14c6ba51a8
Co-authored-by: Cursor <cursoragent@cursor.com>
77 lines
2.3 KiB
Python
77 lines
2.3 KiB
Python
"""交易组持仓周期:目标出场以策略平仓时刻为准;永续先平则以永续平仓为准。"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import Any, Mapping, Sequence
|
|
|
|
# 目标平仓(含 15U / 权利金倍数 / 只平永续)
|
|
_TARGET_REASONS = frozenset({"fixed_usdt", "premium_multiple", "target_perp_only"})
|
|
|
|
|
|
def _ts(v: Any) -> int | None:
|
|
if v is None:
|
|
return None
|
|
try:
|
|
n = int(v)
|
|
except (TypeError, ValueError):
|
|
return None
|
|
return n if n > 0 else None
|
|
|
|
|
|
def first_perp_close_ts_ms(fills: Sequence[Mapping[str, Any]]) -> int | None:
|
|
"""永续平仓成交时间(目标只平永续时作为持仓结束时刻)。"""
|
|
best: int | None = None
|
|
for f in fills:
|
|
if str(f.get("leg") or "") != "perp":
|
|
continue
|
|
if str(f.get("action") or "") != "close":
|
|
continue
|
|
ts = _ts(f.get("ts_ms"))
|
|
if ts is None:
|
|
continue
|
|
if best is None or ts < best:
|
|
best = ts
|
|
return best
|
|
|
|
|
|
def hold_timing(
|
|
group: Mapping[str, Any], fills: Sequence[Mapping[str, Any]]
|
|
) -> dict[str, Any]:
|
|
"""
|
|
返回展示用开仓/平仓/持仓时长。
|
|
|
|
- 开仓:groups.open_at_ms
|
|
- 平仓(策略持仓周期):
|
|
- `target_perp_only` / `option_residual`:永续平仓 fill 时间
|
|
- 其它已平:groups.close_at_ms(缺则回退成交)
|
|
"""
|
|
open_ms = _ts(group.get("open_at_ms"))
|
|
status = str(group.get("status") or "")
|
|
reason = str(group.get("close_reason") or "")
|
|
group_close = _ts(group.get("close_at_ms"))
|
|
perp_close = first_perp_close_ts_ms(fills)
|
|
|
|
use_perp = reason == "target_perp_only" or status == "option_residual"
|
|
if use_perp:
|
|
close_ms = perp_close or group_close
|
|
basis = "perp"
|
|
elif status == "open":
|
|
close_ms = None
|
|
basis = "open"
|
|
else:
|
|
close_ms = group_close
|
|
if close_ms is None and reason in _TARGET_REASONS:
|
|
close_ms = perp_close
|
|
basis = "group"
|
|
|
|
hold_ms: int | None = None
|
|
if open_ms is not None and close_ms is not None and close_ms >= open_ms:
|
|
hold_ms = close_ms - open_ms
|
|
|
|
return {
|
|
"hold_open_at_ms": open_ms,
|
|
"hold_close_at_ms": close_ms,
|
|
"hold_ms": hold_ms,
|
|
"hold_basis": basis,
|
|
}
|