Team Ai
Datasetpublic

Benjamin-eecs/openrsi-commit-runtime-assets

sourceHugging Faceupdated 16d agoView on Hugging Face
0likes168downloads
patch.diff112 linesDownload Raw Back to solution
1diff --git a/CHANGELOG.md b/CHANGELOG.md2index 0d5255e..d6d4e0b 1006443--- a/CHANGELOG.md4+++ b/CHANGELOG.md5@@ -1,5 +1,25 @@6 # Changelog7 8+## 1.2.x9+10+### New11+12+- `NSDLCASData.parse_warnings` — non-fatal warnings for demat holdings whose13+  numbers don't reconcile.14+15+### Fixed16+17+- NSDL demat holdings parsed by arithmetic (`units*nav≈value`) instead of18+  hardcoded pixel columns; fixes wrong nav/value on layout-shifted statements.19+- NSDL equities: same fix (`shares*price≈value`) + pledged sub-rows no longer20+  parsed as separate holdings.21+- CDSL mutual-fund profit/return assigned by `value-cost` identity, not22+  position; fixes return% being reported as profit.23+24+### Changed25+26+- `CapitalGainsReport` is lazy-loaded, keeping `import casparser` lighter.27+28 ## 1.2.129 30 ### Fixed31diff --git a/casparser/parsers/cdsl.py b/casparser/parsers/cdsl.py32index cf3774b..7fc0828 10064433--- a/casparser/parsers/cdsl.py34+++ b/casparser/parsers/cdsl.py35@@ -132,6 +132,66 @@ def _looks_numeric(text: str) -> bool:36     return bool(NUMERIC_RE.match(s))37 38 39+def _rel_close(a: Decimal, b: Decimal, rel: Decimal = Decimal("0.005")) -> bool:40+    if b == 0:41+        return abs(a) <= Decimal("0.01")42+    return abs(a - b) / abs(b) <= rel43+44+45+def _resolve_cdsl_mf_pnl_returns(46+    numerics: List[str],47+    value: Decimal,48+    invested: Optional[Decimal],49+    has_distrib_col: bool,50+) -> Tuple[Optional[Decimal], Optional[Decimal]]:51+    """Assign profit and return% from the post-value numeric tail.52+53+    Positional ``numerics[-2]`` / ``[-1]`` is wrong when the statement54+    omits a printed profit column and only shows return% — identity55+    ``value - invested`` picks profit when present; otherwise leave56+    ``pnl`` unset and treat a small trailing % as ``return_``."""57+    if not has_distrib_col:58+        return None, None59+60+    value_idx = 3 if len(numerics) >= 4 else 261+    remaining = [_to_decimal(n) for n in numerics[value_idx + 1 :]]62+    remaining = [r for r in remaining if r != 0]63+64+    expected_pnl: Optional[Decimal] = None65+    if invested is not None and invested > 0:66+        expected_pnl = value - invested67+68+    pnl: Optional[Decimal] = None69+    ret: Optional[Decimal] = None70+71+    if expected_pnl is not None:72+        for r in remaining:73+            if _rel_close(r, expected_pnl):74+                pnl = r75+                break76+        if pnl is None and len(numerics) >= 6:77+            pos_pnl = _opt_decimal(numerics[-2])78+            if pos_pnl is not None and _rel_close(pos_pnl, expected_pnl):79+                pnl = pos_pnl80+81+    others = [r for r in remaining if r != pnl]82+    if pnl is not None and others:83+        ret = others[-1]84+    elif pnl is None and expected_pnl is not None:85+        for r in others:86+            if abs(r) < Decimal("100"):87+                ret = r88+                break89+    elif len(numerics) >= 5:90+        ret = _opt_decimal(numerics[-1])91+92+    if pnl == 0:93+        pnl = None94+    if ret == 0:95+        ret = None96+    return pnl, ret97+98+99 # --- account key utilities ---100 101 102@@ -586,8 +646,7 @@ def _parse_mf_holdings_row(103         # Reduced row: units | NAV | value (no separate invested/cost).104         invested = None105         value = _to_decimal(numerics[2])106-    pnl = _opt_decimal(numerics[-2]) if has_distrib_col and len(numerics) >= 6 else None107-    ret = _opt_decimal(numerics[-1]) if has_distrib_col and len(numerics) >= 5 else None108+    pnl, ret = _resolve_cdsl_mf_pnl_returns(numerics, value, invested, has_distrib_col)109 110     # Pull UCC from scheme_meta keyed on scheme_code (prefix of name)111     ucc = None112