├── Data1.xlsx ├── Data2.xlsx ├── Getting Stock Data.py ├── BSM.py ├── Black's_Euro_call.py ├── LICENSE ├── Ho-Lee.py ├── American.py ├── Hull-White.py ├── Vasicek.py ├── EuroOpt.py ├── Trinomial.py ├── Reg_Monte.py ├── Binomial.py ├── Black's_Interest_Rate_Cap.py ├── Black's_swap.py ├── AVM.py ├── .gitignore ├── EFD.py ├── blackliter.R ├── CIR.py ├── DELTA.py ├── AVM + DELTA.py ├── Implied_VOT.py ├── ImpNEW.py ├── README.md ├── Impl_Trinomial_Tree.py ├── Comp.py └── Amer_Up&Out_put.py /Data1.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Michalos88/Quant-Projects/HEAD/Data1.xlsx -------------------------------------------------------------------------------- /Data2.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Michalos88/Quant-Projects/HEAD/Data2.xlsx -------------------------------------------------------------------------------- /Getting Stock Data.py: -------------------------------------------------------------------------------- 1 | from pandas_datareader import data as web 2 | import datetime 3 | 4 | 5 | start1 = datetime.datetime(2016, 9, 21) 6 | end1 = datetime.datetime(2016, 9, 21) 7 | start2 = datetime.datetime(2016, 9, 22) 8 | end2 = datetime.datetime(2016, 9, 22) 9 | 10 | SPY1 = web.DataReader("SPY", 'yahoo', start1, end1) 11 | VIX1 = web.DataReader("VIX",'yahoo', start1, end1) 12 | 13 | 14 | SPY1['Time of Download'] = datetime.datetime.time(datetime.datetime.now()) 15 | print(SPY1) 16 | 17 | path = 'C:/Users/Class2017/Desktop/University/FE621/HW/HW1/Code/' 18 | SPY1.to_csv(path+'DATA1.csv') 19 | VIX1.to_csv(path+'DATA1a.csv') 20 | 21 | -------------------------------------------------------------------------------- /BSM.py: -------------------------------------------------------------------------------- 1 | # Only using toolbox functions for normal CDF calculation and mathematical tools 2 | from math import * 3 | from scipy.stats import norm 4 | 5 | # Input Parameters 6 | 7 | 8 | sigma = 3 9 | 10 | T = 0.5 11 | S = 187.85 12 | r = 0.05 13 | K = 80 14 | # Calculations for the solution to BSM equation 15 | dplus = (1/(sigma*sqrt(T)))*((log(S/K))+(r+(sigma**2)/2)*T) 16 | dminus = (1/(sigma*sqrt(T)))*((log(S/K))+(r-(sigma**2)/2)*T) 17 | 18 | # Calculating price of Call and Put 19 | Call = S*norm.cdf(dplus) - K*exp(-r*T)*norm.cdf(dminus) 20 | Put = K*exp(-r*T)*norm.cdf(-dminus)-S*norm.cdf(-dplus) 21 | 22 | # Printing the values of call an put options 23 | print("The Price of the Call option is %s" % round(Call, 2)) 24 | print("The Price of the Put option is %s" % round(Put, 2)) -------------------------------------------------------------------------------- /Black's_Euro_call.py: -------------------------------------------------------------------------------- 1 | # Michal Lyskawinski 2 | # Date: 11/28/2016 3 | # Black's Model 4 | # Assume that the forward bond price volatility is 7%. Price a two 5 | # year European call option with strike 0.8 on a seven-year pure 6 | # discount bond. 7 | 8 | from math import exp, log, sqrt 9 | from scipy.stats import norm 10 | 11 | # Parameters for option 12 | OM = 2 # Maturity of the option in years 13 | Or = 0.04 # Term structure of interest rate 14 | K = 0.8 # Strike 15 | 16 | # Parameters for the bond 17 | Br = 0.04 18 | BM = 7 # Maturity pure discount bond in years 19 | FBPV = 0.07 # Forward bond price volatility 20 | 21 | def PDBprice(r,M): 22 | P = exp(-r*M) 23 | return P 24 | 25 | Bpdb = PDBprice(Br, BM) 26 | Opdb = PDBprice(Or, OM) 27 | 28 | Pf = Bpdb/Opdb 29 | 30 | d1 = (1/(FBPV*sqrt(OM)))*((log(Pf/K))+((FBPV**2)/2)*OM) 31 | d2 = d1 - FBPV*sqrt(OM) 32 | 33 | C = Opdb*(Pf*norm.cdf(d1) - K*norm.cdf(d2)) 34 | 35 | print(C) 36 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Michal Lyskawinski 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Ho-Lee.py: -------------------------------------------------------------------------------- 1 | # Michal Lyskawinski 2 | # Date: 11/28/2016 3 | # Ho-Lee Model 4 | 5 | from math import * 6 | from scipy.stats import norm 7 | 8 | # interest rate parameters: 9 | r = 0.04 10 | r1 = 0.04 11 | sigma = 0.01 12 | 13 | # Option parameters: European Call 14 | OM = 2 # Option Maturity in years 15 | OBM = 6 # Option's Bond Maturity in years 16 | K = 0.73 17 | 18 | # Bond parameters: 19 | T = 1 20 | s = 2 # Bond Maturity in years 21 | t = 0 # Present time 22 | dB = s - T # difference 23 | dt = 0.1 24 | 25 | def PDB(r,M): 26 | P = exp(-r*M) 27 | return P 28 | 29 | # Pricing the Bond: 30 | P5 = PDB(r,s) 31 | P1 = PDB(r,T) 32 | Slope = (log(PDB(r,T+dt))-log(PDB(r,T-dt)))/(2*dt) 33 | lnA = log(P5/P1) - dB*(Slope) - 0.5*(sigma**2)*(T-t)*dB**2 34 | BP = exp(lnA)*PDB(r1,dB) 35 | 36 | print('Price of the bond =',BP) 37 | 38 | # Pricing the European Call Option: 39 | PO = PDB(r,OM) 40 | POB = PDB(r,OBM) 41 | # K = POB/PO # If no K 42 | sigmaP = sigma*(dB)*sqrt(T-t) 43 | d1 = ((log((POB)/(K*P1)))/(sigmaP)) + (sigmaP*0.5) 44 | d2 = d1 - sigmaP 45 | c = POB*norm.cdf(d1) - K*PO*norm.cdf(d2) # call 46 | p = PO*K*norm.cdf(-d2) - POB*norm.cdf(-d1) # put 47 | print('Price of the European Call =',c) 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /American.py: -------------------------------------------------------------------------------- 1 | 2 | from math import * 3 | 4 | # Initialize parameters 5 | S = 150 6 | r = 0.06 7 | sigma = 0.3 8 | T = 1 9 | K = 150 10 | N = 100 11 | option = 'Put' 12 | 13 | def american(S,r,sigma,T,K,N,option): 14 | dt = T/N 15 | u = exp(sigma * sqrt(dt)) 16 | d = 1/u 17 | p = (exp(r*dt)-d)/(u-d) 18 | disc = exp(-r*dt) 19 | 20 | St = [0]*(N+1) 21 | C = [0]*(N+1) 22 | 23 | St[0] = S*d**N 24 | for j in range(1, N): 25 | St[j] = St[j-1]*(u/d) 26 | 27 | for j in range(0, N): 28 | if option == 'Put': 29 | C[j] = max(0.0, K - St[j]) 30 | elif option == 'Call': 31 | C[j] = max(0.0, St[j] - K) 32 | else: 33 | break 34 | 35 | for i in range(N-1, 0): 36 | for j in range(0, i): 37 | C[j] = disc*(p*C[j+1]+(1-p)*C[j]) 38 | St[j] = (St[j])/d 39 | if option == 'Put': 40 | C[j] = max(C[j], K - St[j]) 41 | elif option == 'Call': 42 | C[j] = max(C[j], St[j] - K) 43 | next(j) 44 | next(i) 45 | if option =='Call': 46 | return C[52] 47 | elif option =='Put': 48 | return C[0] 49 | 50 | print(american(S,r,sigma,T,K,N,option)) -------------------------------------------------------------------------------- /Hull-White.py: -------------------------------------------------------------------------------- 1 | # Michal Lyskawinski 2 | # Date: 11/28/2016 3 | # Hull-White Model 4 | 5 | from math import * 6 | from scipy.stats import norm 7 | 8 | # interest rate parameters: 9 | r = 0.04 10 | r1 = 0.04 11 | sigma = 0.01 12 | a = 0.1 13 | 14 | # Option parameters: European Call 15 | OM = 2 # Option Maturity in years 16 | OBM = 6 # Option's Bond Maturity in years 17 | K = 0.73 18 | 19 | # Bond parameters: 20 | T = 1 # Bond Maturity in years 21 | s = 2 22 | t = 0 # Present time 23 | dt = 0.1 24 | 25 | 26 | def PDB(r,M): 27 | P = exp(-r*M) 28 | return P 29 | 30 | # Pricing the Bond: 31 | P5 = PDB(r,s) 32 | P1 = PDB(r,T) 33 | dB = (1/a)*(1-PDB(a,s-T)) 34 | Slope = (log(PDB(r,T+dt))-log(PDB(r,T-dt)))/(2*dt) 35 | lnA = log(P5/P1) - dB*(Slope) 36 | BP = exp(lnA)*PDB(r1,dB) 37 | 38 | print('Price of the bond =',BP) 39 | 40 | # Pricing the European Option: 41 | PO = PDB(r,OM) 42 | POB = PDB(r,OBM) 43 | # K = POB/PO # If no K 44 | sigmaP = sqrt((sigma**2/(2*a**3))*(1-PDB(2*a,OM))*(1-PDB(a,OBM-OM))**2) 45 | d1 = ((log((POB)/(K*P1)))/(sigmaP)) + (sigmaP*0.5) 46 | d2 = d1 - sigmaP 47 | c = POB*norm.cdf(d1) - K*PO*norm.cdf(d2) # call 48 | p = PO*K*norm.cdf(-d2) - POB*norm.cdf(-d1) # put 49 | 50 | print('Price of the European Call =',c) 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /Vasicek.py: -------------------------------------------------------------------------------- 1 | # Michal Lyskawinski 2 | # Date: 11/28/2016 3 | # Vasicek Model 4 | from math import * 5 | from scipy.stats import norm 6 | 7 | 8 | # interest rate parameters: 9 | rzero = 0.04 10 | rbar = 0.05 11 | a = 1.5 12 | sigma = 0.01 13 | 14 | # Option parameters: European Call 15 | OM = 2 # Option Maturity in years 16 | OBM = 6 # Option's Bond Maturity in years 17 | K = 0.73 18 | 19 | # Bond parameters: 20 | BM = 2 # Bond Maturity in years 21 | 22 | def PDB(r,M): 23 | P = exp(-r*M) 24 | return P 25 | 26 | def Pbond(a,M,sigma,rbar): 27 | Bts = (1/a)*(1-PDB(a,M)) 28 | Rinf = rbar - 0.5*((sigma**2)/(a**2)) 29 | lnA = (Rinf/a)*(1-PDB(a,M)) - M*Rinf - ((sigma**2)/(4*a**3))*(1-PDB(a,M))**2 30 | 31 | P = (PDB(-lnA,1))*(PDB(rbar,Bts)) # Price of the bond 32 | return P 33 | 34 | print('Price of the bond =',Pbond(a,BM,sigma,rbar)) 35 | 36 | # Pricing the option 37 | sigmaR = (sigma/(a*(OM)))*(1-PDB(a,OM)) # Spot rate volatility 38 | POB = Pbond(a,OBM,sigma,rbar) 39 | PO = Pbond(a,OM,sigma,rbar) 40 | v = sqrt(((sigma**2)*(1-PDB(2*a,OM)))/(2*a)) 41 | sigmaP =(v*(1-PDB(a, OBM-OM)))/(a) 42 | 43 | d1 = ((log(POB/(K*PO)))/(sigmaP))+(sigmaP/2) 44 | d2 = d1 - sigmaP 45 | 46 | c = POB*norm.cdf(d1) - K*PO*norm.cdf(d2) 47 | print('Price of the European Call =',c) -------------------------------------------------------------------------------- /EuroOpt.py: -------------------------------------------------------------------------------- 1 | from math import * 2 | 3 | 4 | # Initialize parameters 5 | S = 150 6 | r = 0.06 7 | sigma = 0.37 8 | T = 1 9 | K = 150 10 | N = 100 11 | option = 'Put' 12 | 13 | def euro(S,r,sigma,K,N,option): 14 | # Compute more constants 15 | v = r-0.5*sigma**2 16 | deltaT = T/N 17 | disc = exp(-r*deltaT) 18 | dxu = sqrt((sigma**2)*deltaT+(v*deltaT)**2) 19 | dxd = -dxu 20 | # p = (exp(r*deltaT)-d)/(u-d) # probability of going up 21 | pu = 0.5+0.5*((v*deltaT)/dxu) 22 | pd = 1-pu 23 | 24 | # Initialize arrays 25 | St = [0]*(N+1) 26 | C = [0]*(N+1) 27 | 28 | # Initialize asset prices at maturity N 29 | St[0] = S*exp(N*dxd) 30 | for j in range(1,N): 31 | St[j] = St[j-1]*exp(dxu-dxd) 32 | 33 | # Initialize option values at maturity 34 | for j in range(0, N): 35 | if option == 'Call': 36 | C[j] = max(0.0, St[j] - K) 37 | elif option == 'Put': 38 | C[j] = max(0.0, K - St[j]) 39 | 40 | # Step back through the tree 41 | for i in range(N-1, 0): 42 | for j in range(0, i): 43 | C[j] = disc*(pu*C[j+1]+pd*C[j]) 44 | if option == 'Call': 45 | return C[N/2] 46 | elif option == 'Put': 47 | return C[N/2] 48 | 49 | print(euro(S,r,sigma,K,N,option)) 50 | -------------------------------------------------------------------------------- /Trinomial.py: -------------------------------------------------------------------------------- 1 | # Trinomial tree to calculate values for Call and Put European options. 2 | # Written by: Michal Lyskawinski 3 | # 10/31/2016 4 | from math import * 5 | 6 | # Initialize parameters 7 | S = 150 8 | r = 0.06 9 | sig = 0.3 10 | T = 1 11 | K = 150 12 | N = 3 13 | 14 | div = 0.03 # In percentage 15 | dx = 0.2 16 | option = 'Call' 17 | 18 | edx = exp(dx) 19 | 20 | # Compute asset prices at maturity 21 | St = [0 for i in range(2*N+1)] 22 | St[0] = S*exp(-N*dx) 23 | for j in range(1, 2*N+1): 24 | St[j] = St[j - 1] * edx 25 | 26 | # Compute option values at maturity 27 | C = [[0 for i in range(2*N+1)] for j in range(N+1)] 28 | for j in range(0, 2*N+1): 29 | if option == 'Call': 30 | C[N][j] = max(0, St[j]-K) 31 | elif option == 'Put': 32 | C[N][j] = max(0, K - St[j]) 33 | 34 | 35 | # Stepping backwards in time 36 | dt = T/N 37 | disc = exp(-r*dt) 38 | nu = r-div-0.5*sig**2 39 | pu = 0.5*(((sig**2*dt+nu**2*dt**2)/(dx**2))+nu*dt/dx) 40 | pm = 1 - ((sig**2*dt+nu**2*dt**2)/dx**2) 41 | pd = 0.5*(((sig**2*dt+nu**2*dt**2)/dx**2) - nu*dt/dx) 42 | TNar = 0 43 | for i in range(N-1,-1,-1): 44 | for j in range(TNar,2*N-TNar): 45 | C[i][j] = disc * (pu * C[i+1][j + 1] + pm * C[i + 1][j] + pd * C[i + 1][j - 1]) 46 | #C[i][j] = disc * (pu * C[i][j + 1] + pm * C[i + 1][j + 1] + pd * C[i + 1][j -1]) 47 | print(C) 48 | print(C[0][3]) -------------------------------------------------------------------------------- /Reg_Monte.py: -------------------------------------------------------------------------------- 1 | # Monte Carlo Valuation of a European Option in a Black-Scholes World 2 | # by Michal Lyskawinski 3 | # 10/31/2016 4 | 5 | from math import * 6 | import numpy as np 7 | # Initialize parameters 8 | S = 100 9 | r = 0.06 10 | sig = 0.2 11 | T = 1 12 | K = 100 13 | N = 300 14 | M = 100 15 | div = 0.03 # In percentage 16 | option = 'Put' 17 | 18 | # Precompute constants 19 | dt = T/N 20 | nu = r - div - 0.5*(sig**2) 21 | nudt = nu*dt 22 | sigsdt = sig*sqrt(dt) 23 | lnS = log(S) 24 | 25 | sum_CT = 0 26 | sum_CT2 = 0 27 | 28 | for j in range(1,M): # For each simulation 29 | lnST = lnS 30 | 31 | for i in range(1,N): 32 | eps = np.random.normal(0, 1) 33 | lnST = lnST + nudt + sigsdt*eps 34 | 35 | St = exp(lnST) 36 | if option == 'Call': 37 | CT = max(0, St - K) 38 | sum_CT = sum_CT + CT 39 | sum_CT2 = sum_CT2 + CT*CT 40 | elif option == 'Put': 41 | CT = max(0, K - St) 42 | sum_CT = sum_CT + CT 43 | sum_CT2 = sum_CT2 + CT * CT 44 | else: 45 | break 46 | 47 | 48 | Value = sum_CT/M*exp(-r*T) 49 | SD = sqrt((sum_CT2 - sum_CT*sum_CT/M)*exp(-2*r*T)/(M-1)) 50 | SE = SD/sqrt(M) 51 | 52 | 53 | print('The Value of European',option,'Option is',Value) 54 | print('The Standard Deviation of this Option is',SD) 55 | print('The Standard Error in this case is',SE) 56 | 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /Binomial.py: -------------------------------------------------------------------------------- 1 | from math import * 2 | 3 | 4 | # Initialize parameters 5 | S = 214.95 6 | r = 0.06 7 | sigma = 0.37 8 | T = (20/365) 9 | N = 100 10 | option = 'Call' 11 | 12 | def euro(S,r,sigma,K,N,option): 13 | # Compute more constants 14 | v = r-0.5*sigma**2 15 | deltaT = T/N 16 | disc = exp(-r*deltaT) 17 | dxu = sqrt((sigma**2)*deltaT+(v*deltaT)**2) 18 | dxd = -dxu 19 | # p = (exp(r*deltaT)-d)/(u-d) # probability of going up 20 | pu = 0.5+0.5*((v*deltaT)/dxu) 21 | pd = 1-pu 22 | 23 | # Initialize arrays 24 | St = [0]*(N+1) 25 | C = [0]*(N+1) 26 | 27 | # Initialize asset prices at maturity N 28 | St[0] = S*exp(N*dxd) 29 | for j in range(1,N): 30 | St[j] = St[j-1]*exp(dxu-dxd) 31 | 32 | # Initialize option values at maturity 33 | for j in range(0, N): 34 | if option == 'Call': 35 | C[j] = max(0.0, St[j] - K) 36 | elif option == 'Put': 37 | C[j] = max(0.0, K - St[j]) 38 | 39 | # Step back through the tree 40 | for i in range(N-1, 0): 41 | for j in range(0, i): 42 | C[j] = disc*(pu*C[j+1]+pd*C[j]) 43 | if option == 'Call': 44 | return C[int(N/2)] 45 | elif option == 'Put': 46 | return C[int(N/2)] 47 | 48 | Ks = [70,115,120,121,123,125,126,129,130,141] 49 | for i in Ks: 50 | print('For K=',i,'OptionV =',euro(S,r,sigma,i,N,option)) 51 | -------------------------------------------------------------------------------- /Black's_Interest_Rate_Cap.py: -------------------------------------------------------------------------------- 1 | # Michal Lyskawinski 2 | # Date: 11/28/2016 3 | # Black's Model 4 | # Price an interest rate cap at 4.7%. Assume that the cap is for a 5 | # two year period, the reset frequency is four months. Assume that 6 | # the volatility of the forward rate is 9%. The principal of the swap 7 | # is 1 million (you may want to use software for this). Please note 8 | # that a caplet and a cap are two different things. 9 | 10 | from math import exp, log, sqrt 11 | from scipy.stats import norm 12 | 13 | # General Parameters 14 | r = 0.04 # Flat term structure 15 | 16 | # Parameters for option 17 | L = 1*10**6 # Principal 18 | rc = 0.047 # Cap rate 19 | fr = 4 # Reset frequency in months 20 | VFIR = 0.09 # Volatility of future interest rate 21 | M = 24 # Maturity in months 22 | 23 | # Precompute constants 24 | dt = 1/M 25 | 26 | 27 | def PDBprice(r,M): 28 | P = exp(-r*M) 29 | return P 30 | 31 | Ccap = [] 32 | 33 | for i in range(1,int(M/fr)): 34 | m2 = (i+1)*fr*dt 35 | m1 = i*fr*dt 36 | Opdb = PDBprice(r, m1) 37 | d1 = (1 / (VFIR * sqrt(m1))) * ((log(r / rc)) + ((VFIR ** 2) / 2) * m1) 38 | d2 = d1 - VFIR * sqrt(m1) 39 | Ccaplet = Opdb*(r*norm.cdf(d1) - rc*norm.cdf(d2))*dt*L 40 | Ccap.append(Ccaplet) 41 | 42 | C = sum(Ccap) 43 | print(C) 44 | 45 | # We assume for our analysis that there is no caplet over the first cap period as the interest rate applicable to the period is known at time t0 -------------------------------------------------------------------------------- /Black's_swap.py: -------------------------------------------------------------------------------- 1 | # Michal Lyskawinski 2 | # Date: 11/28/2016 3 | # Black's Model 4 | # Price a one year option which exercise into a new two year semi- 5 | # annual payer swap. The strike price of the option is 6% and the 6 | # forward swap rate volatility is 10%. 7 | 8 | from math import * 9 | from scipy.stats import norm 10 | 11 | # Parameters for option 12 | K = 0.06 # Strike in % 13 | r = 0.04 # Term structure of interest rate is flat at r 14 | M1 = 1.00 # Maturity of the option in years 15 | 16 | # Parameters for the swap 17 | FSRvol = 0.1 # forward swap rate volatility 18 | M3 = 3.00 # # Maturity of the swap 19 | dt = 0.5 # Reset period 20 | 21 | # Precompute Constants: 22 | N = (M3-M1)/dt # Number of reset periods of the swap 23 | 24 | 25 | def PDBprice(r,M): 26 | P = exp(-r*M) 27 | return P 28 | 29 | # Under our term structure assumptions the relevant bond prices are given 30 | M1pdb = PDBprice(r,M1) 31 | M3pdb = PDBprice(r,M3) 32 | 33 | Mpdb = [] 34 | FBP = [] # forward bond prices 35 | y = [] 36 | for i in range(1,int(N)): 37 | M = i*dt+M1 38 | pdb = PDBprice(r,M) 39 | Mpdb.append(pdb) 40 | FBP1 = pdb / M1pdb 41 | FBP.append(FBP1) 42 | 43 | 44 | FBP2 = M3pdb/M1pdb 45 | 46 | Rfswap = ((1-FBP2)/(sum(FBP)+FBP2))*2 47 | 48 | d1 = (1 / (FSRvol * sqrt(M1))) * ((log(Rfswap / K)) + ((FSRvol ** 2) / 2) * M1) 49 | d2 = d1 - FSRvol * sqrt(M1) 50 | 51 | # for i in range(1,int(N)): 52 | # x = 1/((1+Rfswap)**N) 53 | # y.append(x) 54 | 55 | 56 | 57 | C = dt*(sum(Mpdb)+M3pdb)*(Rfswap*norm.cdf(d1) - K*norm.cdf(d2)) # *(sum(y)) 58 | 59 | print(C) -------------------------------------------------------------------------------- /AVM.py: -------------------------------------------------------------------------------- 1 | # Monte Carlo Valuation of a European Option in a Black-Scholes World 2 | # With implementation of Antithetic variates method 3 | # by Michal Lyskawinski 4 | # 10/31/2016 5 | 6 | from math import * 7 | import numpy as np 8 | # Initialize parameters 9 | S = 100 10 | r = 0.06 11 | sig = 0.2 12 | T = 1 13 | K = 100 14 | N = 10 15 | M = 100 16 | div = 0.03 # In percentage 17 | option = 'Put' 18 | 19 | # Precompute constants 20 | dt = T/N 21 | nu = r - div - 0.5*(sig**2) 22 | nudt = nu*dt 23 | sigsdt = sig*sqrt(dt) 24 | lnS = log(S) 25 | 26 | sum_CT = 0 27 | sum_CT2 = 0 28 | 29 | for j in range(1,M): # For each simulation 30 | lnST1 = lnS 31 | lnST2 = lnS 32 | 33 | for i in range(1,N): # For each time step 34 | eps = np.random.normal(0, 1) 35 | lnST1 = lnST1 + nudt + sigsdt*eps 36 | lnST2 = lnST2 + nudt + sigsdt * (-eps) 37 | 38 | St1 = exp(lnST1) 39 | St2 = exp(lnST2) 40 | if option == 'Call': 41 | CT = 0.5*(max(0, St1 - K) + max(0, St2 - K)) 42 | sum_CT = sum_CT + CT 43 | sum_CT2 = sum_CT2 + CT*CT 44 | elif option == 'Put': 45 | CT = 0.5*(max(0, K - St1) + max(0, K - St2)) 46 | sum_CT = sum_CT + CT 47 | sum_CT2 = sum_CT2 + CT * CT 48 | else: 49 | break 50 | 51 | 52 | Value = sum_CT/M*exp(-r*T) 53 | SD = sqrt((sum_CT2 - sum_CT*sum_CT/M)*exp(-2*r*T)/(M-1)) 54 | SE = SD/sqrt(M) 55 | 56 | 57 | print('The Value of European',option,'Option is',Value) 58 | print('The Standard Deviation of this Option is',SD) 59 | print('The Standard Error in this case is',SE) 60 | 61 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | 49 | # Translations 50 | *.mo 51 | *.pot 52 | 53 | # Django stuff: 54 | *.log 55 | local_settings.py 56 | 57 | # Flask stuff: 58 | instance/ 59 | .webassets-cache 60 | 61 | # Scrapy stuff: 62 | .scrapy 63 | 64 | # Sphinx documentation 65 | docs/_build/ 66 | 67 | # PyBuilder 68 | target/ 69 | 70 | # Jupyter Notebook 71 | .ipynb_checkpoints 72 | 73 | # pyenv 74 | .python-version 75 | 76 | # celery beat schedule file 77 | celerybeat-schedule 78 | 79 | # SageMath parsed files 80 | *.sage.py 81 | 82 | # dotenv 83 | .env 84 | 85 | # virtualenv 86 | .venv 87 | venv/ 88 | ENV/ 89 | 90 | # Spyder project settings 91 | .spyderproject 92 | .spyproject 93 | 94 | # Rope project settings 95 | .ropeproject 96 | 97 | # mkdocs documentation 98 | /site 99 | 100 | # mypy 101 | .mypy_cache/ 102 | -------------------------------------------------------------------------------- /EFD.py: -------------------------------------------------------------------------------- 1 | # Explicit Finite Difference method to calculate values for Call and Put European options. 2 | # Written by: Michal Lyskawinski 3 | # 10/31/2016 4 | from math import * 5 | import numpy as np 6 | 7 | S = 100 8 | r = 0.06 9 | sig = 0.2 10 | T = 1 11 | K = 100 12 | N = 3 13 | Nj = 3 14 | div = 0.03 # In percentage 15 | dx = 0.2 16 | option = 'Call' 17 | 18 | # Precompute constants 19 | nu = r - div - 0.5 * (sig ** 2) 20 | dt=T/N 21 | edx = exp(dx) 22 | pu = 0.5 * dt * ((sig / dx) ** 2 + nu / dx) 23 | pm = 1.0 - dt * (sig / dx) ** 2 - r * dt 24 | pd = 0.5 * dt * ((sig / dx) ** 2 - nu / dx) 25 | 26 | # Initialise arrays 27 | St = [] 28 | C = [] 29 | 30 | # Initialise asset prices at maturity 31 | S0= float (S*(exp(N*dx))) 32 | St.append(S0) 33 | for j in range (1,2*N+1): 34 | Sa = St[j-1]/edx 35 | St.append(Sa) 36 | 37 | # Initialise option values at maturity 38 | for j in range (0,2*N+1): 39 | if option == 'Call': 40 | Max = max(0,St[j] - K) 41 | C.append(Max) 42 | elif option == 'Put': 43 | Max = max(0, K-St[j]) 44 | C.append(Max) 45 | 46 | # Initialise payoff matrix 47 | P = np.zeros(shape=((2*N)+1,(1*N)+1)) 48 | for i in range (0,2*N+1): 49 | P[i,N] = C[i] 50 | 51 | # Step back through lattice 52 | for i in range (N-1,-1, -1): 53 | for j in range (N-i,(2*N)): 54 | P[j,i]= (pu*P[j+1,i+1]+pm*P[j,i+1]+pd*P[j-1,i+1]) 55 | 56 | # Boundary conditions: 57 | for j in range (N-i-1,-1,-1): 58 | P[j,i]= P[j+1,i] + St[j] - St[j+1] 59 | 60 | for j in range (2*N,2*N-1,-1): 61 | P[j,i]= P[j-1,i] 62 | 63 | 64 | print(P) 65 | print('The value of European',option,'option is',P[int(N),0]) 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /blackliter.R: -------------------------------------------------------------------------------- 1 | #Michal Lyskawinski 2 | #5/9/2017 3 | ######Upload data###### 4 | setwd("C:/Users/Class2017/Desktop/University/FE630") 5 | sigma <- read.csv("sigma.csv") 6 | sigma <- as.data.frame(as.matrix(sigma)) 7 | sigma$X <- NULL 8 | sigma <- subset(sigma, !is.na(aa)) 9 | sigma <- lapply(sigma, function(x) type.convert(as.character(x))) 10 | sigma <- lapply(sigma, function(x) as.numeric(x)) 11 | sigma <- as.matrix(sigma) 12 | weights <- read.csv("weights.csv") 13 | weights <- as.data.frame(weights) 14 | weights <- lapply(weights, function(x) type.convert(as.character(x))) 15 | weights <- lapply(weights, function(x) as.numeric(x)) 16 | weights <- as.matrix(weights$Market) 17 | equlibrium <- function 18 | (risk.aver, # Risk Aversion 19 | sigma, # Covariance matrix 20 | cap.weight, # Market Cap Weights 21 | risk.free # Risk Free Rate 22 | ) 23 | { 24 | return( risk.aver * sigma %*% cap.weight*100 + risk.free) 25 | } 26 | rf <- 5 27 | risk.aversion <- 2.25 28 | impleq <- equlibrium(risk.aversion,sigma,weights,rf) 29 | P<- read.csv("p-matrix.csv") 30 | 31 | P <- as.matrix(P) 32 | 33 | pmat = sum(P %*% sigma %*% t(P)) 34 | CF = pmat/(1/0.5) 35 | omega = diag(c((1/.5)*CF,(1/.65)*CF,(1/.30)*CF)) 36 | omegaAV <- mean(c((1/.5)*CF,(1/.65)*CF,(1/.30)*CF)) 37 | tau <- pmat/omegaAV 38 | Q<-c(10,3,1.5) 39 | 40 | bl.compute <- function 41 | ( 42 | mu, # Equilibrium returns 43 | cov, # Covariance matrix 44 | pmat, # Views pick matrix 45 | qmat, # Views mean vector 46 | tau,# Measure of uncertainty of the prior estimate of the mean returns 47 | omega 48 | ) 49 | { 50 | out = list() 51 | 52 | temp = solve(solve(tau * cov) + t(pmat) %*% solve(omega) %*% pmat) 53 | out$cov = cov + temp 54 | 55 | out$expected.return = temp %*% (solve(tau * cov) %*% mu + t(pmat) %*% solve(omega) %*% qmat) 56 | return(out) 57 | } 58 | 59 | 60 | ###### COMPUTATION OF BLACK_LITTERMAN FOR THE DATA 61 | bl.compute.posterior(impleq,sigma,P,Q,tau,omega) 62 | 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /CIR.py: -------------------------------------------------------------------------------- 1 | # Michal Lyskawinski 2 | # Date: 11/28/2016 3 | # CIR Model 4 | 5 | from math import * 6 | from scipy.stats import norm,chi2 7 | 8 | # interest rate parameters: 9 | rzero = 0.04 10 | rbar = 0.05 11 | a = 1.5 12 | sigma = 0.1 13 | 14 | # Option parameters: European Call 15 | OM = 2 # Option Maturity in years 16 | OBM = 6 # Option's Bond Maturity in years 17 | K = 0.73 18 | 19 | # Bond parameters: 20 | BM = 2 # Bond Maturity in years 21 | 22 | 23 | def PDB(r,M): 24 | P = exp(-r*M) 25 | return P 26 | 27 | 28 | 29 | # Pure discount Bond price calculations: 30 | def PBond(M,a,sigma,rbar,rzero): 31 | phi1 = sqrt(a ** 2 + 2 * sigma ** 2) 32 | phi2 = (a + phi1) / 2 33 | phi3 = (2 * a * rbar) / sigma ** 2 34 | B = (PDB(-phi1,M)-1)/(phi2*(PDB(-phi1,M)-1)+phi1) 35 | A = ((phi1*PDB(-phi2,M))/(phi2*(PDB(-phi1,M)-1)+phi1))**phi3 36 | P = A*PDB(B,rzero) 37 | return P 38 | 39 | print('Price of the bond =',PBond(BM,a,sigma,rbar,rzero)) 40 | 41 | def B(M,a,sigma): 42 | phi1 = sqrt(a ** 2 + 2 * sigma ** 2) 43 | phi2 = (a + phi1) / 2 44 | B = (PDB(-phi1,M)-1)/(phi2*(PDB(-phi1,M)-1)+phi1) 45 | return B 46 | 47 | def A(M,a,sigma,rbar): 48 | phi1 = sqrt(a ** 2 + 2 * sigma ** 2) 49 | phi2 = (a + phi1) / 2 50 | phi3 = (2 * a * rbar) / sigma ** 2 51 | A = ((phi1 * PDB(-phi2, M)) / (phi2 * (PDB(-phi1, M) - 1) + phi1)) ** phi3 52 | return A 53 | 54 | sigmaR = ((sigma*sqrt(rzero))/BM)*B(BM,a,sigma) # volatility of the one-year spot rate 55 | POB = PBond(OBM,a,sigma,rbar,rzero) 56 | PO = PBond(OM,a,sigma,rbar,rzero) 57 | 58 | theta = sqrt((a**2) + 2*(sigma**2)) 59 | phi = (2*theta)/((sigma**2)*(PDB(-theta,OM)-1)) 60 | Y = (a+theta)/sigma**2 61 | BOB = B(OBM-OM,a,sigma) 62 | AOB = A(OBM-OM,a,sigma,rbar) 63 | 64 | d1 = 2*rzero*(phi+Y+BOB) 65 | d2 = (4*a*rbar)/sigma**2 66 | d3 = (2*(phi**2)*rzero*PDB(-theta,OM))/(phi+Y+BOB) 67 | d4 = 2*rzero*(phi+Y) 68 | d5 = (2*(phi**2)*rzero*PDB(-theta,OM))/(phi+Y) 69 | 70 | C = POB*chi2.cdf(d1,d2,d3)-K*PO*chi2.cdf(d4,d2,d5) 71 | print(C) 72 | 73 | -------------------------------------------------------------------------------- /DELTA.py: -------------------------------------------------------------------------------- 1 | # Monte Carlo Valuation of a European Option in a Black-Scholes World 2 | # With implementation of Delta-based control variate method 3 | # by Michal Lyskawinski 4 | # 10/31/2016 5 | 6 | from math import * 7 | import numpy as np 8 | import random 9 | from scipy.stats import norm 10 | 11 | 12 | def CBS(S, K, T, r, sigma,t, option): 13 | 14 | t2t = T-t # time to maturity 15 | # Calculations for the solution to BSM equation 16 | dplus = (1 / (sigma * sqrt(t2t))) * ((log(S / K)) + (r + ((sigma ** 2) / 2)) * t2t) 17 | dminus = (1 / (sigma * sqrt(t2t))) * ((log(S / K)) + (r - (sigma ** 2) / 2) * t2t) 18 | 19 | # Calculating price of Call and Put 20 | if option == 'Call': 21 | return S * norm.cdf(dplus) - K * exp(-r * t2t) * norm.cdf(dminus) 22 | elif option == 'Put': 23 | return K * exp(-r * t2t) * norm.cdf(-dminus) - S * norm.cdf(-dplus) 24 | 25 | 26 | # Initialize parameters 27 | S = 100 28 | r = 0.06 29 | sig = 0.2 30 | T = 1 31 | K = 100 32 | N = 10 33 | M = 100 34 | div = 0.03 # In percentage 35 | option = 'Call' 36 | 37 | # Precompute constants 38 | dt = T/N 39 | nu = r - div - 0.5*(sig**2) 40 | nudt = nu*dt 41 | sigsdt = sig*sqrt(dt) 42 | erddt = exp((r-div)*dt) 43 | 44 | beta1 = -1 45 | 46 | sum_CT = 0 47 | sum_CT2 = 0 48 | 49 | for j in range(1,M): # For each simulation 50 | 51 | St = S 52 | cv = 0 53 | 54 | for i in range(1,N): # For each time step 55 | t = (i-1)*dt 56 | delta = CBS(St,K,T,r,sig,t,option) 57 | eps = np.random.normal(0, 1) 58 | Stn = St*exp(nudt+sigsdt*eps) 59 | cv1 = cv + delta*(Stn-St*erddt) 60 | St = Stn 61 | 62 | 63 | if option == 'Call': 64 | CT = max(0, St - K) + beta1*cv1 65 | sum_CT = sum_CT + CT 66 | sum_CT2 = sum_CT2 + CT*CT 67 | elif option == 'Put': 68 | CT = max(0, K - St) + beta1*cv1 69 | sum_CT = sum_CT + CT 70 | sum_CT2 = sum_CT2 + CT * CT 71 | else: 72 | break 73 | 74 | 75 | Value = sum_CT/M*exp(-r*T) 76 | SD = sqrt((sum_CT2 - sum_CT*sum_CT/M)*exp(-2*r*T)/(M-1)) 77 | SE = SD/sqrt(M) 78 | 79 | 80 | print('The Value of European',option,'Option is',Value) 81 | print('The Standard Deviation of this Option is',SD) 82 | print('The Standard Error in this case is',SE) 83 | 84 | 85 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /AVM + DELTA.py: -------------------------------------------------------------------------------- 1 | # Monte Carlo Valuation of a European Option in a Black-Scholes World 2 | # With implementation of Antithetic and Delta-based control variate method 3 | # by Michal Lyskawinski 4 | # 10/31/2016 5 | 6 | from math import * 7 | import numpy as np 8 | import random 9 | from scipy.stats import norm 10 | 11 | # Computation of Black-Scholes 12 | def CBS(S, K, T, r, sigma,t, option): 13 | 14 | t2t = T-t # time to maturity 15 | # Calculations for the solution to BSM equation 16 | dplus = (1 / (sigma * sqrt(t2t))) * ((log(S / K)) + (r + ((sigma ** 2) / 2)) * t2t) 17 | dminus = (1 / (sigma * sqrt(t2t))) * ((log(S / K)) + (r - (sigma ** 2) / 2) * t2t) 18 | 19 | # Calculating price of Call and Put 20 | if option == 'Call': 21 | return S * norm.cdf(dplus) - K * exp(-r * t2t) * norm.cdf(dminus) 22 | elif option == 'Put': 23 | return K * exp(-r * t2t) * norm.cdf(-dminus) - S * norm.cdf(-dplus) 24 | 25 | 26 | # Initialize parameters 27 | S = 100 28 | r = 0.06 29 | sig = 0.2 30 | T = 1 31 | K = 100 32 | N = 10 33 | M = 100 34 | div = 0.03 # In percentage 35 | option = 'Put' 36 | 37 | # Precompute constants 38 | dt = T/N 39 | nu = r - div - 0.5*(sig**2) 40 | nudt = nu*dt 41 | sigsdt = sig*sqrt(dt) 42 | erddt = exp((r-div)*dt) 43 | beta1 = -1 44 | 45 | sum_CT = 0 46 | sum_CT2 = 0 47 | 48 | for j in range(1,M): # For each simulation 49 | St1 = S 50 | St2 = S 51 | cv1 = 0 52 | cv2 = 0 53 | 54 | for i in range(1,N): # For each time step 55 | t = (i - 1) * dt 56 | delta1 = CBS(St1, K, T, r, sig, t, option) 57 | delta2 = CBS(St2, K, T, r, sig, t, option) 58 | eps = np.random.normal(0, 1) 59 | Stn1 = St1 * exp(nudt + sigsdt * eps) 60 | Stn2 = St2 * exp(nudt + sigsdt * (-eps)) 61 | cv1a = cv1 + delta1 * (Stn1 - St1 * erddt) 62 | cv2a = cv2 + delta2 * (Stn2 - St2 * erddt) 63 | St1 = Stn1 64 | St2 = Stn2 65 | 66 | if option == 'Call': 67 | CT = 0.5*(max(0, St1 - K) + beta1*cv1a + max(0, St2 - K) + beta1*cv2a) 68 | sum_CT = sum_CT + CT 69 | sum_CT2 = sum_CT2 + CT*CT 70 | elif option == 'Put': 71 | CT = 0.5*(max(0, K - St1) + beta1*cv1a + max(0, K - St2) + beta1*cv2a) 72 | sum_CT = sum_CT + CT 73 | sum_CT2 = sum_CT2 + CT * CT 74 | else: 75 | break 76 | 77 | 78 | Value = sum_CT/M*exp(-r*T) 79 | SD = sqrt((sum_CT2 - sum_CT*sum_CT/M)*exp(-2*r*T)/(M-1)) 80 | SE = SD/sqrt(M) 81 | 82 | 83 | print('The Value of European',option,'Option is',Value) 84 | print('The Standard Deviation of this Option is',SD) 85 | print('The Standard Error in this case is',SE) 86 | 87 | 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /Implied_VOT.py: -------------------------------------------------------------------------------- 1 | # Only using toolbox functions for normal CDF calculation and mathematical tools and excel operations 2 | from math import * 3 | import random 4 | from scipy.stats import norm 5 | import openpyxl 6 | 7 | # Opening the data file 8 | wb = openpyxl.load_workbook('Data1.xlsx') 9 | sheet1 = wb.get_sheet_by_name('SPY1118') 10 | 11 | # Initializing constants: 12 | T = 52/365 # Time to maturity = Recorded on 9/26 13 | S = 214.95 # Underlying asset price 14 | r = 0.4 # interest rate 15 | tol = 10**-6 # tolerance 16 | A = 2 # starting row in excel 17 | 18 | # Initializing arrays for variables 19 | K = [0]*101 # Array of strike prices 20 | Vol = [0]*101 # Array of implied volatility 21 | Bid = [0]*101 22 | Ask = [0]*101 23 | C = [0]*101 24 | 25 | option = 'Call' 26 | 27 | def impliedvol(S, K, T, r, option,C,tol): 28 | 29 | def CBS(S, K, T, r, sigma, option): 30 | # Calculations for the solution to BSM equation 31 | dplus = (1 / (sigma * sqrt(T))) * ((log(S / K)) + (r + (sigma ** 2) / 2) * T) 32 | dminus = (1 / (sigma * sqrt(T))) * ((log(S / K)) + (r - (sigma ** 2) / 2) * T) 33 | 34 | # Calculating price of Call and Put 35 | if option == 'Call': 36 | return S * norm.cdf(dplus) - K * exp(-r * T) * norm.cdf(dminus) 37 | elif option == 'Put': 38 | return K * exp(-r * T) * norm.cdf(-dminus) - S * norm.cdf(-dplus) 39 | 40 | 41 | def f(x, option): 42 | return CBS(S, K, T, r, x, option) - C 43 | 44 | 45 | # Calculating implied votality by bisection method 46 | t = 0 47 | while t < 1000: 48 | t = t + 1 49 | a = random.uniform(0, 100) 50 | b = random.uniform(0, 100) 51 | if (f(a, option)) * (f(b, option)) < 0: 52 | break 53 | else: 54 | continue 55 | 56 | 57 | 58 | def bsecvot(S, K, T, r, option, a, b): 59 | c = (a + b) / 2 60 | if f(a,option) == 0: 61 | return a 62 | 63 | elif f(b,option) == 0: 64 | return b 65 | 66 | elif f(a,option) * f(b,option) < 0: 67 | while abs(b - a) > tol: 68 | 69 | if f(a,option) * f(c,option) < 0: 70 | b = c 71 | c = (a + b) / 2 72 | # print('C1') 73 | continue 74 | 75 | elif f(b,option)*f(c,option) < 0: 76 | a = c 77 | c = (a + b) / 2 78 | #print('C2') 79 | continue 80 | return c 81 | 82 | return bsecvot(S, K, T, r, option, a, b) 83 | 84 | while A < 124: 85 | A=A+1 86 | Bid[A] = sheet1.cell(row=A, column=4).value 87 | Ask[A] = sheet1.cell(row=A, column=5).value 88 | K[A] = sheet1.cell(row=A, column=1).value 89 | 90 | C[A] = (Bid[A] + Ask[A]) / 2 91 | Vol[A] = impliedvol(S,K[A],T,r,option,C[A],tol) 92 | 93 | print(Vol) 94 | 95 | 96 | -------------------------------------------------------------------------------- /ImpNEW.py: -------------------------------------------------------------------------------- 1 | # Implicit Finite Difference method to calculate values for Call and Put European options. 2 | # Written by: Michal Lyskawinski 3 | # 10/31/2016 4 | 5 | from math import * 6 | 7 | # Initialize parameters 8 | K = 100 9 | S = 100 10 | r = 0.06 11 | sig = 0.2 12 | T = 1 13 | N = 3 14 | Nj = 3 15 | div = 0.03 # In percentage 16 | dx = 0.2 17 | option = 'Call' 18 | 19 | # Precompute constants 20 | dt = T/N 21 | nu = r - div - 0.5*(sig**2) 22 | edx = exp(dx) 23 | pu = 0.5*dt*((sig/dx)**2 + nu/dx) 24 | pm = 1.0 - dt*(sig/dx)**2 - r*dt 25 | pd = 0.5*dt*((sig/dx)**2 - nu/dx) 26 | 27 | 28 | # print("dt=",dt) 29 | # print("nu=",nu) 30 | # print("edx=",edx) 31 | # print("pu=",pu) 32 | # print("pm=",pm) 33 | # print("pd=",pd) 34 | 35 | #Initialise arrays for asset prices(St) and option values(C) 36 | St = [0 for i in range(2*Nj+1)] 37 | C = [[0 for i in range(2*Nj+1)] for j in range(N+1)] 38 | 39 | 40 | # Initialize asset prices at maturity 41 | St[0] = S*exp(-Nj*dx) 42 | for j in range(1, 2*Nj+1): 43 | St[j] = St[j-1]*edx 44 | 45 | # Initialize option values at maturity 46 | for j in range(0,2*Nj+1): 47 | if option == 'Call': 48 | C[0][j] = max(0, St[j] - K) 49 | elif option == 'Put': 50 | C[0][j] = max(0, K - St[j]) 51 | else: 52 | break 53 | 54 | # Compute derivative BC's 55 | if option == 'Call': 56 | lambdaL = 0.0 57 | lambdaU = St[1] - St[0] 58 | elif option == 'Put': 59 | lambdaL = -1*(St[1]-St[0]) 60 | lambdaU = 0.0 61 | 62 | def solve_implicit_tridiagonal_system(C,pu,pm,pd,lambdaL,lambdaU): 63 | # Substituting BC's at j=0 in j=1 64 | pmp = [0 for i in range(2 * Nj)] 65 | pp = [0 for i in range(2 * Nj)] 66 | pmp[1] = pm + pd 67 | pp[1] = C[0][1] + pd * lambdaL 68 | 69 | # eliminating upper diagonal 70 | for j in range(2, 2 * Nj+1-1): 71 | pmp[j] = pm - pu * pd / pmp[j - 1] 72 | pp[j] = C[0][j] - pp[j - 1] * pd / pmp[j - 1] 73 | 74 | # Using other BC's 75 | C[1][2 * Nj] = (pp[2 * Nj - 1] + pmp[2 * Nj - 1] * lambdaU) / (pu + pmp[2 * Nj - 1]) 76 | C[1][2 * Nj - 1] = C[1][2 * Nj] - lambdaU 77 | 78 | # Back - substitution 79 | for j in range(2 * Nj+1-2, 0, -1): 80 | C[1][j] = (pp[j] - pu * C[1][j + 1]) / pmp[j] 81 | 82 | return 83 | 84 | 85 | for i in range(2*N+1-1,Nj,-1): 86 | solve_implicit_tridiagonal_system(C,pu,pm,pd,lambdaL,lambdaU) 87 | # In case of american: 88 | for j in range(0,2*Nj+1): 89 | # if option == 'Call': 90 | # C[0][j] = max(C[1][j],St[j] - K) 91 | # elif option == 'Put': 92 | # C[0][j] = max(C[1][j],K - St[j]) 93 | C[0][j] = C[1][j] 94 | 95 | 96 | print(C) 97 | print(C[0][Nj]) 98 | 99 | 100 | 101 | 102 | 103 | 104 | # Nj = 2Nj for array, 2Nj +1 for range 105 | # -Nj = 0 106 | # 0 = (if exen 6/2 =3 , if odd 7/2 = 3.5 + 0.5 107 | 108 | 109 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Quant-Projects 2 | 1.BSM.py 3 | Implementation of Black-Scholes-Merton modelas a function of current stock price S0, volatility time to expiration T−t (in years), strike price K and short-term interest rate r (annual). 4 | 5 | 2.EuroOpt.py 6 | Constructed a binomial tree model to calculate the values of the European Call option and one for the European Put option. 7 | 8 | 3.American.py 9 | Implemented a binomial tree to calculate the American option,both Call and Put. 10 | 11 | 4. Implied_VOT.py 12 | Implemented the Bisection method to find the root of arbitrary functions. Applied this method to calculate the implied volatility. 13 | 14 | 5.Comp.py 15 | Comparison of BSM, EuroOPT and American 16 | 17 | 6.AVM + DELTA.py 18 | Monte Carlo Valuation of a European Option in a Black-Scholes World With implementation of Antithetic and Delta-based control variate method (10/31/2016) 19 | 20 | 7. AVM.py 21 | Monte Carlo Valuation of a European Option in a Black-Scholes World With implementation of Antithetic variates method (10/31/2016) 22 | 23 | 8.DELTA.py 24 | Monte Carlo Valuation of a European Option in a Black-Scholes World With implementation of Delta-based control variate method (10/31/2016) 25 | 26 | 9.EFD.py 27 | Explicit Finite Difference method to calculate values for Call and Put European options. 28 | 29 | 10.ImpNEW.py 30 | Implicit Finite Difference method to calculate values for Call and Put European options. 31 | 32 | 11.Reg_Monte.py 33 | Monte Carlo Valuation of a European Option in a Black-Scholes World 34 | 35 | 12.Trinomial.py 36 | Trinomial tree to calculate values for Call and Put European options. 37 | 38 | 13.Impl_Trinomial_Tree.py 39 | Constructed a four time step implied trinomial tree, and computed the state prices and the implied transition probabilities at each 40 | node. 41 | 42 | 14.Amer_Up&Out_put.py 43 | Priced an American Up-and-Out put option using implied trinomial tree 44 | 45 | 15.Black's_Euro_call.py 46 | Using Black's model: Priced a two year European call option with strike 0.8 on a seven-year pure discount bond. 47 | 48 | 16.Black's_Interest_Rate_Cap.py 49 | Using Black's model: Priced an interest rate cap at 4.7%. Assume that the cap is for a two year period, the reset frequency is four months. Assuming that the volatility of the forward rate is 9%. The principal of the swap is 1 million. 50 | 51 | 17.Black's_swap.py 52 | Using Black's model: Priced a one year option which exercise into a new two year semi-annual payer swap. The strike price of the option is 6% and the forward swap rate volatility is 10% 53 | 54 | 18.Vasicek.py 55 | Using Vasicek model priced a two-year pure discount bond and a two-year European call option on a six-year pure discount bond. 56 | 57 | 19.CIR.py 58 | Using CIR model priced a two-year pure discount bond and a two-year European call option on a six-year pure discount bond 59 | 60 | 20.Ho-Lee.py 61 | Using Ho-Lee model priced a two-year pure discount bond and a two-year European call option on a six-year pure discount bond 62 | 63 | 21.Hull-White.py 64 | Using Hull-White model priced a two-year pure discount bond and a two-year European call option on a six-year pure discount bond 65 | 66 | 22.blackliter.R 67 | Implementation of Black–Litterman model 68 | -------------------------------------------------------------------------------- /Impl_Trinomial_Tree.py: -------------------------------------------------------------------------------- 1 | from math import exp 2 | import numpy as np 3 | import openpyxl as op 4 | 5 | wb = op.load_workbook('Euro_prices_F5.3.xlsx') 6 | 7 | 8 | def call(x,y): 9 | sheet_call = wb.get_sheet_by_name('Call') 10 | c = sheet_call.cell(row=x, column=y).value 11 | return c 12 | 13 | 14 | def put(x,y): 15 | sheet_put = wb.get_sheet_by_name('Put') 16 | c = sheet_put.cell(row=x, column=y).value 17 | return c 18 | 19 | # Initialize parameters 20 | T = 1 21 | S = 100 22 | r = 0.05 23 | N = 4 24 | dx = 0.2524 25 | 26 | # Precompute constants 27 | 28 | dt = T/N 29 | edx = exp(dx) 30 | infl = exp(r*dt) 31 | 32 | # Initialize the matrices 33 | 34 | St = np.zeros((2*N + 1, N + 1), dtype=np.float64) # Asset prices 35 | Q = np.zeros((2*N + 1, N + 1), dtype=np.float64) # State prices 36 | pu = np.zeros((2*N + 1, N + 1), dtype=np.float64) 37 | pm = np.zeros((2*N + 1, N + 1), dtype=np.float64) 38 | pd = np.zeros((2*N + 1, N + 1), dtype=np.float64) 39 | 40 | # Initialize asset prices 41 | St[2*N, N] = S*exp(-N*dx) 42 | for j in range(2*N-1,-1,-1): 43 | St[j,N] = St[j+1,N]*edx 44 | 45 | 46 | # For each time step: 47 | 48 | for i in range(0,N+1): 49 | for j in range(N-i,N+1,1): 50 | sum = 0 51 | for k in range(j-2,N,1): #Not sure 52 | sum = sum + Q[k, i]*(St[k, N] - St[j + 1,N]) 53 | # k = j-1 54 | # sum = sum + Q[k, i] * (St[k, N] - St[j + 1, N]) 55 | 56 | D = St[j,N] - St[j+1,N] 57 | Q[j,i] = (call(j+1, i+1) - sum)/D 58 | 59 | for j in range(N+i, N, -1): 60 | # print(j, i) 61 | sum = 0 62 | for k in range(N+i, j+2, 1): # Not sure 63 | if k<=8: 64 | sum = sum + Q[k, i] * (St[j-1, N] - St[k, N]) 65 | 66 | D = St[j-1, N] - St[j , N] 67 | Q[j, i] = (put(j - 1, i + 1) - sum) / D 68 | 69 | 70 | # Implied Trinomial Tree Transition Probabilities 71 | 72 | for i in range(0,N): 73 | for j in range(N-i,N+1,1): 74 | if j == N - i: 75 | pu[N - i, i] = infl * Q[N - i - 1, i + 1] / Q[N - i, i] 76 | pm[j, i] = (infl * St[j, N] - St[j + 1, N] - pu[j, i] * (St[j - 1, N] - St[j + 1, N])) / (St[j, N] - St[j + 1, N]) 77 | pd[j, i] = 1 - pm[j, i] - pu[j, i] 78 | 79 | elif j == N - i + 1: 80 | pu[N - i + 1, i] = (infl * Q[N - i, i + 1] - pm[N - i, i] * Q[N - i, i]) / Q[N - i + 1, i] 81 | pm[j, i] = (infl * St[j, N] - St[j + 1, N] - pu[j, i] * (St[j - 1, N] - St[j + 1, N])) / (St[j, N] - St[j + 1, N]) 82 | pd[j, i] = 1 - pm[j, i] - pu[j, i] 83 | else: 84 | pu[j, i] = (infl * Q[j - 1, i + 1] - pd[j - 2, i] * Q[j - 2, i] - pm[j - 1, i] * Q[j - 1, i]) / Q[j, i] 85 | pm[j, i] = (infl * St[j, N] - St[j + 1, N] - pu[j, i] * (St[j - 1, N] - St[j + 1, N])) / (St[j, N] - St[j + 1, N]) 86 | pd[j, i] = 1 - pm[j, i] - pu[j, i] 87 | 88 | for j in range(N + i, N, -1): 89 | if j == N+i: 90 | pd[N+i,i] = infl*Q[N+i+1,i+1]/Q[N+i,i] 91 | pm[j, i] = (infl * St[j, N] - St[j - 1, N] - pd[j, i] * (St[j + 1, N] - St[j - 1, N])) / (St[j, N] - St[j - 1, N]) 92 | pu[j, i] = 1 - pm[j, i] - pd[j, i] 93 | 94 | elif j == N + i - 1: 95 | pd[N + i - 1,i] = (infl*Q[N+i,i+1] - pm[N+i,i]*Q[N+i,i])/Q[N+i-1,i] 96 | pm[j, i] = (infl * St[j, N] - St[j - 1, N] - pd[j, i] * (St[j + 1, N] - St[j - 1, N])) / (St[j, N] - St[j - 1, N]) 97 | pu[j, i] = 1 - pm[j, i] - pd[j, i] 98 | else: 99 | pd[j,i] = (infl * Q[j + 1, i + 1] - pu[j + 2, i] * Q[j + 2, i] - pm[j + 1, i] * Q[j + 1, i]) / Q[j, i] 100 | pm[j,i] = (infl * St[j, N] - St[j - 1, N] - pd[j, i] * (St[j + 1, N] - St[j - 1, N])) / (St[j, N] - St[j - 1, N]) 101 | pu[j,i] = 1 - pm[j, i] - pd[j, i] 102 | 103 | # np.savetxt("StatePrices.csv", Q, delimiter=",") 104 | # np.savetxt("pm.csv", pm, delimiter=",") 105 | # np.savetxt("pd.csv", pd, delimiter=",") 106 | # np.savetxt("pu.csv", pu, delimiter=",") -------------------------------------------------------------------------------- /Comp.py: -------------------------------------------------------------------------------- 1 | from math import * 2 | from scipy.stats import norm 3 | import openpyxl 4 | 5 | # Opening the data file 6 | wb = openpyxl.load_workbook('Data2.xlsx') 7 | sheet1 = wb.get_sheet_by_name('SPY1118') 8 | 9 | # Initializing arrays for variables 10 | K = [0]*500 # Array of strike prices 11 | BS = [0]*500 # Array of BSM prices 12 | EU = [0]*500 13 | AM = [0]*500 14 | 15 | 16 | # Initializing constants: 17 | 18 | T = (24/365) # Time to maturity 19 | S = 214.95 # Underlying asset price 20 | r = 0.4 # interest rate 21 | tol = 10**-6 # tolerance 22 | A = 107 # starting row in excel 23 | sigma = 0.3 # Implied volatility Call 24 | N = 100 25 | option = 'Put' 26 | 27 | # Calculating option value using BSM: 28 | def CBS(S, K, T, r, sigma, option): 29 | # Calculations for the solution to BSM equation 30 | dplus = (1 / (sigma * sqrt(T))) * ((log(S / K)) + (r + (sigma ** 2) / 2) * T) 31 | dminus = (1 / (sigma * sqrt(T))) * ((log(S / K)) + (r - (sigma ** 2) / 2) * T) 32 | 33 | # Calculating price of Call and Put 34 | if option == 'Call': 35 | return S * norm.cdf(dplus) - K * exp(-r * T) * norm.cdf(dminus) 36 | elif option == 'Put': 37 | return K * exp(-r * T) * norm.cdf(-dminus) - S * norm.cdf(-dplus) 38 | 39 | # Calculating option value using binomial for european: 40 | def euro(S, r, sigma, K, N, option): 41 | # Compute more constants 42 | v = r - 0.5 * sigma ** 2 43 | deltaT = T / N 44 | disc = exp(-r * deltaT) 45 | dxu = sqrt((sigma ** 2) * deltaT + (v * deltaT) ** 2) 46 | dxd = -dxu 47 | # p = (exp(r*deltaT)-d)/(u-d) # probability of going up 48 | pu = 0.5 + 0.5 * ((v * deltaT) / dxu) 49 | pd = 1 - pu 50 | 51 | # Initialize arrays 52 | St = [0] * (N + 1) 53 | C = [0] * (N + 1) 54 | 55 | # Initialize asset prices at maturity N 56 | St[0] = S * exp(N * dxd) 57 | for j in range(1, N): 58 | St[j] = St[j - 1] * exp(dxu - dxd) 59 | 60 | # Initialize option values at maturity 61 | for j in range(0, N): 62 | if option == 'Call': 63 | C[j] = max(0.0, St[j] - K) 64 | elif option == 'Put': 65 | C[j] = max(0.0, K - St[j]) 66 | 67 | # Step back through the tree 68 | for i in range(N - 1, 0): 69 | for j in range(0, i): 70 | C[j] = disc * (pu * C[j + 1] + pd * C[j]) 71 | if option == 'Call': 72 | return C[51] 73 | elif option == 'Put': 74 | return C[0] 75 | 76 | def american(S, r, sigma, T, K, N, option): 77 | dt = T / N 78 | u = exp(sigma * sqrt(dt)) 79 | d = 1 / u 80 | p = (exp(r * dt) - d) / (u - d) 81 | disc = exp(-r * dt) 82 | 83 | St = [0] * (N + 1) 84 | C = [0] * (N + 1) 85 | 86 | St[0] = S * d ** N 87 | for j in range(1, N): 88 | St[j] = St[j - 1] * (u / d) 89 | 90 | for j in range(0, N): 91 | if option == 'Put': 92 | C[j] = max(0.0, K - St[j]) 93 | elif option == 'Call': 94 | C[j] = max(0.0, St[j] - K) 95 | else: 96 | break 97 | 98 | for i in range(N - 1, 0): 99 | for j in range(0, i): 100 | C[j] = disc * (p * C[j + 1] + (1 - p) * C[j]) 101 | St[j] = (St[j]) / d 102 | if option == 'Put': 103 | C[j] = max(C[j], K - St[j]) 104 | elif option == 'Call': 105 | C[j] = max(C[j], St[j] - K) 106 | next(j) 107 | next(i) 108 | if option == 'Call': 109 | return C[52] 110 | elif option == 'Put': 111 | return C[0] 112 | 113 | 114 | ## Calculating option value using Binomial Theorem: 115 | 116 | # Loop for finding values for each row 117 | while A < 211: 118 | A=A+1 119 | 120 | K[A] = float(sheet1.cell(row=(A), column=1).value) 121 | BS[A]= CBS(S,K[A],T,r,sigma,option) 122 | EU[A]= euro(S, r, sigma, K[A], N, option) 123 | AM[A]= american(S, r, sigma, T, K[A], N, option) 124 | 125 | 126 | print(BS) 127 | print(EU) 128 | print(AM) 129 | 130 | -------------------------------------------------------------------------------- /Amer_Up&Out_put.py: -------------------------------------------------------------------------------- 1 | from math import exp 2 | import numpy as np 3 | import openpyxl as op 4 | 5 | 6 | # Initialize parameters 7 | K = 100 8 | T = 1 9 | S = 100 10 | r = 0.05 11 | H = 110 12 | X_rebate = 1 13 | N = 4 14 | dx = 0.2524 15 | 16 | wb = op.load_workbook('Euro_prices_F5.3.xlsx') 17 | 18 | 19 | def call(x,y): 20 | sheet_call = wb.get_sheet_by_name('Call') 21 | c = sheet_call.cell(row=x, column=y).value 22 | return c 23 | 24 | 25 | def put(x,y): 26 | sheet_put = wb.get_sheet_by_name('Put') 27 | c = sheet_put.cell(row=x, column=y).value 28 | return c 29 | 30 | 31 | # Precompute constants 32 | 33 | dt = T/N 34 | edx = exp(dx) 35 | infl = exp(r*dt) 36 | 37 | # Initialize the matrices 38 | 39 | St = np.zeros((2*N + 1, N + 1), dtype=np.float64) # Asset prices 40 | Q = np.zeros((2*N + 1, N + 1), dtype=np.float64) # State prices 41 | pu = np.zeros((2*N + 1, N + 1), dtype=np.float64) 42 | pm = np.zeros((2*N + 1, N + 1), dtype=np.float64) 43 | pd = np.zeros((2*N + 1, N + 1), dtype=np.float64) 44 | 45 | # Initialize asset prices 46 | St[2*N, N] = S*exp(-N*dx) 47 | for j in range(2*N-1,-1,-1): 48 | St[j,N] = St[j+1,N]*edx 49 | 50 | 51 | # For each time step: 52 | 53 | for i in range(0,N+1): 54 | for j in range(N-i,N+1,1): 55 | sum = 0 56 | for k in range(j-2,N,1): #Not sure 57 | sum = sum + Q[k, i]*(St[k, N] - St[j + 1,N]) 58 | # k = j-1 59 | # sum = sum + Q[k, i] * (St[k, N] - St[j + 1, N]) 60 | 61 | D = St[j,N] - St[j+1,N] 62 | Q[j,i] = (call(j+1, i+1) - sum)/D 63 | 64 | for j in range(N+i, N, -1): 65 | # print(j, i) 66 | sum = 0 67 | for k in range(N+i, j+2, 1): # Not sure 68 | if k<=8: 69 | sum = sum + Q[k, i] * (St[j-1, N] - St[k, N]) 70 | 71 | D = St[j-1, N] - St[j , N] 72 | Q[j, i] = (put(j - 1, i + 1) - sum) / D 73 | 74 | 75 | # Implied Trinomial Tree Transition Probabilities 76 | 77 | for i in range(0,N): 78 | for j in range(N-i,N+1,1): 79 | if j == N - i: 80 | pu[N - i, i] = infl * Q[N - i - 1, i + 1] / Q[N - i, i] 81 | pm[j, i] = (infl * St[j, N] - St[j + 1, N] - pu[j, i] * (St[j - 1, N] - St[j + 1, N])) / (St[j, N] - St[j + 1, N]) 82 | pd[j, i] = 1 - pm[j, i] - pu[j, i] 83 | 84 | elif j == N - i + 1: 85 | pu[N - i + 1, i] = (infl * Q[N - i, i + 1] - pm[N - i, i] * Q[N - i, i]) / Q[N - i + 1, i] 86 | pm[j, i] = (infl * St[j, N] - St[j + 1, N] - pu[j, i] * (St[j - 1, N] - St[j + 1, N])) / (St[j, N] - St[j + 1, N]) 87 | pd[j, i] = 1 - pm[j, i] - pu[j, i] 88 | else: 89 | pu[j, i] = (infl * Q[j - 1, i + 1] - pd[j - 2, i] * Q[j - 2, i] - pm[j - 1, i] * Q[j - 1, i]) / Q[j, i] 90 | pm[j, i] = (infl * St[j, N] - St[j + 1, N] - pu[j, i] * (St[j - 1, N] - St[j + 1, N])) / (St[j, N] - St[j + 1, N]) 91 | pd[j, i] = 1 - pm[j, i] - pu[j, i] 92 | 93 | for j in range(N + i, N, -1): 94 | if j == N+i: 95 | pd[N+i,i] = infl*Q[N+i+1,i+1]/Q[N+i,i] 96 | pm[j, i] = (infl * St[j, N] - St[j - 1, N] - pd[j, i] * (St[j + 1, N] - St[j - 1, N])) / (St[j, N] - St[j - 1, N]) 97 | pu[j, i] = 1 - pm[j, i] - pd[j, i] 98 | 99 | elif j == N + i - 1: 100 | pd[N + i - 1,i] = (infl*Q[N+i,i+1] - pm[N+i,i]*Q[N+i,i])/Q[N+i-1,i] 101 | pm[j, i] = (infl * St[j, N] - St[j - 1, N] - pd[j, i] * (St[j + 1, N] - St[j - 1, N])) / (St[j, N] - St[j - 1, N]) 102 | pu[j, i] = 1 - pm[j, i] - pd[j, i] 103 | else: 104 | pd[j,i] = (infl * Q[j + 1, i + 1] - pu[j + 2, i] * Q[j + 2, i] - pm[j + 1, i] * Q[j + 1, i]) / Q[j, i] 105 | pm[j,i] = (infl * St[j, N] - St[j - 1, N] - pd[j, i] * (St[j + 1, N] - St[j - 1, N])) / (St[j, N] - St[j - 1, N]) 106 | pu[j,i] = 1 - pm[j, i] - pd[j, i] 107 | 108 | #Valution of American Up And Out Put Option 109 | 110 | # Precompute constants 111 | disc = exp(-r*dt) 112 | 113 | # Initialize the matrix 114 | 115 | C = np.zeros((2*N + 1, N + 1), dtype=np.float64) # Option Value 116 | 117 | # Initialize option values at maturity 118 | 119 | for j in range(0,2*N+1): 120 | if St[j,N] < H: 121 | C[j,N] = max(0.0,K - St[j,N]) 122 | else: 123 | C[j,N] = 0.0 124 | 125 | for i in range(N-1,-1,-1): 126 | for j in range(N-i-1,N+i+1): 127 | if St[j,N] < H: 128 | C[j,i] = disc*(pu[j,i]*C[j-1,i+1] + pm[j,i]*C[j,i+1] + pd[j,i]*C[j+1,i+1]) 129 | 130 | # Apply the early exercise condition 131 | C[j,i] = max(C[j,i],K - St[j,N]) 132 | else: 133 | C[j,i] = X_rebate 134 | 135 | # np.savetxt("AmericanUpnOutPut.csv", C, delimiter=",") 136 | 137 | --------------------------------------------------------------------------------