Skip to content

Commit b4f1e97

Browse files
authored
Sep25 Release (#302)
* add: ended status with maybe date * use DL for loan * expose reverse in pay order in group * refactor: de-size deal.hs * separate deal collection * factor out projected flow * fix Wac of combine two row * fix bug/amort rate size * remove schedule cashflow * include gadt-th * update README * payable & drawable * fix credit support * Bugfix: update oustanding pool flow after waterfall action * fix bug in pricing IRR * enhance the map lookup * update :price bond with Either * fix flow on projectedCashflow * fix int when buy a bond in future * fix recovery assumption * Add assumption validation * minor fix on stress prepay/default * fix hackage action * add accrue type waterfall * fix genericDates/Accrued * refactor on credit type on liquidity provider * Refactor pay/writeoff on expenses * remove fundWith in liability * use pay/write in liabilities * validate Fees 01 * new q: activeBondNum * use DuePrin * add traversal fn to bond map * include Hermite Interplotion * include new predicate of fee type * remove auto accrue * minor fix: lift error in mannual fire trigger
1 parent 014cb77 commit b4f1e97

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

62 files changed

+4377
-3448
lines changed

.github/workflows/docker-image.yml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ jobs:
4141
matrix:
4242
os: [ubuntu-latest, macOS-latest, windows-latest]
4343
ghc:
44-
- "9.8.2"
44+
- "9.10.2"
4545
cabal: ["3.10.3.0"]
4646

4747
steps:
@@ -168,6 +168,4 @@ jobs:
168168
- uses: haskell-actions/hackage-publish@v1
169169
with:
170170
hackageToken: ${{ secrets.HACKAGE_KEY }}
171-
packagesPath: ${{ runner.temp }}/packages
172-
docsPath: ${{ runner.temp }}/docs
173171
publish: false

CHANGELOG.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,26 @@
22

33
<!-- towncrier release notes start -->
44

5+
## 0.51.6
6+
### 2025-09-05
7+
* NEW: add new integer formula `activeBondNumber`
8+
* NEW: refactor interpolation pricing curve from `linear` to `Hermite` way
9+
10+
11+
## 0.51.5
12+
### 2025-08-20
13+
* ENHANCE: add assumption validation on `prepayment` `default` `recovery` .
14+
* FIX: pricing IRR: engine will use wrong position when `Buy Bond`
15+
16+
17+
## 0.51.2
18+
### 2025-08-02
19+
* NEW: new asset `ProjectedByFactor` and `ProjectedCashflow` .
20+
* ENHANCE: refactor on waterfall action, throw error when `name` is missing from the deal object
21+
* ENHANCE: throw error when divide by zero
22+
* ENHANCE: refactor on `credit support` for `liquidity suppport`.
23+
* FIX: fix zero cashflow when holding position is too small
24+
525
## 0.50.0
626
### 2025-07-14
727
* NEW: add `stopBy` in run assumption ,which stop deal run by a list of `Condition`

Hastructure.cabal

Lines changed: 14 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@ cabal-version: 3.0
55
-- see: https://github.com/sol/hpack
66

77
name: Hastructure
8-
version: 0.50.2
8+
version: 0.51.6
99
synopsis: Cashflow modeling library for structured finance
10-
description: Please see the README on GitHub at <https://github.com/yellowbean/Hastructure#readme>
10+
description: Please see the README on GitHub at <https://github.com/absbox/Hastructure#readme>
1111
category: StructuredFinance,Securitisation,Cashflow
12-
homepage: https://github.com/yellowbean/Hastructure#readme
13-
bug-reports: https://github.com/yellowbean/Hastructure/issues
12+
homepage: https://github.com/absbox/Hastructure#readme
13+
bug-reports: https://github.com/absbox/Hastructure/issues
1414
author: Xiaoyu
1515
maintainer: always.zhang@gmail.com
1616
copyright: 2025 Xiaoyu, Zhang
@@ -23,7 +23,7 @@ extra-doc-files:
2323
CHANGELOG.md
2424
source-repository head
2525
type: git
26-
location: https://github.com/yellowbean/Hastructure
26+
location: https://github.com/absbox/Hastructure
2727

2828
library
2929
exposed-modules:
@@ -52,6 +52,8 @@ library
5252
Deal.DealMod
5353
Deal.DealQuery
5454
Deal.DealValidation
55+
Deal.DealRun
56+
Deal.DealCollection
5557
Errors
5658
Expense
5759
Hedge
@@ -76,48 +78,42 @@ library
7678
src
7779
build-depends:
7880
Decimal >= 0.5.2 && < 0.6,
79-
base >= 4.18.0 && < 4.21.0,
81+
base >= 4.18.0 && < 4.22.0,
8082
deepseq >= 1.5.0 && < 1.6,
8183
MissingH >= 1.6.0 && < 1.7,
8284
containers >= 0.6.8 && < 0.7.1,
83-
template-haskell >= 2.20.0 && < 2.22.1.0,
85+
template-haskell >= 2.20.0 && < 2.23.1.0,
8486
bytestring >= 0.12.1 && < 0.13,
85-
-- exceptions >= 0.10.7 && < 0.11,
8687
mtl >= 2.3.1 && < 2.4,
87-
time >= 1.12.2 && < 1.13,
88+
time >= 1.12.2 && < 1.15,
8889
text >= 2.1.1 && < 2.2,
8990
regex-base >= 0.94.0 && < 0.95,
9091
aeson >= 2.2.3 && < 2.3,
92+
aeson-gadt-th >= 0.2.5.4 && < 0.3,
9193
hashable >= 1.4.7 && < 1.5.1,
9294
dlist >= 1.0 && < 1.1,
9395
scientific >= 0.3.8 && < 0.4,
9496
vector >= 0.13.2 && < 0.14,
9597
aeson-pretty >= 0.8.10 && < 0.9,
9698
base-compat >= 0.13.0 && < 0.15,
97-
attoparsec >= 0.14.4 && < 0.15,
98-
attoparsec-aeson >= 2.2.2 && < 2.3,
99-
generic-lens >= 2.2.2 && < 2.3,
100-
http-types >= 0.12.4 && < 0.13,
101-
-- ieee754 >= 0.8.0 && < 0.9,
10299
lens >= 5.2.3 && < 5.3.6,
103100
parallel >= 3.2.2 && < 3.3,
104101
math-functions >= 0.3.4 && < 0.4,
105102
monad-loops >= 0.4.3 && < 0.5,
106103
numeric-limits >= 0.1.0 && < 0.2,
107104
openapi3 >= 3.2.4 && < 3.3,
108105
regex-pcre-builtin >= 0.95.2 && < 0.96,
109-
-- regex-tdfa >= 1.3.2 && < 1.4,
110106
servant >= 0.20.2 && < 0.21,
111107
servant-openapi3 >= 2.0.1 && < 2.1,
112108
servant-server >= 0.20.2 && < 0.21,
113109
wai >= 3.2.4 && < 3.3,
114110
warp >= 3.4.7 && < 3.5,
115111
split >= 0.2.5 && < 0.3,
116112
string-conversions >= 0.4.0 && < 0.5,
117-
swagger2 >= 2.8.9 && < 2.9,
118113
tabular >= 0.2.2 && < 0.3,
119114
wai-cors >= 0.2.7 && < 0.3,
120115
yaml >= 0.11.11 && < 0.12,
116+
interpolation
121117

122118

123119
default-language: Haskell2010
@@ -135,13 +131,12 @@ executable Hastructure-exe
135131
build-depends:
136132
Hastructure,
137133
Decimal,
138-
base >= 4.18.0 && < 4.21.0,
134+
base,
139135
deepseq,
140136
MissingH,
141137
containers,
142138
template-haskell,
143139
bytestring,
144-
exceptions,
145140
mtl,
146141
time,
147142
text,
@@ -153,14 +148,9 @@ executable Hastructure-exe
153148
vector,
154149
aeson-pretty,
155150
base-compat,
156-
attoparsec,
157-
attoparsec-aeson,
158-
generic-lens,
159-
http-types,
160151
lens,
161152
parallel,
162153
math-functions,
163-
monad-loops,
164154
numeric-limits,
165155
openapi3,
166156
regex-pcre-builtin,
@@ -171,7 +161,6 @@ executable Hastructure-exe
171161
warp,
172162
split,
173163
string-conversions,
174-
swagger2,
175164
tabular,
176165
wai-cors,
177166
yaml,
@@ -214,13 +203,12 @@ test-suite Hastructure-test
214203
build-depends:
215204
Hastructure,
216205
Decimal,
217-
base >= 4.18.0 && < 4.21,
206+
base,
218207
deepseq,
219208
MissingH,
220209
containers,
221210
template-haskell,
222211
bytestring,
223-
exceptions,
224212
mtl,
225213
time,
226214
text,
@@ -232,14 +220,9 @@ test-suite Hastructure-test
232220
vector,
233221
aeson-pretty,
234222
base-compat,
235-
attoparsec,
236-
attoparsec-aeson,
237-
generic-lens,
238-
http-types,
239223
lens,
240224
parallel,
241225
math-functions,
242-
monad-loops,
243226
numeric-limits,
244227
openapi3,
245228
regex-pcre-builtin,
@@ -250,7 +233,6 @@ test-suite Hastructure-test
250233
warp,
251234
split,
252235
string-conversions,
253-
swagger2,
254236
tabular,
255237
wai-cors,
256238
yaml,

README.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
[![Actions Status](https://github.com/yellowbean/Hastructure/workflows/Haskell%20CI/badge.svg)](https://github.com/yellowbean/Hastructure/actions)
2-
[![Docker Build](https://img.shields.io/docker/v/yellowbean/hastructure?color=green&label=docker)](https://hub.docker.com/r/yellowbean/hastructure)
3-
[![Pulls from DockerHub](https://img.shields.io/docker/pulls/yellowbean/hastructure.svg)](https://hub.docker.com/r/yellowbean/hastructure)
1+
[![Actions Status](https://github.com/absbox/Hastructure/workflows/Haskell%20CI/badge.svg)](https://github.com/absbox/Hastructure/actions)
2+
[![Docker Build](https://img.shields.io/docker/v/absbox/hastructure?color=green&label=docker)](https://hub.docker.com/r/absbox/hastructure)
3+
[![Pulls from DockerHub](https://img.shields.io/docker/pulls/absbox/hastructure.svg)](https://hub.docker.com/r/absbox/hastructure)
44
![Hackage Version](https://img.shields.io/hackage/v/Hastructure)
55

66

@@ -27,18 +27,18 @@
2727

2828
* :snake: [Python wrapper](https://github.com/yellowbean/PyABS) is in ``Beta`` now !
2929
* :coffee: Easy integration with ``Java/C#/C++/JavaScript/Python`` with ``RESTful`` interface and Docker image are ready.
30-
* C/Java : [here](https://github.com/yellowbean/Hastructure/issues/106)
30+
* C/Java : [here](https://github.com/absbox/Hastructure/issues/106)
3131

3232
### Documentation
3333

3434
* see what `Hastructure` is capable of -> [Here](https://absbox-doc.readthedocs.io/en/latest/)
35-
* [Where is `Hastructure` doc ? ](https://github.com/yellowbean/Hastructure/wiki/Where-is-documentation-of-Hastructure-%3F)
35+
* [Where is `Hastructure` doc ? ](https://github.com/absbox/Hastructure/wiki/Where-is-documentation-of-Hastructure-%3F)
3636

3737
### Features
3838
* Integration
3939
* Built-in REST API services
4040
* Language independent, integration friendly.
41-
* Swagger -> [here](https://github.com/yellowbean/Hastructure/blob/master/swagger.json)
41+
* Swagger -> [here](https://github.com/absbox/Hastructure/blob/master/swagger.json)
4242
* Public server status -> [here](https://absbox.org)
4343
* Docker Support
4444
* Asset class coverage (Mortgage/Student Loan/Auto Loan/Rentals/Corp Loan/Consumer Installment)
@@ -94,4 +94,4 @@ The demo only cover very limit features of this engine and subject to UI perform
9494

9595

9696
### Others
97-
* [Why yet another cashflow engine](https://github.com/yellowbean/Hastructure/wiki/Why-Yet-Anohter-Cashflow-Engine)
97+
* [Why yet another cashflow engine](https://github.com/absbox/Hastructure/wiki/Why-Yet-Anohter-Cashflow-Engine)

app/Main.hs

Lines changed: 16 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
11
{-# LANGUAGE DataKinds #-}
22
{-# LANGUAGE DeriveGeneric #-}
33
{-# LANGUAGE FlexibleInstances #-}
4-
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
54
{-# LANGUAGE MultiParamTypeClasses #-}
65
{-# LANGUAGE RankNTypes #-}
76
{-# LANGUAGE ScopedTypeVariables #-}
87
{-# LANGUAGE TypeOperators #-}
9-
{-# LANGUAGE TypeApplications #-}
10-
{-# LANGUAGE TemplateHaskell #-}
118
{-# LANGUAGE OverloadedStrings #-}
129
{-# LANGUAGE TypeFamilies #-}
1310
{-# LANGUAGE AllowAmbiguousTypes #-}
@@ -18,7 +15,6 @@ module Main
1815
import Prelude ()
1916
import Prelude.Compat
2017
import System.Environment
21-
import Control.Monad.Catch (MonadCatch, MonadThrow (..))
2218
import Control.Monad.IO.Class (liftIO)
2319
import Control.Monad (mapM)
2420
import Control.Exception (Exception,throwIO,throw)
@@ -28,7 +24,7 @@ import Data.Aeson
2824
import Data.Aeson.Types
2925
import Data.Aeson.TH
3026
import Data.Aeson.Encode.Pretty (encodePretty)
31-
import Data.Attoparsec.ByteString
27+
-- import Data.Attoparsec.ByteString
3228
import Data.ByteString (ByteString)
3329
import Data.List
3430
import Data.Map
@@ -50,9 +46,9 @@ import qualified Data.ByteString.Char8 as BS
5046
import Network.Wai
5147
import Network.Wai.Handler.Warp
5248
import Network.Wai.Middleware.Cors
53-
import qualified Data.Aeson.Parser
49+
-- import qualified Data.Aeson.Parser
5450
import Language.Haskell.TH
55-
import Network.HTTP.Types.Status
51+
--import Network.HTTP.Types.Status
5652
import Servant.OpenApi
5753
import Servant
5854
import Servant.Types.SourceT (source)
@@ -104,7 +100,7 @@ debug = flip Debug.Trace.trace
104100

105101

106102
version1 :: Version
107-
version1 = Version "0.50.2"
103+
version1 = Version "0.51.6"
108104

109105

110106
wrapRun :: [D.ExpectReturn] -> DealType -> Maybe AP.ApplyAssumptionType -> AP.NonPerfAssumption -> RunResp
@@ -141,14 +137,14 @@ wrapRun fs (PDeal d) mAssump mNonPerfAssump
141137
(_d,_pflow,_rs,_p, _osPflow) <- D.runDeal d (S.fromList fs) mAssump mNonPerfAssump
142138
return (PDeal _d,_pflow,_rs,_p,_osPflow)
143139

144-
wrapRun _ x _ _ = Left $ "RunDeal Failed ,due to unsupport deal type "++ show x
145140

146141
patchCumulativeToPoolRun :: RunPoolTypeRtn_ -> RunPoolTypeRtn_
147142
patchCumulativeToPoolRun
148143
= Map.map
149144
(\(CF.CashFlowFrame _ txns,mAssetFlow) ->
150145
(CF.CashFlowFrame (0,Lib.toDate "19000101",Nothing) (CF.patchCumulative (0,0,0,0,0,0) [] txns),mAssetFlow))
151146

147+
-- flag -> breakdown flag
152148
wrapRunPoolType :: Bool -> PoolTypeWrap -> Maybe AP.ApplyAssumptionType -> Maybe [RateAssumption] -> RunPoolTypeRtn
153149
wrapRunPoolType flag (MPool pt) assump mRates = D.runPoolType flag pt assump $ Just (AP.NonPerfAssumption{AP.interest = mRates})
154150
wrapRunPoolType flag (LPool pt) assump mRates = D.runPoolType flag pt assump $ Just (AP.NonPerfAssumption{AP.interest = mRates})
@@ -158,22 +154,21 @@ wrapRunPoolType flag (FPool pt) assump mRates = D.runPoolType flag pt assump $ J
158154
wrapRunPoolType flag (VPool pt) assump mRates = D.runPoolType flag pt assump $ Just (AP.NonPerfAssumption{AP.interest = mRates})
159155
wrapRunPoolType flag (PPool pt) assump mRates = D.runPoolType flag pt assump $ Just (AP.NonPerfAssumption{AP.interest = mRates})
160156
wrapRunPoolType flag (UPool pt) assump mRates = D.runPoolType flag pt assump $ Just (AP.NonPerfAssumption{AP.interest = mRates})
161-
wrapRunPoolType flag x _ _ = Left $ "RunPool Failed ,due to unsupport pool type "++ show x
162157

163158

164159
wrapRunAsset :: RunAssetReq -> RunAssetResp
165160
wrapRunAsset (RunAssetReq d assets Nothing mRates Nothing)
166161
= do
167-
cfs <- sequenceA $ (\a -> MA.calcAssetUnion a d mRates) <$> assets
162+
cfs <- traverse (\a -> MA.calcAssetUnion a d mRates) assets
168163
return (fst (P.aggPool Nothing [(cf,Map.empty) | cf <- cfs]), Nothing)
169164
wrapRunAsset (RunAssetReq d assets (Just (AP.PoolLevel assumps)) mRates Nothing)
170165
= do
171-
cfs <- sequenceA $ (\a -> MA.projAssetUnion a d assumps mRates) <$> assets
166+
cfs <- traverse (\a -> MA.projAssetUnion a d assumps mRates) assets
172167
return (fst (P.aggPool Nothing [(cf,Map.empty) | (cf,_) <- cfs]) , Nothing)
173168
wrapRunAsset (RunAssetReq d assets (Just (AP.PoolLevel assumps)) mRates (Just pm))
174169
= do
175-
cfs <- sequenceA $ (\a -> MA.projAssetUnion a d assumps mRates) <$> assets
176-
pricingResult <- sequenceA $ (\a -> D.priceAssetUnion a d pm assumps mRates) <$> assets
170+
cfs <- traverse (\a -> MA.projAssetUnion a d assumps mRates) assets
171+
pricingResult <- traverse (\a -> D.priceAssetUnion a d pm assumps mRates) assets
177172
let (assetCf,_) = P.aggPool Nothing cfs
178173
return (assetCf , Just pricingResult)
179174

@@ -213,12 +208,11 @@ runAsset req = return $ wrapRunAsset req
213208
runPool :: RunPoolReq -> Handler PoolRunResp
214209
runPool (SingleRunPoolReq f pt passumption mRates)
215210
= return $
216-
patchCumulativeToPoolRun <$> (wrapRunPoolType f pt passumption mRates)
211+
patchCumulativeToPoolRun <$> wrapRunPoolType f pt passumption mRates
217212

218213
runPoolScenarios :: RunPoolReq -> Handler (Map.Map ScenarioName PoolRunResp)
219214
runPoolScenarios (MultiScenarioRunPoolReq f pt mAssumps mRates)
220-
= return $ Map.map (\assump ->
221-
patchCumulativeToPoolRun <$> (wrapRunPoolType f pt (Just assump) mRates))
215+
= return $ Map.map (\assump -> patchCumulativeToPoolRun <$> wrapRunPoolType f pt (Just assump) mRates)
222216
mAssumps
223217

224218
runDeal :: RunDealReq -> Handler RunResp
@@ -407,7 +401,7 @@ evalRootFindStop (BalanceFormula ds targetBal) (dt,collectedFlow,logs,_,osPflow)
407401
Just (EndRun (Just d) _ ) -> d
408402
Nothing -> case queryClosingDate dt of
409403
Right d' -> d'
410-
Left err -> error $ "Error in BalanceFormula: " ++ err
404+
Left err -> error $ "Error in BalanceFormula: " ++ err
411405
v = case queryDealType dt _date (Q.patchDateToStats _date ds) of
412406
Right v' -> fromRational v'
413407
Left err -> error $ "Error in BalanceFormula: " ++ err
@@ -433,13 +427,12 @@ runRootFinderBy (RootFinderReq req@(dt,Just assumps,nonPerfAssump@AP.NonPerfAssu
433427
def = RiddersParam { riddersMaxIter = itertimes, riddersTol = RelTol 0.000001}
434428
riddersFn = case tweak of
435429
SplitFixedBalance _ _ (l,h) -> ridders def (min h 0.99, max l 0.00001)
436-
StressPoolDefault (l,h) -> ridders def (h ,max l 0.00)
437-
StressPoolPrepayment (l,h) -> ridders def (h ,max l 0.00)
438-
MaxSpreadTo _ (l,h) -> ridders def (h ,max l 0.00)
439-
_ -> error ("Unsupported tweak for root finder" ++ show tweak)
430+
StressPoolDefault (l,h) -> ridders def (h ,max l 0.00)
431+
StressPoolPrepayment (l,h) -> ridders def (h ,max l 0.00)
432+
MaxSpreadTo _ (l,h) -> ridders def (h ,max l 0.00)
440433
in
441434
case riddersFn (rootFindAlgo req tweak stop) of
442-
Root r -> Right $ RFResult r (doTweak r tweak req)
435+
Root r -> return $ RFResult r (doTweak r tweak req)
443436
NotBracketed -> Left "Not able to bracket the root"
444437
SearchFailed -> Left "Not able to find the root"
445438

0 commit comments

Comments
 (0)