Hi,
The algorithm you linked to could be directly translated in F# using imperative
constructs, such as arrays and loops, but it wouldn't demonstrate any interesting
or unique feature of the language (the code would look just the same as its C# or
C++ equivalent).
There are probably many other (and more efficient) ways to implement a binomial
tree pricer, but here is one using a higher order function allowing to independently
specify the discretization scheme and the option payoff as function arguments, and
sequences to represent the collection of states at a given date :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
// the exercise style type Style = | European | American // the common payoffs let call k s = max 0.0 (s - k) let put k s = max 0.0 (k - s) // the market parameters type Market = { spot : float; vol : float; rate : float } // the recursion using sequences let binomialPrice discretization n payoff style (maturity : float) market = let (up, down, prob, discount) = discretization n maturity market let rec backprop k states = if k = 0 then Seq.head states |> snd else let states' = states |> Seq.pairwise |> Seq.map (fun ((sd, od), (_, ou)) -> let spot = sd / down let expectation = discount * (prob * ou + (1.0 - prob) * od) match style with | European -> (spot, expectation) | American -> (spot, max expectation (payoff spot)) ) backprop (k - 1) states' (n, market.spot * down ** float n) |> Seq.unfold (fun (k, s) -> if k < 0 then None else Some(s, (k - 1, s * (up / down)))) |> Seq.map (fun spot -> (spot, payoff spot)) |> backprop n // symmetric discretization let cox n maturity market = let dt = maturity / float n let up = exp (market.vol * sqrt dt) let down = 1.0 / up let prob = (exp(market.rate * dt) - down) / (up - down) let disc = exp (-market.rate * dt) (up, down, prob, disc) // three moments matching discretization let tian n maturity market = let dt = maturity / float n let r = exp (market.rate * dt) let v = exp (market.vol * market.vol * dt) let up = 0.5 * r * v * (1.0 + v + sqrt(v * v + 2.0 * v - 3.0)) let down = 0.5 * r * v * (1.0 + v - sqrt(v * v + 2.0 * v - 3.0)) let prob = (r - down) / (up - down) let disc = 1.0 / r (up, down, prob, disc) // concrete pricers obtained by partial application let coxECall n k = binomialPrice cox n (call k) European let coxEPut n k = binomialPrice cox n (put k) European let coxACall n k = binomialPrice cox n (call k) American let coxAPut n k = binomialPrice cox n (put k) American let tianECall n k = binomialPrice tian n (call k) European let tianEPut n k = binomialPrice tian n (put k) European let tianACall n k = binomialPrice tian n (call k) American let tianAPut n k = binomialPrice tian n (put k) American // now we can price some stuff !!! let coxEC = coxECall 500 100.0 1.0 {spot = 100.0; vol = 0.2; rate = 0.02} let coxEP = coxEPut 500 100.0 1.0 {spot = 100.0; vol = 0.2; rate = 0.02} let coxAC = coxACall 500 100.0 1.0 {spot = 100.0; vol = 0.2; rate = 0.02} let coxAP = coxAPut 500 100.0 1.0 {spot = 100.0; vol = 0.2; rate = 0.02} let tianEC = tianECall 500 100.0 1.0 {spot = 100.0; vol = 0.2; rate = 0.02} let tianEP = tianEPut 500 100.0 1.0 {spot = 100.0; vol = 0.2; rate = 0.02} let tianAC = tianACall 500 100.0 1.0 {spot = 100.0; vol = 0.2; rate = 0.02} let tianAP = tianAPut 500 100.0 1.0 {spot = 100.0; vol = 0.2; rate = 0.02}
I hope this was useful.
Cheers, bubo**2.
Hello Bubo,
I'm having a really hard time understading the following "backdrop" function. Could you pls explain the how it is done. I think I know how the binomial tree works, and the back propagation idea, but having trouble understanding the this recursive function. Among other things, I'm also not seeing where the terminal stock price enters into the picture. Could you pls help
Thank you very much.
Joe
Hi Joe,
You didn't mention at which point you were in the process of learning / discovering F#, so i'll try to explain
everything step by step at the risk of stating the obvious.
A tree state is defined as a pair of spot price and option price, and the set of states at a given
time is represented as a sequence ordered by ascending spot price.
The algorithm consists of two parts,
(1) Initialization :
The terminal sequence is generated from the lowest possible spot price at time n (s0*down**n : n down moves), to the highest (s0*up**n : n up moves), by incrementally multiplying by up/down (undo a down move and do an up move instead).
This step is accomplished by Seq.unfold which is a very nice function allowing to build a sequence from a recurrence relation :
it takes as arguments a seed state and a function which, given a current state returns None to indicate termination or Some pair of a generated element and a new state. In order to obtain the terminal option prices as well, we just have to apply Seq.map to transform each spot to a pair of the spot and the associated payoff.
(2) Recursion :
Given the states at time k, compute the states at time (k-1) knowing that the new lowest state will be computed from the old lowest state and its successor and so on. Enter another nice function from the Seq module, pairwise, which produces the sequence of pairs (element, successor) we just need.
The remaining map simply implements the elementary backward computation step with a lambda whose argument is a pattern representing the pair of states ((spot down, option down), (spot up, option up)).
Note that the base sequence obtained at the end of the recursion is actually a kind of delayed computation which unfolds only when Seq.head is called.
Seq.unfold can be replaced with the more explicit :
1 2
[0 .. n] |> Seq.map (fun i -> market.spot * (up ** float i) * (down ** float (n - i)))
Sequences can be replaced with lists altogether (change Seq to List and implement List.pairwise !!!).
Surprisingly enough the code performance is not too bad (?) when compared to the most imperative equivalent (one array + in place mutation + for loops) : american put with 500 steps => ~25ms (seq) ~20ms (list) ~5ms (horribly imperative).
Cheers, bubo**2.
Hi Bubo,
Thanks much for the explanation. Yes, I should have told you this at the beginning, I'm just 2 weeks into F#. Started reading "F#" Oreilly book, but wanted to learn by doing it, and picked what I thought was a non trivial exercise. And sure it turns out to be a non trivial : )
And yes, like you said in the first message I was trying to do it in the functional programming way, not using imperative constructs.
I really appreciate you taking time to explain things. I have to admit, I'm still not able to put everything together. It is the recursive function that's throwing me off. Among other things, you're calling "backprop n" at the end of it, does it not take two variables ?
I'm also wondering if you happen to have a non recursive version of backprop function. I'm thinking it might be easier for me to understand it.
Thanks again for your help.
Joe
Hi Bubo,
Great posting.
Does the sequence function memoize the joining tree? I would think not as there are roundoff issues.
James
Actually, having invested the time to understand the code, I see that the sequences are truely replicating the backwards sweep with pair wise combining. So there is no notion of "over doing" it that would need memoization.
Anyways, for fun I wrote a recursive version to compare speeds (not much faster):
let binomialPrice2 discretization n payoff style (maturity : float) market =
let (up, down, prob, discount) = discretization n maturity market
let cache = Array.zeroCreate<float> (4*n*n)
let rec price i j spot =
if i=n then
payoff spot
else
let index = (2*n*i)+(n+j)
let cp = cache.[index]
if cp<>0.0 then
cp-1.0
else
let ou = price (i+1) (j+1) (up*spot)
let od = price (i+1) (j-1) (down*spot)
let expectation = discount * (prob * ou + (1.0 - prob) * od)
let o =
match style with
| European -> expectation
| American -> max expectation (payoff spot)
cache.[index]<-(o+1.0);
o
price 0 0 market.spot
(obviously you see can't understand how to get the formatting to work!, sorry about that)
Joe, to answer your question about backprop, yes it has two arguments and the second is applied via the pipe-forward (|>) operator. I suggest that you keep reading "Programming F#" through the end of chapter 3 where currying, function composition and recursion are explained and the code above should become clearer (the description of the sequence aggregate operators on the F# MSDN online documentation should be helpful too).
James, I like your recursion on a lattice way of implementing the algorithm, although it seems that some code have gone missing (the cache assignment). Also, I don't quite understand where the cp - 1.0 is coming from (line 11 of the code snippet).
For fun, as well, here is a revised version of the sequence algorithm using only pipelined higher-order functions :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
let binomialPrice discretization n payoff style (maturity : float) market = let (up, down, prob, discount) = discretization n maturity market let backstep ((sd, od), (_, ou)) = let spot = sd / down let expectation = discount * (prob * ou + (1.0 - prob) * od) match style with | European -> (spot, expectation) | American -> (spot, max expectation (payoff spot)) (n, market.spot * down ** float n) |> Seq.unfold (fun (k, s) -> if k < 0 then None else Some(s, (k - 1, s * (up / down)))) |> Seq.map (fun s -> (s, payoff s)) |> Seq.unfold (Seq.pairwise >> Seq.map backstep >> fun x -> Some(x, x)) |> Seq.skip (n - 1) |> Seq.head |> Seq.head |> snd
Bubo**2.
Hi Bubo, Very nice, though I'm still trying to digest this ; ), I can see the elegence in your solution. Thank you very much.
Joe.
Topic tags
- f# × 3705
- websharper × 1897
- compiler × 286
- functional × 201
- ui next × 139
- c# × 121
- classes × 97
- web × 97
- .net × 84
- book × 84
- async × 76
- ui.next × 67
- bug × 54
- core × 49
- website × 49
- server × 45
- parallel × 43
- ui × 43
- enhancement × 41
- parsing × 41
- testing × 41
- trywebsharper × 41
- typescript × 37
- html × 35
- javascript × 35
- owin × 35
- asynchronous × 30
- monad × 28
- ocaml × 28
- tutorial × 27
- warp × 27
- haskell × 26
- sitelet × 25
- linq × 22
- workflows × 22
- wpf × 20
- fpish × 19
- introduction × 19
- silverlight × 19
- sitelets × 19
- monodevelop × 17
- rpc × 17
- suave × 17
- piglets × 16
- collections × 15
- feature request × 15
- jquery × 15
- templates × 15
- getting started × 14
- pipeline × 14
- kendoui × 13
- reactive × 12
- 4.1.0.171 × 11
- monads × 11
- opinion × 10
- 4.0.190.100-rc × 9
- deployment × 9
- fixed × 9
- formlets × 9
- in × 9
- json × 9
- plugin × 9
- proposal × 9
- scheme × 9
- solid × 9
- basics × 8
- concurrent × 8
- highcharts × 8
- how-to × 8
- python × 8
- 4.1.1.175 × 7
- complexity × 7
- documentation × 7
- visual studio × 7
- 4.1.2.178 × 6
- lisp × 6
- real-world × 6
- released in 4.0.192.103-rc × 6
- remoting × 6
- resources × 6
- scala × 6
- websharper ui.next × 6
- workshop × 6
- xaml × 6
- 4.0.193.110 × 5
- 4.2.3.236 × 5
- aspnetmvc × 5
- authentication × 5
- azure × 5
- bootstrap × 5
- conference × 5
- dsl × 5
- formlet × 5
- java × 5
- list × 5
- metaprogramming × 5
- ml × 5
- released in Zafir.4.0.188.91-beta10 × 5
- sql × 5
- visualstudio × 5
- websharper.forms × 5
- zafir × 5
- 4.0.192.106 × 4
- 4.0.195.127 × 4
- 4.1.0.38 × 4
- 4.2.1.86 × 4
- 4.2.6.118 × 4
- css × 4
- example × 4
- extensions × 4
- fsi × 4
- fsx × 4
- html5 × 4
- jqueryui × 4
- lift × 4
- reflection × 4
- remote × 4
- rest × 4
- spa × 4
- teaching × 4
- template × 4
- websocket × 4
- wontfix × 4
- 4.0.196.147 × 3
- 4.1.0.34 × 3
- 4.1.6.207 × 3
- 4.2.1.223-beta × 3
- 4.2.11.258 × 3
- 4.2.4.114 × 3
- 4.2.4.247 × 3
- 4.2.5.115 × 3
- 4.2.6.253 × 3
- 4.2.9.256 × 3
- ajax × 3
- alt.net × 3
- aml × 3
- asp.net mvc × 3
- canvas × 3
- cloudsharper × 3
- compilation × 3
- database × 3
- erlang × 3
- events × 3
- extension × 3
- file upload × 3
- forums × 3
- inline × 3
- issue × 3
- kendo × 3
- macro × 3
- mono × 3
- msbuild × 3
- mvc × 3
- pattern × 3
- piglet × 3
- released in Zafir.4.0.187.90-beta10 × 3
- svg × 3
- type provider × 3
- view × 3
- 4.1.1.64 × 2
- 4.1.5.203 × 2
- 4.1.7.232 × 2
- 4.2.10.257 × 2
- 4.2.3.111 × 2
- 4.2.5.249 × 2
- android × 2
- asp.net × 2
- beginner × 2
- blog × 2
- chart × 2
- client × 2
- client server app × 2
- clojure × 2
- computation expressions × 2
- constructor × 2
- corporate × 2
- courses × 2
- cufp × 2
- d3 × 2
- debugging × 2
- direct × 2
- discriminated union × 2
- docs × 2
- elm × 2
- endpoint × 2
- endpoints × 2
- enterprise × 2
- entity framework × 2
- event × 2
- f# interactive × 2
- fable × 2
- flowlet × 2
- formdata × 2
- forms × 2
- fsc × 2
- google maps × 2
- hosting × 2
- http × 2
- https × 2
- iis 8.0 × 2
- install × 2
- interactive × 2
- interface × 2
- iphone × 2
- iteratee × 2
- jobs × 2
- jquery mobile × 2
- keynote × 2
- lens × 2
- lenses × 2
- linux × 2
- listmodel × 2
- mac × 2
- numeric × 2
- oauth × 2
- obfuscation × 2
- offline × 2
- oop × 2
- osx × 2
- packaging × 2
- pattern matching × 2
- performance × 2
- pipelines × 2
- q&a × 2
- quotation × 2
- reference × 2
- released in Zafir.4.0.185.88-beta10 × 2
- rx × 2
- script × 2
- security × 2
- self host × 2
- seq × 2
- sockets × 2
- stm × 2
- tcp × 2
- trie × 2
- tutorials × 2
- type × 2
- url × 2
- var × 2
- websharper.charting × 2
- websharper4 × 2
- websockets × 2
- wig × 2
- xna × 2
- zh × 2
- .net interop × 1
- 2012 × 1
- 4.0.194.126 × 1
- 4.1.3.184 × 1
- 4.1.4.189 × 1
- 4.2.0.214-beta × 1
- 4.2.12.259 × 1
- 4.2.2.231-beta × 1
- 4.2.8.255 × 1
- Canvas Sample Example × 1
- DynamicStyle Animated Style × 1
- Fixed in 4.0.190.100-rc × 1
- Released in Zafir.UI.Next.4.0.169.79-beta10 × 1
- SvgDynamicAttribute × 1
- WebComponent × 1
- abstract class × 1
- accumulator × 1
- active pattern × 1
- actor × 1
- addin × 1
- agents × 1
- aggregation × 1
- agile × 1
- alter session × 1
- animation × 1
- anonymous object × 1
- apache × 1
- api × 1
- appcelerator × 1
- architecture × 1
- array × 1
- arrays × 1
- asp.net 4.5 × 1
- asp.net core × 1
- asp.net integration × 1
- asp.net mvc 4 × 1
- asp.net web api × 1
- aspnet × 1
- ast × 1
- attributes × 1
- authorization × 1
- b-tree × 1
- back button × 1
- badimageformatexception × 1
- bash script × 1
- batching × 1
- binding-vars × 1
- bistro × 1
- body × 1
- bundle × 1
- camtasia studio × 1
- cas protocol × 1
- charts × 1
- clarity × 1
- class × 1
- cli × 1
- clipboard × 1
- clojurescript × 1
- closures × 1
- cloud × 1
- cms × 1
- coding diacritics × 1
- color highlighting × 1
- color zones × 1
- combinator × 1
- combinators × 1
- compile × 1
- compile code on server × 1
- config × 1
- confirm × 1
- content × 1
- context × 1
- context.usersession × 1
- continuation-passing style × 1
- coords × 1
- cordova × 1
- cors × 1
- coursera × 1
- cross-domain × 1
- csla × 1
- current_schema × 1
- custom content × 1
- data × 1
- data grid × 1
- datetime × 1
- debug × 1
- declarative × 1
- delete × 1
- devexpress × 1
- dhtmlx × 1
- dictionary × 1
- directattribute × 1
- disqus × 1
- distance × 1
- do binding × 1
- doc elt ui.next upgrade × 1
- docker × 1
- dojo × 1
- dol × 1
- dom × 1
- domain × 1
- du × 1
- duf-101 × 1
- dynamic × 1
- eastern language × 1
- eclipse × 1
- edsl × 1
- em algorithm × 1
- emacs × 1
- emotion × 1
- enums × 1
- error × 1
- etw × 1
- euclidean × 1
- eventhandlerlist × 1
- examples × 1
- ext js × 1
- extension methods × 1
- extra × 1
- facet pattern × 1
- failed to translate × 1
- fake × 1
- fantomas × 1
- fear × 1
- float × 1
- form × 1
- form-data × 1
- forum × 1
- fp × 1
- frank × 1
- fsdoc × 1
- fsharp × 1
- fsharp.core × 1
- fsharp.powerpack × 1
- fsharpx × 1
- fsunit × 1
- function × 1
- functional style × 1
- game × 1
- games × 1
- gc × 1
- generic × 1
- geometry × 1
- getlastwin32error × 1
- getting-started × 1
- google × 1
- google.maps × 1
- grid × 1
- group × 1
- guide × 1
- hash × 1
- headers × 1
- hello world example × 1
- heroku × 1
- highchart × 1
- history × 1
- how to × 1
- html-templating × 1
- http405 × 1
- httpcontext × 1
- hubfs × 1
- i18n × 1
- ie 8 × 1
- if-doc × 1
- iis × 1
- image × 1
- images × 1
- inheritance × 1
- initialize × 1
- input × 1
- install "visual studio" × 1
- installer × 1
- int64 × 1
- interfaces × 1
- internet explorer × 1
- interop × 1
- interpreter × 1
- io × 1
- iobservable × 1
- ios × 1
- iot × 1
- ipad × 1
- isomorphic × 1
- javascript optimization × 1
- javascript semanticui resources × 1
- jquery-plugin × 1
- jquery-ui × 1
- jquery-ui-datepicker × 1
- js × 1
- kendo datasource × 1
- kendochart × 1
- kendoui compiler × 1
- knockout × 1
- l10n × 1
- learning × 1
- library × 1
- libs × 1
- license × 1
- licensing × 1
- lineserieszonescfg × 1
- local setting × 1
- localization × 1
- logging × 1
- loop × 1
- macros × 1
- mailboxprocessor × 1
- mapping × 1
- maps × 1
- markerclusterer × 1
- markup × 1
- marshal × 1
- math × 1
- mathjax × 1
- message × 1
- message passing × 1
- message-passing × 1
- meta × 1
- metro style × 1
- micro orm × 1
- minimum-requirements × 1
- mix × 1
- mobile installation × 1
- mod_mono × 1
- modal × 1
- module × 1
- mouseevent × 1
- mouseposition × 1
- multidimensional × 1
- multiline × 1
- multithreading × 1
- mysql × 1
- mysqlclient × 1
- nancy × 1
- native × 1
- nested × 1
- nested loops × 1
- node × 1
- nunit × 1
- object relation mapper × 1
- object-oriented × 1
- om × 1
- onboarding × 1
- onclick × 1
- optimization × 1
- option × 1
- orm × 1
- os x × 1
- output-path × 1
- override × 1
- paper × 1
- parameter × 1
- persistence × 1
- persistent data structure × 1
- phonegap × 1
- pola × 1
- post × 1
- powerpack × 1
- prefix tree × 1
- principle of least authority × 1
- privacy × 1
- private × 1
- profile × 1
- programming × 1
- project × 1
- project euler × 1
- projekt_feladat × 1
- protected × 1
- provider × 1
- proxy × 1
- ptvs × 1
- public × 1
- pure f# × 1
- purescript × 1
- qna × 1
- quant × 1
- query sitelet × 1
- question × 1
- quotations × 1
- range × 1
- raphael × 1
- razor × 1
- rc × 1
- reactjs × 1
- real-time × 1
- ref × 1
- region × 1
- released in 4.0.190.100-rc × 1
- reporting × 1
- responsive design × 1
- rest api × 1
- rest sitelet × 1
- restful × 1
- round table × 1
- router × 1
- routing × 1
- rpc reverseproxy × 1
- runtime × 1
- sales × 1
- sample × 1
- sampleapp × 1
- scriptcs × 1
- scripting × 1
- search × 1
- self hosted × 1
- semanticui × 1
- sequence × 1
- serialisation × 1
- service × 1
- session-state × 1
- sharepoint × 1
- signals × 1
- sitelet website × 1
- sitelet.protect × 1
- sitlets × 1
- slickgrid × 1
- source code × 1
- sqlentityconnection × 1
- ssl × 1
- standards × 1
- static content × 1
- stickynotes × 1
- streamreader × 1
- stress × 1
- strong name × 1
- structures × 1
- submitbutton × 1
- subscribe × 1
- svg example html5 websharper.ui.next × 1
- sweetalert × 1
- system.datetime × 1
- system.reflection.targetinvocationexception × 1
- table storage × 1
- targets × 1
- tdd × 1
- templates ui.next × 1
- templating × 1
- text parsing × 1
- three.js × 1
- time travel × 1
- tls × 1
- tooltip × 1
- tracing × 1
- tsunamiide × 1
- turkish × 1
- twitter-bootstrap × 1
- type erasure × 1
- type inference × 1
- type providers × 1
- type-providers × 1
- typeprovider × 1
- ui next forms × 1
- ui-next × 1
- ui.next jqueryui × 1
- ui.next charting × 1
- ui.next formlets × 1
- ui.next forms × 1
- ui.next suave visualstudio × 1
- ui.next templating × 1
- unicode × 1
- unittest client × 1
- upload × 1
- usersession × 1
- validation × 1
- vb × 1
- vb.net × 1
- vector × 1
- view.map × 1
- visal studio × 1
- visual f# × 1
- visual studio 11 × 1
- visual studio 2012 × 1
- visual studio shell × 1
- vs2017 compiler zafir × 1
- vsix × 1
- web api × 1
- web-scraping × 1
- webapi × 1
- webcomponents × 1
- webforms × 1
- webgl × 1
- webrtc × 1
- webshaper × 1
- websharper async × 1
- websharper codemirror × 1
- websharper f# google × 1
- websharper forms × 1
- websharper reactive × 1
- websharper rpc × 1
- websharper sitelets routing × 1
- websharper warp × 1
- websharper-interface-generator × 1
- websharper.chartsjs × 1
- websharper.com × 1
- websharper.exe × 1
- websharper.owin × 1
- websharper.ui.next × 1
- websharper.ui.next jquery × 1
- websockets iis × 1
- why-websharper × 1
- windows 7 × 1
- windows 8 × 1
- windows-phone × 1
- winrt × 1
- www.grabbitmedia.com × 1
- xamarin × 1
- xml × 1
- yeoman × 1
- yield × 1
- zafir beta × 1
- zafir websharper4 × 1
- zarovizsga × 1
![]() |
Copyright (c) 2011-2012 IntelliFactory. All rights reserved. Home | Products | Consulting | Trainings | Blogs | Jobs | Contact Us | Terms of Use | Privacy Policy | Cookie Policy |
Built with WebSharper |
Hi,
I'm looking at how to implement a combining version of a binomial tree which is often used in finance to price options ([link:en.wikipedia.org])
Can someone show me how to do this in F# ?
Many thanks.
Joe