79 lines
3.1 KiB
Python
79 lines
3.1 KiB
Python
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()
|