Server now returns the results of the Monte Carlo Price

This commit is contained in:
Kevin Keogh
2017-09-15 11:32:24 -04:00
parent c41a1cafe2
commit 5a169915e7
2 changed files with 42 additions and 92 deletions

View File

@@ -1,48 +1,33 @@
package main
import (
"fmt"
"math"
"math/rand"
"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 details
type Option struct {
OptType int64
Strike float64
ExpiryDate RFC8601Time
ExpiryDate time.Time
// Market data
ValueDate RFC8601Time
ValueDate time.Time
Spot float64
Rfr float64
Vol float64
Sims int64
// Results
FV float64
Delta float64
Vega float64
Rho float64
Gamma float64
Theta float64
FV float64
Delta float64
Vega float64
Rho float64
Gamma float64
Theta float64
Levels []float64
}
// 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)
}
// 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
// to calculate the future spot levels
func RunSimulations(opt *Option) {
func runSimulations(opt *Option) {
var i int64
var level float64
levels := make([]float64, opt.Sims)
opt.Levels = make([]float64, opt.Sims)
tte := opt.ExpiryDate.Sub(opt.ValueDate).Hours() / (24 * 365)
for i = 0; i < opt.Sims; i++ {
randNum := rand.NormFloat64()
// Base
levels[i] = gbmSimulation(opt.Spot, opt.Rfr, opt.Vol, tte, randNum)
opt.FV += math.Max((levels[i]-opt.Strike)*float64(opt.OptType), 0)
opt.Levels[i] = gbmSimulation(opt.Spot, opt.Rfr, opt.Vol, tte, randNum)
opt.FV += math.Max((opt.Levels[i]-opt.Strike)*float64(opt.OptType), 0)
// Delta
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)
}
/*
func main() {
value := time.Date(2016, 12, 30, 0, 0, 0, 0, time.UTC)
expiry := time.Date(2017, 12, 30, 0, 0, 0, 0, time.UTC)
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)
// PriceMonteCarlo is the exported method to run the simulations and value
// a vanilla option using Monte Carlo methods
func (opt *Option) PriceMonteCarlo() {
runSimulations(opt)
}
*/

View File

@@ -6,28 +6,37 @@ import (
"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) {
formatRequest(r)
fmt.Fprintf(w, "Hello go!\n")
}
if r.Method == "POST" {
func formatRequest(r *http.Request) {
mcOpt := &Option{}
bsOpt := &Option{}
var opt Option
err := json.NewDecoder(r.Body).Decode(&opt)
if err != nil {
fmt.Printf("Error: %s\n", err)
err := json.NewDecoder(r.Body).Decode(&mcOpt)
if err != nil {
fmt.Printf("Error: %s\n", err)
}
mcOpt.PriceMonteCarlo()
options := make(map[string]Option)
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
}
fmt.Println("Option type:", opt.OptType)
fmt.Println("Strike:", opt.Strike)
fmt.Println("Expiry date:", opt.ExpiryDate.Format("2006-01-02"))
for k, v := range r.Header {
fmt.Printf("%v: %v\n", k, v)
}
}
func main() {
http.HandleFunc("/", index)
http.ListenAndServe(":8080", nil)