forked from robcarver17/pysystemtrade
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmongo_historic_orders.py
230 lines (179 loc) · 7.21 KB
/
mongo_historic_orders.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
import datetime
from syscore.exceptions import missingData
from syscore.constants import arg_not_supplied, success
from sysexecution.orders.named_order_objects import missing_order
from sysdata.mongodb.mongo_generic import mongoDataWithSingleKey
from sysexecution.orders.base_orders import Order
from sysexecution.orders.instrument_orders import instrumentOrder
from sysexecution.orders.contract_orders import contractOrder
from sysexecution.orders.broker_orders import brokerOrder
from syslogging.logger import *
from sysdata.production.historic_orders import (
genericOrdersData,
strategyHistoricOrdersData,
contractHistoricOrdersData,
brokerHistoricOrdersData,
)
from sysobjects.production.tradeable_object import (
instrumentStrategy,
futuresContractStrategy,
)
ORDER_ID_STORE_KEY = "_ORDER_ID_STORE_KEY"
class mongoGenericHistoricOrdersData(genericOrdersData):
"""
Read and write data class to get roll state data
"""
def _collection_name(self):
raise NotImplementedError("Need to inherit for a specific data type")
def _order_class(self):
raise NotImplementedError("Need to inherit for a specific data type")
def _name(self):
return "Historic orders"
def __init__(self, mongo_db=None, log=get_logger("mongoGenericHistoricOrdersData")):
# Not needed as we don't store anything in _state attribute used in parent class
# If we did have _state would risk breaking if we forgot to override methods
# super().__init__()
collection_name = self._collection_name()
self._mongo_data = mongoDataWithSingleKey(
collection_name, "order_id", mongo_db=mongo_db
)
super().__init__(log=log)
@property
def mongo_data(self):
return self._mongo_data
def __repr__(self):
return "%s (%s)" % (self._name, str(self.mongo_data))
def add_order_to_data(self, order: Order, ignore_duplication: bool = False):
# Duplicates will be overridden, so be careful
order_id = order.order_id
no_existing_order = self.get_order_with_orderid(order_id) is missing_order
if no_existing_order:
return self._add_order_to_data_no_checking(order)
else:
if ignore_duplication:
return self.update_order_with_orderid(order_id, order)
else:
raise Exception(
"Can't add order %s as order id %d already exists!"
% (str(order), order_id)
)
def _add_order_to_data_no_checking(self, order: Order):
# Duplicates will be overridden, so be careful
mongo_record = order.as_dict()
self.mongo_data.add_data(order.order_id, mongo_record, allow_overwrite=True)
def get_order_with_orderid(self, order_id: int):
try:
result_dict = self.mongo_data.get_result_dict_for_key(order_id)
except missingData:
return missing_order
order_class = self._order_class()
order = order_class.from_dict(result_dict)
return order
def _delete_order_with_orderid_without_checking(self, order_id):
self.mongo_data.delete_data_without_any_warning(order_id)
def update_order_with_orderid(self, order_id, order):
mongo_record = order.as_dict()
self.mongo_data.add_data(order_id, mongo_record)
def get_list_of_order_ids(self) -> list:
order_ids = self.mongo_data.get_list_of_keys()
return order_ids
def get_list_of_order_ids_in_date_range(
self,
period_start: datetime.datetime,
period_end: datetime.datetime = arg_not_supplied,
) -> list:
if period_end is arg_not_supplied:
period_end = datetime.datetime.now()
find_dict = dict(fill_datetime={"$gte": period_start, "$lt": period_end})
list_of_order_dicts = self.mongo_data.get_list_of_result_dict_for_custom_dict(
find_dict
)
order_ids = [order_dict["order_id"] for order_dict in list_of_order_dicts]
return order_ids
class mongoStrategyHistoricOrdersData(
mongoGenericHistoricOrdersData, strategyHistoricOrdersData
):
def _collection_name(self):
return "_STRATEGY_HISTORIC_ORDERS"
def _order_class(self):
return instrumentOrder
def _name(self):
return "Historic instrument/strategy orders"
def get_list_of_order_ids_for_instrument_strategy(
self, instrument_strategy: instrumentStrategy
) -> list:
old_list_of_order_id = (
self._get_list_of_order_ids_for_instrument_strategy_specify_key(
instrument_strategy, "old_key"
)
)
new_list_of_order_id = (
self._get_list_of_order_ids_for_instrument_strategy_specify_key(
instrument_strategy, "key"
)
)
return old_list_of_order_id + new_list_of_order_id
def _get_list_of_order_ids_for_instrument_strategy_specify_key(
self, instrument_strategy: instrumentStrategy, keyfield: str
) -> list:
object_key = getattr(instrument_strategy, keyfield)
custom_dict = dict(key=object_key)
list_of_result_dicts = self.mongo_data.get_list_of_result_dict_for_custom_dict(
custom_dict
)
list_of_order_id = [result["order_id"] for result in list_of_result_dicts]
return list_of_order_id
class mongoContractHistoricOrdersData(
mongoGenericHistoricOrdersData, contractHistoricOrdersData
):
def _collection_name(self):
return "_CONTRACT_HISTORIC_ORDERS"
def _order_class(self):
return contractOrder
def _name(self):
return "Historic contract orders"
class mongoBrokerHistoricOrdersData(
mongoGenericHistoricOrdersData, brokerHistoricOrdersData
):
def _collection_name(self):
return "_BROKER_HISTORIC_ORDERS"
def _order_class(self):
return brokerOrder
def _name(self):
return "Historic broker orders"
def get_list_of_order_ids_for_instrument_and_contract_str(
self, instrument_code: str, contract_str: str
) -> list:
order_id_list = self.get_list_of_order_ids()
key_list = [
self.mongo_data.get_result_dict_for_key(order_id)["key"]
for order_id in order_id_list
]
contract_strategies = [
futuresContractStrategy.from_key(key) for key in key_list
]
def _contains_both(
futures_contract_strategy: futuresContractStrategy,
instrument_code: str,
contract_str: str,
):
list_of_date_str = futures_contract_strategy.contract_date.list_of_date_str
if (
futures_contract_strategy.instrument_code == instrument_code
and contract_str in list_of_date_str
):
return True
else:
return False
order_ids = [
orderid
for orderid, futures_contract_strategy in zip(
order_id_list, contract_strategies
)
if _contains_both(
futures_contract_strategy,
instrument_code=instrument_code,
contract_str=contract_str,
)
]
return order_ids