Exemplo n.º 1
0
def order_value(id_or_ins, cash_amount, price=None, style=None):
    # type: (Union[str, Instrument], float, Optional[float], Optional[OrderStyle]) -> Optional[Order]
    """
    使用想要花费的金钱买入/卖出股票,而不是买入/卖出想要的股数,正数代表买入,负数代表卖出。股票的股数总是会被调整成对应的100的倍数(在A中国A股市场1手是100股)。如果资金不足,该API将不会创建发送订单。

    需要注意:
    当您提交一个买单时,cash_amount 代表的含义是您希望买入股票消耗的金额(包含税费),最终买入的股数不仅和发单的价格有关,还和税费相关的参数设置有关。
    当您提交一个卖单时,cash_amount 代表的意义是您希望卖出股票的总价值。如果金额超出了您所持有股票的价值,那么您将卖出所有股票。

    :param id_or_ins: 下单标的物
    :param cash_amount: 需要花费现金购买/卖出证券的数目。正数代表买入,负数代表卖出。
    :param price: 下单价格,默认为None,表示 :class:`~MarketOrder`, 此参数主要用于简化 `style` 参数。
    :param style: 下单类型, 默认是市价单。目前支持的订单类型有 :class:`~LimitOrder` 和 :class:`~MarketOrder`

    :example:

    .. code-block:: python

        #花费最多¥10000买入平安银行股票,并以市价单发送。具体下单的数量与您策略税费相关的配置有关。
        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)
    return _order_value(order_book_id, cash_amount, style)
Exemplo n.º 2
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"))
Exemplo n.º 3
0
    def history_bars(self, instrument, bar_count, frequency, fields, dt,
                     skip_suspended=True, include_now=False,
                     adjust_type='pre', adjust_orig=None):
        if frequency != '1d':
            raise NotImplementedError

        if skip_suspended and instrument.type == 'CS':
            bars = self._filtered_day_bars(instrument)
        else:
            bars = self._all_day_bars_of(instrument)

        if not self._are_fields_valid(fields, bars.dtype.names):
            raise RQInvalidArgument("invalid fileds: {}".format(fields))

        if len(bars) <= 0:
            return bars

        dt = np.uint64(convert_date_to_int(dt))
        i = bars['datetime'].searchsorted(dt, side='right')
        left = i - bar_count if i >= bar_count else 0
        bars = bars[left:i]
        if adjust_type == 'none' or instrument.type in {'Future', 'INDX'}:
            # 期货及指数无需复权
            return bars if fields is None else bars[fields]

        if isinstance(fields, str) and fields not in FIELDS_REQUIRE_ADJUSTMENT:
            return bars if fields is None else bars[fields]

        return adjust_bars(bars, self.get_ex_cum_factor(instrument.order_book_id),
                           fields, adjust_type, adjust_orig)
Exemplo n.º 4
0
def index_components(order_book_id, date=None):
    # type: (str, Optional[Union[str, datetime.date]]) -> List[str]
    """
    获取某一指数的股票构成列表,也支持指数的历史构成查询。

    :param order_book_id: 指数代码,可传入order_book_id
    :param date: 查询日期,默认为策略当前日期。如指定,则应保证该日期不晚于策略当前日期
    :return: 构成该指数股票的 order_book_id

    :example:

    得到上证指数在策略当前日期的构成股票的列表:

    ..  code-block:: python3
        :linenos:

        index_components('000001.XSHG')
        #[Out]['600000.XSHG', '600004.XSHG', ...]
    """
    env = Environment.get_instance()
    dt = env.trading_dt.date()
    if date is None:
        date = dt
    else:
        date = to_date(date)
        if date > dt:
            raise RQInvalidArgument(
                _('in index_components, date {} is no earlier than test date {}'
                  ).format(date, dt))
    order_book_id = assure_order_book_id(order_book_id)
    return rqdatac.index_components(order_book_id, date=date)
Exemplo n.º 5
0
def _submit_order(ins, amount, side, position_effect, style, auto_switch_order_value):
    env = Environment.get_instance()
    if isinstance(style, LimitOrder):
        if style.get_limit_price() <= 0:
            raise RQInvalidArgument(_(u"Limit order price should be positive"))
    price = env.data_proxy.get_last_price(ins.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=ins.order_book_id))
        return
    if side == SIDE.BUY:
        round_lot = int(ins.round_lot)
        amount = int(Decimal(amount) / Decimal(round_lot)) * round_lot
    if amount == 0:
        user_system_log.warn(_(u"Order Creation Failed: 0 order quantity"))
        return
    order = Order.__from_create__(ins.order_book_id, abs(amount), side, style, position_effect)
    if order.type == ORDER_TYPE.MARKET:
        order.set_frozen_price(price)
    if side == SIDE.BUY and auto_switch_order_value:
        account, position, ins = _get_account_position_ins(ins)
        if not is_cash_enough(env, order, account):
            user_system_log.warn(_(
                "insufficient cash, use all remaining cash({}) to create order"
            ).format(account.cash))
            return _order_value(account, position, ins, account.cash, style)
    if env.can_submit_order(order):
        env.broker.submit_order(order)
        return order
Exemplo n.º 6
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)
Exemplo n.º 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 | 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)
Exemplo n.º 8
0
def assure_instrument(id_or_ins):
    if isinstance(id_or_ins, Instrument):
        return id_or_ins
    elif isinstance(id_or_ins, six.string_types):
        return Environment.get_instance().data_proxy.instruments(id_or_ins)
    else:
        raise RQInvalidArgument(_(u"unsupported order_book_id type"))
Exemplo n.º 9
0
 def _is_number(self, func_name, value):
     try:
         v = float(value)
     except (ValueError, TypeError):
         raise RQInvalidArgument(
             _(u"function {}: invalid {} argument, expect a number, got {} (type: {})"
               ).format(func_name, self._arg_name, value, type(value)))
Exemplo n.º 10
0
 def get_trading_calendar(self, market=MARKET.CN):
     try:
         return self._multiple_market_trading_dates[
             market].get_trading_calendar()
     except KeyError:
         raise RQInvalidArgument(
             _("Unsupported such market type: {}".format(market)))
Exemplo n.º 11
0
def order_percent(id_or_ins, percent, price=None, style=None):
    # type: (Union[str, Instrument], float, Optional[float], Optional[OrderStyle]) -> Optional[Order]
    """
    发送一个花费价值等于目前投资组合(市场价值和目前现金的总和)一定百分比现金的买/卖单,正数代表买,负数代表卖。股票的股数总是会被调整成对应的一手的股票数的倍数(1手是100股)。百分比是一个小数,并且小于或等于1(<=100%),0.5表示的是50%.需要注意,如果资金不足,该API将不会创建发送订单。

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

    :param id_or_ins: 下单标的物
    :param percent: 占有现有的投资组合价值的百分比。正数表示买入,负数表示卖出。
    :param price: 下单价格,默认为None,表示 :class:`~MarketOrder`, 此参数主要用于简化 `style` 参数。
    :param style: 下单类型, 默认是市价单。目前支持的订单类型有 :class:`~LimitOrder` 和 :class:`~MarketOrder`

    :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)
Exemplo n.º 12
0
def order_shares(id_or_ins, amount, price=None, style=None):
    # type: (Union[str, Instrument], int, Optional[float], Optional[OrderStyle]) -> Optional[Order]
    """
    指定股数的买/卖单,最常见的落单方式之一。如有需要落单类型当做一个参量传入,如果忽略掉落单类型,那么默认是市价单(market order)。

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

    :example:

    .. code-block:: python

        #购买Buy 2000 股的平安银行股票,并以市价单发送:
        order_shares('000001.XSHE', 2000)
        #卖出2000股的平安银行股票,并以市价单发送:
        order_shares('000001.XSHE', -2000)
        #购买1000股的平安银行股票,并以限价单发送,价格为¥10:
        order_shares('000001.XSHG', 1000, style=LimitOrder(10))
    """
    if amount == 0:
        # 如果下单量为0,则认为其并没有发单,则直接返回None
        user_system_log.warn(_(u"Order Creation Failed: Order amount is 0."))
        return None
    style = cal_style(price, style)
    if isinstance(style, LimitOrder):
        if style.get_limit_price() <= 0:
            raise RQInvalidArgument(_(u"Limit order price should be positive"))
    order_book_id = assure_stock_order_book_id(id_or_ins)
    auto_switch_order_value = Environment.get_instance().config.mod.sys_accounts.auto_switch_order_value
    return _order_shares(order_book_id, amount, style, auto_switch_order_value)
Exemplo n.º 13
0
def get_fundamentals(query,
                     entry_date=None,
                     interval='1d',
                     report_quarter=False,
                     expect_df=False,
                     **kwargs):
    global _get_fundamentals_warning_fired
    if not _get_fundamentals_warning_fired:
        user_log.warn('get_fundamentals is deprecated, use get_factor instead')
        _get_fundamentals_warning_fired = True

    env = Environment.get_instance()
    dt = env.calendar_dt.date()
    if entry_date is None and 'date' in kwargs:
        entry_date = kwargs.pop('date')
    if kwargs:
        raise RQInvalidArgument('unknown arguments: {}'.format(kwargs))

    latest_query_day = dt - datetime.timedelta(days=1)

    if entry_date:
        entry_date = to_date(entry_date)
        if entry_date <= latest_query_day:
            query_date = entry_date
        else:
            raise RQInvalidArgument(
                _('in get_fundamentals entry_date {} is no earlier than test date {}'
                  ).format(entry_date, dt))
    else:
        query_date = latest_query_day

    result = rqdatac.get_fundamentals(query,
                                      query_date,
                                      interval,
                                      report_quarter=report_quarter,
                                      expect_df=expect_df)
    if result is None:
        return pd.DataFrame()

    if expect_df:
        return result

    if len(result.major_axis) == 1:
        frame = result.major_xs(result.major_axis[0])
        # research 与回测返回的Frame维度相反
        return frame.T
    return result
Exemplo n.º 14
0
def assure_stock_order_book_id(id_or_symbols):
    if isinstance(id_or_symbols, Instrument):
        order_book_id = id_or_symbols.order_book_id
        """
        这所以使用XSHG和XSHE来判断是否可交易是因为股票类型策略支持很多种交易类型,比如CS, ETF, LOF, FenjiMU, FenjiA, FenjiB,
        INDX等,但实际其中部分由不能交易,所以不能直接按照类型区分该合约是否可以交易。而直接通过判断其后缀可以比较好的区分是否可以进行交易
        """
        if "XSHG" in order_book_id or "XSHE" in order_book_id or "INDX" in order_book_id:
            return order_book_id
        else:
            raise RQInvalidArgument(
                _(u"{order_book_id} is not supported in current strategy type"
                  ).format(order_book_id=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"))
Exemplo n.º 15
0
 def _are_valid_query_entities(self, func_name, entities):
     from sqlalchemy.orm.attributes import InstrumentedAttribute
     for e in entities:
         if not isinstance(e, InstrumentedAttribute):
             raise RQInvalidArgument(
                 _(u"function {}: invalid {} argument, should be entity like "
                   u"Fundamentals.balance_sheet.total_equity, got {} (type: {})"
                   ).format(func_name, self.arg_name, e, type(e)))
Exemplo n.º 16
0
def assure_order_book_id(id_or_ins):
    if isinstance(id_or_ins, Instrument):
        order_book_id = id_or_ins.order_book_id
    elif isinstance(id_or_ins, six.string_types):
        order_book_id = instruments(id_or_ins).order_book_id
    else:
        raise RQInvalidArgument(_(u"unsupported order_book_id type"))

    return order_book_id
Exemplo n.º 17
0
        def check_is_in(func_name, value):
            if ignore_none and value is None:
                return

            if value not in valid_values:
                raise RQInvalidArgument(
                    _(u"function {}: invalid {} argument, valid: {}, got {} (type: {})").format(
                        func_name, self._arg_name, repr(valid_values), value, type(value))
                )
Exemplo n.º 18
0
        def check_is_valid_date(func_name, value):
            if ignore_none and value is None:
                return None
            if isinstance(value, (datetime.date, pd.Timestamp)):
                return
            if isinstance(value, six.string_types):
                try:
                    v = parse_date(value)
                    return
                except ValueError:
                    raise RQInvalidArgument(
                        _(u"function {}: invalid {} argument, expect a valid date, got {} (type: {})"
                          ).format(func_name, self._arg_name, value,
                                   type(value)))

            raise RQInvalidArgument(
                _(u"function {}: invalid {} argument, expect a valid date, got {} (type: {})"
                  ).format(func_name, self._arg_name, value, type(value)))
Exemplo n.º 19
0
def order_target_percent(id_or_ins, percent, price=None, style=None):
    """
    买入/卖出证券以自动调整该证券的仓位到占有一个指定的投资组合的目标百分比。

    *   如果投资组合中没有任何该证券的仓位,那么会买入等于现在投资组合总价值的目标百分比的数目的证券。
    *   如果投资组合中已经拥有该证券的仓位,那么会买入/卖出目标百分比和现有百分比的差额数目的证券,最终调整该证券的仓位占据投资组合的比例至目标百分比。

    其实我们需要计算一个position_to_adjust (即应该调整的仓位)

    `position_to_adjust = target_position - current_position`

    投资组合价值等于所有已有仓位的价值和剩余现金的总和。买/卖单会被下舍入一手股数(A股是100的倍数)的倍数。目标百分比应该是一个小数,并且最大值应该<=1,比如0.5表示50%。

    如果position_to_adjust 计算之后是正的,那么会买入该证券,否则会卖出该证券。 需要注意,如果资金不足,该API将不会创建发送订单。

    :param id_or_ins: 下单标的物
    :type id_or_ins: :class:`~Instrument` object | `str` | List[:class:`~Instrument`] | List[`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

        #如果投资组合中已经有了平安银行股票的仓位,并且占据目前投资组合的10%的价值,那么以下代码会买入平安银行股票最终使其占据投资组合价值的15%:
        order_target_percent('000001.XSHE', 0.15)
    """
    if percent < 0 or percent > 1:
        raise RQInvalidArgument(_(u"percent should between 0 and 1"))
    order_book_id = assure_stock_order_book_id(id_or_ins)

    style = cal_style(price, style)

    account = Environment.get_instance().portfolio.accounts[
        DEFAULT_ACCOUNT_TYPE.STOCK.name]
    position = account.positions[order_book_id]

    if percent == 0:
        return _sell_all_stock(order_book_id, position.sellable, style)

    try:
        market_value = position.market_value
    except RuntimeError:
        order_result = order_value(order_book_id, np.nan, style=style)
        if order_result:
            raise
    else:
        return order_value(order_book_id,
                           account.total_value * percent - market_value,
                           style=style)
Exemplo n.º 20
0
 def rq_invalid_argument(arg):
     if registry:
         return RQInvalidArgument(_(
             u"function {}: invalid {} argument, "
             u"expected an order_book_id or instrument with types {}, got {} (type: {})"
         ).format(funcname, argname, [getattr(i, "name", str(i)) for i in registry], arg, type(arg)))
     else:
         return RQApiNotSupportedError(_(
             "function {} is not supported, please check your account or mod config"
         ).format(funcname))
Exemplo n.º 21
0
def to_date(date):
    if isinstance(date, datetime.datetime):
        return date.date()
    if isinstance(date, datetime.date):
        return date

    if isinstance(date, str):
        return parse(date).date()

    raise RQInvalidArgument('unknown date value: {}'.format(date))
Exemplo n.º 22
0
def to_date(date):
    # type: (Union[str, datetime.date, datetime.datetime]) -> datetime.date
    if isinstance(date, six.string_types):
        return parse(date).date()
    elif isinstance(date, datetime.date):
        return date
    elif isinstance(date, datetime.datetime):
        return date.date()
    else:
        raise RQInvalidArgument("unknown date value: {}".format(date))
Exemplo n.º 23
0
def get_dividend(order_book_id, start_date):
    # type: (str, Union[str, datetime.date, datetime.datetime, pd.Timestamp]) -> Optional[np.ndarray]
    """
    获取某只股票到策略当前日期前一天的分红情况(包含起止日期)。

    :param order_book_id: 股票代码
    :param start_date: 开始日期,需要早于策略当前日期

    =========================   ===================================================
    fields                      字段名
    =========================   ===================================================
    announcement_date           分红宣布日
    book_closure_date           股权登记日
    dividend_cash_before_tax    税前分红
    ex_dividend_date            除权除息日
    payable_date                分红到帐日
    round_lot                   分红最小单位
    =========================   ===================================================

    :example:

    获取平安银行2013-01-04 到策略当前日期前一天的分红数据:

    ..  code-block:: python3
        :linenos:

        get_dividend('000001.XSHE', start_date='20130104')
        #[Out]
        #array([(20130614, 20130619, 20130620, 20130620,  1.7 , 10),
        #       (20140606, 20140611, 20140612, 20140612,  1.6 , 10),
        #       (20150407, 20150410, 20150413, 20150413,  1.74, 10),
        #       (20160608, 20160615, 20160616, 20160616,  1.53, 10)],
        #      dtype=[('announcement_date', '<u4'), ('book_closure_date', '<u4'), ('ex_dividend_date', '<u4'), ('payable_date', '<u4'), ('dividend_cash_before_tax', '<f8'), ('round_lot', '<u4')])

    """
    # adjusted 参数在不复权数据回测时不再提供
    env = Environment.get_instance()
    dt = env.trading_dt.date() - datetime.timedelta(days=1)
    start_date = to_date(start_date)
    if start_date > dt:
        raise RQInvalidArgument(
            _(
                u"in get_dividend, start_date {} is later than the previous test day {}"
            ).format(start_date, dt)
        )
    order_book_id = assure_stock_order_book_id(order_book_id)
    array = env.data_proxy.get_dividend(order_book_id)
    if array is None:
        return None

    sd = start_date.year * 10000 + start_date.month * 100 + start_date.day
    ed = dt.year * 10000 + dt.month * 100 + dt.day
    return array[
        (array["announcement_date"] >= sd) & (array["announcement_date"] <= ed)
    ]
Exemplo n.º 24
0
def get_pit_financials(fields,
                       quarter=None,
                       interval=None,
                       order_book_ids=None,
                       if_adjusted='all'):
    if quarter is None:
        valid = True
    else:
        valid = isinstance(quarter, six.string_types) and quarter[-2] == 'q'
        if valid:
            try:
                valid = 1990 <= int(quarter[:-2]) <= 2050 and 1 <= int(
                    quarter[-1]) <= 4
            except ValueError:
                valid = False
    if not valid:
        raise RQInvalidArgument(
            _(u"function {}: invalid {} argument, quarter should be in form of '2012q3', "
              u"got {} (type: {})").format('get_pit_financials', 'quarter',
                                           quarter, type(quarter)))

    env = Environment.get_instance()
    dt = env.calendar_dt.date()
    year = dt.year
    mon = dt.month
    day = dt.day
    int_date = year * 10000 + mon * 100 + day
    q = (mon - 4) // 3 + 1
    y = year
    if q <= 0:
        y -= 1
        q = 4
    default_quarter = str(y) + 'q' + str(q)
    if quarter is None or quarter > default_quarter:
        quarter = default_quarter
    result = rqdatac.get_pit_financials(fields,
                                        quarter,
                                        interval,
                                        order_book_ids,
                                        if_adjusted,
                                        max_info_date=int_date,
                                        market='cn')
    if result is None:
        return pd.DataFrame()

    if if_adjusted == 'ignore':
        result = result.reset_index().sort_values('info_date')
        result = result.groupby(['order_book_id', 'end_date'],
                                as_index=False).fillna(method='ffill')
        result = result.drop(['info_date', 'if_adjusted'], axis=1)
        result = result.drop_duplicates(['order_book_id', 'end_date'],
                                        keep='last')
        result = result.set_index(['order_book_id', 'end_date']).sort_index()
    return result
Exemplo n.º 25
0
def cal_style(price, style):
    if price is None and style is None:
        return MarketOrder()

    if style is not None:
        if not isinstance(style, OrderStyle):
            raise RuntimeError
        return style

    if isinstance(price, OrderStyle):
        # 为了 order_xxx('RB1710', 10, MarketOrder()) 这种写法
        if isinstance(price, LimitOrder):
            if np.isnan(price.get_limit_price()):
                raise RQInvalidArgument(_(u"Limit order price should not be nan."))
        return price

    if np.isnan(price):
        raise RQInvalidArgument(_(u"Limit order price should not be nan."))

    return LimitOrder(price)
Exemplo n.º 26
0
def to_date(date):
    if isinstance(date, six.string_types):
        return parse(date).date()

    if isinstance(date, datetime.datetime):
        try:
            return date.date()
        except AttributeError:
            return date

    raise RQInvalidArgument("unknown date value: {}".format(date))
Exemplo n.º 27
0
 def _are_valid_instruments(self, func_name, values):
     if isinstance(values, (six.string_types, Instrument)):
         self._is_valid_instrument(func_name, values)
     elif isinstance(values, list):
         for v in values:
             self._is_valid_instrument(func_name, v)
     else:
         raise RQInvalidArgument(
             _(u"function {}: invalid {} argument, expect a string or a list of string, got {} (type: {})"
               ).format(func_name, self._arg_name, repr(values),
                        type(values)))
Exemplo n.º 28
0
    def _is_valid_frequency(self, func_name, value):
        valid = isinstance(value, six.string_types) and value[-1] in ("d", "m")
        if valid:
            try:
                valid = int(value[:-1]) > 0
            except (ValueError, TypeError):
                valid = False

        if not valid:
            raise RQInvalidArgument(
                _(u"function {}: invalid {} argument, frequency should be in form of "
                  u"'1m', '5m', '1d', got {} (type: {})").format(
                      func_name, self.arg_name, value, type(value)))
Exemplo n.º 29
0
    def _is_valid_interval(self, func_name, value):
        valid = isinstance(value, six.string_types) and value[-1] in {'d', 'm', 'q', 'y'}
        if valid:
            try:
                valid = int(value[:-1]) > 0
            except (ValueError, TypeError):
                valid = False

        if not valid:
            raise RQInvalidArgument(
                _(u"function {}: invalid {} argument, interval should be in form of '1d', '3m', '4q', '2y', "
                  u"got {} (type: {})").format(
                    func_name, self.arg_name, value, type(value)
                ))
Exemplo n.º 30
0
        def check_is_valid_instrument(func_name, value):
            instrument = None
            if isinstance(value, six.string_types):
                instrument = Environment.get_instance().get_instrument(value)
            elif isinstance(value, Instrument):
                instrument = value

            if instrument is None:
                self.raise_invalid_instrument_error(func_name, value)
            if valid_instrument_types and instrument.type not in valid_instrument_types:
                raise RQInvalidArgument(
                    _(u"function {}: invalid {} argument, expected instrument with types {}, got instrument with type {}"
                      ).format(func_name, self._arg_name,
                               valid_instrument_types, instrument.type))
            return instrument