Пример #1
0
def ensure_dates_base_on_listed_date(instrument, start_date, end_date, market):
    from rqdatac.services.calendar import get_previous_trading_date, get_latest_trading_date
    if to_date(instrument.listed_date) > datetime.date.today():
        raise ValueError("instrument {} is not listed yet".format(
            instrument.order_book_id))

    if start_date is None:
        start_date = instrument.listed_date
    elif to_date(start_date) < to_date(instrument.listed_date):
        start_date = to_date(instrument.listed_date)
    elif instrument.de_listed_date != "0000-00-00" and to_date(
            start_date) >= to_date(instrument.de_listed_date):
        warnings.warn("{} has been delisted on {}".format(
            instrument.order_book_id, instrument.de_listed_date))
        return None, None

    if end_date is None:
        if instrument.de_listed_date != "0000-00-00":
            end_date = get_previous_trading_date(instrument.de_listed_date,
                                                 market=market)
        else:
            end_date = get_latest_trading_date(market=market)
    elif instrument.de_listed_date != "0000-00-00" and to_date(
            end_date) >= to_date(instrument.de_listed_date):
        warnings.warn("{} has been delisted on {}".format(
            instrument.order_book_id, instrument.de_listed_date))
        end_date = get_previous_trading_date(instrument.de_listed_date,
                                             market=market)
    return start_date, end_date
Пример #2
0
def current_minute(order_book_ids, skip_suspended=False, fields=None, market="cn"):
    """获取实时分钟行情
    :param order_book_ids: 合约代码或代码列表
    :param skip_suspended: 是否过滤停复牌. (Default value = False)
    :param fields: 可选参数。默认为所有字段。 (Default value = None)
    :param market: 地区代码, 如'cn' (Default value = "cn")
    :returns: None or pd.DataFrame
    """
    from rqdatac.services.get_price import classify_order_book_ids, _ensure_fields
    from rqdatac.services.detail.get_price_df import MINBAR_FIELDS

    (order_book_ids, stocks, funds, indexes, futures, futures888, spots, options,
        convertibles, repos) = classify_order_book_ids(order_book_ids, market)
    if skip_suspended and stocks:
        date = get_previous_trading_date(datetime.date.today() + datetime.timedelta(days=1))
        df_suspended = is_suspended(stocks, date, date)
        if not df_suspended.empty:
            df_suspended_t = df_suspended.T
            suspended_obids = set(df_suspended_t[df_suspended_t[df_suspended_t.columns[0]]].index)
            inspection = suspended_obids & set(stocks)
            if inspection:
                stocks = set(stocks) - inspection
                order_book_ids = list(set(order_book_ids) - inspection)

    fields, _ = _ensure_fields(fields, MINBAR_FIELDS, stocks, funds, futures, futures888, spots, options, convertibles, indexes, repos)

    data = get_client().execute("current_minute", order_book_ids, fields + ["datetime"], market=market)
    if not data:
        return
    df = pd.DataFrame(data)
    df["datetime"] = df["datetime"].map(int14_to_datetime, na_action="ignore")
    df.set_index(["order_book_id", "datetime"], inplace=True)
    return df
Пример #3
0
def get_ksh_tickbar(order_book_id, start_date, end_date, fields, market):
    order_book_id = ensure_order_book_id(order_book_id)
    start_date, end_date = ensure_date_range(start_date, end_date, datetime.timedelta(days=3))
    data = get_client().execute(
        "get_ksh_tickbar", order_book_id, start_date, end_date, fields, market
    )
    today = today_int()
    if data:
        data = [(obid, {k: np.frombuffer(*v) for k, v in d.items()}) for obid, d in data]
        df_list = []
        for obid, d in data:
            df = pd.DataFrame(d)
            df_list.append(df)

        df = pd.concat(df_list)  # type: pd.DataFrame
        df["datetime"] = int17_to_datetime_v(df["datetime"].values)
        history_latest_date = date_to_int8(df.iloc[-1]["datetime"])
        df.set_index("datetime", inplace=True)
    else:
        df = None
        history_latest_date = date_to_int8(get_previous_trading_date(today, market=market))

    if history_latest_date >= end_date or start_date > today or history_latest_date >= today:
        return df

    live_df = get_today_ksh_tick(order_book_id, today, fields, market=market)
    if live_df is None:
        return df
    if df is None:
        return live_df
    return pd.concat([df, live_df])
Пример #4
0
def get_ksh_minbar(order_book_ids, start_date, end_date, fields, duration, market):
    data = get_client().execute(
        "get_ksh_minbar", order_book_ids, start_date, end_date, fields, duration, market
    )
    if data:
        data = [(obid, {k: np.frombuffer(*v) for k, v in d.items()}) for obid, d in data]
        df = convert_bar_to_multi_df(data, 'datetime', fields, int14_to_datetime_v)
    else:
        df = None

    today = today_int()
    if df is None:
        history_latest_date = date_to_int8(get_previous_trading_date(today, market=market))
    else:
        history_latest_date = date_to_int8(df.index.get_level_values(1).max())

    if history_latest_date >= end_date or start_date > today or history_latest_date >= today:
        return df

    live_df = get_today_ksh_minbar(order_book_ids, today, fields, duration, market)
    if live_df is None:
        return df
    if df is None:
        return live_df
    df = pd.concat([df, live_df])
    df.sort_index(inplace=True)
    return df
Пример #5
0
def get_capital_flow_tickbar(order_book_id, start_date, end_date, fields,
                             market):
    ensure_string(order_book_id, "order_book_id")
    start_date, end_date = ensure_date_range(start_date, end_date,
                                             datetime.timedelta(days=3))
    history_permission_denied = realtime_permission_denied = False
    try:
        data = get_client().execute("get_capital_flow_tickbar",
                                    order_book_id,
                                    start_date,
                                    end_date,
                                    fields,
                                    market=market)
    except PermissionDenied:
        data = []
        history_permission_denied = True
    today = today_int()

    if data:
        data = [(obid, {k: np.frombuffer(*v)
                        for k, v in d.items()}) for obid, d in data]
        df_list = []
        for obid, d in data:
            df = pd.DataFrame(d)
            df_list.append(df)

        df = pd.concat(df_list)  # type: pd.DataFrame
        df["datetime"] = int17_to_datetime_v(df["datetime"].values)
        history_latest_date = date_to_int8(df.iloc[-1]["datetime"])
        df.set_index("datetime", inplace=True)
    else:
        df = None
        history_latest_date = date_to_int8(
            get_previous_trading_date(today, market=market))

    if history_latest_date >= end_date or start_date > today or history_latest_date >= today:
        return df

    try:
        live_df = get_today_capital_flow_tick(order_book_id,
                                              today,
                                              market=market)
    except PermissionDenied:
        live_df = None
        realtime_permission_denied = True
    except MarketNotSupportError:
        live_df = None

    if history_permission_denied and realtime_permission_denied:
        raise PermissionDenied("get_capital_flow_tick")

    if live_df is None:
        return df
    if df is None:
        return live_df
    return pd.concat([df, live_df])
Пример #6
0
def ensure_trading_date(date):
    from rqdatac.services.calendar import get_trading_dates, get_previous_trading_date, get_next_trading_date

    trading_dates = get_trading_dates(get_previous_trading_date(date),
                                      get_next_trading_date(date))
    if date not in trading_dates:
        raise ValueError(
            "expect a trading date, got {}, for reference {}".format(
                date.strftime("%Y%m%d"), trading_dates))
    return date
Пример #7
0
def get_open_auction_info(order_book_ids, start_date=None, end_date=None, market="cn"):
    """获取盘前集合竞价数据
    :param order_book_ids: 股票代码
    :param start_date: 起始日期,默认为今天
    :param end_date: 截止日期,默认为今天
    :param market:  (Default value = "cn")
    :returns: pd.DataFrame or None
    """
    order_book_ids = ensure_order_book_ids(order_book_ids)
    start_date, end_date = ensure_date_range(start_date, end_date, datetime.timedelta(days=0))

    history_permission_denied = realtime_permission_denied = False
    try:
        # obid add prefix 'OA_'
        data = get_client().execute("get_open_auction_info_daybar", ["OA_" + obid for obid in order_book_ids],
                                    start_date, end_date, OA_FIELDS + ["datetime", "date"], market=market)
    except PermissionDenied:
        data = []
        history_permission_denied = True

    today = today_int()
    prev_trading_date = date_to_int8(get_previous_trading_date(today, market=market))
    if data:
        data = [(obid[3:], {k: np.frombuffer(*v) for k, v in d.items()}) for obid, d in data]
        df = convert_bar_to_multi_df(data, 'datetime', OA_FIELDS + ["date"], int17_to_datetime_v, default=0.0)
        if df is None:
            history_latest_date = prev_trading_date
        else:
            history_latest_date = df["date"].max()
            del df["date"]
    else:
        df = None
        history_latest_date = prev_trading_date
    if history_latest_date >= end_date or start_date > today or history_latest_date >= today or end_date < today:
        return df

    try:
        live_df = get_today_open_auction(order_book_ids, today, market=market)
    except PermissionDenied:
        live_df = None
        realtime_permission_denied = True

    if history_permission_denied and realtime_permission_denied:
        raise PermissionDenied("get_open_auction_info")

    if live_df is None:
        return df
    if df is None:
        return live_df
    df = pd.concat([df, live_df])
    df.sort_index(inplace=True)
    return df
Пример #8
0
def get_capital_flow_minbar(order_book_ids, start_date, end_date, fields,
                            duration, market):
    history_permission_denied = realtime_permission_denied = False
    try:
        data = get_client().execute("get_capital_flow_minbar",
                                    order_book_ids,
                                    start_date,
                                    end_date,
                                    fields,
                                    duration,
                                    market=market)
    except PermissionDenied:
        history_permission_denied = True
        data = []

    if data:
        data = [(obid, {k: np.frombuffer(*v)
                        for k, v in d.items()}) for obid, d in data]
        df = convert_bar_to_multi_df(data, 'datetime', fields,
                                     int14_to_datetime_v)
    else:
        df = None

    today = today_int()
    if df is None:
        history_latest_date = date_to_int8(
            get_previous_trading_date(today, market=market))
    else:
        history_latest_date = date_to_int8(df.index.get_level_values(1).max())

    if history_latest_date >= end_date or start_date > today or history_latest_date >= today:
        return df
    try:
        live_df = get_today_capital_flow_minbar(order_book_ids, today, fields,
                                                duration, market)
    except PermissionDenied:
        live_df = None
        realtime_permission_denied = True

    if history_permission_denied and realtime_permission_denied:
        raise PermissionDenied("get_capital_flow_minbar")

    if live_df is None:
        return df
    if df is None:
        return live_df
    df = pd.concat([df, live_df])
    df.sort_index(inplace=True)
    return df
Пример #9
0
def _weekly_start_end_date_handler(start_date, end_date):
    start_date = to_date(start_date)
    monday = start_date - datetime.timedelta(days=start_date.weekday())
    first_trading_day_in_week = monday if is_trading_date(monday) else get_next_trading_date(monday)
    if first_trading_day_in_week < start_date:
        start_date = monday + datetime.timedelta(weeks=1)

    end_date = to_date(end_date)
    if end_date > datetime.date.today():
        end_date = datetime.date.today()
    friday = end_date - datetime.timedelta(days=end_date.weekday()) + datetime.timedelta(days=4)
    last_trading_day_in_week = friday if is_trading_date(friday) else get_previous_trading_date(friday)
    if last_trading_day_in_week > end_date:
        end_date = friday - datetime.timedelta(weeks=1)

    return to_date_int(start_date), to_date_int(end_date)
Пример #10
0
def get_factor_covariance(date, horizon='daily'):
    """ 获取因子协方差矩阵

    :param date: str 日期(例如:‘2017-03-20’)
    :param horizon: str 预测期限。默认为日度('daily'),可选月度(‘monthly’)或季度('quarterly')。

    :return: pandas.DataFrame,其中 index 和 column 均为因子名称。
    """
    date = get_previous_trading_date(get_next_trading_date(date))
    date = ensure_date_int(date)
    ensure_string_in(horizon, HORIZON_CONTAINER, 'horizon')

    df = get_client().execute('get_factor_covariance', date, horizon)
    if not df:
        return
    df = pd.DataFrame(df)
    df.drop("date", axis=1, inplace=True)
    return df.reindex(columns=df.index)
Пример #11
0
def get_margin_stocks(date=None,
                      exchange=None,
                      margin_type='stock',
                      market="cn"):
    """获取融资融券信息

    :param date: 查询日期,默认返回今天上一交易日,支持 str, timestamp, datetime 类型
    :param exchange: 交易所信息,默认不填写则返回全部。
                    str类型,默认为 None,返回所有字段。可选字段包括:
                    'XSHE', 'sz' 代表深交所;'XSHG', 'sh' 代表上交所,不区分大小写
                    (Default value = None)
    :param margin_type: 'stock' 代表融券卖出,'cash',代表融资买入,默认为'stock'

    """
    if date:
        date = ensure_date_int(date)
    else:
        date = get_previous_trading_date(datetime.date.today())
        date = date.year * 10000 + date.month * 100 + date.day

    if exchange is None:
        exchange = EXCHANGE_CONTENT
    else:
        exchange = ensure_string(exchange, "exchange")
        if exchange in EXCHANGE_TYPE:
            exchange = EXCHANGE_TYPE[exchange]
        check_items_in_container(exchange, EXCHANGE_CONTENT, "exchange")
        exchange = [exchange]

    margin_type = ensure_string(margin_type, "margin_type")
    check_items_in_container(margin_type, MARGIN_TYPE, "margin_type")

    data = get_client().execute("get_margin_stocks",
                                date,
                                exchange,
                                margin_type,
                                market=market)

    if not data:
        return []
    else:
        return sorted(data)
Пример #12
0
def jy_instrument_industry(order_book_ids,
                           date=None,
                           level=1,
                           expect_df=False,
                           market="cn"):
    """获取股票对应的聚源行业

    :param order_book_ids: 股票列表,如['000001.XSHE', '000002.XSHE']
    :param date: 如 '2015-01-07' (Default value = None)
    :param level: 聚源等级,0, 1, 2, 3, 'customized' (Default value = 1)
    :param expect_df: 返回 DataFrame,默认为 False
    :param market:  (Default value = "cn")
    :returns: code, name
        返回输入日期最近交易日的股票对应聚源行业以及对应的聚源等级

    """
    if level not in (0, 1, 2, 3, "customized"):
        raise ValueError("level should in 0, 1, 2, 3, 'customized'")
    order_book_ids = ensure_order_book_ids(order_book_ids, market=market)
    if not date:
        date = ensure_date_int(
            get_previous_trading_date(datetime.date.today(), market=market))
    else:
        date = ensure_date_int(date)

    df = get_client().execute("jy_instrument_industry",
                              order_book_ids,
                              date,
                              level,
                              market=market)
    if not df:
        return
    if len(order_book_ids) == 1 and not expect_df:
        r = df[0]
        if level == 0:
            return r["first_industry_name"], r["second_industry_name"], r[
                "third_industry_name"]
        return r["industry_name"]
    return pd.DataFrame(df).set_index("order_book_id")
Пример #13
0
def get_securities_margin(order_book_ids,
                          start_date=None,
                          end_date=None,
                          fields=None,
                          expect_df=False,
                          market="cn"):
    """获取股票融资融券数据

    :param order_book_ids: 股票代码或代码列表
    :param start_date: 开始时间,支持 str, date, datetime, pandasTimestamp
        默认为 end_date 之前一个月 (Default value = None)
    :param end_date: 结束时间 默认为当前日期前一天 (Default value = None)
    :param fields: str 或 list 类型. 默认为 None, 返回所有字段。可选字段包括:
                   today, week, month, three_month, six_month, year, current_year, total
                   (Default value = None)
    :param expect_df: 返回 MultiIndex DataFrame (Default value = False)
    :param market: 地区代码, 如: 'cn' (Default value = "cn")
    :returns: 如果传入多个股票代码,且 fields 为多个或者 None,返回 pandas.Panel
        如果传入一只股票或者 fields 为单个字段,则返回 pandas.DataFrame
        如果传入的股票代码和字段数都是1,则返回 pandas.Series

    """

    order_book_ids = ensure_list_of_string(order_book_ids, "order_book_ids")
    all_list = []
    for order_book_id in order_book_ids:
        if order_book_id.upper() in MARGIN_SUMMARY_MAP:
            all_list.append(MARGIN_SUMMARY_MAP[order_book_id.upper()])
        else:
            inst = instruments(order_book_id, market)

            if inst.type in ["CS", "ETF", "LOF"]:
                all_list.append(inst.order_book_id)
            else:
                warnings.warn(
                    "{} is not stock, ETF, or LOF.".format(order_book_id))
    order_book_ids = all_list
    if not order_book_ids:
        raise ValueError("no valid securities in {}".format(order_book_ids))

    if fields is None:
        fields = list(MARGIN_FIELDS)
    else:
        fields = ensure_list_of_string(fields, "fields")
        check_items_in_container(fields, MARGIN_FIELDS, "fields")
        fields = ensure_order(fields, MARGIN_FIELDS)
    start_date, end_date = ensure_date_range(start_date, end_date)
    if end_date > ensure_date_or_today_int(None):
        end_date = ensure_date_or_today_int(
            get_previous_trading_date(datetime.date.today()))
    trading_dates = pd.to_datetime(
        get_trading_dates(start_date, end_date, market=market))

    data = get_client().execute("get_securities_margin",
                                order_book_ids,
                                start_date,
                                end_date,
                                market=market)
    if not data:
        return

    if expect_df:
        df = pd.DataFrame(data)
        df.sort_values(["order_book_id", "date"], inplace=True)
        df.set_index(["order_book_id", "date"], inplace=True)
        df = df.reindex(columns=fields)
        return df

    pl = pd.Panel(items=fields,
                  major_axis=trading_dates,
                  minor_axis=order_book_ids)
    for r in data:
        for field in fields:
            value = r.get(field)
            pl.at[field, r["date"], r["order_book_id"]] = value

    if len(order_book_ids) == 1:
        pl = pl.minor_xs(order_book_ids[0])
    if len(fields) == 1:
        pl = pl[fields[0]]
    if len(order_book_ids) != 1 and len(fields) != 1:
        warnings.warn(
            "Panel is removed after pandas version 0.25.0."
            " the default value of 'expect_df' will change to True in the future."
        )
    return pl
Пример #14
0
def _update_weekly_trading_date_index(idx):
    if is_trading_date(idx[1]):
        return idx
    return idx[0], get_previous_trading_date(idx[1])
Пример #15
0
def get_fundamentals(query, entry_date, interval=None, report_quarter=False, expect_df=False, market="cn"):
    """获取财务数据

    :param query: query 对象
    :param entry_date: 日期
    :param interval:  (Default value = None)
    :param report_quarter:  (Default value = False)
    :param expect_df: 返回 MultiIndex DataFrame (Default value = False)
    :param market:  (Default value = "cn")

    """
    if market != "cn":
        raise MarketNotSupportError("don't support market {} yet.", market)

    if not isinstance(query, Query):
        raise ValueError("a sqlalchemy's Query object expected: {}".format(type(query)))

    raise_for_no_panel(expect_df)
    entry_date = to_datetime(entry_date)
    delta = 0
    duration = 0
    if interval is not None:
        if not isinstance(interval, str):
            raise ValueError(
                "invalid interval: {} should be a string like 1d, 5y, 3m, 2q".format(interval)
            )
        if interval[-1] not in __TIME_DELTA_MAP__:
            raise ValueError(
                "invalid interval: {}, interval unit should be d(day), "
                "m(month), q(quarter) or y(year)".format(interval)
            )
        delta = __TIME_DELTA_MAP__[interval[-1]]

        try:
            duration = int(interval[:-1])
        except ValueError:
            raise ValueError(
                "invalid interval: {}, should be a string like 1d, 5y, 3m, 2q".format(interval)
            )

    trading_dates = [get_previous_trading_date(entry_date + __TIME_DELTA_MAP__["d"], market=market)]
    if duration > 0:
        current_date = trading_dates[0]
        one_day = __TIME_DELTA_MAP__["d"]
        for i in range(duration - 1):
            current_date = get_previous_trading_date(current_date - delta + one_day, market=market)
            trading_dates.append(current_date)

    query = _unsafe_apply_query_filter(query, trading_dates)
    sql = _compile_query(query)
    records = get_client().execute("get_fundamentals", sql, market=market)

    if not records:
        warnings.warn("No record found")
        return None

    base_fields = ["STOCKCODE", "TRADEDATE", "RPT_YEAR", "RPT_QUARTER"]
    field_names = base_fields + list(set(records[0].keys()) - set(base_fields))
    items = ["report_quarter"] + field_names[4:] if report_quarter else field_names[4:]

    if expect_df:
        df = pd.DataFrame(records)
        df.rename(columns={"STOCKCODE": "order_book_id", "TRADEDATE": "date"}, inplace=True)
        df["report_quarter"] = df["RPT_YEAR"].map(str) + "q" + df["RPT_QUARTER"].map(str)
        df.sort_values(["order_book_id", "date"], ascending=[True, False], inplace=True)
        df.set_index(["order_book_id", "date"], inplace=True)
        for item in items:
            if item != "report_quarter":
                df[item] = df[item].astype(np.float64)
        return df[items]

    # 只有一个查询日期时, 保持顺序
    if len(trading_dates) > 1:
        stocks = list(set([r[field_names[0]] for r in records]))
    else:
        stocks = [r[field_names[0]] for r in records]

    stock_index = {s: i for i, s in enumerate(stocks)}
    day_index = {d: i for i, d in enumerate(trading_dates)}

    removed_items_size = 3 if report_quarter else 4

    array = np.ndarray(
        ((len(records[0]) - removed_items_size), len(trading_dates), len(stocks)), dtype=object
    )
    array.fill(np.nan)
    for r in records:
        istock = stock_index[r[field_names[0]]]
        iday = day_index[int8_to_date(r[field_names[1]])]
        for i in range(4, len(r)):
            array[(i - removed_items_size, iday, istock)] = np.float64(r[field_names[i]])
        if report_quarter:
            array[(0, iday, istock)] = (
                np.nan
                if None in (r[field_names[2]], r[field_names[3]])
                else str(r[field_names[2]]) + "q" + str(r[field_names[3]])
            )

    trading_dates = pd.to_datetime(trading_dates)

    warnings.warn("Panel is  removed after pandas version 0.25.0."
                  "the  default value of 'expect_df' will change to True in the future.")
    return pd.Panel(data=array, items=items, major_axis=trading_dates, minor_axis=stocks)
Пример #16
0
def get_trading_hours(order_book_id,
                      date=None,
                      expected_fmt="str",
                      frequency="1m",
                      market="cn"):
    """获取合约指定日期交易时间
      :param order_book_id: 合约代码
      :param date: 日期,默认为今天
      :param expected_fmt: 返回格式,默认为str, 也支持datetime.time和datetime.datetime格式
      :param frequency: 频率,默认为1m, 对应米筐分钟线时间段的起始, tick和1m相比区别在于每个交易时间段开盘往前移一分钟
      :param market:  (Default value = "cn")

      :return: trading_hours str or list of datetime.time/datetime.datetime list or None
      """
    date = ensure_date_or_today_int(date)
    if not is_trading_date(date, market):
        warnings.warn(" %d is not a trading date" % date)
        return

    ensure_string(order_book_id, "order_book_id")
    ins = instruments(order_book_id)
    if ins is None:
        return

    ensure_string_in(expected_fmt, ("str", "time", "datetime"), "expected_fmt")
    ensure_string_in(frequency, ("1m", "tick"), "frequency")
    date_str = to_date_str(date)

    if ins.listed_date > date_str:
        return

    if ins.type in (
            "Future", "Option"
    ) and ins.de_listed_date < date_str and ins.de_listed_date != "0000-00-00":
        return

    if ins.type not in (
            "Future", "Option"
    ) and ins.de_listed_date <= date_str and ins.de_listed_date != "0000-00-00":
        return
    if ins.type == "Repo":
        trading_hours = "09:31-11:30,13:01-15:30"
    elif ins.type == "Spot":
        if has_night_trading(date, market):
            trading_hours = "20:01-02:30,09:01-15:30"
        else:
            trading_hours = "09:01-15:30"
    elif ins.type not in ("Future",
                          "Option") or (ins.type == "Option"
                                        and ins.exchange in ("XSHG", "XSHE")):
        trading_hours = "09:31-11:30,13:01-15:00"
    else:
        trading_hours = get_client().execute("get_trading_hours",
                                             ins.underlying_symbol,
                                             date,
                                             market=market)
        if trading_hours is None:
            return
        # 前一天放假或者该品种上市首日没有夜盘
        no_night_trading = (not has_night_trading(date, market)
                            or get_underlying_listed_date(
                                ins.underlying_symbol, ins.type) == date_str)

        if no_night_trading and not trading_hours.startswith("09"):
            trading_hours = trading_hours.split(",", 1)[-1]

    if frequency == "tick":
        trading_hours = ",".join([
            s[:4] + str(int(s[4]) - 1) + s[5:]
            for s in trading_hours.split(",")
        ])

    if expected_fmt != "str":
        trading_hours = [t.split("-", 1) for t in trading_hours.split(",")]
        for i, (start, end) in enumerate(trading_hours):
            trading_hours[i][0] = str_to_dt_time(start)
            trading_hours[i][1] = str_to_dt_time(end)

        if expected_fmt == "datetime":
            td = int8_to_date(date)
            prev_td = get_previous_trading_date(date)
            prev_td_next = prev_td + datetime.timedelta(days=1)

            for i, (start, end) in enumerate(trading_hours):
                if start.hour > 16:
                    start_dt = prev_td
                    end_dt = start_dt if end.hour > 16 else prev_td_next
                else:
                    start_dt = end_dt = td
                trading_hours[i][0] = datetime.datetime.combine(
                    start_dt, start)
                trading_hours[i][1] = datetime.datetime.combine(end_dt, end)

    return trading_hours
Пример #17
0
def get_factor(order_book_ids,
               factor,
               start_date=None,
               end_date=None,
               universe=None,
               expect_df=False,
               **kwargs):
    """获取因子

    :param order_book_ids: 股票代码或代码列表
    :param factor: 如 'total_income'
    :param date: 如 date='2015-01-05', 默认为前一交易日
    :param start_date: 开始日期'2015-01-05', 默认为前一交易日, 最小起始日期为'2000-01-04'
    :param end_date: 结束日期
    :param universe: 股票池,默认为全A股
    :param expect_df: 返回 MultiIndex DataFrame (Default value = False)
    :returns: pd.DataFrame
    """

    order_book_ids = ensure_order_book_ids(order_book_ids, type="CS")
    order_book_ids = list(set(order_book_ids))

    factor = ensure_list_of_string(factor)
    factor = list(OrderedDict.fromkeys(factor))

    if start_date and end_date:
        start_date, end_date = ensure_date_range(start_date, end_date,
                                                 datetime.timedelta(days=15))
        if start_date < 20000104:
            warnings.warn(
                "start_date is earlier than 2000-01-04, adjusted to 2000-01-04"
            )
            start_date = 20000104
    elif start_date:
        raise ValueError("Expect end_date")
    elif end_date:
        raise ValueError("Expect start_date")
    else:
        date = kwargs.pop("date", None)
        date = ensure_date_int(
            date or get_previous_trading_date(datetime.date.today()))
        start_date = end_date = date

    if kwargs:
        raise ValueError('unknown kwargs: {}'.format(kwargs))

    if universe is not None:
        universe = ensure_string(universe, "universe")
        if universe != "all":
            universe = ensure_order_book_id(universe, type="INDX")
            from rqdatac import index_components
            allowed_order_book_ids = set(
                index_components(universe, date=end_date) or [])
            not_permit_order_book_ids = [
                order_book_id for order_book_id in order_book_ids
                if order_book_id not in allowed_order_book_ids
            ]
            if not_permit_order_book_ids:
                warnings.warn(
                    "%s not in universe pool, value of those order_book_ids will always be NaN"
                    % not_permit_order_book_ids)

    data = get_client().execute("get_factor_from_store",
                                order_book_ids,
                                factor,
                                start_date,
                                end_date,
                                universe=universe)

    if not data:
        return

    factor_value_length = len(data[0][2])
    if factor_value_length == 0:
        return

    dates = pd.to_datetime(get_trading_dates(start_date, end_date))
    if len(dates) > factor_value_length:
        _get_factor_warning_msg(dates[factor_value_length], dates[-1])
        dates = dates[0:factor_value_length]

    if expect_df or len(factor) > 1:
        order_book_id_index_map = {o: i for i, o in enumerate(order_book_ids)}
        factor_index_map = {f: i for i, f in enumerate(factor)}
        arr = np.full((len(order_book_ids) * len(dates), len(factor)), np.nan)

        for order_book_id, factor_name, values in data:
            order_book_id_index = order_book_id_index_map[order_book_id]
            factor_index = factor_index_map[factor_name]
            slice_ = slice(order_book_id_index * len(dates),
                           (order_book_id_index + 1) * len(dates), None)
            arr[slice_, factor_index] = values

        multi_index = pd.MultiIndex.from_product(
            [order_book_ids, dates], names=["order_book_id", "date"])
        df = pd.DataFrame(index=multi_index, columns=factor, data=arr)
        return df

    order_book_id_index_map = {o: i for i, o in enumerate(order_book_ids)}
    arr = np.full((len(dates), len(order_book_ids)), np.nan)
    for order_book_id, _, values in data:
        arr[:, order_book_id_index_map[order_book_id]] = values
    df = pd.DataFrame(index=dates, columns=order_book_ids, data=arr)

    if len(df.index) == 1:
        return df.iloc[0]
    if len(df.columns) == 1:
        return df[df.columns[0]]
    return df