ea429b2694
下单监控增加 entry_model 下拉;平仓写入短标签并预填复盘。Binance/OKX 用趋势 profile,Gate 日内仍用手选 trade_style。 Co-authored-by: Cursor <cursoragent@cursor.com>
203 lines
9.8 KiB
Python
203 lines
9.8 KiB
Python
#!/usr/bin/env python3
|
|
"""Patch binance/okx/gate app.py for entry_model support."""
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
import re
|
|
|
|
REPO = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|
|
|
IMPORT_BLOCK = """from lib.trade.entry_model_lib import (
|
|
build_intraday_entry_reason_options,
|
|
build_trend_div_entry_reason_options,
|
|
enrich_entry_model_display,
|
|
migrate_entry_model_columns,
|
|
order_entry_template_context,
|
|
parse_manual_order_style_fields,
|
|
resolve_trade_record_entry_reason,
|
|
trend_manual_entry_reason_count,
|
|
)
|
|
"""
|
|
|
|
KEY_IMPORT = "from lib.key_monitor.key_auto_order_lib import (\n check_monitor_type_add_allowed,\n effective_entry_reason_options,\n effective_stats_segment_defs,\n load_key_auto_order_enabled,"
|
|
|
|
KEY_IMPORT_WITH_KEY_OPTS = "from lib.key_monitor.key_auto_order_lib import (\n KEY_ENTRY_REASON_OPTIONS,\n check_monitor_type_add_allowed,\n effective_entry_reason_options,\n effective_stats_segment_defs,\n load_key_auto_order_enabled,"
|
|
|
|
|
|
def patch_file(path: str, exchange: str) -> bool:
|
|
with open(path, "r", encoding="utf-8") as f:
|
|
text = f.read()
|
|
orig = text
|
|
|
|
if "from lib.trade.entry_model_lib import" not in text:
|
|
text = text.replace(
|
|
"from lib.trade.trade_policy_app_lib import (",
|
|
IMPORT_BLOCK + "from lib.trade.trade_policy_app_lib import (",
|
|
1,
|
|
)
|
|
|
|
if exchange == "gate":
|
|
old_er = '''# 与用户约定的固定开仓类型
|
|
ENTRY_REASON_OPTIONS = (
|
|
"趋势多头:4h大结构突破前进场,确认条件:三次探顶,5m收敛不创新低",
|
|
"趋势空头:4h大结构突破前进场,确认条件:三次探底,5m收敛不创新高",
|
|
"趋势多头:小分歧低吸入场(左侧),确认条件:二次探底",
|
|
"趋势空头:小分歧高吸入场(左侧),确认条件:二次探顶",
|
|
"波段单:5m顺势突破,确认条件:2根k线+成交量放大+4h同向+日成交量前20",
|
|
"关键位箱体突破",
|
|
"关键位收敛突破",
|
|
"关键位斐波0.618",
|
|
"关键位斐波0.786",
|
|
"关键位假突破",
|
|
"关键位回调触价开仓",
|
|
"关键位突破触价开仓",
|
|
) + STRATEGY_ENTRY_REASON_OPTIONS'''
|
|
new_er = """# 日内户:长句开仓类型 + 关键位 + 策略(大分歧 A/B/小分歧 仅趋势户)
|
|
ENTRY_REASON_OPTIONS = build_intraday_entry_reason_options(
|
|
KEY_ENTRY_REASON_OPTIONS,
|
|
STRATEGY_ENTRY_REASON_OPTIONS,
|
|
)"""
|
|
text = text.replace(old_er, new_er)
|
|
if "KEY_ENTRY_REASON_OPTIONS," not in text.split("load_key_auto_order_enabled")[0]:
|
|
text = text.replace(KEY_IMPORT, KEY_IMPORT_WITH_KEY_OPTS, 1)
|
|
else:
|
|
old_er = '''# 与用户约定的固定开仓类型(仅做这几类单子)
|
|
ENTRY_REASON_OPTIONS = (
|
|
"趋势多头:4h大结构突破前进场,确认条件:三次探顶,5m收敛不创新低",
|
|
"趋势空头:4h大结构突破前进场,确认条件:三次探底,5m收敛不创新高",
|
|
"趋势多头:小分歧低吸入场(左侧),确认条件:二次探底",
|
|
"趋势空头:小分歧高吸入场(左侧),确认条件:二次探顶",
|
|
"波段单:5m顺势突破,确认条件:2根k线+成交量放大+4h同向+日成交量前20",
|
|
"关键位箱体突破",
|
|
"关键位收敛突破",
|
|
"关键位斐波0.618",
|
|
"关键位斐波0.786",
|
|
"关键位假突破",
|
|
"关键位回调触价开仓",
|
|
"关键位突破触价开仓",
|
|
) + STRATEGY_ENTRY_REASON_OPTIONS'''
|
|
new_er = """# 趋势户:大分歧A/B/小分歧 + 策略(关键位本实例关闭)
|
|
ENTRY_REASON_OPTIONS = build_trend_div_entry_reason_options(STRATEGY_ENTRY_REASON_OPTIONS)"""
|
|
text = text.replace(old_er, new_er)
|
|
|
|
if "migrate_entry_model_columns(conn)" not in text:
|
|
text = text.replace(
|
|
" conn.commit()\n conn.close()\n\n\ndef get_db",
|
|
" migrate_entry_model_columns(conn)\n conn.commit()\n conn.close()\n\n\ndef get_db",
|
|
1,
|
|
)
|
|
|
|
text = re.sub(
|
|
r" er = \(\n \(entry_reason or \"\"\)\.strip\(\)\n or entry_reason_from_key_signal\(kst\)\n or entry_reason_for_monitor_type\(monitor_type\)\n or \"\"\n \)",
|
|
""" er = resolve_trade_record_entry_reason(
|
|
entry_reason=entry_reason,
|
|
entry_model=entry_model,
|
|
key_signal_type=kst,
|
|
monitor_type=monitor_type,
|
|
entry_reason_from_key_signal=entry_reason_from_key_signal,
|
|
entry_reason_for_monitor_type=entry_reason_for_monitor_type,
|
|
)""",
|
|
text,
|
|
count=1,
|
|
)
|
|
|
|
if "entry_model=None," not in text:
|
|
text = text.replace(
|
|
" entry_reason=None,\n trend_plan_id=None,",
|
|
" entry_reason=None,\n entry_model=None,\n trend_plan_id=None,",
|
|
1,
|
|
)
|
|
|
|
if "enrich_entry_model_display(item)" not in text:
|
|
text = text.replace(
|
|
" enrich_order_display_fields(item, calc_rr_ratio)\n try:",
|
|
" enrich_order_display_fields(item, calc_rr_ratio)\n enrich_entry_model_display(item)\n try:",
|
|
1,
|
|
)
|
|
|
|
text = text.replace(
|
|
""" trade_style = (d.get("trade_style") or DEFAULT_TRADE_STYLE or "trend").strip().lower()
|
|
if trade_style not in ("trend", "swing"):
|
|
trade_style = "trend"
|
|
available_usdt = get_available_trading_usdt()""",
|
|
""" trade_style, entry_model, style_err = parse_manual_order_style_fields(
|
|
TRADE_POLICY, d, default_trade_style=DEFAULT_TRADE_STYLE or "trend"
|
|
)
|
|
if style_err:
|
|
conn.close()
|
|
flash(style_err)
|
|
return redirect("/trade")
|
|
available_usdt = get_available_trading_usdt()""",
|
|
1,
|
|
)
|
|
|
|
old_insert = (
|
|
'"INSERT INTO order_monitors (symbol, exchange_symbol, direction, trigger_price, stop_loss, initial_stop_loss, take_profit, margin_capital, leverage, trade_style, risk_percent, risk_amount, breakeven_rr_trigger, breakeven_offset_pct, breakeven_step_r, breakeven_armed, breakeven_price, breakeven_enabled, notional_value, position_ratio, base_amount, order_amount, exchange_order_id, opened_at, opened_at_ms, session_date, monitor_type, time_close_enabled, time_close_hours, time_close_at_ms) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",\n'
|
|
" (\n"
|
|
" symbol, exchange_symbol, direction, trigger_price, stop_loss, stop_loss, take_profit,\n"
|
|
" margin_capital, leverage, trade_style, risk_percent_db, risk_amount_final, breakeven_rr_trigger, breakeven_offset_pct, breakeven_step_r, 0, breakeven_price,\n"
|
|
" breakeven_enabled,\n"
|
|
" notional_value, position_ratio, base_amount, amount, open_order_id, opened_at_bj, opened_at_ms, trading_day,\n"
|
|
" ORDER_MONITOR_TYPE_MANUAL,\n"
|
|
" tc_en, tc_h, tc_at,\n"
|
|
" )"
|
|
)
|
|
new_insert = (
|
|
'"INSERT INTO order_monitors (symbol, exchange_symbol, direction, trigger_price, stop_loss, initial_stop_loss, take_profit, margin_capital, leverage, trade_style, entry_model, risk_percent, risk_amount, breakeven_rr_trigger, breakeven_offset_pct, breakeven_step_r, breakeven_armed, breakeven_price, breakeven_enabled, notional_value, position_ratio, base_amount, order_amount, exchange_order_id, opened_at, opened_at_ms, session_date, monitor_type, time_close_enabled, time_close_hours, time_close_at_ms) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",\n'
|
|
" (\n"
|
|
" symbol, exchange_symbol, direction, trigger_price, stop_loss, stop_loss, take_profit,\n"
|
|
" margin_capital, leverage, trade_style, entry_model, risk_percent_db, risk_amount_final, breakeven_rr_trigger, breakeven_offset_pct, breakeven_step_r, 0, breakeven_price,\n"
|
|
" breakeven_enabled,\n"
|
|
" notional_value, position_ratio, base_amount, amount, open_order_id, opened_at_bj, opened_at_ms, trading_day,\n"
|
|
" ORDER_MONITOR_TYPE_MANUAL,\n"
|
|
" tc_en, tc_h, tc_at,\n"
|
|
" )"
|
|
)
|
|
text = text.replace(old_insert, new_insert)
|
|
|
|
text = text.replace(
|
|
""" effective_entry_reason_options(
|
|
ENTRY_REASON_OPTIONS,
|
|
POSITION_SIZING_MODE,
|
|
KEY_AUTO_ORDER_ENABLED,
|
|
)""",
|
|
""" effective_entry_reason_options(
|
|
ENTRY_REASON_OPTIONS,
|
|
POSITION_SIZING_MODE,
|
|
KEY_AUTO_ORDER_ENABLED,
|
|
trend_manual_count=trend_manual_entry_reason_count(TRADE_POLICY),
|
|
)""",
|
|
1,
|
|
)
|
|
|
|
if "**order_entry_template_context(TRADE_POLICY)," not in text:
|
|
text = text.replace(
|
|
" trade_policy=trade_policy_template_context(TRADE_POLICY),",
|
|
" trade_policy=trade_policy_template_context(TRADE_POLICY),\n **order_entry_template_context(TRADE_POLICY),",
|
|
1,
|
|
)
|
|
|
|
# insert_trade_record from order row: add entry_model
|
|
text = re.sub(
|
|
r"(insert_trade_record\(\n\s+conn,\n(?:[^\n]+\n)+?\s+trade_style=r\[\"trade_style\"\],\n)",
|
|
r"\1 entry_model=(r[\"entry_model\"] if \"entry_model\" in r.keys() else None),\n",
|
|
text,
|
|
)
|
|
|
|
if text != orig:
|
|
with open(path, "w", encoding="utf-8", newline="\n") as f:
|
|
f.write(text)
|
|
return True
|
|
return False
|
|
|
|
|
|
def main():
|
|
for ex in ("binance", "okx", "gate"):
|
|
path = os.path.join(REPO, f"crypto_monitor_{ex}", "app.py")
|
|
changed = patch_file(path, ex)
|
|
print(f"{ex}: {'patched' if changed else 'no change'}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|