def get_factor( order_book_ids, # type: Union[str, List[str]] factors, # type: Union[str, List[str]] count=1, # type: Optional[int] universe=None, # type: Optional[Union[str, List[Union]]] expect_df=False # type: Optional[bool] ): # type: (...) -> pd.DataFrame """ 获取股票截止T-1日的因子数据 :param order_book_ids: 合约代码,可传入order_book_id, order_book_id list :param factors: 因子名称,可查询 rqdatac.get_all_factor_names() 得到所有有效因子字段 :param count: 获取多少个交易日的数据 :param universe: 当获取横截面因子时,universe指定了因子计算时的股票池 :param expect_df: 默认为False。当设置为True时,总是返回 multi-index DataFrame。pandas 0.25.0 以上该参数应设为 True,以避免因试图构建 Panel 产生异常 """ env = Environment.get_instance() data_proxy = env.data_proxy end_date = data_proxy.get_previous_trading_date(env.trading_dt) if count == 1: start_date = end_date else: start_date = data_proxy.get_nth_previous_trading_date(end_date, count - 1) if isinstance(order_book_ids, six.string_types): order_book_ids = assure_order_book_id(order_book_ids) else: order_book_ids = [assure_order_book_id(i) for i in order_book_ids] return rqdatac.get_factor(order_book_ids, factors, start_date=start_date, end_date=end_date, universe=universe, expect_df=expect_df)
def get_shares( order_book_ids, # type: Union[str, List[str]] count=1, # type: Optional[int] fields=None, # type: Optional[str] expect_df=False # type: Optional[bool] ): # type: (...) -> Union[pd.DataFrame, pd.Series] """ :param order_book_ids: 可输入 order_book_id, order_book_id list, symbol, symbol list :param count: 回溯获取的数据个数。默认为当前能够获取到的最近的数据 :param fields: 期望返回的字段,默认为所有字段。见下方列表 :param expect_df: 是否期望始终返回 DataFrame。pandas 0.25.0 以上该参数应设为 True,以避免因试图构建 Panel 产生异常 ========================= =================================================== fields 字段名 ========================= =================================================== total 总股本 circulation_a 流通A股 management_circulation 已流通高管持股 non_circulation_a 非流通A股合计 total_a A股总股本 ========================= =================================================== :return: 查询时间段内某个股票的流通情况,当 expect_df 为 False 且 fields 指定为单一字段的情况时返回 pandas.Series :example: 获取平安银行总股本数据: .. code-block:: python3 :linenos: logger.info(get_shares('000001.XSHE', count=5, fields='total')) #[Out] #2016-08-01 1.717041e+10 #2016-08-02 1.717041e+10 #2016-08-03 1.717041e+10 #2016-08-04 1.717041e+10 #2016-08-05 1.717041e+10 #Name: total, dtype: float64 """ env = Environment.get_instance() dt = env.trading_dt if count == 1: start_dt = dt else: start_dt = env.data_proxy.get_previous_trading_date(dt, count - 1) if isinstance(order_book_ids, six.string_types): order_book_ids = assure_order_book_id(order_book_ids) else: order_book_ids = [assure_order_book_id(i) for i in order_book_ids] return rqdatac.get_shares(order_book_ids, start_dt, dt, fields=fields, expect_df=expect_df)
def get_price_change_rate( order_book_ids, # type: Union[str, List[str]] count=1, # type: Optional[int] expect_df=False # type: Optional[bool] ): # type: (...) -> Union[pd.DataFrame, pd.Series] """ 获取股票/指数截止T-1日的日涨幅 :param order_book_ids: 可输入 order_book_id, order_book_id list, symbol, symbol list :param count: 回溯获取的数据个数。默认为当前能够获取到的最近的数据 :param expect_df: 是否期望始终返回 DataFrame。pandas 0.25.0 以上该参数应设为 True,以避免因试图构建 Panel 产生异常 当 expect_df 为 False 时,返回值的类型如下: * 传入多个order_book_id,函数会返回pandas DataFrame * 传入一个order_book_id,函数会返回pandas Series :example: 获取平安银行以及沪深300指数一段时间的涨跌幅情况: .. code-block:: python3 :linenos: get_price_change_rate(['000001.XSHE', '510050.XSHG'], 1) # [Out] # 2016-06-01 15:30:00.00 INFO order_book_id 000001.XSHE 510050.XSHG # date # 2016-05-31 0.026265 0.033964 # 2016-06-02 15:30:00.00 INFO order_book_id 000001.XSHE 510050.XSHG # date # 2016-06-01 -0.006635 -0.008308 """ env = Environment.get_instance() data_proxy = env.data_proxy if isinstance(order_book_ids, six.string_types): order_book_ids = assure_order_book_id(order_book_ids) else: order_book_ids = [assure_order_book_id(i) for i in order_book_ids] end_date = data_proxy.get_previous_trading_date(env.trading_dt) if count == 1: start_date = end_date else: start_date = data_proxy.get_previous_trading_date(end_date, count - 1) return rqdatac.get_price_change_rate(order_book_ids, start_date, end_date, expect_df=expect_df)
def get_instrument_industry(order_book_ids, source='citics', level=1): # type: (Union[str, List[str]], Optional[str], Optional[int]) -> pd.DataFrame """ 获取T日时股票行业分类 :param order_book_ids: 合约代码,可传入order_book_id, order_book_id list :param source: 默认为中信(citics),可选聚源(gildata) :param level: 默认为1,可选 0 1 2 3,0表示返回所有级别 """ if isinstance(order_book_ids, six.string_types): order_book_ids = assure_order_book_id(order_book_ids) else: order_book_ids = [assure_order_book_id(i) for i in order_book_ids] env = Environment.get_instance() return rqdatac.get_instrument_industry(order_book_ids, source, level, env.calendar_dt)
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)
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_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) ]
def is_suspended(order_book_id, count=1): # type: (str, Optional[int]) -> Union[bool, pd.DataFrame] """ 判断某只股票是否全天停牌。 :param order_book_id: 某只股票的代码或股票代码,可传入单只股票的order_book_id, symbol :param count: 回溯获取的数据个数。默认为当前能够获取到的最近的数据 """ dt = Environment.get_instance().calendar_dt.date() order_book_id = assure_order_book_id(order_book_id) return Environment.get_instance().data_proxy.is_suspended(order_book_id, dt, count)
def is_st_stock(order_book_id, count=1): # type: (str, Optional[int]) -> Union[bool, pd.DataFrame] """ 判断股票在一段时间内是否为ST股(包括ST与*ST)。 ST股是有退市风险因此风险比较大的股票,很多时候您也会希望判断自己使用的股票是否是'ST'股来避开这些风险大的股票。另外,我们目前的策略比赛也禁止了使用'ST'股。 :param order_book_id: 某只股票的代码,可传入单只股票的order_book_id, symbol :param count: 回溯获取的数据个数。默认为当前能够获取到的最近的数据 """ dt = Environment.get_instance().calendar_dt.date() order_book_id = assure_order_book_id(order_book_id) return Environment.get_instance().data_proxy.is_st_stock(order_book_id, dt, count)
def get_split(order_book_ids, start_date=None): # type: (Union[str, List[str]], Optional[Union[str, datetime.date]]) -> pd.DataFrame """ 获取某只股票到策略当前日期前一天的拆分情况(包含起止日期)。 :param order_book_ids: 证券代码,证券的独特的标识符,例如:'000001.XSHE' :param start_date: 开始日期,用户必须指定,需要早于策略当前日期 :return: 查询时间段内的某个股票的拆分数据 * ex_dividend_date: 除权除息日,该天股票的价格会因为拆分而进行调整 * book_closure_date: 股权登记日 * split_coefficient_from: 拆分因子(拆分前) * split_coefficient_to: 拆分因子(拆分后) 例如:每10股转增2股,则split_coefficient_from = 10, split_coefficient_to = 12. :example: .. code-block:: python3 :linenos: get_split('000001.XSHE', start_date='2010-01-04') #[Out] # book_closure_date payable_date split_coefficient_from \ #ex_dividend_date #2013-06-20 2013-06-19 2013-06-20 10 # split_coefficient_to #ex_dividend_date #2013-06-20 16.0 """ # order_book_id 支持list类型 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( _('in get_split, start_date {} is no earlier than the previous test day {}' ).format(start_date, dt)) if isinstance(order_book_ids, six.string_types): order_book_ids = [order_book_ids] order_book_ids = [assure_order_book_id(i) for i in order_book_ids] return rqdatac.get_split(order_book_ids, start_date, dt)
def index_weights(order_book_id, date=None): # type: (str, Optional[Union[str, datetime.date]]) -> pd.Series """ 获取T-1日的指数权重 :param order_book_id: 指数 :param date: 可选,默认为T-1日 :return: 每只股票在指数中的构成权重 :example: 获取上证50指数上个交易日的指数构成 .. code-block:: python3 :linenos: index_weights('000016.XSHG') # [Out] # Order_book_id # 600000.XSHG 0.03750 # 600010.XSHG 0.00761 # 600016.XSHG 0.05981 # 600028.XSHG 0.01391 # 600029.XSHG 0.00822 # 600030.XSHG 0.03526 # 600036.XSHG 0.04889 # 600050.XSHG 0.00998 # 600104.XSHG 0.02122 """ env = Environment.get_instance() data_proxy = env.data_proxy dt = to_date(data_proxy.get_previous_trading_date(env.trading_dt.date())) if date is None: date = dt else: date = to_date(date) if date > dt: raise RQInvalidArgument( _('in index_weights, date {} is no earlier than previous test date {}' ).format(date, dt)) order_book_id = assure_order_book_id(order_book_id) return rqdatac.index_weights(order_book_id, date)
def get_turnover_rate( order_book_ids, # type: Union[str, List[str]] count=1, # type: Optional[int] fields=None, # type: Optional[set] expect_df=False # type: Optional[bool] ): # type: (...) -> Union[pd.Series, pd.DataFrame, pd.Panel] """ 获取截止T-1交易日的换手率数据 :param order_book_ids: 可输入 order_book_id, order_book_id list, symbol, symbol list :param count: 回溯获取的数据个数。默认为当前能够获取到的最近的数据 :param fields: 期望返回的字段,默认为所有字段。见下方列表 :param expect_df: 是否期望始终返回 DataFrame。pandas 0.25.0 以上该参数应设为 True,以避免因试图构建 Panel 产生异常 ========================= =================================================== fields 字段名 ========================= =================================================== today 当天换手率 week 过去一周平均换手率 month 过去一个月平均换手率 three_month 过去三个月平均换手率 six_month 过去六个月平均换手率 year 过去一年平均换手率 current_year 当年平均换手率 total 上市以来平均换手率 ========================= =================================================== 当 expect_df 为 False 时,返回值的类型如下: * 如果只传入一个order_book_id,多个fields,返回 `pandas.DataFrame` * 如果传入order_book_id list,并指定单个field,函数会返回一个 `pandas.DataFrame` * 如果传入order_book_id list,并指定多个fields,函数会返回一个 `pandas.Panel` :example: 获取平安银行历史换手率情况: .. code-block:: python3 :linenos: logger.info(get_turnover_rate('000001.XSHE', count=5)) #[Out] # today week month three_month six_month year \ #2016-08-01 0.5190 0.4478 0.3213 0.2877 0.3442 0.5027 #2016-08-02 0.3070 0.4134 0.3112 0.2843 0.3427 0.5019 #2016-08-03 0.2902 0.3460 0.3102 0.2823 0.3432 0.4982 #2016-08-04 0.9189 0.4938 0.3331 0.2914 0.3482 0.4992 #2016-08-05 0.4962 0.5031 0.3426 0.2960 0.3504 0.4994 # current_year total #2016-08-01 0.3585 1.1341 #2016-08-02 0.3570 1.1341 #2016-08-03 0.3565 1.1339 #2016-08-04 0.3604 1.1339 #2016-08-05 0.3613 1.1338 """ env = Environment.get_instance() data_proxy = env.data_proxy dt = data_proxy.get_previous_trading_date(env.trading_dt) if count == 1: start_dt = dt else: start_dt = data_proxy.get_previous_trading_date(dt, count - 1) if isinstance(order_book_ids, six.string_types): order_book_ids = assure_order_book_id(order_book_ids) else: order_book_ids = [assure_order_book_id(i) for i in order_book_ids] return rqdatac.get_turnover_rate(order_book_ids, start_dt, dt, fields=fields, expect_df=expect_df)
def get_securities_margin( order_book_ids, # type: Union[str, Iterable[str]] count=1, # type: Optional[int] fields=None, # type: Optional[str] expect_df=False # type: Optional[bool] ): # type: (...) -> Union[pd.Series, pd.DataFrame, pd.Panel] """ 获取融资融券信息。包括 `深证融资融券数据 <http://www.szse.cn/main/disclosure/rzrqxx/rzrqjy/>`_ 以及 `上证融资融券数据 <http://www.sse.com.cn/market/othersdata/margin/detail/>`_ 情况。既包括个股数据,也包括市场整体数据。需要注意,融资融券的开始日期为2010年3月31日。 :param order_book_ids: 可输入order_book_id, order_book_id list, symbol, symbol list。另外,输入'XSHG'或'sh'代表整个上证整体情况;'XSHE'或'sz'代表深证整体情况 :param count: 回溯获取的数据个数。默认为当前能够获取到的最近的数据 :param fields: 期望返回的字段,默认为所有字段。见下方列表 :param expect_df: 是否期望始终返回 DataFrame。pandas 0.25.0 以上该参数应设为 True,以避免因试图构建 Panel 产生异常 ========================= =================================================== fields 字段名 ========================= =================================================== margin_balance 融资余额 buy_on_margin_value 融资买入额 margin_repayment 融资偿还额 short_balance 融券余额 short_balance_quantity 融券余量 short_sell_value 融券卖出额 short_sell_quantity 融券卖出量 short_repayment_quantity 融券偿还量 total_balance 融资融券余额 ========================= =================================================== 当 expect_df 为 False 时,返回值的类型如下: * 多个order_book_id,单个field的时候返回DataFrame,index为date,column为order_book_id * 单个order_book_id,多个fields的时候返回DataFrame,index为date,column为fields * 单个order_book_id,单个field返回Series * 多个order_book_id,多个fields的时候返回DataPanel Items axis为fields Major_axis axis为时间戳 Minor_axis axis为order_book_id :example: * 获取沪深两个市场一段时间内的融资余额: .. code-block:: python3 :linenos: logger.info(get_securities_margin('510050.XSHG', count=5)) #[Out] #margin_balance buy_on_margin_value short_sell_quantity margin_repayment short_balance_quantity short_repayment_quantity short_balance total_balance #2016-08-01 7.811396e+09 50012306.0 3597600.0 41652042.0 15020600.0 1645576.0 NaN NaN #2016-08-02 7.826381e+09 34518238.0 2375700.0 19532586.0 14154000.0 3242300.0 NaN NaN #2016-08-03 7.733306e+09 17967333.0 4719700.0 111043009.0 16235600.0 2638100.0 NaN NaN #2016-08-04 7.741497e+09 30259359.0 6488600.0 22068637.0 17499000.0 5225200.0 NaN NaN #2016-08-05 7.726343e+09 25270756.0 2865863.0 40423859.0 14252363.0 6112500.0 NaN NaN * 获取沪深两个市场一段时间内的融资余额: .. code-block:: python3 :linenos: logger.info(get_securities_margin(['XSHE', 'XSHG'], count=5, fields='margin_balance')) #[Out] # XSHE XSHG #2016-08-01 3.837627e+11 4.763557e+11 #2016-08-02 3.828923e+11 4.763931e+11 #2016-08-03 3.823545e+11 4.769321e+11 #2016-08-04 3.833260e+11 4.776380e+11 #2016-08-05 3.812751e+11 4.766928e+11 * 获取上证个股以及整个上证市场融资融券情况: .. code-block:: python3 :linenos: logger.info(get_securities_margin(['XSHG', '601988.XSHG', '510050.XSHG'], count=5)) #[Out] #<class 'pandas.core.panel.Panel'> #Dimensions: 8 (items) x 5 (major_axis) x 3 (minor_axis) #Items axis: margin_balance to total_balance #Major_axis axis: 2016-08-01 00:00:00 to 2016-08-05 00:00:00 #Minor_axis axis: XSHG to 510050.XSHG * 获取50ETF融资偿还额情况 .. code-block:: python3 :linenos: logger.info(get_securities_margin('510050.XSHG', count=5, fields='margin_repayment')) #[Out] #2016-08-01 41652042.0 #2016-08-02 19532586.0 #2016-08-03 111043009.0 #2016-08-04 22068637.0 #2016-08-05 40423859.0 #Name: margin_repayment, dtype: float64 """ env = Environment.get_instance() data_proxy = env.data_proxy dt = data_proxy.get_previous_trading_date(env.trading_dt) if count == 1: start_dt = dt else: start_dt = data_proxy.get_previous_trading_date(dt, count - 1) if isinstance(order_book_ids, six.string_types): order_book_ids = assure_order_book_id(order_book_ids) else: order_book_ids = [assure_order_book_id(i) for i in order_book_ids] return rqdatac.get_securities_margin(order_book_ids, start_dt, dt, fields=fields, expect_df=expect_df)
def get_price( order_book_ids, # type: Union[str, Iterable[str]] start_date, # type: Union[datetime.date, str] end_date=None, # type: Optional[Union[datetime.date, datetime.datetime, str]] frequency='1d', # type: Optional[str] fields=None, # type: Optional[Iterable[str]] adjust_type='pre', # type: Optional[str] skip_suspended=False, # type: Optional[bool] expect_df=False # type: Optional[bool] ): # type: (...) -> Union[pd.DataFrame, pd.Panel, pd.Series] """ 获取指定合约或合约列表的历史行情(包含起止日期,日线或分钟线),不能在'handle_bar'函数中进行调用。 注意,这一函数主要是为满足在研究平台编写策略习惯而引入。在编写策略中,使用history_bars进行数据获取会更方便。 :param order_book_ids: 合约代码,合约代码,可传入order_book_id, order_book_id list, symbol, symbol list :param start_date: 开始日期,用户必须指定 :param end_date: 结束日期,默认为策略当前日期前一天 :param frequency: 历史数据的频率。 现在支持日/分钟级别的历史数据,默认为'1d'。使用者可自由选取不同频率,例如'5m'代表5分钟线 :param fields: 期望返回的字段名称,如 open,close 等 :param adjust_type: 权息修复方案。前复权 - pre,后复权 - post,不复权 - none :param skip_suspended: 是否跳过停牌数据。默认为False,不跳过,用停牌前数据进行补齐。True则为跳过停牌期。注意,当设置为True时,函数order_book_id只支持单个合约传入 :param expect_df: 是否期望始终返回 DataFrame。pandas 0.25.0 以上该参数应设为 True,以避免因试图构建 Panel 产生异常 当 expect_df 为 False 时,返回值的类型如下 * 传入一个order_book_id,多个fields,函数会返回一个pandas DataFrame * 传入一个order_book_id,一个field,函数会返回pandas Series * 传入多个order_book_id,一个field,函数会返回一个pandas DataFrame * 传入多个order_book_id,函数会返回一个pandas Panel ========================= ========================= ============================================================================== 参数 类型 说明 ========================= ========================= ============================================================================== open float 开盘价 close float 收盘价 high float 最高价 low float 最低价 limit_up float 涨停价 limit_down float 跌停价 total_turnover float 总成交额 volume float 总成交量 acc_net_value float 累计净值(仅限基金日线数据) unit_net_value float 单位净值(仅限基金日线数据) discount_rate float 折价率(仅限基金日线数据) settlement float 结算价 (仅限期货日线数据) prev_settlement float 昨日结算价(仅限期货日线数据) open_interest float 累计持仓量(期货专用) basis_spread float 基差点数(股指期货专用,股指期货收盘价-标的指数收盘价) trading_date pandas.TimeStamp 交易日期(仅限期货分钟线数据),对应期货夜盘的情况 ========================= ========================= ============================================================================== :example: 获取单一股票历史日线行情: .. code-block:: python3 :linenos: get_price('000001.XSHE', start_date='2015-04-01', end_date='2015-04-12') #[Out] #open close high low total_turnover volume limit_up limit_down #2015-04-01 10.7300 10.8249 10.9470 10.5469 2.608977e+09 236637563.0 11.7542 9.6177 #2015-04-02 10.9131 10.7164 10.9470 10.5943 2.222671e+09 202440588.0 11.9102 9.7397 #2015-04-03 10.6486 10.7503 10.8114 10.5876 2.262844e+09 206631550.0 11.7881 9.6448 #2015-04-07 10.9538 11.4015 11.5032 10.9538 4.898119e+09 426308008.0 11.8288 9.6787 #2015-04-08 11.4829 12.1543 12.2628 11.2929 5.784459e+09 485517069.0 12.5409 10.2620 #2015-04-09 12.1747 12.2086 12.9208 12.0255 5.794632e+09 456921108.0 13.3684 10.9403 #2015-04-10 12.2086 13.4294 13.4294 12.1069 6.339649e+09 480990210.0 13.4294 10.9877 #... """ env = Environment.get_instance() yesterday = env.trading_dt.date() - datetime.timedelta(days=1) if end_date is not None: end_date = to_date(end_date) if end_date > yesterday: raise RQInvalidArgument( _('in get_price, end_date {} is no earlier than the previous test day {}' ).format(end_date, yesterday)) else: end_date = yesterday start_date = to_date(start_date) if start_date > yesterday: raise RQInvalidArgument( _('in get_price, start_date {} is no earlier than the previous test day {}' ).format(start_date, yesterday)) if end_date < start_date: raise RQInvalidArgument( _('in get_price, start_date {} > end_date {}').format( start_date, end_date)) if isinstance(order_book_ids, six.string_types): order_book_ids = assure_order_book_id(order_book_ids) else: order_book_ids = [assure_order_book_id(i) for i in order_book_ids] return rqdatac.get_price(order_book_ids, start_date, end_date, frequency=frequency, fields=fields, adjust_type=adjust_type, skip_suspended=skip_suspended, expect_df=expect_df)
def order_target_portfolio(target_portfolio): # type: (Dict[Union[str, Instrument], float]) -> List[Order] """ 买入/卖出证券以批量调整证券的仓位,以期使其持仓市值占账户总权益的比重达到指定值。 :param target_portfolio: 下单标的物及其目标市值占比的字典 :example: .. code-block:: python # 调整仓位,以使平安银行和万科 A 的持仓占比分别达到 10% 和 15% order_target_portfolio({ '000001.XSHE': 0.1 '000002.XSHE': 0.15 }) """ if isinstance(target_portfolio, pd.Series): # FIXME: kind of dirty total_percent = sum(target_portfolio) else: total_percent = sum(target_portfolio.values()) if total_percent > 1 and not np.isclose(total_percent, 1): raise RQInvalidArgument( _(u"total percent should be lower than 1, current: {}").format( total_percent)) env = Environment.get_instance() account = env.portfolio.accounts[DEFAULT_ACCOUNT_TYPE.STOCK] account_value = account.total_value target_quantities = {} for id_or_ins, target_percent in target_portfolio.items(): order_book_id = assure_order_book_id(id_or_ins) if target_percent < 0: raise RQInvalidArgument( _(u"target percent of {} should between 0 and 1, current: {}"). format(order_book_id, target_percent)) price = env.data_proxy.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)) continue target_quantities[order_book_id] = (account_value * target_percent / price, price) close_orders, open_orders = [], [] current_quantities = { p.order_book_id: p.quantity for p in account.get_positions() if p.direction == POSITION_DIRECTION.LONG } for order_book_id, quantity in current_quantities.items(): if order_book_id not in target_portfolio: close_orders.append( Order.__from_create__(order_book_id, quantity, SIDE.SELL, MarketOrder(), POSITION_EFFECT.CLOSE)) for order_book_id, (target_quantity, price) in target_quantities.items(): ins = assure_instrument(order_book_id) round_lot = 100 if order_book_id in current_quantities: delta_quantity = target_quantity - current_quantities[order_book_id] else: delta_quantity = target_quantity if _is_ksh(ins): # KSH can buy(sell) 201, 202 shares delta_quantity = _get_ksh_amount(delta_quantity) else: delta_quantity = int( Decimal(delta_quantity) / Decimal(round_lot)) * round_lot if delta_quantity > 0: open_order = Order.__from_create__(order_book_id, delta_quantity, SIDE.BUY, MarketOrder(), POSITION_EFFECT.OPEN) open_order.set_frozen_price(price) open_orders.append(open_order) elif delta_quantity < -1: close_order = Order.__from_create__(order_book_id, abs(delta_quantity), SIDE.SELL, MarketOrder(), POSITION_EFFECT.CLOSE) close_order.set_frozen_price(price) close_orders.append(close_order) submit_orders = [] for order in chain(close_orders, open_orders): if env.can_submit_order(order): submit_orders.append(order) env.broker.submit_order(order) return submit_orders