增加一键保本

This commit is contained in:
dekun
2026-05-28 12:31:16 +08:00
parent 6184e7a11f
commit 96dd4a041c
9 changed files with 801 additions and 5 deletions
+75
View File
@@ -73,6 +73,7 @@ from key_sl_tp_lib import (
sl_tp_mode_label,
sl_tp_plan_summary_text,
)
from order_manual_breakeven_lib import apply_order_manual_breakeven
from key_monitor_lib import (
KEY_DIRECTION_WATCH,
KEY_MONITOR_ALERT_ONLY_TYPES,
@@ -6207,6 +6208,80 @@ def api_order_cancel_tpsl(order_id):
return jsonify({"ok": False, "msg": friendly_exchange_error(e)}), 400
@app.route("/api/order/<int:order_id>/manual_breakeven", methods=["POST"])
@login_required
def api_order_manual_breakeven(order_id):
data = request.get_json(silent=True) or {}
try:
offset_pct = float(
data.get("offset_pct", os.getenv("MANUAL_BREAKEVEN_OFFSET_PCT", "0.2"))
)
except (TypeError, ValueError):
return jsonify({"ok": False, "msg": "offset_pct 无效"}), 400
if offset_pct < 0 or offset_pct > 10:
return jsonify({"ok": False, "msg": "偏移%须在 010 之间"}), 400
conn = get_db()
row = conn.execute(
"SELECT * FROM order_monitors WHERE id=? AND status='active'",
(order_id,),
).fetchone()
if not row:
conn.close()
return jsonify({"ok": False, "msg": "持仓不存在或已结束"}), 404
ok, err, new_sl = apply_order_manual_breakeven(
row,
offset_pct,
calc_stop_fn=calc_trend_manual_breakeven_stop,
round_price_fn=round_price_to_exchange,
resolve_ex_sym_fn=resolve_monitor_exchange_symbol,
get_position_fn=get_live_position_contracts,
replace_tpsl_fn=replace_active_monitor_tpsl_on_exchange,
)
if not ok:
conn.close()
return jsonify({"ok": False, "msg": err or "保本失败"}), 400
conn.execute(
"UPDATE order_monitors SET stop_loss=?, breakeven_armed=1, breakeven_price=? WHERE id=?",
(new_sl, new_sl, order_id),
)
conn.commit()
sym = row["symbol"]
direction = row["direction"]
ex_sym = resolve_monitor_exchange_symbol(row)
take_profit = float(row["take_profit"] or 0)
slots = fetch_exchange_tpsl_slots(
ex_sym, direction, plan_sl=new_sl, plan_tp=take_profit
)
conn.close()
try:
entry = float(row["trigger_price"] or 0)
send_wechat_msg(
"\n".join(
[
f"# ✅ {sym} 一键保本",
f"**账户:{_wechat_account_label()}**",
f"- 方向:{'做多' if direction == 'long' else '做空'}",
f"- 成交价:{format_price_for_symbol(sym, entry)}",
f"- 偏移:{offset_pct}%(相对成交价)",
f"- 新止损:{format_price_for_symbol(sym, new_sl)}",
"- 交易所:已更新止盈止损",
]
)
)
except Exception:
pass
return jsonify(
{
"ok": True,
"msg": "已一键保本",
"stop_loss": new_sl,
"stop_loss_display": format_price_for_symbol(sym, new_sl),
"breakeven_armed": True,
"exchange_tpsl": slots,
}
)
@app.route("/api/order/<int:order_id>/place_tpsl", methods=["POST"])
@login_required
def api_order_place_tpsl(order_id):