Shorten force-close window to 5m and grey-out open during blocks.

Unify Gate/OKX/Binance: disable the open button with a side note during force-close, cooloff, and daily freeze, and enforce the same gate server-side.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-08-06 08:38:00 +08:00
parent 7352d10254
commit 7f22bffbc6
23 changed files with 403 additions and 42 deletions
+34 -6
View File
@@ -2729,6 +2729,7 @@ def trading_day_reset_allows_new_open(now, conn=None):
def precheck_risk(conn, symbol, direction):
now = app_now()
from lib.trade.account_risk_lib import account_risk_blocks_trading
from lib.trade.force_close_lib import force_close_blocks_new_open
ok_risk, risk_reason = account_risk_blocks_trading(
conn,
@@ -2738,6 +2739,13 @@ def precheck_risk(conn, symbol, direction):
)
if not ok_risk:
return False, risk_reason
fc_block, fc_note = force_close_blocks_new_open(
FORCE_CLOSE_ENABLED,
FORCE_CLOSE_BJ_HOUR,
now_ms=int(now.timestamp() * 1000),
)
if fc_block:
return False, fc_note or "强制清仓窗口内暂不可开仓"
if not trading_day_reset_allows_new_open(now):
return False, f"北京时间 {TRADING_DAY_RESET_HOUR}:00 前不允许持仓"
from lib.trade.account_risk_lib import position_limit_reached
@@ -6399,8 +6407,10 @@ def force_close_before_reset():
if not FORCE_CLOSE_ENABLED:
return
now = app_now()
# 每天北京时间指定整点小时内执行一次性兜底清仓(默认 00:xx)
if now.hour != FORCE_CLOSE_BJ_HOUR:
# 每天北京时间指定整点起 FORCE_CLOSE_GRACE_MINUTES 分钟内执行兜底清仓
from lib.trade.force_close_lib import is_force_close_executing
if not is_force_close_executing(FORCE_CLOSE_BJ_HOUR, now_ms=int(now.timestamp() * 1000)):
return
conn = get_db()
rows = conn.execute("SELECT * FROM order_monitors WHERE status='active'").fetchall()
@@ -6700,14 +6710,22 @@ def render_main_page(page="trade", embed_mode=None):
open_guard_blocks_now = open_guard_enabled and now.hour < TRADING_DAY_RESET_HOUR
opens_today = count_opens_for_trading_day(conn, trading_day)
risk_status = hub_account_risk_status(conn)
can_trade = can_trade_new_open(
from lib.trade.open_trade_gate_lib import resolve_manual_open_gate
_open_gate = resolve_manual_open_gate(
time_allows=trading_day_reset_allows_new_open(now, conn),
active_count=position_limit_count,
max_active_positions=MAX_ACTIVE_POSITIONS,
opens_today=opens_today,
hard_limit=DAILY_OPEN_HARD_LIMIT,
extra_blocks=not risk_status.get("can_trade", True),
risk_status=risk_status,
force_close_enabled=FORCE_CLOSE_ENABLED,
force_close_bj_hour=FORCE_CLOSE_BJ_HOUR,
now_ms=int(now.timestamp() * 1000),
reset_hour=TRADING_DAY_RESET_HOUR,
)
can_trade = _open_gate["can_trade"]
open_block_note = _open_gate["open_block_note"]
key_rule_ctx = {}
if page in ("key_monitor", "trade") or page in (
"strategy",
@@ -6794,6 +6812,7 @@ def render_main_page(page="trade", embed_mode=None):
price_refresh_seconds=PRICE_REFRESH_SECONDS,
active_count=position_limit_count,
can_trade=can_trade,
open_block_note=open_block_note,
opens_today=opens_today,
daily_open_hard_limit=DAILY_OPEN_HARD_LIMIT,
daily_open_alert_threshold=DAILY_OPEN_ALERT_THRESHOLD,
@@ -7050,14 +7069,22 @@ def api_account_snapshot():
header_trade_stats = header_trade_stats_for_window(conn, _list_window_from_request(), APP_TZ)
conn.close()
open_guard_blocks_now = open_guard_enabled and now.hour < TRADING_DAY_RESET_HOUR
can_trade = can_trade_new_open(
from lib.trade.open_trade_gate_lib import resolve_manual_open_gate
_open_gate = resolve_manual_open_gate(
time_allows=trading_day_reset_allows_new_open(now),
active_count=position_limit_count,
max_active_positions=MAX_ACTIVE_POSITIONS,
opens_today=opens_today,
hard_limit=DAILY_OPEN_HARD_LIMIT,
extra_blocks=not risk_status.get("can_trade", True),
risk_status=risk_status,
force_close_enabled=FORCE_CLOSE_ENABLED,
force_close_bj_hour=FORCE_CLOSE_BJ_HOUR,
now_ms=int(now.timestamp() * 1000),
reset_hour=TRADING_DAY_RESET_HOUR,
)
can_trade = _open_gate["can_trade"]
open_block_note = _open_gate["open_block_note"]
available_trading_usdt = get_available_trading_usdt()
unrealized_pnl = None
@@ -7120,6 +7147,7 @@ def api_account_snapshot():
"active_count": position_limit_count,
"max_active_positions": MAX_ACTIVE_POSITIONS,
"can_trade": can_trade,
"open_block_note": open_block_note,
"opens_today": opens_today,
"daily_open_hard_limit": DAILY_OPEN_HARD_LIMIT,
"daily_open_alert_threshold": DAILY_OPEN_ALERT_THRESHOLD,