├── .gitattributes ├── .gitignore ├── 2step-binomial-tree-figure.py ├── 2step-binomial-tree-price-option-risk-neutral-inc.png ├── 2step-binomial-tree-price-option.png ├── 2step-binomial-tree.py ├── 30stocks-diversifiaction ├── BS_call.py ├── CALL_OPTION.py ├── CND-test.py ├── CND.py ├── Chapter3 ├── pv_f-with-comments.py ├── pv_f.py ├── pv_f.txt ├── pv_pertetuity.py └── the-if-function.py ├── Chapter7 ├── intraday-price-pattern.py ├── mathematical-formula.py └── price-trading-volume.py ├── GARCH ├── GARCH.py ├── GJR_GARCH-def.py ├── GJR_GARCH.py ├── IBM-estimate-volitility.py ├── breusch_pagan.py ├── four-moments-SP500.py ├── get_option_data.py ├── lower-partial-standard-deviation.py ├── put_data.py ├── ret_f.py ├── shapiro-wilk.py ├── volitility-clustering.py └── volitility-smile.py ├── IRR.py ├── IRR_f.py ├── IRRs_f.py ├── Implied Volitility ├── boots_f.py ├── choose-20stocks-from500.py ├── choose-random-stocks.py ├── dist-annual-return.py ├── effect-correlation-on-return ├── effect-correlation-on-return.py ├── efficient-frontier-n-stocks ├── efficient-frontier-n-stocks.py ├── frontier-of-2stock-portfolio ├── frontier-of-2stock-portfolio.py ├── geomean_ret ├── geomean_ret.py ├── log-normal-distribution.png ├── log-normal-distribution.py ├── normal-distribution-histogram.png ├── poisson-distribution.png ├── poisson-distribution.py ├── stock-prive-simulation.py ├── stock-simulation.png ├── stock-terminal-price.png └── terminal-price-histogram.py ├── Monte Carlo and Pricing Exotic Options ├── Barrier-in-out-parity ├── Barrier-in-out-parity.py ├── asian-option-artithmeticaverage.py ├── asian-option.py ├── down_and_in_put.py ├── estimate-call-price-from-terminal ├── estimate-call-price-from-terminal.py ├── floating-strike.py ├── geomean_ret.py ├── graph-up-and-out-and-up-and-in.py ├── long-term-forcasting.py ├── lookback_min_price_as_strike.py ├── price-up-and-out-call ├── price-up-and-out-call.py ├── test-up-and-out-equals-up-and-in-call.py ├── up-and-out-barrier-option-european-call ├── up-and-out-barrier-option-european-call.py └── up_call.py ├── NPV.py ├── README.md ├── Time series └── high-freqency-data.py ├── binary-search.py ├── binomial-tree-American-price-option ├── binomial-tree-european-option ├── binomial-tree-option.png ├── binomial-tree-price-option.py ├── binomialCallAmerican ├── binomialCallAmerican.py ├── butterfly-call-strategy.png ├── butterfly.py ├── calender-spread.py ├── ccr-method-discount-risk-neutral-measure.py ├── compund-interest.py ├── covered-call.py ├── def-IRR_f-cashflows-interations-100-rate-1.0-investment-cashflow-0-for-i-in-range-1-interations-1-rate-1-npv_f-rate-cashflows └── IRR_f.py ├── dist-annual-return.py ├── earnings-per-share.py ├── estimate-implied-volitility ├── estimate-implied-volitility.py ├── expected-return-vs-actual-return.py ├── fibonaci.py ├── fin101.py ├── growing-perpetuity.py ├── imp-vol-eurp-put.py ├── implied-vol-european-call.py ├── implied-vol-with-pdf-call.py ├── implied-volitility-american-call.py ├── implied_vol_American_call.py ├── my_f.py ├── npv_f.py ├── p4f.py ├── p4f.pyc ├── parity-put-call.py ├── payoff.py ├── portfolio-diversification.py ├── profit-loss-call.py ├── straddle.py ├── test01.py ├── test02.py ├── volatility-vs-call-price.py └── volatility-vs.-call-price /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # ========================= 18 | # Operating System Files 19 | # ========================= 20 | 21 | # OSX 22 | # ========================= 23 | 24 | .DS_Store 25 | .AppleDouble 26 | .LSOverride 27 | 28 | # Icon must ends with two \r. 29 | Icon 30 | 31 | # Thumbnails 32 | ._* 33 | 34 | # Files that might appear on external disk 35 | .Spotlight-V100 36 | .Trashes 37 | -------------------------------------------------------------------------------- /2step-binomial-tree-figure.py: -------------------------------------------------------------------------------- 1 | from math import sqrt,exp 2 | import matplotlib.pyplot as plt 3 | import p4f as p4f 4 | s=10;r=0.02;sigma=0.2;T=3./12;x=10 5 | n=2;deltaT=T/n;q=0 6 | u=exp(sigma*sqrt(deltaT));d=1/u 7 | a=exp((r-q)*deltaT) 8 | p=(a-d)/(u-d) 9 | su=round(s*u,2);suu=round(s*u*u,2) 10 | sd=round(s*d,2);sdd=round(s*d*d,2) 11 | sud=2 12 | plt.figtext(0.08,0.6,'Stock '+str(s)) 13 | plt.figtext(0.33,0.76,"Stock price=$"+str(su)) 14 | plt.figtext(0.33,0.27,'Stock price='+str(sd)) 15 | plt.figtext(0.75,0.91,'Stock price=$'+str(suu)) 16 | plt.figtext(0.75,0.6,'Stock price=$'+str(sud)) 17 | plt.figtext(0.75,0.28,"Stock price="+str(sdd)) 18 | p4f.binomial_grid(n) 19 | plt.show() 20 | 21 | -------------------------------------------------------------------------------- /2step-binomial-tree-price-option-risk-neutral-inc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saulwiggin/finance-with-python/e1b6d48c6f5e0be04eee60f89168bb478bcc3324/2step-binomial-tree-price-option-risk-neutral-inc.png -------------------------------------------------------------------------------- /2step-binomial-tree-price-option.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saulwiggin/finance-with-python/e1b6d48c6f5e0be04eee60f89168bb478bcc3324/2step-binomial-tree-price-option.png -------------------------------------------------------------------------------- /2step-binomial-tree.py: -------------------------------------------------------------------------------- 1 | import p4f 2 | import matplotlib.pyplot as plt 3 | plt.figtext(0.08,0.6,"Stock price=$20") 4 | plt.figtext(0.08,0.56,"call =7.34") 5 | plt.figtext(0.33,0.76,"Stock price=$67.49") 6 | plt.figtext(0.33,0.70,"Option price=0.93") 7 | plt.figtext(0.75,0.91,"Stock price=$91.11") 8 | plt.figtext(0.75,0.87,"Option price=0") 9 | plt.figtext(0.75,0.6,"Stock price=$50") 10 | plt.figtext(0.75,0.57,"Option price=2") 11 | plt.figtext(0.75,0.28,"Stock price=$27.44") 12 | plt.figtext(0.75,0.24,"Option price=24.56") 13 | n=2 14 | p4f.binomial_grid(n) 15 | 16 | -------------------------------------------------------------------------------- /30stocks-diversifiaction: -------------------------------------------------------------------------------- 1 | from matplotlib.pyplot import * 2 | n=[1,2,4,6,8,10,12,14,15,18,20,25,30,35,40,45,50,75,100,300,400,500,600,700,800,900,1000] 3 | port_sigma=[0.49236,0.37358,0.29687,0.26643,0.24983,0.23932,0.23204, 4 | 0.22670,0.22261,0.21939,0.21677,0.21196,0.20870,0.20643,0.20456,0.20316,0.20203,0.19860,0.19686,0.19432,0.19336,0.19292,0.19265,0.19347,0.19233,0.19224,0.19217,0.19211,0.19158] 5 | xlim(0,50) 6 | ylim(0.1,0.4) 7 | hlines(0.19217, 0, 50, colors='r', linestyle='dashed') 8 | annotate('',xy=(30, 0.19),xycoords = 'data', xytext = (5, 0.28), 9 | textcoords = 'data',arrowprops = {'arrowstyle':'<->'}) 10 | annotate('',xy=(30, 0.19), xycoords = 'data', xytext = (5, 0.28), 11 | textcoords = 'data', arrowprops = {'arrowstyle':'<->'}) 12 | annotate('Total portfolio risk', xy=(5,0.3), xytext=(25,0.25), 13 | arrowprops=dict(facecolor='black',shrink=0.02)) 14 | figtext(0.15,0.4,"Diversiable risk") 15 | figtext(0.65,0.25,"Nondiversable risk") 16 | plot(n[0:17],port_sigma[0:17]) 17 | title("Relationship between n and protfolio risk") 18 | xlabel("Number of stocks in a portfolio") 19 | ylabel("Ratio of Portfolio std to std of one stock") 20 | show() 21 | -------------------------------------------------------------------------------- /BS_call.py: -------------------------------------------------------------------------------- 1 | from math import * 2 | def bs_call(S,X,T,r,sigma): 3 | d1 = (log(S/X)+(r+sigma*sigma/2.)*T)/(sigma*sqrt(T)) 4 | d2 = d1-sigma*sqrt(T) 5 | return S*CND(d1)-X*exp(-r*T)*CND(d2) 6 | 7 | def CND(X): 8 | (a1,a2,a3,a4 9 | ,a5)=(0.31938153,-0.356563782,1.781477937,-1.821255978,1.330274429) 10 | L = abs(X) 11 | K=1.0/(1.0+0.2316419*L) 12 | w=1.0-1.0/sqrt(2*pi)*exp(-L*L/2.)*(a1*K+a2*K*K+a3*pow(K,3)+a4*pow(K,4)+ 13 | a5*pow(K,5)) 14 | if X<0: 15 | w = 1.0-w 16 | return w 17 | -------------------------------------------------------------------------------- /CALL_OPTION.py: -------------------------------------------------------------------------------- 1 | from math import * 2 | def bs_call(S,X,T,r,sigma); 3 | d1 = (log(S/X)+(r+sigma*sigma/2.)*T)/sigma*sqrt(T)) 4 | d2 = d2*d1 - sigma*sqrt*sqrt(T) 5 | return S*CND(d1)-X*exp(-r*T)*CND(d2) -------------------------------------------------------------------------------- /CND-test.py: -------------------------------------------------------------------------------- 1 | from math import * 2 | def CND(x): 3 | (a1,a2,a3,a4,a5)=(0.31939153,-0.356563792,1.781477937,-1.921255979,1.330274429) 4 | L = abs(x) 5 | K=1.0/(1.0+0.2316419*L) 6 | w=1.0-1.0/sqrt(2*pi)*exp(-L*L/2.)*(a1*K+a2*K*K+a3*pow(K,3)+a4*pow(K,4)+a5*pow(K,5)) 7 | if x<0: 8 | w=1.0-w 9 | return w 10 | -------------------------------------------------------------------------------- /CND.py: -------------------------------------------------------------------------------- 1 | def CND(X): 2 | (a1,a2,a3,a4 3 | ,a5)=(0.31938153,-0.356563782,1.781477937,-1.821255978,1.330274429) 4 | L = abs(X) 5 | K=1.0/(1.0+0.2316419*L) 6 | w=1.0-1.0/sqrt(2*pi)*exp(-L*L/2.)*(a1*K+a2*K*K+a3*pow(K,3)+a4*pow(K,4)+ 7 | a5*pow(K,5)) 8 | if X<0: 9 | w = 1.0-w 10 | return w -------------------------------------------------------------------------------- /Chapter3/pv_f-with-comments.py: -------------------------------------------------------------------------------- 1 | def pv_f(fv,r,n): 2 | """ 3 | Objective: estimate present value 4 | fv: future value 5 | r : discount periodic rate 6 | n: number of periods 7 | formula : fv/(1+r)**n 8 | e.g., 9 | >>>pv_f(100,0.1,1) 10 | 90.90909090909090909090909 11 | >>>pv_f(r=0.1,fv=100,n=1) 12 | 90.90909090909090909090909 13 | >>>pv_f(f=1,fv,100,r=0.1) 14 | 90.90909090909090909090909 15 | """ 16 | return fv/(1+r)**n 17 | 18 | -------------------------------------------------------------------------------- /Chapter3/pv_f.py: -------------------------------------------------------------------------------- 1 | def pv_f(pv,r,n): 2 | return fv/(1+r)**n 3 | -------------------------------------------------------------------------------- /Chapter3/pv_f.txt: -------------------------------------------------------------------------------- 1 | def pv_f(pv,r,n): 2 | return fv/(1+r)**n 3 | -------------------------------------------------------------------------------- /Chapter3/pv_pertetuity.py: -------------------------------------------------------------------------------- 1 | #present value of perpetuity 2 | def pv_perpetuity(c,r): 3 | # c is cash flow 4 | # r is discount rate 5 | return c/r 6 | -------------------------------------------------------------------------------- /Chapter3/the-if-function.py: -------------------------------------------------------------------------------- 1 | def pv_growing_perpetuity(c,r,g): 2 | if(r0: 54 | print ('i=',i,', c=',c) 55 | if x!=x_old: 56 | vol=implied_vol_call_min(s,x,T,r,c) 57 | strike.append(x) 58 | implied_vol.append(vol) 59 | call2.append(c) 60 | Volatility Measures and GARCH 61 | [ 362 ] 62 | print x,c,vol 63 | x_old=x 64 | # Step 5: draw a smile 65 | title('Skewness smile (skew)') 66 | xlabel('Exercise Price') 67 | ylabel('Implied Volatility') 68 | plot(strike,implied_vol,'o') 69 | -------------------------------------------------------------------------------- /IRR.py: -------------------------------------------------------------------------------- 1 | def npv_f(rate, cashflows): 2 | total = 0.0 3 | for i, cashflow in enumerate(cashflow): 4 | total += cashflow / (1 +rate)**i 5 | return total 6 | -------------------------------------------------------------------------------- /IRR_f.py: -------------------------------------------------------------------------------- 1 | def npv_f(rate, cashflows): 2 | total = 0.0 3 | for i, cashflow in enumerate(cashflows): 4 | total += cashflow / (1 +rate)**i 5 | return total 6 | def IRR_f(cashflow, iterations=100): 7 | if len(cashflows)==0: 8 | print 'number of cash flows is zero' 9 | return -99 10 | rate = 1.0 11 | investment = cashflows[0] 12 | for i in range(1, iterations+1): 13 | rate *= (1 - npv_f(rate, cashflows) / investment) 14 | return rate 15 | -------------------------------------------------------------------------------- /IRRs_f.py: -------------------------------------------------------------------------------- 1 | from math import copysign 2 | from scipy import mean 3 | def npv_f(rate, cashflows): 4 | total = 0.0 5 | for i, cashflow in enumerate(cashflows): 6 | total += cashflow / (1 +rate)**i 7 | return total 8 | def IRRs_f(cash_flows): 9 | n=1000 10 | r=range(1,n) 11 | epsilon=abs(mean(cashflows)*0.01) 12 | irr=[-99.00] 13 | j=1 14 | npv=[] 15 | for i in r: npv.append(0) 16 | lag_sign=copysign(npv_f(float(r[0]*1.0/n*1.0),cash_flows),npv_f(float(r[0]*1.0/n*1.0),cash_flows)) 17 | for i in range(1,n-1): 18 | interest=float(r[i]*1.0/n*1.0) 19 | npv[i]=npv_f(interest,cash_flows) 20 | s=copysign(npv[i],npv[i]) 21 | if s*lag_sign<0: 22 | lag_sign=s 23 | if j==1: 24 | irr=[interest] 25 | j=2 26 | else: 27 | irr.append(interest) 28 | return irr 29 | -------------------------------------------------------------------------------- /Implied Volitility/boots_f.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | def boots_f(data,n_obs,replacement= None): 3 | n=len(data) 4 | if (nbarrier: 14 | out=True 15 | if out ==False: 16 | total+=p4f.bs_call(s0,x,T,r,sigma) 17 | return total/n_simulation 18 | 19 | -------------------------------------------------------------------------------- /Monte Carlo and Pricing Exotic Options/up_call.py: -------------------------------------------------------------------------------- 1 | def up_call(s0,x,T,r,sigma,n_simulation,barrier): 2 | import scipy as sp 3 | import p4f 4 | n_steps=100. 5 | dt=T/n_steps 6 | inTotal=0 7 | outTotal=0 8 | for j in range(0, n_simulation): 9 | sT=s0 10 | inStatus=False 11 | outStatus=True 12 | for i in range(0,int(n_steps)): 13 | e=sp.random.normal() 14 | sT*=sp.exp((r-0.5*sigma*sigma)*dt+sigma*e*sp.sqrt(dt)) 15 | if (sT>barrier) : 16 | outStatus=False 17 | inStatus=True 18 | #print 'sT=',sT 19 | #print 'j=', j, 'out=',out 20 | if outStatus==True: 21 | outTotal+=p4f.bs_call(s0,x,T,r,sigma) 22 | else: 23 | inTotal+=p4f.bs_call(s0,x,T,r,sigma) 24 | return outTotal/n_simulation, inTotal/n_simulation 25 | -------------------------------------------------------------------------------- /NPV.py: -------------------------------------------------------------------------------- 1 | def npv_f(rate, cashflows): 2 | total = 0.0 3 | for i, cashflow in enumerate(cashflows): 4 | total += cashflow / (1 +rate)**i 5 | return total 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Python-for-finance 2 | ================== 3 | Quant finance in python. Monti Carlo simulations. Black Scholes. Option Pricing. 4 | -------------------------------------------------------------------------------- /Time series/high-freqency-data.py: -------------------------------------------------------------------------------- 1 | import pandas as pd, numpy as np, datetime 2 | ticker='AAPL' 3 | path='http://www.google.com/finance/getprices?q=ttt&i=60&p=5&f=d,o,h,l,c,v' 4 | x=np.array(pd.read_csv(path.replace('ttt',ticker),skiprows=7,header=None)) 5 | date=[] 6 | -------------------------------------------------------------------------------- /binary-search.py: -------------------------------------------------------------------------------- 1 | def binary_search(x, target, my_min=1, my_max=None): 2 | if my_max is None: 3 | my_max = len(x) - 1 4 | while my_min <= my_max: 5 | mid = (my_min + my_max)//2 6 | midval = x[mid] 7 | if midval < target: 8 | my_min = my_mid +1 9 | elif midval > target: 10 | my_max = mid - 1 11 | else: 12 | return mid 13 | raise ValueError 14 | -------------------------------------------------------------------------------- /binomial-tree-American-price-option: -------------------------------------------------------------------------------- 1 | from math import exp,sqrt 2 | def binomialCallAmerican(s,x,T,r,sigma,n=100): 3 | deltaT=T/n 4 | u=exp(sigma * sqrt(deltaT)) 5 | d=1.0 / u 6 | a = exp(r*deltaT) 7 | p=(a-d) / (u-d) 8 | v = [[0.0 for j in xrange(i + 1)] for i in xrange (n+1)] 9 | for j in xrange(i+1): 10 | v[n][j] = max(s* u**j * d**(n-j)-x,0.0) 11 | for i in xrange(n-1,-1,-1): 12 | for j in xrange(i + 1): 13 | v1=exp(-r*deltaT)*(p*v[i+1][j+1]+(1.0-p)*v[i+1][j]) 14 | v2=max(x-s,0) 15 | v[i][j]=max(v1,v2) 16 | return v[0][0] 17 | 18 | -------------------------------------------------------------------------------- /binomial-tree-european-option: -------------------------------------------------------------------------------- 1 | from math import exp,sqrt 2 | def binomialCall(s,x,T,r,sigma,n=100): 3 | deltaT = T/n 4 | u = exp(sigma * sqrt(deltaT)) 5 | d = 1.0 / u 6 | a = exp(r * deltaT) 7 | p = (a - d) / (u - d) 8 | v = [[0.0 for j in xrange(i+1)] for i in xrange(n+1)] 9 | for j in xrange (i+1): 10 | v[n][j]-max(s*u**j*d**(n-j)-x,0.0) 11 | for i in xrange(n-1, -1, -1): 12 | for j in xrange(i + 1): 13 | v[i][j]=exp(-r*deltaT)*(p*v[i+1][j+1]+(1.0-p)*v[i+1][j]) 14 | return v[0][0] 15 | -------------------------------------------------------------------------------- /binomial-tree-option.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saulwiggin/finance-with-python/e1b6d48c6f5e0be04eee60f89168bb478bcc3324/binomial-tree-option.png -------------------------------------------------------------------------------- /binomial-tree-price-option.py: -------------------------------------------------------------------------------- 1 | import networkx as nx 2 | import matplotlib.pyplot as plt 3 | plt.figtext(0.08,0.6,"Stock price=$20") 4 | plt.figtext(0.75,0.91,"Stock price=$22") 5 | plt.figtext(0.75,0.87,"Option price=$1") 6 | plt.figtext(0.75,0.28,"Stock price=$18") 7 | plt.figtext(0.75,0.24,"Option price=0") 8 | plt.figtext(0.75,0.24,"Option price=0") 9 | n=1 10 | def bionomial_grid(n): 11 | G=nx.Graph() 12 | for i in range(0,n+1): 13 | for j in range(1,i+2): 14 | if i>>help(pv_f) 8 | """ 9 | def pv_f(fv,r,n): 10 | """ 11 | Objective: estimate present value 12 | fv: future value 13 | r : discount periodic rate 14 | n: number of periods 15 | formula : fv/(1+r)**n 16 | e.g., 17 | >>>pv_f(100,0.1,1) 18 | 90.90909090909090909090909 19 | >>>pv_f(r=0.1,fv=100,n=1) 20 | 90.90909090909090909090909 21 | >>>pv_f(f=1,fv,100,r=0.1) 22 | 90.90909090909090909090909 23 | """ 24 | return fv/(1+r)**n 25 | 26 | #present value of perpetuity 27 | def pv_perpetuity(c,r): 28 | # c is cash flow 29 | # r is discount rate 30 | return c/r 31 | 32 | def pv_growing_perpetuity(c,r,g): 33 | if(r>>>>>> python for finance 9 | return total 10 | -------------------------------------------------------------------------------- /p4f.py: -------------------------------------------------------------------------------- 1 | """ 2 | Name : 4375OS_09_30_pdf.py 3 | Book : Python for Finance 4 | Publisher: Packt Publishing Ltd. 5 | Author : Yuxing Yan 6 | Date : 12/26/2013 7 | email : yany@canisius.edu 8 | paulyxy@hotmail.com 9 | """ 10 | 11 | 12 | 13 | 14 | def bs_call(S,X,T,rf,sigma): 15 | """ 16 | Objective: Black-Schole-Merton option model 17 | Format : bs_call(S,X,T,r,sigma) 18 | S: current stock price 19 | X: exercise price 20 | T: maturity date in years 21 | rf: risk-free rate (continusouly compounded) 22 | sigma: volatiity of underlying security 23 | Example 1: 24 | >>>bs_call(40,40,1,0.1,0.2) 25 | 5.3078706338643578 26 | """ 27 | from scipy import log,exp,sqrt,stats 28 | d1=(log(S/X)+(rf+sigma*sigma/2.)*T)/(sigma*sqrt(T)) 29 | d2 = d1-sigma*sqrt(T) 30 | return S*stats.norm.cdf(d1)-X*exp(-rf*T)*stats.norm.cdf(d2) 31 | 32 | 33 | def bs_put(S,X,T,rf,sigma): 34 | """ 35 | Objective: Black-Schole-Merton option model 36 | Format : bs_call(S,X,T,r,sigma) 37 | S: current stock price 38 | X: exercise price 39 | T: maturity date in years 40 | rf: risk-free rate (continusouly compounded) 41 | sigma: volatiity of underlying security 42 | Example 1: 43 | >>> put=bs_put(40,40,0.5,0.05,0.2) 44 | >>> round(put,2) 45 | 1.77 46 | """ 47 | from scipy import log,exp,sqrt,stats 48 | d1=(log(S/X)+(rf+sigma*sigma/2.)*T)/(sigma*sqrt(T)) 49 | d2 = d1-sigma*sqrt(T) 50 | return X*exp(-rf*T)*stats.norm.cdf(-d2)-S*stats.norm.cdf(-d1) 51 | 52 | def binomial_grid(n): 53 | import networkx as nx 54 | import matplotlib.pyplot as plt 55 | G=nx.Graph() 56 | for i in range(0,n+1): 57 | for j in range(1,i+2): 58 | if i>> CND(0) 76 | 0.5000000005248086 77 | """ 78 | (a1,a2,a3,a4,a5)=(0.31938153,-0.356563782,1.781477937,-1.821255978,1.330274429) 79 | L = abs(X) 80 | K = 1.0 / (1.0 + 0.2316419 * L) 81 | w = 1.0 - 1.0 / sqrt(2*pi)*exp(-L*L/2.) * (a1*K + a2*K*K + a3*pow(K,3) + 82 | a4*pow(K,4) + a5*pow(K,5)) 83 | if X<0: 84 | w = 1.0-w 85 | return w 86 | -------------------------------------------------------------------------------- /p4f.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saulwiggin/finance-with-python/e1b6d48c6f5e0be04eee60f89168bb478bcc3324/p4f.pyc -------------------------------------------------------------------------------- /parity-put-call.py: -------------------------------------------------------------------------------- 1 | import pylab as pl 2 | import numpy as np 3 | x=10 4 | sT=np.arange(0,30,5) 5 | payoff_call=(abs(sT-x)+sT-x)/2 6 | payoff_put=(abs(x-sT)+x-sT)/2 7 | cash=np.zeros(len(sT))+x 8 | #def graph(text,text2=''): 9 | # pl.xticks(()) 10 | # pl.yticks(()) 11 | # pl.xlim(0,30) 12 | # pl.ylim(0,20) 13 | # pl.plot([x,x],[0,3]) 14 | #pl.text(x,-2,"X"); 15 | # pl.text(0,x,"X") 16 | # pl.text(x,x*1.7, text, ha='center', va='canter',size-10, 17 | # pl.text(-5,10,text2,size=25) 18 | #pl.figure(figsize=(6, 4)) 19 | -------------------------------------------------------------------------------- /payoff.py: -------------------------------------------------------------------------------- 1 | def payoff_call(sT,x): 2 | return (sT-x+abs(sT-x))/2 -------------------------------------------------------------------------------- /portfolio-diversification.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import matplotlib.pyplot as plt 3 | year=[2009,2010,2011,2012,2013] 4 | ret_A=[0.102,-0.02,0.213,0.12,0.13] 5 | ret_B=[0.1062,0.23,0.045,0.234,0.113] 6 | port_EW=(np.array(ret_A)+np.array(ret_B))/2. 7 | 8 | plt.figtext(0.2,0.65,"Stock A") 9 | plt.figtext(0.15,0.4,"Stock B") 10 | plt.xlabel("Year") 11 | plt.ylabel("Returns") 12 | plt.plot(year,ret_A,lw=2) 13 | plt.plot(year,ret_B,lw=2) 14 | plt.plot(year,port_EW,lw=2) 15 | plt.title("Individual stocks vs. an equal-weighted 2-stock portfolio") 16 | plt.annotate('Equal-weighted Portfolio', xy=(2010, 0.1), xytext=(2011.,0), 17 | arrowprops=dict(facecolor='black',shrink=0.05), 18 | plt.ylim(-0.1,0.3) 19 | plt.show() 20 | -------------------------------------------------------------------------------- /profit-loss-call.py: -------------------------------------------------------------------------------- 1 | import numpy 2 | import matlibplot 3 | 4 | s = np.arange(30,70,5) 5 | x=45;call=2.5 6 | profit=(abs(s-x)+s-x)/2-call 7 | y2=zeros(len(s)) 8 | ylim(-30,50) 9 | 10 | plot(s,profit) 11 | plot(s,y2,'-.') 12 | plot(s,-profit) 13 | title("Profit/Loss function") 14 | xlabel('Stock price') 15 | ylabel('Profit (loss)') 16 | plt.annotate('Call option buyer', xy=(55,15),xytext=(35,20), 17 | arrowprops=dict(facecolor='blue',shrink=0.01),) 18 | plt.annotate('Call option seller', xy=(55,-10), xytext=(40,-20), 19 | arrowprops=dict(facecolor='red',shrink=0.01),) 20 | show() 21 | -------------------------------------------------------------------------------- /straddle.py: -------------------------------------------------------------------------------- 1 | import matplotlib.pyplot as plt 2 | sT = arange(30,80,5) 3 | x=50; c=2; p=1; 4 | straddle=(abs(sT-x)+sT-x)/2-c + (abs(x-sT)+x-sT)/2-p 5 | y0=zeros(len(sT)) 6 | ylim(-6,20) 7 | xlim(40,70) 8 | plot(sT,y0) 9 | plot([x,x],[-6,4],'g-.') 10 | title("Profit-loss for a Straddle") 11 | xlabel('Stock price') 12 | ylabel('Profite (loss)') 13 | plt.annotate('Point 1='+str(x-c-p), xy=(x,p-c,0), xytext=(x-p-c,10), 14 | arrowprops=dict(facecolor='red',shrink=0.01),) 15 | plt.annpotate('Point 2='+str(x+c+p), xy=(x+p+c,0), ytext=(x,p,c,13), 16 | arrowprops=dict(facecolor='blue',shrink=0.01),) 17 | plt.annotate('exercise price', xy=(x+1,-5)) 18 | plt.annotate('Buy a call and buy a put with the same excercise price', xy=(45,16)) 19 | -------------------------------------------------------------------------------- /test01.py: -------------------------------------------------------------------------------- 1 | def pv_f(fv,r,n): 2 | return fv/(1+r)**n 3 | -------------------------------------------------------------------------------- /test02.py: -------------------------------------------------------------------------------- 1 | def pv_f(fv,r,n): 2 | return fv/(1+R)**n # a type of r 3 | -------------------------------------------------------------------------------- /volatility-vs-call-price.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import p4f as pf 3 | s0=30;T0=0.5;sigma0=0.2;r0=0.05;x0=30 4 | sigma=np.arange(0.5,2.0,0.5) 5 | call_0=pf.bs_call(s0,x0,T0,r0,sigma) 6 | call_sigma=pf.bs_call(s0,x0,T0,r0,sigma) 7 | call_T=pf.bs_call(s0,x0,Tr0,sigma0) 8 | plot(sigma,call_sigma,'b') 9 | plot(T,call_T) 10 | -------------------------------------------------------------------------------- /volatility-vs.-call-price: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import p4f as pf 3 | --------------------------------------------------------------------------------