Welcome to quantlib’s documentation!¶
Tutorial¶
获取Wind数据¶
直接从万得SQL数据库查询数据,需要设置数据库连接信息。
配置信息¶
使用万得数据库需要配置数据库对应的连接信息。
配置文件``~/.quantlib/config.cfg``:
wind_db_driver = ‘pymysql’wind_db_type = ‘mysql’wind_host = ‘localhost’wind_port = 3306wind_username = ‘wind’wind_password = ‘password’wind_db_name = ‘quant’
基本用法¶
股票基本信息¶
from quant.data import wind
wind.get_stock_basics()
量价数据¶
wind.get_data("AShareEODPrices", "s_dq_pctchange")
格式为 wind.get_data(表名,列名)
,会以trade_dt为index,s_info_windcode为column重新排列数据。
日衍生数据¶
# 获取A股个股市值
wind.get_data("AShareEODDerivativeIndicator", "s_val_mv")
万得数据库原始表¶
wind.get_table("AShareEODPrices", ["s_info_windcode", "trade_dt", "s_dq_adjclose", "s_dq_adjopen"])
获取指数权重¶
# 获取中证500指数的免费权重
wind.get_index_weight("AIndexHS300FreeWeight", "000905.SH")
获取A股特殊处理信息¶
# AShareST表示通过entry_dt和remove_dt来维护股票进入ST和离开ST的时间的
# arrange_entry_table把该信息重新整理成以交易日为行、股票为列的“交易日”表
# 最后把剩下的NA用False填充
wind.arrange_entry_table("AShareST").fillna(False)
获取分析师预测数据¶
# 获取预测一年的平均每股收益
wind.get_consensus_data('eps_avg', 1)
获取股票行业分类¶
# 获取中国A股中信行业分类 (一级分类)
wind.get_stock_industries("AShareIndustriesClassCITICS", 1)
策略回测¶
起步¶
一个简单的股票回测程序只需要继承一个抽象策略类,定义一个选股策略就可以,一个简单的例子是:
from quant.backtest.stock.strategy import AbstractStrategy
class SimpleStrategy(AbstractStrategy):
start_date = "2017-03-01"
def handle(self, today, universe):
self.change_position({universe[0]: 0.1})
这个简单的策略定义了从2017年3月开始回测,每天选择可选股票池中的第一只股票买入10%的仓位。
运行 SimpleStrategy().run()
运行回测,几秒钟后,会输出简单的年化收益率、年化波动率和夏普率信息。
同时,还会生成一个以策略名和运行时间命名的网页,记录着回测的详细信息。如果是在视窗环境下的话,浏览器会自动打开该网页。如图所示。

回测方法¶
quantlib提供 quant.backtest.strategy.Strategy
类作为所有策略的基类。用户可以继承该类并通过重载 __init__
方法
和 handle
方法来自定义策略的行为。另外,quantlib也提供 SimpleStrategy
和 ConstraintStrategy
来提供通用
而方便的回测功能。
SimpleStrategy¶
SimpleStrategy(predicted, name=None, buy_count=50, mods=None)
通过传入一个 DataFrame
对象, SimpleStrategy`` 每期做多分数最高的 ``buy_count
只股票。
ConstraintStrategy¶
ConstraintStrategy
根据传入的DataFrame的值、及一系列约束条件,来优化出在给定风险暴露的前提下
期望收益率最大的组合,并买入该组合。
import numpy as np
import pandas as pd
from quant.backtest.strategy import ConstraintStrategy
from quant.backtest.common.mods import AbstractMod
from quant.common.settings import CONFIG
CONFIG.BENCHMARK = "000905.SH"
config = {
"factors": {
"Beta": 1.0,
"Size": 0.5,
"BookToPrice": 0.5,
"ResidualVolatility": 0.5,
"NonLinearSize": 0.5,
"Liquidity": 0.5,
"Leverage": 0.5,
"Momentum": 0.5
},
"industries": {
"Automobile": 0.05,
"LightIndustry": 0.05,
"Medical": 0.05,
"FundamentalChemistry": 0.05,
"Media": 0.05,
"BuildingMaterials": 0.05,
"ElectricDevice": 0.05,
"Construction": 0.05,
"ElectronicComponents": 0.05,
"RealEstate": 0.05,
"Food": 0.05,
"Retail": 0.05,
"Petroleum": 0.05,
"Composite": 0.05,
"Computer": 0.05,
"Communication": 0.05,
"Mechanism": 0.05,
"Iron": 0.05,
"NonbankFinance": 0.05,
"Transportation": 0.05,
"Public": 0.05,
"Agriculture": 0.05,
"Military": 0.05,
"ElectricalAppliance": 0.05,
"Clothing": 0.05,
"NonferrousMetal": 0.05,
"Bank": 0.05,
"Tourism": 0.05,
"Coal": 0.05
},
"stocks": 0.02
}
data = pd.DataFrame(...)
strategy = ConstraintStrategy(config, data, name="constraint_strategy")
strategy.run()
以上代码在约束单只股票最大持仓2%、行业暴露5%、风格暴露0.5的前提下优化目标收益率最大的持仓比例并进行回测。
模块¶
本回测框架提供一些可选模块来支持扩展特性,同时也允许用户自定义模块。默认提供的模块有:
Mod Name | Purpose |
---|---|
NoSTUniverse* | Remove ST stocks from universe |
NoIPOUniverse* | Remove new stocks from universe |
NoUpLimitUniverse* | Remove stocks that reach up-limit from universe |
ActivelyTraded* | Remove inactive stocks (daily amount<10million) |
ShowBasicResults* | Show simple statistic infomation after backtest |
Abigale* | Generate analytical details for abigale2 |
Output | Save position information to ‘output.h5’ |
Visualizer | Show details of backtest in webpage (abigale is preferred) |
默认以上所有模块都会自动被加载,用户也可以在策略类的mods属性中定义自己要使用的模块,如:
class Strategy(AbstractStrategy):
mods = ["ShowBasicResults"]
则以上策略只会显示简单的回测信息,且不会对可选股票池作任何变化。
开发者¶
To be expected.
命令行¶
quantlib提供一些在命令行使用的快捷命令,通过 python -m quant
来调用这些命令。
数据集管理¶
quantlib使用 quant.common.decorators.Localizer
来缓存数据,这些数据默认保存在 ~/.quantlib/data
目录下,每个数据集保存成一个hdf5文件。
每个文件中可以有多个DataFrame数据。 python -m quant data
命令可以用来管理这些数据集。
数据表管理¶
quantlib的WindDB会把从wind数据库取得的原始数据缓存在wind_table.h5中。久而久之这个数据集会非常庞大。如果每次更新数据都要把整个数据集删除的话非常不方便。
因此,quantlib提供了额外的命令行 python -m quant table
来专门管理wind_table中的数据表。
列出所有的键¶
python -m quant table ls
增量更新所有的表¶
python -m quant table update
增量更新指定的表¶
python -m quant table update "表名"
删除某个数据表¶
python -m quant table rm "表名"
删除某个表的字段¶
python -m quant table rm "表名/字段名"
API¶
quant.barra¶
基类¶
-
class
quant.barra.factors.
Descriptor
[源代码]¶ Methods
B2P
quant.barra.factors.book_to_price.BToP
的别名BLEV
Book leverage Beta
quant.barra.factors.beta.BetaDescriptor
的别名CETOP
quant.barra.factors.earnings_yield.CEToP
的别名CMRA
()Cumulative range DASTD
()Daily standard deviation DTOA
quant.barra.factors.leverage.DToA
的别名EGRLF
Long-term predicted earnings growth EGRO
Earnings growth (trailing five years) EGRSF
Short-term predicted earnings growth EPFWD
Predicted earnings-to-price ratio ETOP
quant.barra.factors.earnings_yield.EToP
的别名HSigma
()Historical sigma LD
Long-term debt LnCap
Natural log of market cap MLEV
Market leverage NLSize
Cube of Size RSTR
Relative strength STOA
()Share turnover, trailing 12 months STOM
()Share turnover, one month STOQ
()Share turnover, trailing 3 months get_raw_value
()返回原始值。需重载此方法 get_zscore
()返回zscore register
(name)注册一个Descriptor,注册以后可以通过Descriptor.xxx来引用这个类
-
class
quant.barra.factors.
Factor
(name, descriptors, weights, disentangle=None)[源代码]¶ Methods
get_exposures
([fillna])返回每只股票每天在该因子上的暴露 get_factors
()返回所有已注册的因子
Descriptor¶
Beta¶
-
class
quant.barra.factors.beta.
BetaDescriptor
¶ Beta
Computed as the slope coefficient in a time-series regression of excess stock return, \(r_t - r_{ft}\), against the cap-weighted excess return of the estimation universe \(R_t\),
\[r_t-r_{ft} = \alpha + \beta R_t + e_t\]The regression coefficients are estimated over the trailing 252 trading days of returns with a half-life of 63 trading days.
RSTR¶
-
class
quant.barra.factors.momentum.
RSTR
¶ Relative strength
Computed as the sum of excess log returns over the trailing T = 504 trading days with a lag of L=21 tradingdays,
\[RSTR = \Sigma_{t=L}^{T+L}w_t[ln(1+r_t)-ln(1+r_{ft})]\]where \(r_t\) is the stock return on day t, \(r_{ft}\) is the risk-free return, and \(w_t\) is an exponential weight with a half-life of 126 trading days.
LnCap¶
-
class
quant.barra.factors.size.
LnCap
¶ Natural log of market cap
Given by the logarithm of the total market capitalization of the firm.
BToP¶
-
class
quant.barra.factors.book_to_price.
B2P
¶ Book-to-price ratio
Last reported book value of common equity divided by current market capitalization.
EPFWD¶
-
class
quant.barra.factors.earnings_yield.
EPFWD
¶ Predicted earnings-to-price ratio
Given by the 12-month forward-looking earnings divided by the current market capitalization. Forward-looking earnings are defined as a weighted average between the average analyst-predicted earnings for the current and next fiscal years.
CEToP¶
-
class
quant.barra.factors.earnings_yield.
CEToP
¶ Cash earnings-to-price ratio
Given by the trailing 12-month cash earnings divided by current price.
EToP¶
-
class
quant.barra.factors.earnings_yield.
EToP
¶ Trailing earnings-to-price ratio
Given by the trailing 12-month earnings divided by the current market capitalization. Trailing earnings are defined as the last reported fiscal-year earnings plus the difference between current interim figure and the comparative interim figure from the previous year.
EGRLF¶
-
class
quant.barra.factors.growth.
EGRLF
¶ Long-term predicted earnings growth
Long-term (3-5 years) earnings growth forecasted by analysts.
EGRSF¶
-
class
quant.barra.factors.growth.
EGSRLF
¶ Short-term predicted earnings growth
Short-term (1 year) earnings growth forecasted by analysts.
EGRO¶
-
class
quant.barra.factors.growth.
EGSRO
¶ Earnings growth (trailing five years)
Annual reported earnings per share are regressed against time over the past five fiscal years. The slope coefficient is then divided by the average annual earnings per share to obtain the earnings growth.
MLEV¶
-
class
quant.barra.factors.leverage.
MLEV
¶ Market leverage
Computed as MLEV = (ME + PE + LD) / ME where ME is the market value of common equity on the last trading day, PE is the most recent book value of preferred equity, and LD is the most recent book value of long-term debt.
BLEV¶
-
class
quant.barra.factors.leverage.
BLEV
¶ Book leverage
Computed as BLEV = (BE + PE + LD) / ME where BE is the book value of common equity on the last trading day, PE is the most recent book value of preferred equity, and LD is the most recent book value of long-term debt.
DToA¶
-
class
quant.barra.factors.leverage.
DToA
¶ Debt-to-assets
Computed as
\[DTOA = TD / TA\]where TD is the book value of total debt (long-term debt and current liabilities), and TA is most recent book value of total assets.
STOM¶
-
class
quant.barra.factors.liquidity.
STOM
¶ Share turnover, one month
Computed as the log of the sum of daily turnover during the previous 21 trading days,
\[STOM = ln[\Sigma_{t=1}^{21}\frac{V_t}{S_t}]\]where Vt is the trading volume on day t , and St is the number of shares outstanding.
STOQ¶
-
class
quant.barra.factors.liquidity.
STOQ
¶ Share turnover, trailing 3 months
Let STOM_t be the share turnover for month t , with each month consisting of 21 trading days. The quarterly share turnover is defined by
\[STOQ = ln[\frac{1}{T}\Sigma_{t=1}{T}exp\{STOM_t\}]\]where T = 3 months.
STOA¶
-
class
quant.barra.factors.liquidity.
STOA
¶ Share turnover, trailing 12 months
Let STOM_t be the share turnover for month t , with each month consisting of 21 trading days. The quarterly share turnover is defined by
\[STOQ = ln[\frac{1}{T}\Sigma_{t=1}{T}exp\{STOM_t\}]\]where T = 12 months.
NLSize¶
DASTD¶
CMRA¶
HSigma¶
Factors¶
Beta¶
BookToPrice¶
EarningsYield¶
Growth¶
Leverage¶
Liquidity¶
Momentum¶
NonLinearSize¶
ResidualVolatility¶
Size¶
quant.backtest¶
-
class
quant.backtest.strategy.
AbstractStrategy
[源代码]¶ 股票回测策略基类
Attributes: - end_date
- mods
net_value
净值序列, pd.Series
- start_date
Methods
change_position
(tobuy_pct)更新持仓比例 handle
(today, universe)每日调仓函数,用户逻辑,需重载 run
()运行回测过程 -
end_date
= None¶ 结束日期 %Y-%m-%d
-
mods
= None¶ 可用Mod列表
-
name
= 'strategy'¶ 策略名称,用于结果输出
-
net_value
¶ 净值序列, pd.Series
-
start_date
= None¶ 起始日期 %Y-%m-%d
-
class
quant.backtest.strategy.
SimpleStrategy
(predicted, name=None, buy_count=50, mods=None)[源代码]¶ 简单的回测,只需要输入一个预测收益率的DataFrame, 每期自动等权做多预测最高的`buy_count`只股票
Attributes: - end_date
- mods
net_value
净值序列, pd.Series
- start_date
Methods
change_position
(tobuy_pct)更新持仓比例 handle
(today, universe)每日调仓函数,用户逻辑,需重载 run
()运行回测过程
-
class
quant.backtest.strategy.
ConstraintStrategy
(*args, constraint_config=None, **kwargs)[源代码]¶ 中性策略,在SimpleStrategy的基础上控制行业和因子暴露 # TODO: cost in objective
Attributes: - end_date
- mods
net_value
净值序列, pd.Series
- start_date
Methods
change_position
(tobuy_pct)更新持仓比例 handle
(today, universe)每日调仓函数,用户逻辑,需重载 optimize_with_mosek
(predicted, today)使用Mosek来优化构建组合。在测试中Mosek比scipy的单纯形法快约18倍,如果可能请尽量使用Mosek。 但是Mosek是一个商业软件,因此你需要一份授权。如果没有授权的话请使用scipy或optlang。 optimize_with_optlang
(predicted, today)Optlang是一个支持很多后端优化器的接口,包括scipy。 optimize_with_scipy
(predicted, today)最大化预期收益,最小化风险暴露。 run
()运行回测过程
quant.data¶
quant.data.wind¶
-
class
quant.data.wind.
WindDB
[源代码]¶ 万得金融数据库接口
Methods
add_wind_columns get_all_columns get_fetched_columns get_unfetched_columns get_wind_connection sql_select update_last_update_time update_wind_table
-
class
quant.data.wind.
WindData
[源代码]¶ 万得金融数据库接口
Methods
arrange_entry_table
(table, …)把带有entry_dt, remove_dt的表重新整理成以股票为列、日期为行的透视表 get_consensus_data
(field, est_years)A股盈利预测汇总 get_data
(table, field, index, columns)获取万得交易数据 get_index_weight
(table, s_info_windcode)从指定的表中获得指数权重 get_stock_basics
()从AShareDescription表中获取每个股票的基本信息 get_stock_industries
(table, level)从指定的表中获取股票行业表 get_stock_st
()This method is deprecated in favor of arrange_entry_table. get_table
(table_name, columns, str] = None)万得数据库原始表 get_wind_data
(*args, **kwargs)This method is deprecated in favor of get_data. get_wind_table
(*args, **kwargs)This method is deprecated in favor of get_table. -
arrange_entry_table
(table: Union[str, pandas.core.frame.DataFrame], field: str = '', columns: str = None)[源代码]¶ 把带有entry_dt, remove_dt的表重新整理成以股票为列、日期为行的透视表
原数据表样例:
s_info_windcode entry_dt remove_dt XXXXX1.SH 20150101 20150201 XXXXX2.SH 20150130 20150307 … … … 转换后数据样例:
trade_dt XXXXX1.SH XXXXX2.SH … … … 2014-12-30 False False 2014-12-30 False False 2015-01-01 True False 2015-01-02 True False … … … 2015-01-29 True False 2015-01-30 True True 2015-01-31 True True 2015-02-01 True True 2015-02-02 False True … … … Parameters: - table: str
要查询的表名,或DataFrame数据框
- field: str
以某字段为内容。如果为空,则生成的数据只含有True,False
- columns: str
指定要作为列名的字段,默认为s_info_windcode
Examples
# AShareST表示通过entry_dt和remove_dt来维护股票进入ST和离开ST的时间的 # arrange_entry_table把该信息重新整理成以交易日为行、股票为列的“交易日”表 # 最后把剩下的NA用False填充 wind.arrange_entry_table("AShareST").fillna(False)
-
get_consensus_data
(field: str, est_years: int = 1) → pandas.core.frame.DataFrame[源代码]¶ A股盈利预测汇总
Parameters: - field: str
分析师预测数据字段
- est_years: {1, 2, 3}
预测周期(年)
Examples
# 获取预测一年的平均每股收益 wind.get_consensus_data('eps_avg', 1)
-
get_data
(table: str, field: str, index: str = None, columns: str = None) → pandas.core.frame.DataFrame[源代码]¶ 获取万得交易数据
Parameters: - table: str
数据库中数据表的名称
- field: str
要查询的字段名
- index: str
要作为行的字段名,默认为trade_dt
- column: str
要作为列的字段名,默认为s_info_windcode
Examples
wind.get_data("AShareEODPrices", "s_dq_pctchange")
-
get_index_weight
(table: str, s_info_windcode: str) → pandas.core.frame.DataFrame[源代码]¶ 从指定的表中获得指数权重
Parameters: - table
要取权重的数据表,例如AIndexHS300FreeWeight
- s_info_windcode
要取权重的指数的万得代码,中证500为000905.SH,沪深300为399300.SZ。
Examples
# 获取中证500指数的免费权重 wind.get_index_weight("AIndexHS300FreeWeight", "000905.SH")
-
get_stock_industries
(table: str, level: int = 1) → pandas.core.frame.DataFrame[源代码]¶ 从指定的表中获取股票行业表
Parameters: - table: str
AShareIndustriesClass 中国A股行业分类
AShareSECNIndustriesClass 中国A股证监会新版行业分类
AShareSECIndustriesClass 中国A股证监会行业分类
AShareIndustriesClassCITICS 中国A股中信行业分类
- level: {1, 2, 3}
行业等级
Examples
# 获取中国A股中信行业分类 (一级分类) wind.get_stock_industries("AShareIndustriesClassCITICS", 1)
-
get_stock_st
() → pandas.core.frame.DataFrame[源代码]¶ This method is deprecated in favor of arrange_entry_table. Use wind.arrange_entry_table(‘AShareST’).fillna(False)
-
get_table
(table_name: str, columns: Union[List[str], str] = None, format='table') → pandas.core.frame.DataFrame[源代码]¶ 万得数据库原始表
Parameters: - table_name: str
数据库中数据表的名称
- columns: List[str], 可选
要查询的数据字段,如果为None则查询所有字段
Returns: - pd.DataFrame
Examples
wind.get_table("AShareEODPrices", ["s_info_windcode", "trade_dt", "s_dq_adjclose", "s_dq_adjopen"])
-
Math Helpers¶
-
quant.common.math_helpers.
cal_mdd
(netvalue, compound=True)[源代码]¶ 计算最大回撤
Parameters: - netvalue: pd.Series
净值序列
- compound: bool, optional
是否为复利制,如果为真,回撤计算方法为 \(\frac{N_j}{N_i}-1\) (j > i); 如果为假,回撤计算方法为 \(N_j-N_i\) (j > i)
Returns: - 最大回撤值(正值)
Examples
In [1]: import pandas as pd In [2]: from quant.common.math_helpers import cal_mdd In [3]: series = pd.Series([1.0, 1.1, 1.11, 1.04, 1.02, 1.08]) In [4]: cal_mdd(series) Out[4]: 0.08108108108108114 In [5]: 1.02 / 1.11 - 1