Skip to main content
Fixed bug that was introduced
Source Link

or Update: Added (DividendGroup.Tele, _) -> 0 to match original implementation

let dividendQuarter (t : Time) =
    match (c.DividendGroup, Time.month t) with
    | (DividendGroup.Tele, 3) -> 4
    | (DividendGroup.Tele, 6) -> 1
    | (DividendGroup.Tele, 9) -> 2
    | (DividendGroup.Tele, 12) -> 3
    | (_, 2) -> 4
    | (_, 5) -> 1
    | (_DividendGroup.Tele, 8) -> 2
    | (_, 11) -> 3
    | _  -> 0

Update: or even

let dividendQuarter (t : Time) =
    match (c.DividendGroup, Time.month t) with
    | (DividendGroup.Tele, 3) | (_, 2) -> 4
    | (DividendGroup.Tele, 6) | (_, 5) -> 1
    | (DividendGroup.Tele, 9) | (_, 8) -> 2
    | (DividendGroup.Tele, 12) | (_, 11) -> 3
    | _  -> 0

or

let dividendQuarter (t : Time) =
    match (c.DividendGroup, Time.month t) with
    | (DividendGroup.Tele, 3) -> 4
    | (DividendGroup.Tele, 6) -> 1
    | (DividendGroup.Tele, 9) -> 2
    | (DividendGroup.Tele, 12) -> 3
    | (_, 2) -> 4
    | (_, 5) -> 1
    | (_, 8) -> 2
    | (_, 11) -> 3
    | _  -> 0

Update: or even

let dividendQuarter (t : Time) =
    match (c.DividendGroup, Time.month t) with
    | (DividendGroup.Tele, 3) | (_, 2) -> 4
    | (DividendGroup.Tele, 6) | (_, 5) -> 1
    | (DividendGroup.Tele, 9) | (_, 8) -> 2
    | (DividendGroup.Tele, 12) | (_, 11) -> 3
    | _  -> 0

or Update: Added (DividendGroup.Tele, _) -> 0 to match original implementation

let dividendQuarter (t : Time) =
    match (c.DividendGroup, Time.month t) with
    | (DividendGroup.Tele, 3) -> 4
    | (DividendGroup.Tele, 6) -> 1
    | (DividendGroup.Tele, 9) -> 2
    | (DividendGroup.Tele, 12) -> 3
    | (DividendGroup.Tele, _) -> 0
    | (_, 2) -> 4
    | (_, 5) -> 1
    | (_, 8) -> 2
    | (_, 11) -> 3
    | _  -> 0
Added another version of the match expression
Source Link

Update: or even

let dividendQuarter (t : Time) =
    match (c.DividendGroup, Time.month t) with
    | (DividendGroup.Tele, 3) | (_, 2) -> 4
    | (DividendGroup.Tele, 6) | (_, 5) -> 1
    | (DividendGroup.Tele, 9) | (_, 8) -> 2
    | (DividendGroup.Tele, 12) | (_, 11) -> 3
    | _  -> 0

according to taste.

according to taste.

Update: or even

let dividendQuarter (t : Time) =
    match (c.DividendGroup, Time.month t) with
    | (DividendGroup.Tele, 3) | (_, 2) -> 4
    | (DividendGroup.Tele, 6) | (_, 5) -> 1
    | (DividendGroup.Tele, 9) | (_, 8) -> 2
    | (DividendGroup.Tele, 12) | (_, 11) -> 3
    | _  -> 0

according to taste.

Source Link

While this does not directly address the issue of how to solve the larger problem with refactoring, reducing the amount and complexity of code should make it simpler to do that. Here are a couple of suggestions on how to do this (I don't have an F# compiler handy so please excuse any errors).

I would change

let dividendQuarter (t : Time) =
    let currMonth = Time.month t
    match c.DividendGroup with
    | DividendGroup.Tele -> 
        if currMonth = 3 then 4
        else if currMonth = 6 then 1
        else if currMonth = 9 then 2
        else if currMonth = 12 then 3
        else 0
    | _ -> 
        if currMonth = 2 then 4
        else if currMonth = 5 then 1
        else if currMonth = 8 then 2
        else if currMonth = 11 then 3
        else 0

to

let dividendQuarter (t : Time) =
    match c.DividendGroup with
    | DividendGroup.Tele ->
        match Time.month t with
        | 3 -> 4
        | 6 -> 1
        | 9 -> 2
        | 12 -> 3
        | _ -> 0
    | _ ->
        match Time.month t with
        | 2 -> 4
        | 5 -> 1
        | 8 -> 2
        | 11 -> 3
        | _ -> 0

or

let dividendQuarter (t : Time) =
    match (c.DividendGroup, Time.month t) with
    | (DividendGroup.Tele, 3) -> 4
    | (DividendGroup.Tele, 6) -> 1
    | (DividendGroup.Tele, 9) -> 2
    | (DividendGroup.Tele, 12) -> 3
    | (_, 2) -> 4
    | (_, 5) -> 1
    | (_, 8) -> 2
    | (_, 11) -> 3
    | _  -> 0

according to taste.


You have a number of functions with the same pattern, for example:

 let openingBalanceShareCapital  = 
            memoise2 (fun closingBalanceShareCapital (t : Time) ->
                if (t - 1).IsForecast then
                    closingBalanceShareCapital
                else
                    - balanceSheet.ShareCapital (t - 1) 
                    - balanceSheet.SharePremium (t - 1)
            ) 

I would change those to something like this (maybe this idea can be applied in other areas as well):

let opening balance t =
    let transformed =
        memoise2 (fun closing (t : Time) ->
            if (t - 1).IsForecast then
                closing
            else
                balance t
        )
    transformed
    
let balanceCash t =
    balanceSheet.Cash (t - 1)

let alanceIntercompanyDebt t =
    balanceSheet.IntercompanyLoan (t - 1) 

let alanceRetainedEarnings t =
    - balanceSheet.RetainedEarnings (t - 1) 

let balanceShareCapital t =
    - balanceSheet.ShareCapital (t - 1) - balanceSheet.SharePremium (t - 1)

let openingBalanceCash = opening balanceCash t
let openingBalanceIntercompanyDebt = opening alanceIntercompanyDebt t
let openingBalanceRetainedEarnings = opening alanceRetainedEarnings t
let openingBalanceShareCapital = opening balanceShareCapital t

With regards to Company, IntercoTimeSeries and DividendTrappedCashSolver, you could put them in a single record, reducing the amount of parameters you have to pass around.