Skip to content

Commit

Permalink
monte carlo: valuation of barrier options
Browse files Browse the repository at this point in the history
This adds support for the valuation of simple barrier options via monte
carlo.
  • Loading branch information
drsk0 committed Nov 5, 2023
1 parent 95188da commit 3f38d8a
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 4 deletions.
1 change: 1 addition & 0 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ version = "1.2.1"
BusinessDays = "4f18b42c-503e-5345-9536-bb0f25fc7038"
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210"
LanguageServer = "2b0e0bc5-e4fd-59b4-8912-456d1b03d8d7"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
Optim = "429524aa-4258-5aef-a3af-852621145aeb"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
Expand Down
3 changes: 3 additions & 0 deletions src/contracts.jl
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,9 @@ The maturity date of a contract `c` is the date at which contract is completed o
"""
maturitydate(c::WhenAt{C}) where {C} = c.p.a[2].val
maturitydate(c::AnytimeBefore{C}) where {C} = c.p.a[2].val
maturitydate(c::Anytime{LiftObs{F,Tuple{ValueObs{S, A},ConstObs{A}},Bool},C}) where {S,F,A,C} = maturitydate(c.c)
maturitydate(c::Anytime{LiftObs{F,Tuple{ConstObs{A}, ValueObs{S, A}},Bool},C}) where {S,F,A,C} = maturitydate(c.c)
maturitydate(c::Give{C}) where {C} = maturitydate(c.c)

"""
strikeprice(c::Contract)
Expand Down
2 changes: 0 additions & 2 deletions src/models/lsmc.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ end

function value(m::LeastSquaresMonteCarlo, c::AnytimeBefore{C}) where C
uc = c.c # underlying contract
uc1 = uc.c1
uc2 = uc.c2
N = date2index(m.m, maturitydate(c))
R = discount(m.m.core.yieldcurve, m.m.dates[2]) # TODO: could be better...

Expand Down
21 changes: 20 additions & 1 deletion src/models/montecarlo.jl
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,20 @@ function value(m::MonteCarloModel, c::WhenAt{SingleStock})
end
value(m::MonteCarloModel, c::SingleStock) = value(m.core, c)

# value of a barrier option
function value(m::MonteCarloModel, c::Anytime{LiftObs{F,Tuple{ValueObs{SingleStock, A},ConstObs{A}},Bool},C}) where {F,A,C}
N = date2index(m, maturitydate(c))
discount(m.core.yieldcurve, maturitydate(c)) * mean(valueat(ms, c.c, N) for ms in scenarios(m) if observe(ms, c.p, any))
end

function value(m::MonteCarloModel, c::Anytime{LiftObs{F,Tuple{ConstObs{A},ValueObs{SingleStock,A}},Bool},C}) where {F,A,C}
N = date2index(m, maturitydate(c))
discount(m.core.yieldcurve, maturitydate(c)) * mean(valueat(ms, c.c, N) for ms in scenarios(m) if observe(ms, c.p, any))
end

function value(m::MonteCarloModel, c::Cond{O, C1, C2}) where {O<:Observable{Bool}, C1<:Contract, C2<:Contract}
mean([observeat(ms, c.p, 1) ? valueat(ms, c.c1, 1) : valueat(ms, c.c2, 1) for ms in scenarios(m)])
N = date2index(m, maturitydate(c))
discount(m.core.yieldcurve, maturitydate(c)) * mean(valueat(ms, c, N) for ms in scenarios(m))
end


Expand Down Expand Up @@ -149,6 +161,13 @@ function valueat(m::MonteCarloScenario, c::WhenAt{Either{C1,C2}}, i::Int) where
forward_rate(m.core.yieldcurve, t, T) * maximum
end

function observe(ms::MonteCarloScenario, o::LiftObs{F,Tuple{ValueObs{SingleStock,A},ConstObs{A}},Bool}, predicateFold::Function)::Bool where {F,A}
predicateFold(p -> o.f(p, o.a[2].val), ms.path)
end
function observe(ms::MonteCarloScenario, o::LiftObs{F,Tuple{ConstObs{A}, ValueObs{SingleStock,A}},Bool}, predicateFold::Function)::Bool where {F,A}
predicateFold(p -> o.f(o.a[1].val, p), ms.path)
end

observeat(_::MonteCarloScenario, o::ConstObs{T}, _::Int) where T = o.val
function observeat(m::MonteCarloScenario, o::LiftObs{F, Tuple{DateObs, ConstObs{Date}}, Bool}, i::Int) where F
(_, t2) = o.a
Expand Down
21 changes: 20 additions & 1 deletion test/montecarlo.jl
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using Miletus, Dates
using Test

import Miletus: WhenAt
import Miletus: WhenAt, ConstObs, ValueObs, LiftObs
using Miletus.Currency
using Miletus.Currency: @defcurrency

d1 = today()
d2 = d1 + Day(120)
Expand Down Expand Up @@ -32,3 +34,20 @@ c = WhenAt(d2, SingleStock())

o = EuropeanCall(d2, SingleStock(), 100.00USD) # std(y)/mean(y) = 0.013
@test isapprox(value(m, o), value(mcm, o), rtol=0.013*4)

# barrier options
@defcurrency CHF

initialFixing = Date("2020-12-15")
maturity = Date("2023-12-15")
faceValue = 1000CHF

smi = SingleStock()

euput = EuropeanPut(maturity, smi, 100.00CHF)
bond = ZCB(maturity, faceValue)
knockedIn = LiftObs(<, ConstObs(1.0CHF), ValueObs{SingleStock, CurrencyQuantity{CurrencyUnit{:CHF}, Float64}}(smi))
brc = Both(bond, Anytime(knockedIn, Give(euput)))
m = GeomBMModel(initialFixing, faceValue, 0.05, 0.0, 0.3)
mcm = montecarlo(m, initialFixing:Day(1):maturity, 10_000)
@test isapprox(value(mcm, brc), 860.70CHF, rtol=1e-2)

0 comments on commit 3f38d8a

Please sign in to comment.