Ejemplo n.º 1
0
 def _valid_order(self, order):
     """ 判断订单是否合法。 """
     if order.quantity <= 0:
         raise TradingError(err="交易数量不能小于0")
     # 撤单
     if order.side == TradeSide.CANCEL:
         if order not in self.open_orders:
             raise TradingError(err='撤销失败: 不存在该订单!')
     if order.side == TradeSide.PING:
         try:
             poskey = PositionKey(order.contract, order.direction)
             pos = self.positions[poskey]
             if pos.closable < order.quantity:
                 raise TradingError(err='可平仓位不足')
         except KeyError:
             # 没有持有该合约
             #logger.warn("不存在合约[%s]" % order.contract)
             raise TradingError(err="不存在合约[%s]" % order.contract)
     elif order.side == TradeSide.KAI:
         new_price = self._ticks[order.contract]
         if self.holding['cash'] < order.order_margin(new_price):
             raise TradingError(err='没有足够的资金开仓')
         else:
             self.holding['cash'] -= order.order_margin(new_price)
     return True
Ejemplo n.º 2
0
 def _valid_order(self, order):
     if order.quantity <= 0:
         logger.warn("下单数量错误!")
         return False
     """ 判断订单是否合法。 """
     if order.side == TradeSide.PING:
         try:
             poskey = PositionKey(order.contract, order.direction)
             pos = self.positions[poskey]
             if pos.quantity >= order.quantity:
                 return True
         except KeyError:
             # 没有持有该合约
             logger.warn("不存在合约[%s]" % order.contract)
             #assert False
             return False
         logger.warn("下单仓位问题")
         return False
     elif order.side == TradeSide.KAI:
         if self.holding['cash'] < order.price * order.quantity:
             raise TradingError(err='没有足够的资金开仓')
         else:
             new_price = self._ticks[order.contract]
             self.holding['cash'] -= order.order_margin(new_price)
     return True
Ejemplo n.º 3
0
    def update_signal(self, event):
        """ 处理策略函数产生的下单事件。

        可能产生一系列order事件,在bar的开盘时间交易。
        """
        assert event.type == Event.SIGNAL
        new_orders = []
        for order in event.orders:
            errmsg = self._valid_order(order)
            if errmsg == '':
                order.datetime = self._datetime
                new_orders.append(order)
                if order.side == TradeSide.KAI:
                    self.holding['cash'] -= \
                        order.order_margin(self._bars[order.contract].open)
            else:
                logger.warn(errmsg)
                # print len(event.orders), len(new_orders)
                continue
        self.open_orders.update(new_orders)  # 改变对象的值,不改变对象地址。
        self._all_orders.extend(new_orders)
        for order in new_orders:
            self.api.order(copy.deepcopy(order))
        for order in new_orders:
            if order.side == TradeSide.PING:
                pos = self.positions[
                    PositionKey(order.contract, order.direction)]
                pos.closable -= order.quantity
Ejemplo n.º 4
0
def _update_positions(current_positions, deal_positions, trans):
    """ 更新持仓 
        current_positions: 当前持仓
        deal_positions: 开平仓对
    """
    class PositionsDetail(object):
        """ 当前相同合约持仓集合(可能不同时间段下单)。

        :ivar cost: 持仓成本。
        :ivar total: 持仓总数。
        :ivar positions: 持仓集合。
        :vartype positions: list
        """
        def __init__(self):
            self.total = 0
            self.positions = []
            self.cost = 0

    assert trans.quantity > 0
    poskey = PositionKey(trans.contract, trans.direction)
    p = current_positions.setdefault(poskey, PositionsDetail())
    if trans.side == TradeSide.KAI:
        # 开仓
        p.positions.append(trans)
        p.total += trans.quantity

    elif trans.side == TradeSide.PING:
        # 平仓
        assert (len(p.positions) > 0 and '所平合约没有持仓')
        left_vol = trans.quantity
        last_index = 0
        p.total -= trans.quantity
        for position in reversed(p.positions):
            if position.quantity < left_vol:
                # 还需从之前的仓位中平。
                left_vol -= position.quantity
                last_index -= 1
                deal_positions.append(
                    OneDeal(position, trans, position.quantity))

            elif position.quantity == left_vol:
                left_vol -= position.quantity
                last_index -= 1
                deal_positions.append(
                    OneDeal(position, trans, position.quantity))
                break

            else:
                position.quantity -= left_vol
                left_vol = 0
                deal_positions.append(OneDeal(position, trans, left_vol))
                break
        if last_index != 0:
            p.positions = p.positions[0:last_index]
        assert (left_vol == 0)  # 会被catch捕获 AssertError
Ejemplo n.º 5
0
 def _update_holding(self, trans):
     """ 更新佣金和平仓盈亏。 """
     if trans.side == TradeSide.CANCEL:
         return
     self.holding['commission'] += trans.commission
     # 平仓,更新历史持仓盈亏。
     if trans.side == TradeSide.PING:
         poskey = PositionKey(trans.contract, trans.direction)
         flag = 1 if trans.direction == Direction.LONG else -1
         profit = (trans.price-self.positions[poskey].cost) * \
             trans.quantity * flag * trans.volume_multiple
         self.holding['history_profit'] += profit
     self._all_transactions.append(trans)
Ejemplo n.º 6
0
 def _update_holding(self, trans):
     """
     更新佣金和平仓盈亏。
     """
     # 每笔佣金,和数目无关!
     self.holding['commission'] += trans.commission
     # 平仓,更新历史持仓盈亏。
     if trans.side == TradeSide.PING:
         poskey = PositionKey(trans.contract, trans.direction)
         multi = 1 if trans.direction == Direction.LONG else -1
         profit = (trans.price -
                   self.positions[poskey].cost) * trans.quantity * multi
         self.holding['history_profit'] += profit
     self._all_transactions.append(trans)
Ejemplo n.º 7
0
 def _update_positions(self, trans):
     """ 更新持仓 """
     poskey = PositionKey(trans.contract, trans.direction)
     pos = self.positions.setdefault(poskey, Position(trans))
     #print len(self.positions)
     #print pos.contract, pos.quantity
     if trans.side == TradeSide.KAI:
         # 开仓
         pos.cost = (pos.cost * pos.quantity + trans.price *
                     trans.quantity) / (pos.quantity + trans.quantity)
         pos.quantity += trans.quantity
     elif trans.side == TradeSide.PING:
         # 平仓
         pos.quantity -= trans.quantity
         if pos.quantity == 0:
             del self.positions[poskey]
Ejemplo n.º 8
0
 def update_datetime(self, dt):
     """ 在新的价格数据来的时候触发。 """
     if self._datetime == None:
         self._datetime = dt
         self._start_date = dt
         self._init_state()
     elif self._datetime.date() != dt.date():
         for order in self.open_orders:
             if order.side == TradeSide.PING:
                 pos = self.positions[PositionKey(order.contract, order.direction)]
                 pos.closable += order.quantity
         self.open_orders.clear()
         for key, pos in self.positions.iteritems():
             pos.closable += pos.today
             pos.today = 0
     self._datetime = dt
Ejemplo n.º 9
0
 def update_signal(self, event):
     """ 处理策略函数产生的下单事件。 """
     assert event.type == Event.SIGNAL
     new_orders = []
     for order in event.orders:
         if self._valid_order(order):
             order.datetime = self._datetime
             self.api.order(copy.deepcopy(order))
             new_orders.append(order)
         else:
             continue
     self.open_orders.update(new_orders)  # 改变对象的值,不改变对象地址。
     self._all_orders.extend(new_orders)
     for order in new_orders:
         if order.side == TradeSide.PING:
             pos = self.positions[PositionKey(order.contract,
                                              order.direction)]
             pos.closable -= order.quantity
Ejemplo n.º 10
0
 def _update_positions(self, trans):
     """ 更新持仓 """
     poskey = PositionKey(trans.contract, trans.direction)
     if trans.side == TradeSide.CANCEL:
         pos = self.positions.get(poskey, None)
         if pos:
             pos.closable += trans.quantity
         return
     pos = self.positions.setdefault(poskey, Position(trans))
     if trans.side == TradeSide.KAI:
         pos.cost = (pos.cost*pos.quantity + trans.price*trans.quantity) / \
                     (pos.quantity+trans.quantity)
         pos.quantity += trans.quantity
         if trans.contract.is_stock:
             pos.today += trans.quantity
         else:
             pos.closable += trans.quantity
         assert(pos.quantity == pos.today + pos.closable)
     elif trans.side == TradeSide.PING:
         pos.quantity -= trans.quantity
         if pos.quantity == 0:
             del self.positions[poskey]
Ejemplo n.º 11
0
    def position(self, direction='long', symbol=None):
        """ 合约当前持仓仓位。

        Args:
            direction (str/int): 持仓方向。多头 - 'long' / 1 ;空头 - 'short'  / 2
            , 默认为多头。

            symbol (str): 字符串合约,默认为None表示主合约。

        Returns:
            Position. 该合约的持仓
        """
        if not self.on_bar:
            raise Exception('只有on_bar函数内能查询当前持仓!')
        direction = Direction.arg_to_type(direction)
        contract = Contract(symbol) if symbol else \
            self.contract
        # @TODO assert direction
        try:
            poskey = PositionKey(contract, direction)
            return self.blotter.positions[poskey]
        except KeyError:
            return None
Ejemplo n.º 12
0
 def _valid_order(self, order):
     """ 判断订单是否合法。 """
     if order.quantity <= 0:
         return "交易数量要大于0"
     # 撤单
     if order.side == TradeSide.CANCEL:
         if order not in self.open_orders:
             return '撤销失败: 不存在该订单!'
     if order.side == TradeSide.PING:
         try:
             poskey = PositionKey(order.contract, order.direction)
             pos = self.positions[poskey]
             if pos.closable < order.quantity:
                 return '可平仓位不足'
         except KeyError:
             # 没有持有该合约
             # logger.warn("不存在合约[%s]" % order.contract)
             return "不存在合约[%s]" % order.contract
     elif order.side == TradeSide.KAI:
         new_price = self._bars[order.contract].open
         if self.holding['cash'] < order.order_margin(new_price):
             # print self.holding['cash'], new_price * order.quantity
             return '没有足够的资金开仓'
     return ''
Ejemplo n.º 13
0
 def pos(self, contract, direction):
     try:
         poskey = PositionKey(contract, direction)
         return self.blotter.positions[poskey].closable
     except KeyError:
         return 0
Ejemplo n.º 14
0
    def _update_positions(self, current_positions, deal_positions, trans):
        """ 根据交易明细计算开平仓对。 """
        class PositionsDetail(object):
            """ 当前相同合约持仓集合(可能不同时间段下单)。

            :ivar cost: 持仓成本。
            :ivar total: 持仓总数。
            :ivar positions: 持仓集合。
            :vartype positions: list
            """
            def __init__(self):
                self.total = 0
                self.positions = []
                self.cost = 0
        assert trans.quantity > 0
        poskey = PositionKey(trans.contract, trans.direction)
        p = current_positions.setdefault(poskey, PositionsDetail())
        if trans.side == TradeSide.KAI:
            # 开仓
            p.positions.append(trans)
            p.total += trans.quantity

        elif trans.side == TradeSide.PING:
            # 平仓
            assert(len(p.positions) > 0 and '所平合约没有持仓')
            left_vol = trans.quantity
            last_index = 0
            search_index = 0
            p.total -= trans.quantity
            if trans.contract.is_stock:
                for position in reversed(p.positions):
                    # 开仓日期小于平仓时间
                    if position.datetime.date() < trans.datetime.date():
                        break
                    search_index -= 1
            if search_index != 0:
                positions = p.positions[:search_index]
                left_positions = p.positions[search_index:]
            else:
                positions = p.positions
            for position in reversed(positions):
                if position.quantity < left_vol:
                    # 还需从之前的仓位中平。
                    left_vol -= position.quantity
                    last_index -= 1
                    deal_positions.append(
                        OneDeal(position, trans, position.quantity))
                elif position.quantity == left_vol:
                    left_vol -= position.quantity
                    last_index -= 1
                    deal_positions.append(
                        OneDeal(position, trans, position.quantity))
                    break
                else:
                    position.quantity -= left_vol
                    left_vol = 0
                    deal_positions.append(OneDeal(position, trans, left_vol))
                    break
            if last_index != 0 and search_index != 0:
                p.positions = positions[0:last_index] + left_positions
            elif last_index != 0:
                p.positions = positions[0:last_index]
            # last_index == 0, 表示没找到可平的的开仓对,最后一根强平
            # 可以被catch捕获 AssertError
            assert(left_vol == 0 or last_index == 0)
Ejemplo n.º 15
0
 def position(self, contract, direction):
     try:
         poskey = PositionKey(contract, direction)
         return self.blotter.positions[poskey].quantity
     except KeyError:
         return 0