This commit is contained in:
2026-09-07 21:22:51 +08:00
parent 9778d54f3d
commit ba61ed5de7
28 changed files with 303 additions and 64 deletions

View File

@@ -2,9 +2,14 @@ from datetime import datetime, time
from math import floor
_MORNING_START, _MORNING_END = time(9, 30), time(11, 30)
_AFTERNOON_START, _AFTERNOON_END = time(13), time(15)
def trading_time(now: datetime) -> bool:
if now.weekday() >= 5: return False
return time(9, 30) <= now.time() <= time(11, 30) or time(13) <= now.time() <= time(15)
clock = now.time()
return _MORNING_START <= clock <= _MORNING_END or _AFTERNOON_START <= clock <= _AFTERNOON_END
def calc_buy_volume(price: float, buy_value: float) -> int:
@@ -29,4 +34,4 @@ def calculate_min_profit_rate(price: float, profit_mult: int) -> float:
elif price >= 100:
return 7 * profit_mult # 7%
else:
return 9 * profit_mult # 9%
return 9 * profit_mult # 9%

View File

@@ -1,7 +1,5 @@
"""简单的文件锁标记工具。"""
from __future__ import annotations
from os import PathLike
from pathlib import Path

View File

@@ -1,7 +1,5 @@
"""策略共用委托簿。"""
from __future__ import annotations
import secrets
from dataclasses import dataclass
from datetime import datetime, timedelta
@@ -69,17 +67,19 @@ class OrderBook:
canceled = 0
for item in orders:
status = str(item.order_status)
# 不处理状态不对的
if str(item.order_status) not in TRACKED_STATUSES:
if status not in TRACKED_STATUSES:
continue
if str(item.order_status) in BUSY_STATUSES:
if status in BUSY_STATUSES:
busy_keys.add(self._busy_key(item.side, item.stock_code))
# 清理过期的
created_at = item.created_at
if (
item.created_at is not None
created_at is not None
and item.local_order_id.startswith(f"{self.order_prefix}-")
and str(item.order_status) in CANCELABLE_STATUSES
and current - item.created_at > self.cancel_timeout_sec
and status in CANCELABLE_STATUSES
and current - created_at > self.cancel_timeout_sec
):
try:
client.cancel_by_id(item.order_sys_id)

View File

@@ -1,13 +1,12 @@
"""SQLite positions and deals, aligned with SDK models; one writer per database."""
from __future__ import annotations
import math
import sqlite3
from contextlib import closing
from dataclasses import asdict, fields
from datetime import datetime
from pathlib import Path
from itertools import chain
from sdk import DealItem, PositionItem
@@ -106,7 +105,7 @@ class OrderBook:
raise ValueError('System order ID and positive volume are required')
row = asdict(deal)
row['order_local_id'] = deal.get_local_order_id()
row['order_local_id'] = deal.local_order_id
if not row['order_local_id']:
raise ValueError('Local order ID is required')
@@ -145,7 +144,7 @@ class OrderBook:
raise ValueError('Execution history is append-only')
new_deals = deals[len(self.deals):]
positions = [{**POSITION_DEFAULTS, **item} for item in items.values()]
for row in [*positions, *new_deals]:
for row in chain(positions, new_deals):
if any(isinstance(value, float) and not math.isfinite(value) for value in row.values()):
raise ValueError('Numeric values must be finite')
with closing(self._connect()) as db, db:

View File

@@ -1,7 +1,5 @@
"""策略单次运行所需的公共上下文对象。"""
from __future__ import annotations
from concurrent.futures import ThreadPoolExecutor
from dataclasses import dataclass