import sqlite3 import tempfile import unittest from contextlib import closing from dataclasses import asdict from pathlib import Path from libs.orderbook import OrderBook from sdk.models import DealItem from sdk.portfolio import PortfolioMixin class DealModelTests(unittest.TestCase): def setUp(self): self.raw = { 'm_strOrderSysID': 'sys-123', 'm_strInstrumentID': '600000', 'm_strExchangeID': 'SH', 'm_strInstrumentName': 'Test stock', 'm_nOffsetFlag': '24', 'm_nOrderStatus': '56', 'm_nVolumeTotal': '0', 'm_nVolumeTraded': '200', 'm_nOrderTime': '101530', 'm_strInsertDate': '20260907', 'm_strInsertTime': '10:15:30', 'm_strRemark': 'zt-t-sell-local1|zt', 'm_dPrice': '15.8', 'm_dTradePrice': '15.6', 'm_dTradeAmount': '3120', } def test_all_api_fields_are_parsed(self): self.assertEqual(asdict(DealItem.from_trade_detail(self.raw)), { 'sys_order_id': 'sys-123', 'local_order_id': 'zt-t-sell-local1', 'code': '600000.SH', 'instrument_id': '600000', 'exchange_id': 'SH', 'name': 'Test stock', 'offset_flag': '24', 'side': 'SELL', 'status': '56', 'remaining_volume': 0, 'traded_volume': 200, 'order_time': 101530, 'insert_date': '20260907', 'insert_time': '10:15:30', 'remark': 'zt-t-sell-local1|zt', 'price': 15.8, 'trade_price': 15.6, 'trade_amount': 3120.0, }) def test_api_deals_response_returns_deal_items(self): client = PortfolioMixin() for response in ({'deals': [self.raw]}, [self.raw]): with self.subTest(response_type=type(response).__name__): client._get_json = lambda path: response deals = client.deals() self.assertIsInstance(deals[0], DealItem) self.assertEqual(deals[0].sys_order_id, 'sys-123') self.assertEqual(deals[0].traded_volume, 200) def test_model_matches_sql_columns_and_restart(self): deal = DealItem.from_trade_detail(self.raw) with tempfile.TemporaryDirectory() as tmp: path = Path(tmp) / 'state.db' book = OrderBook(path) book.sync_deals([deal]) with closing(sqlite3.connect(path)) as db: columns = {row[1] for row in db.execute('PRAGMA table_info(deals)')} self.assertEqual(columns, {'id', *asdict(deal)}) loaded = OrderBook(path).deals['sys-123'] expected = asdict(deal) expected['insert_date'] = '2026-09-07' self.assertEqual({key: value for key, value in loaded.items() if key != 'id'}, expected) def test_missing_amount_uses_execution_price_not_order_price(self): deal = DealItem.from_trade_detail({**self.raw, 'm_dTradeAmount': '0'}) row = OrderBook.deal_record(deal) self.assertEqual(row['trade_amount'], 3120) deal.trade_price = 0 with self.assertRaises(ValueError): OrderBook.deal_record(deal) if __name__ == '__main__': unittest.main()