Skip to content

Commit

Permalink
fixup Equity & Option Module & tests, add EuroPut (#172)
Browse files Browse the repository at this point in the history
  • Loading branch information
alecloudenback authored Dec 28, 2023
1 parent 078e19e commit 50ebc33
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 18 deletions.
21 changes: 20 additions & 1 deletion src/Contract.jl
Original file line number Diff line number Diff line change
Expand Up @@ -358,11 +358,30 @@ A European call option on the given contract with the given strike and maturity.
EuroCall{S,K,M} <: FinanceCore.AbstractContract <: Any
"""
struct EuroCall{S<:AbstractContract,K<:Real,M<:Timepoint} <: AbstractContract
underlying::S
strike::K
maturity::M
end

"""
EuroPut(contract,strike,maturity)
A European put option on the given contract with the given strike and maturity.
# Arguments
- contract::AbstractContract - The underlying contract.
- strike::Real - The strike price.
- maturity::Union{Real,Date} - The maturity of the option.
Supertype Hierarchy
≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡
EuroPut{S,K,M} <: FinanceCore.AbstractContract <: Any
"""
struct EuroCall{S<:AbstractContract,K<:Real,M<:Timepoint} <: AbstractContract
struct EuroPut{S<:AbstractContract,K<:Real,M<:Timepoint} <: AbstractContract
underlying::S
strike::K
maturity::M
Expand Down
27 changes: 22 additions & 5 deletions src/model/Equity.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,13 @@ The `Equity` module provides equity-related model definitions.
See also: the [`Volatility`](@ref FinanceModels.Volatility-API-Reference) module.
"""
module Equity

import ..AbstractModel
import ..Volatility
import ..Option
import ..CommonEquity
import ..eurocall, ..europut
using ..FinanceCore

abstract type AbstractEquityModel <: AbstractModel end

Expand All @@ -14,8 +20,8 @@ abstract type AbstractEquityModel <: AbstractModel end
A struct representing the Black-Scholes-Merton model for equity prices.
# Arguments
- `r`: The risk-free rate.
- `q`: The dividend yield.
- `r`: The risk-free rate (continuously compounded scalar or a `FinanceCore.Rate` type).
- `q`: The dividend yield (continuously compounded scalar or a `FinanceCore.Rate` type).
- `σ`: The volatility model of the underlying asset (see [`Volatility`](@ref FinanceModels.Volatility-API-Reference) module)
# Fields
Expand Down Expand Up @@ -57,20 +63,31 @@ struct BlackScholesMerton{T,U,V} <: AbstractEquityModel
r::T # risk free rate
q::U # dividend yield
σ::V # roughly equivalent to the volatility in the usual lognormal model multiplied by F^{1-β}_{0}
end
# an inner constructor:

function BlackScholesMerton(r, q, σ::V) where {V}
rc = rate(Continuous(r))
qc = rate(Continuous(q))
new{typeof(rc),typeof(qc),V}(rc, qc, σ)
end

end

"""
volatility(volatiltiy_model,strike_ratio,time_to_maturity)
volatility(volatility_model,strike_ratio,time_to_maturity)
Returns the volatility associated with the moneyness (strike/price ratio) and time to maturity.
Returns the volatility associated with the money-ness (strike/price ratio) and time to maturity.
"""
function volatility(vol::Volatility.Constant, strike_ratio, time_to_maturity)
return vol.σ
end

function FinanceCore.present_value(model::M, c::Option.EuroCall{CommonEquity,K,T}) where {M<:Equity.BlackScholesMerton,K,T}
eurocall(; S=1.0, K=c.strike, τ=c.maturity, r=model.r, q=model.q, σ=model.σ)
end

function FinanceCore.present_value(model::M, c::Option.EuroPut{CommonEquity,K,T}) where {M<:Equity.BlackScholesMerton,K,T}
europut(; S=1.0, K=c.strike, τ=c.maturity, r=model.r, q=model.q, σ=model.σ)
end

end
41 changes: 29 additions & 12 deletions test/Equity.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,28 @@
# tested against https://option-price.com/index.php
params = (S=1.0, K=1.0, τ=1, r=0.05, σ=0.25, q=0.0)

@test eurocall(; params...) 0.12336 atol = 1e-5
@test europut(; params...) 0.07459 atol = 1e-5
@test FinanceModels.eurocall(; params...) 0.12336 atol = 1e-5
@test FinanceModels.europut(; params...) 0.07459 atol = 1e-5

params = (S=1.0, K=1.0, τ=1, r=0.05, σ=0.25, q=0.03)
@test eurocall(; params...) 0.105493 atol = 1e-5
@test europut(; params...) 0.086277 atol = 1e-5
@test FinanceModels.eurocall(; params...) 0.105493 atol = 1e-5
@test FinanceModels.europut(; params...) 0.086277 atol = 1e-5

params = (S=1.0, K=0.5, τ=1, r=0.05, σ=0.25, q=0.03)
@test eurocall(; params...) 0.49494 atol = 1e-5
@test europut(; params...) 0.00011 atol = 1e-5
@test FinanceModels.eurocall(; params...) 0.49494 atol = 1e-5
@test FinanceModels.europut(; params...) 0.00011 atol = 1e-5

params = (S=1.0, K=0.5, τ=1, r=0.05, σ=0.25, q=0.03)
@test eurocall(; params...) 0.49494 atol = 1e-5
@test europut(; params...) 0.00011 atol = 1e-5
@test FinanceModels.eurocall(; params...) 0.49494 atol = 1e-5
@test FinanceModels.europut(; params...) 0.00011 atol = 1e-5

params = (S=1.0, K=0.5, τ=0, r=0.05, σ=0.25, q=0.03)
@test eurocall(; params...) 0.5 atol = 1e-5
@test europut(; params...) 0.0 atol = 1e-5
@test FinanceModels.eurocall(; params...) 0.5 atol = 1e-5
@test FinanceModels.europut(; params...) 0.0 atol = 1e-5

params = (S=1.0, K=1.5, τ=0, r=0.05, σ=0.25, q=0.03)
@test eurocall(; params...) 0.0 atol = 1e-5
@test europut(; params...) 0.5 atol = 1e-5
@test FinanceModels.eurocall(; params...) 0.0 atol = 1e-5
@test FinanceModels.europut(; params...) 0.5 atol = 1e-5

end
end
Expand All @@ -40,11 +40,28 @@ end

@test pv(m, a) 0.05410094201902403

ap = Option.EuroPut(CommonEquity(), 1.0, 1.0)

# put call parity with continuous dividend yield
# https://web.ma.utexas.edu/users/mcudina/m339d_lecture6.pdf, pg 2
@test pv(m, a) - pv(m, ap) 1.0 * exp(-0.02) - exp(-0.01) * 1.0


# test fitting volatility
qs = [
Quote(0.0541, a),
Quote(0.072636, b),
]
m = Equity.BlackScholesMerton(0.01, 0.02, Volatility.Constant())
fit(m, qs)
@test fit(m, qs).σ 0.15 atol = 1e-4

# test constructor with Rates
@test Equity.BlackScholesMerton(Continuous(0.01), Continuous(0.02), 0.15) isa Equity.BlackScholesMerton
m = Equity.BlackScholesMerton(Periodic(0.01, 1), Periodic(0.02, 1), 0.15)
# periodic rates should convert to Continuous equivalent that's higher than the Continuous rate
@test m.r < 0.01
@test m.q < 0.02


end
1 change: 1 addition & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ using Transducers
include("generic.jl")
include("sp.jl")

include("Equity.jl")
include("Yield.jl")
include("CompositeYield.jl")
include("SmithWilson.jl")
Expand Down

0 comments on commit 50ebc33

Please sign in to comment.