diff --git a/Project.toml b/Project.toml index 5745dd6c..775ab1a1 100644 --- a/Project.toml +++ b/Project.toml @@ -16,12 +16,14 @@ DiffEqBayes = "ebbdde9d-f333-5424-9be2-dbf1e9acfb5e" DiffEqBiological = "eb300fae-53e8-50a0-950c-e21f52c2b7e0" DiffEqCallbacks = "459566f4-90b8-5000-8ac3-15dfb0a30def" DiffEqDevTools = "f3b72e0c-5b89-59e1-b016-84e28bfd966d" +DiffEqNoiseProcess = "77a26b50-5914-5dd7-bc55-306e6241c503" DiffEqOperators = "9fdde737-9c7f-55bf-ade8-46b3f136cc48" DiffEqParamEstim = "1130ab10-4a5a-5621-a13d-e4788d82bd4c" DiffEqPhysics = "055956cb-9e8b-5191-98cc-73ae4a59e68a" DifferentialEquations = "0c46a032-eb83-5123-abaf-570d42b7fbaa" Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f" DoubleFloats = "497a8b3b-efae-58df-a0af-a86822472b78" +Flux = "587475ba-b771-5e3f-ad9e-33799f191a9c" ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210" IJulia = "7073ff75-c697-5162-941a-fcdaad2a7d2a" InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240" @@ -31,6 +33,7 @@ MCMCChains = "c7f686f2-ff18-58e9-bc7b-31028e88f75d" Measurements = "eff96d63-e80a-5855-80a2-b1b0885c5ab7" ModelingToolkit = "961ee093-0014-501f-94e3-6117800e7a78" NLsolve = "2774e3e8-f4cf-5e23-947b-6d7e65073b56" +NeuralNetDiffEq = "8faf48c0-8b73-11e9-0e63-2155955bfa4d" Optim = "429524aa-4258-5aef-a3af-852621145aeb" OrdinaryDiffEq = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed" ParameterizedFunctions = "65888b18-ceab-5e60-b2b9-181511a3b968" @@ -42,6 +45,7 @@ SparseDiffTools = "47a9eef4-7e08-11e9-0b38-333d64bd3804" SparsityDetection = "684fba80-ace3-11e9-3d08-3bc7ed6f96df" StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" StatsPlots = "f3b207a7-027a-5e70-b257-86293d7955fd" +StochasticDiffEq = "789caeaf-c7a9-5a7d-9973-96adeb23e2a0" Sundials = "c3572dad-4567-51f8-b174-8c6c989267f4" Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d" Weave = "44d3d7a6-8a23-5bf8-98c5-b353f8df5ec9" diff --git a/html/introduction/06-kolmogorov_equations.html b/html/introduction/06-kolmogorov_equations.html new file mode 100644 index 00000000..9b7dc958 --- /dev/null +++ b/html/introduction/06-kolmogorov_equations.html @@ -0,0 +1,913 @@ + + + + + + Kolmogorov Equations + + + + + + + + + + + + + + + +
+
+
+
+

Kolmogorov Equations

+
Ashutosh Bharambe
+ +
+ + +
+using Flux, StochasticDiffEq
+using  NeuralNetDiffEq
+using Plots
+using LinearAlgebra
+
+ + + +

Introduction on Kolmogorov Equations

+

The one dimensional backward kolmogorov equation that we are going to deal with is of the form :

+

\[ +\begin{equation} + \frac{\partial p}{\partial t} = \mu(x)\frac{\partial p}{\partial x} + \frac{1}{2}{\sigma^2}(x)\frac{\partial^2 p}{\partial x^2} +\end{equation} +\]

+

Consider a Black Scholes Partial Differential Equation of the form :

+

\[ +\begin{equation} + \frac{\partial V}{\partial t} + rS\frac{\partial V}{\partial S} + \frac{1}{2}{\sigma^2}{S^2}\frac{\partial^2 V}{\partial S^2} -rV = 0 +\end{equation} +\]

+

In order to make the above equation in the form of the Backward - Kolmogorov PDE we should substitute

+

\[ +\begin{equation} + V(S , t) = e^{rt}p(S , t) +\end{equation} +\begin{equation} + p(S , T) = max\{ x - \mathcal{K} , 0 \} +\end{equation} +\]

+

We should start defining the terminal condition for our equation:

+ + +
+function phi(xi)
+    y = Float64[]
+    K = 100
+    for x in eachcol(xi)
+        val = max(K - maximum(x) , 0.00)
+        y = push!(y , val)
+    end
+    y = reshape(y , 1 , size(y)[1] )
+    return y
+end
+
+ + +
+phi (generic function with 1 method)
+
+ + +

Now we shall define the problem : We will start with a simple one dimensional Black-Scholes PDE and then move to the higher dimensions We will define the σ and μ by comparing it to the orignal equation.

+ + +
+d = 1
+r = 0.06
+sigma = 0.4
+xspan = (95.00 , 110.0)
+tspan = (0.0 , 1.0)
+σ(du , u , p , t) = du .= sigma.*u
+μ(du , u , p , t) = du .= r.*u
+
+ + +
+μ (generic function with 1 method)
+
+ + +

Now once we have defined our problem it is necessary to define the parameters for the solver.

+ + +
+sdealg = EM()
+ensemblealg = EnsembleThreads()
+dt = 0.01
+dx = 0.01
+trajectories = 100000
+
+ + +
+100000
+
+ + +

Now lets define our model m and the optimiser

+ + +
+m = Chain(Dense(d, 32, leakyrelu),Dense(32, 128, leakyrelu),Dense(128 , 32 , leakyrelu) , Dense(32 , 1))
+m = fmap(cu , m)
+
+ + +
+ERROR: UndefVarError: cu not defined
+
+ + + +
+prob = KolmogorovPDEProblem(μ , σ , phi , xspan , tspan, d)
+opt = Flux.ADAM(0.01)
+
+ + +
+ADAM(0.01, (0.9, 0.999), IdDict{Any,Any}())
+
+ + +

And then finally call the solver

+ + +
+sol = solve(prob, NeuralNetDiffEq.NNKolmogorov(m, opt, sdealg, ensemblealg), verbose = true, dt = dt,
+            dx = dx , trajectories = trajectories , abstol=1e-6, maxiters = 3000)
+
+ + +
+Current loss is: 561.711498088225
+Current loss is: 386.22229456357377
+Current loss is: 296.80721579035924
+Current loss is: 324.38432342387557
+Current loss is: 349.2953855668709
+Current loss is: 335.98255012439193
+Current loss is: 311.27680726367424
+Current loss is: 295.37787544376033
+Current loss is: 302.71222054144835
+Current loss is: 312.29963874523617
+Current loss is: 310.0594473214611
+Current loss is: 302.37353839562803
+Current loss is: 296.45023439229044
+Current loss is: 295.15561561986084
+Current loss is: 297.2961876000978
+Current loss is: 299.91116127358544
+Current loss is: 300.614684811973
+Current loss is: 299.1410869807606
+Current loss is: 296.78057049421614
+Current loss is: 295.25791255616923
+Current loss is: 295.19178606538486
+Current loss is: 296.2725870709754
+Current loss is: 297.12846342631974
+Current loss is: 297.0123166653831
+Current loss is: 296.17366586047854
+Current loss is: 295.32546177836065
+Current loss is: 295.0267334278429
+Current loss is: 295.346872950253
+Current loss is: 295.73072278145463
+Current loss is: 295.7533136410972
+Current loss is: 295.5129969768086
+Current loss is: 295.23461197689846
+Current loss is: 295.05682093896877
+
+ +
+ERROR: InterruptException:
+
+ + +

Analyzing the solution

+

Now let us find a Monte-Carlo Solution and plot the both:

+ + +
+monte_carlo_sol = []
+x_out = collect(98:1.00:110.00)
+for x in x_out
+  u₀= [x]
+  g_val(du , u , p , t) = 0.4.*u
+  f_val(du , u , p , t) = du .= 0.04.*u
+  dt = 0.01
+  tspan = (0.0,1.0)
+  prob = SDEProblem(f,g,u₀,tspan)
+  output_func(sol,i) = (sol[end],false)
+  ensembleprob_val = EnsembleProblem(prob , output_func = output_func )
+  sim_val = solve(ensembleprob_val, EM(), EnsembleThreads() , dt=0.01, trajectories=100000,adaptive=false)
+  s = reduce(hcat , sim_val.u)
+  global monte_carlo_sol = push!(monte_carlo_sol , mean(phi(s)))
+end
+
+ + +
+ERROR: UndefVarError: f not defined
+
+ + + +
+m = fmap(cpu , m)
+x_model = reshape(x_out, 1 , size(x_out)[1])
+y_out = m(x_model)
+y_out = reshape(y_out , 13 , 1)
+
+ + +
+13×1 Array{Float32,2}:
+ 11.862513
+ 11.9830265
+ 12.103537
+ 12.224047
+ 12.3445635
+ 12.46507
+ 12.585586
+ 12.706097
+ 12.826607
+ 12.947119
+ 13.067632
+ 13.188141
+ 13.308652
+
+ + +

Plotting the solutions

+ + +
+plot(x_out , y_out , lw = 3 ,  xaxis="Initial Stock Price", yaxis="Payoff")
+plot!(x_out , monte_carlo_sol , lw = 3 ,  xaxis="Initial Stock Price", yaxis="Payoff")
+
+ + +
+ERROR: BoundsError: attempt to access 0-element Array{Float64,1} at index [1:13]
+
+ + + +
+ +
+
+
+ + + diff --git a/html/introduction/jl_fb5xAW/06-kolmogorov_equations_4_1.svg b/html/introduction/jl_fb5xAW/06-kolmogorov_equations_4_1.svg new file mode 100644 index 00000000..0dd9f6c8 --- /dev/null +++ b/html/introduction/jl_fb5xAW/06-kolmogorov_equations_4_1.svg @@ -0,0 +1,240 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pdf/introduction/jl_ue4KZg/06-kolmogorov_equations_4_1.pdf b/pdf/introduction/jl_ue4KZg/06-kolmogorov_equations_4_1.pdf new file mode 100644 index 00000000..084dcf95 Binary files /dev/null and b/pdf/introduction/jl_ue4KZg/06-kolmogorov_equations_4_1.pdf differ diff --git a/script/introduction/06-kolmogorov_equations.jl b/script/introduction/06-kolmogorov_equations.jl new file mode 100644 index 00000000..9e34af37 --- /dev/null +++ b/script/introduction/06-kolmogorov_equations.jl @@ -0,0 +1,71 @@ + +using Flux, StochasticDiffEq +using NeuralNetDiffEq +using Plots +using LinearAlgebra + + +function phi(xi) + y = Float64[] + K = 100 + for x in eachcol(xi) + val = max(K - maximum(x) , 0.00) + y = push!(y , val) + end + y = reshape(y , 1 , size(y)[1] ) + return y +end + + +d = 1 +r = 0.06 +sigma = 0.4 +xspan = (95.00 , 110.0) +tspan = (0.0 , 1.0) +σ(du , u , p , t) = du .= sigma.*u +μ(du , u , p , t) = du .= r.*u + + +sdealg = EM() +ensemblealg = EnsembleThreads() +dt = 0.01 +dx = 0.01 +trajectories = 100000 + + +m = Chain(Dense(d, 32, leakyrelu),Dense(32, 128, leakyrelu),Dense(128 , 32 , leakyrelu) , Dense(32 , 1)) +m = fmap(cu , m) +prob = KolmogorovPDEProblem(μ , σ , phi , xspan , tspan, d) +opt = Flux.ADAM(0.01) + + +sol = solve(prob, NeuralNetDiffEq.NNKolmogorov(m, opt, sdealg, ensemblealg), verbose = true, dt = dt, + dx = dx , trajectories = trajectories , abstol=1e-6, maxiters = 3000) + + +monte_carlo_sol = [] +x_out = collect(98:1.00:110.00) +for x in x_out + u₀= [x] + g_val(du , u , p , t) = 0.4.*u + f_val(du , u , p , t) = du .= 0.04.*u + dt = 0.01 + tspan = (0.0,1.0) + prob = SDEProblem(f,g,u₀,tspan) + output_func(sol,i) = (sol[end],false) + ensembleprob_val = EnsembleProblem(prob , output_func = output_func ) + sim_val = solve(ensembleprob_val, EM(), EnsembleThreads() , dt=0.01, trajectories=100000,adaptive=false) + s = reduce(hcat , sim_val.u) + global monte_carlo_sol = push!(monte_carlo_sol , mean(phi(s))) +end + + +m = fmap(cpu , m) +x_model = reshape(x_out, 1 , size(x_out)[1]) +y_out = m(x_model) +y_out = reshape(y_out , 13 , 1) + + +plot(x_out , y_out , lw = 3 , xaxis="Initial Stock Price", yaxis="Payoff") +plot!(x_out , monte_carlo_sol , lw = 3 , xaxis="Initial Stock Price", yaxis="Payoff") + diff --git a/tutorials/introduction/06-kolmogorov_equations.jmd b/tutorials/introduction/06-kolmogorov_equations.jmd new file mode 100644 index 00000000..c8d4f4be --- /dev/null +++ b/tutorials/introduction/06-kolmogorov_equations.jmd @@ -0,0 +1,124 @@ +--- +title: Kolmogorov Backward Equations +author: Ashutosh Bharambe +--- + +```julia +using Flux, StochasticDiffEq +using NeuralNetDiffEq +using Plots +using Distributions +``` +## Introduction on Backward Kolmogorov Equations + +The backward Kolmogorov Equation deals with a terminal condtion. +The one dimensional backward kolmogorov equation that we are going to deal with is of the form : + +$$ + \frac{\partial p}{\partial t} = -\mu(x)\frac{\partial p}{\partial x} - \frac{1}{2}{\sigma^2}(x)\frac{\partial^2 p}{\partial x^2} ,\hspace{0.5cm} p(T , x) = \varphi(x) +$$ +for all $ t \in{ [0 , T] } $ and for all $ x \in R^d $ + +#### The Black Scholes Model + +The Black-Scholes Model governs the price evolution of the European put or call option. In the below equation V is the price of some derivative , S is the Stock Price , r is the risk free interest +rate and σ the volatility of the stock returns. The payoff at a time T is known to us. And this makes it a terminal PDE. In case of an European put option the PDE is: +$$ + \frac{\partial V}{\partial t} + rS\frac{\partial V}{\partial S} + \frac{1}{2}{\sigma^2}{S^2}\frac{\partial^2 V}{\partial S^2} -rV = 0 ,\hspace{0.5cm} V(T , S) = max\{\mathcal{K} - S , 0 \} +$$ +for all $ t \in{ [0 , T] } $ and for all $ S \in R^d $ + +In order to make the above equation in the form of the Backward - Kolmogorov PDE we should substitute + +$$ + V(S , t) = e^{r(t-T)}p(S , t) +$$ +and thus we get +$$ + e^{r(t-T)}\frac{\partial p}{\partial t} + re^{r(t-T)}p(S , t) = -\mu(x)\frac{\partial p}{\partial x}e^{r(t-T)} - \frac{1}{2}{\sigma^2}(x)\frac{\partial^2 p}{\partial x^2}e^{r(t-T)} + + re^{r(t-T)}p(S , t) +$$ +And the terminal condition +$$ + p(S , T) = max\{ \mathcal{K} - x , 0 \} +$$ +We will train our model and the model itself will be the solution of the equation +## Defining the problem and the solver +We should start defining the terminal condition for our equation: +```julia +function phi(xi) + y = Float64[] + K = 100 + for x in eachcol(xi) + val = max(K - maximum(x) , 0.00) + y = push!(y , val) + end + y = reshape(y , 1 , size(y)[1] ) + return y +end +``` +Now we shall define the problem : +We will define the σ and μ by comparing it to the orignal equation. The xspan is the span of initial stock prices. +```julia +d = 1 +r = 0.04 +sigma = 0.4 +xspan = (95.00 , 110.0) +tspan = (0.0 , 1.0) +σ(du , u , p , t) = du .= sigma.*u +μ(du , u , p , t) = du .= r.*u +prob = KolmogorovPDEProblem(μ , σ , phi , xspan , tspan, d) +``` +Now once we have defined our problem it is necessary to define the parameters for the solver. +```julia +sdealg = EM() +ensemblealg = EnsembleThreads() +dt = 0.01 +dx = 0.001 +trajectories = 100000 +``` + +Now lets define our model m and the optimiser +```julia +m = Chain(Dense(d, 8, leakyrelu),Dense(8, 16, leakyrelu),Dense(16 , 8 , leakyrelu) , Dense(8 , 1)) +m = fmap(cu , m) +opt = Flux.ADAM(0.01) +``` +And then finally call the solver +```julia +sol = solve(prob, NeuralNetDiffEq.NNKolmogorov(m, opt, sdealg, ensemblealg), verbose = true, dt = dt, + dx = dx , trajectories = trajectories , abstol=1e-6, maxiters = 4200) +``` +## Analyzing the solution +Now let us find a Monte-Carlo Solution and plot the both: +```julia +monte_carlo_sol = [] +x_out = collect(98:1.00:110.00) +for x in x_out + u₀= [x] + g_val(du , u , p , t) = du .= 0.4.*u + f_val(du , u , p , t) = du .= 0.04.*u + dt = 0.01 + tspan = (0.0,1.0) + prob = SDEProblem(f_val,g_val,u₀,tspan) + output_func(sol,i) = (sol[end],false) + ensembleprob_val = EnsembleProblem(prob , output_func = output_func ) + sim_val = solve(ensembleprob_val, EM(), EnsembleThreads() , dt=0.01, trajectories=100000,adaptive=false) + s = reduce(hcat , sim_val.u) + global monte_carlo_sol = push!(monte_carlo_sol , mean(phi(s))) +end +``` + +##Plotting the Solutions +We should reshape the inputs and outputs to make it compatible with our model. This is the most important part. The algorithm gives a distributed function over all initial prices in the xspan. +```julia +x_model = reshape(x_out, 1 , size(x_out)[1]) +m = fmap(cpu , m) +y_out = m(x_model) +y_out = reshape(y_out , 13 , 1) +``` +And now finally we can plot the solutions +```julia +plot(x_out , y_out , lw = 3 , xaxis="Initial Stock Price", yaxis="Payoff" , label = "NNKolmogorov") +plot!(x_out , monte_carlo_sol , lw = 3 , xaxis="Initial Stock Price", yaxis="Payoff" ,label = "Monte Carlo Solutions") +```