# 投资研究
基于 IPython NoteBook 搭建的 Ricequant 研究平台为进行策略研究的您提供了丰富的工具。在这里,您既可以享受到 Python 分析、计算库所带来的研究上的便利性,又可以使用经过我们处理并且每日更新的各种高质量数据。
Ricequant 研究平台已引入了金融数据模块 RQData, 高效地为您提供高质量的历史、实时量价数据, 财务因子等数据信息。
举例来说, 您可以新建一个 .ipynb 文件, 输以下代码来获取对应合约的历史数据信息:
# 获取平安银行历史分钟线行情
get_price('000001.XSHE', start_date='20180801', end_date='20180810', frequency='1m')
# RQData 金融数据
Ricequant 数据 SDK - RQData 是一个面向机构的商用版 Python 金融数据工具包。它为量化工程师们提供了丰富整齐的历史数据以及简单高效的 API 接口,最大限度地免除了您进行数据搜索、清洗的烦恼。rqdata 已经集成到投资研究平台中, 可以直接使用。有关 API 文档您可以参考 RQData 使用文档
Ricequant 为您提供的每日更新的数据包括:
- 中国 A 股、ETF,中国期货(股指、国债、商品期货),上金所现货的所有基本信息
- 中国 A 股、ETF 过去 10 多年以来每日市场数据
- 中国 A 股、ETF2005 年以来的分钟线数据
- ETF 过去 20 多年以来的所有市场数据
- 中国 A 股上市以来的所有财务数据
- 中国期货从 1999 年以来的每日行情数据
- 中国期货 2010 年以来的分钟线数据
- 舆情大数据
- 中国 50ETF、商品期权上市以来的日线、分钟线数据
# RQPortal API - 获取策略回测及模拟交易数据(Alpha 版)
rqportal 模块的加入使得用户分析自己策略回测和模拟交易的结果成为可能。目前 rqportal 提供的 api 可以获取某个策略回测和某个模拟交易的交易, 持仓和收益等回测和模拟交易数据。需要注意的是,该功能目前处于实验阶段,不排除未来修改接口的可能。
以下 API 中所需传入的 run_id 可以在历史回测和模拟交易的列表中找到,如下图:
# rqportal.info - 获取回测或模拟交易基础信息
rqportal.info(run_id)
# 参数
参数 类型 说明 run_id int 回测运行 ID/模拟交易 ID, 可从回测历史列表或模拟交易列表中获取 type str ID 所属的类型,默认为 backtest。
回测 - backtest,
模拟交易 - papertrading
# 返回
Python dict
参数 类型 说明 title str 回测策略名称/模拟交易名称 start_date datetime 回测/模拟交易开始时间 end_date datetime 回测/模拟交易结束时间 time_unit str DAY - 日回测/日模拟 MINUTE - 分钟回测/分钟模拟 type str STOCK - 股票 FUTURE - 期货 stock_init_cash float 股票账户初始资金 future_init_cash float 期货账户初始资金
# rqportal.risk - 获取回测或模拟交易风险数据
rqportal.risk(run_id)
# 参数
参数 类型 说明 run_id int 回测运行 ID/模拟交易 ID, 可从回测历史列表或模拟列表中获取 type str ID 所属的类型,默认为 backtest。
回测 - backtest,
模拟交易 - papertrading
# 返回
Python dict
参数 类型 说明 cash float 回测/模拟交易期末资金 market_value float 回测/模拟交易期末总市值 alpha float alpha 值 annual_downside_risk float 年度下跌风险 annual_volatility float 年度收益波动率 beta float beta 值 information_ratio float 信息比率 max_drawdown float 最大回撤 portfolio_value float 总权益 sharpe float 夏普比率 sortino float 索提诺比率 total_returns float 总收益
# rqportal.portfolio - 获取每日收益数据
rqportal.portfolio(run_id, start_date, end_date)
# 参数
参数 类型 说明 run_id int 回测运行 ID/模拟交易 ID, 可从回测历史列表中获取 type str ID 所属的类型,默认为 backtest。
回测 - backtest,
模拟交易 - papertradingstart_date str 开始日期, 格式为 'YYYY-mm-dd', 默认从回测/模拟交易最早的日期开始 end_date str 结束日期, 格式为 'YYYY-mm-dd', 默认以回测/模拟交易最晚的日期结束
# 返回
pandas DataFrame - 收益
每列的定义可参考portfolio
# 范例
- 获取回测 ID 为 2012 的每日收益数据
[In]: rqportal.portfolio(2012)
[Out]:
daily_returns pnl total_returns annualized_returns cash benchmark_daily_returns
2010-01-04 15:00:00 0.000000 0.00 0.000000 0.000000 100000.000000 -0.017267
2010-01-05 15:00:00 0.000000 0.00 0.000000 0.000000 100000.000000 0.007915
...
2015-11-03 15:00:00 -0.032762 -12187.12 2.598044 0.245341 467.473962 -0.002924
2015-11-04 15:00:00 0.069233 24910.28 2.847147 0.259573 467.473962 0.045671
- 获取回测 ID 为 2012 的一段时间内每日收益数据
[In]: rqportal.portfolio(2012, start_date="2011-09-10", end_date="2011-10-20")
[Out]:
daily_returns pnl total_returns annualized_returns cash benchmark_daily_returns
2011-09-13 15:00:00 -0.000128 -16.014597 0.246833 0.139163 65724.616896 0.000000
2011-09-14 15:00:00 -0.000596 -74.260000 0.246090 0.138523 65724.616896 -0.006299
2011-09-15 15:00:00 -0.000294 -36.660000 0.245724 0.138088 65724.616896 -0.001430
2011-09-16 15:00:00 -0.001494 -186.120000 0.243863 0.136851 65724.616896 0.001742
2011-09-19 15:00:00 -0.007149 -889.240000 0.234970 0.131392 65724.616896 -0.019277
2011-09-20 15:00:00 0.001499 185.180000 0.236822 0.132159 65724.616896 0.003799
# rqportal.positions - 获取每日持仓数据
rqportal.positions(run_id, start_date, end_date)
# 参数
参数 类型 说明 run_id int 回测运行 ID/模拟交易 ID, 可从回测历史列表/模拟交易列表中获取 type str ID 所属的类型,默认为 backtest。
回测 - backtest,
模拟交易 - papertradingstart_date str 开始日期, 格式为 'YYYY-mm-dd', 默认从回测/模拟交易最早的日期开始 end_date str 结束日期, 格式为 'YYYY-mm-dd', 默认以回测/模拟交易最晚的日期结束
# 返回
pandas DataFrame - 每日投资组合中每个证券的市场价值
# 范例
- 获取回测 ID 为 2012 的每日投资组合中每个证券的市场价值
[In]: rqportal.positions(2012)
[Out]:
cash 000916.XSHE 000926.XSHE 002485.XSHE 600270.XSHG 600626.XSHG 601718.XSHG
...
2013-10-08 15:00:00 42.49148 9368.5 53664.72 1867.25 14056.25 38426.75 31464
2013-10-09 15:00:00 42.49148 9614.5 53376.20 1867.25 15470.00 40183.00 31464
...
2013-10-31 15:00:00 42.49148 8097.5 52799.16 1716.00 17485.00 37935.00 30438
2013-11-01 15:00:00 42.49148 7933.5 52943.42 1738.00 17696.25 37935.00 30552
# rqportal.trades - 获取每日交易数据
rqportal.trades(run_id, start_date, end_date)
# 参数
参数 类型 说明 run_id int 回测运行 ID/模拟交易 ID, 可从回测历史列表/模拟交易列表中获取 type str ID 所属的类型,默认为 backtest。
回测 - backtest,
模拟交易 - papertradingstart_date str 开始日期, 格式为 'YYYY-mm-dd', 默认从回测/模拟交易最早的日期开始 end_date str 结束日期, 格式为 'YYYY-mm-dd', 默认以回测/模拟交易最晚的日期结束
# 返回
pandas DataFrame - 每日交易数据
参数 类型 说明 order_book_id str 合约代码 price float 成交价 quantity float 成交量(股数),正数为买入,负数为卖出 transaction_cost float 交易产生的费用,包括佣金、印花税等加总 position_effect str OPEN - 开仓 CLOSE - 平仓 CLOSE_TODAY - 今平 side str BUY - 买,SELL - 卖
# Ipython 运行回测的三种回测方式
Ricequant 内在的策略引擎 - 用户可以在 Ipython 中直接使用该策略引擎进行策略研发。
# 1、使用 rqalpha_plus 进行回测
%%rqalpha_plus -s 20160301 -e 20160901 --account stock 10000 -fq 1d -p -bm 000001.XSHG
# 上述命令参数可以通过运行 %%rqalpha_plus -h 查看到
def init(context):
# 策略初始化运行
logger.info('init')
context.counter = 0
def before_trading(context):
# 每日开盘前运行
pass
def handle_bar(context, bar_dict):
# 每个 bar 数据运行
context.counter += 1
if context.counter == 1:
order_shares('000001.XSHE', 500)
def after_trading(context):
# 每日收盘后运行
pass
运行上列代码之后,在研究中继续输入
In []:report.keys()
Out []:dict_keys(['portfolio', 'benchmark_portfolio', 'trades', 'stock_positions', 'stock_account', 'summary'])
# 2、使用 run_func 进行回测
from rqalpha_plus.apis import *
#以上操作会导致当前数据获取API被覆盖,所以在运行完毕之后需要通过 from rqdatac import * 的方式恢复
from rqalpha_plus import run_func
#config 中可设置选项可以通过 %%rqalpha_plus -h 查看到
config = {
"base": {
"start_date": "2016-03-01", # 回测开始日期
"end_date": "2016-09-01", # 回测结束日期
"frequency": '1d', # 回测频率, 分钟: '1m'
"accounts": {
"stock": 100000# 股票初始资金 期货:"future":100000
}
},
"mod": {
"sys_progress": {
"enabled": True,
"show": True,
},
"sys_analyser": {
"enabled": True,
"benchmark": "000001.XSHG", # 基准合约
},
"sys_simulation": {
"matching_type": "current_bar",
}
}
}
def init(context):
context.s1 = "000001.XSHE"
context.fired = False
def handle_bar(context, bar_dict):
if not context.fired:
# order_percent并且传入1代表买入该股票并且使其占有投资组合的100%
order_percent(context.s1, 1)
context.fired = True
results = run_func(init=init, config=config, handle_bar=handle_bar)
#如果您有自己的函数命名习惯,则可以通过以下指定函数名的方式运行回测
#results = run_func(init=init, handle_bar=handle_bar, before_trading=before_trading, after_trading=after_trading, config=config)
#下面的 import 将之前 from rqalpha_plus.api import * 的覆盖恢复
from rqdatac import *
策略框架支持的 config 主要设置项如下:
支持的 config 设置项
config = {
'base': {
'start_date': '2016-06-01',
'end_date': '2016-12-01',
# 回测频率,1d, 1m, tick
'frequency': '1d',
# 回测所需 bundle 数据地址,可设置为 RQPro 终端【个人设置】的【数据下载路径】
'data_bundle_path': './bundle',
# 策略文件地址
'strategy_file': './strategy.py',
# 保证金倍率。基于基础保证金水平进行调整
'margin_multiplier': 1,
# 运行类型。b 为回测,p 为模拟交易,r 为实盘交易
'run_type': 'b',
# 期货交易佣金设置
'future_info': {
# 期货品种
'SC': {
# 平仓费率
'close_commission_ratio': 0.00005,
# 开仓费率
'open_commission_ratio': 0.00005,
# 平今费率
'close_commission_today_ratio': 0,
# BY_MONEY 为按照名义价值收取, BY_VOLUME 为根据成交合约张数收取
'commission_type': 'BY_MONEY',
},
},
# 账户类别及初始资金
'accounts': {
'stock': 1000,
'future': 2000
},
# 初始仓位,为合约: 持仓数量方式,对应建仓成本为回测起始日期合约的收盘价
'init_positions': "000001.XSHE: 100,000002.XSHE: 500",
},
'extra': {
# 是否开启性能分析
'enable_profiler': False,
# 输出日志等级,有 verbose, info, warning, error 等选项,可以通过设置为 verbose 来查看最详细日志
'log_level': 'info',
},
'mod': {
# 模拟撮合模块
'sys_simulation': {
'enabled': True,
# 是否开启信号模式。如果开启,限价单将按照指定价格成交,并且不受撮合成交量限制
'signal': False,
# 撮合方式。current_bar 当前 bar 收盘价成交,next_bar 下一 bar 开盘价成交,best_own 己方最优价格成交(tick 回测使用)
# best_counterparty 对手方最优价格成交(tick 回测使用),last 最新价成交(tick 回测使用)
'matching_type': 'current_bar',
# 是否允许涨跌停状态下买入、卖出
'price_limit': True,
# 是否开启成交量限制
'volume_limit': True,
# 按照 bar 数据成交量的一定比例进行限制,超限部分无法在当前 bar 一次性撮合成交
'volume_percent': 0.25,
# 滑点模型。PriceRatioSlippage 为基于价格比例的滑点模型,TickSizeSlippage 为基于最小价格变动单位的滑点模型
'slippage_model': 'PriceRatioSlippage',
# 滑点值
'slippage': 0,
},
# 风控模块
'sys_risk': {
'enabled': True,
# 检查可用资金是否足够
'validate_cash': True,
# 检查可平仓位是否足够
'validate_position': True,
},
# 分析模块
'sys_analyser': {
'enabled': True,
"benchmark": "000001.XSHG", # 基准合约
# 是否画图
'plot': True,
# 指定输出回测报告 csv 路径
'report_save_path': None,
},
'sys_transaction_cost': {
'enabled': True,
# 设置最小佣金费用
'cn_stock_min_commission': 5,
# 佣金倍率
'commission_multiplier': 1,
}
}
}
# 3、使用 run_code 进行回测
from rqalpha_plus import run_code
config = {
"base": {
"start_date": "2016-03-01", # 回测开始日期
"end_date": "2016-09-01", # 回测结束日期
"frequency": '1d', # 回测频率, 分钟: '1m'
"accounts": {
"stock": 100000# 股票初始资金 期货:"future":100000
}
},
"extra": {
"log_level": "info",
},
"mod": {
"sys_progress": {
"enabled": True,
"show": True,
},
"sys_analyser": {
"enabled": True,
"benchmark": "000001.XSHG", # 基准合约
'plot': True,
},
"sys_simulation": {
"matching_type": "current_bar",
}
}
}
code="""
def init(context):
context.s1 = "000001.XSHE"
update_universe(context.s1)
context.fired = False
def before_trading(context):
pass
def handle_bar(context, bar_dict):
if not context.fired:
# order_percent并且传入1代表买入该股票并且使其占有投资组合的100%
order_percent(context.s1, 1)
context.fired = True
"""
results = run_code(code, config)
[2017-06-15 14:24:59.671903] INFO: system_log: rqdatac use socket (None, None)
# 获取回测报告
运行完回测后,报告会自动存储到 report
变量中。可以直接通过 report
变量获取当次回测的结果。run_func
, run_code
函数本身也会返回回测结果,您可以将其保存到指定的变量中。另外 rqalpha 的 mod 的输出会自动存储在 results
变量中。
In[]:report.portfolio.head()
In[]:report.keys()
Out[]:dict_keys(['portfolio', 'benchmark_portfolio', 'trades', 'summary', 'stock_positions', 'stock_account'])
In[]:
import matplotlib.pyplot as plt
report.portfolio.unit_net_value.plot(legend='unit_net_value')
plt.show()
# 查看运行命令帮助
In[]:%%rqalpha_plus -h
Out[]:
sage: ipykernel_launcher.py [OPTIONS]
Start to run a strategy
Options:
-h, --help Show this message and exit.
-f, --strategy-file PATH
-s, --start-date DATE
-e, --end-date DATE
-mm, --margin-multiplier FLOAT
-a, --account TEXT... set account type with starting cash
--position TEXT set init position
-fq, --frequency [1d|1m|tick]
-rt, --run-type [b|p|r]
-rp, --round-price
-mk, --market [cn|hk]
--source-code TEXT
--rqdatac, --rqdatac-uri TEXT rqdatac uri, eg user:password or or
license:xxxxxxx or
tcp://user:password@ip:port
-l, --log-level [verbose|debug|info|error|none]
--logger TEXT... config logger, e.g. --logger system_log
debug
--locale [cn|en]
--extra-vars TEXT override context vars
--enable-profiler add line profiler to profile your strategy
--config TEXT config file path
-mc, --mod-config TEXT... mod extra config
--resume [DEPRECATED] --resume is deprecated
-rdu, --rqdatad-username TEXT [ricequant_data] rqdatad username
-rdpw, --rqdatad-password TEXT [ricequant_data] rqdatad password
-rda, --rqdatad-addr TEXT [ricequant_data] rqdatad server address
-rdpt, --rqdatad-port INTEGER [ricequant_data] rqdatad server port
--night-trading [ricequant_data] night trading
--redis-url TEXT [ricequant_data] bar & event redis url
-d, --data-bundle-path PATH [ricequant_data] data bundle path
--h5-tick-path TEXT [ricequant_data] path of hdf5 tick bundle
--h5-minbar-path TEXT [ricequant_data] path of hdf5 minute bar
bundle
--tick-type TEXT [ricequant_data] data sourc of bt on tick
frequency. choose in [h5, rqdata]
--stock-t1 / --no-stock-t1 [sys_accounts] enable/disable stock T+1
--dividend-reinvestment [sys_accounts] enable dividend reinvestment
--cash-return-by-stock-delisted / --no-cash-return-by-stock-delisted
[sys_simulation] return cash when stock
delisted
--no-short-stock / --short-stock
[sys_simulation] enable stock shorting
--signal [sys_simulation] exclude match engine
-sp, --slippage FLOAT [sys_simulation] set slippage
--slippage-model TEXT [sys_simulation] set slippage model
-mt, --matching-type [current_bar|next_bar|last|best_own|best_counterparty|vwap]
[sys_simulation] set matching type
--inactive-limit BOOLEAN [sys_simulation] Limit transaction when
volume is 0
--management-fee TEXT... [sys_simulation] Account management rate. eg
'--management-fee stock 0.0002'
--progress [sys_progress]show progress bar
--cash-validation / --no-cash-validation
[sys_risk] enable cash validation
--report PATH [sys_analyser] save report
-o, --output-file PATH [sys_analyser] output result pickle file
-p, --plot / --no-plot [sys_analyser] plot result
--plot-save TEXT [sys_analyser] save plot to file
-bm, --benchmark TEXT [sys_analyser] order_book_id of benchmark
-cm, --commission-multiplier FLOAT
[sys_simulation] set commission multiplier
-cnsmc, --cn-stock-min-commission FLOAT
[sys_simulation] set minimum commission in
chinese stock trades.
-hksmc, --hk-stock-min-commission FLOAT
[sys_simulation] set minimum commission in
Hong Kong stock trades.
-smc, --stock-min-commission FLOAT
[sys_simulation][deprecated] set minimum
commission in chinese stock trades.
-tm, --tax-multiplier FLOAT [sys_simulation] set tax multiplier
--valuation-source TEXT [ricequant_bond_backtest]
valuation_source.choose in [chinabond,
exchange, auto]
# 参数调优
In[]:
import os
from rqalpha_plus import run_func
from rqalpha_plus.apis import *
config = {
'extra': {
'log_level': 'error',
},
'base': {
'start_date': '2015-01-01',
'end_date': '2016-01-01',
'frequency': '1d',
'accounts': {
'stock': 100000
}
},
'mod': {
'sys_progress': {
'enabled': True,
'show': True,
},
'sys_analyser': {
'enabled': True,
'benchmark': '000001.XSHE',
'plot': True,
},
'sys_simulation': {
"matching_type": "current_bar",
}
}
}
tasks = []
for signal in range(1, 101, 20):
tasks.append((config, signal))
def run_bt(config, signal):
def init(context):
context.s1 = '000001.XSHE'
context.counter = 0
context.signal = signal
def handle_bar(context, bar_dict):
context.counter += 1
if context.counter == context.signal:
order_target_percent(context.s1, 0.8)
result = run_func(config=config, init=init, handle_bar=handle_bar)
return result, signal
results = []
for task in tasks:
result = run_bt(*task)
results.append({'signal': result[1],
'sharpe': result[0]['sys_analyser']['summary']['sharpe']})
In[]: results_df = pd.DataFrame(results)
#根据 sharpe 进行排序,并且获取对应 signal 值
print(results_df.sort_values('sharpe', ascending=False))
Out[]:
sharpe signal
4 1.694 81
1 1.513 21
0 1.362 1
2 0.593 41
3 0.053 61
# 其他
# 读取自己的数据文件
上传在研究平台的文件可以通过函数进行读取,例如 csv 文件可以直接通过 pandas read_csv 等函数读取,其他文件格式可以选择通过 get_file 这一 API 读取。
get_file(file_path)
读取您的私有文件(您的私有文件可以在研究模块中看到)
参数
参数 类型 注释 file_path str 相对路径,相对于您的私有的在研究模块空间的根目录的路径
返回
返回文件的原始内容,不做任何 decode。
范例
df = get_price('000001.XSHE')
df.to_csv('day_px.csv')
import pandas as pd
from six import StringIO
from six import BytesIO
body = get_file('day_px.csv')
data=pd.read_csv(BytesIO(body))
data
# 保存自己的数据到 csv 文件
目前我们支持您在 IPython 策略研究平台上产生的数据保存成 csv 文件。只需要使用以下简单代码即可实现保存到 csv 功能:
import pandas as pd
df = pd.DataFrame(xxxx)
df.to_csv('xxxx.csv')
回到 IPython 平台的首页,您就会看到您的刚才保存的 csv 数据文件了。当然,您也可以将其下载到本地保存。
# 安装第三方库
用户可通过下面的步骤下在 IPython Notebook 中安装自己需要的第三方库,如QuantLib
- 在 ipynb 文件中输入
pip install QuantLib --user
- 点击重启 kernel