示例#1
0
def parse_future_info(future_info):
    new_info = {}

    for underlying_symbol, info in six.iteritems(future_info):
        try:
            underlying_symbol = underlying_symbol.upper()
        except AttributeError:
            raise RuntimeError(_("Invalid future info: underlying_symbol {} is illegal.".format(underlying_symbol)))

        for field, value in six.iteritems(info):
            if field in (
                "open_commission_ratio", "close_commission_ratio", "close_commission_today_ratio"
            ):
                new_info.setdefault(underlying_symbol, {})[field] = float(value)
            elif field == "commission_type":
                if isinstance(value, six.string_types) and value.upper() == "BY_MONEY":
                    new_info.setdefault(underlying_symbol, {})[field] = COMMISSION_TYPE.BY_MONEY
                elif isinstance(value, six.string_types) and value.upper() == "BY_VOLUME":
                    new_info.setdefault(underlying_symbol, {})[field] = COMMISSION_TYPE.BY_VOLUME
                elif isinstance(value, COMMISSION_TYPE):
                    new_info.setdefault(underlying_symbol, {})[field] = value
                else:
                    raise RuntimeError(_(
                        "Invalid future info: commission_type is suppose to be BY_MONEY or BY_VOLUME"
                    ))
            else:
                raise RuntimeError(_("Invalid future info: field {} is not valid".format(field)))
    return new_info
示例#2
0
def init_portfolio(env):
    accounts = {}
    config = env.config
    start_date = config.base.start_date
    total_cash = 0

    if DEFAULT_ACCOUNT_TYPE.FUTURE.name in config.base.accounts and config.base.frequency != '1d':
        BaseAccount.AGGRESSIVE_UPDATE_LAST_PRICE = True

    for account_type, starting_cash in six.iteritems(config.base.accounts):
        if account_type == DEFAULT_ACCOUNT_TYPE.STOCK.name:
            if starting_cash == 0:
                raise RuntimeError(_(u"stock starting cash can not be 0, using `--account stock 100000`"))
            StockAccount = env.get_account_model(DEFAULT_ACCOUNT_TYPE.STOCK.name)
            StockPosition = env.get_position_model(DEFAULT_ACCOUNT_TYPE.STOCK.name)
            accounts[DEFAULT_ACCOUNT_TYPE.STOCK.name] = StockAccount(starting_cash, Positions(StockPosition))
            total_cash += starting_cash
        elif account_type == DEFAULT_ACCOUNT_TYPE.FUTURE.name:
            if starting_cash == 0:
                raise RuntimeError(_(u"future starting cash can not be 0, using `--account future 100000`"))
            FutureAccount = env.get_account_model(DEFAULT_ACCOUNT_TYPE.FUTURE.name)
            FuturePosition = env.get_position_model(DEFAULT_ACCOUNT_TYPE.FUTURE.name)
            accounts[DEFAULT_ACCOUNT_TYPE.FUTURE.name] = FutureAccount(starting_cash, Positions(FuturePosition))
            total_cash += starting_cash
        else:
            raise NotImplementedError
    return Portfolio(start_date, 1, total_cash, accounts)
示例#3
0
文件: mod.py 项目: jacktang/rqalpha
    def start_up(self, env, mod_config):
        mod_config.matching_type = self.parse_matching_type(mod_config.matching_type)
        if mod_config.commission_multiplier < 0:
            raise patch_user_exc(ValueError(_(u"invalid commission multiplier value: value range is [0, +∞)")))
        if env.config.base.margin_multiplier <= 0:
            raise patch_user_exc(ValueError(_(u"invalid margin multiplier value: value range is (0, +∞]")))

        if env.config.base.frequency == "tick":
            mod_config.volume_limit = False
            if mod_config.matching_type not in [
                MATCHING_TYPE.NEXT_TICK_LAST,
                MATCHING_TYPE.NEXT_TICK_BEST_OWN,
                MATCHING_TYPE.NEXT_TICK_BEST_COUNTERPARTY,
            ]:
                raise RuntimeError(_("Not supported matching type {}").format(mod_config.matching_type))
        else:
            if mod_config.matching_type not in [
                MATCHING_TYPE.NEXT_BAR_OPEN,
                MATCHING_TYPE.CURRENT_BAR_CLOSE,
            ]:
                raise RuntimeError(_("Not supported matching type {}").format(mod_config.matching_type))

        if mod_config.signal:
            env.set_broker(SignalBroker(env, mod_config))
        else:
            env.set_broker(SimulationBroker(env, mod_config))

        event_source = SimulationEventSource(env, env.config.base.account_list)
        env.set_event_source(event_source)
示例#4
0
        def check_are_valid_fields(func_name, fields):
            if isinstance(fields, six.string_types):
                if fields not in valid_fields:
                    raise RQInvalidArgument(
                        _(u"function {}: invalid {} argument, valid fields are {}, got {} (type: {})").format(
                            func_name, self._arg_name, repr(valid_fields), fields, type(fields)
                        ))
                return

            if fields is None and ignore_none:
                return

            if isinstance(fields, list):
                invalid_fields = [field for field in fields if field not in valid_fields]
                if invalid_fields:
                    raise RQInvalidArgument(
                        _(u"function {}: invalid field {}, valid fields are {}, got {} (type: {})").format(
                            func_name, invalid_fields, repr(valid_fields), fields, type(fields)
                        ))
                return

            raise RQInvalidArgument(
                _(u"function {}: invalid {} argument, expect a string or a list of string, got {} (type: {})").format(
                    func_name, self._arg_name, repr(fields), type(fields)
                ))
示例#5
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
示例#6
0
def update_bundle(data_bundle_path=None, locale="zh_Hans_CN", confirm=True):
    set_locale(locale)
    default_bundle_path = os.path.abspath(os.path.expanduser('~/.rqalpha/bundle'))
    if data_bundle_path is None:
        data_bundle_path = default_bundle_path
    else:
        data_bundle_path = os.path.abspath(os.path.join(data_bundle_path, './bundle/'))
    if (confirm and os.path.exists(data_bundle_path) and data_bundle_path != default_bundle_path and
            os.listdir(data_bundle_path)):
        click.confirm(_(u"""
[WARNING]
Target bundle path {data_bundle_path} is not empty.
The content of this folder will be REMOVED before updating.
Are you sure to continue?""").format(data_bundle_path=data_bundle_path), abort=True)

    tmp = os.path.join(tempfile.gettempdir(), 'rq.bundle')
    url, total_length = get_exactly_url()

    out = open(tmp, 'wb')
    down_load_helper(out, total_length, url)
    out.close()

    shutil.rmtree(data_bundle_path, ignore_errors=True)
    os.makedirs(data_bundle_path)
    tar = tarfile.open(tmp, 'r:bz2')
    tar.extractall(data_bundle_path)
    tar.close()
    os.remove(tmp)
    six.print_(_(u"Data bundle download successfully in {bundle_path}").format(bundle_path=data_bundle_path))
示例#7
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)
示例#8
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
示例#9
0
    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.quantity > position.closable_sell_quantity:
            order.mark_rejected(_(
                "Order Rejected: 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:
            order.mark_rejected(_(
                "Order Rejected: 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
示例#10
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
示例#11
0
    def _match(self, account, order):
        # TODO support tick cal
        env = Environment.get_instance()
        bar = env.get_bar(order.order_book_id)
        bar_status = bar._bar_status

        if bar_status == BAR_STATUS.ERROR:
            listed_date = bar.instrument.listed_date.date()
            if listed_date == self._trading_dt.date():
                reason = _(
                    "Order Cancelled: current security [{order_book_id}] can not be traded in listed date [{listed_date}]").format(
                    order_book_id=order.order_book_id,
                    listed_date=listed_date,
                )
            else:
                reason = _(u"Order Cancelled: current bar [{order_book_id}] miss market data.").format(
                    order_book_id=order.order_book_id)
            order.mark_rejected(reason)
            self._env.event_bus.publish_event(Event(EVENT.ORDER_UNSOLICITED_UPDATE, account=account, order=order))
            return

        if isinstance(order.style, LimitOrder):
            deal_price = order.style.get_limit_price()
        else:
            deal_price = bar.close

        deal_price = min(deal_price, bar.high)
        deal_price = max(deal_price, bar.low)

        deal_price = self._slippage_decider.get_trade_price(order.side, deal_price)

        if (order.side == SIDE.BUY and bar_status == BAR_STATUS.LIMIT_UP) or (
                order.side == SIDE.SELL and bar_status == BAR_STATUS.LIMIT_DOWN):
            user_system_log.warning(_(u"You have traded {order_book_id} with {quantity} lots in {bar_status}").format(
                order_book_id=order.order_book_id,
                quantity=order.quantity,
                bar_status=bar_status
            ))
        ct_amount = account.portfolio.positions.get_or_create(order.order_book_id).cal_close_today_amount(order.quantity, order.side)
        trade = Trade.__from_create__(
            order_id=order.order_id,
            calendar_dt=self._calendar_dt,
            trading_dt=self._trading_dt,
            price=deal_price,
            amount=order.quantity,
            side=order.side,
            position_effect=order.position_effect,
            order_book_id=order.order_book_id,
            frozen_price=order.frozen_price,
            close_today_amount=ct_amount
        )
        trade._commission = self._commission_decider.get_commission(account.type, trade)
        trade._tax = self._tax_decider.get_tax(account.type, trade)
        order.fill(trade)

        env.event_bus.publish_event(Event(EVENT.TRADE, account=account, trade=trade))
示例#12
0
文件: main.py 项目: vt100/rqalpha
def _exception_handler(e):
    better_exceptions.excepthook(e.error.exc_type, e.error.exc_val, e.error.exc_tb)
    user_system_log.error(e.error)
    if not is_user_exc(e.error.exc_val):
        code = const.EXIT_CODE.EXIT_INTERNAL_ERROR
        system_log.exception(_(u"strategy execute exception"))
    else:
        code = const.EXIT_CODE.EXIT_USER_ERROR
        user_detail_log.exception(_(u"strategy execute exception"))

    return code
示例#13
0
def assure_future_order_book_id(id_or_symbols):
    if isinstance(id_or_symbols, Instrument):
        if id_or_symbols.type != "Future":
            raise RQInvalidArgument(
                _(u"{order_book_id} is not supported in current strategy type").format(
                    order_book_id=id_or_symbols.order_book_id))
        else:
            return id_or_symbols.order_book_id
    elif isinstance(id_or_symbols, six.string_types):
        return assure_future_order_book_id(instruments(id_or_symbols))
    else:
        raise RQInvalidArgument(_(u"unsupported order_book_id type"))
示例#14
0
 def tear_down(self, *args):
     result = {}
     for mod_name, __ in reversed(self._mod_list):
         try:
             basic_system_log.debug(_(u"mod tear_down [START] {}").format(mod_name))
             ret = self._mod_dict[mod_name].tear_down(*args)
             basic_system_log.debug(_(u"mod tear_down [END]   {}").format(mod_name))
         except Exception as e:
             system_log.exception("tear down fail for {}", mod_name)
             continue
         if ret is not None:
             result[mod_name] = ret
     return result
示例#15
0
文件: mod.py 项目: kknet/rqalpha
    def start_up(self, env, mod_config):
        mod_config.matching_type = self.parse_matching_type(mod_config.matching_type)
        if mod_config.commission_multiplier < 0:
            raise patch_user_exc(ValueError(_(u"invalid commission multiplier value: value range is [0, +∞)")))
        if env.config.base.margin_multiplier <= 0:
            raise patch_user_exc(ValueError(_(u"invalid margin multiplier value: value range is (0, +∞]")))

        if mod_config.signal:
            env.set_broker(SignalBroker(env, mod_config))
        else:
            env.set_broker(SimulationBroker(env, mod_config))
        event_source = SimulationEventSource(env, env.config.base.account_list)
        env.set_event_source(event_source)
示例#16
0
文件: main.py 项目: gaoyunhua/rqalpha
def _exception_handler(e):
    try:
        sys.excepthook(e.error.exc_type, e.error.exc_val, e.error.exc_tb)
    except Exception as e:
        system_log.exception("hook exception failed")

    user_system_log.error(e.error)
    if not is_user_exc(e.error.exc_val):
        code = const.EXIT_CODE.EXIT_INTERNAL_ERROR
        system_log.error(_(u"strategy execute exception"), exc=e)
    else:
        code = const.EXIT_CODE.EXIT_USER_ERROR
        user_detail_log.error(_(u"strategy execute exception"), exc=e)

    return code
示例#17
0
文件: config.py 项目: vt100/rqalpha
    def to_position_list(positions):
        result = []
        for s in positions.split(','):
            try:
                order_book_id, quantity = s.split(':')
            except ValueError:
                raise RuntimeError(_(u"invalid init position {}, should be in format 'order_book_id:quantity'").format(s))

            try:
                result.append((order_book_id, float(quantity)))
            except ValueError:
                raise RuntimeError(_(u"invalid quantity for instrument {order_book_id}: {quantity}").format(
                    order_book_id=order_book_id, quantity=quantity))

        return result
    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
示例#19
0
def init_portfolio(env):
    accounts = {}
    config = env.config
    start_date = datetime.datetime.combine(config.base.start_date, datetime.time.min)
    units = 0

    if config.base.init_positions or (DEFAULT_ACCOUNT_TYPE.FUTURE.name in config.base.accounts and
                                      config.base.frequency != '1d'):
        BaseAccount.AGGRESSIVE_UPDATE_LAST_PRICE = True

    for account_type, starting_cash in six.iteritems(config.base.accounts):
        if starting_cash == 0:
            raise RuntimeError(_(u"{} starting cash can not be 0, using `--account {} 100000`").format(account_type, account_type))

        account_model = env.get_account_model(account_type)
        position_model = env.get_position_model(account_type)
        positions = Positions(position_model)

        for order_book_id, quantity in _filter_positions(env, account_type):
            instrument = env.get_instrument(order_book_id)
            if instrument is None:
                raise RuntimeError(_(u'invalid order book id {} in initial positions').format(order_book_id))
            if not instrument.listing:
                raise RuntimeError(_(u'instrument {} in initial positions is not listing').format(order_book_id))

            bars = env.data_proxy.history_bars(order_book_id, 1, '1d', 'close',
                                               env.data_proxy.get_previous_trading_date(start_date),
                                               adjust_type='none')
            if bars is None:
                raise RuntimeError(_(u'the close price of {} in initial positions is not available').format(order_book_id))

            price = bars[0]
            trade = _fake_trade(order_book_id, quantity, price)
            if order_book_id not in positions:
                positions[order_book_id] = position_model(order_book_id)
            positions[order_book_id].apply_trade(trade)
            # FIXME
            positions[order_book_id]._last_price = price

        # 变成昨仓
        for order_book_id, position in positions.items():
            position.apply_settlement()

        account = account_model(starting_cash, positions)
        units += account.total_value
        accounts[account_type] = account

    return Portfolio(config.base.start_date, 1, units, accounts)
示例#20
0
    def clock_worker(self):
        data_proxy = self._env.data_proxy

        while True:
            # wait for the first data ready
            if data_proxy.current_snapshot("000001.XSHG", None, None).datetime.date() == datetime.date.today():
                system_log.info(_("Market data is ready, start to work now!"))
                break
            time.sleep(0.1)

        while True:
            time.sleep(self.fps)

            if is_holiday_today():
                time.sleep(60)
                continue

            dt = datetime.datetime.now()

            if dt.strftime("%H:%M:%S") >= "08:30:00" and dt.date() > self.before_trading_fire_date:
                self.event_queue.put((dt, EVENT.BEFORE_TRADING))
                self.before_trading_fire_date = dt.date()
            elif dt.strftime("%H:%M:%S") >= "15:10:00" and dt.date() > self.after_trading_fire_date:
                self.event_queue.put((dt, EVENT.AFTER_TRADING))
                self.after_trading_fire_date = dt.date()
            elif dt.strftime("%H:%M:%S") >= "15:10:00" and dt.date() > self.settlement_fire_date:
                self.event_queue.put((dt, EVENT.SETTLEMENT))
                self.settlement_fire_date = dt.date()

            if is_tradetime_now():
                self.event_queue.put((dt, EVENT.BAR))
示例#21
0
def get_positions():
    booking = Environment.get_instance().booking
    if not booking:
        raise RuntimeError(
            _("Booking has not been set, please check your broker configuration.")
        )
    return booking.get_positions()
示例#22
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的订单,如果这些订单都生成是没有意义的。
        order.mark_rejected(_(u"Order Creation Failed: 0 order quantity"))
        return order

    env.broker.submit_order(order)
    return order
示例#23
0
def order_percent(id_or_ins, percent, price=None, style=None):
    """
    发送一个花费价值等于目前投资组合(市场价值和目前现金的总和)一定百分比现金的买/卖单,正数代表买,负数代表卖。股票的股数总是会被调整成对应的一手的股票数的倍数(1手是100股)。百分比是一个小数,并且小于或等于1(<=100%),0.5表示的是50%.需要注意,如果资金不足,该API将不会创建发送订单。

    需要注意:
    发送买单时,percent 代表的是期望买入股票消耗的金额(包含税费)占投资组合总权益的比例。
    发送卖单时,percent 代表的是期望卖出的股票总价值占投资组合总权益的比例。

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

    :param float percent: 占有现有的投资组合价值的百分比。正数表示买入,负数表示卖出。

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

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

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

    :example:

    .. code-block:: python

        #花费等于现有投资组合50%价值的现金买入平安银行股票:
        order_percent('000001.XSHG', 0.5)
    """
    if percent < -1 or percent > 1:
        raise RQInvalidArgument(_(u"percent should between -1 and 1"))

    style = cal_style(price, style)
    account = Environment.get_instance().portfolio.accounts[DEFAULT_ACCOUNT_TYPE.STOCK.name]
    return order_value(id_or_ins, account.total_value * percent, style=style)
示例#24
0
def order_percent(id_or_ins, percent, price=None, style=None):
    """
    发送一个等于目前投资组合价值(市场价值和目前现金的总和)一定百分比的买/卖单,正数代表买,负数代表卖。股票的股数总是会被调整成对应的一手的股票数的倍数(1手是100股)。百分比是一个小数,并且小于或等于1(<=100%),0.5表示的是50%.需要注意,如果资金不足,该API将不会创建发送订单。

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

    :param float percent: 占有现有的投资组合价值的百分比。正数表示买入,负数表示卖出。

    :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

        #买入等于现有投资组合50%价值的平安银行股票。如果现在平安银行的股价是¥10/股并且现在的投资组合总价值是¥2000,那么将会买入200股的平安银行股票。(不包含交易成本和滑点的损失):
        order_percent('000001.XSHG', 0.5)
    """
    if percent < -1 or percent > 1:
        raise RQInvalidArgument(_(u"percent should between -1 and 1"))

    style = cal_style(price, style)
    account = Environment.get_instance().portfolio.accounts[DEFAULT_ACCOUNT_TYPE.STOCK.name]
    return order_value(id_or_ins, account.total_value * percent, style=style)
示例#25
0
def assure_stock_order_book_id(id_or_symbols):
    if isinstance(id_or_symbols, Instrument):
        return id_or_symbols.order_book_id
    elif isinstance(id_or_symbols, six.string_types):
        return assure_stock_order_book_id(instruments(id_or_symbols))
    else:
        raise RQInvalidArgument(_(u"unsupported order_book_id type"))
示例#26
0
文件: __init__.py 项目: xcbat/rqalpha
    def set_env(self, environment):
        self._env = environment

        config = environment.config

        for mod_name in config.mod.__dict__:
            mod_config = getattr(config.mod, mod_name)
            if not mod_config.enabled:
                continue
            self._mod_list.append((mod_name, mod_config))

        for idx, (mod_name, user_mod_config) in enumerate(self._mod_list):
            if hasattr(user_mod_config, 'lib'):
                lib_name = user_mod_config.lib
            elif mod_name in SYSTEM_MOD_LIST:
                lib_name = "rqalpha.mod.rqalpha_mod_" + mod_name
            else:
                lib_name = "rqalpha_mod_" + mod_name
            system_log.debug(_(u"loading mod {}").format(lib_name))
            mod_module = import_mod(lib_name)
            if mod_module is None:
                del self._mod_list[idx]
                return
            mod = mod_module.load_mod()

            mod_config = RqAttrDict(copy.deepcopy(getattr(mod_module, "__config__", {})))
            mod_config.update(user_mod_config)
            setattr(config.mod, mod_name, mod_config)
            self._mod_list[idx] = (mod_name, mod_config)
            self._mod_dict[mod_name] = mod

        self._mod_list.sort(key=lambda item: getattr(item[1], "priority", 100))
        environment.mod_dict = self._mod_dict
示例#27
0
 def _get_transaction_cost_decider(self, account_type):
     try:
         return self._transaction_cost_decider_dict[account_type]
     except KeyError:
         raise NotImplementedError(_(u"No such transaction cost decider for such account_type {}.".format(
             account_type
         )))
示例#28
0
 def check_portfolio_exist(func_name):
     if Environment.get_instance().portfolio is None:
         raise RQApiNotSupportedError(_(
             "Api {} cannot be called in current strategy, because portfolio instance dose not exist".format(
                 func_name
             )
         ))
示例#29
0
    def get_bars(self, order_book_id, fields=None):
        try:
            s, e = self._index[order_book_id]
        except KeyError:
            six.print_(_(u"No data for {}").format(order_book_id))
            return

        if fields is None:
            # the first is date
            fields = self._table.names[1:]

        if len(fields) == 1:
            return self._converter.convert(fields[0], self._table.cols[fields[0]][s:e])

        # remove datetime if exist in fields
        self._remove_(fields, 'datetime')

        dtype = np.dtype([('datetime', np.uint64)] +
                         [(f, self._converter.field_type(f, self._table.cols[f].dtype))
                          for f in fields])
        result = np.empty(shape=(e - s, ), dtype=dtype)
        for f in fields:
            result[f] = self._converter.convert(f, self._table.cols[f][s:e])
        result['datetime'] = self._table.cols['date'][s:e]
        result['datetime'] *= 1000000

        return result
示例#30
0
    def __from_create__(
            cls, order_id, price, amount, side, position_effect, order_book_id, commission=0., tax=0.,
            trade_id=None, close_today_amount=0, frozen_price=0, calendar_dt=None, trading_dt=None
    ):

        trade = cls()
        trade_id = trade_id or next(trade.trade_id_gen)

        for value in (price, amount, commission, tax, frozen_price):
            if value != value:
                raise RuntimeError(_(
                    "price, amount, commission, tax and frozen_price of trade {trade_id} is not supposed to be nan, "
                    "current_value is {price}, {amount}, {commission}, {tax}, {frozen_price}"
                ).format(
                    trade_id=trade_id, price=price, amount=amount, commission=commission, tax=tax,
                    frozen_price=frozen_price
                ))

        env = Environment.get_instance()
        trade._calendar_dt = calendar_dt or env.calendar_dt
        trade._trading_dt = trading_dt or env.trading_dt
        trade._price = price
        trade._amount = amount
        trade._order_id = order_id
        trade._commission = commission
        trade._tax = tax
        trade._trade_id = trade_id
        trade._close_today_amount = close_today_amount
        trade._side = side
        trade._position_effect = position_effect
        trade._order_book_id = order_book_id
        trade._frozen_price = frozen_price
        return trade
示例#31
0
 def raise_invalid_instrument_error(self, func_name, value):
     return self.raise_instrument_error(func_name, value,
                                        _("valid order_book_id/instrument"))
示例#32
0
def _submit_order(id_or_ins, amount, side, position_effect, style):
    amount = int(amount)
    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"))

    instrument = assure_instrument(id_or_ins)
    order_book_id = instrument.order_book_id
    env = Environment.get_instance()
    if env.config.base.run_type != RUN_TYPE.BACKTEST and instrument.type == INSTRUMENT_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."
                  ))

    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

    env = Environment.get_instance()

    orders = []
    if position_effect in (POSITION_EFFECT.CLOSE_TODAY, POSITION_EFFECT.CLOSE):
        direction = POSITION_DIRECTION.LONG if side == SIDE.SELL else POSITION_DIRECTION.SHORT
        position = env.portfolio.get_position(order_book_id,
                                              direction)  # type: Position
        if position_effect == POSITION_EFFECT.CLOSE_TODAY:
            if amount > position.today_closable:
                user_system_log.warning(
                    _("Order Creation Failed: "
                      "close today amount {amount} is larger than today closable quantity {quantity}"
                      ).format(amount=amount,
                               quantity=position.today_closable))
                return []
            orders.append(
                Order.__from_create__(order_book_id, amount, side, style,
                                      POSITION_EFFECT.CLOSE_TODAY))
        else:
            quantity, old_quantity = position.quantity, position.old_quantity
            if amount > quantity:
                user_system_log.warn(
                    _(u"Order Creation Failed: close amount {amount} is larger than position quantity {quantity}"
                      ).format(amount=amount, quantity=quantity))
                return []
            if amount > old_quantity:
                if old_quantity != 0:
                    # 如果有昨仓,则创建一个 POSITION_EFFECT.CLOSE 的平仓单
                    orders.append(
                        Order.__from_create__(order_book_id, old_quantity,
                                              side, style,
                                              POSITION_EFFECT.CLOSE))
                # 剩下还有仓位,则创建一个 POSITION_EFFECT.CLOSE_TODAY 的平今单
                orders.append(
                    Order.__from_create__(order_book_id, amount - 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))
    elif position_effect == POSITION_EFFECT.OPEN:
        orders.append(
            Order.__from_create__(order_book_id, amount, side, style,
                                  position_effect))
    else:
        raise NotImplementedError()

    if len(orders) > 1:
        user_system_log.warn(
            _("Order was separated, original order: {original_order_repr}, new orders: [{new_orders_repr}]"
              ).
            format(
                original_order_repr=
                "Order(order_book_id={}, quantity={}, side={}, position_effect={})"
                .format(order_book_id, amount, side, position_effect),
                new_orders_repr=", ".join([
                    "Order({}, {}, {}, {})".format(o.order_book_id, o.quantity,
                                                   o.side, o.position_effect)
                    for o in 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)
        else:
            orders.remove(o)

    # 向前兼容,如果创建的order_list 只包含一个订单的话,直接返回对应的订单,否则返回列表
    if len(orders) == 1:
        return orders[0]
    else:
        return orders
示例#33
0
    def events(self, start_date, end_date, frequency):
        trading_dates = self._env.data_proxy.get_trading_dates(
            start_date, end_date)
        if frequency == "1d":
            # 根据起始日期和结束日期,获取所有的交易日,然后再循环获取每一个交易日
            for day in trading_dates:
                date = day.to_pydatetime()
                dt_before_trading = date.replace(hour=0, minute=0)

                dt_bar = self._get_day_bar_dt(date)
                dt_after_trading = self._get_after_trading_dt(date)

                yield Event(EVENT.BEFORE_TRADING,
                            calendar_dt=dt_before_trading,
                            trading_dt=dt_before_trading)
                yield Event(EVENT.OPEN_AUCTION,
                            calendar_dt=dt_before_trading,
                            trading_dt=dt_before_trading)
                yield Event(EVENT.BAR, calendar_dt=dt_bar, trading_dt=dt_bar)
                yield Event(EVENT.AFTER_TRADING,
                            calendar_dt=dt_after_trading,
                            trading_dt=dt_after_trading)
        elif frequency == '1m':
            for day in trading_dates:
                before_trading_flag = True
                date = day.to_pydatetime()
                last_dt = None
                done = False

                dt_before_day_trading = date.replace(hour=8, minute=30)

                while True:
                    if done:
                        break
                    exit_loop = True
                    trading_minutes = self._get_trading_minutes(date)
                    for calendar_dt in trading_minutes:
                        if last_dt is not None and calendar_dt < last_dt:
                            continue

                        if calendar_dt < dt_before_day_trading:
                            trading_dt = calendar_dt.replace(year=date.year,
                                                             month=date.month,
                                                             day=date.day)
                        else:
                            trading_dt = calendar_dt
                        if before_trading_flag:
                            before_trading_flag = False
                            yield Event(EVENT.BEFORE_TRADING,
                                        calendar_dt=calendar_dt -
                                        timedelta(minutes=30),
                                        trading_dt=trading_dt -
                                        timedelta(minutes=30))
                            yield Event(
                                EVENT.OPEN_AUCTION,
                                calendar_dt=calendar_dt - timedelta(minutes=3),
                                trading_dt=trading_dt - timedelta(minutes=3),
                            )
                        if self._universe_changed:
                            self._universe_changed = False
                            last_dt = calendar_dt
                            exit_loop = False
                            break
                        # yield handle bar
                        yield Event(EVENT.BAR,
                                    calendar_dt=calendar_dt,
                                    trading_dt=trading_dt)
                    if exit_loop:
                        done = True

                dt = self._get_after_trading_dt(date)
                yield Event(EVENT.AFTER_TRADING, calendar_dt=dt, trading_dt=dt)
        elif frequency == "tick":
            data_proxy = self._env.data_proxy
            for day in trading_dates:
                date = day.to_pydatetime()
                last_tick = None
                last_dt = None
                dt_before_day_trading = date.replace(hour=8, minute=30)
                while True:
                    for tick in data_proxy.get_merge_ticks(
                            self._get_universe(), date, last_dt):
                        # find before trading time

                        calendar_dt = tick.datetime

                        if calendar_dt < dt_before_day_trading:
                            trading_dt = calendar_dt.replace(year=date.year,
                                                             month=date.month,
                                                             day=date.day)
                        else:
                            trading_dt = calendar_dt

                        if last_tick is None:
                            last_tick = tick

                            yield Event(EVENT.BEFORE_TRADING,
                                        calendar_dt=calendar_dt -
                                        timedelta(minutes=30),
                                        trading_dt=trading_dt -
                                        timedelta(minutes=30))
                            yield Event(
                                EVENT.OPEN_AUCTION,
                                calendar_dt=calendar_dt - timedelta(minutes=3),
                                trading_dt=trading_dt - timedelta(minutes=3),
                            )

                        if self._universe_changed:
                            self._universe_changed = False
                            break

                        last_dt = calendar_dt
                        yield Event(EVENT.TICK,
                                    calendar_dt=calendar_dt,
                                    trading_dt=trading_dt,
                                    tick=tick)

                    else:
                        break

                dt = self._get_after_trading_dt(date)
                yield Event(EVENT.AFTER_TRADING, calendar_dt=dt, trading_dt=dt)
        else:
            raise NotImplementedError(
                _("Frequency {} is not support.").format(frequency))
示例#34
0
 def start_up(self):
     for mod_name, mod_config in self._mod_list:
         system_log.debug(
             _(u"mod start_up [START] {}\n{}").format(mod_name, mod_config))
         self._mod_dict[mod_name].start_up(self._env, mod_config)
         system_log.debug(_(u"mod start_up [END]   {}").format(mod_name))
示例#35
0
 def short_selling_allowed(self, value):
     user_system_log.warn(
         _(u"[abandon] {} is no longer used.").format(
             'context.short_selling_allowed'))
示例#36
0
 def margin_rate(self, value):
     user_system_log.warn(
         _(u"[abandon] {} is no longer used.").format(
             'context.margin_rate'))
示例#37
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
示例#38
0
def run(config, source_code=None, user_funcs=None):
    env = Environment(config)
    persist_helper = None
    init_succeed = False
    mod_handler = ModHandler()

    try:
        # avoid register handlers everytime
        # when running in ipython
        set_loggers(config)
        init_rqdatac(getattr(config.base, 'rqdatac_uri', None))
        system_log.debug("\n" + pformat(config.convert_to_dict()))

        env.set_strategy_loader(
            init_strategy_loader(env, source_code, user_funcs, config))
        mod_handler.set_env(env)
        mod_handler.start_up()

        if not env.data_source:
            env.set_data_source(
                BaseDataSource(config.base.data_bundle_path,
                               getattr(config.base, "future_info", {})))
        if env.price_board is None:
            from rqalpha.data.bar_dict_price_board import BarDictPriceBoard
            env.price_board = BarDictPriceBoard()
        env.set_data_proxy(DataProxy(env.data_source, env.price_board))

        _adjust_start_date(env.config, env.data_proxy)

        ctx = ExecutionContext(const.EXECUTION_PHASE.GLOBAL)
        ctx._push()

        # FIXME
        start_dt = datetime.datetime.combine(config.base.start_date,
                                             datetime.datetime.min.time())
        env.calendar_dt = start_dt
        env.trading_dt = start_dt

        assert env.broker is not None
        assert env.event_source is not None
        if env.portfolio is None:
            from rqalpha.portfolio import Portfolio
            env.set_portfolio(
                Portfolio(config.base.accounts, config.base.init_positions))

        env.event_bus.publish_event(Event(EVENT.POST_SYSTEM_INIT))

        scope = create_base_scope()
        scope.update({"g": env.global_vars})
        scope.update(get_strategy_apis())
        scope = env.strategy_loader.load(scope)

        if config.extra.enable_profiler:
            enable_profiler(env, scope)

        ucontext = StrategyContext()
        executor = Executor(env)

        persist_helper = init_persist_helper(env, ucontext, executor, config)
        user_strategy = Strategy(env.event_bus, scope, ucontext)
        env.user_strategy = user_strategy

        env.event_bus.publish_event(Event(EVENT.BEFORE_STRATEGY_RUN))

        if config.extra.context_vars:
            for k, v in config.extra.context_vars.items():
                if isinstance(v, RqAttrDict):
                    v = v.__dict__
                setattr(ucontext, k, v)

        if persist_helper:
            with LogCapture(user_log) as log_capture:
                user_strategy.init()
        else:
            user_strategy.init()

        if persist_helper:
            env.event_bus.publish_event(Event(EVENT.BEFORE_SYSTEM_RESTORED))
            restored_obj_state = persist_helper.restore(None)
            check_key = ["global_vars", "user_context", "executor", "universe"]
            kept_current_init_data = not any(
                v for k, v in restored_obj_state.items() if k in check_key)
            system_log.debug(
                "restored_obj_state: {}".format(restored_obj_state))
            system_log.debug(
                "kept_current_init_data: {}".format(kept_current_init_data))
            if kept_current_init_data:
                # 未能恢复init相关数据 保留当前策略初始化变量(展示当前策略初始化日志)
                log_capture.replay()
            else:
                system_log.debug(_('system restored'))
            env.event_bus.publish_event(Event(EVENT.POST_SYSTEM_RESTORED))

        init_succeed = True

        bar_dict = BarMap(env.data_proxy, config.base.frequency)
        executor.run(bar_dict)
        env.event_bus.publish_event(Event(EVENT.POST_STRATEGY_RUN))

        if env.profile_deco:
            output_profile_result(env)
        release_print(scope)
    except CustomException as e:
        if init_succeed and persist_helper and env.config.base.persist_mode == const.PERSIST_MODE.ON_CRASH:
            persist_helper.persist()

        code = _exception_handler(e)
        mod_handler.tear_down(code, e)
    except Exception as e:
        system_log.error(traceback.format_exc())

        if init_succeed and persist_helper and env.config.base.persist_mode == const.PERSIST_MODE.ON_CRASH:
            persist_helper.persist()

        exc_type, exc_val, exc_tb = sys.exc_info()
        user_exc = create_custom_exception(exc_type, exc_val, exc_tb,
                                           config.base.strategy_file)

        code = _exception_handler(user_exc)
        mod_handler.tear_down(code, user_exc)
    else:
        if persist_helper and env.config.base.persist_mode == const.PERSIST_MODE.ON_NORMAL_EXIT:
            persist_helper.persist()
        result = mod_handler.tear_down(const.EXIT_CODE.EXIT_SUCCESS)
        system_log.debug(_(u"strategy run successfully, normal exit"))
        return result
示例#39
0
    def _set_env_and_data_source(self):
        env = self._env
        mod_config = self._mod_config
        system_log.info("use recorder {}", mod_config.recorder)
        if mod_config.recorder == "CsvRecorder":
            if not mod_config.persist_folder:
                raise RuntimeError(
                    _(u"You need to set persist_folder to use CsvRecorder"))
            persist_provider = DiskPersistProvider(
                os.path.join(mod_config.persist_folder, "persist"))
            self._recorder = recorders.CsvRecorder(mod_config.persist_folder)
        elif mod_config.recorder == "MongodbRecorder":
            if mod_config.strategy_id is None:
                raise RuntimeError(_(u"You need to set strategy_id"))
            persist_provider = persist_providers.MongodbPersistProvider(
                mod_config.strategy_id, mod_config.mongo_url,
                mod_config.mongo_dbname)
            self._recorder = recorders.MongodbRecorder(mod_config.strategy_id,
                                                       mod_config.mongo_url,
                                                       mod_config.mongo_dbname)
        else:
            raise RuntimeError(
                _(u"unknown recorder {}").format(mod_config.recorder))

        if env.persist_provider is None:
            env.set_persist_provider(persist_provider)

        self._meta = {
            "strategy_id":
            mod_config.strategy_id,
            "origin_start_date":
            self._env.config.base.start_date.strftime("%Y-%m-%d"),
            "start_date":
            self._env.config.base.start_date.strftime("%Y-%m-%d"),
            "end_date":
            self._env.config.base.end_date.strftime("%Y-%m-%d"),
            "last_end_time":
            self._env.config.base.end_date.strftime("%Y-%m-%d"),
            "last_run_time":
            datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
        }

        event_start_time = self._env.config.base.start_date
        persist_meta = self._recorder.load_meta()
        if persist_meta:
            # 不修改回测开始时间
            self._env.config.base.start_date = persist_meta['start_date']
            event_start_time = datetime.datetime.strptime(
                persist_meta['last_end_time'],
                '%Y-%m-%d').date() + datetime.timedelta(days=1)
            # 代表历史有运行过,根据历史上次运行的end_date下一天设为事件发送的start_time

            self._meta["origin_start_date"] = persist_meta["origin_start_date"]
            self._meta["start_date"] = persist_meta["start_date"]
            self._meta[
                "last_end_time"] = self._env.config.base.end_date.strftime(
                    "%Y-%m-%d")
        env.set_data_source(
            IncrementcalDataSource(
                self._env.config.base.data_bundle_path,
                getattr(self._env.config.base, "future_info", {}),
                self._env.config.base.start_date))

        event_source = IncrementalEventSource(env, event_start_time,
                                              self._env.config.base.end_date)
        env.set_event_source(event_source)
示例#40
0
 def check_less_than(func_name, value):
     if value >= high:
         raise RQInvalidArgument(
             _(u"function {}: invalid {} argument, expect a value < {}, got {} (type: {})").format(
                 func_name, self._arg_name, high, value, type(value)
             ))
示例#41
0
 def check_greater_than(func_name, value):
     if value <= low:
         raise RQInvalidArgument(
             _(u"function {}: invalid {} argument, expect a value > {}, got {} (type: {})").format(
                 func_name, self._arg_name, low, value, type(value)
             ))
示例#42
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)
示例#43
0
 def benchmark(self, value):
     user_system_log.warn(
         _(u"[abandon] {} is no longer used.").format('context.benchmark'))
示例#44
0
 def raise_instrument_error(self, func_name, value, instrument_info):
     raise RQInvalidArgument(
         _(u"function {}: invalid {} argument, expected a {}, got {} (type: {})"
           ).format(func_name, self._arg_name, instrument_info, value,
                    type(value)))
示例#45
0
 def commission(self, value):
     user_system_log.warn(
         _(u"[abandon] {} is no longer used.").format('context.commission'))
示例#46
0
def order_shares(id_or_ins, amount, price=None, style=None):
    """
    落指定股数的买/卖单,最常见的落单方式之一。如有需要落单类型当做一个参量传入,如果忽略掉落单类型,那么默认是市价单(market order)。

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

    :param int amount: 下单量, 正数代表买入,负数代表卖出。将会根据一手xx股来向下调整到一手的倍数,比如中国A股就是调整成100股的倍数。

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

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

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

    :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)
    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

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

    if side == SIDE.BUY:
        # 卖出不再限制 round_lot, order_shares 不再依赖 portfolio
        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

    r_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
    if r_order.type == ORDER_TYPE.MARKET:
        r_order.set_frozen_price(price)
    if env.can_submit_order(r_order):
        env.broker.submit_order(r_order)
        return r_order
示例#47
0
def order_target_portfolio(target_portfolio):
    # type: (Dict[Union[str, Instrument], float]) -> List[Order]
    """
    买入/卖出证券以批量调整证券的仓位,以期使其持仓市值占账户总权益的比重达到指定值。

    :param target_portfolio: 下单标的物及其目标市值占比的字典

    :example:

    .. code-block:: python

        # 调整仓位,以使平安银行和万科 A 的持仓占比分别达到 10% 和 15%
        order_target_portfolio({
            '000001.XSHE': 0.1
            '000002.XSHE': 0.15
        })
    """

    if isinstance(target_portfolio, pd.Series):
        # FIXME: kind of dirty
        total_percent = sum(target_portfolio)
    else:
        total_percent = sum(six.itervalues(target_portfolio))
    if total_percent > 1:
        raise RQInvalidArgument(_(u"total percent should be lower than 1, current: {}").format(total_percent))

    env = Environment.get_instance()
    account = env.portfolio.accounts[DEFAULT_ACCOUNT_TYPE.STOCK]
    account_value = account.total_value
    target_quantities = {}
    for id_or_ins, target_percent in target_portfolio.items():
        order_book_id = assure_order_book_id(id_or_ins)
        if target_percent < 0:
            raise RQInvalidArgument(_(u"target percent of {} should between 0 and 1, current: {}").format(
                order_book_id, target_percent
            ))
        price = env.data_proxy.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)
            )
            continue
        target_quantities[order_book_id] = account_value * target_percent / price

    close_orders, open_orders = [], []
    current_quantities = {
        p.order_book_id: p.quantity for p in account.get_positions() if p.direction == POSITION_DIRECTION.LONG
    }
    for order_book_id, quantity in current_quantities.items():
        if order_book_id not in target_portfolio:
            close_orders.append(Order.__from_create__(
                order_book_id, quantity, SIDE.SELL, MarketOrder(), POSITION_EFFECT.CLOSE
            ))

    round_lot = 100
    for order_book_id, target_quantity in target_quantities.items():
        if order_book_id in current_quantities:
            delta_quantity = target_quantity - current_quantities[order_book_id]
        else:
            delta_quantity = target_quantity

        if delta_quantity >= round_lot:
            delta_quantity = math.floor(delta_quantity / round_lot) * round_lot
            open_orders.append(Order.__from_create__(
                order_book_id, delta_quantity, SIDE.BUY, MarketOrder(), POSITION_EFFECT.OPEN
            ))
        elif delta_quantity < -1:
            delta_quantity = math.floor(delta_quantity)
            close_orders.append(Order.__from_create__(
                order_book_id, abs(delta_quantity), SIDE.SELL, MarketOrder(), POSITION_EFFECT.CLOSE
            ))

    submit_orders = []
    for order in chain(close_orders, open_orders):
        if env.can_submit_order(order):
            submit_orders.append(order)
            env.broker.submit_order(order)
    return submit_orders
示例#48
0
 def total_trades(self):
     """abandon"""
     user_system_log.warn(
         _(u"[abandon] {} is no longer valid.").format(
             'position.total_trades'))
     return 0
示例#49
0
文件: main.py 项目: qiuwei/rqalpha
def run(config, source_code=None, user_funcs=None):
    env = Environment(config)
    persist_helper = None
    init_succeed = False
    mod_handler = ModHandler()

    try:
        # avoid register handlers everytime
        # when running in ipython
        set_loggers(config)
        basic_system_log.debug("\n" + pformat(config.convert_to_dict()))

        if source_code is not None:
            env.set_strategy_loader(SourceCodeStrategyLoader(source_code))
        elif user_funcs is not None:
            env.set_strategy_loader(UserFuncStrategyLoader(user_funcs))
        else:
            env.set_strategy_loader(
                FileStrategyLoader(config.base.strategy_file))
        env.set_global_vars(GlobalVars())
        mod_handler.set_env(env)
        mod_handler.start_up()

        try:
            future_info = config.base.future_info
        except AttributeError:
            pass
        else:
            deep_update(future_info, future_info_cn.CN_FUTURE_INFO)

        if not env.data_source:
            env.set_data_source(BaseDataSource(config.base.data_bundle_path))

        if env.price_board is None:
            from .core.bar_dict_price_board import BarDictPriceBoard
            env.price_board = BarDictPriceBoard()

        env.set_data_proxy(DataProxy(env.data_source, env.price_board))

        Scheduler.set_trading_dates_(env.data_source.get_trading_calendar())
        scheduler = Scheduler(config.base.frequency)
        mod_scheduler._scheduler = scheduler

        env._universe = StrategyUniverse()

        _adjust_start_date(env.config, env.data_proxy)

        # FIXME
        start_dt = datetime.datetime.combine(config.base.start_date,
                                             datetime.datetime.min.time())
        env.calendar_dt = start_dt
        env.trading_dt = start_dt

        broker = env.broker
        assert broker is not None
        try:
            env.portfolio = broker.get_portfolio()
        except NotImplementedError:
            pass
        else:
            if env.benchmark_provider:
                env.benchmark_portfolio = BenchmarkPortfolio(
                    env.benchmark_provider, env.portfolio.units)

        try:
            env.booking = broker.get_booking()
        except NotImplementedError:
            pass

        event_source = env.event_source
        assert event_source is not None

        bar_dict = BarMap(env.data_proxy, config.base.frequency)
        env.set_bar_dict(bar_dict)

        ctx = ExecutionContext(const.EXECUTION_PHASE.GLOBAL)
        ctx._push()

        env.event_bus.publish_event(Event(EVENT.POST_SYSTEM_INIT))

        scope = create_base_scope(config.base.run_type == RUN_TYPE.BACKTEST)
        scope.update({"g": env.global_vars})

        apis = api_helper.get_apis()
        scope.update(apis)

        scope = env.strategy_loader.load(scope)

        if env.config.extra.enable_profiler:
            enable_profiler(env, scope)

        ucontext = StrategyContext()
        user_strategy = Strategy(env.event_bus, scope, ucontext)
        env.user_strategy = user_strategy
        scheduler.set_user_context(ucontext)

        if not config.extra.force_run_init_when_pt_resume:
            with run_with_user_log_disabled(disabled=config.base.resume_mode):
                user_strategy.init()

        if config.extra.context_vars:
            for k, v in six.iteritems(config.extra.context_vars):
                if isinstance(v, RqAttrDict):
                    v = v.__dict__
                setattr(ucontext, k, v)

        from .core.executor import Executor
        executor = Executor(env)

        if config.base.persist:
            persist_provider = env.persist_provider
            if persist_provider is None:
                raise RuntimeError(
                    _(u"Missing persist provider. You need to set persist_provider before use persist"
                      ))
            persist_helper = PersistHelper(persist_provider, env.event_bus,
                                           config.base.persist_mode)
            env.set_persist_helper(persist_helper)
            persist_helper.register('core', CoreObjectsPersistProxy(scheduler))
            persist_helper.register('user_context', ucontext)
            persist_helper.register('global_vars', env.global_vars)
            persist_helper.register('universe', env._universe)
            if isinstance(event_source, Persistable):
                persist_helper.register('event_source', event_source)
            if env.portfolio:
                persist_helper.register('portfolio', env.portfolio)
            for name, module in six.iteritems(env.mod_dict):
                if isinstance(module, Persistable):
                    persist_helper.register('mod_{}'.format(name), module)
            # broker will restore open orders from account
            if isinstance(broker, Persistable):
                persist_helper.register('broker', broker)
            persist_helper.register('executor', executor)

            env.event_bus.publish_event(Event(EVENT.BEFORE_SYSTEM_RESTORED))
            persist_helper.restore()
            env.event_bus.publish_event(Event(EVENT.POST_SYSTEM_RESTORED))

        init_succeed = True

        # When force_run_init_when_pt_resume is active,
        # we should run `init` after restore persist data
        if config.extra.force_run_init_when_pt_resume:
            assert config.base.resume_mode == True
            with run_with_user_log_disabled(disabled=False):
                env._universe._set = set()
                user_strategy.init()

        executor.run(bar_dict)

        if env.profile_deco:
            output_profile_result(env)
    except CustomException as e:
        if init_succeed and env.config.base.persist and persist_helper and env.config.base.persist_mode == const.PERSIST_MODE.ON_CRASH:
            persist_helper.persist()

        code = _exception_handler(e)
        mod_handler.tear_down(code, e)
    except Exception as e:
        if init_succeed and env.config.base.persist and persist_helper and env.config.base.persist_mode == const.PERSIST_MODE.ON_CRASH:
            persist_helper.persist()

        exc_type, exc_val, exc_tb = sys.exc_info()
        user_exc = create_custom_exception(exc_type, exc_val, exc_tb,
                                           config.base.strategy_file)

        code = _exception_handler(user_exc)
        mod_handler.tear_down(code, user_exc)
    else:
        if (env.config.base.persist and persist_helper
                and env.config.base.persist_mode
                == const.PERSIST_MODE.ON_NORMAL_EXIT):
            persist_helper.persist()
        result = mod_handler.tear_down(const.EXIT_CODE.EXIT_SUCCESS)
        system_log.debug(_(u"strategy run successfully, normal exit"))
        return result
示例#50
0
    def match(self, account, order, open_auction):
        # type: (Account, Order, bool) -> None
        if order.position_effect == POSITION_EFFECT.EXERCISE:
            raise NotImplementedError
        order_book_id = order.order_book_id
        instrument = self._env.get_instrument(order_book_id)

        if open_auction:
            deal_price = self._open_auction_deal_price_decider(
                order_book_id, order.side)
        else:
            deal_price = self._deal_price_decider(order_book_id, order.side)

        if not is_valid_price(deal_price):
            listed_date = instrument.listed_date.date()
            if listed_date == self._env.trading_dt.date():
                reason = _(
                    u"Order Cancelled: current security [{order_book_id}] can not be traded"
                    u" in listed date [{listed_date}]").format(
                        order_book_id=order.order_book_id,
                        listed_date=listed_date,
                    )
            else:
                reason = _(
                    u"Order Cancelled: current bar [{order_book_id}] miss market data."
                ).format(order_book_id=order.order_book_id)
            order.mark_rejected(reason)
            return

        price_board = self._env.price_board
        if order.type == ORDER_TYPE.LIMIT:
            if order.side == SIDE.BUY and order.price < deal_price:
                return
            if order.side == SIDE.SELL and order.price > deal_price:
                return
            # 是否限制涨跌停不成交
            if self._price_limit:
                if order.side == SIDE.BUY and deal_price >= price_board.get_limit_up(
                        order_book_id):
                    return
                if order.side == SIDE.SELL and deal_price <= price_board.get_limit_down(
                        order_book_id):
                    return
            if self._liquidity_limit:
                if order.side == SIDE.BUY and price_board.get_a1(
                        order_book_id) == 0:
                    return
                if order.side == SIDE.SELL and price_board.get_b1(
                        order_book_id) == 0:
                    return
        else:
            if self._price_limit:
                if order.side == SIDE.BUY and deal_price >= price_board.get_limit_up(
                        order_book_id):
                    reason = _(
                        "Order Cancelled: current bar [{order_book_id}] reach the limit_up price."
                    ).format(order_book_id=order.order_book_id)
                    order.mark_rejected(reason)
                    return
                if order.side == SIDE.SELL and deal_price <= price_board.get_limit_down(
                        order_book_id):
                    reason = _(
                        "Order Cancelled: current bar [{order_book_id}] reach the limit_down price."
                    ).format(order_book_id=order.order_book_id)
                    order.mark_rejected(reason)
                    return
            if self._liquidity_limit:
                if order.side == SIDE.BUY and price_board.get_a1(
                        order_book_id) == 0:
                    reason = _(
                        "Order Cancelled: [{order_book_id}] has no liquidity."
                    ).format(order_book_id=order.order_book_id)
                    order.mark_rejected(reason)
                    return
                if order.side == SIDE.SELL and price_board.get_b1(
                        order_book_id) == 0:
                    reason = _(
                        "Order Cancelled: [{order_book_id}] has no liquidity."
                    ).format(order_book_id=order.order_book_id)
                    order.mark_rejected(reason)
                    return

        if self._volume_limit:
            if open_auction:
                volume = self._env.data_proxy.get_open_auction_bar(
                    order_book_id, self._env.calendar_dt).volume
            else:
                volume = self._env.get_bar(order_book_id).volume
            if volume == volume:
                volume_limit = round(
                    volume *
                    self._volume_percent) - self._turnover[order.order_book_id]

                round_lot = instrument.round_lot
                volume_limit = (volume_limit // round_lot) * round_lot
                if volume_limit <= 0:
                    if order.type == ORDER_TYPE.MARKET:
                        reason = _(
                            u"Order Cancelled: market order {order_book_id} volume {order_volume}"
                            u" due to volume limit").format(
                                order_book_id=order.order_book_id,
                                order_volume=order.quantity)
                        order.mark_cancelled(reason)
                    return

                fill = min(order.unfilled_quantity, volume_limit)
            else:
                fill = order.unfilled_quantity
        else:
            fill = order.unfilled_quantity

        ct_amount = account.calc_close_today_amount(order_book_id, fill,
                                                    order.position_direction)
        price = self._slippage_decider.get_trade_price(order, deal_price)

        trade = Trade.__from_create__(order_id=order.order_id,
                                      price=price,
                                      amount=fill,
                                      side=order.side,
                                      position_effect=order.position_effect,
                                      order_book_id=order.order_book_id,
                                      frozen_price=order.frozen_price,
                                      close_today_amount=ct_amount)
        trade._commission = self._env.get_trade_commission(trade)
        trade._tax = self._env.get_trade_tax(trade)
        order.fill(trade)
        self._turnover[order.order_book_id] += fill

        self._env.event_bus.publish_event(
            Event(EVENT.TRADE, account=account, trade=trade, order=order))

        if order.type == ORDER_TYPE.MARKET and order.unfilled_quantity != 0:
            reason = _(
                u"Order Cancelled: market order {order_book_id} volume {order_volume} is"
                u" larger than {volume_percent_limit} percent of current bar volume, fill {filled_volume} actually"
            ).format(order_book_id=order.order_book_id,
                     order_volume=order.quantity,
                     filled_volume=order.filled_quantity,
                     volume_percent_limit=self._volume_percent * 100.0)
            order.mark_cancelled(reason)
示例#51
0
    def match(self, open_orders):
        price_board = self._env.price_board
        for account, order in open_orders:
            order_book_id = order.order_book_id
            instrument = self._env.get_instrument(order_book_id)

            if np.isnan(price_board.get_last_price(order_book_id)):
                listed_date = instrument.listed_date.date()
                if listed_date == self._trading_dt.date():
                    reason = _(
                        u"Order Cancelled: current security [{order_book_id}] can not be traded in listed date [{listed_date}]"
                    ).format(
                        order_book_id=order.order_book_id,
                        listed_date=listed_date,
                    )
                else:
                    reason = _(
                        u"Order Cancelled: current bar [{order_book_id}] miss market data."
                    ).format(order_book_id=order.order_book_id)
                order.mark_rejected(reason)
                continue

            deal_price = self._deal_price_decider(order_book_id, order.side)
            if order.type == ORDER_TYPE.LIMIT:
                if order.side == SIDE.BUY and order.price < deal_price:
                    continue
                if order.side == SIDE.SELL and order.price > deal_price:
                    continue
            else:
                if self._price_limit and order.side == SIDE.BUY and deal_price >= price_board.get_limit_up(
                        order_book_id):
                    reason = _(
                        "Order Cancelled: current bar [{order_book_id}] reach the limit_up price."
                    ).format(order_book_id=order.order_book_id)
                    order.mark_rejected(reason)
                    continue
                elif self._price_limit and order.side == SIDE.SELL and deal_price <= price_board.get_limit_down(
                        order_book_id):
                    reason = _(
                        "Order Cancelled: current bar [{order_book_id}] reach the limit_down price."
                    ).format(order_book_id=order.order_book_id)
                    order.mark_rejected(reason)
                    continue

            # 是否限制涨跌停不成交
            if self._price_limit:
                if order.side == SIDE.BUY and deal_price >= price_board.get_limit_up(
                        order_book_id):
                    continue
                if order.side == SIDE.SELL and deal_price <= price_board.get_limit_down(
                        order_book_id):
                    continue

            if self._volume_limit:
                bar = self._env.bar_dict[order_book_id]
                volume_limit = round(
                    bar.volume *
                    self._volume_percent) - self._turnover[order.order_book_id]
                round_lot = instrument.round_lot
                volume_limit = (volume_limit // round_lot) * round_lot
                if volume_limit <= 0:
                    if order.type == ORDER_TYPE.MARKET:
                        reason = _(
                            u"Order Cancelled: market order {order_book_id} volume {order_volume}"
                            u" due to volume limit").format(
                                order_book_id=order.order_book_id,
                                order_volume=order.quantity)
                        order.mark_cancelled(reason)
                    continue

                unfilled = order.unfilled_quantity
                fill = min(unfilled, volume_limit)
            else:
                fill = order.unfilled_quantity

            ct_amount = account.positions.get_or_create(
                order.order_book_id).cal_close_today_amount(fill, order.side)
            price = self._slippage_decider.get_trade_price(
                order.side, deal_price)
            trade = Trade.__from_create__(
                order_id=order.order_id,
                calendar_dt=self._calendar_dt,
                trading_dt=self._trading_dt,
                price=price,
                amount=fill,
                side=order.side,
                position_effect=order.position_effect,
                order_book_id=order.order_book_id,
                frozen_price=order.frozen_price,
                close_today_amount=ct_amount)
            trade._commission = self._commission_decider.get_commission(
                account.type, trade)
            trade._tax = self._tax_decider.get_tax(account.type, trade)
            order.fill(trade)
            self._turnover[order.order_book_id] += fill

            self._env.event_bus.publish_event(
                Event(EVENT.TRADE, account=account, trade=trade))

            if order.type == ORDER_TYPE.MARKET and order.unfilled_quantity != 0:
                reason = _(
                    u"Order Cancelled: market order {order_book_id} volume {order_volume} is"
                    u" larger than 25 percent of current bar volume, fill {filled_volume} actually"
                ).format(order_book_id=order.order_book_id,
                         order_volume=order.quantity,
                         filled_volume=order.filled_quantity)
                order.mark_cancelled(reason)
示例#52
0
 def get_position_model(self, account_type):
     if account_type not in self._position_model_dict:
         raise RuntimeError(
             _(u"Unknown Account Type {}").format(account_type))
     return self._position_model_dict[account_type]
示例#53
0
 def raise_instrument_not_listed_error(self, func_name, value):
     return self.raise_instrument_error(
         func_name, value, _("listed order_book_id/instrument"))
示例#54
0
    def match(self, open_orders):
        for account, order in open_orders:

            bar = self._board[order.order_book_id]
            bar_status = bar._bar_status

            if bar_status == BAR_STATUS.ERROR:
                listed_date = bar.instrument.listed_date.date()
                if listed_date == self._trading_dt.date():
                    reason = _(
                        u"Order Cancelled: current security [{order_book_id}] can not be traded in listed date [{listed_date}]"
                    ).format(
                        order_book_id=order.order_book_id,
                        listed_date=listed_date,
                    )
                else:
                    reason = _(
                        u"Order Cancelled: current bar [{order_book_id}] miss market data."
                    ).format(order_book_id=order.order_book_id)
                order.mark_rejected(reason)
                continue

            deal_price = self._deal_price_decider(bar)
            if order.type == ORDER_TYPE.LIMIT:
                if order.side == SIDE.BUY and order.price < deal_price:
                    continue
                if order.side == SIDE.SELL and order.price > deal_price:
                    continue
            else:
                if self._bar_limit and order.side == SIDE.BUY and bar_status == BAR_STATUS.LIMIT_UP:
                    reason = _(
                        "Order Cancelled: current bar [{order_book_id}] reach the limit_up price."
                    ).format(order_book_id=order.order_book_id)
                    order.mark_rejected(reason)
                    continue
                elif self._bar_limit and order.side == SIDE.SELL and bar_status == BAR_STATUS.LIMIT_DOWN:
                    reason = _(
                        "Order Cancelled: current bar [{order_book_id}] reach the limit_down price."
                    ).format(order_book_id=order.order_book_id)
                    order.mark_rejected(reason)
                    continue

            if self._bar_limit:
                if order.side == SIDE.BUY and bar_status == BAR_STATUS.LIMIT_UP:
                    continue
                if order.side == SIDE.SELL and bar_status == BAR_STATUS.LIMIT_DOWN:
                    continue

            volume_limit = round(
                bar.volume *
                self._volume_percent) - self._turnover[order.order_book_id]
            round_lot = bar.instrument.round_lot
            volume_limit = (volume_limit // round_lot) * round_lot
            if volume_limit <= 0:
                if order.type == ORDER_TYPE.MARKET:
                    reason = _(
                        'Order Cancelled: market order {order_book_id} volume {order_volume}'
                        ' due to volume limit').format(
                            order_book_id=order.order_book_id,
                            order_volume=order.quantity)
                    order.mark_cancelled(reason)
                continue

            unfilled = order.unfilled_quantity
            fill = min(unfilled, volume_limit)
            ct_amount = account.positions.get_or_create(
                order.order_book_id).cal_close_today_amount(fill, order.side)
            price = self._slippage_decider.get_trade_price(
                order.side, deal_price)
            trade = Trade.__from_create__(
                order_id=order.order_id,
                calendar_dt=self._calendar_dt,
                trading_dt=self._trading_dt,
                price=price,
                amount=fill,
                side=order.side,
                position_effect=order.position_effect,
                order_book_id=order.order_book_id,
                frozen_price=order.frozen_price,
                close_today_amount=ct_amount)
            trade._commission = self._commission_decider.get_commission(
                account.type, trade)
            trade._tax = self._tax_decider.get_tax(account.type, trade)
            order.fill(trade)
            self._turnover[order.order_book_id] += fill

            Environment.get_instance().event_bus.publish_event(
                Event(EVENT.TRADE, account=account, trade=trade))

            if order.type == ORDER_TYPE.MARKET and order.unfilled_quantity != 0:
                reason = _(
                    "Order Cancelled: market order {order_book_id} volume {order_volume} is"
                    " larger than 25 percent of current bar volume, fill {filled_volume} actually"
                ).format(order_book_id=order.order_book_id,
                         order_volume=order.quantity,
                         filled_volume=order.filled_quantity)
                order.mark_cancelled(reason)
示例#55
0
 def raise_not_valid_future_error(self, func_name, value):
     return self.raise_instrument_error(
         func_name, value, _("valid future order_book_id/instrument"))
示例#56
0
 def future_portfolio(self):
     user_system_log.warn(
         _(u"[abandon] {} is no longer used.").format(
             'context.future_portfolio'))
     return self.future_account
示例#57
0
 def slippage(self, value):
     user_system_log.warn(
         _(u"[abandon] {} is no longer used.").format('context.slippage'))
示例#58
0
    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]:
            from rqalpha_mod_fxdayu_source.data_source.mongo import MongoDataSource, MongoCacheDataSource
            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:
            from rqalpha_mod_fxdayu_source.data_source.bundle import BundleCacheDataSource, BundleDataSource
            args = (env.config.base.data_bundle_path, mod_config.bundle_path)
            data_source_cls = BundleCacheDataSource if mod_config.enable_cache else BundleDataSource
        elif type_ == DataSourceType.QUANTOS:
            from rqalpha_mod_fxdayu_source.data_source.quantos import QuantOsSource, QuantOsCacheSource
            args = (env.config.base.data_bundle_path, mod_config.quantos_url,
                    mod_config.quantos_user, mod_config.quantos_token)
            data_source_cls = QuantOsCacheSource if mod_config.enable_cache else QuantOsSource
        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_max_cache_space(int(mod_config.max_cache_space))
        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 type_ == DataSourceType.QUANTOS:
                inday_bars = QuantOsIndayBars(mod_config.quantos_url,
                                              mod_config.quantos_user,
                                              mod_config.quantos_token)
            elif mod_config.redis_url:
                inday_bars = RedisIndayBars(mod_config.redis_url)
                system_log.info(_("RealtimeTradeMod using market from redis"))
            else:
                raise RuntimeError(
                    "No Inday bar data source with valid config")
            data_source = RealtimeDataSource(inday_bars=inday_bars,
                                             hist_source=data_source)
        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 allowed it to be setted large than last trade date.
        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)
示例#59
0
 def check_is_instance_of(func_name, value):
     if not isinstance(value, types):
         raise RQInvalidArgument(
             _(u"function {}: invalid {} argument, expect a value of type {}, got {} (type: {})").format(
                 func_name, self._arg_name, types, value, type(value)
             ))
示例#60
0
 def raise_not_valid_future_error(self, func_name, arg_name, value):
     raise RQInvalidArgument(
         _(u"function {}: invalid {} argument, expect a valid future instrument/order_book_id/symbol, "
           u"got {} (type: {})").format(
             func_name, self._arg_name, value, type(value)
         ))