示例#1
0
def _order_value(account, position, ins, cash_amount, style):
    env = Environment.get_instance()
    if cash_amount > 0:
        cash_amount = min(cash_amount, account.cash)
    if isinstance(style, LimitOrder):
        price = style.get_limit_price()
    else:
        price = env.data_proxy.get_last_price(ins.order_book_id)
    amount = int(Decimal(cash_amount) / Decimal(price))

    if cash_amount > 0:
        round_lot = int(ins.round_lot)
        amount = int(Decimal(amount) / Decimal(round_lot)) * round_lot
        while amount > 0:
            expected_transaction_cost = env.get_order_transaction_cost(Order.__from_create__(
                ins.order_book_id, amount, SIDE.BUY, LimitOrder(price), POSITION_EFFECT.OPEN
            ))
            if amount * price + expected_transaction_cost <= cash_amount:
                break
            amount -= round_lot
        else:
            user_system_log.warn(_(u"Order Creation Failed: 0 order quantity"))
            return

    if amount < 0:
        amount = max(amount, -position.closable)

    return _order_shares(ins, amount, style, auto_switch_order_value=False)
示例#2
0
    def _on_settlement(self, event):
        trading_date = Environment.get_instance().trading_dt.date()

        for order_book_id, positions in list(self._positions.items()):
            for position in six.itervalues(positions):
                delta_cash = position.settlement(trading_date)
                self._total_cash += delta_cash

        for order_book_id, positions in list(self._positions.items()):
            if all(p.quantity == 0 and p.equity == 0
                   for p in six.itervalues(positions)):
                del self._positions[order_book_id]

        self._backward_trade_set.clear()

        fee = self._management_fee()
        self._management_fees += fee
        self._total_cash -= fee

        # 如果 total_value <= 0 则认为已爆仓,清空仓位,资金归0
        forced_liquidation = Environment.get_instance(
        ).config.base.forced_liquidation
        if self.total_value <= 0 and forced_liquidation:
            if self._positions:
                user_system_log.warn(
                    _("Trigger Forced Liquidation, current total_value is 0"))
            self._positions.clear()
            self._total_cash = 0
示例#3
0
    def __init__(self, event_bus, scope, ucontext):
        self._user_context = ucontext
        self._current_universe = set()

        self._init = scope.get('init', None)
        self._handle_bar = scope.get('handle_bar', None)
        self._handle_tick = scope.get('handle_tick', None)
        self._open_auction = scope.get("open_auction", None)
        func_before_trading = scope.get('before_trading', None)
        if func_before_trading is not None and func_before_trading.__code__.co_argcount > 1:
            self._before_trading = lambda context: func_before_trading(
                context, None)
            user_system_log.warn(
                _(u"deprecated parameter[bar_dict] in before_trading function."
                  ))
        else:
            self._before_trading = func_before_trading
        self._after_trading = scope.get('after_trading', None)

        if self._before_trading is not None:
            event_bus.add_listener(EVENT.BEFORE_TRADING, self.before_trading)
        if self._handle_bar is not None:
            event_bus.add_listener(EVENT.BAR, self.handle_bar)
        if self._handle_tick is not None:
            event_bus.add_listener(EVENT.TICK, self.handle_tick)
        if self._after_trading is not None:
            event_bus.add_listener(EVENT.AFTER_TRADING, self.after_trading)
        if self._open_auction is not None:
            event_bus.add_listener(EVENT.OPEN_AUCTION, self.open_auction)
示例#4
0
def order_value(id_or_ins, cash_amount, price=None, style=None):
    """
    使用想要花费的金钱买入/卖出股票,而不是买入/卖出想要的股数,正数代表买入,负数代表卖出。股票的股数总是会被调整成对应的100的倍数(在A中国A股市场1手是100股)。当您提交一个卖单时,该方法代表的意义是您希望通过卖出该股票套现的金额。如果金额超出了您所持有股票的价值,那么您将卖出所有股票。需要注意,如果资金不足,该API将不会创建发送订单。

    :param id_or_ins: 下单标的物
    :type id_or_ins: :class:`~Instrument` object | `str`

    :param float cash_amount: 需要花费现金购买/卖出证券的数目。正数代表买入,负数代表卖出。

    :param float price: 下单价格,默认为None,表示 :class:`~MarketOrder`, 此参数主要用于简化 `style` 参数。

    :param style: 下单类型, 默认是市价单。目前支持的订单类型有 :class:`~LimitOrder` 和 :class:`~MarketOrder`
    :type style: `OrderStyle` object

    :return: :class:`~Order` object

    :example:

    .. code-block:: python

        #买入价值¥10000的平安银行股票,并以市价单发送。如果现在平安银行股票的价格是¥7.5,那么下面的代码会买入1300股的平安银行,因为少于100股的数目将会被自动删除掉:
        order_value('000001.XSHE', 10000)
        #卖出价值¥10000的现在持有的平安银行:
        order_value('000001.XSHE', -10000)

    """

    style = cal_style(price, style)

    if isinstance(style, LimitOrder):
        if style.get_limit_price() <= 0:
            raise RQInvalidArgument(_(u"Limit order price should be positive"))

    order_book_id = assure_stock_order_book_id(id_or_ins)
    env = Environment.get_instance()

    price = env.get_last_price(order_book_id)
    if not is_valid_price(price):
        user_system_log.warn(
            _(u"Order Creation Failed: [{order_book_id}] No market data").
            format(order_book_id=order_book_id))
        return

    account = env.portfolio.accounts[DEFAULT_ACCOUNT_TYPE.STOCK.name]

    if cash_amount > 0:
        cash_amount = min(cash_amount, account.cash)

    if isinstance(style, MarketOrder):
        amount = int(Decimal(cash_amount) / Decimal(price))
    else:
        amount = int(Decimal(cash_amount) / Decimal(style.get_limit_price()))

    # if the cash_amount is larger than you current security’s position,
    # then it will sell all shares of this security.

    position = account.positions[order_book_id]
    amount = downsize_amount(amount, position)

    return order_shares(order_book_id, amount, style=style)
    def start_up(self, env, mod_config):
        env.set_price_board(StockLimitUpDownPriceBoard())
        type_ = DataSourceType(mod_config.source)
        if type_ in [DataSourceType.MONGO, DataSourceType.REAL_TIME]:
            args = (env.config.base.data_bundle_path, mod_config.mongo_url)
            data_source_cls = MongoCacheDataSource if mod_config.enable_cache else MongoDataSource
        elif type_ == DataSourceType.BUNDLE:
            args = (env.config.base.data_bundle_path, mod_config.bundle_path)
            data_source_cls = BundleCacheDataSource if mod_config.enable_cache else BundleDataSource
        else:
            raise RuntimeError("data source type [%s] is not supported" %
                               mod_config.source)
        if mod_config.enable_cache:
            if mod_config.cache_length:
                CacheMixin.set_cache_length(int(mod_config.cache_length))
            if mod_config.max_cache_space:
                CacheMixin.set_cache_length(int(mod_config.cache_length))
        data_source = data_source_cls(*args)
        mod_config.redis_uri = mod_config.redis_url  # fit rqalpha
        if env.config.base.run_type is RUN_TYPE.BACKTEST and env.config.base.persist_mode == PERSIST_MODE.ON_NORMAL_EXIT:
            # generate user context using backtest
            persist_provider = DiskPersistProvider(mod_config.persist_path)
            env.set_persist_provider(persist_provider)

        is_real_time = env.config.base.run_type in (RUN_TYPE.PAPER_TRADING,
                                                    RUN_TYPE.LIVE_TRADING)
        if is_real_time or type_ == DataSourceType.REAL_TIME:
            user_system_log.warn(
                _("[Warning] When you use this version of RealtimeTradeMod, history_bars can only "
                  "get data from yesterday."))
            if mod_config.redis_url:
                data_source = RedisDataSource(env.config.base.data_bundle_path,
                                              mod_config.redis_url,
                                              datasource=data_source)
                system_log.info(_("RealtimeTradeMod using market from redis"))
            else:
                data_source = DirectDataSource(
                    env.config.base.data_bundle_path)
                system_log.info(
                    _("RealtimeTradeMod using market from network"))
        if is_real_time:
            event_source = RealTimeEventSource(mod_config.fps, mod_config)
            # add persist
            persist_provider = DiskPersistProvider(mod_config.persist_path)
            env.set_persist_provider(persist_provider)

            env.config.base.persist = True
            env.config.base.persist_mode = PERSIST_MODE.REAL_TIME
        else:
            event_source = IntervalEventSource(env)
        env.set_data_source(data_source)
        # a patch to start_date since it's real time mod
        if env.config.base.start_date == datetime.now().date():
            trading_dates = data_source.get_trading_calendar()
            pos = trading_dates.searchsorted(env.config.base.start_date)
            if trading_dates[pos].to_pydatetime().date(
            ) != env.config.base.start_date:
                env.config.base.start_date = trading_dates[max(
                    0, pos - 1)].to_pydatetime().date()
        env.set_event_source(event_source)
示例#6
0
    def can_submit_order(self, order, account=None):
        if order.type != ORDER_TYPE.LIMIT:
            return True

        # FIXME: it may be better to round price in data source
        limit_up = round(self._env.price_board.get_limit_up(order.order_book_id), 4)
        if order.price > limit_up:
            reason = _(
                "Order Creation Failed: limit order price {limit_price} is higher than limit up {limit_up}."
            ).format(
                limit_price=order.price,
                limit_up=limit_up
            )
            user_system_log.warn(reason)
            return False

        limit_down = round(self._env.price_board.get_limit_down(order.order_book_id), 4)
        if order.price < limit_down:
            reason = _(
                "Order Creation Failed: limit order price {limit_price} is lower than limit down {limit_down}."
            ).format(
                limit_price=order.price,
                limit_down=limit_down
            )
            user_system_log.warn(reason)
            return False

        return True
    def _settlement(self, event, check_delist=True):
        delete_list = []
        for direction, positions in list(self._positions_dict.items()):
            for order_book_id, position in list(positions.items()):
                pass

        for direction, positions in self._positions_dict.items():
            for order_book_id, position in positions.items():
                if check_delist and position.is_de_listed(
                ) and position.quantity != 0:
                    user_system_log.warn(
                        _(u"{order_book_id} is expired, close all positions by system"
                          ).format(order_book_id=order_book_id))
                    delete_list.append((order_book_id, direction))
                    # del self._positions[order_book_id]
                elif position.quantity == 0:
                    delete_list.append((order_book_id, direction))
                    # del self._positions[order_book_id]
                else:
                    position.apply_settlement()

        for order_book_id, direction in delete_list:
            self._positions_dict[direction].pop(order_book_id)

        self._backward_trade_set.clear()
示例#8
0
    def _on_settlement(self, event):
        self._static_total_value = self.total_value

        for position in list(self._positions.values()):
            order_book_id = position.order_book_id
            if position.is_de_listed(
            ) and position.buy_quantity + position.sell_quantity != 0:
                user_system_log.warn(
                    _(u"{order_book_id} is expired, close all positions by system"
                      ).format(order_book_id=order_book_id))
                del self._positions[order_book_id]
            elif position.buy_quantity == 0 and position.sell_quantity == 0:
                del self._positions[order_book_id]
            else:
                position.apply_settlement()

        # 如果 total_value <= 0 则认为已爆仓,清空仓位,资金归0
        if self._static_total_value <= 0 and self.forced_liquidation:
            if self._positions:
                user_system_log.warn(
                    _("Trigger Forced Liquidation, current total_value is 0"))
            self._positions.clear()
            self._static_total_value = 0

        self._backward_trade_set.clear()
示例#9
0
def submit_order(id_or_ins, amount, side, price=None, position_effect=None):

    order_book_id = assure_order_book_id(id_or_ins)
    env = Environment.get_instance()
    if env.config.base.run_type != RUN_TYPE.BACKTEST:
        if "88" in order_book_id:
            raise RQInvalidArgument(
                _(u"Main Future contracts[88] are not supported in paper trading."
                  ))
        if "99" in order_book_id:
            raise RQInvalidArgument(
                _(u"Index Future contracts[99] are not supported in paper trading."
                  ))
    style = cal_style(price, None)
    market_price = env.get_last_price(order_book_id)
    if not is_valid_price(market_price):
        user_system_log.warn(
            _(u"Order Creation Failed: [{order_book_id}] No market data").
            format(order_book_id=order_book_id))
        return

    order = Order.__from_create__(order_book_id=order_book_id,
                                  quantity=amount,
                                  side=side,
                                  style=style,
                                  position_effect=position_effect)

    if order.type == ORDER_TYPE.MARKET:
        order.set_frozen_price(market_price)
    if env.can_submit_order(order):
        env.broker.submit_order(order)
    return order
示例#10
0
def order_shares(id_or_ins, amount, price=None, style=None):
    order_book_id = assure_order_book_id(id_or_ins)
    env = Environment.get_instance()

    if amount > 0:
        side = SIDE.BUY
        position_effect = POSITION_EFFECT.OPEN
    else:
        amount = abs(amount)
        side = SIDE.SELL
        position_effect = POSITION_EFFECT.CLOSE

    round_lot = int(env.get_instrument(order_book_id).round_lot)
    try:
        amount = int(Decimal(amount) / Decimal(round_lot)) * round_lot
    except ValueError:
        amount = 0

    order = Order.__from_create__(order_book_id, amount, side, style,
                                  position_effect)

    if amount == 0:
        # 如果计算出来的下单量为0, 则不生成Order, 直接返回None
        # 因为很多策略会直接在handle_bar里面执行order_target_percent之类的函数,经常会出现下一个量为0的订单,如果这些订单都生成是没有意义的。
        user_system_log.warn(_(u"Order Creation Failed: 0 order quantity"))
        return

    env.broker.submit_order(order)
    return order
示例#11
0
    def _on_settlement(self, event):
        env = Environment.get_instance()
        for position in list(self._positions.values()):
            order_book_id = position.order_book_id
            if position.is_de_listed() and position.quantity != 0:
                try:
                    transform_data = env.data_proxy.get_share_transformation(
                        order_book_id)
                except NotImplementedError:
                    pass
                else:
                    if transform_data is not None:
                        self._pending_transform[order_book_id] = transform_data
                        continue
                if env.config.mod.sys_accounts.cash_return_by_stock_delisted:
                    self._total_cash += position.market_value
                user_system_log.warn(
                    _(u"{order_book_id} is expired, close all positions by system"
                      ).format(order_book_id=order_book_id))
                self._positions.pop(order_book_id, None)
            elif position.quantity == 0:
                self._positions.pop(order_book_id, None)
            else:
                position.apply_settlement()

        self._backward_trade_set.clear()
示例#12
0
    def can_submit_order(self, order, account=None):
        if order.type != ORDER_TYPE.LIMIT:
            return True

        # FIXME: it may be better to round price in data source
        limit_up = round(self._env.price_board.get_limit_up(order.order_book_id), 4)
        if order.price > limit_up:
            reason = _(
                "Order Creation Failed: limit order price {limit_price} is higher than limit up {limit_up}."
            ).format(
                limit_price=order.price,
                limit_up=limit_up
            )
            user_system_log.warn(reason)
            return False

        limit_down = round(self._env.price_board.get_limit_down(order.order_book_id), 4)
        if order.price < limit_down:
            reason = _(
                "Order Creation Failed: limit order price {limit_price} is lower than limit down {limit_down}."
            ).format(
                limit_price=order.price,
                limit_down=limit_down
            )
            user_system_log.warn(reason)
            return False

        return True
示例#13
0
def order_value(id_or_ins, cash_amount, price=None, style=None):
    """
    使用想要花费的金钱买入/卖出股票,而不是买入/卖出想要的股数,正数代表买入,负数代表卖出。股票的股数总是会被调整成对应的100的倍数(在A中国A股市场1手是100股)。当您提交一个卖单时,该方法代表的意义是您希望通过卖出该股票套现的金额。如果金额超出了您所持有股票的价值,那么您将卖出所有股票。需要注意,如果资金不足,该API将不会创建发送订单。

    :param id_or_ins: 下单标的物
    :type id_or_ins: :class:`~Instrument` object | `str`

    :param float cash_amount: 需要花费现金购买/卖出证券的数目。正数代表买入,负数代表卖出。

    :param float price: 下单价格,默认为None,表示 :class:`~MarketOrder`, 此参数主要用于简化 `style` 参数。

    :param style: 下单类型, 默认是市价单。目前支持的订单类型有 :class:`~LimitOrder` 和 :class:`~MarketOrder`
    :type style: `OrderStyle` object

    :return: :class:`~Order` object

    :example:

    .. code-block:: python

        #买入价值¥10000的平安银行股票,并以市价单发送。如果现在平安银行股票的价格是¥7.5,那么下面的代码会买入1300股的平安银行,因为少于100股的数目将会被自动删除掉:
        order_value('000001.XSHE', 10000)
        #卖出价值¥10000的现在持有的平安银行:
        order_value('000001.XSHE', -10000)

    """

    style = cal_style(price, style)

    if isinstance(style, LimitOrder):
        if style.get_limit_price() <= 0:
            raise RQInvalidArgument(_(u"Limit order price should be positive"))

    order_book_id = assure_stock_order_book_id(id_or_ins)
    env = Environment.get_instance()

    price = env.get_last_price(order_book_id)
    if not is_valid_price(price):
        user_system_log.warn(
            _(u"Order Creation Failed: [{order_book_id}] No market data").format(order_book_id=order_book_id))
        return

    account = env.portfolio.accounts[DEFAULT_ACCOUNT_TYPE.STOCK.name]
    round_lot = int(env.get_instrument(order_book_id).round_lot)

    if cash_amount > 0:
        cash_amount = min(cash_amount, account.cash)

    if isinstance(style, MarketOrder):
        amount = int(Decimal(cash_amount) / Decimal(price) / Decimal(round_lot)) * round_lot
    else:
        amount = int(Decimal(cash_amount) / Decimal(style.get_limit_price()) / Decimal(round_lot)) * round_lot

    # if the cash_amount is larger than you current security’s position,
    # then it will sell all shares of this security.

    position = account.positions[order_book_id]
    amount = downsize_amount(amount, position)

    return order_shares(order_book_id, amount, style=style)
示例#14
0
    def start_up(self, env, mod_config):

        if env.config.base.run_type in (RUN_TYPE.PAPER_TRADING,
                                        RUN_TYPE.LIVE_TRADING):
            user_system_log.warn(
                _("[Warning] When you use this version of RealtimeTradeMod, history_bars can only get data from yesterday."
                  ))

            if mod_config.redis_uri:
                env.set_data_source(
                    RedisDataSource(env.config.base.data_bundle_path,
                                    mod_config.redis_uri))
                system_log.info(_("RealtimeTradeMod using market from redis"))
            else:
                env.set_data_source(
                    DirectDataSource(env.config.base.data_bundle_path))
                system_log.info(
                    _("RealtimeTradeMod using market from network"))

            env.set_event_source(
                RealtimeEventSource(mod_config.fps, mod_config))

            # add persist
            persist_provider = DiskPersistProvider(mod_config.persist_path)
            env.set_persist_provider(persist_provider)

            env.config.base.persist = True
            env.config.base.persist_mode = PERSIST_MODE.REAL_TIME
示例#15
0
def submit_order(id_or_ins, amount, side, price=None, position_effect=None):
    """
    通用下单函数,策略可以通过该函数自由选择参数下单。

    :param id_or_ins: 下单标的物
    :type id_or_ins: :class:`~Instrument` object | `str`

    :param float amount: 下单量,需为正数

    :param side: 多空方向,多(SIDE.BUY)或空(SIDE.SELL)
    :type side: :class:`~SIDE` enum

    :param float price: 下单价格,默认为None,表示市价单

    :param position_effect: 开平方向,开仓(POSITION_EFFECT.OPEN),平仓(POSITION.CLOSE)或平今(POSITION_EFFECT.CLOSE_TODAY),交易股票不需要该参数
    :type position_effect: :class:`~POSITION_EFFECT` enum

    :return: :class:`~Order` object | None

    :example:

    .. code-block:: python

        # 购买 2000 股的平安银行股票,并以市价单发送:
        submit_order('000001.XSHE', 2000, SIDE.BUY)
        # 平 10 份 RB1812 多方向的今仓,并以 4000 的价格发送限价单
        submit_order('RB1812', 10, SIDE.SELL, price=4000, position_effect=POSITION_EFFECT.CLOSE_TODAY)

    """
    order_book_id = assure_order_book_id(id_or_ins)
    env = Environment.get_instance()
    if env.config.base.run_type != RUN_TYPE.BACKTEST and env.get_instrument(
            order_book_id).type == "Future":
        if "88" in order_book_id:
            raise RQInvalidArgument(
                _(u"Main Future contracts[88] are not supported in paper trading."
                  ))
        if "99" in order_book_id:
            raise RQInvalidArgument(
                _(u"Index Future contracts[99] are not supported in paper trading."
                  ))
    style = cal_style(price, None)
    market_price = env.get_last_price(order_book_id)
    if not is_valid_price(market_price):
        user_system_log.warn(
            _(u"Order Creation Failed: [{order_book_id}] No market data").
            format(order_book_id=order_book_id))
        return

    order = Order.__from_create__(order_book_id=order_book_id,
                                  quantity=amount,
                                  side=side,
                                  style=style,
                                  position_effect=position_effect)

    if order.type == ORDER_TYPE.MARKET:
        order.set_frozen_price(market_price)
    if env.can_submit_order(order):
        env.broker.submit_order(order)
        return order
 def pnl(self):
     """
     [已弃用] 请使用 total_value
     """
     user_system_log.warn(
         _(u"[abandon] {} is no longer used.").format('account.pnl'))
     return 0
示例#17
0
def submit_order(id_or_ins, amount, side, price=None, position_effect=None):

    order_book_id = assure_order_book_id(id_or_ins)
    env = Environment.get_instance()
    if env.config.base.run_type != RUN_TYPE.BACKTEST:
        if "88" in order_book_id:
            raise RQInvalidArgument(_(u"Main Future contracts[88] are not supported in paper trading."))
        if "99" in order_book_id:
            raise RQInvalidArgument(_(u"Index Future contracts[99] are not supported in paper trading."))
    style = cal_style(price, None)
    market_price = env.get_last_price(order_book_id)
    if not is_valid_price(market_price):
        user_system_log.warn(
            _(u"Order Creation Failed: [{order_book_id}] No market data").format(order_book_id=order_book_id)
        )
        return

    order = Order.__from_create__(
        order_book_id=order_book_id,
        quantity=amount,
        side=side,
        style=style,
        position_effect=position_effect
    )

    if order.type == ORDER_TYPE.MARKET:
        order.set_frozen_price(market_price)
    if env.can_submit_order(order):
        env.broker.submit_order(order)
    return order
示例#18
0
def order_shares(id_or_ins, amount, price=None, style=None):
    # type: (Union[str, Instrument], int, Optional[float], Optional[OrderStyle]) -> Optional[Order]
    """
    指定股数的买/卖单,最常见的落单方式之一。如有需要落单类型当做一个参量传入,如果忽略掉落单类型,那么默认是市价单(market order)。

    :param id_or_ins: 下单标的物
    :param amount: 下单量, 正数代表买入,负数代表卖出。将会根据一手xx股来向下调整到一手的倍数,比如中国A股就是调整成100股的倍数。
    :param price: 下单价格,默认为None,表示 :class:`~MarketOrder`, 此参数主要用于简化 `style` 参数。
    :param style: 下单类型, 默认是市价单。目前支持的订单类型有 :class:`~LimitOrder` 和 :class:`~MarketOrder`

    :example:

    .. code-block:: python

        #购买Buy 2000 股的平安银行股票,并以市价单发送:
        order_shares('000001.XSHE', 2000)
        #卖出2000股的平安银行股票,并以市价单发送:
        order_shares('000001.XSHE', -2000)
        #购买1000股的平安银行股票,并以限价单发送,价格为¥10:
        order_shares('000001.XSHG', 1000, style=LimitOrder(10))
    """
    if amount == 0:
        # 如果下单量为0,则认为其并没有发单,则直接返回None
        user_system_log.warn(_(u"Order Creation Failed: Order amount is 0."))
        return None
    style = cal_style(price, style)
    if isinstance(style, LimitOrder):
        if style.get_limit_price() <= 0:
            raise RQInvalidArgument(_(u"Limit order price should be positive"))
    order_book_id = assure_stock_order_book_id(id_or_ins)
    auto_switch_order_value = Environment.get_instance().config.mod.sys_accounts.auto_switch_order_value
    return _order_shares(order_book_id, amount, style, auto_switch_order_value)
示例#19
0
    def update_realtime_quotes(self, order_book_ids, print_log=False):

        if print_log:
            user_system_log.info('update_realtime_quotes\n%s' %
                                 repr(order_book_ids))

        if not order_book_ids:
            return

        codes = [ts_code(book_id) for book_id in order_book_ids]
        try:
            df = ts.get_realtime_quotes(codes)
        except Exception as e:
            user_system_log.warn(repr(e))
            return

        columns = set(df.columns) - set(['name', 'time', 'date', 'code'])
        for label in columns:
            df[label] = df[label].map(lambda x: 0
                                      if str(x).strip() == '' else x)
            df[label] = df[label].astype(float)

        df['chg'] = df['price'] / df['pre_close'] - 1
        df['order_book_id'] = df['code'].apply(order_book_id)
        df = df.set_index('order_book_id').sort_index()
        df['order_book_id'] = df.index
        df['datetime'] = df['date'] + ' ' + df['time']
        df['close'] = df['price']
        df['last'] = df['price']
        df = df.rename(
            columns={
                'pre_close': 'prev_close',
                'amount': 'total_turnover',
                'b1_p': 'b1',
                'a1_p': 'a1',
                'b2_p': 'b2',
                'a2_p': 'a2',
                'b3_p': 'b3',
                'a3_p': 'a3',
                'b4_p': 'b4',
                'a4_p': 'a4',
                'b5_p': 'b5',
                'a5_p': 'a5',
            })

        df['limit_up'] = df.apply(lambda row: row.prev_close *
                                  (1.1 if 'ST' not in row['name'] else 1.05),
                                  axis=1).round(2)
        df['limit_down'] = df.apply(lambda row: row.prev_close *
                                    (0.9 if 'ST' not in row['name'] else 0.95),
                                    axis=1).round(2)

        del df['code']
        del df['date']
        del df['time']

        self._env.price_board.set_snapshot(df)

        if print_log:
            user_system_log.info(repr(df))
示例#20
0
    def can_submit_order(self, order, account=None):
        if (order.type != ORDER_TYPE.LIMIT) or (order.position_effect
                                                == POSITION_EFFECT.EXERCISE):
            return True

        # FIXME: it may be better to round price in data source
        limit_up = round(
            self._env.price_board.get_limit_up(order.order_book_id), 4)
        if order.price > limit_up:
            reason = _(
                "Order Creation Failed: limit order price {limit_price} is higher "
                "than limit up {limit_up}, order_book_id={order_book_id}"
            ).format(order_book_id=order.order_book_id,
                     limit_price=order.price,
                     limit_up=limit_up)
            user_system_log.warn(reason)
            return False

        limit_down = round(
            self._env.price_board.get_limit_down(order.order_book_id), 4)
        if order.price < limit_down:
            reason = _(
                "Order Creation Failed: limit order price {limit_price} is lower "
                "than limit down {limit_down}, order_book_id={order_book_id}"
            ).format(order_book_id=order.order_book_id,
                     limit_price=order.price,
                     limit_down=limit_down)
            user_system_log.warn(reason)
            return False

        return True
示例#21
0
 def can_submit_order(self, order, account=None):
     # type: (Order, Optional[AbstractAccount]) -> bool
     if account is None:
         return True
     if not account.position_validator_enabled(order.order_book_id):
         return True
     if order.position_effect in (POSITION_EFFECT.OPEN,
                                  POSITION_EFFECT.EXERCISE):
         return True
     position = account.get_position(
         order.order_book_id,
         order.position_direction)  # type: AbstractPosition
     if order.position_effect == POSITION_EFFECT.CLOSE_TODAY and order.quantity > position.today_closable:
         user_system_log.warn(
             _("Order Creation Failed: not enough today position {order_book_id} to close, target"
               " quantity is {quantity}, closable today quantity is {closable}"
               ).format(
                   order_book_id=order.order_book_id,
                   quantity=order.quantity,
                   closable=position.today_closable,
               ))
         return False
     if order.position_effect == POSITION_EFFECT.CLOSE and order.quantity > position.closable:
         user_system_log.warn(
             _("Order Creation Failed: not enough position {order_book_id} to close or exercise, target"
               " sell quantity is {quantity}, closable quantity is {closable}"
               ).format(
                   order_book_id=order.order_book_id,
                   quantity=order.quantity,
                   closable=position.closable,
               ))
         return False
     return True
示例#22
0
 def cancel_order(self, order):
     if self._open_orders.get(order.order_id, None):
         url = '%s%s?%s' % (self._address, '/cancel', self._order_id_map[order.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)
                     if resp.get('success', False):
                         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))
                         str_order_id = str(order.order_id)
                         entrust_no = self._order_id_map[str_order_id]
                         del self._open_orders[str_order_id]
                         del self._order_id_map[entrust_no]
                         del self._order_id_map[str_order_id]
                         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)
示例#23
0
 def bought_value(self):
     """
     [已弃用]
     """
     user_system_log.warn(
         _(u"[abandon] {} is no longer valid.").format(
             'stock_position.bought_value'))
     return self._quantity * self._avg_price
示例#24
0
 def set_state(self, state):
     dict_data = pickle.loads(state)
     for key, value in six.iteritems(dict_data):
         try:
             self.__dict__[key] = pickle.loads(value)
             system_log.debug("restore context.{} {}", key, type(self.__dict__[key]))
         except Exception as e:
             user_system_log.warn('context.{} can not restore', key)
示例#25
0
 def average_cost(self):
     """
     [已弃用] 请使用 avg_price 获取持仓买入均价
     """
     user_system_log.warn(
         _(u"[abandon] {} is no longer valid.").format(
             'stock_position.average_cost'))
     return self._avg_price
示例#26
0
文件: order.py 项目: yeoshine/rqalpha
 def round_price(self, tick_size):
     if tick_size:
         with decimal_rounding_floor():
             limit_price_decimal = Decimal("{:.4f}".format(self.limit_price))
             tick_size_decimal = Decimal("{:.4f}".format(tick_size))
             self.limit_price = float((limit_price_decimal / tick_size_decimal).to_integral() * tick_size_decimal)
     else:
         user_system_log.warn('Invalid tick size: {}'.format(tick_size))
示例#27
0
 def round_price(self, tick_size):
     if tick_size:
         with decimal_rounding_floor():
             limit_price_decimal = Decimal("{:.4f}".format(self.limit_price))
             tick_size_decimal = Decimal("{:.4f}".format(tick_size))
             self.limit_price = float((limit_price_decimal / tick_size_decimal).to_integral() * tick_size_decimal)
     else:
         user_system_log.warn('Invalid tick size: {}'.format(tick_size))
示例#28
0
 def sold_value(self):
     """
     [已弃用]
     """
     user_system_log.warn(
         _(u"[abandon] {} is no longer valid.").format(
             'stock_position.sold_value'))
     return 0
 def portfolio_value(self):
     """
     [已弃用] 请使用 total_value
     """
     user_system_log.warn(
         _(u"[abandon] {} is no longer used.").format(
             'account.portfolio_value'))
     return self.total_value
示例#30
0
 def get_state(self):
     dict_data = {}
     for key, value in six.iteritems(self.__dict__):
         try:
             dict_data[key] = pickle.dumps(value)
         except Exception:
             user_system_log.warn("g.{} can not pickle", key)
     return pickle.dumps(dict_data)
示例#31
0
 def daily_realized_pnl(self):
     """
     [已弃用] 请使用 realized_pnl
     """
     user_system_log.warn(
         _(u"[abandon] {} is no longer used.").format(
             'future_account.daily_realized_pnl'))
     return self.realized_pnl
示例#32
0
文件: order.py 项目: zwupup/rqalpha
 def round_price(self, tick_size):
     if tick_size:
         with decimal_rounding_floor():
             self.limit_price = float(
                 (Decimal(self.limit_price) /
                  Decimal(tick_size)).to_integral() * Decimal(tick_size))
     else:
         user_system_log.warn('Invalid tick size: {}'.format(tick_size))
示例#33
0
 def set_state(self, state):
     dict_data = jsonpickle.decode(state)
     for key, value in six.iteritems(dict_data):
         try:
             self.__dict__[key] = value
             system_log.debug("restore context.{} {}", key, type(self.__dict__[key]))
         except Exception as e:
             user_system_log.warn('context.{} can not restore', key)
 def starting_cash(self):
     """
     [已弃用] 请使用 total_value
     """
     user_system_log.warn(
         _(u"[abandon] {} is no longer used.").format(
             'account.starting_cash'))
     return 0
示例#35
0
 def set_state(self, state):
     dict_data = pickle.loads(state)
     for key, value in six.iteritems(dict_data):
         try:
             self.__dict__[key] = pickle.loads(value)
             system_log.debug("restore g.{} {}", key,
                              type(self.__dict__[key]))
         except Exception:
             user_system_log.warn("g.{} restore failed", key)
示例#36
0
 def get_state(self):
     dict_data = {}
     for key, value in six.iteritems(self.__dict__):
         try:
             dict_data[key] = pickle.dumps(value)
         except Exception as e:
             user_detail_log.exception("g.{} can not pickle", key)
             user_system_log.warn("g.{} can not pickle", key)
     return pickle.dumps(dict_data)
示例#37
0
def _sell_all_stock(order_book_id, amount, style):
    env = Environment.get_instance()
    order = Order.__from_create__(order_book_id, amount, SIDE.SELL, style, POSITION_EFFECT.CLOSE)
    if amount == 0:
        user_system_log.warn(_(u"Order Creation Failed: 0 order quantity"))
        return

    if env.can_submit_order(order):
        env.broker.submit_order(order)
        return order
示例#38
0
 def get_state(self):
     dict_data = {}
     for key, value in six.iteritems(self.__dict__):
         if key.startswith("_"):
             continue
         try:
             dict_data[key] = pickle.dumps(value)
         except Exception as e:
             user_system_log.warn("context.{} can not pickle", key)
     return pickle.dumps(dict_data)
    def _stock_validator(account, order):
        if order.side != SIDE.SELL:
            return True

        position = account.positions[order.order_book_id]
        if order.quantity <= position.sellable:
            return True

        user_system_log.warn(_(
            "Order Creation Failed: not enough stock {order_book_id} to sell, you want to sell {quantity},"
            " sellable {sellable}").format(
            order_book_id=order.order_book_id,
            quantity=order.quantity,
            sellable=position.sellable,
        ))
        return False
示例#40
0
    def _stock_validator(self, account, order):
        if order.side == SIDE.SELL:
            return True
        frozen_value = order.frozen_price * order.quantity
        cost_money = frozen_value + self._env.get_order_transaction_cost(DEFAULT_ACCOUNT_TYPE.STOCK, order)
        if cost_money <= account.cash:
            return True

        user_system_log.warn(
            _("Order Creation Failed: not enough money to buy {order_book_id}, needs {cost_money:.2f}, "
              "cash {cash:.2f}").format(
                order_book_id=order.order_book_id,
                cost_money=cost_money,
                cash=account.cash,
            )
        )
        return False
示例#41
0
    def _on_settlement(self, event):
        env = Environment.get_instance()
        for position in list(self._positions.values()):
            order_book_id = position.order_book_id
            if position.is_de_listed() and position.quantity != 0:
                if env.config.mod.sys_accounts.cash_return_by_stock_delisted:
                    self._total_cash += position.market_value
                user_system_log.warn(
                    _(u"{order_book_id} is expired, close all positions by system").format(order_book_id=order_book_id)
                )
                self._positions.pop(order_book_id, None)
            elif position.quantity == 0:
                self._positions.pop(order_book_id, None)
            else:
                position.apply_settlement()

        self._backward_trade_set.clear()
示例#42
0
文件: mod.py 项目: 8dspaces/rqalpha
    def start_up(self, env, mod_config):

        if env.config.base.run_type in (RUN_TYPE.PAPER_TRADING, RUN_TYPE.LIVE_TRADING):
            user_system_log.warn(_("[Warning] When you use this version of RealtimeTradeMod, history_bars can only get data from yesterday."))

            if mod_config.redis_uri:
                env.set_data_source(RedisDataSource(env.config.base.data_bundle_path, mod_config.redis_uri))
                system_log.info(_("RealtimeTradeMod using market from redis"))
            else:
                env.set_data_source(DirectDataSource(env.config.base.data_bundle_path))
                system_log.info(_("RealtimeTradeMod using market from network"))

            env.set_event_source(RealtimeEventSource(mod_config.fps, mod_config))

            # add persist
            persist_provider = DiskPersistProvider(mod_config.persist_path)
            env.set_persist_provider(persist_provider)

            env.config.base.persist = True
            env.config.base.persist_mode = PERSIST_MODE.REAL_TIME
示例#43
0
    def _future_validator(self, account, order):
        if order.position_effect != POSITION_EFFECT.OPEN:
            return True

        instrument = self._env.get_instrument(order.order_book_id)
        margin = order.frozen_price * order.quantity * instrument.contract_multiplier * instrument.margin_rate
        cost_money = margin * self._env.config.base.margin_multiplier
        cost_money += self._env.get_order_transaction_cost(DEFAULT_ACCOUNT_TYPE.FUTURE, order)
        if cost_money <= account.cash:
            return True

        user_system_log.warn(
            _("Order Creation Failed: not enough money to buy {order_book_id}, needs {cost_money:.2f},"
              " cash {cash:.2f}").format(
                order_book_id=order.order_book_id,
                cost_money=cost_money,
                cash=account.cash,
            )
        )
        return False
示例#44
0
    def _settlement(self, event):
        total_value = self.total_value

        for position in list(self._positions.values()):
            order_book_id = position.order_book_id
            if position.is_de_listed() and position.buy_quantity + position.sell_quantity != 0:
                user_system_log.warn(
                    _(u"{order_book_id} is expired, close all positions by system").format(order_book_id=order_book_id))
                del self._positions[order_book_id]
            elif position.buy_quantity == 0 and position.sell_quantity == 0:
                del self._positions[order_book_id]
            else:
                position.apply_settlement()
        self._total_cash = total_value - self.margin - self.holding_pnl

        # 如果 total_value <= 0 则认为已爆仓,清空仓位,资金归0
        if total_value <= 0:
            self._positions.clear()
            self._total_cash = 0

        self._backward_trade_set.clear()
示例#45
0
    def _on_settlement(self, event):
        env = Environment.get_instance()
        for position in list(self._positions.values()):
            order_book_id = position.order_book_id
            if self.AGGRESSIVE_UPDATE_LAST_PRICE:
                position.update_last_price()
            if position.is_de_listed() and position.quantity != 0:
                if env.config.validator.cash_return_by_stock_delisted:
                    self._total_cash += position.market_value
                user_system_log.warn(
                    _(u"{order_book_id} is expired, close all positions by system").format(order_book_id=order_book_id)
                )
                self._positions.pop(order_book_id, None)
            elif position.quantity == 0:
                self._positions.pop(order_book_id, None)
            else:
                position.apply_settlement()

        self._transaction_cost = 0
        self._backward_trade_set.clear()
        self._handle_dividend_book_closure(event.trading_dt.date())
示例#46
0
    def __init__(self, event_bus, scope, ucontext):
        self._user_context = ucontext
        self._current_universe = set()

        self._init = scope.get('init', None)
        self._handle_bar = scope.get('handle_bar', None)
        self._handle_tick = scope.get('handle_tick', None)
        func_before_trading = scope.get('before_trading', None)
        if func_before_trading is not None and func_before_trading.__code__.co_argcount > 1:
            self._before_trading = lambda context: func_before_trading(context, None)
            user_system_log.warn(_(u"deprecated parameter[bar_dict] in before_trading function."))
        else:
            self._before_trading = func_before_trading
        self._after_trading = scope.get('after_trading', None)

        if self._before_trading is not None:
            event_bus.add_listener(EVENT.BEFORE_TRADING, self.before_trading)
        if self._handle_bar is not None:
            event_bus.add_listener(EVENT.BAR, self.handle_bar)
        if self._handle_tick is not None:
            event_bus.add_listener(EVENT.TICK, self.handle_tick)
        if self._after_trading is not None:
            event_bus.add_listener(EVENT.AFTER_TRADING, self.after_trading)

        self._before_day_trading = scope.get('before_day_trading', None)
        self._before_night_trading = scope.get('before_night_trading', None)
        if self._before_day_trading is not None:
            user_system_log.warn(_(u"[deprecated] before_day_trading is no longer used. use before_trading instead."))
        if self._before_night_trading is not None:
            user_system_log.warn(_(u"[deprecated] before_night_trading is no longer used. use before_trading instead."))

        self._force_run_before_trading = Environment.get_instance().config.extra.force_run_init_when_pt_resume
示例#47
0
    def can_submit_order(self, order, account=None):
        instrument = self._env.data_proxy.instruments(order.order_book_id)
        if instrument.listed_date > self._env.trading_dt:
            user_system_log.warn(_(u"Order Creation Failed: {order_book_id} is not listed!").format(
                order_book_id=order.order_book_id,
            ))
            return False

        if instrument.de_listed_date.date() < self._env.trading_dt.date():
            user_system_log.warn(_(u"Order Creation Failed: {order_book_id} has been delisted!").format(
                order_book_id=order.order_book_id,
            ))
            return False

        if instrument.type == 'CS' and self._env.data_proxy.is_suspended(order.order_book_id, self._env.trading_dt):
            user_system_log.warn(_(u"Order Creation Failed: security {order_book_id} is suspended on {date}").format(
                order_book_id=order.order_book_id,
                date=self._env.trading_dt
            ))
            return False

        if instrument.type == 'PublicFund':
            if order.side == SIDE.BUY and self._env.data_proxy.non_subscribable(order.order_book_id,
                                                                                self._env.trading_dt):
                user_system_log.warn(_(u"Order Creation Failed: security {order_book_id} cannot be subscribed on {date}").format(
                    order_book_id=order.order_book_id,
                    date=self._env.trading_dt
                ))
                return False
            elif order.side == SIDE.SELL and self._env.data_proxy.non_redeemable(order.order_book_id,
                                                                                 self._env.trading_dt):
                user_system_log.warn(_(u"Order Creation Failed: security {order_book_id} cannot be redeemed on {date}").format(
                    order_book_id=order.order_book_id,
                    date=self._env.trading_dt
                ))
                return False

        return True
    def _future_validator(account, order):
        if order.position_effect == POSITION_EFFECT.OPEN:
            return True

        position = account.positions[order.order_book_id]

        if order.side == SIDE.BUY and order.position_effect == POSITION_EFFECT.CLOSE_TODAY \
                and order.quantity > position._closable_today_sell_quantity:
            user_system_log.warn(_(
                "Order Creation Failed: not enough today position {order_book_id} to buy close, target"
                " quantity is {quantity}, closable today quantity {closable}").format(
                order_book_id=order.order_book_id,
                quantity=order.quantity,
                closable=position._closable_today_sell_quantity,
            ))
            return False

        if order.side == SIDE.SELL and order.position_effect == POSITION_EFFECT.CLOSE_TODAY \
                and order.quantity > position._closable_today_buy_quantity:
            user_system_log.warn(_(
                "Order Creation Failed: not enough today position {order_book_id} to sell close, target"
                " quantity is {quantity}, closable today quantity {closable}").format(
                order_book_id=order.order_book_id,
                quantity=order.quantity,
                closable=position._closable_today_buy_quantity,
            ))
            return False

        if order.side == SIDE.BUY and order.quantity > position.closable_sell_quantity:
            user_system_log.warn(_(
                "Order Creation Failed: not enough securities {order_book_id} to buy close, target"
                " sell quantity is {quantity}, sell_closable_quantity {closable}").format(
                order_book_id=order.order_book_id,
                quantity=order.quantity,
                closable=position.closable_sell_quantity,
            ))
            return False

        elif order.side == SIDE.SELL and order.quantity > position.closable_buy_quantity:
            user_system_log.warn(_(
                "Order Creation Failed: not enough securities {order_book_id} to sell close, target"
                " sell quantity is {quantity}, buy_closable_quantity {closable}").format(
                order_book_id=order.order_book_id,
                quantity=order.quantity,
                closable=position.closable_buy_quantity,
            ))
            return False
        return True
示例#49
0
    def _settlement(self, event, check_delist=True):
        delete_list = []
        for direction, positions in list(self._positions_dict.items()):
            for order_book_id, position in list(positions.items()):
                pass

        for direction, positions in self._positions_dict.items():
            for order_book_id, position in positions.items():
                if check_delist and position.is_de_listed() and position.quantity != 0:
                    user_system_log.warn(
                        _(u"{order_book_id} is expired, close all positions by system").format(order_book_id=order_book_id))
                    delete_list.append((order_book_id, direction))
                    # del self._positions[order_book_id]
                elif position.quantity == 0:
                    delete_list.append((order_book_id, direction))
                    # del self._positions[order_book_id]
                else:
                    position.apply_settlement()

        for order_book_id, direction in delete_list:
            self._positions_dict[direction].pop(order_book_id)

        self._backward_trade_set.clear()
示例#50
0
 def starting_cash(self):
     """
     [已弃用] 请使用 total_value
     """
     user_system_log.warn(_(u"[abandon] {} is no longer used.").format('account.starting_cash'))
     return 0
示例#51
0
 def average_cost(self):
     """
     [已弃用] 请使用 avg_price 获取持仓买入均价
     """
     user_system_log.warn(_(u"[abandon] {} is no longer valid.").format('stock_position.average_cost'))
     return self._avg_price
示例#52
0
 def daily_realized_pnl(self):
     """
     [已弃用] 请使用 realized_pnl
     """
     user_system_log.warn(_(u"[abandon] {} is no longer used.").format('future_account.daily_realized_pnl'))
     return self.realized_pnl
示例#53
0
 def portfolio_value(self):
     """
     [已弃用] 请使用 total_value
     """
     user_system_log.warn(_(u"[abandon] {} is no longer used.").format('account.portfolio_value'))
     return self.total_value
示例#54
0
 def bought_value(self):
     """
     [已弃用]
     """
     user_system_log.warn(_(u"[abandon] {} is no longer valid.").format('stock_position.bought_value'))
     return self._quantity * self._avg_price
示例#55
0
 def sold_value(self):
     """
     [已弃用]
     """
     user_system_log.warn(_(u"[abandon] {} is no longer valid.").format('stock_position.sold_value'))
     return 0
示例#56
0
 def mark_rejected(self, reject_reason):
     if not self.is_final():
         self._message = reject_reason
         self._status = ORDER_STATUS.REJECTED
         user_system_log.warn(reject_reason)
示例#57
0
 def mark_cancelled(self, cancelled_reason, user_warn=True):
     if not self.is_final():
         self._message = cancelled_reason
         self._status = ORDER_STATUS.CANCELLED
         if user_warn:
             user_system_log.warn(cancelled_reason)
示例#58
0
 def round_price(self, tick_size):
     if tick_size:
         with decimal_rounding_floor():
             self.limit_price = float((Decimal(self.limit_price) / Decimal(tick_size)).to_integral() * Decimal(tick_size))
     else:
         user_system_log.warn('Invalid tick size: {}'.format(tick_size))
示例#59
0
 def pnl(self):
     """
     [已弃用] 请使用 total_value
     """
     user_system_log.warn(_(u"[abandon] {} is no longer used.").format('account.pnl'))
     return 0
示例#60
0
def order(id_or_ins, amount, side, position_effect, style):
    if not isinstance(style, OrderStyle):
        raise RuntimeError
    if amount < 0:
        raise RuntimeError
    if amount == 0:
        user_system_log.warn(_(u"Order Creation Failed: Order amount is 0."))
        return None
    if isinstance(style, LimitOrder) and style.get_limit_price() <= 0:
        raise RQInvalidArgument(_(u"Limit order price should be positive"))

    order_book_id = assure_future_order_book_id(id_or_ins)
    env = Environment.get_instance()
    if env.config.base.run_type != RUN_TYPE.BACKTEST:
        if "88" in order_book_id:
            raise RQInvalidArgument(_(u"Main Future contracts[88] are not supported in paper trading."))
        if "99" in order_book_id:
            raise RQInvalidArgument(_(u"Index Future contracts[99] are not supported in paper trading."))

    price = env.get_last_price(order_book_id)
    if np.isnan(price):
        user_system_log.warn(
            _(u"Order Creation Failed: [{order_book_id}] No market data").format(order_book_id=order_book_id)
        )
        return

    amount = int(amount)

    position = Environment.get_instance().portfolio.positions[order_book_id]

    orders = []
    if position_effect == POSITION_EFFECT.CLOSE:
        if side == SIDE.BUY:
            # 如果平仓量大于持仓量,则 Warning 并 取消订单创建
            if amount > position.sell_quantity:
                user_system_log.warn(
                    _(u"Order Creation Failed: close amount {amount} is larger than position "
                      u"quantity {quantity}").format(amount=amount, quantity=position.sell_quantity)
                )
                return []
            sell_old_quantity = position.sell_old_quantity
            if amount > sell_old_quantity:
                if sell_old_quantity != 0:
                    # 如果有昨仓,则创建一个 POSITION_EFFECT.CLOSE 的平仓单
                    orders.append(Order.__from_create__(
                        order_book_id,
                        sell_old_quantity,
                        side,
                        style,
                        POSITION_EFFECT.CLOSE
                    ))
                # 剩下还有仓位,则创建一个 POSITION_EFFECT.CLOSE_TODAY 的平今单
                orders.append(Order.__from_create__(
                    order_book_id,
                    amount - sell_old_quantity,
                    side,
                    style,
                    POSITION_EFFECT.CLOSE_TODAY
                ))
            else:
                # 创建 POSITION_EFFECT.CLOSE 的平仓单
                orders.append(Order.__from_create__(
                    order_book_id,
                    amount,
                    side,
                    style,
                    POSITION_EFFECT.CLOSE
                ))
        else:
            if amount > position.buy_quantity:
                user_system_log.warn(
                    _(u"Order Creation Failed: close amount {amount} is larger than position "
                      u"quantity {quantity}").format(amount=amount, quantity=position.sell_quantity)
                )
                return []
            buy_old_quantity = position.buy_old_quantity
            if amount > buy_old_quantity:
                if buy_old_quantity != 0:
                    orders.append(Order.__from_create__(
                        order_book_id,
                        buy_old_quantity,
                        side,
                        style,
                        POSITION_EFFECT.CLOSE
                    ))
                orders.append(Order.__from_create__(
                    order_book_id,
                    amount - buy_old_quantity,
                    side,
                    style,
                    POSITION_EFFECT.CLOSE_TODAY
                ))
            else:
                orders.append(Order.__from_create__(
                    order_book_id,
                    amount,
                    side,
                    style,
                    POSITION_EFFECT.CLOSE
                ))
    else:
        orders.append(Order.__from_create__(
            order_book_id,
            amount,
            side,
            style,
            position_effect
        ))

    if np.isnan(price) or price == 0:
        user_system_log.warn(
            _(u"Order Creation Failed: [{order_book_id}] No market data").format(order_book_id=order_book_id))
        for o in orders:
            o.mark_rejected(
                _(u"Order Creation Failed: [{order_book_id}] No market data").format(order_book_id=order_book_id))
        return orders

    for o in orders:
        if o.type == ORDER_TYPE.MARKET:
            o.set_frozen_price(price)
        if env.can_submit_order(o):
            env.broker.submit_order(o)

    # 向前兼容,如果创建的order_list 只包含一个订单的话,直接返回对应的订单,否则返回列表
    if len(orders) == 1:
        return orders[0]
    else:
        return orders