I m trying to implement something in f# that I already have in c# to see how much more succinct the syntax is. I used an option pricing formula (Black 76) as test because this seems like a functional problem to me. All seems fine but I have trouble computing the implied vol as I need to call a method of the same class from within. Here is what I have so far:
module Module1
open System
type Black76 (CallPutFlag, Fwd, Strike, time, rf, vol, ?BlackPrice:float) =
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()
member x.valuation =
match CallPutFlag with
| "c" | "C" | "Call" | "call" -> Math.Exp(-rf * time) * (Fwd * n.InverseCumulativeDistribution(d1) - Strike * n.InverseCumulativeDistribution(d2))
| "p" | "P" | "Put" | "put" -> Math.Exp(-rf * time) * (Strike * n.InverseCumulativeDistribution(-d2)- Fwd * n.InverseCumulativeDistribution(-d1))
| _ -> failwith "Unrecognized option type"
member x.delta =
match CallPutFlag with
| "c" | "C" | "Call" | "call" -> Math.Exp(-rf * time) * n.InverseCumulativeDistribution(d1)
| "p" | "P" | "Put" | "put" -> Math.Exp(-rf * time) * n.InverseCumulativeDistribution(-d1)
| _ -> failwith "Unrecognized option type"
member x.gamma =
Math.Exp(-rf * time) * (n.Density(d1) / (Fwd * vol * Math.Sqrt(time)))
member x.vega =
Math.Exp(-rf * time) * n.Density(d1) * Fwd * Math.Sqrt(time)
member x.rho =
match CallPutFlag with
| "c" | "C" | "Call" | "call" -> time * Strike * Math.Sqrt(-rf * time) * n.InverseCumulativeDistribution(d2)
| "p" | "P" | "Put" | "put" -> -time * Strike * Math.Sqrt(-rf * time) * n.InverseCumulativeDistribution(-d2)
| _ -> failwith "Unrecognized option type"
member x.theta =
match CallPutFlag with
| "c" | "C" | "Call" | "call" -> -(Fwd * vol * n.Density(d1)) / (2.0 * Math.Sqrt(time)) - rf * Strike * Math.Sqrt(-rf * time) * n.InverseCumulativeDistribution(d2)
| "p" | "P" | "Put" | "put" -> -(Fwd * vol * n.Density(d1)) / (2.0 * Math.Sqrt(time)) + rf * Strike * Math.Sqrt(-rf * time) * n.InverseCumulativeDistribution(-d2)
| _ -> failwith "Unrecognized option type"
member x.impliedvol =
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 >= tol && k < kmax) do
let option = Black76.valuation(CallPutFlag, Fwd, Strike, time, rf, v)
let cvega = Black76.vega(CallPutFlag, Fwd, Strike, time, rf, v)
let increment = (option - BlackPrice) / cvega
v <- v - increment
k < - k + 1
sigmadiff = Math.Abs(increment)
v
This all works apart from the implied vol function. Also it does not seem to be much more succinct than the c# version. Could you please let me know how I can call the method from within for the implied vol funcitons? Also do you know how to get rid of the let mutable (after all you are not supposed to use this in fsharp (I think).
thanks
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.
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):
type CallPutFlag = Call | Put
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):
type Black76Results = { Vega : float; Valuation : float }
Now, I think it makes good sense to separate the black76 function from the implied volatility. The black76 function can run the calculation for given inputs and return the results as a value of Black76Results record:
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 ->
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 ->
failwith "TODO: Similar for Put"
Although there is some shared code in Call and Put, 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).
Now, impliedVol is simply a function that calls black76 repeatedly:
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 >= tol && k < 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 <- v - increment
k <- k + 1
sigmadiff <- Math.Abs(increment)
v
So your problem is the lines:
let option = Black76.valuation(CallPutFlag, Fwd, Strike, time, rf, v)
let cvega = Black76.vega(CallPutFlag, Fwd, Strike, time, rf, v)
Your trying to call them on the type Black76, when they're instance members of an object of type Black76. You should use x.valuation(...) instead, (x because that's what you've called your this variable).
F# doesn't have a fixed keyword for what in C# is known as this. Instead when you declare a member you give any name you want before the dot.
member this.method_name =
member x.another_method =
Related
I'm learning F# by implementing a board game engine. In accordance with the principle that invalid states should not be representable, I want to create a type which represents (x, y) coordinates (with x and y integers) where x and y must satisfy 0 <= x <= n and 0 <= y <= m. Creating an instance that does not satisfy those inequalities shouldn't compile. Is this possible?
I don't think compile time assurances on values like this are possible.
I would handle this with a private constructor and the Result or Option type depending whether I wanted to propagate error information.
type Position =
private {
X: int
Y: int
}
static member TryNew(x, y) =
if x >= 0 && x <= 10 then
if y >= 0 && y <=10 then
Ok {
X = x
Y = y
}
else
Error $"Supplied y ({y}) must be between 0 and 10"
else
Error $"Supplied x ({x}) must be between 0 and 10"
module Position =
let moveX1 pos =
Position.TryNew(pos.X + 1, pos.Y)
This does create the issue where Results are now everywhere in your code but they don't have to be visible or cause you a lot of typing. This problem is precisely what computation expression libraries e.g. FsToolkit.ErrorHandling are designed to eliminate.
let example =
result {
let! start = Position.TryNew(0,0)
let! next = start |> moveX1
}
There's no way to do this that takes integers as input, but it can be done with a type that only provides integers as output:
type XCoord = X0 | X1 | X2 with
member this.Int =
match this with
| X0 -> 0
| X1 -> 1
| X2 -> 2
static member (-)(xa : XCoord, xb: XCoord) =
xa.Int - xb.Int
type YCoord = Y0 | Y1 | Y2 with
member this.Int =
match this with
| Y0 -> 0
| Y1 -> 1
| Y2 -> 2
static member (-)(ya : YCoord, yb: YCoord) =
ya.Int - yb.Int
type Point = MkPoint of (XCoord * YCoord) with
member this.Ints =
let (MkPoint (x, y)) = this
x.Int, y.Int
static member (-)((MkPoint (ax, ay)), (MkPoint (bx, by))) =
ax - bx, ay - by
let ptA = MkPoint (X0, Y1)
let ptB = MkPoint (X2, Y0)
printfn "%A" ptA.Ints
printfn "%A" ptB.Ints
printfn "%A" (ptA - ptB)
I think this would be pretty clunky to use in practice, but it might work, depending on exactly what you want to do with it. I guess it's a case of "careful what you ask for". 😀
this is an EMA calculation:
let EMA (period : int) (data : double[]) : double[] =
let multiplier = 2.0 / (double)(period + 1)
let output = Array.create data.Length System.Double.NaN
output.[period - 1] <- data.[0..period - 1] |> Seq.average
for i in seq {period .. (data.Length - 1)} do
output.[i] <- (data.[i] * multiplier) + (output.[i - 1] * (1. - multiplier))
output
you can test it with:
EMA 3 [|1.;3.;4.;7.;5.;6.;9.;8.|]
and it gives:
[|NaN;Nan;2.66.;4.83;4.91;5.45;7.22;7.61|]
my first question is regarding the loop at the end:
for i in seq {period .. (data.Length - 1)} do
output.[i] <- (data.[i] * multiplier) + (output.[i - 1] * (1. - multiplier))
can this be rewritten using a sequence operator?
my second question is: is there a fast F# implementation floating around? I couldn't find any.
Well, I don't know about floating around, but I did just write an EMA function yesterday. It looks like this:
let ema alpha vs =
(None, vs)
||> Array.scan (fun prev x ->
match prev with
| None -> Some(x)
| Some(s) -> Some(alpha*x + (1. - alpha)*s))
|> Array.choose id
My version looks all the way back, rather than only a number of periods, as your version. If you want that behaviour instead, you could replace the state of type float option in my version with a float[], or even implement it using the Array.windowed function.
I have a csv file containing daily weights as follows:
Date,Name,Weight
11-Sep-2017,Alpha,9-1
13-Sep-2017,Alpha,8-13
15-Sep-2017,Alpha,8-11
Though I can successfully import them using CsvProvider, the weight column defaults to System.DateTime.
// Weight
[<Measure>] type lb
[<Literal>]
let input = "DayWeights.csv"
type Weights = CsvProvider<input, HasHeaders=true>
let data = Weights.GetSample()
for row in data.Rows do
printfn "Output: (%A, %A, %A)" row.Date row.Name row.Weight
Is it possible to create a Unit of Measure (UoM) to define "stlb" with the option to convert to lbs on import and, if so, how?
I don't think you could represent stones-pounds as a single numeric type, and units of measure can only be used on numeric types (although there is some discussion about changing this in future). This is because some of their features only make sense with numeric operations like addition and multiplication. The units themselves are multiplied and divided:
[<Measure>] type lb
2<lb> + 2<lb> // 4<lb>
2<lb> * 2<lb> // 4<lb ^ 2>
2<lb> / 2<lb> // 1
Instead of units of measure, if you want some kind of tag to know that a given value has a type of stones-pounds, you could create a single case discriminated union:
type StonesPounds = StonesPounds of int * int
// StonesPounds -> int<lb>
let convertToLb (StonesPounds (s, p)) = (s * 14 + p) * 1<lb>
StonesPounds (1, 2) |> convertToLb // 16<lb>
The downside of this compared to units of measure is that you have to manually pack and unpack these values in code before you can use the numbers and there is a runtime cost for that too.
I resolved the automatic converting of the input weight column to System.DateTime as follows:
// http://fssnip.net/27
let lazySplit (sep:string) (str:string) =
match sep, str with
| ((null | ""), _) | (_, (null | "")) -> seq [str]
| _ ->
let n, j = str.Length, sep.Length
let rec loop p =
seq {
if p < n then
let i = match str.IndexOf(sep, p) with -1 -> n | i -> i
yield str.Substring(p, i - p)
yield! loop (i + j)
}
loop 0
let weight input =
input
|> (fun x -> lazySplit "/" x |> Seq.take 2 |> String.concat("-"))
let data = Weighings.GetSample()
for row in data.Rows do
let stlbs = weight (string row.Weight)
printfn "Output: (%A, %A, %A)" row.Date row.Name stlbs
// Output: 11-Sep-2017,"Alpha","09-01")
Thanks to one and all for your expert help and guidance.
I am looking for some pointers/snippets to resolve below task.
type Rel =
{
id:int,
from:int,
to:int,
percent:float
IsLeafNode:string
}
I have below data
id from to percent isLeafNode`
1 A B 0.6 N
2 A C 0.4 N
3 B D 0.2 N
4 B E 0.8 Y
5 C F 1.0 N
6 D G 1.0 Y
7 F H 0.7 Y
8 F B 0.3 N
9 I J 1.0 N
10 J K 1.0 Y
I need to build a tree or graph like relationship between from and to values and multiply percentages from some specific nodes (A and I in this case) to leaf nodes and figure out starting id to leaf level Id and computed percentage. I am looking for below results
1 - 6 (A to G via B,D) = 0.6 * 0.2 * 1.0 = 0.12
1 - 4 (A to E via B) = 0.6 * 0.8 = 0.48
1 - 7 (A to H via C,F) = 0.4 * 1.0 * 0.7 = 0.28
1 - 6 (A to G via C,F,B,D,G) = 0.4 * 1.0 * 0.3 * 0.2 * 1.0 = 0.024
1 - 4 (A to E via C,F,B,E) = 0.4 * 1.0 * 0.3 * 0.8 = 0.096
9 - 10(I to K via J) = 1.0 * 1.0 = 1.0
I am trying to figure what will be right type of structure to use and how to use some of already resolved nodes e.g. B already resolved while resolving left side of A; F to B should be able to use already computed B to G and B to E percentages. I have lot of data to process using this approach and it could be up to 50 levels deep.
just taking first few nodes, here is what I am doing
type internal LeafNode
{
ID:int;
to:string;
percent:float;
}
type internal ChurnNode =
{
ID:int;
from:string;
percent:float;
}
type internal Tree<'L,'N> =
| Leaf of 'L
| Node of 'N * Tree<'L,'N> seq
type internal Eq = Tree<LeafNode, ChurnNode>
let rec Fold fLeaf fNode acc (tree: Tree<'L,'N>) : 'r =
let recurse = Fold fLeaf fNode
match tree with
| Leaf leafInfo ->
fLeaf acc leafINfo
| Node (nodeInfo, children) ->
let localAcc = fNode acc nodeInfo
let finalAcc = children |> Seq.fold recurse localAcc
finalAcc //return
let ComputePercent eq =
let fleaf acc (leaf:LeafNode) =
acc * leaf.percent
let fNode acc (node:ChurnNode) =
acc * node.percent
Fold fleaf fNode 1.0 eq
let RunProcess() =
let nodeA = {ID=0;from="A";percent=1.0}
let nodeB = {ID=1;from="B";percent=0.6}
let leafC = {ID=2;to="C";percent=0.4}
let leafD = {ID=2;to="D";percent=0.2}
let leafE = {ID=2;to="E";percent=0.8}
let t = Node(nodeA, [NodeB, [Leaf(leafD); Leaf(leafE)]; Leaf(leafC)]
t |> ComputePercentage
For A to B to D & E, this code returns 1.0 * 0.6 * 0.2 * 0.8 but I need A to B to D = 1.0 * 0.6 * 0.2 and A to B to E = 1.0 * 0.6 * 0.8. Can you let me how how to reset the accumulator when done with a leaf. May be I got off wrong foot here but it's bit tricky for me.
I have a function to generate doubles in a range:
let gen_doublein =
fun mx mn -> Arb.generate<float> |> Gen.suchThat ( (>) mx ) |> Gen.suchThat ( (<) mn )
and then a function to generate an array of 2 of these:
let gen_params:Gen<double array> =
gen { let! x = gen_doublein 0.0 20000.0
let! y = gen_doublein 0.0 2000.0
return [| x;y|] }
I put:
static member arb_params = Arb.fromGen gen_params
in the Generator class and register it. All seems OK. To test that this is all OK I have:
let f2 (xs:double array) :double= exp (-2.0*xs.[0]) + xs.[1]*exp (-2.0*xs.[0])
let fcheck fn xs = fn xs > 0.0
then using an array generator 'arrayOfLength':
Check.Quick (Prop.forAll (arrayOfLength 2) (fcheck f2))
works as expected, however:
Check.Quick (Prop.forAll (Generators.arb_params) (fcheck f2))
just starts doing some calculation and never comes back. f# gurus please help.
I did not try this, but I think the problem is that the generator creates float values randomly and then checks whether they match the predicate you specified (the range). This means that it has to generate a large number of floats before it (randomly) generates one that matches.
It would be easier to generate values in a specified range by generating float values in a range [0 .. 1]
and then re-scaling them to match the range you need.
I'm not familiar with FsCheck enough, so I don't know if there is a generator for [0 .. 1] floating-point range, but you could start by generating integers and transforming them to floats:
let gen_doublein mx mn = gen {
let! n = Arb.generate<int>
let f = float n / float Int32.MaxValue
return mx + (f * (mn - mx)) }
EDIT I see that you solved the problem already. I think the solution I posted might still be relevant for smaller ranges (where the random generator does not produce enough matching values soon enough).
The problem was the parameters were the wrong way round. Tomas's suggestion is a good one, and there are some helper functions to implement it.
// Another id function
let fd (d:double) = d
// Check that it is in bounds
let mn=1.0
let mx=5.0
let fdcheck d = (fd d <= mx) && (fd d >= mn)
// Run the check with the numbers generated within the bounds
Check.Quick (Prop.forAll (Arb.fromGen (Gen.map (fun x->
match x with
| _ when Double.IsNaN x -> (mn+mx)/2.0
| _ when x> 1e+17 ->mx
| _ when x< -1e17 ->mn
| _ -> mn + (mx-mn)*(sin x+1.0)/2.0
) Arb.generate<double>
)
) fdcheck
)
Here I have a function which passes the test if the parameter is generated correctly. I'm not sure Tomas's idea with integers works because I think that a lot of small integers are generated and so the doubles don't explore the domain much - but maybe somebody who knows FSCheck might enlighten us.
Rewritten a sample from #b1g3ar5 this way
let mapRangeNormal (min : float<_>, max : float<_>) x =
match x with
| _ when Double.IsNaN x -> (min + max) / 2.0
| _ when Double.IsPositiveInfinity x -> max
| _ when Double.IsNegativeInfinity x -> min
| _ -> min + (max - min) * (sin x + 1.0) / 2.0
let mapRangeUniform (min : float<_>, max : float<_>) x =
match x with
| _ when Double.IsNaN x -> (min + max) / 2.0
| _ when Double.IsPositiveInfinity x -> max
| _ when Double.IsNegativeInfinity x -> min
| _ when x < 0.0 ->
let newRange = max - min
min - x * (newRange / Double.MaxValue) - newRange / 2.0
| _ -> let newRange = max - min
min + x * (newRange / Double.MaxValue) + newRange / 2.0