Skip to content
Merged
3 changes: 3 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@ jobs:
timeout-minutes: 15

steps:
# full history required: shallow clones break gitleaks PR-range scans (base^..head)
- uses: actions/checkout@v6
with:
fetch-depth: 0

- uses: actions/setup-python@v6
with:
Expand Down
1 change: 1 addition & 0 deletions bt_api_py/_compat.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Module-level docstring."""

from bt_api_base._compat import UTC

__all__ = ["UTC"]
1 change: 1 addition & 0 deletions bt_api_py/backtrader/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Module-level docstring."""

from bt_api_py.backtrader.btapibroker import BtApiBroker

__all__ = ["BtApiBroker"]
8 changes: 4 additions & 4 deletions bt_api_py/certification/audit.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
import json
import uuid
from dataclasses import asdict, dataclass, field
from datetime import datetime, timezone
from enum import Enum
from datetime import UTC, datetime
from enum import Enum, StrEnum
from pathlib import Path
from typing import Any

Expand All @@ -22,7 +22,7 @@
}


class CertificationAuditStatus(str, Enum):
class CertificationAuditStatus(StrEnum):
"""Certification scenario/event result states."""

PASS = "PASS"
Expand Down Expand Up @@ -64,7 +64,7 @@ class CertificationAuditEvent:
event_id: str = field(default_factory=lambda: str(uuid.uuid4()))
trace_id: str = ""
severity: str = "INFO"
timestamp: str = field(default_factory=lambda: datetime.now(timezone.utc).isoformat())
timestamp: str = field(default_factory=lambda: datetime.now(UTC).isoformat())
gateway_key: str = ""
exchange_type: str = "CTP"
account_id_masked: str = ""
Expand Down
256 changes: 224 additions & 32 deletions bt_api_py/certification/scenarios.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,39 +54,231 @@ def to_dicts(self) -> list[dict[str, Any]]:


_SCENARIO_ROWS = [
("AUTH-01", "认证登录", "接口适应性", ("store_auth_success", "store_login_success"), ("front_id", "session_id", "trading_day")),
("TRADE-OPEN-01", "正常下达开仓指令", "基础交易", ("order_submit_request", "order_status_accepted"), ("order_ref", "external_order_id")),
("TRADE-CLOSE-01", "正常下达平仓指令", "基础交易", ("order_submit_request", "order_status_accepted"), ("order_ref", "external_order_id")),
("TRADE-CANCEL-01", "正常下达撤单指令", "基础交易", ("order_cancel_request", "order_status_canceled"), ("order_ref", "external_order_id")),
("MONITOR-CONN-01", "连接成功显示连接成功", "连接异常监测", ("store_connected",), ("gateway_key", "market_connection", "trade_connection")),
("MONITOR-CONN-02", "连接断开显示连接断开", "连接异常监测", ("store_disconnected",), ("gateway_key", "timestamp")),
("MONITOR-CONN-03", "断线后显示重连成功", "连接异常监测", ("store_reconnect_success",), ("gateway_key", "timestamp")),
("MONITOR-COUNT-01", "正常统计报单笔数", "报撤单监测", ("order_submit_request",), ("submitted_order_count",)),
("MONITOR-COUNT-02", "正常统计撤单笔数", "报撤单监测", ("order_cancel_request",), ("cancel_order_count",)),
("RISK-REPEAT-01", "重复开仓报单统计", "重复报单监测", ("risk_repeat_order_detected",), ("repeat_key", "repeat_count")),
("RISK-REPEAT-02", "重复平仓报单统计", "重复报单监测", ("risk_repeat_order_detected",), ("repeat_key", "repeat_count")),
("RISK-REPEAT-03", "重复撤单统计", "重复报单监测", ("risk_repeat_cancel_detected",), ("repeat_key", "repeat_count")),
("RISK-THRESHOLD-01", "报单笔数阈值设置", "阈值管理", ("risk_threshold_configured",), ("order_threshold",)),
("RISK-THRESHOLD-02", "报单笔数达到阈值预警", "阈值管理", ("risk_threshold_triggered",), ("order_threshold", "submitted_order_count")),
("RISK-THRESHOLD-03", "报撤单笔数阈值设置", "阈值管理", ("risk_threshold_configured",), ("cancel_threshold",)),
("RISK-THRESHOLD-04", "报撤单笔数达到阈值预警", "阈值管理", ("risk_threshold_triggered",), ("cancel_threshold", "cancel_order_count")),
("RISK-THRESHOLD-05", "重复报单阈值设置", "阈值管理", ("risk_threshold_configured",), ("repeat_threshold", "repeat_window_sec")),
("RISK-THRESHOLD-06", "重复报单达到阈值预警", "阈值管理", ("risk_threshold_triggered",), ("repeat_threshold", "repeat_count")),
("VALIDATION-01", "合约代码错误检查并拒绝报单", "错误防范", ("order_validation_rejected",), ("instrument", "error_msg")),
("VALIDATION-02", "价格最小变动价位错误检查", "错误防范", ("order_validation_rejected",), ("price", "price_tick", "error_msg")),
("VALIDATION-03", "单笔委托最大手数检查", "错误防范", ("order_validation_rejected",), ("size", "max_order_size", "error_msg")),
("ERROR-01", "资金不足错误展示", "错误提示", ("order_reject_remote",), ("ErrorID", "ErrorMsg", "StatusMsg")),
("ERROR-02", "持仓不足错误展示", "错误提示", ("order_reject_remote",), ("ErrorID", "ErrorMsg", "StatusMsg")),
("ERROR-03", "市场状态不允许错误展示", "错误提示", ("order_reject_remote",), ("ErrorID", "ErrorMsg", "StatusMsg")),
("EMERGENCY-01", "限制账号交易权限暂停交易", "应急处理", ("account_trading_disabled",), ("account_id_masked", "reason")),
("EMERGENCY-02", "暂停策略执行", "应急处理", ("strategy_trading_paused",), ("strategy_id", "reason")),
("EMERGENCY-03", "强制账号退出", "应急处理", ("gateway_force_logout_requested",), ("gateway_key", "reason")),
("BATCH-CANCEL-01", "多笔部分成交报单批量撤单", "批量撤单", ("batch_cancel_requested",), ("order_refs", "partial_count")),
("BATCH-CANCEL-02", "多笔已报单批量撤单", "批量撤单", ("batch_cancel_requested",), ("order_refs", "open_order_count")),
("LOG-TRADE-01", "交易信息记录", "日志记录", ("order_submit_request", "trade_execution"), ("trace_id", "order_ref", "trade_id")),
("LOG-SYSTEM-01", "系统运行信息记录", "日志记录", ("store_connected", "store_ready"), ("trace_id", "gateway_key")),
(
"AUTH-01",
"认证登录",
"接口适应性",
("store_auth_success", "store_login_success"),
("front_id", "session_id", "trading_day"),
),
(
"TRADE-OPEN-01",
"正常下达开仓指令",
"基础交易",
("order_submit_request", "order_status_accepted"),
("order_ref", "external_order_id"),
),
(
"TRADE-CLOSE-01",
"正常下达平仓指令",
"基础交易",
("order_submit_request", "order_status_accepted"),
("order_ref", "external_order_id"),
),
(
"TRADE-CANCEL-01",
"正常下达撤单指令",
"基础交易",
("order_cancel_request", "order_status_canceled"),
("order_ref", "external_order_id"),
),
(
"MONITOR-CONN-01",
"连接成功显示连接成功",
"连接异常监测",
("store_connected",),
("gateway_key", "market_connection", "trade_connection"),
),
(
"MONITOR-CONN-02",
"连接断开显示连接断开",
"连接异常监测",
("store_disconnected",),
("gateway_key", "timestamp"),
),
(
"MONITOR-CONN-03",
"断线后显示重连成功",
"连接异常监测",
("store_reconnect_success",),
("gateway_key", "timestamp"),
),
(
"MONITOR-COUNT-01",
"正常统计报单笔数",
"报撤单监测",
("order_submit_request",),
("submitted_order_count",),
),
(
"MONITOR-COUNT-02",
"正常统计撤单笔数",
"报撤单监测",
("order_cancel_request",),
("cancel_order_count",),
),
(
"RISK-REPEAT-01",
"重复开仓报单统计",
"重复报单监测",
("risk_repeat_order_detected",),
("repeat_key", "repeat_count"),
),
(
"RISK-REPEAT-02",
"重复平仓报单统计",
"重复报单监测",
("risk_repeat_order_detected",),
("repeat_key", "repeat_count"),
),
(
"RISK-REPEAT-03",
"重复撤单统计",
"重复报单监测",
("risk_repeat_cancel_detected",),
("repeat_key", "repeat_count"),
),
(
"RISK-THRESHOLD-01",
"报单笔数阈值设置",
"阈值管理",
("risk_threshold_configured",),
("order_threshold",),
),
(
"RISK-THRESHOLD-02",
"报单笔数达到阈值预警",
"阈值管理",
("risk_threshold_triggered",),
("order_threshold", "submitted_order_count"),
),
(
"RISK-THRESHOLD-03",
"报撤单笔数阈值设置",
"阈值管理",
("risk_threshold_configured",),
("cancel_threshold",),
),
(
"RISK-THRESHOLD-04",
"报撤单笔数达到阈值预警",
"阈值管理",
("risk_threshold_triggered",),
("cancel_threshold", "cancel_order_count"),
),
(
"RISK-THRESHOLD-05",
"重复报单阈值设置",
"阈值管理",
("risk_threshold_configured",),
("repeat_threshold", "repeat_window_sec"),
),
(
"RISK-THRESHOLD-06",
"重复报单达到阈值预警",
"阈值管理",
("risk_threshold_triggered",),
("repeat_threshold", "repeat_count"),
),
(
"VALIDATION-01",
"合约代码错误检查并拒绝报单",
"错误防范",
("order_validation_rejected",),
("instrument", "error_msg"),
),
(
"VALIDATION-02",
"价格最小变动价位错误检查",
"错误防范",
("order_validation_rejected",),
("price", "price_tick", "error_msg"),
),
(
"VALIDATION-03",
"单笔委托最大手数检查",
"错误防范",
("order_validation_rejected",),
("size", "max_order_size", "error_msg"),
),
(
"ERROR-01",
"资金不足错误展示",
"错误提示",
("order_reject_remote",),
("ErrorID", "ErrorMsg", "StatusMsg"),
),
(
"ERROR-02",
"持仓不足错误展示",
"错误提示",
("order_reject_remote",),
("ErrorID", "ErrorMsg", "StatusMsg"),
),
(
"ERROR-03",
"市场状态不允许错误展示",
"错误提示",
("order_reject_remote",),
("ErrorID", "ErrorMsg", "StatusMsg"),
),
(
"EMERGENCY-01",
"限制账号交易权限暂停交易",
"应急处理",
("account_trading_disabled",),
("account_id_masked", "reason"),
),
(
"EMERGENCY-02",
"暂停策略执行",
"应急处理",
("strategy_trading_paused",),
("strategy_id", "reason"),
),
(
"EMERGENCY-03",
"强制账号退出",
"应急处理",
("gateway_force_logout_requested",),
("gateway_key", "reason"),
),
(
"BATCH-CANCEL-01",
"多笔部分成交报单批量撤单",
"批量撤单",
("batch_cancel_requested",),
("order_refs", "partial_count"),
),
(
"BATCH-CANCEL-02",
"多笔已报单批量撤单",
"批量撤单",
("batch_cancel_requested",),
("order_refs", "open_order_count"),
),
(
"LOG-TRADE-01",
"交易信息记录",
"日志记录",
("order_submit_request", "trade_execution"),
("trace_id", "order_ref", "trade_id"),
),
(
"LOG-SYSTEM-01",
"系统运行信息记录",
"日志记录",
("store_connected", "store_ready"),
("trace_id", "gateway_key"),
),
("LOG-MONITOR-01", "监测信息记录", "日志记录", ("risk_monitor_event",), ("trace_id", "metric")),
("LOG-ERROR-01", "错误提示信息记录", "日志记录", ("store_error",), ("trace_id", "error_code", "error_msg")),
(
"LOG-ERROR-01",
"错误提示信息记录",
"日志记录",
("store_error",),
("trace_id", "error_code", "error_msg"),
),
]


Expand Down
1 change: 1 addition & 0 deletions bt_api_py/configs/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
"""Module-level docstring."""

from __future__ import annotations
3 changes: 2 additions & 1 deletion bt_api_py/ctp_env_selector.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,11 @@ def _load_default_fronts() -> dict[str, dict[str, str]]:
for field in ("td_front", "md_front"):
if section.get(field):
defaults[key][field] = str(section[field])
except Exception: # noqa: BLE001 - 配置不可用时用硬编码兜底
except Exception:
pass
return defaults


_TRADING_SESSIONS = (
(time(9, 0), time(11, 30)),
(time(13, 30), time(15, 0)),
Expand Down
12 changes: 5 additions & 7 deletions bt_api_py/gateway/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from __future__ import annotations

import warnings
from typing import Any, cast
from typing import Any

from bt_api_py.forwarding.client import ZmqForwardingClient

Expand Down Expand Up @@ -57,16 +57,14 @@ def __init__(

timeout_ms = command_timeout_ms
if timeout_ms is None:
timeout_sec = (
raw = (
gateway_command_timeout_sec
if gateway_command_timeout_sec not in (None, "")
else command_timeout_sec
)
resolved = cast(
"float | int | str",
timeout_sec if timeout_sec not in (None, "") else 2.0,
)
timeout_ms = int(float(resolved) * 1000)
if raw is None or raw == "":
raw = 2.0
timeout_ms = int(float(raw) * 1000)

super().__init__(
market_endpoint=str(market),
Expand Down
3 changes: 2 additions & 1 deletion bt_api_py/monitoring/elk.py
Original file line number Diff line number Diff line change
Expand Up @@ -550,4 +550,5 @@ async def shutdown_elk_integration() -> None:
if _elk_integration:
try:
await _elk_integration.disconnect()
finally: _elk_integration = None
finally:
_elk_integration = None
Loading
Loading