Example #1
0
 def _before_trading(self, event):
     trading_date = Environment.get_instance().trading_dt.date()
     last_date = Environment.get_instance(
     ).data_proxy.get_previous_trading_date(trading_date)
     self._handle_dividend_book_closure(last_date)
     self._handle_dividend_payable(trading_date)
     self._handle_split(trading_date)
Example #2
0
 def update(self, universe):
     if isinstance(universe, (six.string_types, Instrument)):
         universe = [universe]
     new_set = set(universe)
     if new_set != self._set:
         self._set = new_set
         Environment.get_instance().event_bus.publish_event(
             Event(EVENT.POST_UNIVERSE_CHANGED, universe=self._set))
Example #3
0
def plot(series_name, value):
    """
    Add a point to custom series.
    :param str series_name: the name of custom series
    :param float value: the value of the series in this time
    :return: None
    """
    Environment.get_instance().add_plot(series_name, value)
Example #4
0
    def init(self):
        if not self._init:
            return

        with ExecutionContext(EXECUTION_PHASE.ON_INIT):
            with ModifyExceptionFromType(EXC_TYPE.USER_EXC):
                self._init(self._user_context)

        Environment.get_instance().event_bus.publish_event(Event(EVENT.POST_USER_INIT))
Example #5
0
 def annualized_returns(self):
     """
     [float] 累计年化收益率
     """
     current_date = Environment.get_instance().trading_dt.date()
     natural_start_date = Environment.get_instance(
     ).config.base.natural_start_date
     return self.unit_net_value**(DAYS_CNT.DAYS_A_YEAR / float(
         (current_date - natural_start_date).days + 1)) - 1
Example #6
0
 def is_de_listed(self):
     """
     判断合约是否过期
     """
     instrument = Environment.get_instance().get_instrument(
         self._order_book_id)
     current_date = Environment.get_instance().trading_dt
     if instrument.de_listed_date is not None and current_date >= instrument.de_listed_date:
         return True
     return False
Example #7
0
def update_universe(id_or_symbols):
    """
    该方法用于更新现在关注的证券的集合(e.g.:股票池)。PS:会在下一个bar事件触发时候产生(新的关注的股票池更新)效果。并且update_universe会是覆盖(overwrite)的操作而不是在已有的股票池的基础上进行增量添加。比如已有的股票池为['000001.XSHE', '000024.XSHE']然后调用了update_universe(['000030.XSHE'])之后,股票池就会变成000030.XSHE一个股票了,随后的数据更新也只会跟踪000030.XSHE这一个股票了。

    :param id_or_ins: 标的物
    :type id_or_ins: :class:`~Instrument` object | `str` | List[:class:`~Instrument`] | List[`str`]
    """
    if isinstance(id_or_symbols, (six.string_types, Instrument)):
        id_or_symbols = [id_or_symbols]
    order_book_ids = set(assure_order_book_id(order_book_id) for order_book_id in id_or_symbols)
    if order_book_ids != Environment.get_instance().get_universe():
        Environment.get_instance().update_universe(order_book_ids)
Example #8
0
def is_suspended(order_book_id, count=1):
    """
    判断某只股票是否全天停牌。

    :param str order_book_id: 某只股票的代码或股票代码,可传入单只股票的order_book_id, symbol

    :param int count: 回溯获取的数据个数。默认为当前能够获取到的最近的数据

    :return: count为1时 `bool`; count>1时 `pandas.DataFrame`
    """
    dt = Environment.get_instance().calendar_dt.date()
    order_book_id = assure_stock_order_book_id(order_book_id)
    return Environment.get_instance().data_proxy.is_suspended(order_book_id, dt, count)
Example #9
0
    def prev_settlement(self):
        """
        [float] 昨日结算价(期货专用)
        """
        try:
            return self._data['prev_settlement']
        except (ValueError, KeyError):
            pass

        if self._prev_settlement is None:
            trading_dt = Environment.get_instance().trading_dt
            data_proxy = Environment.get_instance().data_proxy
            self._prev_settlement = data_proxy.get_prev_settlement(self._instrument.order_book_id, trading_dt)
        return self._prev_settlement
Example #10
0
    def prev_close(self):
        """
        [float] 截止到当前的最低价
        """
        try:
            return self._data['prev_close']
        except (ValueError, KeyError):
            pass

        if self._prev_close is None:
            trading_dt = Environment.get_instance().trading_dt
            data_proxy = Environment.get_instance().data_proxy
            self._prev_close = data_proxy.get_prev_close(self._instrument.order_book_id, trading_dt)
        return self._prev_close
Example #11
0
def is_st_stock(order_book_id, count=1):
    """
    判断股票在一段时间内是否为ST股(包括ST与*ST)。

    ST股是有退市风险因此风险比较大的股票,很多时候您也会希望判断自己使用的股票是否是'ST'股来避开这些风险大的股票。另外,我们目前的策略比赛也禁止了使用'ST'股。

    :param str order_book_id: 某只股票的代码,可传入单只股票的order_book_id, symbol

    :param int count: 回溯获取的数据个数。默认为当前能够获取到的最近的数据

    :return: count为1时 `bool`; count>1时 `pandas.DataFrame`
    """
    dt = Environment.get_instance().calendar_dt.date()
    order_book_id = assure_stock_order_book_id(order_book_id)
    return Environment.get_instance().data_proxy.is_st_stock(order_book_id, dt, count)
Example #12
0
    def basis_spread(self):
        try:
            return self._data['basis_spread']
        except (ValueError, KeyError):
            if self._instrument.type != 'Future' or Environment.get_instance().config.base.run_type != RUN_TYPE.PAPER_TRADING:
                raise

        if self._basis_spread is None:
            if self._instrument.underlying_symbol in ['IH', 'IC', 'IF']:
                order_book_id = self.INDEX_MAP[self._instrument.underlying_symbol]
                bar = Environment.get_instance().data_proxy.get_bar(order_book_id, None, '1m')
                self._basis_spread = self.close - bar.close
            else:
                self._basis_spread = np.nan
        return self._basis_spread
Example #13
0
def margin_of(order_book_id, quantity, price):
    env = Environment.get_instance()
    margin_info = env.data_proxy.get_margin_info(order_book_id)
    margin_multiplier = env.config.base.margin_multiplier
    margin_rate = margin_info['long_margin_ratio'] * margin_multiplier
    contract_multiplier = env.get_instrument(order_book_id).contract_multiplier
    return quantity * contract_multiplier * price * margin_rate
Example #14
0
 def register_event(self):
     event_bus = Environment.get_instance().event_bus
     event_bus.prepend_listener(EVENT.SETTLEMENT, self._on_settlement)
     event_bus.prepend_listener(EVENT.PRE_BEFORE_TRADING,
                                self._before_trading)
     event_bus.prepend_listener(EVENT.PRE_BAR, self._on_bar)
     event_bus.prepend_listener(EVENT.TICK, self._on_tick)
Example #15
0
    def __init__(self, order_book_id, tick):
        system_log.warn("[deprecated] Tick class is no longer used. use TickObject class instead.")
        try:
            tick["asks"] = tick["ask"]
        except KeyError:
            pass

        try:
            tick["bids"] = tick["bid"]
        except KeyError:
            pass

        try:
            tick["ask_vols"] = tick["ask_vol"]
        except KeyError:
            pass

        try:
            tick["bid_vols"] = tick["bid_vol"]
        except KeyError:
            pass

        super(Tick, self).__init__(
            instrument=Environment.get_instance().data_proxy.instruments(order_book_id),
            tick_dict=tick
        )
Example #16
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
Example #17
0
 def __from_create__(cls, order_book_id, quantity, side, style, position_effect):
     env = Environment.get_instance()
     order = cls()
     order._order_id = next(order.order_id_gen)
     order._calendar_dt = env.calendar_dt
     order._trading_dt = env.trading_dt
     order._quantity = quantity
     order._order_book_id = order_book_id
     order._side = side
     order._position_effect = position_effect
     order._message = ""
     order._filled_quantity = 0
     order._status = ORDER_STATUS.PENDING_NEW
     if isinstance(style, LimitOrder):
         if env.config.base.round_price:
             tick_size = env.data_proxy.get_tick_size(order_book_id)
             style.round_price(tick_size)
         order._frozen_price = style.get_limit_price()
         order._type = ORDER_TYPE.LIMIT
     else:
         order._frozen_price = 0.
         order._type = ORDER_TYPE.MARKET
     order._avg_price = 0
     order._transaction_cost = 0
     return order
Example #18
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):
     env = Environment.get_instance()
     trade = cls()
     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 if trade_id is not None else next(
         trade.trade_id_gen)
     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
Example #19
0
def order_lots(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

        #买入20手的平安银行股票,并且发送市价单:
        order_lots('000001.XSHE', 20)
        #买入10手平安银行股票,并且发送限价单,价格为¥10:
        order_lots('000001.XSHE', 10, style=LimitOrder(10))

    """
    order_book_id = assure_stock_order_book_id(id_or_ins)

    round_lot = int(Environment.get_instance().get_instrument(order_book_id).round_lot)

    style = cal_style(price, style)

    return order_shares(id_or_ins, amount * round_lot, style=style)
Example #20
0
 def wrapper(*args, **kwargs):
     if not Environment.get_instance().config.extra.is_hold:
         return func(*args, **kwargs)
     else:
         system_log.debug(
             _(u"not run {}({}, {}) because strategy is hold").format(
                 func, args, kwargs))
Example #21
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 | None

    :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)
Example #22
0
    def listing(self):
        """
        [bool] 该合约当前日期是否在交易
        """

        now = Environment.get_instance().calendar_dt
        return self.listed_date <= now <= self.de_listed_date
Example #23
0
def _validate_benchmark(config, data_proxy):
    benchmark = config.base.benchmark
    if benchmark is None:
        return
    instrument = data_proxy.instruments(benchmark)
    if instrument is None:
        raise patch_user_exc(
            ValueError(_(u"invalid benchmark {}").format(benchmark)))

    if instrument.order_book_id == "000300.XSHG":
        # 000300.XSHG 数据进行了补齐,因此认为只要benchmark设置了000300.XSHG,就存在数据,不受限于上市日期。
        return
    config = Environment.get_instance().config
    start_date = config.base.start_date
    end_date = config.base.end_date
    if instrument.listed_date.date() > start_date:
        raise patch_user_exc(
            ValueError(
                _(u"benchmark {benchmark} has not been listed on {start_date}"
                  ).format(benchmark=benchmark, start_date=start_date)))
    if instrument.de_listed_date.date() < end_date:
        raise patch_user_exc(
            ValueError(
                _(u"benchmark {benchmark} has been de_listed on {end_date}").
                format(benchmark=benchmark, end_date=end_date)))
Example #24
0
def industry(code):
    if not isinstance(code, six.string_types):
        code = code.code
    else:
        code = to_industry_code(code)

    return Environment.get_instance().data_proxy.industry(code)
Example #25
0
    def __init__(self, commission_rate, commission_multiplier, min_commission):
        self.commission_rate = commission_rate
        self.commission_multiplier = commission_multiplier
        self.commission_map = defaultdict(lambda: min_commission)
        self.min_commission = min_commission

        self.env = Environment.get_instance()
Example #26
0
def sector(code):
    if not isinstance(code, six.string_types):
        code = code.name
    else:
        code = to_sector_name(code)

    return Environment.get_instance().data_proxy.sector(code)
Example #27
0
def get_open_orders():
    """
    获取当日未成交订单数据

    :return: List[:class:`~Order` object]
    """
    return Environment.get_instance().broker.get_open_orders()
Example #28
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 | None

    :example:

    .. code-block:: python

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

    """

    style = cal_style(price, style)

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

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

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

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

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

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

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

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

    return order_shares(order_book_id, amount, style=style)
Example #29
0
    def days_to_expire(self):
        if self.type != 'Future' or self.order_book_id[
                -2:] == '88' or self.order_book_id[-2:] == '99':
            return -1

        date = Environment.get_instance().trading_dt.date()
        days = (self.maturity_date.date() - date).days
        return -1 if days < 0 else days
Example #30
0
 def _handle_split(self, trading_date):
     data_proxy = Environment.get_instance().data_proxy
     for order_book_id, position in six.iteritems(self._positions):
         ratio = data_proxy.get_split_by_ex_date(order_book_id,
                                                 trading_date)
         if ratio is None:
             continue
         position.split_(ratio)