Example #1
0
    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)
Example #2
0
    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)
Example #3
0
    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
Example #4
0
    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 *')
Example #5
0
    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