47 lines
1.9 KiB
Python
47 lines
1.9 KiB
Python
"""策略单次运行所需的公共上下文对象。"""
|
|
|
|
import logging
|
|
from concurrent.futures import ThreadPoolExecutor
|
|
from dataclasses import dataclass, field
|
|
|
|
from config import AccountConfig, GlobalConfig, HTTP_TIMEOUT
|
|
from sdk import Client
|
|
from libs.grid_take_profit import GridTrailingTracker
|
|
from libs.http import get_json
|
|
from libs.order import OrderBook
|
|
from libs.watch import DipWatch
|
|
|
|
|
|
@dataclass(slots=True)
|
|
class Runtime:
|
|
"""集中保存策略运行期间共享的客户端、配置和内存组件。"""
|
|
|
|
client: Client
|
|
global_cfg: GlobalConfig
|
|
account_cfg: AccountConfig
|
|
orders: OrderBook
|
|
open_watch: DipWatch
|
|
add_watch: DipWatch
|
|
profit_tracker: GridTrailingTracker
|
|
executor: ThreadPoolExecutor | None = None
|
|
server_inital: dict[str, list[str]] = field(init=False)
|
|
|
|
def __post_init__(self) -> None:
|
|
"""读取服务端初始化数据,失败时保留空证券列表。"""
|
|
self.server_inital = {"all_codes": [], "today_pass_codes": []}
|
|
try:
|
|
url = f"{self.global_cfg.api_host.rstrip('/')}/a/initial"
|
|
payload = get_json(url, HTTP_TIMEOUT)
|
|
if not isinstance(payload, dict) or str(payload.get("code")) != "0":
|
|
raise ValueError(f"服务端初始化响应失败: {payload!r}")
|
|
data = payload.get("data")
|
|
if not isinstance(data, dict):
|
|
raise ValueError("服务端初始化 data 必须为对象")
|
|
for key in ("all_codes", "today_pass_codes"):
|
|
codes = data.get(key)
|
|
if not isinstance(codes, list) or not all(isinstance(code, str) for code in codes):
|
|
raise ValueError(f"服务端初始化 {key} 必须为字符串列表")
|
|
self.server_inital = data
|
|
except Exception:
|
|
logging.exception("[初始化] 获取服务端初始化数据失败")
|