def send_stop_order(self, dt, accnt, stock, direction, offset, price, volume, comments): self.context.stop_order_count += 1 stop_order = StopOrder(symbol=stock, exchange=get_exchange(stock), order_id=generate_random_id('stoporder'), direction=direction, offset=offset, price=price, order_volume=volume, account=accnt, order_datetime=dt, comments=comments) self.context.active_stop_orders[stop_order.order_id] = stop_order self.context.stop_orders[stop_order.order_id] = stop_order event_order = Event(EVENT_ORDER, dt, stop_order) self.event_engine.put(event_order)
def send_limit_order(self, dt, accnt, stock, direction, offset, price, volume, comments): self.context.limit_order_count += 1 order = OrderData(symbol=stock, exchange=get_exchange(stock), order_id=generate_random_id('order'), direction=direction, offset=offset, price=price, order_volume=volume, status=Status_SUBMITTING, account=accnt, gateway=self.gateway, order_datetime=dt, comments=comments) self.context.active_limit_orders[order.order_id] = order self.context.limit_orders[order.order_id] = order event_order = Event(EVENT_ORDER, dt, order) self.event_engine.put(event_order)
def cross_stop_order(self, event_market, cur_mkt_data): """处理未成交止损单""" print("-- this is deal_stop_order() @ {0}.".format(event_market.dt)) # 逐个未成交委托进行判断 for stop_order in list(self.context.active_stop_orders.values()): long_cross_price = cur_mkt_data['high'][stop_order.symbol] short_cross_price = cur_mkt_data['low'][stop_order.symbol] long_best_price = cur_mkt_data['open'][stop_order.symbol] short_best_price = cur_mkt_data['open'][stop_order.symbol] # 检查止损单是否能被触发 long_cross = (stop_order.direction == Direction_LONG and stop_order.price <= long_cross_price) short_cross = (stop_order.direction == Direction_SHORT and stop_order.price >= short_cross_price) # 如果委托单仍然不能被触发,则其所有状态都不改变,继续等待被触发 if not long_cross and not short_cross: continue # 否则新增一笔限价单(止损单在本地被触发后,最终以限价单形式发送到交易所) self.context.limit_order_count += 1 order = OrderData(symbol=stop_order.symbol, exchange=get_exchange(stop_order.symbol), order_id=generate_random_id('order'), direction=stop_order.direction, offset=stop_order.offset, price=stop_order.price, order_volume=stop_order.order_volume, filled_volume=stop_order.order_volume, status=Status_ALL_TRADED, account=stop_order.accnt, order_datetime=event_market.dt) self.context.limit_orders[order.order_id] = order # 更新stop_order对象的属性 # stop_order.order_ids.append(order.order_id) stop_order.filled_datetime = event_market.dt stop_order.status = StopOrderStatus_TRIGGERED # 未成交止损单清单中将本止损单去掉 if stop_order.order_id in self.context.active_stop_orders: self.context.active_stop_orders.pop(stop_order.order_id) # 止损单被触发,本地止损单转成限价单成交,新增order_event并送入队列中 event_order = Event(EVENT_ORDER, event_market.dt, order) self.event_engine.put(event_order) # 止损单被触发,新建一个成交对象 if long_cross: trade_price = max(stop_order.price, long_best_price) pos_change = order.order_volume else: trade_price = min(stop_order.price, short_best_price) pos_change = -order.order_volume self.context.trade_count += 1 trade = TradeData(symbol=order.symbol, exchange=order.exchange, order_id=order.order_id, trade_id=generate_random_id('filled'), direction=order.direction, offset=order.offset, price=trade_price, volume=order.order_volume, datetime=self.datetime, gateway=self.gateway) self.pos[trade.symbol] += pos_change # 新建成交事件,并推送到事件队列中 event_trade = Event(EVENT_TRADE, event_market.dt, trade) self.event_engine.put(event_trade) self.handle_trade(event_trade) self.context.trade_data_dict[trade.trade_id] = trade
def handle_trade(self, event_trade): """订单成交后,在 context 中更新相关持仓数据""" print('handle_trade() method @ {0}'.format( event_trade.data.order_datetime)) # 更新 context 中的交易信息 self.context.current_trade_data.trade_id = generate_random_id('traded') self.context.current_trade_data.order_id = self.context.current_order_data.order_id self.context.current_trade_data.symbol = self.context.current_order_data.symbol self.context.current_trade_data.exchange = self.context.current_order_data.exchange self.context.current_trade_data.account_id = self.context.current_order_data.account_id self.context.current_trade_data.price = self.context.current_order_data.price self.context.current_trade_data.direction = self.context.current_order_data.direction self.context.current_trade_data.offset = self.context.current_order_data.offset self.context.current_trade_data.volume = self.context.current_order_data.total_volume self.context.current_trade_data.datetime = self.context.current_order_data.order_time self.context.current_trade_data.frozen += self.context.current_order_data.filled_volume # 计算滑点 if self.context.current_trade_data.exchange == "SH" or self.context.current_trade_data.exchange == "SZ": if self.context.slippage_dict[Product_STOCK][ "slippage_type"] == SLIPPAGE_FIX: if self.context.current_trade_data.offset == Offset_OPEN: self.context.current_trade_data.price += \ self.context.slippage_dict[Product_STOCK]["value"] elif self.context.current_trade_data.offset == Offset_CLOSE: self.context.current_trade_data.trade_price -= \ self.context.slippage_dict[Product_STOCK]["value"] elif self.context.slippage_dict[Product_STOCK][ "slippage_type"] == SLIPPAGE_PERCENT: if self.context.current_trade_data.offset == Offset_OPEN: self.context.current_trade_data.price *= ( 1 + self.context.slippage_dict[Product_STOCK]["value"]) elif self.context.current_trade_data.offset == Offset_CLOSE: self.context.current_trade_data.trade_price *= ( 1 - self.context.slippage_dict[Product_STOCK]["value"]) # 计算手续费 commission = {} trade_balance = self.context.current_trade_data.price * self.context.current_trade_data.trade_volume # 分市场标的计算手续费率 if self.context.current_trade_data.exchange == "SH": commission = self.context.commission_dict[Product_STOCK_SH] elif self.context.current_trade_data.exchange == "SZ": commission = self.context.commission_dict[Product_STOCK_SZ] # 根据经过交易手续费后的成交额,更新成交价格 if self.context.current_trade_data.offset == Offset_OPEN: total_commission = commission['open_commission'] trade_balance *= 1 + total_commission self.context.current_trade_data.price = trade_balance / self.context.current_trade_data.trade_volume elif self.context.current_trade_data.offset == Offset_CLOSE: total_commission = commission['close_commission'] + commission[ 'tax'] trade_balance *= 1 - total_commission self.context.current_trade_data.price = trade_balance / self.context.current_trade_data.trade_volume # 更新 context 中的持仓信息 self.context.current_position_data.trade_id = self.context.current_trade_data.trade_id self.context.current_position_data.order_id = self.context.current_trade_data.order_id self.context.current_position_data.symbol = self.context.current_trade_data.symbol self.context.current_position_data.exchange = self.context.current_trade_data.exchange self.context.current_position_data.account_id = self.context.current_order_data.account_id self.context.current_position_data.price = self.context.current_trade_data.price self.context.current_position_data.direction = self.context.current_trade_data.direction self.context.current_position_data.offset = self.context.current_trade_data.offset self.context.current_position_data.volume = self.context.current_trade_data.total_volume self.context.current_position_data.datetime = self.context.current_trade_data.order_time self.context.current_position_data.frozen += self.context.current_trade_data.filled_volume if self.context.bar_position_data_list: position_num = 0 position_hold = False for position_data in self.context.bar_position_data_list: position_num += 1 if self.context.current_position_data.symbol == position_data.symbol: position_hold = True # print(self.context.current_trade_data.offset, "方向"*10) if self.context.current_trade_data.offset == Offset_OPEN: total_position = position_data.position + self.context.current_trade_data.trade_volume position_cost_balance = position_data.position * position_data.init_price trade_balance = \ self.context.current_trade_data.trade_volume * self.context.current_trade_data.price # 更新持仓成本 position_data.init_price = \ (position_cost_balance + trade_balance) / total_position # 更新持仓数量 position_data.position = total_position # 更新冻结数量 position_data.frozen += self.context.current_trade_data.trade_volume # print("update_position_list") elif self.context.current_trade_data.offset == Offset_CLOSE: total_position = \ position_data.position - self.context.current_trade_data.trade_volume position_cost_balance = position_data.position * position_data.init_price trade_balance = \ self.context.current_trade_data.trade_volume * self.context.current_trade_data.price if total_position > 0: position_data.init_price = \ (position_cost_balance - trade_balance) / total_position else: position_data.init_price = 0 position_data.position = total_position # print("sell position"*5, position_data.position) # 持仓不为空,且不在持仓里面的,append到self.context.bar_position_data_list if position_num == len(self.context.bar_position_data_list ) and position_hold is False: self.context.current_position_data.init_price = self.context.current_trade_data.trade_price self.context.current_position_data.position = self.context.current_trade_data.trade_volume self.context.bar_position_data_list.append( self.context.current_position_data) else: self.context.current_position_data.init_price = self.context.current_trade_data.trade_price self.context.current_position_data.position = self.context.current_trade_data.trade_volume # 持仓为空,append到self.context.bar_position_data_list self.context.bar_position_data_list.append( self.context.current_position_data) # 更新委托的状态和成交数量,并把此次委托append到self.context.bar_order_data_list self.context.current_order_data.status = Status_ALL_TRADED self.context.current_order_data.trade_volume = self.context.current_trade_data.trade_volume self.context.bar_order_data_list.append( self.context.current_order_data) # 把此次成交append到self.context.bar_trade_data_list self.context.bar_trade_data_list.append( self.context.current_trade_data) # 更新现金 if self.context.bar_account_data_list: for account in self.context.bar_account_data_list: if account.account_id == self.context.current_order_data.account_id: if self.context.current_trade_data.offset == Offset_OPEN: # 更新可用资金 account.available -= \ self.context.current_trade_data.price * self.context.current_trade_data.trade_volume elif self.context.current_trade_data.offset == Offset_CLOSE: account.available += \ self.context.current_trade_data.price * self.context.current_trade_data.trade_volume self.context.refresh_current_data() # 订单状态及时更新 print('--- * update trade info *')
def cross_limit_order(self, event_market, cur_mkt_data): """处理未成交限价单""" print("-- this is deal_limit_order() @ {0}".format(event_market.dt)) # 逐个未成交委托进行判断 for order in list(self.context.active_limit_orders.values()): long_cross_price = cur_mkt_data['low'][order.symbol] short_cross_price = cur_mkt_data['high'][order.symbol] long_best_price = cur_mkt_data['open'][order.symbol] short_best_price = cur_mkt_data['open'][order.symbol] # 委托状态从“待提交”转成“未成交“ if order.status == Status_SUBMITTING: order.status = Status_NOT_TRADED event_order = Event(EVENT_ORDER, event_market.dt, order) self.event_engine.put(event_order) # 检查限价单是否能被成交 long_cross = (order.direction == Direction_LONG and order.price >= long_cross_price > 0) short_cross = (order.direction == Direction_SHORT and order.price <= short_cross_price and short_cross_price > 0) # 如果委托单仍然不能被成交,则其所有状态都不改变,继续等待被成交 if not long_cross and not short_cross: continue # 委托单被成交了,状态改变成 filled order.filled_volume = order.order_volume order.status = Status_ALL_TRADED event_order = Event(EVENT_ORDER, event_market.dt, order) self.event_engine.put(event_order) self.context.active_limit_orders.pop(order.order_id) # 交易数量 + 1 self.context.trade_count += 1 if long_cross: trade_price = min(order.price, long_best_price) pos_change = order.order_volume else: trade_price = max(order.price, short_best_price) pos_change = -order.order_volume # 新建交易事件并送入事件驱动队列中 trade = TradeData(symbol=order.symbol, exchange=order.exchange, order_id=order.order_id, trade_id=generate_random_id('filled'), direction=order.direction, offset=order.offset, price=trade_price, volume=order.order_volume, datetime=event_market.dt, gateway=self.gateway) self.pos[trade.symbol] += pos_change event_trade = Event(EVENT_TRADE, event_market.dt, trade) self.event_engine.put(event_trade) self.handle_trade(event_trade) # 交易事件更新 self.context.trade_data_dict[trade.trade_id] = trade