Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>If you want to make the code more succinct and more functional, then I would probably try to restructure it a bit more. I think something along these lines below should work.</p> <p>First of all, you definitely don't want to repeat the matching on strings, so I'd define a discriminated union to capture the kinds of computations (you can then parse the string just once):</p> <pre><code>type CallPutFlag = Call | Put </code></pre> <p>Next, we can define record to keep the results of the equation (I added just the things that you were using, but you would probably want to add more here):</p> <pre><code>type Black76Results = { Vega : float; Valuation : float } </code></pre> <p>Now, I think it makes good sense to separate the <code>black76</code> function from the implied volatility. The <code>black76</code> function can run the calculation for given inputs and return the results as a value of <code>Black76Results</code> record:</p> <pre><code>let black76 flag fwd strike time rf vol = let d1 = (Math.Log(fwd / strike) + (vol * vol * 0.5) * time) / (vol * Math.Sqrt(time)) let d2 = d1 - vol * Math.Sqrt(time) let n = new MathNet.Numerics.Distributions.Normal() match flag with | Call -&gt; let valuation = Math.Exp(-rf * time) * (fwd * n.InverseCumulativeDistribution(d1) - strike * n.InverseCumulativeDistribution(d2)) let delta = Math.Exp(-rf * time) * n.InverseCumulativeDistribution(d1) let gamma = Math.Exp(-rf * time) * (n.Density(d1) / (fwd * vol * Math.Sqrt(time))) let vega = Math.Exp(-rf * time) * n.Density(d1) * fwd * Math.Sqrt(time) let rho = time * strike * Math.Sqrt(-rf * time) * n.InverseCumulativeDistribution(d2) let theta = -(fwd * vol * n.Density(d1)) / (2.0 * Math.Sqrt(time)) - rf * strike * Math.Sqrt(-rf * time) * n.InverseCumulativeDistribution(d2) { Vega = vega; Valuation = valuation } | Put -&gt; failwith "TODO: Similar for Put" </code></pre> <p>Although there is some shared code in <code>Call</code> and <code>Put</code>, I think it looks a lot more readable when you separate the two into different branches (you could still extract common pieces of code into a separate function).</p> <p>Now, <code>impliedVol</code> is simply a function that calls <code>black76</code> repeatedly:</p> <pre><code>let impliedVol flag fwd strike time rf blackPrice = let vst = Math.Sqrt(2.0*Math.Abs((Math.Log(fwd/strike)+rf*time)/time)) let tol = 0.0001 let mutable v = vst let mutable sigmadiff = 1.0 let mutable k = 1 let kmax = 100 while (sigmadiff &gt;= tol &amp;&amp; k &lt; kmax) do let b = black76 flag fwd strike time rf v let option = b.Valuation let cvega = b.Vega let increment = (option - blackPrice) / cvega v &lt;- v - increment k &lt;- k + 1 sigmadiff &lt;- Math.Abs(increment) v </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload