Schedule CTP disconnect 30 minutes after day and night session close.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+59
-18
@@ -3,7 +3,7 @@
|
||||
# 严禁用于:带单/代客理财、向他人推荐期货品种或买卖建议、融资配资等业务。
|
||||
# 详见 LICENSE.zh-CN.txt 与 docs/软件购买与使用协议.md
|
||||
|
||||
"""交易前自动连接 CTP(默认开盘前 30 分钟)。"""
|
||||
"""CTP 按计划自动连接/断开:盘前 30 分钟连,日盘/夜盘收盘后 30 分钟断。"""
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
@@ -12,13 +12,19 @@ import threading
|
||||
import time
|
||||
from typing import Callable
|
||||
|
||||
from market_sessions import in_premarket_connect_window, is_trading_session
|
||||
from vnpy_bridge import ctp_start_connect, ctp_status
|
||||
from market_sessions import (
|
||||
in_premarket_connect_window,
|
||||
in_postmarket_grace_window,
|
||||
is_trading_session,
|
||||
should_keep_ctp_connected,
|
||||
)
|
||||
from vnpy_bridge import ctp_disconnect, ctp_start_connect, ctp_status
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
CHECK_INTERVAL_SEC = 60
|
||||
DEFAULT_MINUTES_BEFORE = 30
|
||||
DEFAULT_MINUTES_AFTER = 30
|
||||
|
||||
|
||||
def premarket_minutes_before() -> int:
|
||||
@@ -28,7 +34,14 @@ def premarket_minutes_before() -> int:
|
||||
return DEFAULT_MINUTES_BEFORE
|
||||
|
||||
|
||||
def _premarket_enabled() -> bool:
|
||||
def postmarket_minutes_after() -> int:
|
||||
try:
|
||||
return max(5, int(os.getenv("CTP_POSTMARKET_MINUTES", str(DEFAULT_MINUTES_AFTER))))
|
||||
except (TypeError, ValueError):
|
||||
return DEFAULT_MINUTES_AFTER
|
||||
|
||||
|
||||
def _scheduled_connect_enabled() -> bool:
|
||||
return (os.getenv("CTP_PREMARKET_CONNECT", "true") or "true").strip().lower() in (
|
||||
"1",
|
||||
"true",
|
||||
@@ -36,14 +49,25 @@ def _premarket_enabled() -> bool:
|
||||
)
|
||||
|
||||
|
||||
def _scheduled_disconnect_enabled() -> bool:
|
||||
return (os.getenv("CTP_POSTMARKET_DISCONNECT", "true") or "true").strip().lower() in (
|
||||
"1",
|
||||
"true",
|
||||
"yes",
|
||||
)
|
||||
|
||||
|
||||
def should_auto_connect_now(*, minutes_before: int | None = None) -> bool:
|
||||
"""交易时段内,或距下一段开盘 <= minutes_before 且尚未开盘。"""
|
||||
mins = premarket_minutes_before() if minutes_before is None else minutes_before
|
||||
if is_trading_session():
|
||||
return True
|
||||
if not _premarket_enabled():
|
||||
return False
|
||||
return in_premarket_connect_window(minutes_before=mins)
|
||||
"""是否应保持/发起 CTP 连接(供重连、权限判断复用)。"""
|
||||
mins_b = premarket_minutes_before() if minutes_before is None else minutes_before
|
||||
mins_a = postmarket_minutes_after()
|
||||
if not _scheduled_connect_enabled() and not is_trading_session():
|
||||
if not in_postmarket_grace_window(minutes_after=mins_a):
|
||||
return False
|
||||
return should_keep_ctp_connected(
|
||||
minutes_before=mins_b,
|
||||
minutes_after=mins_a,
|
||||
)
|
||||
|
||||
|
||||
def start_ctp_premarket_connect_worker(
|
||||
@@ -52,16 +76,20 @@ def start_ctp_premarket_connect_worker(
|
||||
get_setting_fn: Callable[[str, str], str] | None = None,
|
||||
interval: int = CHECK_INTERVAL_SEC,
|
||||
) -> None:
|
||||
"""在交易开始前若干分钟自动发起 CTP 连接。"""
|
||||
"""盘前自动连接;日盘/夜盘收盘宽限结束后自动断开。"""
|
||||
|
||||
def _loop() -> None:
|
||||
time.sleep(10)
|
||||
while True:
|
||||
sleep_sec = max(30, interval)
|
||||
try:
|
||||
if should_auto_connect_now():
|
||||
mode = get_mode_fn()
|
||||
st = ctp_status(mode)
|
||||
mins_b = premarket_minutes_before()
|
||||
mins_a = postmarket_minutes_after()
|
||||
keep = should_auto_connect_now()
|
||||
mode = get_mode_fn()
|
||||
st = ctp_status(mode)
|
||||
|
||||
if keep:
|
||||
if (
|
||||
not st.get("connected")
|
||||
and not st.get("connecting")
|
||||
@@ -71,18 +99,31 @@ def start_ctp_premarket_connect_worker(
|
||||
if info.get("started"):
|
||||
if is_trading_session():
|
||||
logger.info("交易时段内自动连接 CTP [%s]", mode)
|
||||
elif in_postmarket_grace_window(minutes_after=mins_a):
|
||||
logger.info(
|
||||
"盘后宽限期内保持/恢复 CTP 连接 [%s](收盘后 %d 分钟内)",
|
||||
mode,
|
||||
mins_a,
|
||||
)
|
||||
else:
|
||||
logger.info(
|
||||
"盘前自动连接 CTP [%s](开盘前 %d 分钟)",
|
||||
mode,
|
||||
premarket_minutes_before(),
|
||||
mins_b,
|
||||
)
|
||||
if not is_trading_session() and in_premarket_connect_window(
|
||||
minutes_before=premarket_minutes_before(),
|
||||
minutes_before=mins_b,
|
||||
):
|
||||
sleep_sec = 30
|
||||
elif _scheduled_disconnect_enabled() and st.get("connected"):
|
||||
ctp_disconnect()
|
||||
logger.info(
|
||||
"盘后自动断开 CTP [%s](日盘/夜盘结束 %d 分钟后)",
|
||||
mode,
|
||||
mins_a,
|
||||
)
|
||||
except Exception as exc:
|
||||
logger.warning("CTP premarket connect worker: %s", exc)
|
||||
logger.warning("CTP scheduled connect worker: %s", exc)
|
||||
time.sleep(sleep_sec)
|
||||
|
||||
threading.Thread(target=_loop, daemon=True, name="ctp-premarket-connect").start()
|
||||
|
||||
Reference in New Issue
Block a user