|
|
|
|
|
by ryandv
223 days ago
|
|
XIRR is laughably trivial with automatic differentiation in Haskell. Take as many iterations from the resulting [Double] as desired: type Cashflow = (Text, Day, Double)
irr :: V.Vector Cashflow -> [Double]
irr = fmap (flip findZero 0.01) npv
npv :: V.Vector Cashflow -> (forall s. AD s ForwardDouble -> AD s ForwardDouble)
npv cashflows = sum . flip discountedCashflows cashflows
where
discountedCashflows :: forall s. AD s ForwardDouble -> V.Vector Cashflow -> V.Vector (AD s ForwardDouble)
discountedCashflows = fmap . presentValue
presentValue :: forall s. AD s ForwardDouble -> Cashflow -> AD s ForwardDouble
presentValue r (_,t,cf) = auto cf / ( (1 + r) ** numCompoundingPeriods t)
numCompoundingPeriods t = (fromRational . toRational $ diffDays t t0) / 365.0
t0 = maybe (toEnum 0) viewInvestmentDate $ cashflows V.!? 0
viewInvestmentDate = view _2
|
|