Skip to content

Commit 331dfc1

Browse files
committed
enforce "start" in fee & liquidity provider
1 parent 3a4006e commit 331dfc1

Some content is hidden

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

58 files changed

+114388
-3813
lines changed

absbox/local/china.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,15 +61,14 @@ def json(self):
6161
"pool": mkPoolType(lastAssetDate, self.资产池, mixedAssetFlag),
6262
"bonds": {bn: mkBndComp(bn, bo) for (bn, bo) in self.债券 },
6363
"waterfall": mkWaterfall({},self.分配规则.copy()),
64-
"fees": {fn: mkFee(fo|{"名称":fn}, fsDate=defaultStartDate) for (fn, fo) in self.费用 },
64+
"fees": {fn: mkFee(fo|{"名称":fn}) for (fn, fo) in self.费用 },
6565
"accounts": {an:mkAcc(an,ao) for (an, ao) in self.账户 },
6666
"collects": [ mkCollection(c) for c in self.归集规则],
6767
"rateSwap": {k:mkRateSwap(v) for k,v in self.利率对冲.items()} if self.利率对冲 else None,
6868
"currencySwap": None,
6969
"custom": {cn:mkCustom(co) for cn,co in self.自定义.items()} if self.自定义 else None,
7070
"triggers": renameKs2({k: {_k: mkTrigger(_v) for (_k,_v) in v.items()} for (k,v) in self.触发事件.items() },chinaDealCycle) if self.触发事件 else None,
71-
"liqProvider": {ln: mkLiqProvider(ln, lo | {"起始日":defaultStartDate} )
72-
for ln,lo in self.流动性支持.items() } if self.流动性支持 else None,
71+
"liqProvider": {ln: mkLiqProvider(ln, lo) for ln,lo in self.流动性支持.items() } if self.流动性支持 else None,
7372
"ledgers": {ln: mkLedger(ln, v) for ln,v in self.科目.items()} if self.科目 else None,
7473
"stats": [{},{},{},{}]
7574
}

absbox/local/component.py

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,20 @@
77
from lenses import lens
88
import pandas as pd
99
from schema import Or
10+
from rich.console import Console
11+
1012

1113
from .interface import mkTag
1214
from .util import mkTs, readTagStr, subMap, subMap2, renameKs, ensure100
1315
from .util import mapListValBy, uplift_m_list, mapValsBy, allList, getValWithKs, applyFnToKey,flat
1416
from .util import earlyReturnNone, mkFloatTs, mkRateTs, mkRatioTs, mkTbl, mapNone, guess_pool_flow_header
15-
from .util import filter_by_tags, enumVals, lmap, readTagMap, patchDicts,updateKs
17+
from .util import filter_by_tags, enumVals, lmap, readTagMap, patchDicts,updateKs, ensureKeysInMap
1618
from .base import *
1719

1820
from ..validation import vDict, vList, vStr, vNum, vInt, vDate, vFloat, vBool, vTuple, vListOfList
1921

2022
numVal = Or(float,int)
21-
23+
console = Console()
2224

2325
def mkLiq(x):
2426
''' make pricing method '''
@@ -2101,10 +2103,11 @@ def mkLiqProviderType(x):
21012103
case {}:
21022104
return mkTag(("UnLimit"))
21032105
case _:
2104-
raise RuntimeError(f"Failed to match LiqProvider Type{x}")
2106+
raise RuntimeError(f"Failed to match LiqProvider Type:{x}")
21052107

21062108

21072109
def mkLiqProvider(n: str, x: dict):
2110+
ensureKeysInMap(x,["start",],msg="Init liquidity provider")
21082111
x_transformed = renameKs(x,[("已提供","liqBalance"),("应付利息","liqDueInt"),("应付费用","liqDuePremium")
21092112
,("利率","liqRate"),("费率","liqPremiumRate"),("记录","liqStmt")
21102113
,("name","liqName"),("type","liqType")
@@ -2114,7 +2117,8 @@ def mkLiqProvider(n: str, x: dict):
21142117
,("rateType","liqRateType"),("feeType","liqPremiumRateType")
21152118
,("dueIntDate","liqDueIntDate")
21162119
,("balance","liqBalance")
2117-
,("end","liqEnds"),("start","liqStart")
2120+
,("end","liqEnds")
2121+
,("start","liqStart")
21182122
,("stmt","liqStmt")
21192123
,("creditCalc","liqCreditCalc")
21202124
]
@@ -2200,15 +2204,20 @@ def mkCollection(x):
22002204
raise RuntimeError(f"Failed to match collection rule {x}")
22012205

22022206

2203-
def mkFee(x,fsDate=None):
2207+
def mkFee(x):
22042208
match x :
22052209
case {"name":fn, "type": feeType, **fi}:
2206-
opt_fields = subMap(fi, [("feeStart",fsDate),("feeDueDate",None),("feeDue",0),
2207-
("feeArrears",0),("feeLastPaidDate",None)])
2210+
if "feeStart" not in fi:
2211+
raise RuntimeError("feeStart not found in fee:after version 0.45.x fee must to include field feeStart")
2212+
opt_fields = subMap(fi, [("feeDueDate",None),("feeDue",0),
2213+
("feeArrears",0),("feeLastPaidDate",None),
2214+
("feeStart",None)])
22082215
return {"feeName": vStr(fn), "feeType": mkFeeType(feeType)} | opt_fields
22092216
case {"名称":fn , "类型": feeType, **fi}:
2210-
opt_fields = subMap2(fi, [("起算日","feeStart",fsDate),("计算日","feeDueDate",None),("应计费用","feeDue",0),
2211-
("拖欠","feeArrears",0),("上次缴付日期","feeLastPaidDay",None)])
2217+
print("fee info", fi)
2218+
opt_fields = subMap2(fi, [("计算日","feeDueDate",None),("应计费用","feeDue",0),
2219+
("拖欠","feeArrears",0),("上次缴付日期","feeLastPaidDay",None),
2220+
("起始日","feeStart",None)])
22122221
return {"feeName": vStr(fn), "feeType": mkFeeType(feeType)} | opt_fields
22132222
case _:
22142223
raise RuntimeError(f"Failed to match fee: {x}")
@@ -2245,7 +2254,6 @@ def mkIrrType(x):
22452254
raise RuntimeError(f"Failed to match irrType: {x}")
22462255

22472256

2248-
22492257
def mkPricingAssump(x):
22502258
match x:
22512259
case ("pv",pricingDay,xs) | {"贴现日": pricingDay, "贴现曲线": xs} | {"date": pricingDay, "curve": xs}| {"PVDate": pricingDay, "PVCurve": xs}:

absbox/local/generic.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,15 +64,15 @@ def json(self) -> dict:
6464
"pool":mkPoolType(lastAssetDate, self.pool, mixedAssetFlag),
6565
"bonds": {bn: mkBndComp(bn, bo) for (bn, bo) in self.bonds},
6666
"waterfall": mkWaterfall({},self.waterfall.copy()),
67-
"fees": {fn: mkFee(fo|{"name": fn}, fsDate = lastCloseDate) for (fn, fo) in self.fees},
67+
"fees": {fn: mkFee(fo|{"name": fn}) for (fn, fo) in self.fees},
6868
"accounts": {an:mkAcc(an, ao) for (an, ao) in self.accounts},
6969
"collects": lmap(mkCollection, self.collection),
7070
"rateSwap": tz.valmap(mkRateSwap, self.rateSwap) if self.rateSwap else None,
7171
"rateCap": tz.valmap(mkRateCap, self.rateCap) if self.rateCap else None,
7272
"currencySwap":None ,
7373
"custom": tz.valmap(mkCustom, self.custom) if self.custom else None,
7474
"triggers": renameKs2({k: {_k: mkTrigger(_v) for (_k,_v) in v.items() } for (k, v) in self.trigger.items()},englishDealCycle) if self.trigger else None,
75-
"liqProvider": {ln: mkLiqProvider(ln, lo | {"start":lastCloseDate} )
75+
"liqProvider": {ln: mkLiqProvider(ln, lo)
7676
for ln,lo in self.liqFacility.items() } if self.liqFacility else None,
7777
"ledgers": {ln: mkLedger(ln, v) for ln,v in self.ledgers.items()} if self.ledgers else None,
7878
"stats": self.buildStats()

absbox/local/util.py

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,6 @@ def flat(xss) -> list:
2525
return reduce(lambda xs, ys: xs + ys, xss)
2626

2727

28-
29-
3028
def filter_by_tags(xs: list, tags: list) -> list:
3129
''' fiter a list of maps by tags'''
3230
tags_set = set(tags)
@@ -147,11 +145,12 @@ def guess_pool_locale(x):
147145
raise RuntimeError("Failed to match {x} in guess pool locale")
148146

149147

150-
def renameKs(m: dict, mapping, opt_key=False):
148+
def renameKs(_m: dict, mapping, opt_key=False):
151149
'''
152150
rename keys in a map with from a mapping tuple passed in
153151
`opt_key` = True, allow skipping mapping tuple not exist in the map
154152
'''
153+
m = _m.copy()
155154
for (o, n) in mapping:
156155
if opt_key and o not in m:
157156
continue
@@ -160,6 +159,18 @@ def renameKs(m: dict, mapping, opt_key=False):
160159
return m
161160

162161

162+
def ensureKeysInMap(m: dict, ks: list, msg=""):
163+
''' Ensure keys in a map, if not found, add with None'''
164+
missing = []
165+
for k in ks:
166+
if k not in m:
167+
missing.append(k)
168+
if missing:
169+
raise RuntimeError(f"Missing keys in map:{missing}, not found in {m.keys()}, location:{msg}")
170+
return m
171+
172+
173+
163174
def subMap(m: dict, ks: list):
164175
''' get a map subset by keys,if keys not found, supplied with default value '''
165176
return {k: m.get(k, defaultVal) for (k, defaultVal) in ks}
@@ -447,7 +458,6 @@ def patchDicts(dict1:dict,dict2:dict)-> dict:
447458
return tz.merge_with(lambda xs: xs[1] if len(xs)==2 else xs[0] ,dict1 ,dict2)
448459

449460

450-
451461
def getNumCols(df:pd.DataFrame)-> list:
452462
numeric_columns = [col for col in df.columns if pd.to_numeric(df[col], errors='coerce').notna().all()]
453463
return numeric_columns

absbox/tests/benchmark/china/out/test01.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -199,11 +199,11 @@
199199
"tag": "FixFee",
200200
"contents": 10
201201
},
202-
"feeStart": "2021-06-15",
203202
"feeDueDate": null,
204203
"feeDue": 0,
205204
"feeArrears": 0,
206-
"feeLastPaidDay": null
205+
"feeLastPaidDay": null,
206+
"feeStart": "2021-06-15"
207207
}
208208
},
209209
"accounts": {

absbox/tests/benchmark/china/out/test03.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -232,11 +232,11 @@
232232
"tag": "FixFee",
233233
"contents": 25
234234
},
235-
"feeStart": "2021-10-15",
236235
"feeDueDate": null,
237236
"feeDue": 0,
238237
"feeArrears": 0,
239-
"feeLastPaidDay": null
238+
"feeLastPaidDay": null,
239+
"feeStart": "2021-10-15"
240240
}
241241
},
242242
"accounts": {

absbox/tests/benchmark/china/out/test04.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -367,11 +367,11 @@
367367
}
368368
]
369369
},
370-
"feeStart": "2022-10-02",
371370
"feeDueDate": null,
372371
"feeDue": 0,
373372
"feeArrears": 0,
374-
"feeLastPaidDay": null
373+
"feeLastPaidDay": null,
374+
"feeStart": "2022-10-02"
375375
},
376376
"\u670d\u52a1\u5546\u8d39\u7528": {
377377
"feeName": "\u670d\u52a1\u5546\u8d39\u7528",
@@ -388,11 +388,11 @@
388388
}
389389
]
390390
},
391-
"feeStart": "2022-10-02",
392391
"feeDueDate": null,
393392
"feeDue": 0,
394393
"feeArrears": 0,
395-
"feeLastPaidDay": null
394+
"feeLastPaidDay": null,
395+
"feeStart": "2022-10-02"
396396
}
397397
},
398398
"accounts": {

absbox/tests/benchmark/china/out/test05.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -365,11 +365,11 @@
365365
}
366366
]
367367
},
368-
"feeStart": "2021-10-15",
369368
"feeDueDate": null,
370369
"feeDue": 0,
371370
"feeArrears": 0,
372-
"feeLastPaidDay": null
371+
"feeLastPaidDay": null,
372+
"feeStart": "2021-10-15"
373373
},
374374
"\u670d\u52a1\u5546\u8d39\u7528": {
375375
"feeName": "\u670d\u52a1\u5546\u8d39\u7528",
@@ -386,11 +386,11 @@
386386
}
387387
]
388388
},
389-
"feeStart": "2021-10-15",
390389
"feeDueDate": null,
391390
"feeDue": 0,
392391
"feeArrears": 0,
393-
"feeLastPaidDay": null
392+
"feeLastPaidDay": null,
393+
"feeStart": "2021-10-15"
394394
},
395395
"\u6267\u884c\u8d39\u7528": {
396396
"feeName": "\u6267\u884c\u8d39\u7528",
@@ -403,11 +403,11 @@
403403
599
404404
]
405405
},
406-
"feeStart": "2021-10-15",
407406
"feeDueDate": null,
408407
"feeDue": 0,
409408
"feeArrears": 0,
410-
"feeLastPaidDay": null
409+
"feeLastPaidDay": null,
410+
"feeStart": "2021-10-15"
411411
}
412412
},
413413
"accounts": {

absbox/tests/benchmark/china/out/test06.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -415,11 +415,11 @@
415415
}
416416
]
417417
},
418-
"feeStart": "2022-06-30",
419418
"feeDueDate": null,
420419
"feeDue": 0,
421420
"feeArrears": 0,
422-
"feeLastPaidDay": null
421+
"feeLastPaidDay": null,
422+
"feeStart": "2022-06-30"
423423
},
424424
"\u670d\u52a1\u5546\u8d39\u7528": {
425425
"feeName": "\u670d\u52a1\u5546\u8d39\u7528",
@@ -436,11 +436,11 @@
436436
}
437437
]
438438
},
439-
"feeStart": "2022-06-30",
440439
"feeDueDate": null,
441440
"feeDue": 0,
442441
"feeArrears": 0,
443-
"feeLastPaidDay": null
442+
"feeLastPaidDay": null,
443+
"feeStart": "2022-06-30"
444444
},
445445
"\u62a5\u9500": {
446446
"feeName": "\u62a5\u9500",
@@ -453,11 +453,11 @@
453453
60000
454454
]
455455
},
456-
"feeStart": "2022-06-30",
457456
"feeDueDate": null,
458457
"feeDue": 0,
459458
"feeArrears": 0,
460-
"feeLastPaidDay": null
459+
"feeLastPaidDay": null,
460+
"feeStart": "2022-05-30"
461461
}
462462
},
463463
"accounts": {

absbox/tests/benchmark/china/out/test07.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -950,11 +950,11 @@
950950
}
951951
]
952952
},
953-
"feeStart": "2022-07-26",
954953
"feeDueDate": null,
955954
"feeDue": 0,
956955
"feeArrears": 0,
957-
"feeLastPaidDay": null
956+
"feeLastPaidDay": null,
957+
"feeStart": "2022-07-26"
958958
},
959959
"\u670d\u52a1\u5546\u8d39\u7528": {
960960
"feeName": "\u670d\u52a1\u5546\u8d39\u7528",
@@ -971,11 +971,11 @@
971971
}
972972
]
973973
},
974-
"feeStart": "2022-07-26",
975974
"feeDueDate": null,
976975
"feeDue": 0,
977976
"feeArrears": 0,
978-
"feeLastPaidDay": null
977+
"feeLastPaidDay": null,
978+
"feeStart": "2022-07-26"
979979
}
980980
},
981981
"accounts": {

0 commit comments

Comments
 (0)