feat: add fixed RR stop-loss mode for manual live orders on all instances

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-06-08 20:57:29 +08:00
parent 38f4280bb8
commit a5c6e0c5b6
10 changed files with 555 additions and 310 deletions
+22 -56
View File
@@ -40,6 +40,11 @@ from ai_review_lib import (
collect_images_for_ai_review,
journal_row_lines_for_ai,
)
from manual_sltp_lib import (
normalize_open_sltp_mode,
resolve_entrust_sltp_prices,
resolve_open_sltp_prices,
)
from position_sizing_lib import (
assert_open_source_allowed,
compute_full_margin_sizing,
@@ -3351,33 +3356,14 @@ def cancel_gate_tpsl_slot(exchange_symbol, slot):
def _resolve_tpsl_prices_for_manual(
direction, live_price, sltp_mode, data, *, fallback_sl=None, fallback_tp=None
):
sltp_mode = (sltp_mode or "price").strip().lower()
if sltp_mode == "pct":
sl_pct = float(data.get("sl_pct") or 0)
tp_pct = float(data.get("tp_pct") or 0)
if sl_pct <= 0 or tp_pct <= 0:
raise ValueError("百分比止盈止损须为正数")
sl_ratio = sl_pct / 100.0
tp_ratio = tp_pct / 100.0
entry = float(live_price)
if direction == "short":
stop_loss = entry * (1 + sl_ratio)
take_profit = entry * (1 - tp_ratio)
else:
stop_loss = entry * (1 - sl_ratio)
take_profit = entry * (1 + tp_ratio)
else:
stop_loss = float(data.get("sl") or data.get("stop_loss") or 0)
take_profit = float(data.get("tp") or data.get("take_profit") or data.get("tgt") or 0)
if stop_loss <= 0 and fallback_sl is not None:
stop_loss = float(fallback_sl)
if take_profit <= 0 and fallback_tp is not None:
take_profit = float(fallback_tp)
if stop_loss <= 0:
raise ValueError("止损价格须大于 0")
if take_profit <= 0:
raise ValueError("请填写止盈价格,或保留原计划止盈")
return stop_loss, take_profit
return resolve_entrust_sltp_prices(
direction,
live_price,
sltp_mode,
data,
fallback_sl=fallback_sl,
fallback_tp=fallback_tp,
)
def cancel_all_open_orders_for_symbol(exchange_symbol):
@@ -6345,35 +6331,15 @@ def add_order():
conn.close()
flash("获取交易所实时价格失败,请稍后重试")
return redirect("/")
sltp_mode = (d.get("sltp_mode") or "price").strip().lower()
if sltp_mode not in ("price", "pct"):
sltp_mode = "price"
if sltp_mode == "pct":
try:
sl_pct = float(d.get("sl_pct") or 0)
tp_pct = float(d.get("tp_pct") or 0)
if sl_pct <= 0 or tp_pct <= 0:
raise ValueError("pct")
sl_ratio = sl_pct / 100.0
tp_ratio = tp_pct / 100.0
if direction == "short":
stop_loss = float(live_price) * (1 + sl_ratio)
take_profit = float(live_price) * (1 - tp_ratio)
else:
stop_loss = float(live_price) * (1 - sl_ratio)
take_profit = float(live_price) * (1 + tp_ratio)
except Exception:
conn.close()
flash("百分比止盈止损参数错误,请填写正数百分比")
return redirect("/")
else:
try:
stop_loss = float(d["sl"])
take_profit = float(d["tgt"])
except Exception:
conn.close()
flash("价格参数格式错误")
return redirect("/")
sltp_mode = normalize_open_sltp_mode(d.get("sltp_mode"))
try:
stop_loss, take_profit = resolve_open_sltp_prices(
direction, live_price, sltp_mode, d
)
except ValueError as e:
conn.close()
flash(str(e) or "止盈止损参数错误")
return redirect("/")
if stop_loss <= 0 or take_profit <= 0:
conn.close()
flash("价格参数必须大于0")