修复滚仓
This commit is contained in:
@@ -2267,6 +2267,9 @@ def friendly_okx_error(err, available_usdt=None):
|
||||
return f"交易所下单失败:{clean}"
|
||||
|
||||
|
||||
friendly_exchange_error = friendly_okx_error
|
||||
|
||||
|
||||
def get_exchange_capitals(force=False):
|
||||
ok_live, _ = ensure_okx_live_ready()
|
||||
if not ok_live:
|
||||
|
||||
+23
-5
@@ -97,9 +97,14 @@ def build_strategy_config(
|
||||
def limit_add(ex_sym, direction, amount, price, leverage):
|
||||
m.exchange.set_leverage(int(leverage), ex_sym)
|
||||
side = "buy" if direction == "long" else "sell"
|
||||
params = {}
|
||||
if hasattr(m, "build_gate_order_params"):
|
||||
if hasattr(m, "build_okx_order_params"):
|
||||
params = m.build_okx_order_params(direction, reduce_only=False)
|
||||
elif hasattr(m, "build_binance_order_params"):
|
||||
params = m.build_binance_order_params(direction, reduce_only=False)
|
||||
elif hasattr(m, "build_gate_order_params"):
|
||||
params = m.build_gate_order_params(direction, reduce_only=False)
|
||||
else:
|
||||
params = {}
|
||||
return m.exchange.create_order(ex_sym, "limit", side, float(amount), float(price), params or None)
|
||||
|
||||
def replace_tpsl(ex_sym, direction, sl, tp, order_row):
|
||||
@@ -116,6 +121,21 @@ def build_strategy_config(
|
||||
except Exception:
|
||||
return 0
|
||||
|
||||
def friendly_error(err):
|
||||
fn = getattr(m, "friendly_exchange_error", None) or getattr(
|
||||
m, "friendly_okx_error", None
|
||||
)
|
||||
if not callable(fn):
|
||||
return str(err)
|
||||
try:
|
||||
snap = m.get_available_trading_usdt()
|
||||
except Exception:
|
||||
snap = None
|
||||
try:
|
||||
return fn(err, available_usdt=snap)
|
||||
except TypeError:
|
||||
return fn(err)
|
||||
|
||||
note = trend_disabled_note or (
|
||||
"趋势回调(自动补仓)请在 Gate 趋势机器人实例使用:/strategy/trend"
|
||||
)
|
||||
@@ -138,9 +158,7 @@ def build_strategy_config(
|
||||
"ensure_live_ready": m.ensure_exchange_live_ready,
|
||||
"default_risk_percent": float(getattr(m, "RISK_PERCENT", 2)),
|
||||
"default_leverage": m.infer_leverage,
|
||||
"friendly_error": lambda e: m.friendly_exchange_error(e, available_usdt=m.get_available_trading_usdt())
|
||||
if "friendly_exchange_error" in dir(m)
|
||||
else str(e),
|
||||
"friendly_error": friendly_error,
|
||||
"app_now_str": m.app_now_str,
|
||||
"resolve_fill_price": m.resolve_order_entry_price,
|
||||
"price_fmt": m.format_price_for_symbol,
|
||||
|
||||
+40
-28
@@ -66,7 +66,12 @@ def register_strategy_trading(app: Flask, cfg: dict[str, Any]) -> None:
|
||||
@app.route("/strategy/roll/execute", methods=["POST"])
|
||||
def strategy_roll_execute():
|
||||
data = request.form
|
||||
ok, msg = _roll_execute(cfg, data)
|
||||
try:
|
||||
ok, msg = _roll_execute(cfg, data)
|
||||
except Exception as e:
|
||||
fe = cfg.get("friendly_error")
|
||||
msg = fe(e) if callable(fe) else str(e)
|
||||
ok = False
|
||||
flash(msg)
|
||||
return redirect(url_for("strategy_trading_page"))
|
||||
|
||||
@@ -170,31 +175,35 @@ def _roll_preview_response(cfg: dict, data: dict, json_mode: bool = False) -> di
|
||||
|
||||
|
||||
def _roll_execute(cfg: dict, data: dict) -> tuple[bool, str]:
|
||||
ok_live, reason = cfg["ensure_live_ready"]()
|
||||
if not ok_live:
|
||||
return False, reason or "实盘未就绪"
|
||||
prev = _roll_preview_response(cfg, data)
|
||||
if not prev.get("ok"):
|
||||
return False, prev.get("msg") or "预览失败"
|
||||
preview = prev["preview"]
|
||||
symbol = cfg["normalize_symbol_input"](data.get("symbol") or "")
|
||||
direction = preview["direction"]
|
||||
ex_sym = cfg["normalize_exchange_symbol"](symbol)
|
||||
add_mode = preview["add_mode"]
|
||||
amount = cfg["amount_to_precision"](ex_sym, float(preview["add_amount_raw"]))
|
||||
if amount is None or amount <= 0:
|
||||
return False, "加仓张数低于交易所最小精度"
|
||||
leverage = int(data.get("leverage") or 0) or int(cfg.get("default_leverage", lambda s: 5)(symbol))
|
||||
conn = get_db()
|
||||
init_strategy_tables(conn)
|
||||
mon = _get_active_monitor(conn, cfg, symbol, direction)
|
||||
if not mon:
|
||||
conn.close()
|
||||
return False, "监控单已不存在"
|
||||
rg, legs_done = _get_or_create_roll_group_meta(conn, mon)
|
||||
new_sl = float(preview["new_stop_loss"])
|
||||
tp0 = float(preview["initial_take_profit"])
|
||||
get_db = cfg["get_db"]
|
||||
conn = None
|
||||
try:
|
||||
ok_live, reason = cfg["ensure_live_ready"]()
|
||||
if not ok_live:
|
||||
return False, reason or "实盘未就绪"
|
||||
prev = _roll_preview_response(cfg, data)
|
||||
if not prev.get("ok"):
|
||||
return False, prev.get("msg") or "预览失败"
|
||||
preview = prev["preview"]
|
||||
symbol = cfg["normalize_symbol_input"](data.get("symbol") or "")
|
||||
direction = preview["direction"]
|
||||
ex_sym = cfg["normalize_exchange_symbol"](symbol)
|
||||
add_mode = preview["add_mode"]
|
||||
amount = cfg["amount_to_precision"](ex_sym, float(preview["add_amount_raw"]))
|
||||
if amount is None or amount <= 0:
|
||||
return False, "加仓张数低于交易所最小精度"
|
||||
lev_fn = cfg.get("default_leverage")
|
||||
if not callable(lev_fn):
|
||||
lev_fn = lambda _s: 5
|
||||
leverage = int(data.get("leverage") or 0) or int(lev_fn(symbol))
|
||||
conn = get_db()
|
||||
init_strategy_tables(conn)
|
||||
mon = _get_active_monitor(conn, cfg, symbol, direction)
|
||||
if not mon:
|
||||
return False, "监控单已不存在"
|
||||
rg, legs_done = _get_or_create_roll_group_meta(conn, mon)
|
||||
new_sl = float(preview["new_stop_loss"])
|
||||
tp0 = float(preview["initial_take_profit"])
|
||||
if add_mode == "market":
|
||||
order = cfg["market_add"](ex_sym, direction, amount, leverage)
|
||||
fill = float(cfg.get("resolve_fill_price", lambda o, s, p: p)(order, ex_sym, preview["add_price"]) or preview["add_price"])
|
||||
@@ -228,7 +237,6 @@ def _roll_execute(cfg: dict, data: dict) -> tuple[bool, str]:
|
||||
(legs_done + 1, cfg["app_now_str"](), rg["id"]),
|
||||
)
|
||||
conn.commit()
|
||||
conn.close()
|
||||
return True, f"已挂限价加仓单 #{oid},成交后请在页面点「同步持仓并更新止损」"
|
||||
cfg["replace_tpsl"](ex_sym, direction, new_sl, tp0, mon)
|
||||
conn.execute(
|
||||
@@ -260,12 +268,16 @@ def _roll_execute(cfg: dict, data: dict) -> tuple[bool, str]:
|
||||
(new_sl, mon["id"]),
|
||||
)
|
||||
conn.commit()
|
||||
conn.close()
|
||||
return True, f"滚仓第 {legs_done + 1} 腿已市价成交,交易所止损已更新,止盈仍为首仓 {tp0}"
|
||||
except Exception as e:
|
||||
conn.close()
|
||||
fe = cfg.get("friendly_error")
|
||||
return False, fe(e) if callable(fe) else str(e)
|
||||
finally:
|
||||
if conn is not None:
|
||||
try:
|
||||
conn.close()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
def _get_active_monitor(conn, cfg: dict, symbol: str, direction: str) -> Optional[dict]:
|
||||
|
||||
Reference in New Issue
Block a user