F#: Discriminated Unions

March 10th, 2010 / Tales from a Trading Desk

I’ve managed to move on somewhat with my F# Market Risk Proof Of Concept (POC). I’ve attached some of the code below. The issue I ran into last night and this morning during train travel was with discriminated unions – which I use for the legs of the trade. As is normal these days, a quick google provided me with the solution I’d been missing. The pattern matching on object type is quite nice.

I’m hoping to be able to use the Parallel LINQ support via F# PowerPack to calculate the cashflows, and pay move from lists to seq.

You’ll notice I am now using [] in the code, since I have multiple files which means you need to be aware of the project file order. Once I get the cashflows generating I’ll look at fsunit

type TradeHeader =
    {
        TradeDate : DateTime;
    }

type Period =
    {
        PeriodMultiplier : int;
        Period : string;
    }

type CalculationPeriodDates =
    {
        EffectiveDate : DateTime;
        TerminationDate : DateTime;
        CalculationPeriodFrequency : Period;
    }

type PaymentDates =
    {
        PaymentFrequency : Period;
    }

type NonNegativeAmountSchedule =
    {
        InitialValue : double;
        Currency : string;
    }

type Notional =
    {
        NotionalStepSchedule : NonNegativeAmountSchedule;
    }

type FloatingRateCalculation =
    {
        FloatingRateIndex : string;
        IndexTenor : Period;
    }

type FixedRateSchedule =
    {
        InitialValue : double;
    }

type RateCalculation = | Floating of FloatingRateCalculation | Fixed of FixedRateSchedule

type Calculation =
    {
        NotionalSchedule : Notional;
        RateCalculation : RateCalculation;
        DayCountFraction : string;
    }

type CalculationPeriodAmount =
    {
        Calculation : Calculation;
    }

type InterestRateStream =
    {
        CalculationPeriodDates : CalculationPeriodDates;
        PaymentDates : PaymentDates;
        CalculationPeriodAmount : CalculationPeriodAmount;
    }

type Trade =
    {
        Id : int;
        Header : TradeHeader;
        SwapStream: List<InterestRateStream>;
    }

let createTrade (id : int) =
    let effectiveDate = new DateTime(2010,1,1)
    let termDate = new DateTime(2015,1,1)
    let calcPeriod =  {PeriodMultiplier = 6; Period = "M";}
    let payments = { PeriodMultiplier =6; Period= "M"}
    let calPeriodDates = {EffectiveDate=effectiveDate; TerminationDate=termDate; CalculationPeriodFrequency=calcPeriod;}

    let initVal = {InitialValue=100000000.00;}
    let calPeriodAmt = {Calculation={NotionalSchedule={NotionalStepSchedule={InitialValue=100000000.00;Currency="GBP";};};
                            RateCalculation=Fixed(initVal);DayCountFraction="30E/360";}}
    let pay = {CalculationPeriodDates=calPeriodDates;PaymentDates={PaymentFrequency=payments;};CalculationPeriodAmount=calPeriodAmt;}

    let floater = {FloatingRateIndex="USD-LIBOR";IndexTenor=calcPeriod;}
    let calPeriodAmt = {Calculation={NotionalSchedule={NotionalStepSchedule={InitialValue=100000000.00;Currency="GBP";};};
                            RateCalculation=Floating(floater);DayCountFraction="ACT/360";}}
    let receive = {CalculationPeriodDates=calPeriodDates;PaymentDates={PaymentFrequency=payments;};CalculationPeriodAmount=calPeriodAmt;}

    let trade = {Id=id; Header={TradeDate=DateTime.Now;};SwapStream=[pay;receive;]}
    trade

let generateFixedCashflows(fixedLeg:FixedRateSchedule, trade:Trade, valueDate:DateTime) =
    // Calculate Dates
    0.0

let generateCashflow(stream:InterestRateStream, trade:Trade, valueDate:DateTime) =
    match (stream.CalculationPeriodAmount.Calculation.RateCalculation) with
    | Fixed(f) ->
        printfn "Fixed Leg of %A" trade.Id
        generateFixedCashflows(f, trade, valueDate)
    | Floating(fl) ->
        printfn "Float Leg of %A" trade.Id
        0.5

let main =
    let valueDate = new DateTime(2010,1,1)
    let trade  = createTrade 101
    let cashFlows =
        trade.SwapStream |> List.sumBy (fun x -> generateCashflow(x,trade, valueDate))

    let pay =  Seq.head trade.SwapStream
    Console.ReadLine()
    0

[<EntryPoint>]
main

Comments are closed.