115 lines
4.6 KiB
Python
115 lines
4.6 KiB
Python
"""各交易所 app 模块 → strategy_register 配置(统一工厂)。"""
|
|
from __future__ import annotations
|
|
|
|
from typing import Any
|
|
|
|
|
|
def build_strategy_config(app_module: Any, *, trend_enabled: bool = False, trend_disabled_note: str = "") -> dict:
|
|
m = app_module
|
|
|
|
def get_trading_capital_usdt(conn):
|
|
if hasattr(m, "get_exchange_capitals"):
|
|
_, tc = m.get_exchange_capitals(force=True)
|
|
if tc is not None:
|
|
return float(tc)
|
|
if hasattr(m, "get_available_trading_usdt"):
|
|
snap = m.get_available_trading_usdt()
|
|
if snap is not None:
|
|
return float(snap)
|
|
day = m.get_trading_day(m.app_now())
|
|
row = m.ensure_session(conn, day)
|
|
return float(row["current_capital"])
|
|
|
|
def get_position(ex_sym, direction):
|
|
qty = m.get_live_position_contracts(ex_sym, direction)
|
|
entry = None
|
|
try:
|
|
rows = m.exchange.fetch_positions([ex_sym])
|
|
for p in rows or []:
|
|
matcher = getattr(m, "_row_matches_monitor_direction", None)
|
|
if matcher and not matcher(direction, p):
|
|
continue
|
|
contracts = getattr(m, "_position_row_effective_contracts", lambda x: abs(float(x.get("contracts") or 0)))(p)
|
|
if contracts <= 0:
|
|
continue
|
|
coerce = getattr(m, "_coerce_float", None)
|
|
if coerce:
|
|
entry = coerce(
|
|
p.get("entryPrice"),
|
|
p.get("average"),
|
|
(p.get("info") or {}).get("entryPrice"),
|
|
)
|
|
if entry:
|
|
break
|
|
except Exception:
|
|
pass
|
|
return {"contracts": float(qty or 0), "entry_price": entry}
|
|
|
|
def amount_to_precision(ex_sym, amount):
|
|
try:
|
|
return float(m.exchange.amount_to_precision(ex_sym, float(amount)))
|
|
except Exception:
|
|
return None
|
|
|
|
def price_to_precision(ex_sym, price):
|
|
try:
|
|
return float(m.exchange.price_to_precision(ex_sym, float(price)))
|
|
except Exception:
|
|
return None
|
|
|
|
def market_add(ex_sym, direction, amount, leverage):
|
|
return m.place_exchange_order(ex_sym, direction, amount, leverage, stop_loss=None, take_profit=None)
|
|
|
|
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"):
|
|
params = m.build_gate_order_params(direction, reduce_only=False)
|
|
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):
|
|
row = order_row or {"symbol": ex_sym, "exchange_symbol": ex_sym, "direction": direction}
|
|
m.replace_active_monitor_tpsl_on_exchange(row, sl, tp)
|
|
|
|
def count_trends(conn):
|
|
try:
|
|
return int(
|
|
conn.execute(
|
|
"SELECT COUNT(*) FROM trend_pullback_plans WHERE status='active'"
|
|
).fetchone()[0]
|
|
)
|
|
except Exception:
|
|
return 0
|
|
|
|
note = trend_disabled_note or (
|
|
"趋势回调(自动补仓)请在 Gate 趋势机器人实例使用:/strategy/trend"
|
|
)
|
|
return {
|
|
"exchange_display": getattr(m, "EXCHANGE_DISPLAY_NAME", ""),
|
|
"trend_enabled": trend_enabled,
|
|
"trend_disabled_note": note,
|
|
"login_required": m.login_required,
|
|
"get_db": m.get_db,
|
|
"normalize_symbol_input": m.normalize_symbol_input,
|
|
"normalize_exchange_symbol": m.normalize_exchange_symbol,
|
|
"get_price": m.get_price,
|
|
"get_trading_capital_usdt": get_trading_capital_usdt,
|
|
"get_position": get_position,
|
|
"amount_to_precision": amount_to_precision,
|
|
"price_to_precision": price_to_precision,
|
|
"market_add": market_add,
|
|
"limit_add": limit_add,
|
|
"replace_tpsl": replace_tpsl,
|
|
"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),
|
|
"app_now_str": m.app_now_str,
|
|
"resolve_fill_price": m.resolve_order_entry_price,
|
|
"price_fmt": m.format_price_for_symbol,
|
|
"count_active_trend_plans": count_trends if trend_enabled else count_trends,
|
|
}
|