增加趋势回调

This commit is contained in:
dekun
2026-05-23 11:33:01 +08:00
parent fc8f9b70da
commit 4439bedcb7
12 changed files with 1419 additions and 194 deletions
+87 -2
View File
@@ -2228,6 +2228,7 @@ def insert_trade_record(
exchange_trade_id=None,
key_signal_type=None,
entry_reason=None,
trend_plan_id=None,
):
hold_minutes = calc_hold_minutes(hold_seconds)
open_ts = opened_at or app_now_str()
@@ -2238,12 +2239,13 @@ def insert_trade_record(
snap_sl = initial_stop_loss if initial_stop_loss not in (None, "") else stop_loss
er = (entry_reason or "").strip() or entry_reason_from_key_signal(kst) or ""
conn.execute(
"INSERT INTO trade_records (symbol,monitor_type,key_signal_type,direction,trigger_price,stop_loss,initial_stop_loss,take_profit,margin_capital,leverage,pnl_amount,hold_seconds,trade_style,risk_amount,planned_rr,actual_rr,hold_minutes,opened_at,opened_at_ms,closed_at,closed_at_ms,result,miss_reason,exchange_trade_id,entry_reason) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",
"INSERT INTO trade_records (symbol,monitor_type,key_signal_type,direction,trigger_price,stop_loss,initial_stop_loss,take_profit,margin_capital,leverage,pnl_amount,hold_seconds,trade_style,risk_amount,planned_rr,actual_rr,hold_minutes,opened_at,opened_at_ms,closed_at,closed_at_ms,result,miss_reason,exchange_trade_id,entry_reason,trend_plan_id) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",
(
symbol, monitor_type, kst, direction, trigger_price, snap_sl, snap_sl, take_profit,
margin_capital, leverage, pnl_amount, hold_seconds,
trade_style, risk_amount, planned_rr, actual_rr, hold_minutes,
open_ts, open_ts_ms, close_ts, close_ts_ms, result, miss_reason, exchange_trade_id, er or None
open_ts, open_ts_ms, close_ts, close_ts_ms, result, miss_reason, exchange_trade_id, er or None,
trend_plan_id,
)
)
@@ -3000,6 +3002,76 @@ def _gate_place_tp_sl_orders(exchange_symbol, direction, contracts_amount, stop_
)
def _gate_place_stop_loss_only_position(exchange_symbol, direction, stop_loss):
"""Gate 永续:仅挂仓位类止损触发单(趋势回调用)。"""
ensure_markets_loaded()
market = exchange.market(exchange_symbol)
if not market.get("swap"):
raise RuntimeError("仅支持永续合约 symbol")
settle = market["settleId"]
contract = market["id"]
order_type = "close-long-position" if direction == "long" else "close-short-position"
close_side = "sell" if direction == "long" else "buy"
sl_rule = 2 if close_side == "sell" else 1
initial = {
"contract": contract,
"size": 0,
"price": "0",
"close": True,
"reduce_only": True,
"tif": "ioc",
"text": "api",
}
if GATE_POS_MODE == "hedge":
initial["auto_size"] = "close_long" if direction == "long" else "close_short"
initial["close"] = False
sl_s = exchange.price_to_precision(exchange_symbol, float(stop_loss))
def _payload(trigger_price, rule):
trig = {
"strategy_type": 0,
"price_type": GATE_TPSL_PRICE_TYPE,
"price": trigger_price,
"rule": rule,
}
if GATE_TPSL_TRIGGER_EXPIRATION > 0:
trig["expiration"] = GATE_TPSL_TRIGGER_EXPIRATION
return {
"settle": settle,
"initial": dict(initial),
"trigger": trig,
"order_type": order_type,
}
last_err = None
for attempt in range(8):
try:
exchange.privateFuturesPostSettlePriceOrders(_payload(sl_s, sl_rule))
return
except Exception as e:
last_err = e
time.sleep(0.2 * (attempt + 1))
raise RuntimeError(f"交易所未接受仅止损仓位触发单:{last_err}")
def calc_trend_manual_breakeven_stop(direction, entry_price, offset_pct=None):
try:
e = float(entry_price)
pct = float(
offset_pct
if offset_pct is not None
else float(os.getenv("TREND_PULLBACK_MANUAL_BREAKEVEN_OFFSET_PCT", "0.3"))
)
except (TypeError, ValueError):
return None
if e <= 0:
return None
direction = (direction or "long").strip().lower()
if direction == "short":
return e * (1.0 - pct / 100.0)
return e * (1.0 + pct / 100.0)
def ensure_markets_loaded(force=False):
global MARKETS_LOADED
if force or not MARKETS_LOADED:
@@ -5290,6 +5362,11 @@ def background_task():
check_fib_key_monitors()
check_key_monitors()
check_order_monitors()
cfg = app.extensions.get("strategy_trend_cfg")
if cfg:
from strategy_trend_register import check_trend_pullback_plans
check_trend_pullback_plans(cfg)
except:
pass
time.sleep(MONITOR_POLL_SECONDS)
@@ -5668,6 +5745,12 @@ def render_main_page(page="trade"):
strategy_extra = strategy_page_template_vars(
conn, page, default_risk_percent=float(RISK_PERCENT)
)
if page == "strategy_trend":
cfg = app.extensions.get("strategy_trend_cfg")
if cfg:
from strategy_trend_register import load_trend_page_context
strategy_extra.update(load_trend_page_context(conn, request, cfg))
conn.close()
return render_template(
"index.html",
@@ -7756,8 +7839,10 @@ def strategy_roll_page():
from strategy_register import install_strategy_trading
from strategy_trend_register import install_strategy_trend
install_strategy_trading(app, _REPO_ROOT, app_module=sys.modules[__name__])
install_strategy_trend(app, _REPO_ROOT, app_module=sys.modules[__name__])
# 启动