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.
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". 😀
I have a bunch of functions that I want to compute with the same inputs. Is there a better way to see the outputs than the way I chose below?
open MathNet.Numerics.Distributions
// The functions
let EuVanillaPut S0 K T r sigma =
let d1 = (log(S0/K) + (r + sigma ** 2.0 / 2.0) * T)/(sqrt(T)*sigma)
let d2 = d1 - sqrt(T)*sigma
K*exp(-r*T)*Normal.CDF(0.0,1.0,-d2) - S0*Normal.CDF(0.0,1.0,-d1)
let BSMdelta S0 K T r sigma =
let d1 = (log(S0/K) + (r + sigma ** 2.0 / 2.0) * T)/(sqrt(T)*sigma)
Normal.CDF(0.0,1.0,d1)
let BSMgamma S0 K T r sigma =
let d1 = (log(S0/K) + (r + sigma ** 2.0 / 2.0) * T)/(sqrt(T)*sigma)
Normal.PDF(0.0,1.0,d1) / (S0 * sigma * sqrt(T))
let BSMvega S0 K T r sigma =
let d1 = (log(S0/K) + (r + sigma ** 2.0 / 2.0) * T)/(sqrt(T)*sigma)
Normal.PDF(0.0,1.0,d1) * S0 * sqrt(T)
let BSMthetacall S0 K T r sigma =
let d1 = (log(S0/K) + (r + sigma ** 2.0 / 2.0) * T)/(sqrt(T)*sigma)
let d2 = d1 - sqrt(T)*sigma
-S0 * Normal.PDF(0.0,1.0,d1) * sigma / (2.0*sqrt(T)) - r*K*exp(-r*T)*Normal.CDF(0.0,1.0,d2)
let BSMthetaput S0 K T r sigma =
let d1 = (log(S0/K) + (r + sigma ** 2.0 / 2.0) * T)/(sqrt(T)*sigma)
let d2 = d1 - sqrt(T)*sigma
-S0 * Normal.PDF(0.0,1.0,d1) * sigma / (2.0*sqrt(T)) + r*K*exp(-r*T)*Normal.CDF(0.0,1.0,-d2)
// Calling them all at once on the same inputs
// So ugly! Is there a better way?
(30.0, 25.0, 5.0, 0.02, 0.05)
|> fun (S0, K, T, r, sigma) -> [EuVanillaPut S0 K T r sigma;
BSMdelta S0 K T r sigma;
BSMgamma S0 K T r sigma;
BSMvega S0 K T r sigma;
BSMthetacall S0 K T r sigma;
BSMthetaput S0 K T r sigma]
I'm pretty new to F#, should I make a type for this? Should I be using a different data structure as an input for the functions? Any and all pointers are much appreciated.
As suggested in the comments, one option is to create a list of functions and then use List.map to iterate over all the functions and call them:
let results =
[ EuVanillaPut; BSMdelta; BSMgamma ]
|> List.map (fun f -> f 30.0 25.0 5.0 0.02 0.05)
I suppose you'd then also want to extract the individual results - to do that, you can use pattern matching (but you will get a warning, because the compiler cannot know that the number of elements in the list is correct):
let [euVanillaPut; bsmdelta; bsmgamma] = results
To avoid the warning, you'd have to write:
match results with
| [euVanillaPut; bsmdelta; bsmgamma] -> // all good
| _ -> failwith "This should not happen..."
Alternatively, you could change the function definition to use tuple (or a record):
let EuVanillaPut (S0, K, T, r, sigma) =
let d1 = (log(S0/K) + (r + sigma ** 2.0 / 2.0) * T)/(sqrt(T)*sigma)
let d2 = d1 - sqrt(T)*sigma
K*exp(-r*T)*Normal.CDF(0.0,1.0,-d2) - S0*Normal.CDF(0.0,1.0,-d1)
Then you can define a single tuple to hold the parameters and use it as an argument to multiple functions:
let ps = (30.0, 25.0, 5.0, 0.02, 0.05)
let euVanillaPut = EuVanillaPut ps
let bsmdelta = BSMdelta ps
let bsmgamma = BSMgamma ps
The first approach is a clever trick, but if you are doing this often, then extracting the individual results from the list will be a bit ugly. The second approach is simpler and makes more sense if you have a lot of functions with the same group of parameters.
I am working through an F# function that calculates variance. I'm trying to step through each iteration to get the correct answer but think im getitng off track somewhere because I keep getting the wrong answer. Could someone please walk me through one iteration of this function to get me back on track
let variance values
let average = Seq.average values
let length = Seq.length values
values
|> Seq.map (fun x -> 1.0 / float length * (x - average) ** 2.0)
|> Seq.sum
call is variance [1.0..6.0]
To me the first value passed is 1.0 so it would be (1.0 / 6 * (1.0-3.5) ** 2.0) and therefore .166 * -2.5 ** 2.0
I'm also unsure what the ** means in formula I'm assuming multiply.
Correct answer should be 2.9166666667
To make it easier to understand, you can rewrite the code as follows:
let variance values =
let average = Seq.average values
let length = Seq.length values
let sum = values
|> Seq.map (fun x -> (x - average) ** 2.0)
|> Seq.sum in sum / float length
variance [1.0..6.0] |> printfn "%A"
Print: 2.916666667
Link: https://dotnetfiddle.net/09PHXn
By iteration:
let variancetest values =
let average = Seq.average values
let length = Seq.length values
values
|> Seq.iteri(fun i x ->
printfn "%i [%f]: %f ^ 2 = %A" i x (x - average) ((x - average) ** 2.0))
let sum = values
|> Seq.map (fun x -> (x - average) ** 2.0)
|> Seq.sum
let flength = float length
printfn "Sum = %f" sum
printfn "1/length = %f" (1.0 / flength)
printfn "Result / length = %f" (sum / flength)
variancetest [1.0..6.0]
Print:
0 [1.000000]: -2.500000 ^ 2 = 6.25
1 [2.000000]: -1.500000 ^ 2 = 2.25
2 [3.000000]: -0.500000 ^ 2 = 0.25
3 [4.000000]: 0.500000 ^ 2 = 0.25
4 [5.000000]: 1.500000 ^ 2 = 2.25
5 [6.000000]: 2.500000 ^ 2 = 6.25
Sum = 17.500000
1/length = 0.166667
Result / length = 2.916667
https://dotnetfiddle.net/02r3qG
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 =
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