Seq.sumBy vs Seq.groupBy

Viewed 86

I am trying to convert some pieces of C# code to F# in order to practice. While doing so, I stumbled on a position calculation. The logic is to group by counterparty and security and sum algebraically the nominal in order to calculate the position.

let position instance =
        portfolio
        |> Seq.filter (isActive instance)
        |> Seq.groupBy (fun trade -> trade.Counterparty, trade.Bond)
        |> Seq.map (fun ((cp, bond), trades) -> cp, bond.Isin, trades |> Seq.sumBy (fun t -> t.Nominal))

The pipeline above produces the expected outcome but it feels like that it could be simplified a bit. That's what I would have done in C#, filter, group and then project it by either using an anonymous type or creating a DTO and using that.

Counterparty Bond Position
A FR100 100
A DE100 -100
B FR100 200
C DE100 100

Setting up the example:

type Bond = {Isin : string; Maturity : DateTime; Price : float}
type Trade = {Bond: Bond; Nominal : float; Counterparty : string}
let french = {Isin = "FR100"; Maturity = DateTime(2021,12,31); Price = 122.2}
let deutch = {Isin = "DE100"; Maturity = DateTime(2021,12,31); Price = 100.2}
let expired = {Isin = "XX100"; Maturity = DateTime(2020,12,31); Price = 111.2}
let one = {Bond= expired; Nominal = 199.0; Counterparty = "A"}
let two = {Bond= expired; Nominal = 200.0; Counterparty = "B"}
let three = {Bond= french; Nominal = 100.0; Counterparty = "A"}
let four = {Bond= french; Nominal = 200.0; Counterparty = "B"}
let five = {Bond= deutch; Nominal = 100.0; Counterparty = "A"}
let six = {Bond= deutch; Nominal = -200.0; Counterparty = "A"}
let seven = {Bond= deutch; Nominal = 100.0; Counterparty = "C"}
let portfolio = [|one;two;three;four;five;six;seven|]

let instrumentHasMatured instance bond = bond.Maturity < instance
let isActive instance trade = not (instrumentHasMatured instance trade.Bond)
0 Answers
Related