This commit is contained in:
2026-09-10 12:50:40 +08:00
parent 72a49bc741
commit d837250bcb
10 changed files with 423 additions and 458 deletions

View File

@@ -22,6 +22,11 @@ class ArchivingTests(unittest.TestCase):
(code, order, order, flag, amount / qty, qty, amount, '2026-09-08', time),
)
def test_schema_only_has_state_and_deals(self):
with closing(self.book._connect()) as db:
tables = {row[0] for row in db.execute("SELECT name FROM sqlite_master WHERE type='table'")}
self.assertEqual(tables, {'state', 'deals', 'sqlite_sequence'})
def test_accumulates_once_and_preserves_base(self):
self.book.sync_state([PositionItem(stock_code='600000.SH', volume=100, open_price=8)])
original = dict(self.book.state['600000.SH'])
@@ -45,7 +50,7 @@ class ArchivingTests(unittest.TestCase):
row = self.book.state['600000.SH']
self.assertEqual(row['added_qty'], 150)
self.assertAlmostEqual(row['added_price'], 1620 / 150)
self.assertEqual(row['added_order_local_id'], 'second')
self.assertEqual(row['added_order_local_id'], 'late')
def test_sell_added_then_clear_base(self):
self.book.sync_state([PositionItem(stock_code='600000.SH', volume=100, open_price=8)])
@@ -80,11 +85,7 @@ class ArchivingTests(unittest.TestCase):
self.book.archiving()
self.assertEqual(self.book.state, {})
def test_excess_sell_rolls_back_and_other_directions_are_skipped(self):
self.insert_deal('other', 100, 1000, '09:59:00', flag=23)
self.book.archiving()
self.assertEqual(self.book.state, {})
self.assertEqual(self.book.deals['other']['is_arch'], 0)
def test_excess_sell_rolls_back(self):
self.insert_deal('buy', 50, 500, '10:00:00')
self.insert_deal('sell', 100, 1200, '10:01:00', flag=49)
errors = self.book.archiving()
@@ -93,6 +94,17 @@ class ArchivingTests(unittest.TestCase):
self.assertEqual(restarted.state, {})
self.assertTrue(all(deal['is_arch'] == 0 for deal in restarted.deals.values()))
def test_stock_buy_and_sell_flags(self):
self.book.sync_state([PositionItem(stock_code='600000.SH', volume=100, open_price=8)])
self.insert_deal('buy', 100, 1000, '10:00:00', flag=23)
self.insert_deal('sell', 50, 600, '10:01:00', flag=24)
self.assertEqual(self.book.archiving(), {})
row = self.book.state['600000.SH']
self.assertEqual((row['base_qty'], row['added_qty']), (100, 50))
self.assertEqual(self.book.deals['buy']['offset_flag'], 23)
self.assertEqual(self.book.deals['sell']['offset_flag'], 24)
self.assertTrue(all(deal['is_arch'] == 1 for deal in self.book.deals.values()))
def test_new_state_and_failed_mark_roll_back_together(self):
self.insert_deal('first', 100, 1000, '10:00:00')
self.insert_deal('second', 100, 1200, '10:01:00', code='600001.SH')
@@ -115,7 +127,7 @@ class ArchivingTests(unittest.TestCase):
self.assertEqual(self.book.state['600000.SH']['base_qty'], 0)
self.assertEqual(self.book.state['600000.SH']['added_qty'], 100)
def test_snapshot_matching_buy_is_not_added(self):
def test_equal_quantity_buy_is_added_and_preserves_status(self):
self.book.sync_state([PositionItem(stock_code='600000.SH', volume=100, open_price=8)])
self.book.sync_deals([DealItem(
stock_code='600000.SH', order_sys_id='first', remark='base1|test',
@@ -124,7 +136,7 @@ class ArchivingTests(unittest.TestCase):
)])
self.assertEqual(self.book.archiving(), {})
row = self.book.state['600000.SH']
self.assertEqual((row['base_qty'], row['added_qty']), (100, 0))
self.assertEqual((row['base_qty'], row['added_qty']), (100, 100))
self.assertEqual(self.book.deals['first']['is_arch'], 1)
restarted = State(self.book.path)
self.assertEqual(restarted.archiving(), {})
@@ -134,19 +146,20 @@ class ArchivingTests(unittest.TestCase):
db.execute("UPDATE state SET status = 'CUSTOM' WHERE stock_code = '600000.SH'")
self.assertEqual(self.book.archiving(), {})
row = self.book.state['600000.SH']
self.assertEqual((row['base_qty'], row['added_qty'], row['status']), (100, 100, 'CUSTOM'))
self.assertEqual((row['base_qty'], row['added_qty'], row['status']), (100, 200, 'CUSTOM'))
def test_old_archived_history_without_baseline_is_not_reapplied(self):
def test_archived_history_is_not_reapplied(self):
self.insert_deal('old', 100, 1000, '10:00:00')
with closing(self.book._connect()) as db, db:
db.execute('UPDATE deals SET is_arch = 1')
self.insert_deal('new', 50, 500, '10:01:00')
errors = self.book.archiving()
self.assertIn('baseline', errors['600000.SH'])
self.assertEqual(errors, {})
self.assertEqual(self.book.state['600000.SH']['added_qty'], 50)
self.assertEqual(self.book.deals['old']['is_arch'], 1)
self.assertEqual(self.book.deals['new']['is_arch'], 0)
self.assertEqual(self.book.deals['new']['is_arch'], 1)
def test_late_buy_replays_after_liquidation_and_restart(self):
def test_late_buy_is_incremental_after_liquidation_and_restart(self):
self.insert_deal('buy', 100, 1000, '10:00:00')
self.insert_deal('sell', 100, 1500, '10:02:00', flag=49)
self.book.archiving()
@@ -156,11 +169,12 @@ class ArchivingTests(unittest.TestCase):
self.assertEqual(self.book.archiving(), {})
row = self.book.state['600000.SH']
self.assertEqual(row['added_qty'], 100)
self.assertEqual(row['added_price'], 15)
self.assertEqual(row['added_price'], 20)
def test_snapshot_deletion_before_sell_archiving(self):
def test_archive_sell_before_syncing_empty_positions(self):
self.book.sync_state([PositionItem(stock_code='600000.SH', volume=100, open_price=8)])
self.insert_deal('sell', 100, 1000, '10:01:00', flag=49)
self.assertEqual(self.book.archiving(), {})
self.book.sync_state([])
self.book = State(self.book.path)
self.assertEqual(self.book.archiving(), {})