Преглед изворни кода

refactor#去掉-全部卖出后票据上当前增额已是 0,工具算不出卖出前基线,只能标可疑。

hefuzheng пре 1 недеља
родитељ
комит
57d34afeaa

BIN
code/post_clear_check/src/post_clear_check/__pycache__/order_rules.cpython-312.pyc


+ 39 - 11
code/post_clear_check/src/post_clear_check/order_rules.py

@@ -421,6 +421,7 @@ def _append_sell(
     ratio, ratio_mode, ratio_live, ratio_error = _ratio(sub, note, note_ambiguous, logs, sources)
     face_calc, add_calc, dividend_calc = None, None, None
     face_live = add_live = dividend_live = ratio_live
+    add_skip = dividend_skip = False
     if ratio_mode == "skip":
         # 没有执行名义本金,比例三列不核。日志留一行,结论里不出现。
         logger.info("卖出比例不核:没有执行名义本金,子单 {}", label)
@@ -436,24 +437,39 @@ def _append_sell(
             face_name = "当前票据面值"
             face_formula = "卖出票据面值 = 比例 × 当前票据面值"
         face_calc, face_text, face_live = _sell_share(ratio, ratio_mode, ratio_live, face_base, face_name, ratio_error)
-        add_calc, add_text, add_live = _sold_amount_share(
+        add_calc, add_text, add_live, add_skip = _sold_amount_share(
             sub, logs, sources, ratio, ratio_mode, ratio_live, ratio_error,
             read_note_cell(note, "add_amt", logs, sources), "当前增额金额", "sold_add_amt", fully_sold,
         )
-        dividend_calc, dividend_text, dividend_live = _sold_amount_share(
+        dividend_calc, dividend_text, dividend_live, dividend_skip = _sold_amount_share(
             sub, logs, sources, ratio, ratio_mode, ratio_live, ratio_error,
             read_note_cell(note, "dividend_amt", logs, sources), "当前分红金额", "realized_dividend", fully_sold,
         )
         _finish_share(lines, sub, logs, sources, label, face_formula, "sold_face_value", face_text, face_calc, face_live, ratio_mode)
-        _finish_share(lines, sub, logs, sources, label, "卖出增额金额 = 比例 × 当前增额金额", "sold_add_amt", add_text, add_calc, add_live, ratio_mode)
-        _finish_share(lines, sub, logs, sources, label, "实现分红 = 比例 × 当前分红金额", "realized_dividend", dividend_text, dividend_calc, dividend_live, ratio_mode)
+        # 全卖后票上增额/分红已清零且无卖出前快照时不核这两列,避免明知核不动还刷可疑。
+        if not add_skip:
+            _finish_share(
+                lines, sub, logs, sources, label,
+                "卖出增额金额 = 比例 × 当前增额金额", "sold_add_amt", add_text, add_calc, add_live, ratio_mode,
+            )
+        if not dividend_skip:
+            _finish_share(
+                lines, sub, logs, sources, label,
+                "实现分红 = 比例 × 当前分红金额", "realized_dividend", dividend_text, dividend_calc, dividend_live, ratio_mode,
+            )
+    # 分红公式因无快照跳过时,底层盈亏改用订单已落库的实现分红代入(不循环自证增额)。
+    pnl_dividend, pnl_dividend_live = dividend_calc, dividend_live
+    if dividend_skip:
+        stored_div = read_cell(sub, "realized_dividend", "order_sub_a", logs, sources)
+        pnl_dividend = stored_div.number
+        pnl_dividend_live = dividend_live or stored_div.live
     pnl_calc, pnl_text, pnl_live = _pnl_for_sub(
         sub,
         note,
         logs,
         sources,
-        dividend_calc,
-        dividend_live,
+        pnl_dividend,
+        pnl_dividend_live,
     )
     finish_number(
         lines,
@@ -467,7 +483,11 @@ def _append_sell(
         scale=SCALE_AMT,
         extra_live=pnl_live,
     )
-    _total_line(lines, sub, note, logs, sources, label, face_calc, add_calc, pnl_calc, face_live or add_live or pnl_live)
+    # 增额因无快照不核时,总金额缺独立算出的增额,同样不核。
+    _total_line(
+        lines, sub, note, logs, sources, label, face_calc, add_calc, pnl_calc,
+        face_live or add_live or pnl_live, skip_total=add_skip,
+    )
     _final_line(lines, sub, logs, sources, label)
 
 
@@ -1015,15 +1035,19 @@ def _sold_amount_share(
     base_name: str,
     column: str,
     fully_sold: bool,
-) -> tuple[Decimal | None, str, bool]:
-    """全部卖出后增额、分红已扣成 0。订单上仍有金额时,卖出前的数不在票据上,不拿 0 去比。"""
+) -> tuple[Decimal | None, str, bool, bool]:
+    """全卖后增额/分红已扣成 0 且订单上仍有金额时,卖出前基数不在票上,本列不核。
+
+    返回 (算出值, 代入文案, 是否活表, 是否跳过本列)。第四项为 True 时调用方不出结论行。
+    """
 
     if fully_sold and not base.absent and base.number == 0:
         sold = read_cell(sub, column, "order_sub_a", logs, sources)
         if sold.number not in (None, 0):
             live = ratio_live or base.live or sold.live
-            return None, f"全部卖出后{base_name}已是 0,卖出前金额没有留在票据上", live
-    return _sell_share(ratio, mode, ratio_live, base, base_name, error_text)
+            return None, "", live, True
+    calc, text, live = _sell_share(ratio, mode, ratio_live, base, base_name, error_text)
+    return calc, text, live, False
 
 
 def _finish_share(
@@ -1153,7 +1177,11 @@ def _total_line(
     sold_add: Decimal | None,
     pnl: Decimal | None,
     extra_live: bool,
+    skip_total: bool = False,
 ) -> None:
+    # 卖出增额因全卖无快照跳过时,总金额缺独立增额,整列不核。
+    if skip_total:
+        return
     check = read_cell(sub, "exec_total_amt_settle", "order_sub_a", logs, sources)
     formula = "总金额 = 若底层资产盈亏 > 0,则卖出票据面值 + 卖出增额金额 + 底层资产盈亏 × 收益比例,否则取与 0 的较大者"
     if sold_face is None or sold_add is None or pnl is None:

BIN
code/post_clear_check/tests/__pycache__/test_order_rules.cpython-312-pytest-9.1.1.pyc


+ 28 - 5
code/post_clear_check/tests/test_order_rules.py

@@ -194,8 +194,8 @@ def test_full_sell_without_initial_notional_is_error() -> None:
     assert "初始名义本金缺失或为 0" in line.calc_text
 
 
-def test_full_sell_cleared_dividend_is_not_compared_with_zero() -> None:
-    """全部卖出后票据分红已扣成 0,订单上仍有实现分红时,不用 0 去报错。"""
+def test_full_sell_cleared_dividend_is_skipped() -> None:
+    """全部卖出后票据分红已扣成 0、订单上仍有实现分红时,无卖出前快照,本列不核。"""
 
     order = _sell_order(
         exec_notional_trade=Decimal("100"),
@@ -210,9 +210,32 @@ def test_full_sell_cleared_dividend_is_not_compared_with_zero() -> None:
     note["init_face_value"] = Decimal("200")
     note["dividend_amt"] = Decimal("0")
     sub["realized_dividend"] = Decimal("8")
-    line = _one(check_order(order), "实现分红")
-    assert line.verdict == "suspect"
-    assert "没有留在票据上" in line.calc_text
+    formulas = [line.formula_text for line in check_order(order)]
+    assert not any(text.startswith("实现分红") for text in formulas)
+
+
+def test_full_sell_cleared_add_and_total_are_skipped() -> None:
+    """全部卖出后当前增额已是 0、订单上仍有卖出增额时,增额与总金额均不核。"""
+
+    order = _sell_order(
+        exec_notional_trade=Decimal("100"),
+        cur_notional_trade=Decimal("0"),
+        cur_face_value=Decimal("0"),
+        sold_face_value=Decimal("200"),
+    )
+    note = order["note_sub_a"][0]
+    sub = order["order_sub_a"][0]
+    assert isinstance(note, dict) and isinstance(sub, dict)
+    note["init_notional_trade"] = Decimal("100")
+    note["init_face_value"] = Decimal("200")
+    note["add_amt"] = Decimal("0")
+    sub["sold_add_amt"] = Decimal("140000")
+    formulas = [line.formula_text for line in check_order(order)]
+    assert not any(text.startswith("卖出增额金额") for text in formulas)
+    assert not any(text.startswith("总金额") for text in formulas)
+    # 面值仍可按初始面值核;最终盈亏读订单落库列,不受增额跳过影响。
+    assert any(text.startswith("卖出票据面值") for text in formulas)
+    assert any(text.startswith("最终盈亏") for text in formulas)
 
 
 def test_force_and_maturity_use_sell_formulas() -> None:

+ 2 - 2
doc/业务链路核对设计.md

@@ -143,9 +143,9 @@
 | 对冲执行根 | 同买入执行 | 同买入执行 | 研发设计 `docs/清算/三端清算最终实施方案.md`「5.4 TRS 核对、订单和交收计算」 |
 | 累计成交股数、累计发生金额、对冲含费成交均价、结算汇率 | `work/3` 必须出现 | 等于有效对冲记录汇总,有效金额口径同买入执行。汇率不读订单上或 TRS 结果里的 `fx_settle` 当输入 | Excel「卖出订单」第 12 行「累计成交股数」、第 13 行「对冲含费成交均价」、第 14、15 行「累计发生金额」、第 16 行「结算汇率」 |
 | 订单卖出股数 | 必须出现 | 按卖出比例;最后一笔取剩余股数。无法判断是不是最后一笔时记可疑。被核对的值在 `input` | Excel「卖出订单」第 19 行「订单卖出股数」 |
-| 卖出票据面值、卖出增额金额、实现分红 | 必须出现 | 比例 × 卖出前的票据值。被核对的值在 `input`。部分卖出(当前名义本金大于 0):比例 = 本次执行名义本金 ÷ 票据当前名义本金,面值、增额、分红用当前值。全部卖出后当前名义本金被扣成 0:比例 = 本次执行名义本金 ÷ 初始名义本金,等于初始名义本金时就是 100%;一笔票据分多笔卖完时,每笔用自己的执行名义本金去除,面值改乘初始面值(当前面值已是 0)。当前名义本金缺失(没有这列或为空)而执行名义本金已有,是错误;全部卖出时初始名义本金缺失或为 0,也是错误。执行名义本金没有时不核这三列,日志记一行。全部卖出后增额或分红已是 0、订单上对应金额却不是 0 的,卖出前金额没有留在票据上,记可疑,不用 0 去比 | Excel「卖出订单」第 21 行「卖出票据面值」、第 22 行「卖出增额金额」、第 23 行「实现分红」 |
+| 卖出票据面值、卖出增额金额、实现分红 | 必须出现(见右列例外) | 比例 × 卖出前的票据值。被核对的值在 `input`。部分卖出(当前名义本金大于 0):比例 = 本次执行名义本金 ÷ 票据当前名义本金,面值、增额、分红用当前值。全部卖出后当前名义本金被扣成 0:比例 = 本次执行名义本金 ÷ 初始名义本金,等于初始名义本金时就是 100%;一笔票据分多笔卖完时,每笔用自己的执行名义本金去除,面值改乘初始面值(当前面值已是 0)。当前名义本金缺失(没有这列或为空)而执行名义本金已有,是错误;全部卖出时初始名义本金缺失或为 0,也是错误。执行名义本金没有时不核这三列,日志记一行。全部卖出后增额或分红已是 0、订单上对应金额却不是 0 的,卖出前金额没有留在票据上,**本列不核**(不出结论行);因此缺独立增额时「总金额」也不核。面值仍核;底层盈亏在分红跳过时改用订单已落库的实现分红代入 | Excel「卖出订单」第 21 行「卖出票据面值」、第 22 行「卖出增额金额」、第 23 行「实现分红」 |
 | 底层资产盈亏 | `work/3` 必须出现 | 按两个汇率分别换算。股数和均价读 `input` | Excel「卖出订单」第 24 行「底层资产盈亏」 |
-| 总金额 | `work/3` 必须出现 | 按执行信息计算。收益比例是百分数(10 表示 10%),乘之前除以 100 | Excel「卖出订单」第 25 行「总金额」 |
+| 总金额 | `work/3` 必须出现(增额因全卖无快照不核时本列也不核) | 按执行信息计算。收益比例是百分数(10 表示 10%),乘之前除以 100。缺独立算出的卖出增额时不出结论行 | Excel「卖出订单」第 25 行「总金额」 |
 | 最终盈亏 | `work/3` 必须出现 | 总金额读 `work/3`,卖出面值和卖出增额读 `input` | Excel「卖出订单」第 26 行「最终盈亏」 |
 | T日订单结算 | `work/3`、`work/4`、`cleared/0` 都必须有该子单 | 结算口径列一致 | 研发设计 `docs/tmp/data_check_tool/doc/清算步骤核对改造方案.md`「5.1 发行端(6 步)」 |
 | 当前投影 | 实时子单必须存在 | 实时结算口径列等于 `cleared`。执行事实列由执行事实节点核对 | 研发设计 `docs/tmp/data_check_tool/doc/清算步骤核对改造方案.md`「5.1 发行端(6 步)」 |

Разлика између датотеке није приказан због своје велике величине
+ 0 - 0
doc/使用说明.md


Неке датотеке нису приказане због велике количине промена