Skip to content

Commit efd5481

Browse files
committed
refactor cmpResult
1 parent 41ab880 commit efd5481

2 files changed

Lines changed: 35 additions & 62 deletions

File tree

absbox/local/cmp.py

Lines changed: 34 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ def compResult(r1:dict, r2:dict, names=("Left", "Right")):
1111
:type names: tuple, optional
1212
"""
1313

14-
def compDf(x, y):
14+
def compDf(x:pd.DataFrame, y:pd.DataFrame) -> pd.DataFrame:
15+
""" Compare two dataframe ,return the dataframe with difference """
16+
1517
(nameA,nameB) = names
1618
x, y = x.align(y, fill_value=pd.NA)
1719
cmp = x.compare(y, result_names=(nameA,nameB))
@@ -21,60 +23,51 @@ def compDf(x, y):
2123
result[column, 'diff'] = cmp[column][nameA].fillna(0) - cmp[column][nameB].fillna(0)
2224
return result.reindex(axis=1, level=1, labels=[nameA, nameB, 'diff']).sort_index(axis=1,level=0)
2325

26+
def cmpMap(x:dict, y:dict) -> dict:
27+
""" compare two map with the same keys """
28+
assert set(x.keys())==set(y.keys()), f"keys not match {x.keys()} vs {y.keys()}"
29+
cmp = {}
30+
for k,v in x.items():
31+
assert isinstance(v, pd.DataFrame), f"expecting DataFrame, got {type(v)}"
32+
assert isinstance(y[k], pd.DataFrame), f"expecting DataFrame, got {type(y[k])}"
33+
if not v.equals(y[k]):
34+
cmp[k] = compDf(v, y[k])
35+
else:
36+
cmp[k] = pd.DataFrame()
37+
return cmp
38+
2439
# r1 -> Left
2540
# r2 -> Right
2641
comp_result = {}
2742
# pool check
28-
comp_result['pool'] = {}
29-
for k,v in r1['pool']['flow'].items():
30-
if not v.equals(r2['pool']['flow'][k]):
31-
comp_result['pool'][k] = compDf(v, r2['pool']['flow'][k])
32-
else:
33-
comp_result['pool'] = True
43+
comp_result['pools'] = cmpMap(r1['pool']['flow'], r2['pool']['flow'])
3444

3545
# expense check
36-
comp_result['fees'] = {}
37-
for fn, f in r1['fees'].items():
38-
if not f.equals(r2['fees'][fn]):
39-
comp_result['fees'][fn] = compDf(f, r2['fees'][fn])
40-
else:
41-
comp_result['fees'][fn] = True
46+
comp_result['fees'] = cmpMap(r1['fees'], r2['fees'])
4247

4348
# bond check
44-
comp_result['bonds'] = {}
45-
for fn, f in r1['bonds'].items():
46-
if not f.equals(r2['bonds'][fn]):
47-
comp_result['bonds'][fn] = compDf(f, r2['bonds'][fn])
48-
else:
49-
comp_result['bonds'][fn] = True
49+
if all([ isinstance(_, pd.DataFrame) for _ in r1['bonds'].values()]) and all([ isinstance(_, pd.DataFrame) for _ in r2['bonds'].values()]):
50+
comp_result['bonds'] = cmpMap(r1['bonds'], r2['bonds'])
51+
else:
52+
comp_result['bonds'] = {}
53+
for k,v in r1['bonds'].items():
54+
if isinstance(v, pd.DataFrame):
55+
comp_result['bonds'][k] = compDf(v, r2['bonds'][k])
56+
elif isinstance(v, dict):
57+
assert isinstance(r2['bonds'][k], dict), f"expecting dict, got {type(r2['bonds'][k])}"
58+
comp_result['bonds'][k] = cmpMap(v, r2['bonds'][k])
5059

5160
# account check
52-
comp_result['accounts'] = {}
53-
for fn, f in r1['accounts'].items():
54-
if not f.equals(r2['accounts'][fn]):
55-
comp_result['accounts'][fn] = compDf(f, r2['accounts'][fn])
56-
else:
57-
comp_result['accounts'][fn] = True
61+
comp_result['accounts'] = cmpMap(r1['accounts'], r2['accounts'])
5862

5963
# ledger check
60-
comp_result['ledgers'] = {}
61-
if 'ledgers' in r1:
62-
for fn, f in r1['ledgers'].items():
63-
if not f.equals(r2['ledgers'][fn]):
64-
comp_result['ledgers'][fn] = compDf(f, r2['ledgers'][fn])
65-
else:
66-
comp_result['ledgers'][fn] = True
64+
comp_result['ledgers'] = cmpMap(r1['ledgers'], r2['ledgers']) if 'ledgers' in r1 else {}
6765

68-
comp_result['triggers'] = {}
69-
if 'triggers' in r1:
66+
if 'triggers' in r1 and r1['triggers'] is not None:
67+
comp_result['triggers'] = {}
7068
for locName, tMap in r1['triggers'].items() :
7169
if len(tMap) == 0:
7270
continue
73-
comp_result['triggers'][locName] = {}
74-
for tn, t in tMap.items():
75-
if not t.equals(r2['triggers'][locName][tn]):
76-
comp_result['trigger'][locName][tn] = compDf(t, r2['triggers'][locName][tn])
77-
else:
78-
comp_result['trigger'][locName][tn] = True
79-
71+
comp_result['triggers'][locName] = cmpMap(r1['triggers'][locName], r2['triggers'][locName])
72+
8073
return comp_result

absbox/local/component.py

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1394,10 +1394,6 @@ def mkWaterfall(r, x):
13941394
r[_w_tag] = lmap(mkAction, _v)
13951395
return mkWaterfall(r, x)
13961396

1397-
def mkWaterfall2(x:dict):
1398-
1399-
return {}
1400-
14011397

14021398
def mkRoundingType(x):
14031399
match x:
@@ -1409,22 +1405,6 @@ def mkRoundingType(x):
14091405
raise RuntimeError(f"Failed to match {x}:mkRoundingType")
14101406

14111407

1412-
def mkAssetRate(x):
1413-
match x:
1414-
case ["固定", r] | ["fix", r]:
1415-
return mkTag(("Fix", r))
1416-
case ["浮动", r, {"基准": idx, "利差": spd, "重置频率": p} as m]:
1417-
_m = subMap(m, [("cap", None), ("floor", None), ("rounding", None)])
1418-
_m = applyFnToKey(_m, mkRoundingType, 'rounding')
1419-
return mkTag(("Floater", [idx, vNum(spd), vNum(r), mkDatePattern(p), _m['floor'], _m['cap'], _m['rounding']]))
1420-
case ["floater", r, {"index": idx, "spread": spd, "reset": p} as m]:
1421-
_m = subMap(m, [("cap", None), ("floor", None), ("rounding", None)])
1422-
_m = applyFnToKey(_m, mkRoundingType, 'rounding')
1423-
return mkTag(("Floater", [idx, vNum(spd), vNum(r), mkDatePattern(p), _m['floor'], _m['cap'], _m['rounding']]))
1424-
case _:
1425-
raise RuntimeError(f"Failed to match {x}:mkAssetRate")
1426-
1427-
14281408
def mkAmortPlan(x) -> dict:
14291409
match x:
14301410
case "等额本息" | "Level" | "level":
@@ -1467,7 +1447,7 @@ def mkAssetStatus(x):
14671447
case "违约" | "Defaulted" | "defaulted":
14681448
return mkTag(("Defaulted",None))
14691449
case ("违约", d) | ("Defaulted", d) | ("defaulted", d):
1470-
return mkTag(("Defaulted", d))
1450+
return mkTag(("Defaulted", vDate(d)))
14711451
case _:
14721452
raise RuntimeError(f"Failed to match asset statuts {x}:mkAssetStatus")
14731453

0 commit comments

Comments
 (0)