Files
crypto_monitor_user/scripts/patch_entry_model_instances.py
T
dekun 53863559f4 Initialize crypto_monitor_user (user edition) from monitor codebase.
Retarget git remote, install path, and deploy docs from crypto_monitor to crypto_monitor_user.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-17 16:18:13 +08:00

203 lines
9.5 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()