Benutzer:MovGP0/F♯/Option Pricing

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

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
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

[Bearbeiten | Quelltext bearbeiten]
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

[Bearbeiten | Quelltext bearbeiten]
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