Exemplo n.º 1
0
def all_instruments(type=None, date=None):
    """
    获取某个国家市场的所有合约信息。使用者可以通过这一方法很快地对合约信息有一个快速了解,目前仅支持中国市场。

    :param str type: 需要查询合约类型,例如:type='CS'代表股票。默认是所有类型

    :param date: 查询时间点
    :type date: `str` | `datetime` | `date`


    :return: `pandas DataFrame` 所有合约的基本信息。

    其中type参数传入的合约类型和对应的解释如下:

    =========================   ===================================================
    合约类型                      说明
    =========================   ===================================================
    CS                          Common Stock, 即股票
    ETF                         Exchange Traded Fund, 即交易所交易基金
    LOF                         Listed Open-Ended Fund,即上市型开放式基金
    FenjiMu                     Fenji Mu Fund, 即分级母基金
    FenjiA                      Fenji A Fund, 即分级A类基金
    FenjiB                      Fenji B Funds, 即分级B类基金
    INDX                        Index, 即指数
    Future                      Futures,即期货,包含股指、国债和商品期货
    =========================   ===================================================

    :example:

    获取中国市场所有分级基金的基础信息:

    ..  code-block:: python3
        :linenos:

        [In]all_instruments('FenjiA')
        [Out]
            abbrev_symbol    order_book_id    product    sector_code  symbol
        0    CYGA    150303.XSHE    null    null    华安创业板50A
        1    JY500A    150088.XSHE    null    null    金鹰500A
        2    TD500A    150053.XSHE    null    null    泰达稳健
        3    HS500A    150110.XSHE    null    null    华商500A
        4    QSAJ    150235.XSHE    null    null    鹏华证券A
        ...

    """
    env = Environment.get_instance()
    if date is None:
        dt = env.trading_dt
    else:
        dt = pd.Timestamp(date).to_pydatetime()
        dt = min(dt, env.trading_dt)

    if type is not None:
        if isinstance(type, six.string_types):
            type = [type]

        types = set()
        for t in type:
            if t == 'Stock':
                types.add('CS')
            elif t == 'Fund':
                types.update(['ETF', 'LOF', 'SF', 'FenjiA', 'FenjiB', 'FenjiMu'])
            else:
                types.add(t)
    else:
        types = None

    result = env.data_proxy.all_instruments(types, dt)
    if types is not None and len(types) == 1:
        return pd.DataFrame([i._ins_dict for i in result])

    return pd.DataFrame(
        [[i.order_book_id, i.symbol, i.type, i.listed_date, i.de_listed_date] for i in result],
        columns=['order_book_id', 'symbol', 'type', 'listed_date', 'de_listed_date'])
Exemplo n.º 2
0
    def __init__(self, commission_multiplier):
        self.commission_multiplier = commission_multiplier
        self.hedge_type = HEDGE_TYPE.SPECULATION

        self.env = Environment.get_instance()
Exemplo n.º 3
0
 def config(self):
     return Environment.get_instance().config
Exemplo n.º 4
0
 def update_last_price(self):
     price = Environment.get_instance().get_last_price(self._order_book_id)
     if price == price:
         # 过滤掉 nan
         self._last_price = price
Exemplo n.º 5
0
 def _frozen_cash_of_order(order):
     order_cost = order.frozen_price * order.quantity if order.side == SIDE.BUY else 0
     return order_cost + Environment.get_instance(
     ).get_order_transaction_cost(DEFAULT_ACCOUNT_TYPE.STOCK, order)
Exemplo n.º 6
0
 def now(self):
     """
     [datetime.datetime] 当前 Bar 所对应的时间
     """
     return Environment.get_instance().calendar_dt
Exemplo n.º 7
0
 def __init__(self):
     self._set = set()
     Environment.get_instance().event_bus.prepend_listener(
         EVENT.AFTER_TRADING, self._clear_de_listed)
Exemplo n.º 8
0
def order(id_or_ins, amount, side, position_effect, style):
    if not isinstance(style, OrderStyle):
        raise RuntimeError
    if amount < 0:
        raise RuntimeError
    if amount == 0:
        user_system_log.warn(_(u"Order Creation Failed: Order amount is 0."))
        return None
    if isinstance(style, LimitOrder) and style.get_limit_price() <= 0:
        raise RQInvalidArgument(_(u"Limit order price should be positive"))

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

    price = env.get_last_price(order_book_id)
    if 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

    amount = int(amount)

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

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

    if 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 []

    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
Exemplo n.º 9
0
 def margin_rate(self):
     env = Environment.get_instance()
     margin_info = env.data_proxy.get_margin_info(self.order_book_id)
     margin_multiplier = env.config.base.margin_multiplier
     return margin_info['long_margin_ratio'] * margin_multiplier
Exemplo n.º 10
0
 def contract_multiplier(self):
     return Environment.get_instance().get_instrument(
         self.order_book_id).contract_multiplier
Exemplo n.º 11
0
 def _margin_of(self, quantity, price):
     env = Environment.get_instance()
     instrument = env.data_proxy.instruments(self.order_book_id)
     return quantity * instrument.contract_multiplier * price * self.margin_rate
Exemplo n.º 12
0
 def open_orders(self):
     return Environment.get_instance().broker.get_open_orders(
         self.order_book_id)
Exemplo n.º 13
0
 def _frozen_cash_of_order(order):
     order_cost = margin_of(
         order.order_book_id, order.quantity, order.frozen_price
     ) if order.position_effect == POSITION_EFFECT.OPEN else 0
     return order_cost + Environment.get_instance(
     ).get_order_transaction_cost(DEFAULT_ACCOUNT_TYPE.FUTURE, order)
Exemplo n.º 14
0
def now_time_str(str_format="%H:%M:%S"):
    return Environment.get_instance().trading_dt.strftime(str_format)
Exemplo n.º 15
0
 def register_event(self):
     event_bus = Environment.get_instance().event_bus
     event_bus.prepend_listener(EVENT.POST_SETTLEMENT,
                                lambda e: self._apply_settlement())
     event_bus.add_listener(EVENT.TRADE,
                            lambda e: self.apply_trade(e.trade))
Exemplo n.º 16
0
 def tick_size(self):
     return Environment.get_instance().data_proxy.get_tick_size(
         self.order_book_id)
Exemplo n.º 17
0
    def suspended(self):
        if self.isnan:
            return True

        return Environment.get_instance().data_proxy.is_suspended(self._instrument.order_book_id, int(self._data['datetime'] // 1000000))
Exemplo n.º 18
0
 def __init__(self):
     self._env = Environment.get_instance()
Exemplo n.º 19
0
 def items(self):
     return ((o, self.__getitem__(o)) for o in Environment.get_instance().get_universe())
Exemplo n.º 20
0
    def init_fixture(self):
        from rqrobot.utils import RqAttrDict
        from rqrobot.environment import Environment

        super(EnvironmentFixture, self).init_fixture()
        self.env = Environment(RqAttrDict(self.env_config))
Exemplo n.º 21
0
 def keys(self):
     return (o for o in Environment.get_instance().get_universe())
Exemplo n.º 22
0
 def run_info(self):
     """
     [:class:`~RunInfo`] 运行信息
     """
     config = Environment.get_instance().config
     return RunInfo(config)
Exemplo n.º 23
0
 def values(self):
     return (self.__getitem__(o) for o in Environment.get_instance().get_universe())
Exemplo n.º 24
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

    round_lot = int(env.get_instrument(order_book_id).round_lot)

    if side == SIDE.BUY or amount != env.portfolio.accounts[
        DEFAULT_ACCOUNT_TYPE.STOCK.name
    ].positions[order_book_id].sellable:
        # 一次性申报卖出时可以卖散股
        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
Exemplo n.º 25
0
 def __contains__(self, o):
     return o in Environment.get_instance().get_universe()
Exemplo n.º 26
0
def history_bars(order_book_id, bar_count, frequency, fields=None, skip_suspended=True,
                 include_now=False, adjust_type='pre'):
    """
    获取指定合约的历史行情,同时支持日以及分钟历史数据。不能在init中调用。 注意,该API会自动跳过停牌数据。

    日回测获取分钟历史数据:不支持

    日回测获取日历史数据

    =========================   ===================================================
    调用时间                      返回数据
    =========================   ===================================================
    T日before_trading            T-1日day bar
    T日handle_bar                T日day bar
    =========================   ===================================================

    分钟回测获取日历史数据

    =========================   ===================================================
    调用时间                      返回数据
    =========================   ===================================================
    T日before_trading            T-1日day bar
    T日handle_bar                T-1日day bar
    =========================   ===================================================

    分钟回测获取分钟历史数据

    =========================   ===================================================
    调用时间                      返回数据
    =========================   ===================================================
    T日before_trading            T-1日最后一个minute bar
    T日handle_bar                T日当前minute bar
    =========================   ===================================================

    :param order_book_id: 合约代码
    :type order_book_id: `str`

    :param int bar_count: 获取的历史数据数量,必填项
    :param str frequency: 获取数据什么样的频率进行。'1d'或'1m'分别表示每日和每分钟,必填项
    :param str fields: 返回数据字段。必填项。见下方列表。

    =========================   ===================================================
    fields                      字段名
    =========================   ===================================================
    datetime                    时间戳
    open                        开盘价
    high                        最高价
    low                         最低价
    close                       收盘价
    volume                      成交量
    total_turnover              成交额
    open_interest               持仓量(期货专用)
    basis_spread                期现差(股指期货专用)
    settlement                  结算价(期货日线专用)
    prev_settlement             结算价(期货日线专用)
    =========================   ===================================================

    :param bool skip_suspended: 是否跳过停牌数据
    :param bool include_now: 是否包含当前数据
    :param str adjust_type: 复权类型,默认为前复权 pre;可选 pre, none, post

    :return: `ndarray`, 方便直接与talib等计算库对接,效率较history返回的DataFrame更高。

    :example:

    获取最近5天的日线收盘价序列(策略当前日期为20160706):

    ..  code-block:: python3
        :linenos:

        [In]
        logger.info(history_bars('000002.XSHE', 5, '1d', 'close'))
        [Out]
        [ 8.69  8.7   8.71  8.81  8.81]
    """
    order_book_id = assure_order_book_id(order_book_id)
    env = Environment.get_instance()
    dt = env.calendar_dt

    if frequency[-1] not in {'m', 'd'}:
        raise RQInvalidArgument('invalid frequency {}'.format(frequency))

    if frequency[-1] == 'm' and env.config.base.frequency == '1d':
        raise RQInvalidArgument('can not get minute history in day back test')

    if frequency[-1] == 'd' and frequency != '1d':
        raise RQInvalidArgument('invalid frequency')

    if adjust_type not in {'pre', 'post', 'none'}:
        raise RuntimeError('invalid adjust_type')

    if frequency == '1d':
        sys_frequency = Environment.get_instance().config.base.frequency
        if ((
                sys_frequency in ['1m', 'tick'] and
                not include_now and
                ExecutionContext.phase() != EXECUTION_PHASE.AFTER_TRADING
        ) or (
                ExecutionContext.phase() == EXECUTION_PHASE.BEFORE_TRADING
        )):
            dt = env.data_proxy.get_previous_trading_date(env.trading_dt.date())
            # 当 EXECUTION_PHASE.BEFORE_TRADING 的时候,强制 include_now 为 False
            include_now = False
        if sys_frequency == "1d":
            # 日回测不支持 include_now
            include_now = False

    if fields is None:
        fields = ["datetime", "open", "high", "low", "close", "volume"]

    return env.data_proxy.history_bars(order_book_id, bar_count, frequency, fields, dt,
                                       skip_suspended=skip_suspended, include_now=include_now,
                                       adjust_type=adjust_type, adjust_orig=env.trading_dt)
Exemplo n.º 27
0
 def __len__(self):
     return len(Environment.get_instance().get_universe())
Exemplo n.º 28
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()
Exemplo n.º 29
0
 def _get_tax(self, order_book_id, side, cost_money):
     instrument = Environment.get_instance().get_instrument(order_book_id)
     if instrument.type != 'CS':
         return 0
     return cost_money * self.tax_rate if side == SIDE.SELL else 0