packages feed

Hastructure 0.45.3 → 0.50.0

raw patch · 6 files changed

+34/−21 lines, 6 filesdep ~basedep ~lensdep ~template-haskellPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: base, lens, template-haskell

API changes (from Hackage documentation)

Files

CHANGELOG.md view
@@ -2,6 +2,16 @@  <!-- towncrier release notes start --> +## 0.50.0+### 2025-07-14+* NEW: add `stopBy` in run assumption ,which stop deal run by a list of `Condition`+* NEW: expose `asset level` cashflow ,with a toggle+* NEW: expose `Un-Used Pool cashflow`+* ENHANCE: parameterized the `tweaks`+* ENHANCE: update dependency to accomodate publishment to `Hackage`+* FIX: enable `Lease` deal for `Financial reports`++ ## 0.46.4 ### 2025-06-10 * ENHANCE: add error message when calculation IRR for bond with non cashflow
Hastructure.cabal view
@@ -5,7 +5,7 @@ -- see: https://github.com/sol/hpack  name:           Hastructure-version:        0.45.3+version:        0.50.0 synopsis:       Cashflow modeling library for structured finance description:    Please see the README on GitHub at <https://github.com/yellowbean/Hastructure#readme> category:       StructuredFinance,Securitisation,Cashflow@@ -76,11 +76,11 @@       src   build-depends:     Decimal >= 0.5.2 && < 0.6,-    base >= 4.18.0 && < 4.20,+    base >= 4.18.0 && < 4.21,     deepseq >= 1.5.1 && < 1.6,     MissingH >= 1.6.0 && < 1.7,     containers >= 0.6.8 && < 0.7,-    template-haskell >= 2.20.0 && < 2.22,+    template-haskell >= 2.20.0 && < 2.21.1.0,     bytestring >= 0.12.1 && < 0.13,     exceptions >= 0.10.7 && < 0.11,     mtl >= 2.3.1 && < 2.4,@@ -99,7 +99,7 @@     generic-lens >= 2.2.2 && < 2.3,     http-types >= 0.12.4 && < 0.13,     ieee754 >= 0.8.0 && < 0.9,-    lens >= 5.2.3 && < 5.3.5,+    lens >= 5.2.3 && < 5.3.6,     parallel >= 3.2.2 && < 3.3,     math-functions >= 0.3.4 && < 0.4,     monad-loops >= 0.4.3 && < 0.5,
app/Main.hs view
@@ -104,7 +104,7 @@   version1 :: Version -version1 = Version "0.46.4"+version1 = Version "0.50.0"   wrapRun :: [D.ExpectReturn] -> DealType -> Maybe AP.ApplyAssumptionType -> AP.NonPerfAssumption -> RunResp
src/Cashflow.hs view
@@ -25,10 +25,10 @@                 ,mergeCf,buildStartTsRow                 ,txnCumulativeStats,consolidateCashFlow, cfBeginStatus, getBegBalCashFlowFrame                 ,splitCashFlowFrameByDate, mergePoolCf2, buildBegBal, extendCashFlow, patchBalance-		,splitPoolCashflowByDate+                ,splitPoolCashflowByDate                 ,getAllDatesCashFlowFrame,splitCf, cutoffCashflow-		,AssetCashflow,PoolCashflow-		,emptyCashflow,isEmptyRow2+                ,AssetCashflow,PoolCashflow+                ,emptyCashflow,isEmptyRow2                 ) where  import Data.Time (Day)@@ -269,23 +269,23 @@       (ls,rs) = splitByDate txns d st       newStatus = case rs of                      [] -> (0, d, Nothing)-                    (r:_) -> (mflowBegBalance r, d, Nothing)+                    (r:_) -> (buildBegBal rs, d, Nothing)     in        (CashFlowFrame status ls,CashFlowFrame newStatus rs) + splitPoolCashflowByDate :: PoolCashflow -> Date -> SplitType -> (PoolCashflow,PoolCashflow) splitPoolCashflowByDate (poolCF, mAssetCfs) d st   = let        (lPoolCF,rPoolCF) = splitCashFlowFrameByDate poolCF d st       mAssetSplited = (\xs -> [ splitCashFlowFrameByDate x d st | x <- xs ]) <$> mAssetCfs       assetCfs = (\xs -> [ (lCf, rCf) | (lCf,rCf) <- xs ]) <$> mAssetSplited -      lAssetCfs = (\xs -> fst <$> xs ) <$> assetCfs-      rAssetCfs = (\xs -> snd <$> xs ) <$> assetCfs+      lAssetCfs = (fst <$>) <$> assetCfs+      rAssetCfs = (snd <$>) <$> assetCfs     in        ((lPoolCF, lAssetCfs) , (rPoolCF, rAssetCfs))  - getTxnLatestAsOf :: CashFlowFrame -> Date -> Maybe TsRow getTxnLatestAsOf (CashFlowFrame _ txn) d = L.find (\x -> getDate x <= d) $ reverse txn @@ -425,7 +425,7 @@  buildBegBal :: [TsRow] -> Balance buildBegBal [] = 0-buildBegBal (x:_) = mflowBegBalance x+buildBegBal (x:xs) = mflowBegBalance x   sumTs :: [TsRow] -> Date -> TsRow
src/Deal.hs view
@@ -1020,15 +1020,16 @@         let poolFlowUsedNoEmpty = Map.map  	                            (over CF.cashflowTxn CF.dropTailEmptyTxns)  	                            (getAllCollectedFrame finalDeal Nothing)+        let poolFlowUnUsed = osPoolFlow & mapped . _1 . CF.cashflowTxn %~ CF.dropTailEmptyTxns+		                        & mapped . _2 . _Just . each . CF.cashflowTxn %~ CF.dropTailEmptyTxns         bndPricing <- case mPricing of                          (Just p) -> priceBonds finalDeal p                          Nothing -> Right Map.empty         return (finalDeal                  , poolFlowUsedNoEmpty-                 , getRunResult finalDeal ++ V.validateRun finalDeal ++ DL.toList (DL.append logs (unCollectedPoolFlowWarning osPoolFlow))+                 , getRunResult finalDeal ++ V.validateRun finalDeal ++ DL.toList (DL.append logs (unCollectedPoolFlowWarning poolFlowUnUsed)) 		 , bndPricing-	         , osPoolFlow & mapped . _1 . CF.cashflowTxn %~ CF.dropTailEmptyTxns-		              & mapped . _2 . _Just . each . CF.cashflowTxn %~ CF.dropTailEmptyTxns+	         , poolFlowUnUsed 	       ) -- `debug` ("run deal done with pool" ++ show poolFlowUsedNoEmpty)     where       (runFlag, valLogs) = V.validateReq t nonPerfAssumps @@ -1038,9 +1039,11 @@                         Nothing -> Nothing                         Just (AP.AvailableAssets rp rperf) -> Just (Map.fromList [("Consol", (rp, rperf))])                         Just (AP.AvailableAssetsBy rMap) -> Just rMap-      -- TODO: need to add warning if uncollected pool flow is not empty-      unCollectedPoolFlowWarning pMap = if sum (Map.elems (Map.map (CF.sizeCashFlowFrame . view _1) pMap)) > 0 then -                                          DL.singleton $ WarningMsg "Oustanding pool cashflow hasn't been collected yet"+      unCollectedPoolFlowWarning pMap = let+                                           countMap = Map.map (CF.sizeCashFlowFrame . view _1) pMap +                                        in +					  if sum (Map.elems countMap) > 0 then +                                          DL.singleton $ WarningMsg $ "Oustanding pool cashflow hasn't been collected yet"++ show countMap                                         else 					  DL.empty 
src/Deal/DealAction.hs view
@@ -573,7 +573,7 @@                                   boughtCfDates = getDate <$> view CF.cashflowTxn cfBought                                    newAggDates = case (dsInterval,boughtCfDates) of                                                    ([],[]) -> []-                                                  (_,[]) -> [] -- `debug` ("hit with non cash date from bought"++ show dsInterval) +                                                  (_,[]) -> []                                                   ([],_) -> boughtCfDates                                                   (oDs,bDs) ->                                                      let @@ -584,7 +584,7 @@                                                         []                                                       else                                                          sliceDates (SliceAfter lastOdate) bDs-+                                  -- TODO: the cfOrigin may not have correct beg balance ,which doesn't match all the amortization of cashflow txn                                   mergedCf = CF.mergePoolCf2 cfOrigin cfBought                                  in                                    ((over CF.cashflowTxn (`CF.aggTsByDates` (dsInterval ++ newAggDates)) mergedCf), (++ [cfBought]) <$> mAflow)