コード例 #1
0
def get_stock_connect(order_book_ids, start_date=None, end_date=None, fields=None, expect_df=False):
    """获取"陆股通"的持股、持股比例

    :param order_book_ids: 股票列表
    :param start_date: 开始日期: 如'2017-03-17' (Default value = None)
    :param end_date: 结束日期: 如'2018-03-16' (Default value = None)
    :param fields: 默认为所有字段,可输入shares_holding或者holding_ratio (Default value = None)
    :param expect_df: 返回 MultiIndex DataFrame (Default value = False)
    :returns: 返回pandas.DataFrame or pandas.Panel

    """
    if order_book_ids not in ("shanghai_connect", "shenzhen_connect", "all_connect"):
        order_book_ids = ensure_order_book_ids(order_book_ids, type="CS")
    start_date, end_date = ensure_date_range(start_date, end_date)
    if fields is not None:
        fields = ensure_list_of_string(fields)
        for f in fields:
            if f not in ("shares_holding", "holding_ratio"):
                raise ValueError("invalid field: {}".format(f))
    else:
        fields = ["shares_holding", "holding_ratio"]
    data = get_client().execute("get_stock_connect", order_book_ids, start_date, end_date, fields)
    if not data:
        return None
    df = pd.DataFrame(data, columns=["trading_date", "order_book_id"] + fields)

    if not expect_df and not is_panel_removed:
        df = df.set_index(["trading_date", "order_book_id"])
        df = df.to_panel()
        df.major_axis.name = None
        df.minor_axis.name = None
        if len(order_book_ids) == 1:
            df = df.minor_xs(order_book_ids[0])
        if len(fields) == 1:
            df = df[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 df
    else:
        df.sort_values(["order_book_id", "trading_date"], inplace=True)
        df.set_index(["order_book_id", "trading_date"], inplace=True)
        if expect_df:
            return df

        if len(order_book_ids) != 1 and len(fields) != 1:
            raise_for_no_panel()

        if len(order_book_ids) == 1:
            df.reset_index(level=0, drop=True, inplace=True)
            if len(fields) == 1:
                df = df[fields[0]]
            return df
        else:
            df = df.unstack(0)[fields[0]]
            df.index.name = None
            df.columns.name = None
            return df
コード例 #2
0
def parse_results(records, quarters, expect_df):
    if not records:
        return None

    removed_items_size = 3
    base_fields = ["stockcode", "rpt_year", "rpt_quarter"]

    field_names = base_fields + list(set(records[0].keys()) - set(base_fields))
    items = field_names[removed_items_size:]

    if not expect_df and not is_panel_removed:
        # 只有一个查询日期时, 保持顺序
        stocks = list(set(r[field_names[0]] for r in records))
        stock_index = {s: i for i, s in enumerate(stocks)}
        quarter_index = {q: i for i, q in enumerate(quarters)}

        array = np.ndarray(
            (len(records[0]) - removed_items_size, len(quarters), len(stocks)), dtype=object
        )
        array.fill(np.nan)
        for r in records:
            istock = stock_index[r[field_names[0]]]
            iquarter = quarter_index[(r[field_names[1]], r[field_names[2]])]
            for i in range(removed_items_size, len(r)):
                if field_names[i] == "announce_date":
                    announce_date = r[field_names[i]]
                    array[i - removed_items_size, iquarter, istock] = (
                        np.nan if announce_date is None else announce_date
                    )
                else:
                    array[i - removed_items_size, iquarter, istock] = np.float64(r[field_names[i]])

        s_quarters = ["%dq%d" % (year, quarter) for year, quarter in quarters]
        results = pd.Panel(data=array, items=items, major_axis=s_quarters, minor_axis=stocks)
        item_size, major_size, minor_size = results.shape
        if minor_size == 1:
            ret = results.minor_xs(*stocks)
            return ret[field_names[removed_items_size]] if item_size == 1 else ret
        elif item_size == 1:
            return results[field_names[removed_items_size]]
        elif major_size == 1:
            return results.major_xs(*s_quarters)
        else:
            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 results
    else:
        df = pd.DataFrame(records)
        df.rename(columns={"stockcode": "order_book_id"}, inplace=True)
        df["quarter"] = df["rpt_year"].map(str) + "q" + df["rpt_quarter"].map(str)
        df.sort_values(["order_book_id", "quarter"], ascending=[True, False], inplace=True)
        df.set_index(["order_book_id", "quarter"], inplace=True)
        for item in items:
            if item != "announce_date":
                df[item] = df[item].astype(np.float64)
        df = df[items]
        if expect_df:
            return df
        else:
            if len(df.index.get_level_values(0).unique()) == 1:
                df.reset_index(level=0, inplace=True, drop=True)
                df.index.name = None
                df.sort_index(ascending=False, inplace=True)
                if len(df.columns) == 1:
                    df = df[df.columns[0]]
                return df
            elif len(df.columns) == 1:
                field = df.columns[0]
                df = df.unstack(0)[field]
                df.index.name = None
                df.columns.name = None
                df.sort_index(ascending=False, inplace=True)
                return df
            elif len(df.index.get_level_values(1).unique()) == 1:
                df.reset_index(level=1, inplace=True, drop=True)
                df.index.name = None
                return df
            raise_for_no_panel()
コード例 #3
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)
コード例 #4
0
def get_price(
        order_book_ids,
        start_date=None,
        end_date=None,
        frequency="1d",
        fields=None,
        adjust_type="pre",
        skip_suspended=False,
        expect_df=False,
        market="cn",
        **kwargs
):
    """获取证券的历史数据

    :param order_book_ids: 股票列表
    :param market: 地区代码, 如 'cn' (Default value = "cn")
    :param start_date: 开始日期, 如 '2013-01-04' (Default value = None)
    :param end_date: 结束日期, 如 '2014-01-04' (Default value = None)
    :param frequency: 可选参数, 默认为日线。日线使用 '1d', 分钟线 '1m' (Default value = "1d")
    :param fields: 可选参数。默认为所有字段。 (Default value = None)
    :param adjust_type: 可选参数,默认为‘pre', 返回开盘价,收盘价,最高价,最低价依据get_ex_factor 复权因子(包含分红,拆分),volume依据get_split 复权因子(仅涵盖拆分)计算的前复权数据
            'none'将返回原始数据
            'post'返回开盘价,收盘价,最高价,最低价依据get_ex_factor 复权因子(包含分红,拆分),volume依据get_split 复权因子(仅涵盖拆分)计算的后复权数据
            'pre_volume'返回开盘价,收盘价,最高价,最低价,成交量依据get_ex_factor 复权因子(包含分红,拆分)计算的前复权数据
            'post_volume'返回开盘价,收盘价,最高价,最低价,成交量依据get_ex_factor 复权因子(包含分红,拆分)计算的后复权数据
            'internal'返回只包含拆分的前复权数据。 (Default value = "pre")
    :param skip_suspended: 可选参数,默认为False;当设置为True时,返回的数据会过滤掉停牌期间,
                    此时order_book_ids只能设置为一只股票 (Default value = False)
    :param expect_df: 返回 MultiIndex DataFrame (Default value = False)
    :returns: 如果仅传入一只股票, 返回一个 pandas.DataFrame
        如果传入多只股票, 则返回一个 pandas.Panel

    """
    # tick数据
    if frequency == "tick":
        return get_tick_price(order_book_ids, start_date, end_date, fields, expect_df, market)
    elif frequency.endswith(("d", "m", "w")):
        duration = int(frequency[:-1])
        frequency = frequency[-1]
        assert 1 <= duration <= 240, "frequency should in range [1, 240]"
        if market == "hk" and frequency == "m" and duration not in (1, 5, 15, 30, 60):
            raise ValueError("frequency should be str like 1m, 5m, 15m 30m,or 60m")
        elif frequency == 'w' and duration not in (1,):
            raise ValueError("Weekly frequency should be str '1w'")
    else:
        raise ValueError("frequency should be str like 1d, 1m, 5m or tick")
    # 验证adjust_type
    if "adjusted" in kwargs:
        adjusted = kwargs.pop("adjusted")
        adjust_type = "pre" if adjusted else "none"

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

    valid_adjust = ["pre", "post", "none", "pre_volume", "post_volume"]
    ensure_string(adjust_type, "adjust_type")
    check_items_in_container(adjust_type, valid_adjust, "adjust_type")
    order_book_ids = ensure_list_of_string(order_book_ids, "order_book_ids")
    if skip_suspended and len(order_book_ids) > 1:
        raise ValueError("only accept one order_book_id or symbol if skip_suspended is True")

    assert isinstance(skip_suspended, bool), "'skip_suspended' should be a bool"
    assert isinstance(expect_df, bool), "'expect_df' should be a bool"

    order_book_ids, stocks, funds, indexes, futures, futures888, spots, options, convertibles, repos = classify_order_book_ids(
        order_book_ids, market
    )
    if not order_book_ids:
        warnings.warn("no valid instrument")
        return
    start_date, end_date = _ensure_date(
        start_date, end_date, stocks, funds, indexes, futures, spots, options, convertibles, repos
    )
    from rqdatac.services.detail.get_price_df import get_price_df, get_week_df
    if frequency != 'w':
        df = get_price_df(
            order_book_ids, start_date, end_date, frequency, duration, fields, adjust_type, skip_suspended,
            stocks, funds, indexes, futures, futures888, spots, options, convertibles, repos, market
        )
        if df is None or expect_df:
            return df
        # 单个合约
        if len(df.index.get_level_values(0).unique()) == 1:
            df.reset_index(level=0, inplace=True, drop=True)
            # df.index.name = None
            if len(df.columns) == 1:
                df = df[df.columns[0]]
            return df
        # 单个字段
        elif len(df.columns) == 1:
            field = df.columns[0]
            df = df.unstack(0)[field]
            # df.index.name = None
            df.columns.name = None
            return df
        raise_for_no_panel(False)
        # 交换index的顺序,以制作panel
        return df.swaplevel().to_panel()
    else:
        if not expect_df:
            raise ValueError(
                "Weekly frequency can only return a DataFrame object, set 'expect_df' to True to resolve this")
        if skip_suspended:
            raise ValueError(
                "Weekly frequency does not support skipping suspended trading days, set 'skip_suspended' to False to resolve this")
        start_date, end_date = _weekly_start_end_date_handler(start_date, end_date)
        if start_date > end_date:
            # 如果*当周没有结束*
            # 或者start date 和 end date 不能涵盖当周所有的交易日,查询该周的数据时返回为空。
            return None
        return get_week_df(order_book_ids, start_date, end_date, fields, adjust_type, market,
                           *(stocks, funds, indexes, futures, futures888, spots, options, convertibles, repos))
コード例 #5
0
def get_turnover_rate(order_book_ids,
                      start_date=None,
                      end_date=None,
                      fields=None,
                      expect_df=False,
                      market="cn"):
    """获取股票换手率数据

    :param order_book_ids: 股票代码或股票代码列表
    :param start_date: 开始时间
    :param end_date: 结束时间;在 start_date 和 end_date 都不指定的情况下,默认为最近3个月
    :param fields: str或list类型. 默认为None, 返回所有fields.
                   field 包括: 'today', 'week', 'month', 'year', 'current_year'
                   (Default value = None)
    :param expect_df: 返回 MultiIndex DataFrame (Default value = False)
    :param market: 地区代码, 如: 'cn' (Default value = "cn")
    :returns: 如果order_book_ids或fields为单个值 返回pandas.DataFrame, 否则返回pandas.Panel

    """
    order_book_ids = ensure_order_book_ids(order_book_ids)
    start_date, end_date = ensure_date_range(start_date, end_date)
    if fields is not None:
        fields, mapped_fields = _get_maped_fields(fields)
    else:
        fields, mapped_fields = list(TURNOVER_FIELDS_MAP.keys()), list(
            TURNOVER_FIELDS_MAP.values())
    df = get_client().execute("get_turnover_rate",
                              order_book_ids,
                              start_date,
                              end_date,
                              mapped_fields,
                              market=market)
    df = pd.DataFrame(df,
                      columns=["tradedate", "order_book_id"] + mapped_fields)
    df.rename(columns={v: k
                       for k, v in TURNOVER_FIELDS_MAP.items()},
              inplace=True)

    if not expect_df and not is_panel_removed:
        df.set_index(["tradedate", "order_book_id"], inplace=True)
        df.sort_index(inplace=True)
        df = df.to_panel()
        df = pf_fill_nan(df, order_book_ids)
        if len(order_book_ids) == 1:
            df = df.minor_xs(*order_book_ids)
            if fields and len(fields) == 1:
                return df[fields[0]]
            return df
        if fields and len(fields) == 1:
            return df[fields[0]]
        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 df
    else:
        df.sort_values(["order_book_id", "tradedate"], inplace=True)
        df.set_index(["order_book_id", "tradedate"], inplace=True)
        if expect_df:
            return df

        if len(order_book_ids) != 1 and len(fields) != 1:
            raise_for_no_panel()

        if len(order_book_ids) == 1:
            df.reset_index(level=0, drop=True, inplace=True)
            if len(fields) == 1:
                df = df[fields[0]]
            return df
        else:
            df = df.unstack(0)[fields[0]]
            df.index.name = None
            df.columns.name = None
            return df
コード例 #6
0
def get_shares(order_book_ids, start_date=None, end_date=None, fields=None, expect_df=False, market="cn"):
    """获取流通股本信息

    :param order_book_ids: 股票名称
    :param start_date: 开始日期, 如'2013-01-04' (Default value = None)
    :param end_date: 结束日期,如'2014-01-04' (Default value = None)
    :param fields: 如'total', 'circulation_a' (Default value = None)
    :param expect_df: 返回 MultiIndex DataFrame (Default value = False)
    :param market: 地区代码,如'cn' (Default value = "cn")
    :returns: 返回一个DataFrame

    """
    order_book_ids = ensure_order_book_ids(order_book_ids, market=market)
    start_date, end_date = ensure_date_range(start_date, end_date)
    if fields:
        fields = ensure_list_of_string(fields, "fields")
        if 'management_circulation' in fields:
            fields.remove('management_circulation')
            if fields:
                warnings.warn("management_circulation is removed")
            else:
                raise ValueError("management_circulation is removed")
        check_items_in_container(fields, set(share_fields), "fields")
        fields = [share_fields[i] for i in fields]
    else:
        fields = list(share_fields.values())

    all_shares = get_client().execute("get_shares", order_book_ids, fields, market=market)
    if not all_shares:
        return
    dates = get_trading_dates_in_type(start_date, end_date, expect_type="datetime", market=market)
    df = pd.DataFrame(all_shares)
    unique = set(df.order_book_id)
    for order_book_id in order_book_ids:
        if order_book_id not in unique:
            df = df.append(
                {"order_book_id": order_book_id, "date": df.date.iloc[-1]}, ignore_index=True
            )
    df.set_index(["date", "order_book_id"], inplace=True)
    df.sort_index(inplace=True)
    df = df.unstack(level=1)
    index = df.index.union(dates)
    df = df.reindex(index)
    df = df.fillna(method="ffill")
    df = df.loc[list(dates)]
    df = df.dropna(how="all")
    df = df[fields]
    if not is_panel_removed and not expect_df:
        pl = df.stack(1).to_panel()
        pl.items = [anti_fields[i] for i in pl.items]
        if len(order_book_ids) == 1:
            pl = pl.minor_xs(order_book_ids[0])
        if len(fields) == 1:
            pl = pl[anti_fields[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
    else:
        df = df.stack(1)
        df.index.set_names(["date", "order_book_id"], inplace=True)
        df = df.reorder_levels(["order_book_id", "date"]).sort_index()
        df = df.rename(columns=anti_fields)
        if expect_df:
            return df

        if len(order_book_ids) != 1 and len(fields) != 1:
            raise_for_no_panel()

        if len(order_book_ids) == 1:
            df.reset_index(level=0, drop=True, inplace=True)
            if len(fields) == 1:
                df = df[anti_fields[fields[0]]]
            return df
        else:
            df = df.unstack(0)[anti_fields[fields[0]]]
            df.index.name = None
            df.columns.name = None
            return df
コード例 #7
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 not expect_df and not is_panel_removed:

        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
    else:
        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)
        if expect_df:
            return df

        if len(order_book_ids) != 1 and len(fields) != 1:
            raise_for_no_panel()

        if len(order_book_ids) == 1:
            df.reset_index(level=0, drop=True, inplace=True)
            if len(fields) == 1:
                df = df[fields[0]]
            return df
        else:
            df = df.unstack(0)[fields[0]]
            df.index.name = None
            df.columns.name = None
            return df