Server now returns the results of the Monte Carlo Price
This commit is contained in:
83
models.go
83
models.go
@@ -1,36 +1,20 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"math"
|
"math"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// RFC8601Time is a time.Time wrapper
|
|
||||||
type RFC8601Time struct {
|
|
||||||
time.Time
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t RFC8601Time) Sub(u RFC8601Time) time.Duration {
|
|
||||||
return t.Sub(u)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t RFC8601Time) MarshalJSON() ([]byte, error) {
|
|
||||||
fmt.Println("Here!")
|
|
||||||
stamp := fmt.Sprintf("\"%s\"", t.Format("2006-01-02"))
|
|
||||||
return []byte(stamp), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Option struct that holds all the details of an option
|
// Option struct that holds all the details of an option
|
||||||
// Option details
|
// Option details
|
||||||
type Option struct {
|
type Option struct {
|
||||||
OptType int64
|
OptType int64
|
||||||
Strike float64
|
Strike float64
|
||||||
ExpiryDate RFC8601Time
|
ExpiryDate time.Time
|
||||||
|
|
||||||
// Market data
|
// Market data
|
||||||
ValueDate RFC8601Time
|
ValueDate time.Time
|
||||||
Spot float64
|
Spot float64
|
||||||
Rfr float64
|
Rfr float64
|
||||||
Vol float64
|
Vol float64
|
||||||
@@ -43,6 +27,7 @@ type Option struct {
|
|||||||
Rho float64
|
Rho float64
|
||||||
Gamma float64
|
Gamma float64
|
||||||
Theta float64
|
Theta float64
|
||||||
|
Levels []float64
|
||||||
}
|
}
|
||||||
|
|
||||||
// Single simulation of Geometric Brownian Motion
|
// Single simulation of Geometric Brownian Motion
|
||||||
@@ -54,23 +39,23 @@ func gbmSimulation(spot float64, rfr float64, vol float64, tte float64, randNum
|
|||||||
return spot * math.Exp(drift+stoch)
|
return spot * math.Exp(drift+stoch)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RunSimulations is the main function that runs Monte Carlo simulations
|
// runSimulations is the main function that runs Monte Carlo simulations
|
||||||
// for an option. Note that it runs normal Geometric Brownian Motion
|
// for an option. Note that it runs normal Geometric Brownian Motion
|
||||||
// to calculate the future spot levels
|
// to calculate the future spot levels
|
||||||
func RunSimulations(opt *Option) {
|
func runSimulations(opt *Option) {
|
||||||
|
|
||||||
var i int64
|
var i int64
|
||||||
var level float64
|
var level float64
|
||||||
|
|
||||||
levels := make([]float64, opt.Sims)
|
opt.Levels = make([]float64, opt.Sims)
|
||||||
|
|
||||||
tte := opt.ExpiryDate.Sub(opt.ValueDate).Hours() / (24 * 365)
|
tte := opt.ExpiryDate.Sub(opt.ValueDate).Hours() / (24 * 365)
|
||||||
|
|
||||||
for i = 0; i < opt.Sims; i++ {
|
for i = 0; i < opt.Sims; i++ {
|
||||||
randNum := rand.NormFloat64()
|
randNum := rand.NormFloat64()
|
||||||
// Base
|
// Base
|
||||||
levels[i] = gbmSimulation(opt.Spot, opt.Rfr, opt.Vol, tte, randNum)
|
opt.Levels[i] = gbmSimulation(opt.Spot, opt.Rfr, opt.Vol, tte, randNum)
|
||||||
opt.FV += math.Max((levels[i]-opt.Strike)*float64(opt.OptType), 0)
|
opt.FV += math.Max((opt.Levels[i]-opt.Strike)*float64(opt.OptType), 0)
|
||||||
|
|
||||||
// Delta
|
// Delta
|
||||||
level = gbmSimulation(opt.Spot+0.0001, opt.Rfr, opt.Vol, tte, randNum)
|
level = gbmSimulation(opt.Spot+0.0001, opt.Rfr, opt.Vol, tte, randNum)
|
||||||
@@ -104,52 +89,8 @@ func RunSimulations(opt *Option) {
|
|||||||
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// PriceMonteCarlo is the exported method to run the simulations and value
|
||||||
func main() {
|
// a vanilla option using Monte Carlo methods
|
||||||
value := time.Date(2016, 12, 30, 0, 0, 0, 0, time.UTC)
|
func (opt *Option) PriceMonteCarlo() {
|
||||||
expiry := time.Date(2017, 12, 30, 0, 0, 0, 0, time.UTC)
|
runSimulations(opt)
|
||||||
opt := Option{optType: 1, strike: 100, expiryDate: expiry, valueDate: value, spot: 100, rfr: 0.03, vol: 0.25, sims: 1000000}
|
|
||||||
rand.Seed(time.Now().UTC().UnixNano())
|
|
||||||
RunSimulations(&opt)
|
|
||||||
|
|
||||||
fmt.Printf(
|
|
||||||
`
|
|
||||||
Valuation date: %s
|
|
||||||
|
|
||||||
|
|
||||||
| BS Analytic | BS Monte Carlo |
|
|
||||||
---------------------------------------------
|
|
||||||
|Type: | %10s | %13s |
|
|
||||||
|Spot: | %10.2f | %13.2f |
|
|
||||||
|Expiry: | %s | %s |
|
|
||||||
|Strike: | %10.2f | %13.2f |
|
|
||||||
|Risk-free: | %10.2f%% | %13.2f%% |
|
|
||||||
|Implied Vol:| %10.2f%% | %13.2f%% |
|
|
||||||
---------------------------------------------
|
|
||||||
|Fair value: | %8.4f | %11.4f |
|
|
||||||
|Delta: | %8.4f | %11.4f |
|
|
||||||
|Gamma: | %8.4f | %11.4f |
|
|
||||||
|Vega: | %8.4f | %11.4f |
|
|
||||||
|Theta: | %8.4f | %11.4f |
|
|
||||||
|Rho: | %8.4f | %11.4f |
|
|
||||||
|Simulations:| | %11d |
|
|
||||||
---------------------------------------------
|
|
||||||
|
|
||||||
`,
|
|
||||||
value.Format("2006-01-02"),
|
|
||||||
"Call", "Call",
|
|
||||||
opt.Spot, opt.Spot,
|
|
||||||
expiry.Format("2006-01-02"), expiry.Format("2006-01-02"),
|
|
||||||
opt.Strike, opt.Strike,
|
|
||||||
opt.Rfr*100, opt.Rfr*100,
|
|
||||||
opt.Vol*100, opt.Vol*100,
|
|
||||||
opt.FV, opt.FV,
|
|
||||||
opt.Delta, opt.Delta,
|
|
||||||
opt.Gamma, opt.Gamma,
|
|
||||||
opt.Vega, opt.Vega,
|
|
||||||
opt.Theta, opt.Theta,
|
|
||||||
opt.Rho, opt.Rho,
|
|
||||||
opt.Sims)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|||||||
31
serve.go
31
serve.go
@@ -6,28 +6,37 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// index is a function that handles all requests to the main page
|
||||||
|
// Note that there are two separate returns
|
||||||
func index(w http.ResponseWriter, r *http.Request) {
|
func index(w http.ResponseWriter, r *http.Request) {
|
||||||
formatRequest(r)
|
if r.Method == "POST" {
|
||||||
fmt.Fprintf(w, "Hello go!\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
func formatRequest(r *http.Request) {
|
mcOpt := &Option{}
|
||||||
|
bsOpt := &Option{}
|
||||||
|
|
||||||
var opt Option
|
err := json.NewDecoder(r.Body).Decode(&mcOpt)
|
||||||
err := json.NewDecoder(r.Body).Decode(&opt)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("Error: %s\n", err)
|
fmt.Printf("Error: %s\n", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("Option type:", opt.OptType)
|
mcOpt.PriceMonteCarlo()
|
||||||
fmt.Println("Strike:", opt.Strike)
|
|
||||||
fmt.Println("Expiry date:", opt.ExpiryDate.Format("2006-01-02"))
|
|
||||||
|
|
||||||
for k, v := range r.Header {
|
options := make(map[string]Option)
|
||||||
fmt.Printf("%v: %v\n", k, v)
|
options["MonteCarlo"] = *mcOpt
|
||||||
|
options["BlackScholes"] = *bsOpt
|
||||||
|
|
||||||
|
json.NewEncoder(w).Encode(options)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Error: %v\n", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} else if r.Method == "GET" {
|
||||||
|
fmt.Fprintf(w, "Hello go!") // To be updated
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
http.HandleFunc("/", index)
|
http.HandleFunc("/", index)
|
||||||
http.ListenAndServe(":8080", nil)
|
http.ListenAndServe(":8080", nil)
|
||||||
|
|||||||
Reference in New Issue
Block a user