fix ipo bug
This commit is contained in:
@@ -14,6 +14,31 @@ from sdk.trade import TradeMixin
|
||||
from strategy.ipo import boot
|
||||
|
||||
|
||||
class IPOResponseClient(TradeMixin):
|
||||
"""真实解析 + 模拟传输:用于验证 QMT 原始响应到下单的完整链路。"""
|
||||
|
||||
def __init__(self, payload, orders=None):
|
||||
self.payload = payload
|
||||
self._orders = orders or []
|
||||
self.submitted = []
|
||||
|
||||
def _post_json(self, path, body=None):
|
||||
return self.payload
|
||||
|
||||
def orders(self):
|
||||
return self._orders
|
||||
|
||||
def passorder(self, **kwargs):
|
||||
self.submitted.append(kwargs)
|
||||
return {'status': 'success'}
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def __exit__(self, *_args):
|
||||
return False
|
||||
|
||||
|
||||
class IPOTests(unittest.TestCase):
|
||||
def setUp(self):
|
||||
temp = tempfile.TemporaryDirectory()
|
||||
@@ -151,6 +176,17 @@ class IPOTests(unittest.TestCase):
|
||||
self.client.passorder.assert_called_once()
|
||||
self.assertEqual(len(self.records()), 1)
|
||||
|
||||
def test_code_keyed_qmt_response_submits_subscription(self):
|
||||
client = IPOResponseClient(
|
||||
{'301001.SZ': {'issuePrice': 12.5, 'maxPurchaseNum': 15000}})
|
||||
with patch.object(boot, 'Client', return_value=client):
|
||||
self.assertEqual(boot.AutoBuyIpo(), 1)
|
||||
self.assertEqual(len(client.submitted), 1)
|
||||
self.assertEqual(client.submitted[0]['stock'], '301001.SZ')
|
||||
self.assertEqual(client.submitted[0]['volume'], 15000)
|
||||
self.assertEqual(client.submitted[0]['price'], 12.5)
|
||||
self.assertEqual([r['status'] for r in self.records()], ['pending'])
|
||||
|
||||
def test_supported_codes_and_numeric_strings(self):
|
||||
for stock in ['600001.SH', '688001.SH', '689001.SH', '000001.SZ',
|
||||
'001001.SZ', '002001.SZ', '003001.SZ', '300001.SZ', '301001.SZ']:
|
||||
@@ -161,14 +197,56 @@ class IPOTests(unittest.TestCase):
|
||||
|
||||
|
||||
class IPOResponseTests(unittest.TestCase):
|
||||
def test_only_list_response_is_accepted(self):
|
||||
def parsed(self, value):
|
||||
client = TradeMixin()
|
||||
for value in [None, {}, {'error': 'bad'}, '', 0, False]:
|
||||
client._post_json = Mock(return_value=value)
|
||||
client._post_json = Mock(return_value=value)
|
||||
return client.ipo_data()
|
||||
|
||||
def test_code_keyed_mapping_is_parsed(self):
|
||||
payload = {
|
||||
'301001.SZ': {'issuePrice': 12.5, 'maxPurchaseNum': 15000, 'stockName': '示例'},
|
||||
'601127.SH': {'issuePrice': 4.09, 'maxPurchaseNum': 15000},
|
||||
}
|
||||
self.assertEqual(self.parsed(payload), [
|
||||
dict(stock='301001.SZ', issuePrice=12.5, maxPurchaseNum=15000, stockName='示例'),
|
||||
dict(stock='601127.SH', issuePrice=4.09, maxPurchaseNum=15000),
|
||||
])
|
||||
|
||||
def test_bare_code_uses_market_field(self):
|
||||
payload = {'301001': {'market': 'SZ', 'issuePrice': 12.5, 'maxPurchaseNum': 15000}}
|
||||
self.assertEqual(self.parsed(payload), [
|
||||
dict(stock='301001.SZ', market='SZ', issuePrice=12.5, maxPurchaseNum=15000),
|
||||
])
|
||||
|
||||
def test_market_bucketed_mapping_is_flattened(self):
|
||||
payload = {
|
||||
'SH': {'601127': {'issuePrice': 4.09, 'maxPurchaseNum': 15000}},
|
||||
'SZ': {'301001': {'issuePrice': 12.5, 'maxPurchaseNum': 15000}},
|
||||
}
|
||||
self.assertEqual(self.parsed(payload), [
|
||||
dict(stock='601127.SH', market='SH', issuePrice=4.09, maxPurchaseNum=15000),
|
||||
dict(stock='301001.SZ', market='SZ', issuePrice=12.5, maxPurchaseNum=15000),
|
||||
])
|
||||
|
||||
def test_legacy_data_wrapper_is_unwrapped(self):
|
||||
payload = {'data': {'301001.SZ': {'issuePrice': 12.5, 'maxPurchaseNum': 15000}}}
|
||||
self.assertEqual(self.parsed(payload), [
|
||||
dict(stock='301001.SZ', issuePrice=12.5, maxPurchaseNum=15000),
|
||||
])
|
||||
|
||||
def test_list_response_passes_through(self):
|
||||
payload = [dict(stock='600001.SH', issuePrice=10, maxPurchaseNum=100)]
|
||||
self.assertEqual(self.parsed(payload), payload)
|
||||
|
||||
def test_empty_response_means_no_candidate(self):
|
||||
for value in [None, {}, [], {'SH': {}, 'SZ': {}}]:
|
||||
with self.subTest(value=value):
|
||||
self.assertEqual(self.parsed(value), [])
|
||||
|
||||
def test_unrecognised_structure_raises(self):
|
||||
for value in ['', 0, False, 'unexpected', {'error': 'bad'}, {'SH': 'x'}]:
|
||||
with self.subTest(value=value), self.assertRaises(ValueError):
|
||||
client.ipo_data()
|
||||
client._post_json = Mock(return_value=[])
|
||||
self.assertEqual(client.ipo_data(), [])
|
||||
self.parsed(value)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
Reference in New Issue
Block a user