Add closed form Black-Scholes model
This commit is contained in:
28
models.go
28
models.go
@@ -82,7 +82,33 @@ func (opt *Option) PriceMonteCarlo() {
|
|||||||
opt.Delta = (opt.Delta/float64(opt.Sims)*df - opt.FV) / 0.0001
|
opt.Delta = (opt.Delta/float64(opt.Sims)*df - opt.FV) / 0.0001
|
||||||
opt.Gamma = (opt.Gamma/float64(opt.Sims)*df - opt.FV) / 10000
|
opt.Gamma = (opt.Gamma/float64(opt.Sims)*df - opt.FV) / 10000
|
||||||
opt.Vega = (opt.Vega/float64(opt.Sims)*df - opt.FV) / 0.01
|
opt.Vega = (opt.Vega/float64(opt.Sims)*df - opt.FV) / 0.01
|
||||||
opt.Theta = (opt.Theta/float64(opt.Sims)*math.Exp(-opt.Rfr*(tte-1./365)) - opt.FV) / -(1. / 365)
|
opt.Theta = (opt.Theta/float64(opt.Sims)*math.Exp(-opt.Rfr*(tte-1./365)) -
|
||||||
|
opt.FV) / -(1. / 365)
|
||||||
opt.Rho = (opt.Rho/float64(opt.Sims)*math.Exp(-(opt.Rfr+0.01)*tte) - opt.FV)
|
opt.Rho = (opt.Rho/float64(opt.Sims)*math.Exp(-(opt.Rfr+0.01)*tte) - opt.FV)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (opt *Option) PriceClosedForm() {
|
||||||
|
var d1, d2, tte float64
|
||||||
|
|
||||||
|
tte = opt.ExpiryDate.Sub(opt.ValueDate).Hours() / (24 * 365)
|
||||||
|
|
||||||
|
d1 = (math.Log(opt.Spot/opt.Strike) + tte*(opt.Rfr+math.Pow(opt.Vol, 2)/2)) /
|
||||||
|
(opt.Vol * math.Pow(tte, 0.5))
|
||||||
|
d2 = d1 - (opt.Vol * math.Pow(tte, 0.5))
|
||||||
|
|
||||||
|
opt.FV = opt.Spot*NormCDF(d1*float64(opt.OptType))*float64(opt.OptType) -
|
||||||
|
opt.Strike*math.Exp(-opt.Rfr*tte)*
|
||||||
|
NormCDF(d2*float64(opt.OptType))*float64(opt.OptType)
|
||||||
|
opt.Delta = NormCDF(d1)
|
||||||
|
if opt.OptType == -1 {
|
||||||
|
opt.Delta -= 1
|
||||||
|
}
|
||||||
|
opt.Gamma = 1 / (opt.Vol * math.Sqrt(tte) * math.Sqrt(2*math.Pi)) *
|
||||||
|
math.Exp(-d1*d1/2)
|
||||||
|
opt.Vega = opt.Spot / 100 * math.Pow(tte, 0.5) * NormPDF(d1)
|
||||||
|
opt.Rho = float64(opt.OptType) * tte * opt.Strike * math.Exp(-opt.Rfr*tte) *
|
||||||
|
NormCDF(float64(opt.OptType)*d2) / 100
|
||||||
|
opt.Theta = -float64(opt.OptType)*(opt.Rfr*opt.Strike*math.Exp(-opt.Rfr*tte)*
|
||||||
|
NormCDF(float64(opt.OptType)*d1)) - (opt.Vol/2*math.Pow(tte, 0.5))*
|
||||||
|
opt.Spot*NormPDF(float64(opt.OptType)*d1)
|
||||||
|
}
|
||||||
|
|||||||
1
serve.go
1
serve.go
@@ -22,6 +22,7 @@ func index(w http.ResponseWriter, r *http.Request) {
|
|||||||
json.Unmarshal(body, &mcOpt)
|
json.Unmarshal(body, &mcOpt)
|
||||||
|
|
||||||
mcOpt.PriceMonteCarlo()
|
mcOpt.PriceMonteCarlo()
|
||||||
|
bsOpt.PriceClosedForm()
|
||||||
|
|
||||||
options := make(map[string]Option)
|
options := make(map[string]Option)
|
||||||
options["MonteCarlo"] = mcOpt
|
options["MonteCarlo"] = mcOpt
|
||||||
|
|||||||
35
utils.go
Normal file
35
utils.go
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "math"
|
||||||
|
|
||||||
|
// NormCDF computes the Cumulative Density Function of a Standard Normal
|
||||||
|
// Distribution.
|
||||||
|
// Code adapted from https://www.johndcook.com/blog/cpp_phi/
|
||||||
|
func NormCDF(z float64) float64 {
|
||||||
|
// constants
|
||||||
|
var a1, a2, a3, a4, a5, p, t, y, sign float64
|
||||||
|
|
||||||
|
a1 = 0.254829592
|
||||||
|
a2 = -0.284496736
|
||||||
|
a3 = 1.421413741
|
||||||
|
a4 = -1.453152027
|
||||||
|
a5 = 1.061405429
|
||||||
|
p = 0.3275911
|
||||||
|
|
||||||
|
sign = 1
|
||||||
|
if z < 0 {
|
||||||
|
sign = -1
|
||||||
|
}
|
||||||
|
x := math.Abs(z) / math.Sqrt2
|
||||||
|
|
||||||
|
t = 1.0 / (1.0 + p*x)
|
||||||
|
y = 1.0 - (((((a5*t+a4)*t)+a3)*t+a2)*t+a1)*t*math.Exp(-x*x)
|
||||||
|
|
||||||
|
return 0.5 * (1.0 + sign*y)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NormPDF computes the Probability Density Function of a Standard Normal
|
||||||
|
// Distribution.
|
||||||
|
func NormPDF(z float64) float64 {
|
||||||
|
return 1 / math.Sqrt(2*math.Pi) * math.Exp(-math.Pow(z, 2)/2)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user