Allow scheduled CTP connect when auto-connect setting is off.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -12,7 +12,6 @@ import threading
|
||||
import time
|
||||
from typing import Callable
|
||||
|
||||
from ctp_settings import is_ctp_auto_connect_enabled
|
||||
from market_sessions import in_premarket_connect_window, is_trading_session
|
||||
from vnpy_bridge import ctp_start_connect, ctp_status
|
||||
|
||||
@@ -60,10 +59,7 @@ def start_ctp_premarket_connect_worker(
|
||||
while True:
|
||||
sleep_sec = max(30, interval)
|
||||
try:
|
||||
gs = get_setting_fn
|
||||
if gs is None:
|
||||
from fee_specs import get_setting as gs
|
||||
if is_ctp_auto_connect_enabled(gs) and should_auto_connect_now():
|
||||
if should_auto_connect_now():
|
||||
mode = get_mode_fn()
|
||||
st = ctp_status(mode)
|
||||
if (
|
||||
@@ -71,7 +67,7 @@ def start_ctp_premarket_connect_worker(
|
||||
and not st.get("connecting")
|
||||
and int(st.get("login_cooldown_sec") or 0) <= 0
|
||||
):
|
||||
info = ctp_start_connect(mode, force=False)
|
||||
info = ctp_start_connect(mode, force=False, scheduled=True)
|
||||
if info.get("started"):
|
||||
if is_trading_session():
|
||||
logger.info("交易时段内自动连接 CTP [%s]", mode)
|
||||
|
||||
+1
-9
@@ -13,7 +13,6 @@ import time
|
||||
from typing import Callable
|
||||
|
||||
from ctp_premarket_connect import should_auto_connect_now
|
||||
from ctp_settings import is_ctp_auto_connect_enabled
|
||||
from vnpy_bridge import ctp_try_auto_reconnect
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -40,14 +39,7 @@ def start_ctp_reconnect_worker(
|
||||
def _loop() -> None:
|
||||
while True:
|
||||
try:
|
||||
gs = get_setting_fn
|
||||
if gs is None:
|
||||
from fee_specs import get_setting as gs
|
||||
if (
|
||||
is_ctp_auto_connect_enabled(gs)
|
||||
and _auto_reconnect_enabled()
|
||||
and should_auto_connect_now()
|
||||
):
|
||||
if _auto_reconnect_enabled() and should_auto_connect_now():
|
||||
mode = get_mode_fn()
|
||||
if ctp_try_auto_reconnect(mode):
|
||||
logger.debug("CTP 连接正常 [%s]", mode)
|
||||
|
||||
+2
-2
@@ -35,11 +35,11 @@ LIVE_FIELDS: tuple[tuple[str, str, str, str], ...] = (
|
||||
PASSWORD_DB_KEYS = frozenset({"simnow_password", "ctp_live_password"})
|
||||
|
||||
CTP_AUTO_CONNECT_KEY = "ctp_auto_connect"
|
||||
CTP_DISABLED_HINT = "CTP 自动连接已关闭(非交易时段建议关闭,避免反复连接失败)"
|
||||
CTP_DISABLED_HINT = "CTP 自动连接已关闭(非交易时段不重连;开盘前 30 分钟仍会按计划连接)"
|
||||
|
||||
|
||||
def is_ctp_auto_connect_enabled(get_setting=None) -> bool:
|
||||
"""系统设置:是否允许 CTP 连接(含自动重连、盘前连接、手动连接)。"""
|
||||
"""系统设置:是否允许手动连接及非交易时段自动重连(盘前/交易时段计划连接不受此限制)。"""
|
||||
if get_setting is None:
|
||||
from fee_specs import get_setting as _gs
|
||||
|
||||
|
||||
+5
-3
@@ -1667,10 +1667,12 @@ def install_trading(app, *, login_required, require_nav, get_db, get_setting, se
|
||||
|
||||
threading.Thread(target=_warm, daemon=True, name="position-bootstrap").start()
|
||||
try:
|
||||
if is_ctp_auto_connect_enabled(get_setting):
|
||||
from vnpy_bridge import ctp_start_connect
|
||||
from ctp_premarket_connect import should_auto_connect_now
|
||||
from vnpy_bridge import ctp_start_connect
|
||||
|
||||
if should_auto_connect_now():
|
||||
mode = get_trading_mode(get_setting)
|
||||
ctp_start_connect(mode, force=False)
|
||||
ctp_start_connect(mode, force=False, scheduled=True)
|
||||
except Exception as exc:
|
||||
logger.debug("bootstrap ctp connect: %s", exc)
|
||||
|
||||
|
||||
+1
-1
@@ -484,7 +484,7 @@
|
||||
if (hint) {
|
||||
hint.textContent = ctpAutoConnectEnabled
|
||||
? '断线自动重连 · 开盘前 30 分钟自动连接'
|
||||
: 'CTP 自动连接已关闭(系统设置可开启)';
|
||||
: '自动连接已关闭 · 开盘前 30 分钟仍会按计划连接';
|
||||
}
|
||||
if (btnConnect && !ctpAutoConnectEnabled) {
|
||||
btnConnect.disabled = true;
|
||||
|
||||
@@ -271,7 +271,7 @@
|
||||
<span>
|
||||
<strong>CTP 自动连接</strong>
|
||||
<span class="hint" style="display:block;margin:.25rem 0 0;font-size:.78rem;line-height:1.55">
|
||||
开启:盘前自动连接、断线重连、持仓页可连 CTP。关闭:立即断开所有 CTP 连接,不再尝试重连。
|
||||
开启:盘前自动连接、断线重连、持仓页可连 CTP。关闭:立即断开,非交易时段不再重连;开盘前 30 分钟及交易时段仍会自动连接。
|
||||
SimNow 非交易时段前置常不可用(与快期相同),建议收盘后关闭。
|
||||
</span>
|
||||
</span>
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
{% if not ctp_auto_connect %}disabled title="请先在系统设置 → CTP 连接 中开启自动连接"{% endif %}>
|
||||
{% if ctp_status.connected %}重连 CTP{% else %}连接 CTP{% endif %}
|
||||
</button>
|
||||
<span class="text-muted trade-top-hint" id="ctp-auto-hint">{% if ctp_auto_connect %}断线自动重连 · 开盘前 30 分钟自动连接{% else %}CTP 自动连接已关闭{% endif %}</span>
|
||||
<span class="text-muted trade-top-hint" id="ctp-auto-hint">{% if ctp_auto_connect %}断线自动重连 · 开盘前 30 分钟自动连接{% else %}自动连接已关闭 · 开盘前 30 分钟仍会按计划连接{% endif %}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
+26
-13
@@ -575,10 +575,10 @@ class CtpBridge:
|
||||
"td_address": st.get("交易服务器", ""),
|
||||
}
|
||||
|
||||
def connect(self, mode: str, *, force: bool = False) -> None:
|
||||
from ctp_settings import CTP_DISABLED_HINT, is_ctp_auto_connect_enabled
|
||||
def connect(self, mode: str, *, force: bool = False, scheduled: bool = False) -> None:
|
||||
from ctp_settings import CTP_DISABLED_HINT
|
||||
|
||||
if not is_ctp_auto_connect_enabled():
|
||||
if not _ctp_connect_permitted(scheduled=scheduled):
|
||||
self._last_error = CTP_DISABLED_HINT
|
||||
_persist_last_error(CTP_DISABLED_HINT)
|
||||
raise RuntimeError(CTP_DISABLED_HINT)
|
||||
@@ -680,11 +680,13 @@ class CtpBridge:
|
||||
finally:
|
||||
self._connect_in_progress = False
|
||||
|
||||
def start_connect_async(self, mode: str, *, force: bool = False) -> dict[str, Any]:
|
||||
def start_connect_async(
|
||||
self, mode: str, *, force: bool = False, scheduled: bool = False,
|
||||
) -> dict[str, Any]:
|
||||
"""后台连接,不阻塞 HTTP 请求。"""
|
||||
from ctp_settings import CTP_DISABLED_HINT, is_ctp_auto_connect_enabled
|
||||
from ctp_settings import CTP_DISABLED_HINT
|
||||
|
||||
if not is_ctp_auto_connect_enabled():
|
||||
if not _ctp_connect_permitted(scheduled=scheduled):
|
||||
self._last_error = CTP_DISABLED_HINT
|
||||
_persist_last_error(CTP_DISABLED_HINT)
|
||||
return {
|
||||
@@ -709,7 +711,7 @@ class CtpBridge:
|
||||
|
||||
def _run() -> None:
|
||||
try:
|
||||
self.connect(mode, force=force)
|
||||
self.connect(mode, force=force, scheduled=scheduled)
|
||||
except Exception as exc:
|
||||
logger.warning("CTP 后台连接失败: %s", exc)
|
||||
|
||||
@@ -1915,6 +1917,19 @@ def vnpy_available() -> bool:
|
||||
return get_bridge().available()
|
||||
|
||||
|
||||
def _ctp_connect_permitted(*, scheduled: bool = False) -> bool:
|
||||
"""scheduled=True:盘前/交易时段计划连接,不受「自动连接」开关限制。"""
|
||||
from ctp_settings import is_ctp_auto_connect_enabled
|
||||
|
||||
if is_ctp_auto_connect_enabled():
|
||||
return True
|
||||
if not scheduled:
|
||||
return False
|
||||
from ctp_premarket_connect import should_auto_connect_now
|
||||
|
||||
return should_auto_connect_now()
|
||||
|
||||
|
||||
def ctp_disconnect(*, set_disabled_hint: bool = False) -> None:
|
||||
"""主动断开 CTP 并清理内存状态。"""
|
||||
from ctp_settings import CTP_DISABLED_HINT
|
||||
@@ -1935,19 +1950,17 @@ def ctp_connect(mode: str, *, force: bool = False) -> dict[str, Any]:
|
||||
return b.status(mode)
|
||||
|
||||
|
||||
def ctp_start_connect(mode: str, *, force: bool = False) -> dict[str, Any]:
|
||||
def ctp_start_connect(mode: str, *, force: bool = False, scheduled: bool = False) -> dict[str, Any]:
|
||||
"""非阻塞发起连接,供 Web API 使用。"""
|
||||
b = get_bridge()
|
||||
info = b.start_connect_async(mode, force=force)
|
||||
info = b.start_connect_async(mode, force=force, scheduled=scheduled)
|
||||
st = b.status(mode)
|
||||
return {**info, "status": st}
|
||||
|
||||
|
||||
def ctp_try_auto_reconnect(mode: str) -> bool:
|
||||
"""断线时静默异步重连;已连接且交易通道正常则不再重复 connect。"""
|
||||
from ctp_settings import is_ctp_auto_connect_enabled
|
||||
|
||||
if not is_ctp_auto_connect_enabled():
|
||||
if not _ctp_connect_permitted(scheduled=True):
|
||||
return False
|
||||
b = get_bridge()
|
||||
if not b.available():
|
||||
@@ -1974,7 +1987,7 @@ def ctp_try_auto_reconnect(mode: str) -> bool:
|
||||
"请更新 SIMNOW_TD_ADDRESS 并确认服务器出网。"
|
||||
)
|
||||
return False
|
||||
info = b.start_connect_async(mode, force=False)
|
||||
info = b.start_connect_async(mode, force=False, scheduled=True)
|
||||
return bool(
|
||||
info.get("connected")
|
||||
or info.get("connecting")
|
||||
|
||||
Reference in New Issue
Block a user