fix: Gate hub close sync and trade record open stop-loss snapshot
Sync order monitors from Gate position history after hub flat close. Store and display initial_stop_loss in trade records instead of post-amend exchange stops. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
"""Gate 平仓历史匹配(fetch_positions_history),供 reconcile / 中控全平同步共用。"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
|
||||
def unified_symbol_for_match(symbol_str: str) -> str:
|
||||
x = (symbol_str or "").strip().upper()
|
||||
if ":" in x:
|
||||
x = x.split(":")[0]
|
||||
return x
|
||||
|
||||
|
||||
def pick_gate_position_close(
|
||||
hist: list[dict],
|
||||
symbol: str,
|
||||
direction: str,
|
||||
*,
|
||||
opened_at_ms: int | None = None,
|
||||
closed_at_ms: int | None = None,
|
||||
used_keys: set[str] | None = None,
|
||||
max_close_delta_ms: int = 25 * 60 * 1000,
|
||||
) -> dict | None:
|
||||
"""
|
||||
从 Gate 平仓历史列表中选取与 symbol/direction/开仓时间最匹配的一条。
|
||||
返回 normalize 后的 dict(含 close_ms、pnl、sync_key 等),无匹配则 None。
|
||||
"""
|
||||
if not hist:
|
||||
return None
|
||||
sym_u = unified_symbol_for_match(symbol)
|
||||
dir_l = (direction or "long").strip().lower()
|
||||
if dir_l not in ("long", "short"):
|
||||
return None
|
||||
used = used_keys or set()
|
||||
ref_ms = closed_at_ms or opened_at_ms
|
||||
best = None
|
||||
best_d = None
|
||||
for h in hist:
|
||||
if not isinstance(h, dict):
|
||||
continue
|
||||
sk = h.get("sync_key")
|
||||
if not sk or sk in used:
|
||||
continue
|
||||
if h.get("symbol_u") != sym_u:
|
||||
continue
|
||||
if (h.get("side") or "").strip().lower() != dir_l:
|
||||
continue
|
||||
cm = h.get("close_ms")
|
||||
if cm is None:
|
||||
continue
|
||||
if opened_at_ms is not None:
|
||||
if cm < opened_at_ms - 15 * 60 * 1000:
|
||||
continue
|
||||
if cm > opened_at_ms + 15 * 86400 * 1000:
|
||||
continue
|
||||
if ref_ms is not None:
|
||||
d = abs(int(cm) - int(ref_ms))
|
||||
else:
|
||||
d = 0
|
||||
if best_d is None or d < best_d:
|
||||
best_d = d
|
||||
best = h
|
||||
if best is None or best_d is None:
|
||||
return None
|
||||
if ref_ms is not None and best_d > max_close_delta_ms:
|
||||
return None
|
||||
return best
|
||||
Reference in New Issue
Block a user