cce26e87b5
Net PnL (after estimated close fees) drives auto close; Plan/Settings expose the choice. Co-authored-by: Cursor <cursoragent@cursor.com>
50 lines
1.4 KiB
Python
50 lines
1.4 KiB
Python
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass
|
|
|
|
EXIT_MODE_FIXED = "fixed_usdt"
|
|
EXIT_MODE_PREMIUM = "premium_multiple"
|
|
|
|
|
|
@dataclass(slots=True)
|
|
class ExitDecision:
|
|
should_close: bool
|
|
reason: str = ""
|
|
target: float = 0.0
|
|
|
|
|
|
def resolve_exit_target(
|
|
*,
|
|
exit_mode: str,
|
|
net_profit_target: float,
|
|
premium_exit_multiple: float,
|
|
initial_premium: float,
|
|
) -> tuple[float, str]:
|
|
"""返回 (出场目标金额 USDT, 模式标记)。"""
|
|
mode = (exit_mode or EXIT_MODE_FIXED).strip().lower()
|
|
if mode == EXIT_MODE_PREMIUM:
|
|
mult = max(0.0, float(premium_exit_multiple))
|
|
return float(initial_premium) * mult, EXIT_MODE_PREMIUM
|
|
return float(net_profit_target), EXIT_MODE_FIXED
|
|
|
|
|
|
def check_exits(
|
|
*,
|
|
net_pnl: float,
|
|
exit_mode: str,
|
|
net_profit_target: float,
|
|
premium_exit_multiple: float,
|
|
initial_premium: float,
|
|
) -> ExitDecision:
|
|
"""净盈利(预估全平后)≥ 所选模式目标则全平。"""
|
|
target, mode = resolve_exit_target(
|
|
exit_mode=exit_mode,
|
|
net_profit_target=net_profit_target,
|
|
premium_exit_multiple=premium_exit_multiple,
|
|
initial_premium=initial_premium,
|
|
)
|
|
if target > 0 and net_pnl + 1e-9 >= target:
|
|
reason = "premium_multiple" if mode == EXIT_MODE_PREMIUM else "fixed_usdt"
|
|
return ExitDecision(True, reason, target)
|
|
return ExitDecision(False, "", target)
|