예제 #1
0
    def order(self,
              entity_id,
              current_price,
              current_timestamp,
              order_amount=0,
              order_pct=1.0,
              order_price=0,
              order_type=ORDER_TYPE_LONG,
              order_money=0):
        """
        下单

        Parameters
        ----------
        entity_id : str
            交易标的id

        current_price : float
            当前价格

        current_timestamp: timestamp
            下单的时间

        order_amount : int
            数量

        order_pct : float
            使用可用现金(仓位)的百分比,0.0-1.0

        order_price : float
            用于限价交易

        order_type : {ORDER_TYPE_LONG,ORDER_TYPE_SHORT,ORDER_TYPE_CLOSE_LONG,ORDER_TYPE_CLOSE_SHORT}
            交易类型

        Returns

        """

        # 市价交易,就是买卖是"当时"并"一定"能成交的
        # 简单起见,目前只支持这种方式
        if order_price == 0:
            current_position = self.get_current_position(entity_id=entity_id)

            if not current_position:
                trading_t = get_trading_meta(entity_id=entity_id)['trading_t']
                current_position = {
                    'trader_name': self.trader_name,
                    'entity_id': entity_id,
                    'long_amount': 0,
                    'available_long': 0,
                    'average_long_price': 0,
                    'short_amount': 0,
                    'available_short': 0,
                    'average_short_price': 0,
                    'profit': 0,
                    'value': 0,
                    'trading_t': trading_t
                }
                # add it to latest account
                self.latest_account['positions'].append(current_position)

            # 按钱交易
            if order_money > 0:
                # 开多
                if order_type == ORDER_TYPE_LONG:
                    if current_position['short_amount'] > 0:
                        raise InvalidOrderError(
                            "close the short position before open long")

                    if order_money > self.latest_account['cash']:
                        raise NotEnoughMoneyError()

                    cost = current_price * (1 + self.slippage + self.buy_cost)
                    # 买的数量
                    order_amount = order_money // cost

                    if order_amount > 0:
                        self.update_position(current_position, order_amount,
                                             current_price, order_type,
                                             current_timestamp)
                    else:
                        raise NotEnoughMoneyError()
                # 开空
                elif order_type == ORDER_TYPE_SHORT:
                    if current_position['long_amount'] > 0:
                        raise InvalidOrderError(
                            "close the long position before open short")

                    if order_money > self.latest_account['cash']:
                        raise NotEnoughMoneyError()

                    cost = current_price * (1 + self.slippage + self.buy_cost)

                    order_amount = order_money // cost
                    if order_amount > 0:
                        self.update_position(current_position, order_amount,
                                             current_price, order_type,
                                             current_timestamp)
                    else:
                        raise NotEnoughMoneyError()
                else:
                    raise InvalidOrderParamError(
                        'close long/short not support order_money')

            # 按数量交易
            elif order_amount > 0:
                # 开多
                if order_type == ORDER_TYPE_LONG:
                    if current_position['short_amount'] > 0:
                        raise InvalidOrderError(
                            "close the short position before open long")

                    self.update_position(current_position, order_amount,
                                         current_price, order_type,
                                         current_timestamp)
                # 开空
                elif order_type == ORDER_TYPE_SHORT:
                    if current_position['long_amount'] > 0:
                        raise InvalidOrderError(
                            "close the long position before open short")

                    self.update_position(current_position, order_amount,
                                         current_price, order_type,
                                         current_timestamp)
                # 平多
                elif order_type == ORDER_TYPE_CLOSE_LONG:
                    if current_position['available_long'] >= order_amount:
                        self.update_position(current_position, order_amount,
                                             current_price, order_type,
                                             current_timestamp)
                    else:
                        raise NotEnoughPositionError()
                # 平空
                elif order_type == ORDER_TYPE_CLOSE_SHORT:
                    if current_position['available_short'] >= order_amount:
                        self.update_position(current_position, order_amount,
                                             current_price, order_type,
                                             current_timestamp)
                    else:
                        raise Exception("not enough position")

            # 按仓位比例交易
            elif 0 < order_pct <= 1:
                # 开多
                if order_type == ORDER_TYPE_LONG:
                    if current_position['short_amount'] > 0:
                        raise InvalidOrderError(
                            "close the short position before open long")

                    cost = current_price * (1 + self.slippage + self.buy_cost)
                    want_pay = self.latest_account['cash'] * order_pct
                    # 买的数量
                    order_amount = want_pay // cost
                    if order_amount > 0:
                        self.update_position(current_position, order_amount,
                                             current_price, order_type,
                                             current_timestamp)
                    else:
                        raise NotEnoughMoneyError()
                # 开空
                elif order_type == ORDER_TYPE_SHORT:
                    if current_position['long_amount'] > 0:
                        raise InvalidOrderError(
                            "close the long position before open short")

                    cost = current_price * (1 + self.slippage + self.buy_cost)
                    want_pay = self.latest_account['cash'] * order_pct

                    order_amount = want_pay // cost
                    if order_amount > 0:
                        self.update_position(current_position, order_amount,
                                             current_price, order_type,
                                             current_timestamp)
                    else:
                        raise NotEnoughMoneyError()

                # 平多
                elif order_type == ORDER_TYPE_CLOSE_LONG:
                    if current_position['available_long'] > 0:
                        if order_pct == 1.0:
                            order_amount = current_position['available_long']
                        else:
                            order_amount = math.floor(
                                current_position['available_long'] * order_pct)

                        if order_amount != 0:
                            self.update_position(current_position,
                                                 order_amount, current_price,
                                                 order_type, current_timestamp)
                        else:
                            self.logger.warning(
                                "{} available_long:{} order_pct:{} order_amount:{}",
                                entity_id, current_position['available_long'],
                                order_pct, order_amount)
                    else:
                        raise NotEnoughPositionError()
                # 平空
                elif order_type == ORDER_TYPE_CLOSE_SHORT:
                    if current_position['available_short'] > 0:
                        if order_pct == 1.0:
                            order_amount = current_position['available_short']
                        else:
                            order_amount = math.floor(
                                current_position['available_short'] *
                                order_pct)

                        if order_amount != 0:
                            self.update_position(current_position,
                                                 order_amount, current_price,
                                                 order_type, current_timestamp)
                        else:
                            self.logger.warning(
                                "{} available_long:{} order_pct:{} order_amount:{}",
                                entity_id, current_position['available_long'],
                                order_pct, order_amount)
                    else:
                        raise Exception("not enough position")
예제 #2
0
    def order(self,
              entity_id,
              current_price,
              current_timestamp,
              order_amount=0,
              order_pct=1.0,
              order_price=0,
              order_type=ORDER_TYPE_LONG,
              order_money=0):
        """
        下单

        Parameters
        ----------
        entity_id : str
            交易标的id

        current_price : float
            当前价格

        current_timestamp: timestamp
            下单的时间

        order_amount : int
            数量

        order_pct : float
            使用可用现金(仓位)的百分比,0.0-1.0

        order_price : float
            用于限价交易

        order_type : {ORDER_TYPE_LONG,ORDER_TYPE_SHORT,ORDER_TYPE_CLOSE_LONG,ORDER_TYPE_CLOSE_SHORT}
            交易类型

        Returns

        """

        # 市价交易,就是买卖是"当时"并"一定"能成交的
        # 简单起见,目前只支持这种方式
        if order_price == 0:
            current_position = self.get_current_position(entity_id=entity_id)

            if not current_position:
                trading_t = self.entity_schema.get_trading_t()
                current_position = Position(trader_name=self.trader_name,
                                            entity_id=entity_id,
                                            long_amount=0,
                                            available_long=0,
                                            average_long_price=0,
                                            short_amount=0,
                                            available_short=0,
                                            average_short_price=0,
                                            profit=0,
                                            value=0,
                                            trading_t=trading_t)
                # add it to latest account
                self.account.positions.append(current_position)

            # 按钱交易
            if order_money > 0:
                # 开多
                if order_type == ORDER_TYPE_LONG:
                    if current_position.short_amount > 0:
                        raise InvalidOrderError(
                            "close the short position before open long")

                    if order_money > self.account.cash:
                        if self.rich_mode:
                            self.input_money()
                        else:
                            raise NotEnoughMoneyError()

                    cost = current_price * (1 + self.slippage + self.buy_cost)
                    # 买的数量
                    order_amount = order_money // cost

                    if order_amount < 1:
                        self.logger.error(
                            f'invalid order_money:{order_money}, cost:{cost}, order_amount:{order_amount}'
                        )
                        return

                    self.update_position(current_position, order_amount,
                                         current_price, order_type,
                                         current_timestamp)
                # 开空
                elif order_type == ORDER_TYPE_SHORT:
                    if current_position.long_amount > 0:
                        raise InvalidOrderError(
                            "close the long position before open short")

                    if order_money > self.account.cash:
                        if self.rich_mode:
                            self.input_money()
                        else:
                            raise NotEnoughMoneyError()

                    cost = current_price * (1 + self.slippage + self.buy_cost)

                    order_amount = order_money // cost

                    if order_amount < 1:
                        self.logger.error(
                            f'invalid order_money:{order_money}, cost:{cost}, order_amount:{order_amount}'
                        )
                        return
                    self.update_position(current_position, order_amount,
                                         current_price, order_type,
                                         current_timestamp)
                else:
                    raise InvalidOrderParamError(
                        'close long/short not support order_money')

            # 按数量交易
            elif order_amount > 0:
                # 开多
                if order_type == ORDER_TYPE_LONG:
                    if current_position.short_amount > 0:
                        raise InvalidOrderError(
                            "close the short position before open long")

                    self.update_position(current_position, order_amount,
                                         current_price, order_type,
                                         current_timestamp)
                # 开空
                elif order_type == ORDER_TYPE_SHORT:
                    if current_position.long_amount > 0:
                        raise InvalidOrderError(
                            "close the long position before open short")

                    self.update_position(current_position, order_amount,
                                         current_price, order_type,
                                         current_timestamp)
                # 平多
                elif order_type == ORDER_TYPE_CLOSE_LONG:
                    if current_position.available_long >= order_amount:
                        self.update_position(current_position, order_amount,
                                             current_price, order_type,
                                             current_timestamp)
                    else:
                        raise NotEnoughPositionError()
                # 平空
                elif order_type == ORDER_TYPE_CLOSE_SHORT:
                    if current_position.available_short >= order_amount:
                        self.update_position(current_position, order_amount,
                                             current_price, order_type,
                                             current_timestamp)
                    else:
                        raise Exception("not enough position")

            # 按仓位比例交易
            elif 0 < order_pct <= 1:
                # 开多
                if order_type == ORDER_TYPE_LONG:
                    if current_position.short_amount > 0:
                        raise InvalidOrderError(
                            "close the short position before open long")

                    cost = current_price * (1 + self.slippage + self.buy_cost)
                    want_pay = self.account.cash * order_pct
                    # 买的数量
                    order_amount = want_pay // cost

                    if order_amount < 1:
                        if self.rich_mode:
                            self.input_money()
                            order_amount = max(
                                (self.account.cash * order_pct) // cost, 1)
                        else:
                            raise NotEnoughMoneyError()
                    self.update_position(current_position, order_amount,
                                         current_price, order_type,
                                         current_timestamp)
                # 开空
                elif order_type == ORDER_TYPE_SHORT:
                    if current_position.long_amount > 0:
                        raise InvalidOrderError(
                            "close the long position before open short")

                    cost = current_price * (1 + self.slippage + self.buy_cost)
                    want_pay = self.account.cash * order_pct

                    order_amount = want_pay // cost

                    if order_amount < 1:
                        if self.rich_mode:
                            self.input_money()
                            order_amount = max(
                                (self.account.cash * order_pct) // cost, 1)
                        else:
                            raise NotEnoughMoneyError()

                    self.update_position(current_position, order_amount,
                                         current_price, order_type,
                                         current_timestamp)

                # 平多
                elif order_type == ORDER_TYPE_CLOSE_LONG:
                    if current_position.available_long > 0:
                        if order_pct == 1.0:
                            order_amount = current_position.available_long
                        else:
                            order_amount = math.floor(
                                current_position.available_long * order_pct)

                        if order_amount != 0:
                            self.update_position(current_position,
                                                 order_amount, current_price,
                                                 order_type, current_timestamp)
                        else:
                            self.logger.warning(
                                f'{entity_id} available_long:{current_position.available_long} order_pct:{order_pct} order_amount:{order_amount}'
                            )
                    else:
                        raise NotEnoughPositionError()
                # 平空
                elif order_type == ORDER_TYPE_CLOSE_SHORT:
                    if current_position.available_short > 0:
                        if order_pct == 1.0:
                            order_amount = current_position.available_short
                        else:
                            order_amount = math.floor(
                                current_position.available_short * order_pct)

                        if order_amount != 0:
                            self.update_position(current_position,
                                                 order_amount, current_price,
                                                 order_type, current_timestamp)
                        else:
                            self.logger.warning(
                                f'{entity_id} available_long:{current_position.available_long} order_pct:{order_pct} order_amount:{order_amount}'
                            )
                    else:
                        raise Exception("not enough position")
예제 #3
0
파일: account.py 프로젝트: pikachule/zvt
    def order(self, security_id, current_price, current_timestamp, order_amount=0, order_pct=1.0, order_price=0,
              order_type=ORDER_TYPE_LONG):
        """
        下单

        Parameters
        ----------
        security_id : str
            交易标的id

        current_price : float
            当前价格

        current_timestamp: timestamp
            下单的时间

        order_amount : int
            数量

        order_pct : float
            使用可用现金(仓位)的百分比,0.0-1.0

        order_price : float
            用于限价交易

        order_type : {ORDER_TYPE_LONG,ORDER_TYPE_SHORT,ORDER_TYPE_CLOSE_LONG,ORDER_TYPE_CLOSE_SHORT}
            交易类型

        Returns
        -------


        """

        # 市价交易,就是买卖是"当时"并"一定"能成交的
        # 简单起见,目前只支持这种方式
        if order_price == 0:
            current_position: Position = self.get_current_position(security_id=security_id)
            the_id = '{}_{}_{}'.format(self.trader_name, security_id,
                                       to_time_str(current_timestamp, TIME_FORMAT_ISO8601))

            if not current_position:
                current_position = Position(id=the_id, trader_name=self.trader_name, timestamp=current_timestamp,
                                            security_id=security_id, long_amount=0, available_long=0,
                                            average_long_price=0, short_amount=0,
                                            available_short=0, average_short_price=0, profit=0, value=0)
            else:
                current_position = Position(id=the_id, trader_name=self.trader_name, timestamp=current_timestamp,
                                            security_id=security_id, long_amount=current_position.long_amount,
                                            available_long=current_position.available_long,
                                            average_long_price=current_position.average_long_price,
                                            short_amount=current_position.short_amount,
                                            available_short=current_position.available_short,
                                            average_short_price=current_position.average_short_price,
                                            profit=current_position.profit, value=current_position.value)

            # 按数量交易
            if order_amount > 0:
                # 开多
                if order_type == ORDER_TYPE_LONG:
                    if current_position.short_amount > 0:
                        raise InvalidOrderError("close the short position before open long")

                    self.update_position(current_position, order_amount, current_price, order_type)
                # 开空
                elif order_type == ORDER_TYPE_SHORT:
                    if current_position.long_amount > 0:
                        raise InvalidOrderError("close the long position before open short")

                    self.update_position(current_position, order_amount, current_price, order_type)
                # 平多
                elif order_type == ORDER_TYPE_CLOSE_LONG:
                    if current_position.available_long >= order_amount:
                        self.update_position(current_position, order_amount, current_price, order_type)
                    else:
                        raise NotEnoughPositionError()
                # 平空
                elif order_type == ORDER_TYPE_CLOSE_SHORT:
                    if current_position.available_short >= order_amount:
                        self.update_position(current_position, order_amount, current_price, order_type)
                    else:
                        raise Exception("not enough position")

            # 按仓位比例交易
            elif 0 < order_pct <= 1:
                # 开多
                if order_type == ORDER_TYPE_LONG:
                    if current_position.short_amount > 0:
                        raise InvalidOrderError("close the short position before open long")

                    cost = current_price * (1 + self.slippage + self.buy_cost)
                    want_pay = self.latest_account.cash * order_pct
                    # 买的数量
                    order_amount = want_pay // cost
                    if order_amount > 0:
                        self.update_position(current_position, order_amount, current_price, order_type)
                    else:
                        raise NotEnoughMoneyError()
                # 开空
                elif order_type == ORDER_TYPE_SHORT:
                    if current_position.long_amount > 0:
                        raise InvalidOrderError("close the long position before open short")

                    cost = current_price * (1 + self.slippage + self.buy_cost)
                    want_pay = self.latest_account.cash * order_pct

                    order_amount = want_pay // cost
                    if order_amount > 0:
                        self.update_position(current_position, order_amount, current_price, order_type)
                    else:
                        raise NotEnoughMoneyError()

                # 平多
                elif order_type == ORDER_TYPE_CLOSE_LONG:
                    if current_position.available_long > 1:
                        if order_pct == 1.0:
                            order_amount = current_position.available_long
                        else:
                            order_amount = math.floor(current_position.available_long * order_pct)

                        if order_amount != 0:
                            self.update_position(current_position, order_amount, current_price, order_type)
                        else:
                            self.logger.warning("{} available_long:{} order_pct:{} order_amount:{}", security_id,
                                                current_position.available_long, order_pct, order_amount)
                    else:
                        raise NotEnoughPositionError()
                # 平空
                elif order_type == ORDER_TYPE_CLOSE_SHORT:
                    if current_position.available_short > 1:
                        if order_pct == 1.0:
                            order_amount = current_position.available_short
                        else:
                            order_amount = math.floor(current_position.available_short * order_pct)

                        if order_amount != 0:
                            self.update_position(current_position, order_amount, current_price, order_type)
                        else:
                            self.logger.warning("{} available_long:{} order_pct:{} order_amount:{}", security_id,
                                                current_position.available_long, order_pct, order_amount)
                    else:
                        raise Exception("not enough position")

            self.update_account(security_id, current_position, current_timestamp)