Benutzer:MovGP0/F♯/Option Pricing

aus Wikipedia, der freien Enzyklopädie
   MovGP0        Über mich        Hilfen        Artikel        Weblinks        Literatur        Zitate        Notizen        Programmierung        MSCert        Physik      

Option Pricing

Modelling a Wiener Process

module Program

open System
open System.Drawing
open System.Net
open System.Windows.Forms
open System.Windows.Forms.DataVisualization.Charting
open MathNet.Numerics.Distributions
open Microsoft.FSharp.Control.WebExtensions

let normalDistribution = new Normal(0.0, 1.0)

// create series for stock price
let getWienerProcessChartSeries () = 
    let wienerProcess = new Series("process")
    wienerProcess.ChartType <- SeriesChartType.Line
    wienerProcess.BorderWidth <- 2
    wienerProcess.Color <- Color.Red
    wienerProcess
    
// define an infinite Wiener Series
let WienerSeries scalingFactor = 
    let T = 1.0
    let n = 500.0
    let Δt = T / n

    let rec loop x = 
        seq {
            yield x
            yield! loop (x + sqrt(Δt) * normalDistribution.Sample() * scalingFactor)
        }
    loop scalingFactor

[<STAThread>]
do
    let wienerProcess = getWienerProcessChartSeries()

    // create chart and form
    let chart = new Chart(Dock = DockStyle.Fill)
    let chartArea = new ChartArea("Main")
    chart.ChartAreas.Add chartArea
    chart.Series.Add wienerProcess

    let mainForm = new Form(Visible = true, TopMost = true, Width = 700, Height = 500)
    mainForm.Text <- "Wiener process in F#"
    mainForm.Controls.Add chart
    
    WienerSeries 55.00
    |> Seq.take 100
    |> Seq.iter (wienerProcess.Points.Add >> ignore)

    Application.Run mainForm

Black Scholes

Formula
module BlackScholes

let private pow x n = exp(n * log(x))

type PutCallFlag = Put | Call

/// <summary>
/// Cumulative Distribution function
/// </summary>
/// <param name="x"></param>
let private cnd x = 
    let a1 = +0.31938153
    let a2 = -0.356563782
    let a3 = +1.781477937
    let a4 = -1.821255978
    let a5 = +1.330274429
    let pi = +3.141592654
    let l = abs x
    let k = 1.0 / (1.0 + 0.2316419 * l)
    let w = (1.0 - 1.0 / sqrt(2.0 * pi) * exp(-l * l / 2.0) * (a1 * (pow k 1.0) + a2 * (pow k 2.0) + a3 * (pow k 3.0) + a4 * (pow k 4.0) + a5 * (pow k 5.0)))
    
    if x < 0.0 
    then 
        1.0 - w 
    else 
        w

let BlackScholes callPutFlag stockPrice strikePriceOfOption timeToExpirationInYears riskFreeInterestRate volatility = 
    let d1 = (log(stockPrice / strikePriceOfOption) + (riskFreeInterestRate + volatility * volatility * 0.5) * timeToExpirationInYears) / (volatility * sqrt(timeToExpirationInYears))
    let d2 = d1 - volatility * sqrt(timeToExpirationInYears)

    match callPutFlag with
    | Put -> strikePriceOfOption * exp(-riskFreeInterestRate * timeToExpirationInYears) * cnd(-d2) - stockPrice * cnd(-d1)
    | Call -> stockPrice * cnd(d1) - strikePriceOfOption * exp(-riskFreeInterestRate * timeToExpirationInYears) * cnd(d2)
Visualization
open System
open System.Drawing
open System.Net
open System.Windows.Forms
open System.Windows.Forms.DataVisualization.Charting
open Microsoft.FSharp.Control.WebExtensions
open BlackScholes

let getOptionPriceCall () =
    let optionPriceCall = new Series "Call option price"
    optionPriceCall.ChartType <- SeriesChartType.Line
    optionPriceCall.BorderWidth <- 2
    optionPriceCall.Color <- Color.Red
    optionPriceCall

let getOptionPricePut () = 
    let optionPricePut = new Series "Put option price"
    optionPricePut.ChartType <- SeriesChartType.Line
    optionPricePut.BorderWidth <- 2
    optionPricePut.Color <- Color.Blue
    optionPricePut

[<STAThread>]
do
    let optionPricePut = getOptionPricePut()
    let optionPriceCall = getOptionPriceCall()

    let chart = new Chart(Dock = DockStyle.Fill)
    let chartArea = new ChartArea("Main")
    chart.ChartAreas.Add chartArea
    chart.Legends.Add(new Legend())
    chart.Series.Add optionPriceCall
    chart.Series.Add optionPricePut

    let mainForm = new Form(Visible = true, TopMost = true, Width = 700, Height = 500)
    mainForm.Text <- "Option price as a function of time"
    mainForm.Controls.Add chart

    let daysToYears days = (float days) / 365.25

    let timeSpan = [(daysToYears 20)..(-(daysToYears 1)) .. 0.0]
    let opc = [for x in timeSpan do yield BlackScholes Call 58.60 60.0 x 0.01 0.3]
    opc |> Seq.iter (optionPriceCall.Points.Add >> ignore)

    let opp = [for x in timeSpan do yield BlackScholes Put 58.60 60.0 x 0.01 0.3]
    opp |> Seq.iter (optionPricePut.Points.Add >> ignore)

    Application.Run mainForm

Black Scholes Greeks

Implementation
module BlackScholesGreeks

open BlackScholes
open MathNet.Numerics.Distributions

let private normd = new Normal(0.0, 1.0)

let private d s x t r v = (log(s / x) + (r + v * v * 0.5) * t)/(v * sqrt(t))

/// <summary>
/// Black-Scholes Delta
/// </summary>
/// <param name="callPutFlag">Put | Call</param>
/// <param name="s">stock price</param>
/// <param name="x">strike price of option</param>
/// <param name="t">time to expiration in years</param>
/// <param name="r">risk free interest rate</param>
/// <param name="v">volatility</param>
let blackScholesDelta callPutFlag s x t r v = 
    let d1 = d s x t r v
    match callPutFlag with
    | Put -> cnd(d1) - 1.0
    | Call -> cnd(d1)

/// <summary>
/// Black-Scholes Gamma
/// </summary>
/// <param name="s">stock price</param>
/// <param name="x">strike price of option</param>
/// <param name="t">time to expiration in years</param>
/// <param name="r">risk free interest rate</param>
/// <param name="v">volatility</param>
let blackScholesGamma s x t r v = 
    let d1 = d s x t r v
    normd.Density(d1) / (s * v * sqrt(t))

/// <summary>
/// Black-Scholes Vega
/// </summary>
/// <param name="s">stock price</param>
/// <param name="x">strike price of option</param>
/// <param name="t">time to expiration in years</param>
/// <param name="r">risk free interest rate</param>
/// <param name="v">volatility</param>
let blackScholesVega s x t r v = 
    let d1 = d s x t r v
    s * normd.Density(d1) * sqrt(t)

/// <summary>
/// Black-Scholes Theta
/// </summary>
/// <param name="callPutFlag">Put | Call</param>
/// <param name="s">stock price</param>
/// <param name="x">strike price of option</param>
/// <param name="t">time to expiration in years</param>
/// <param name="r">risk free interest rate</param>
/// <param name="v">volatility</param>
let blackScholesTheta callPutFlag s x t r v = 
    let d1 = d s x t r v
    let d2 = d1 - v * sqrt(t)
    let res = ref 0.0
    match callPutFlag with
    | Put -> -(s * normd.Density(d1) * v) / (2.0 * sqrt(t)) + r * x * exp(r * t) * cnd(-d2)
    | Call -> -(s * normd.Density(d1) * v) / (2.0 * sqrt(t)) - r * x * exp(-r * t) * cnd(d2)

/// <summary>
/// Black-Scholes Rho
/// </summary>
/// <param name="callPutFlag">Put | Call</param>
/// <param name="s">stock price</param>
/// <param name="x">strike price of option</param>
/// <param name="t">time to expiration in years</param>
/// <param name="r">risk free interest rate</param>
/// <param name="v">volatility</param>
let blackSholesRho callPutFlag s x t r v = 
    let d1 = d s x t r v
    let d2 = d1 - v * sqrt(t) 
    let res = ref 0.0
    match callPutFlag with 
    | Put -> -x * t * -exp(-r * t) * cnd(-d2)
    | Call -> x * t * exp(-r * t) * cnd(d2)
Visualization
open System
open System.Drawing
open System.Net
open System.Windows.Forms
open System.Windows.Forms.DataVisualization.Charting
open Microsoft.FSharp.Control.WebExtensions
open BlackScholes
open BlackScholesGreeks

let range = [10.0..1.0..70.0]

let getOptionCallDelta () = 
    let series = new Series("Call option delta")
    series.ChartType <- SeriesChartType.Line
    series.BorderWidth <- 2
    series.Color <- Color.Red

    [for x in range do yield blackScholesDelta Call x 60.0 0.5 0.01 0.3]
    |> Seq.iter (series.Points.Add >> ignore)

    series

let getOptionCallGamma () = 
    let series = new Series("Call option gamma")
    series.ChartType <- SeriesChartType.Line
    series.BorderWidth <- 2
    series.Color <- Color.DarkBlue

    [for x in range do yield blackScholesGamma x 60.0 0.5 0.01 0.3]
    |> Seq.iter (series.Points.Add >> ignore)

    series

let getOptionCallTheta () = 
    let series = new Series("Call option theta")
    series.ChartType <- SeriesChartType.Line
    series.BorderWidth <- 2
    series.Color <- Color.DarkGreen

    [for x in range do yield blackScholesTheta Call x 60.0 0.5 0.01 0.3]
    |> Seq.iter (series.Points.Add >> ignore)

    series

let getOptionCallVega () = 
    let series = new Series("Call option vega")
    series.ChartType <- SeriesChartType.Line
    series.BorderWidth <- 2
    series.Color <- Color.DarkViolet

    [for x in range do yield blackScholesVega x 60.0 0.5 0.01 0.3]
    |> Seq.iter (series.Points.Add >> ignore)

    series

[<STAThread>]
do
    let chartArea = new ChartArea("Main")

    let chart = new Chart(Dock = DockStyle.Fill)
    chart.ChartAreas.Add chartArea
    chart.Legends.Add(new Legend())

    chart.Series.Add(getOptionCallDelta())
    chart.Series.Add(getOptionCallGamma())
    chart.Series.Add(getOptionCallTheta())
    chart.Series.Add(getOptionCallVega())

    let mainForm = new Form(Visible = true, TopMost = true, Width = 700, Height = 500)
    mainForm.Text <- "Option delta as a function of underlying price"
    mainForm.Controls.Add chart
    
    Application.Run mainForm

Monte Carlo Method

module MonteCarlo

open System
open Microsoft.FSharp.Data.UnitSystems

[<Measure>] type Day
[<Measure>] type Year
[<Measure>] type Price

/// <summary>
/// Convert days to years
/// </summary>
/// <param name="days"></param>
let daysToYears (days:float<Day>) : float<Year> = days / 365.25<Day/Year>

/// <summary>
/// Asset price at maturity for sample rnd
/// </summary>
/// <param name="s">stock price</param>
/// <param name="t">time to expiration in years</param>
/// <param name="r">risk free interest rate</param>
/// <param name="v">volatility</param>
/// <param name="rnd">sample</param>
let priceForSample (s:float<Price>) (t:float<Year>) (r:float) (v:float) (rnd:float) : float<Price> = 
    s * exp((r - v * v / 2.0) * (t * 1.0<1/Year>) + v * rnd * sqrt(t * 1.0<1/Year>))

/// <summary>
/// For each sample we run the monte carlo simulation
/// </summary>
/// <param name="s">stock price</param>
/// <param name="x">strike price of option</param>
/// <param name="t">time to expiration in years</param>
/// <param name="r">risk free interest rate</param>
/// <param name="v">volatility</param>
/// <param name="samples">random samples as input to simulation</param>
let monteCarlo (s:float<Price>) x (t:float<Year>) (r:float) (v:float) (samples:seq<float>) : float<Price> = 
    samples
    |> Seq.map (fun rnd -> (priceForSample s t r v rnd) - x)
    |> Seq.average


let random = new Random()
let rnd = random.NextDouble
let data = [for _ in 1..1000 -> rnd()]

let calculatedCallOptionPrices = monteCarlo 58.60<Price> 60.0<Price> 0.5<Year> 0.01 0.3 data