Files
crypto_monitor/scripts/apply_time_close_patches.py
dekun 959593cdab feat: add timed position close (1h/2h/4h) for key levels and live orders
Program monitors open positions and market-closes at deadline; UI shows label and countdown on instance and hub boards.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-11 19:30:16 +08:00

413 lines
22 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
"""对 binance/okx/gate_bot 应用与 gate 相同的时间平仓代码替换。"""
from __future__ import annotations
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
FILES = [
ROOT / "crypto_monitor_binance" / "app.py",
ROOT / "crypto_monitor_okx" / "app.py",
ROOT / "crypto_monitor_gate_bot" / "app.py",
]
REPLACEMENTS: list[tuple[str, str]] = [
(
"def _market_open_for_key_monitor(\n conn,\n symbol,\n direction,\n exchange_symbol,\n stop_loss,\n take_profit,\n key_signal_type=None,\n breakeven_enabled=0,\n):",
"def _market_open_for_key_monitor(\n conn,\n symbol,\n direction,\n exchange_symbol,\n stop_loss,\n take_profit,\n key_signal_type=None,\n breakeven_enabled=0,\n time_close_enabled=0,\n time_close_hours=None,\n):",
),
(
"def _add_false_breakout_key_monitor(\n conn, symbol, direction_sel, upper_px, lower_px, key_px, breakeven_enabled=0,\n):",
"def _add_false_breakout_key_monitor(\n conn, symbol, direction_sel, upper_px, lower_px, key_px, breakeven_enabled=0,\n time_close_enabled=0, time_close_hours=None,\n):",
),
(
"def _add_fib_key_monitor(conn, symbol, direction_sel, mt, upper_px, lower_px, breakeven_enabled=0):",
"def _add_fib_key_monitor(\n conn, symbol, direction_sel, mt, upper_px, lower_px, breakeven_enabled=0,\n time_close_enabled=0, time_close_hours=None,\n):",
),
(
" key_sig = typ if typ in KEY_MONITOR_AUTO_TYPES else None\n be_on = breakeven_enabled_from_row(r, 0)\n ok_trade, trade_err, det = _market_open_for_key_monitor(\n conn,\n sym,\n direction,\n exchange_symbol,\n sl_raw,\n tp_raw,\n key_signal_type=key_sig,\n breakeven_enabled=1 if be_on else 0,\n )",
" key_sig = typ if typ in KEY_MONITOR_AUTO_TYPES else None\n be_on = breakeven_enabled_from_row(r, 0)\n tc_en, tc_h, _ = time_close_settings_from_row(r)\n ok_trade, trade_err, det = _market_open_for_key_monitor(\n conn,\n sym,\n direction,\n exchange_symbol,\n sl_raw,\n tp_raw,\n key_signal_type=key_sig,\n breakeven_enabled=1 if be_on else 0,\n time_close_enabled=tc_en,\n time_close_hours=tc_h,\n )",
),
(
" res = None\n # 做多\n if direction == \"long\":\n if p >= take_profit: res = \"止盈\"\n elif p <= stop_loss: res = \"止损\"\n # 做空\n elif direction == \"short\":\n if p <= take_profit: res = \"止盈\"\n elif p >= stop_loss: res = \"止损\"",
" res = None\n if should_trigger_time_close(r):\n res = TIME_CLOSE_RESULT\n # 做多\n if not res and direction == \"long\":\n if p >= take_profit: res = \"止盈\"\n elif p <= stop_loss: res = \"止损\"\n # 做空\n elif not res and direction == \"short\":\n if p <= take_profit: res = \"止盈\"\n elif p >= stop_loss: res = \"止损\"",
),
(
' "SELECT id,symbol,exchange_symbol,direction,trigger_price,stop_loss,initial_stop_loss,take_profit,margin_capital,leverage FROM order_monitors WHERE status=\'active\'"',
' "SELECT id,symbol,exchange_symbol,direction,trigger_price,stop_loss,initial_stop_loss,take_profit,margin_capital,leverage,"\n "time_close_enabled,time_close_hours,time_close_at_ms,opened_at_ms FROM order_monitors WHERE status=\'active\'"',
),
(
" apply_order_price_display_fields(\n payload,\n direction=r[\"direction\"],\n entry_price=entry,\n initial_stop_loss=r[\"initial_stop_loss\"],\n stop_loss=r[\"stop_loss\"],\n take_profit=r[\"take_profit\"],\n calc_rr_ratio_fn=calc_rr_ratio,\n exchange_tpsl=exchange_tpsl,\n format_price_fn=format_price_for_symbol,\n symbol=r[\"symbol\"],\n )\n new_sl, new_tp, changed = order_monitor_tpsl_needs_sync(",
" apply_order_price_display_fields(\n payload,\n direction=r[\"direction\"],\n entry_price=entry,\n initial_stop_loss=r[\"initial_stop_loss\"],\n stop_loss=r[\"stop_loss\"],\n take_profit=r[\"take_profit\"],\n calc_rr_ratio_fn=calc_rr_ratio,\n exchange_tpsl=exchange_tpsl,\n format_price_fn=format_price_for_symbol,\n symbol=r[\"symbol\"],\n )\n apply_time_close_to_payload(payload, r)\n new_sl, new_tp, changed = order_monitor_tpsl_needs_sync(",
),
(
" be_flag = parse_breakeven_enabled_form(d.get(\"breakeven_enabled\"))\n if is_false_breakout_key_monitor_type(mt):",
" be_flag = parse_breakeven_enabled_form(d.get(\"breakeven_enabled\"))\n tc_en = parse_time_close_enabled_form(d.get(\"time_close_enabled\"))\n tc_h = parse_time_close_hours_form(d.get(\"time_close_hours\")) if tc_en else None\n if tc_en and not tc_h:\n tc_en = 0\n if is_false_breakout_key_monitor_type(mt):",
),
(
" ok_fb, err_fb = _add_false_breakout_key_monitor(\n conn, symbol, direction_sel, upper_px, lower_px, key_px, breakeven_enabled=be_flag,\n )",
" ok_fb, err_fb = _add_false_breakout_key_monitor(\n conn, symbol, direction_sel, upper_px, lower_px, key_px, breakeven_enabled=be_flag,\n time_close_enabled=tc_en, time_close_hours=tc_h,\n )",
),
(
" f\"|有效期 {FALSE_BREAKOUT_VALIDITY_HOURS}h|移动保本:{'' if be_flag else ''}\"\n )",
" f\"|有效期 {FALSE_BREAKOUT_VALIDITY_HOURS}h|移动保本:{'' if be_flag else ''}\"\n + (f\"{time_close_label(tc_h)}\" if tc_en else \"\")\n )",
),
(
" ok_fib, err_fib = _add_fib_key_monitor(\n conn, symbol, direction_sel, mt, upper_px, lower_px, breakeven_enabled=be_flag,\n )",
" ok_fib, err_fib = _add_fib_key_monitor(\n conn, symbol, direction_sel, mt, upper_px, lower_px, breakeven_enabled=be_flag,\n time_close_enabled=tc_en, time_close_hours=tc_h,\n )",
),
(
" f\"|移动保本:{'' if be_flag else ''}\"\n )\n return redirect(\"/key_monitor\")",
" f\"|移动保本:{'' if be_flag else ''}\"\n + (f\"{time_close_label(tc_h)}\" if tc_en else \"\")\n )\n return redirect(\"/key_monitor\")",
),
(
" if mt in KEY_MONITOR_AUTO_TYPES:\n extra = f\"|方案:{sl_tp_mode_label(sl_tp_mode)}|移动保本:{'' if be_flag else ''}\"",
" if mt in KEY_MONITOR_AUTO_TYPES:\n extra = f\"|方案:{sl_tp_mode_label(sl_tp_mode)}|移动保本:{'' if be_flag else ''}\"\n if tc_en:\n extra += f\"{time_close_label(tc_h)}\"",
),
]
MARKET_OPEN_OLD = """ breakeven_price = round_price_to_exchange(exchange_symbol, breakeven_raw)
be_enabled = 1 if int(breakeven_enabled or 0) != 0 else 0
conn.execute(
"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, key_signal_type) "
"VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",
(
symbol,
exchange_symbol,
direction,
trigger_price,
stop_loss,
stop_loss,
take_profit,
margin_capital,
leverage,
trade_style,
risk_percent,
risk_amount_final,
breakeven_rr_trigger,
breakeven_offset_pct,
breakeven_step_r,
0,
breakeven_price,
be_enabled,
notional_value,
position_ratio,
base_amount,
amount,
open_order_id,
opened_at_bj,
opened_at_ms,
trading_day,
ORDER_MONITOR_TYPE_KEY_AUTO,
stored_key_signal_type(key_signal_type),
),
)"""
MARKET_OPEN_NEW = """ breakeven_price = round_price_to_exchange(exchange_symbol, breakeven_raw)
be_enabled = 1 if int(breakeven_enabled or 0) != 0 else 0
tc_en, tc_h, tc_at = time_close_insert_values(
time_close_enabled, time_close_hours, opened_at_ms
)
conn.execute(
"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, key_signal_type, "
"time_close_enabled, time_close_hours, time_close_at_ms) "
"VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",
(
symbol,
exchange_symbol,
direction,
trigger_price,
stop_loss,
stop_loss,
take_profit,
margin_capital,
leverage,
trade_style,
risk_percent,
risk_amount_final,
breakeven_rr_trigger,
breakeven_offset_pct,
breakeven_step_r,
0,
breakeven_price,
be_enabled,
notional_value,
position_ratio,
base_amount,
amount,
open_order_id,
opened_at_bj,
opened_at_ms,
trading_day,
ORDER_MONITOR_TYPE_KEY_AUTO,
stored_key_signal_type(key_signal_type),
tc_en,
tc_h,
tc_at,
),
)"""
FIB_INSERT_OLD = """ opened_at_bj = app_now_str()
opened_at_ms = _to_ms_with_fallback(None, opened_at_bj)
conn.execute(
"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, key_signal_type) "
"VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",
(
symbol,
exchange_symbol,
direction,
trigger_price,
stop_loss,
stop_loss,
take_profit,
margin_capital,
leverage,
trade_style,
risk_percent,
risk_amount_final,
breakeven_rr_trigger,
breakeven_offset_pct,
breakeven_step_r,
0,
breakeven_price,
1 if breakeven_enabled_from_row(row, 0) else 0,
notional_value,
position_ratio,
base_amount,
amount,
exchange_order_id or "",
opened_at_bj,
opened_at_ms,
trading_day,
ORDER_MONITOR_TYPE_KEY_AUTO,
stored_key_signal_type(typ),
),
)"""
FIB_INSERT_NEW = """ opened_at_bj = app_now_str()
opened_at_ms = _to_ms_with_fallback(None, opened_at_bj)
tc_en, tc_h, _ = time_close_settings_from_row(row)
tc_en, tc_h, tc_at = time_close_insert_values(tc_en, tc_h, opened_at_ms)
conn.execute(
"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, key_signal_type, "
"time_close_enabled, time_close_hours, time_close_at_ms) "
"VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",
(
symbol,
exchange_symbol,
direction,
trigger_price,
stop_loss,
stop_loss,
take_profit,
margin_capital,
leverage,
trade_style,
risk_percent,
risk_amount_final,
breakeven_rr_trigger,
breakeven_offset_pct,
breakeven_step_r,
0,
breakeven_price,
1 if breakeven_enabled_from_row(row, 0) else 0,
notional_value,
position_ratio,
base_amount,
amount,
exchange_order_id or "",
opened_at_bj,
opened_at_ms,
trading_day,
ORDER_MONITOR_TYPE_KEY_AUTO,
stored_key_signal_type(typ),
tc_en,
tc_h,
tc_at,
),
)"""
KEY_FB_OLD = """ be_flag = 1 if int(breakeven_enabled or 0) != 0 else 0
conn.execute(
"INSERT INTO key_monitors "
"(symbol, monitor_type, direction, upper, lower, "
"fib_limit_order_id, fib_entry_price, fib_stop_loss, fib_take_profit, "
"fib_order_amount, fib_margin_capital, fib_leverage, breakeven_enabled) "
"VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)",
(
symbol, FALSE_BREAKOUT_MONITOR_TYPE, direction_sel, upper_px, lower_px,
oid, entry, sl, tp, float(amount), margin_capital, leverage, be_flag,
),
)"""
KEY_FB_NEW = """ be_flag = 1 if int(breakeven_enabled or 0) != 0 else 0
tc_en, tc_h, _ = time_close_insert_values(time_close_enabled, time_close_hours, None)
conn.execute(
"INSERT INTO key_monitors "
"(symbol, monitor_type, direction, upper, lower, "
"fib_limit_order_id, fib_entry_price, fib_stop_loss, fib_take_profit, "
"fib_order_amount, fib_margin_capital, fib_leverage, breakeven_enabled, time_close_enabled, time_close_hours) "
"VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",
(
symbol, FALSE_BREAKOUT_MONITOR_TYPE, direction_sel, upper_px, lower_px,
oid, entry, sl, tp, float(amount), margin_capital, leverage, be_flag, tc_en, tc_h,
),
)"""
KEY_FIB_OLD = """ be_flag = 1 if int(breakeven_enabled or 0) != 0 else 0
conn.execute(
"INSERT INTO key_monitors "
"(symbol, monitor_type, direction, upper, lower, "
"fib_limit_order_id, fib_entry_price, fib_stop_loss, fib_take_profit, "
"fib_order_amount, fib_margin_capital, fib_leverage, breakeven_enabled) "
"VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)",
(
symbol, mt, direction_sel, upper_px, lower_px,
oid, entry, sl, tp, float(amount), margin_capital, leverage, be_flag,
),
)"""
KEY_FIB_NEW = """ be_flag = 1 if int(breakeven_enabled or 0) != 0 else 0
tc_en, tc_h, _ = time_close_insert_values(time_close_enabled, time_close_hours, None)
conn.execute(
"INSERT INTO key_monitors "
"(symbol, monitor_type, direction, upper, lower, "
"fib_limit_order_id, fib_entry_price, fib_stop_loss, fib_take_profit, "
"fib_order_amount, fib_margin_capital, fib_leverage, breakeven_enabled, time_close_enabled, time_close_hours) "
"VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",
(
symbol, mt, direction_sel, upper_px, lower_px,
oid, entry, sl, tp, float(amount), margin_capital, leverage, be_flag, tc_en, tc_h,
),
)"""
ADD_KEY_RS_OLD = """ conn.execute(
"INSERT INTO key_monitors "
"(symbol,monitor_type,direction,upper,lower,sl_tp_mode,manual_take_profit,breakeven_enabled,"
"max_notify,notify_interval_min) "
"VALUES (?,?,?,?,?,?,?,?,?,?)",
(
symbol,
mt,
direction_sel,
upper_px,
lower_px,
sl_tp_mode,
manual_tp,
be_flag,
KEY_ALERT_MAX_TIMES,
KEY_ALERT_INTERVAL_MINUTES,
),
)
else:
conn.execute(
"INSERT INTO key_monitors "
"(symbol,monitor_type,direction,upper,lower,sl_tp_mode,manual_take_profit,breakeven_enabled) "
"VALUES (?,?,?,?,?,?,?,?)",
(symbol, mt, direction_sel, upper_px, lower_px, sl_tp_mode, manual_tp, be_flag),
)"""
ADD_KEY_RS_NEW = """ conn.execute(
"INSERT INTO key_monitors "
"(symbol,monitor_type,direction,upper,lower,sl_tp_mode,manual_take_profit,breakeven_enabled,"
"max_notify,notify_interval_min,time_close_enabled,time_close_hours) "
"VALUES (?,?,?,?,?,?,?,?,?,?,?,?)",
(
symbol,
mt,
direction_sel,
upper_px,
lower_px,
sl_tp_mode,
manual_tp,
be_flag,
KEY_ALERT_MAX_TIMES,
KEY_ALERT_INTERVAL_MINUTES,
tc_en,
tc_h,
),
)
else:
conn.execute(
"INSERT INTO key_monitors "
"(symbol,monitor_type,direction,upper,lower,sl_tp_mode,manual_take_profit,breakeven_enabled,"
"time_close_enabled,time_close_hours) "
"VALUES (?,?,?,?,?,?,?,?,?,?)",
(symbol, mt, direction_sel, upper_px, lower_px, sl_tp_mode, manual_tp, be_flag, tc_en, tc_h),
)"""
ADD_ORDER_OLD = """ breakeven_enabled = 1 if (d.get("breakeven_enabled") or "").strip() in ("1", "true", "on", "yes") else 0
conn.execute(
"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) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",
(
symbol, exchange_symbol, direction, trigger_price, stop_loss, stop_loss, take_profit,
margin_capital, leverage, trade_style, risk_percent_db, risk_amount_final, breakeven_rr_trigger, breakeven_offset_pct, breakeven_step_r, 0, breakeven_price,
breakeven_enabled,
notional_value, position_ratio, base_amount, amount, open_order_id, opened_at_bj, opened_at_ms, trading_day,
ORDER_MONITOR_TYPE_MANUAL,
)
)"""
ADD_ORDER_NEW = """ breakeven_enabled = 1 if (d.get("breakeven_enabled") or "").strip() in ("1", "true", "on", "yes") else 0
tc_en = parse_time_close_enabled_form(d.get("time_close_enabled"))
tc_h = parse_time_close_hours_form(d.get("time_close_hours")) if tc_en else None
if tc_en and not tc_h:
tc_en = 0
tc_en, tc_h, tc_at = time_close_insert_values(tc_en, tc_h, opened_at_ms)
conn.execute(
"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 (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",
(
symbol, exchange_symbol, direction, trigger_price, stop_loss, stop_loss, take_profit,
margin_capital, leverage, trade_style, risk_percent_db, risk_amount_final, breakeven_rr_trigger, breakeven_offset_pct, breakeven_step_r, 0, breakeven_price,
breakeven_enabled,
notional_value, position_ratio, base_amount, amount, open_order_id, opened_at_bj, opened_at_ms, trading_day,
ORDER_MONITOR_TYPE_MANUAL,
tc_en, tc_h, tc_at,
)
)"""
BIG_BLOCKS = [
(MARKET_OPEN_OLD, MARKET_OPEN_NEW),
(FIB_INSERT_OLD, FIB_INSERT_NEW),
(KEY_FB_OLD, KEY_FB_NEW),
(KEY_FIB_OLD, KEY_FIB_NEW),
(ADD_KEY_RS_OLD, ADD_KEY_RS_NEW),
(ADD_ORDER_OLD, ADD_ORDER_NEW),
]
def patch(path: Path) -> None:
text = path.read_text(encoding="utf-8")
for old, new in REPLACEMENTS + BIG_BLOCKS:
if old in text:
text = text.replace(old, new, 1)
path.write_text(text, encoding="utf-8")
print("done", path.name)
def main() -> None:
for f in FILES:
patch(f)
if __name__ == "__main__":
main()