update etc/*
This commit is contained in:
@@ -60,6 +60,7 @@ CREATE INDEX IF NOT EXISTS idx_deals_date_time ON deals (trade_date);
|
||||
# SQL is assembled once; order_local_id is derived from the SDK remark property.
|
||||
POSITION_FIELDS = tuple(field.name for field in fields(PositionItem))
|
||||
DEAL_FIELDS = tuple(field.name for field in fields(DealItem)) + ('order_local_id',)
|
||||
POSITION_DEFAULTS = asdict(PositionItem())
|
||||
POSITION_UPSERT = (
|
||||
f"INSERT INTO positions ({', '.join(POSITION_FIELDS)}) "
|
||||
f"VALUES ({', '.join(':' + key for key in POSITION_FIELDS)}) "
|
||||
@@ -98,20 +99,17 @@ class OrderBook:
|
||||
self.positions = positions
|
||||
self.deals = deals
|
||||
self.deals_sys_ids = set(deals)
|
||||
self._deal_count = len(deals)
|
||||
|
||||
@staticmethod
|
||||
def _insert_deals(db: sqlite3.Connection, deals: list[dict]) -> None:
|
||||
db.executemany(DEAL_INSERT, deals)
|
||||
|
||||
@staticmethod
|
||||
def deal_record(deal: DealItem) -> dict:
|
||||
if not deal.order_sys_id or deal.volume <= 0:
|
||||
raise ValueError('System order ID and positive volume are required')
|
||||
if not deal.local_order_id:
|
||||
raise ValueError('Local order ID is required')
|
||||
|
||||
row = asdict(deal)
|
||||
row['order_local_id'] = deal.local_order_id
|
||||
row['order_local_id'] = deal.get_local_order_id()
|
||||
if not row['order_local_id']:
|
||||
raise ValueError('Local order ID is required')
|
||||
|
||||
if any(isinstance(value, float) and not math.isfinite(value) for value in row.values()):
|
||||
raise ValueError('Numeric values must be finite')
|
||||
amount = deal.trade_amount if deal.trade_amount > 0 else deal.price * deal.volume
|
||||
@@ -125,35 +123,38 @@ class OrderBook:
|
||||
return row
|
||||
|
||||
def sync_deals(self, deals: list[DealItem]) -> None:
|
||||
new_deals = []
|
||||
seen = self.deals_sys_ids.copy()
|
||||
new_deals = {}
|
||||
for deal in deals:
|
||||
if deal.order_sys_id in seen:
|
||||
continue
|
||||
new_deals.append(self.deal_record(deal))
|
||||
seen.add(deal.order_sys_id)
|
||||
if deal.order_sys_id not in self.deals_sys_ids and deal.order_sys_id not in new_deals:
|
||||
new_deals[deal.order_sys_id] = self.deal_record(deal)
|
||||
if not new_deals:
|
||||
return
|
||||
with closing(self._connect()) as db, db:
|
||||
self._insert_deals(db, new_deals)
|
||||
db.executemany(DEAL_INSERT, new_deals.values())
|
||||
self.load()
|
||||
|
||||
def sync_positions(self, positions: list[PositionItem]) -> None:
|
||||
"""Replace the complete position snapshot, retaining IDs for existing stocks."""
|
||||
self.save({item.stock_code: asdict(item) for item in positions}, list(self.deals.values()))
|
||||
self.save({item.stock_code: asdict(item) for item in positions})
|
||||
|
||||
def save(self, items: dict, deals: list[dict]) -> None:
|
||||
if len(deals) < self._deal_count:
|
||||
raise ValueError('Execution history is append-only')
|
||||
new_deals = deals[self._deal_count:]
|
||||
positions = [{**asdict(PositionItem()), **item} for item in items.values()]
|
||||
def save(self, items: dict, deals: list[dict] | None = None) -> None:
|
||||
"""保存持仓快照,可同时追加成交;省略 deals 时仅更新持仓。"""
|
||||
new_deals = []
|
||||
if deals is not None:
|
||||
if len(deals) < len(self.deals):
|
||||
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]:
|
||||
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:
|
||||
for row in db.execute('SELECT stock_code FROM positions').fetchall():
|
||||
if row['stock_code'] not in items:
|
||||
db.execute('DELETE FROM positions WHERE stock_code = ?', (row['stock_code'],))
|
||||
removed = [
|
||||
(row['stock_code'],)
|
||||
for row in db.execute('SELECT stock_code FROM positions')
|
||||
if row['stock_code'] not in items
|
||||
]
|
||||
db.executemany('DELETE FROM positions WHERE stock_code = ?', removed)
|
||||
db.executemany(POSITION_UPSERT, positions)
|
||||
self._insert_deals(db, new_deals)
|
||||
db.executemany(DEAL_INSERT, new_deals)
|
||||
self.load()
|
||||
|
||||
Reference in New Issue
Block a user