This commit is contained in:
2026-09-10 22:16:18 +08:00
parent 1255ab21ba
commit 4e693d773a
2 changed files with 44 additions and 37 deletions

View File

@@ -88,16 +88,26 @@ class State:
return db return db
def load(self) -> None: def load(self) -> None:
"""从数据库刷新状态、成交及去重缓存。""" """缓存状态表和成交记录"""
self.load_state()
self.load_deals()
def load_state(self) -> None:
"""缓存状态表。"""
with closing(self._connect()) as db, db: with closing(self._connect()) as db, db:
db.execute('BEGIN') db.execute('BEGIN')
state = {row['stock_code']: dict(row) for row in db.execute('SELECT * FROM state')} state = {row['stock_code']: dict(row) for row in db.execute('SELECT * FROM state')}
deals = {row['order_sys_id']: dict(row) for row in db.execute('SELECT * FROM deals ORDER BY id')}
self.state = state self.state = state
def load_deals(self) -> None:
"""缓存成交记录。"""
with closing(self._connect()) as db, db:
db.execute('BEGIN')
deals = {row['order_sys_id']: dict(row) for row in db.execute('SELECT * FROM deals ORDER BY id')}
self.deals = deals self.deals = deals
self.deals_sys_ids = set(deals) self.deals_sys_ids = set(deals)
def sync_deals(self, deals: list[DealItem], *, archived: bool = False) -> None: def sync_deals(self, deals: list[DealItem]) -> None:
"""按成交编号去重;初始化底仓时,已包含在快照内的成交可直接标记归档。""" """按成交编号去重;初始化底仓时,已包含在快照内的成交可直接标记归档。"""
new_deals = {} new_deals = {}
for deal in deals: for deal in deals:
@@ -124,10 +134,37 @@ class State:
'VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', 'VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)',
(deal.stock_code, deal.order_sys_id, order_id, deal.ref, (deal.stock_code, deal.order_sys_id, order_id, deal.ref,
deal.order_ref, deal.direction, deal.offset_flag, deal.price, deal.volume, deal.order_ref, deal.direction, deal.offset_flag, deal.price, deal.volume,
amount, date, deal.trade_time, deal.remark, deal.close_profit, int(archived)), amount, date, deal.trade_time, deal.remark, deal.close_profit, 0),
) )
self.load() self.load_deals()
def sync_state(self, positions: list[PositionItem]) -> None:
"""同步完整持仓:无状态则插入底仓,已有则保留,清仓则删除。
"""
# 传入完整账户持仓;同步时间作为新增底仓的创建时间。
created_at = datetime.now().isoformat(timespec='seconds')
holdings = {item.stock_code: item for item in positions if item.volume > 0}
with closing(self._connect()) as db, db:
db.execute('BEGIN')
existing = {row['stock_code'] for row in db.execute('SELECT stock_code FROM state')}
db.executemany(
'DELETE FROM state WHERE stock_code = ?',
[(code,) for code in existing if code not in holdings],
)
for code, item in holdings.items():
if code in existing:
continue
if not math.isfinite(item.open_price):
raise ValueError('Base price must be finite')
# 只插入底仓字段,补仓字段使用数据库默认值。
db.execute(
'INSERT INTO state '
'(stock_code, status, base_order_local_id, base_qty, base_price, base_created_at) '
"VALUES (?, '', '', ?, ?, ?)",
(code, item.volume, item.open_price, created_at),
)
self.load_state()
def archiving(self, *, base_order_prefix: str = '') -> dict[str, str]: def archiving(self, *, base_order_prefix: str = '') -> dict[str, str]:
"""将未归档成交累加到当前底仓和加仓;失败证券保留记录供重试。""" """将未归档成交累加到当前底仓和加仓;失败证券保留记录供重试。"""
errors = {} errors = {}
@@ -197,34 +234,4 @@ class State:
self.load() self.load()
return errors return errors
def sync_state(self, positions: list[PositionItem], *, remove_missing: bool = True) -> None:
"""同步完整持仓:无状态则插入底仓,已有则保留,清仓则删除。
数量为零或未出现在完整持仓列表中的证券视为已清仓;空列表清空状态。
底仓已包含的历史成交不应再次归档;后续成交须先归档,再同步持仓。
remove_missing=False 时仅接纳新底仓,减仓由成交归档处理。
"""
# 传入完整账户持仓;同步时间作为新增底仓的创建时间。
created_at = datetime.now().isoformat(timespec='seconds')
holdings = {item.stock_code: item for item in positions if item.volume > 0}
with closing(self._connect()) as db, db:
db.execute('BEGIN')
existing = {row['stock_code'] for row in db.execute('SELECT stock_code FROM state')}
if remove_missing:
db.executemany(
'DELETE FROM state WHERE stock_code = ?',
[(code,) for code in existing if code not in holdings],
)
for code, item in holdings.items():
if code in existing:
continue
if not math.isfinite(item.open_price):
raise ValueError('Base price must be finite')
# 只插入底仓字段,补仓字段使用数据库默认值。
db.execute(
'INSERT INTO state '
'(stock_code, status, base_order_local_id, base_qty, base_price, base_created_at) '
"VALUES (?, '', '', ?, ?, ?)",
(code, item.volume, item.open_price, created_at),
)
self.load()

View File

@@ -85,7 +85,7 @@ def sync_account_state(
) -> None: ) -> None:
"""初次持仓作为底仓;后续只按成交减仓,避免延迟快照删除持仓。""" """初次持仓作为底仓;后续只按成交减仓,避免延迟快照删除持仓。"""
zt_deals = [d for d in deals if d.get_local_order_id.startswith('zt-')] zt_deals = [d for d in deals if d.get_local_order_id.startswith('zt-')]
state.sync_deals(zt_deals, archived=initialize) state.sync_deals(zt_deals)
if initialize: if initialize:
state.sync_state(positions) state.sync_state(positions)
return return