修复交易记录基数虚高:禁止币×价÷杠杆发明保证金,优先计划保证金/风险金额反推。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-08-13 00:12:02 +08:00
parent 5ad22a57da
commit 35b70777b8
4 changed files with 163 additions and 42 deletions
+3
View File
@@ -20,6 +20,9 @@ def enrich_trade_price_displays(
trigger_price=item.get("trigger_price"),
leverage=item.get("leverage"),
symbol=item.get("symbol"),
stop_loss=item.get("stop_loss"),
initial_stop_loss=item.get("initial_stop_loss"),
risk_amount=item.get("risk_amount"),
)
if fixed is not None:
item["margin_capital"] = fixed
+82 -24
View File
@@ -1,4 +1,4 @@
"""交易记录「基数」= U 保证金;防止把折算标的(币数量)误写成/误显示为基数."""
"""交易记录「基数」= U 保证金;防止币数量/账户保证金误入,展示时禁止用币×价÷杠杆虚增."""
from __future__ import annotations
from typing import Any, Optional
@@ -55,13 +55,33 @@ def looks_like_coin_amount_as_margin(
return False
def margin_from_risk_amount(
risk_amount: Any,
*,
trigger_price: Any,
stop_loss: Any,
leverage: Any,
) -> Optional[float]:
"""由风险金额反推保证金: risk ≈ margin × lev × |entry-sl| / entry."""
risk = _pos_float(risk_amount)
px = _pos_float(trigger_price)
sl = _pos_float(stop_loss)
lev = _pos_float(leverage)
if risk is None or px is None or sl is None or lev is None or lev <= 0 or px <= 0:
return None
dist = abs(px - sl)
if dist <= 0:
return None
return round(risk * px / (lev * dist), 2)
def coin_amount_to_margin_usdt(
coin_amount: Any,
*,
trigger_price: Any,
leverage: Any,
) -> Optional[float]:
"""币数量 × 价格 / 杠杆 ≈ USDT 保证金."""
"""币数量 × 价格 / 杠杆 ≈ USDT 保证金(仅作末位兜底,展示层勿优先使用)."""
coin = _pos_float(coin_amount)
px = _pos_float(trigger_price)
lev = _pos_float(leverage)
@@ -77,7 +97,7 @@ def sanitize_exchange_initial_margin(
order_leverage: Any = None,
coin_amount: Any = None,
) -> Optional[float]:
"""交易所快照保证金清洗:拒绝币数量误入,必要时用名义/杠杆粗算."""
"""交易所快照保证金清洗:拒绝币数量/过大账户保证金,必要时用名义/杠杆粗算."""
m = _pos_float(initial)
coin = _pos_float(coin_amount)
if m is not None and coin is not None and _near(m, coin, rel=0.05, abs_tol=1e-4):
@@ -87,8 +107,12 @@ def sanitize_exchange_initial_margin(
approx = None
if notional_v is not None and lev is not None and lev > 0:
approx = notional_v / lev
if m is not None and approx is not None and approx >= 1.0 and m < max(1.0, approx * 0.05):
m = None
if m is not None and approx is not None and approx >= 1.0:
if m < max(1.0, approx * 0.05):
m = None
elif m > approx * 2.5:
# 常见于全仓 collateral≈账户权益,远大于本仓占用
m = None
if m is not None:
return round(m, 4)
if approx is not None and approx > 0:
@@ -104,10 +128,22 @@ def resolve_trade_record_margin_usdt(
notional_value: Any = None,
leverage: Any = None,
trigger_price: Any = None,
stop_loss: Any = None,
risk_amount: Any = None,
) -> Optional[float]:
"""写入 trade_records.基数:优先交易所快照,异常时回退计划保证金."""
"""写入 trade_records.基数:计划保证金优先于异常交易所快照;禁止币×价÷杠杆虚增."""
plan = _pos_float(plan_margin_capital)
ex = _pos_float(exchange_margin_usdt)
if plan is not None and looks_like_coin_amount_as_margin(
plan,
trigger_price=trigger_price,
leverage=leverage,
base_amount=base_amount,
notional_value=notional_value,
):
plan = None
if ex is not None and looks_like_coin_amount_as_margin(
ex,
trigger_price=trigger_price,
@@ -116,19 +152,28 @@ def resolve_trade_record_margin_usdt(
plan_margin=plan,
notional_value=notional_value,
):
# 快照像币数量:优先用计划保证金;无计划时再按币×价/杠杆反推
if plan is not None:
return round(plan, 2)
repaired = coin_amount_to_margin_usdt(
ex, trigger_price=trigger_price, leverage=leverage
)
if repaired is not None:
return repaired
ex = None
if ex is not None:
return round(ex, 2)
if ex is not None and plan is not None and ex > plan * 2.5:
ex = None
if plan is not None:
return round(plan, 2)
if ex is not None:
return round(ex, 2)
from_risk = margin_from_risk_amount(
risk_amount,
trigger_price=trigger_price,
stop_loss=stop_loss,
leverage=leverage,
)
if from_risk is not None:
return from_risk
notional = _pos_float(notional_value)
lev = _pos_float(leverage)
if notional is not None and lev is not None and lev > 0:
return round(notional / lev, 2)
return None
@@ -138,18 +183,31 @@ def repair_stored_margin_capital(
trigger_price: Any = None,
leverage: Any = None,
symbol: Any = None,
stop_loss: Any = None,
risk_amount: Any = None,
initial_stop_loss: Any = None,
) -> Optional[float]:
"""展示/列表:修复已入库的「币数量当基数」旧数据."""
del symbol # 预留按币种阈值;当前用价位启发式即可
"""展示/列表:修复已入库的异常基数;禁止把币数量换算成虚高保证金."""
del symbol # 预留按币种阈值
m = _pos_float(margin_capital)
sl = stop_loss if stop_loss not in (None, "") else initial_stop_loss
from_risk = margin_from_risk_amount(
risk_amount,
trigger_price=trigger_price,
stop_loss=sl,
leverage=leverage,
)
if m is None:
return None
return from_risk
if looks_like_coin_amount_as_margin(
m, trigger_price=trigger_price, leverage=leverage
):
repaired = coin_amount_to_margin_usdt(
m, trigger_price=trigger_price, leverage=leverage
)
if repaired is not None:
return repaired
return from_risk
if from_risk is not None and m > from_risk * 2.5:
# 已入库虚高(如曾用币×价÷杠杆「纠偏」成 384)
return from_risk
return round(m, 2)