def after_trading(self, event): for account, order in self._open_orders: order.mark_rejected(_(u"Order Rejected: {order_book_id} can not match. Market close.").format( order_book_id=order.order_book_id )) self._env.event_bus.publish_event(Event(EVENT.ORDER_UNSOLICITED_UPDATE, account=account, order=order)) self._open_orders = self._delayed_orders self._delayed_orders = []
def _match(self): self._matcher.match(self._open_orders) final_orders = [(a, o) for a, o in self._open_orders if o.is_final()] self._open_orders = [(a, o) for a, o in self._open_orders if not o.is_final()] for account, order in final_orders: if order.status == ORDER_STATUS.REJECTED or order.status == ORDER_STATUS.CANCELLED: self._env.event_bus.publish_event(Event(EVENT.ORDER_UNSOLICITED_UPDATE, account=account, order=order))
def output_profile_result(env): stdout_trap = six.StringIO() env.profile_deco.print_stats(stdout_trap) profile_output = stdout_trap.getvalue() profile_output = profile_output.rstrip() six.print_(profile_output) env.event_bus.publish_event( Event(EVENT.ON_LINE_PROFILER_RESULT, result=profile_output))
def update(self, universe): if isinstance(universe, (six.string_types, Instrument)): universe = [universe] new_set = set(universe) if new_set != self._set: self._set = new_set Environment.get_instance().event_bus.publish_event( Event(EVENT.POST_UNIVERSE_CHANGED, universe=self._set))
def _get_events_for_tick(self, start_date, end_date, frequency): data_proxy = self._env.data_proxy for day in data_proxy.get_trading_dates(start_date, end_date): date = day.to_pydatetime() last_tick = None last_dt = None dt_before_day_trading = date.replace(hour=8, minute=30) while True: for tick in data_proxy.get_merge_ticks(self._get_universe(), date, last_dt): # find before trading time if last_tick is None: last_tick = tick dt = tick.datetime before_trading_dt = dt - datetime.timedelta(minutes=30) yield Event(EVENT.BEFORE_TRADING, calendar_dt=before_trading_dt, trading_dt=before_trading_dt) dt = tick.datetime if dt < dt_before_day_trading: trading_dt = dt.replace(year=date.year, month=date.month, day=date.day) else: trading_dt = dt yield Event(EVENT.TICK, calendar_dt=dt, trading_dt=trading_dt, tick=tick) if self._universe_changed: self._universe_changed = False last_dt = dt break else: break dt = date.replace(hour=15, minute=30) yield Event(EVENT.AFTER_TRADING, calendar_dt=dt, trading_dt=dt) dt = date.replace(hour=17, minute=0) yield Event(EVENT.SETTLEMENT, calendar_dt=dt, trading_dt=dt)
def init(self): if not self._init: return with ExecutionContext(EXECUTION_PHASE.ON_INIT): with ModifyExceptionFromType(EXC_TYPE.USER_EXC): self._init(self._user_context) Environment.get_instance().event_bus.publish_event(Event(EVENT.POST_USER_INIT))
def submit_order(self, order): account = self._env.get_account(order.order_book_id) self._env.event_bus.publish_event( Event(EVENT.ORDER_PENDING_NEW, account=account, order=order)) if order.is_final(): return '''if self._env.config.base.frequency == 'tick' and not self._match_immediately: #zoulida self._delayed_orders.append((account, order)) return''' if self._env.config.base.frequency == '1d' and not self._match_immediately: self._delayed_orders.append((account, order)) return self._open_orders.append((account, order)) order.active() self._env.event_bus.publish_event( Event(EVENT.ORDER_CREATION_PASS, account=account, order=order)) if self._match_immediately: self._match()
def on_order(self, event): vnpy_order = event.dict_['data'] system_log.debug("on_order {}", vnpy_order.__dict__) # FIXME 发现订单会重复返回,此操作是否会导致订单丢失有待验证 if vnpy_order.status == STATUS_UNKNOWN: return vnpy_order_id = vnpy_order.vtOrderID order = self._data_factory.get_order(vnpy_order) if not self._account_inited: self._data_factory.cache_vnpy_order_before_init(vnpy_order) else: account = Environment.get_instance().get_account( order.order_book_id) order.active() self._env.event_bus.publish_event( Event(EVENT.ORDER_CREATION_PASS, account=account, order=order)) self._data_factory.cache_vnpy_order(order.order_id, vnpy_order) if vnpy_order.status == STATUS_NOTTRADED or vnpy_order.status == STATUS_PARTTRADED: self._data_factory.cache_open_order(vnpy_order_id, order) elif vnpy_order.status == STATUS_ALLTRADED: self._data_factory.del_open_order(vnpy_order_id) elif vnpy_order.status == STATUS_CANCELLED: self._data_factory.del_open_order(vnpy_order_id) if order.status == ORDER_STATUS.PENDING_CANCEL: order.mark_cancelled( "%d order has been cancelled by user." % order.order_id) self._env.event_bus.publish_event( Event(EVENT.ORDER_CANCELLATION_PASS, account=account, order=order)) else: order.mark_rejected( 'Order was rejected or cancelled by vnpy.') self._env.event_bus.publish_event( Event(EVENT.ORDER_UNSOLICITED_UPDATE, account=account, order=order))
def _get_events_in_day(self, start_date, end_date, frequency): for day in self._env.data_proxy.get_trading_dates(start_date, end_date): before_trading_flag = True date = day.to_pydatetime() last_dt = None done = False dt_before_day_trading = date.replace(hour=8, minute=30) while True: if done: break exit_loop = True trading_points = self._get_trading_points(date, frequency) for calendar_dt in trading_points: if last_dt is not None and calendar_dt < last_dt: continue if calendar_dt < dt_before_day_trading: trading_dt = calendar_dt.replace(year=date.year, month=date.month, day=date.day) else: trading_dt = calendar_dt if before_trading_flag: before_trading_flag = False yield Event(EVENT.BEFORE_TRADING, calendar_dt=calendar_dt - datetime.timedelta(minutes=30), trading_dt=trading_dt - datetime.timedelta(minutes=30)) if self._universe_changed: self._universe_changed = False last_dt = calendar_dt exit_loop = False break # yield handle bar yield Event(EVENT.BAR, calendar_dt=calendar_dt, trading_dt=trading_dt) if exit_loop: done = True dt = date.replace(hour=15, minute=30) yield Event(EVENT.AFTER_TRADING, calendar_dt=dt, trading_dt=dt) dt = date.replace(hour=17, minute=0) yield Event(EVENT.SETTLEMENT, calendar_dt=dt, trading_dt=dt)
def _clear_de_listed(self, event): de_listed = set() env = Environment.get_instance() for o in self._set: i = env.data_proxy.instruments(o) if i.de_listed_date <= env.trading_dt: de_listed.add(o) if de_listed: self._set -= de_listed env.event_bus.publish_event(Event(EVENT.POST_UNIVERSE_CHANGED, universe=self._set))
def submit_order(self, order): """ 提交订单。在当前版本,RQAlpha 会生成 :class:`~Order` 对象,再通过此接口提交到 Broker。 TBD: 由 Broker 对象生成 Order 并返回? """ print("Broker.submit_order") # if order.type == ORDER_TYPE.MARKET: # raise RuntimeError("submit_order not support ORDER_TYPE.MARKET") account = self._get_account(order.order_book_id) self._env.event_bus.publish_event( Event(EVENT.ORDER_PENDING_NEW, account=account, order=order)) order.active() security_id, exchange_id = order.order_book_id.split(".") # convert to wind style if exchange_id == "XSHG": exchange_id = "SH" if exchange_id == "XSHE": exchange_id = "SZ" if order.side == SIDE.BUY: order_side = "B" if order.side == SIDE.SELL: order_side = "S" resultData, returnMsg = self._trade_api.place_order( security_id + "." + exchange_id, order_side, order.quantity, order.price) # 事件通知 if resultData == "-1": order.mark_rejected("trade api req err:{} ".format(returnMsg[1])) self._env.event_bus.publish_event( Event(EVENT.ORDER_CREATION_REJECT, account=account, order=order)) else: # order.secondary_order_id = resultData self._open_orders[resultData] = order self._env.event_bus.publish_event( Event(EVENT.ORDER_CREATION_PASS, account=account, order=order))
def publish_settlement(e=None): if e: previous_trading_date = self._env.data_proxy.get_previous_trading_date(e.trading_dt).date() if self._env.trading_dt.date() != previous_trading_date: self._env.trading_dt = datetime.combine(previous_trading_date, self._env.trading_dt.time()) self._env.calendar_dt = datetime.combine(previous_trading_date, self._env.calendar_dt.time()) event_bus.publish_event(PRE_SETTLEMENT) event_bus.publish_event(Event(EVENT.SETTLEMENT)) event_bus.publish_event(POST_SETTLEMENT)
def cancel_order(self, order): account = Environment.get_instance().get_account(order.order_book_id) self._env.event_bus.publish_event( Event(EVENT.ORDER_PENDING_CANCEL, account=account, order=order)) cancel_order_req = self._data_factory.make_cancel_order_req(order) if cancel_order_req is None: system_log.warn('Cannot find VN.PY order in order cache.') self.vnpy_gateway.cancelOrder(cancelOrderReq=cancel_order_req)
def end(self): if not self._end: return with ExecutionContext(EXECUTION_PHASE.FINALIZED): with ModifyExceptionFromType(EXC_TYPE.USER_EXC): self._end(self._user_context) Environment.get_instance().event_bus.publish_event( Event(EVENT.POST_USER_END))
def cancel_order(self, order): account = self._env.get_account(order.order_book_id) self._env.event_bus.publish_event( Event(EVENT.ORDER_PENDING_CANCEL, account=account, order=order)) order.mark_cancelled( _(u"{order_id} order has been cancelled by user.").format( order_id=order.order_id)) self._env.event_bus.publish_event( Event(EVENT.ORDER_CANCELLATION_PASS, account=account, order=order)) try: self._open_orders.remove((account, order)) except ValueError: try: self._delayed_orders.remove((account, order)) except ValueError: pass
def _get_events_for_d(self, start_date, end_date, frequency): num = int(frequency[:-1]) for day in islice( self._env.data_proxy.get_trading_dates(start_date, end_date), None, None, num): date = day.to_pydatetime() dt_before_trading = date.replace(hour=0, minute=0) dt_bar = date.replace(hour=15, minute=0) dt_after_trading = date.replace(hour=15, minute=30) dt_settlement = date.replace(hour=17, minute=0) yield Event(EVENT.BEFORE_TRADING, calendar_dt=dt_before_trading, trading_dt=dt_before_trading) yield Event(EVENT.BAR, calendar_dt=dt_bar, trading_dt=dt_bar) yield Event(EVENT.AFTER_TRADING, calendar_dt=dt_after_trading, trading_dt=dt_after_trading) yield Event(EVENT.SETTLEMENT, calendar_dt=dt_settlement, trading_dt=dt_settlement)
def _pre_after_trading(self, event): # 收盘时清掉未完成的订单 for __, order in self._open_order: order.mark_rejected(_(u"Order Rejected: {order_book_id} can not match. Market close.").format( order_book_id=order.order_book_id )) account = self._env.get_account(order.order_book_id) self._env.event_bus.publish_event(Event(EVENT.ORDER_UNSOLICITED_UPDATE, account=account, order=order)) self._open_orders = [] print("broker after_trading")
def send_order(self, order): account = Environment.get_instance().get_account(order.order_book_id) self._env.event_bus.publish_event( Event(EVENT.ORDER_PENDING_NEW, account=account, order=order)) order_req = self._data_factory.make_order_req(order) if order_req is None: self._env.event_bus.publish_event(Event( EVENT.ORDER_PENDING_CANCEL)) order.mark_cancelled( 'No contract exists whose order_book_id is %s' % order.order_book_id) self._env.event_bus.publish_event( Event(EVENT.ORDER_CANCELLATION_PASS)) if order.is_final(): return vnpy_order_id = self.vnpy_gateway.sendOrder(order_req) self._data_factory.cache_order(vnpy_order_id, order)
def events(self, start_date, end_date, frequency): running = True self.clock_engine_thread.start() self.quotation_engine_thread.start() while running: real_dt = datetime.datetime.now() dt, event_type = self.event_queue.get() system_log.debug("real_dt {}, dt {}, event {}", real_dt, dt, event_type) yield Event(event_type, real_dt, dt)
def test_on_tick(self): from rqalpha.events import EVENT, Event self.assertEqual(self.benchmark_account.total_value, self.benchmark_account_total_cash) self.assertEqual(len(self.benchmark_account.positions), 0) mock_event = Event(EVENT.TICK, tick=mock_tick(mock_instrument(self.benchmark), last=3000)) self.env.event_bus.publish_event(mock_event) self.assertAlmostEqual(self.benchmark_account.positions[self.benchmark].quantity, 4000 / 3000) self.env.event_bus.publish_event(mock_event) self.assertAlmostEqual(self.benchmark_account.positions[self.benchmark].quantity, 4000 / 3000)
def cancel_order(self, order): """ 撤单。 :param order: 订单 :type order: :class:`~Order` """ account = self._get_account(order.order_book_id) order_id = self._get_order_id(order) if order_id is None: return if order.is_final(): return self._env.event_bus.publish_event( Event(EVENT.ORDER_PENDING_CANCEL, account=account, order=order)) # ret_code, ret_msg = self._trade_api.cancel_order (0, futu_order_id, self._env) # 0 = 撤单 self._env.event_bus.publish_event( Event(EVENT.ORDER_CANCELLATION_REJECT, account=account, order=order))
def on_trade(self, event): vnpy_trade = event.dict_['data'] system_log.debug("on_trade {}", vnpy_trade.__dict__) if not self._account_inited: self._data_factory.cache_vnpy_trade_before_init(vnpy_trade) else: order = self._data_factory.get_order(vnpy_trade) trade = self._data_factory.make_trade(vnpy_trade, order.order_id) account = Environment.get_instance().get_account( order.order_book_id) self._env.event_bus.publish_event( Event(EVENT.TRADE, account=account, trade=trade))
def submit_order(self, order): route = '/sell' if order.side == SIDE.SELL else '/buy' price = order.price if order.type == ORDER_TYPE.MARKET: if order.side == SIDE.SELL: price = self._env.price_board.get_limit_down(order.order_book_id) else: price = self._env.price_board.get_limit_up(order.order_book_id) parmas = 'stock_no=%s&amount=%d&price=%f' % ( stock_no(order.order_book_id), order.quantity, price, ) url = '%s%s?%s' % (self._address, route, parmas) user_system_log.info('loading: %s' % url) reason = 'request failed' try: account = self._env.get_account(order.order_book_id) self._env.event_bus.publish_event(Event(EVENT.ORDER_PENDING_NEW, account=account, order=order)) with request.urlopen(url) as f: user_system_log.info('status: %d %s' % (f.status, f.reason)) if f.status == 200: data = f.read().decode('utf-8') resp = json.loads(data) if resp.get('success', False): order.active() self._env.event_bus.publish_event(Event(EVENT.ORDER_CREATION_PASS, account=account, order=order)) str_order_id = str(order.order_id) entrust_no = resp['entrust_no'] self._open_orders[str_order_id] = order self._order_id_map[entrust_no] = str_order_id self._order_id_map[str_order_id] = entrust_no return else: reason = resp.get('msg', reason) except Exception as e: user_system_log.warn(repr(e)) order.mark_rejected(reason) self._env.event_bus.publish_event(Event(EVENT.ORDER_UNSOLICITED_UPDATE, account=account, order=order))
def submit_order(self, order): """ 提交订单。在当前版本,RQAlpha 会生成 :class:`~Order` 对象,再通过此接口提交到 Broker。 TBD: 由 Broker 对象生成 Order 并返回? """ print("FUTUBrokerCN.submit_order:{}".format(order)) if order.type == ORDER_TYPE.MARKET: raise RuntimeError("submit_order not support ORDER_TYPE.MARKET") account = self._get_account(order.order_book_id) self._env.event_bus.publish_event( Event(EVENT.ORDER_PENDING_NEW, account=account, order=order)) order.active() # 发起futu api接口请求 futu_order_side = 0 if order.side == SIDE.BUY else 1 futu_order_type = 0 # 港股增强限价单 ret_code, ret_data = self._trade_context.place_order( order.price, order.quantity, order.order_book_id, futu_order_side, futu_order_type, self._trade_envtype) # 事件通知 if ret_code != 0: order.mark_rejected("futu api req err:{} ".format(ret_code)) self._env.event_bus.publish_event( Event(EVENT.ORDER_CREATION_REJECT, account=account, order=order)) else: futu_order_id = ret_data.loc[0, 'orderid'] self._open_order.append((futu_order_id, order)) self._env.event_bus.publish_event( Event(EVENT.ORDER_CREATION_PASS, account=account, order=order)) sleep(0.1) self._check_open_orders(futu_order_id)
def test_booking(self): def mock_get_instrument(order_book_id): not_delisted_ins = MagicMock() not_delisted_ins.de_listed_date = datetime.datetime.max delisted_ins = MagicMock() delisted_ins.de_listed_date = datetime.datetime.min if order_book_id == "TF1812": return delisted_ins return not_delisted_ins self.assertPositions({(POSITION_DIRECTION.LONG, "RB1812", 3, 1), (POSITION_DIRECTION.SHORT, "TF1812", 4, 0)}) self.env.event_bus.publish_event( Event(EVENT.TRADE, trade=Trade.__from_create__(0, 0, 2, SIDE.SELL, POSITION_EFFECT.OPEN, "RB1812"))) self.assertPositions({(POSITION_DIRECTION.LONG, "RB1812", 3, 1), (POSITION_DIRECTION.SHORT, "RB1812", 2, 0), (POSITION_DIRECTION.SHORT, "TF1812", 4, 0)}) self.env.event_bus.publish_event( Event(EVENT.TRADE, trade=Trade.__from_create__(0, 0, 3, SIDE.SELL, POSITION_EFFECT.CLOSE, "RB1812"))) self.assertPositions({(POSITION_DIRECTION.LONG, "RB1812", 1, 0), (POSITION_DIRECTION.SHORT, "RB1812", 2, 0), (POSITION_DIRECTION.SHORT, "TF1812", 4, 0)}) with self.mock_env_method("get_instrument", mock_get_instrument): self.env.trading_dt = datetime.datetime(2018, 8, 31) self.env.event_bus.publish_event(Event(EVENT.POST_SETTLEMENT)) self.assertPositions({ (POSITION_DIRECTION.LONG, "RB1812", 0, 1), (POSITION_DIRECTION.SHORT, "RB1812", 0, 2), })
def submit_order(self, order): if order.position_effect == POSITION_EFFECT.MATCH: raise TypeError( _("unsupported position_effect {}").format( order.position_effect)) account = self._env.get_account(order.order_book_id) self._env.event_bus.publish_event( Event(EVENT.ORDER_PENDING_NEW, account=account, order=order)) if order.is_final(): return if order.position_effect == POSITION_EFFECT.EXERCISE: return self._open_exercise_orders.append((account, order)) if ExecutionContext.phase() == EXECUTION_PHASE.OPEN_AUCTION: self._open_auction_orders.append((account, order)) else: if self._env.config.base.frequency == '1d' and not self._match_immediately: self._delayed_orders.append((account, order)) return self._open_orders.append((account, order)) order.active() self._env.event_bus.publish_event( Event(EVENT.ORDER_CREATION_PASS, account=account, order=order)) if self._match_immediately: self._match()
def events(self, start_date, end_date, frequency): while True: now = datetime.now() if self.is_trading_day(now): if now.date( ) > self.before_trading_fire_date and 8 <= now.hour < 15: self.before_trading_fire_date = now.date() yield Event(EVENT.BEFORE_TRADING, calendar_dt=now, trading_dt=now) if self.is_trading_time(now): self._env.data_source.update_realtime_quotes( self._env.get_universe()) yield Event(EVENT.BAR, calendar_dt=now, trading_dt=now) elif self.after_trading_fire_date < now.date( ) == self.before_trading_fire_date and now.hour >= 15: self.after_trading_fire_date = now.date() yield Event(EVENT.AFTER_TRADING, calendar_dt=now, trading_dt=now) if now.date() >= end_date: return sec = datetime.now().second gevent.sleep(60 - sec if 5 < sec else 60)
def cancel_order(self, order): """ 撤单。 :param order: 订单 :type order: :class:`~Order` """ account = self._get_account(order.order_book_id) futu_order_id = self._get_futu_order_id(order) if futu_order_id is None: return # 立即检查一次订单状态 self._check_open_orders(futu_order_id) if order.is_final(): return self._env.event_bus.publish_event(Event(EVENT.ORDER_PENDING_CANCEL, account=account, order=order)) ret_code, ret_data = self._trade_context.set_order_status(0, futu_order_id, self._env) # 0 = 撤单 if ret_code != 0: self._env.event_bus.publish_event(Event(EVENT.ORDER_CANCELLATION_REJECT, account=account, order=order)) else: sleep(0.1) self._check_open_orders(futu_order_id) # 提交请求后,立即再检查一次状态
def cancel_order(self, order): if self._orders.get(order.order_id, None): url = '%s/cancel?entrust_no=%s' % (self._address, order.secondary_order_id) user_system_log.info('loading: %s' % url) try: with request.urlopen(url) as f: user_system_log.info('status: %d %s' % (f.status, f.reason)) if f.status == 200: data = f.read().decode('utf-8') resp = json.loads(data) code = resp.get('code', 1) if code == 0: account = self._env.get_account( order.order_book_id) self._env.event_bus.publish_event( Event(EVENT.ORDER_PENDING_CANCEL, account=account, order=order)) order.mark_cancelled( "%d order has been cancelled." % order.order_id) self._env.event_bus.publish_event( Event(EVENT.ORDER_CANCELLATION_PASS, account=account, order=order)) return else: user_system_log.warn( resp.get('msg', 'request failed')) except Exception as e: user_system_log.warn(repr(e)) return else: user_system_log.info('cancel order not fund: %s' % order.order_id)
def match(self, exercise_orders): # type: (Iterable[Order]) -> None for order in exercise_orders: account = self._env.portfolio.get_account(order.order_book_id) # type: AbstractAccount for trade in self._match(account, order): if trade.position_effect == POSITION_EFFECT.EXERCISE: order.fill(trade) self._env.event_bus.publish_event(Event(EVENT.TRADE, account=account, trade=trade, order=order)) if order.unfilled_quantity != 0: order.mark_cancelled(_( u"exercisable quantity {exercisable_quantity} of {order_book_id} is less than " u"order quantity {order_quantity}" ).format( exercisable_quantity=order.filled_quantity, order_book_id=order.order_book_id, order_quantity=order.quantity ))