def run(self): log.info("runing strategies...") # 初始化策略自定义时间序列变量 self._init_strategies() has_next = True while True: # Feeding data of latest. toremove = set() for s_pcontract in self._all_pcontracts: for ctx in self._contexts: ctx.data_ref.switch_to_pcontract(s_pcontract) has_next = ctx.data_ref.rolling_forward( ctx.update_datetime) if not has_next: toremove.add(s_pcontract) if toremove: for s_pcontract in toremove: self._all_pcontracts.remove(s_pcontract) if len(self._all_pcontracts) == 0: # 策略退出后的处理 for ctx in self._contexts: ctx.data_ref.switch_to_default_pcontract() # 异步情况下不同策略的结束时间不一样。 ctx.strategy.on_exit(ctx) return # Updating global context variables like # close price and context time. for s_pcontract in self._all_pcontracts: for ctx in self._contexts: ctx.data_ref.switch_to_pcontract(s_pcontract) if ctx.data_ref.datetime_aligned(ctx.aligned_dt): ctx.data_ref.update_system_vars() ctx.data_ref.original.has_pending_data = False # Calculating user context variables. for s_pcontract in self._all_pcontracts: # Iterating over combinations. for ctx in self._contexts: ctx.data_ref.switch_to_pcontract(s_pcontract) if not ctx.data_ref.datetime_aligned(ctx.aligned_dt): continue ctx.data_ref.update_user_vars() ctx.on_bar = False ctx.strategy.on_symbol(ctx) # 遍历组合策略每轮数据的最后处理 tick_test = settings['tick_test'] for ctx in self._contexts: # 确保单合约回测的默认值 ctx.data_ref.switch_to_default_pcontract() ctx.on_bar = True # 确保交易状态是基于开盘时间的。 ctx.process_trading_events(at_baropen=True) ctx.strategy.on_bar(ctx) if not tick_test: # 保证有可能在当根Bar成交 ctx.process_trading_events(at_baropen=False) ctx.aligned_dt = MAX_DATETIME ctx.aligned_bar_index += 1
def _load_data(self, strpcons, dt_start, dt_end, n, spec_date): all_data = OrderedDict() max_window = -1 log.info("loading data...") pcontracts = [PContract.from_string(s) for s in strpcons] pcontracts = sorted(pcontracts, key=PContract.__str__, reverse=True) for i, pcon in enumerate(pcontracts): strpcon = str(pcon) if strpcon in spec_date: dt_start = spec_date[strpcon][0] dt_end = spec_date[strpcon][1] assert (dt_start < dt_end) if n: raw_data = self._data_manager.get_last_bars(strpcon, n) else: raw_data = self._data_manager.get_bars(strpcon, dt_start, dt_end) if len(raw_data) == 0: continue all_data[strpcon] = raw_data max_window = max(max_window, len(raw_data)) if n: assert (max_window <= n) if len(all_data) == 0: assert (False) # @TODO raise return all_data, max_window
def __init__(self, name, event_protocol="tcp://127.0.0.1:5555", register_protocol="tcp://127.0.0.1:5557"): EventEngine.__init__(self) self._name = name self._context = zmq.Context() try: self._broadcast_event_socket = self._context.socket(zmq.PUB) self._broadcast_event_socket.bind(event_protocol) self._server_recv_event_socket = self._context.socket(zmq.PULL) self._server_recv_event_socket.bind(register_protocol) self._is_server = True log.info('Run ZMQEventEngine Server: %s' % self._name) except zmq.error.ZMQError: log.info('Run ZMQEventEngine client: %s' % self._name) self._is_server = False self._emit_event_socket = self._context.socket(zmq.PUSH) self._emit_event_socket.connect(register_protocol) self._client_recv_event_socket = self._context.socket(zmq.SUB) self._client_recv_event_socket.connect(event_protocol) self._thrd = Thread(target=self._run) self._thrd.daemon = True self._queue_engine = QueueEventEngine(self._name) time.sleep(1)
def run(self): def run_strategy(ctx, pcontract_symbols): for s_pcontract in self._all_pcontracts: ctx.data_ref.switch_to_pcontract(s_pcontract) ctx.strategy.on_init(ctx) while True: # Feeding data of latest. toremove = set() for s_pcontract in pcontract_symbols: ctx.data_ref.switch_to_pcontract(s_pcontract) has_next = ctx.data_ref.rolling_forward( ctx.update_datetime) if not has_next: toremove.add(s_pcontract) if toremove: for s_pcontract in toremove: pcontract_symbols.remove(s_pcontract) # call `on_exit` of strategies if len(pcontract_symbols) == 0: ctx.data_ref.switch_to_default_pcontract() ctx.strategy.on_exit(ctx) return for s_pcontract in pcontract_symbols: ctx.data_ref.switch_to_pcontract(s_pcontract) if not ctx.data_ref.datetime_aligned(ctx.aligned_dt): continue # Update original and derived series data ctx.data_ref.update_original_vars() ctx.data_ref.update_derived_vars() ctx.data_ref.original.has_pending_data = False # call `on_symbol` of strategies ctx.on_bar = False ctx.strategy.on_symbol(ctx) # call `on_bar` of strategies ctx.data_ref.switch_to_default_pcontract() ctx.on_bar = True # 确保交易状态是基于开盘时间的。 ctx.process_trading_events(at_baropen=True) ctx.strategy.on_bar(ctx) if not settings['tick_test']: # 保证有可能在当根Bar成交 ctx.process_trading_events(at_baropen=False) ctx.aligned_dt = MAX_DATETIME ctx.aligned_bar_index += 1 for ctx in self._contexts: log.info("run strategy {0}".format(ctx.strategy_name)) run_strategy(ctx, deepcopy(self._all_pcontracts))
def __init__(self, event_engine, service, event_client=None, event_server=None): super(EventRPCServer, self).__init__() self._routes = {} self._routes_lock = Lock() # server监听的client事件 self.EVENT_FROM_CLIENT = event_client if event_client else "EVENT_FROM_%s_CLIENT" % service.upper( ) # client监听的server事件 self.EVENT_FROM_SERVER = event_server if event_server else "EVENT_FROM_%s_SERVER" % service.upper( ) self._event_engine = event_engine self._event_engine.register(self.EVENT_FROM_CLIENT, self._process_request) log.info("[Create RPCServer %s]" % self.EVENT_FROM_CLIENT) self._name = service.upper()
def _process_apiback(self, event): assert (event.route == self.EVENT_FROM_SERVER) self._timeout = 0 rid = event.args['rid'] try: with self._handlers_lock: handler = self._handlers[rid] except KeyError: log.info('[RPCClient._process_apiback] 放弃超时任务的返回结果') else: try: if handler: # 异步 handler(event.args['ret']) else: # 同步 self._sync_ret = event.args['ret'] self._notify_server_data() except Exception as e: log.error(e) log.debug("[RPCClient._process_apiback] 删除已经完成的任务 rid; %s" % rid) with self._handlers_lock: del self._handlers[rid]
def get_bars(self, pcontract, dt_start, dt_end): try: log.info('trying to load from cache') return self.cache.get_bars(pcontract, dt_start, dt_end) except LoadCacheException as e: log.info('updating cache') missing_range = e.missing_range log.info('missing range: {0}', missing_range) missing_data = [] for start, end in missing_range: wrapper = self.datasource.get_bars(pcontract, start, end) missing_data.append(HashObject.new(data=wrapper.data, start=start, end=end)) self.cache.save_data(missing_data, pcontract) log.info('loading cache') return self.cache.get_bars(pcontract, dt_start, dt_end)
def on_register(self, name): log.info('register datasource: {0} => {1}'.format(self.cls, name))
def start(self): log.info('start timer') self._timer_active = True self._timer.start()