BigTrader - 回测与交易引擎
由qxiao创建,最终由qxiao 被浏览 2094 用户
什么是BigTrader
BigTrader是宽邦科技推出的致力于为用户提供便捷、功能强大的交易引擎。
在量化研究的过程中,量化研究员(宽客)需要在历史数据里回放模拟,验证策略效果,这就是BigTrader交易引擎的应用场景。
主要功能: 量化策略编写、回测分析、仿真模拟和实盘交易。
支持品种: 股票、基金、期货、可转债、指数;未来会支持期权、债券、两融等。
交易频率: 日线、分钟、Tick、逐笔。
交易引擎的优势:
- 回测研究贴近真实 交易,最大程度保证回测的准确性
- 回测研究、模拟交易、实盘交易为同一套代码,无需做任务修改
- 交易引擎是一个有体系、结构化的工程框架,能大幅提升策略开发的效率
交易引擎介绍
BigQuant回测引擎为时间驱动回测引擎,当设定好每一根K线后,会根据K线频率读取数据。如当在回测引擎中设置为daily时,回测引擎会按照天从传入数据读取。
回测引擎的运行逻辑为每一根K线运行一次,在当前K线进行下单操作时会在下一根K线开始撮合成交。
\
回测引擎的调取
搜索bigtrader, 拖入画布即可
\
回测引擎启动参数
回测引擎启动参数介绍:
参数 | 数据类型 | 参数功能 | 调用方法 |
---|---|---|---|
instruments | List | 通过第一个输入口传给回测引擎数据中instrument的合集。回测引擎会自动订阅日期内股票的日线行情,同时会根据日线时间区间运行回测引擎。 | context.instruments |
data | DataFrame | 获取传入回测引擎回测数据(通过第一个输入口),并且根据该数据进行下单。 | context.data |
\
回测引擎函数介绍
回测引擎内置了几类主要函数,会按照顺序依次运行。用户可通过可视化或代码方式对函数内容进行更改,最终实现通过回测引擎达到回测的目的。以下是各类函数的运行逻辑。
函数名称 | 函数英文名称 | 说明 |
---|---|---|
初始化函数 | initialize | 策略初始化函数,只触发一次。可以在该函数中初始化一些变量,如读取配置等 |
盘前处理函数 | before_trading | 策略盘前交易函数,每日盘前触发一次。可以在该函数中处理一些启动前的准备,如订阅行情等 |
bar处理函数 | handle_bar | 当根bar行情通知函数,每根bar时间周期会触发,包括日线和分钟。注册多个合约时,每个合约都会调用一次handlebar。handlebar和handle_data不能同时使用。此函数主要用于期货分钟级别回测。 |
行情处理函数 | handle_data | 行情通知函数,频率支持日线和分钟。注册多个合约时,handle_data会等待所有合约数据到齐后统一触发一次。例如多合约套利时,需要同时处理多个合约建议用handle_data。handle_data和handlebar不能同时使用。 |
tick处理函数 | handle_tick | Tick快照行情通知函数,每个标的的行情有变化时则会触发。 |
逐笔成交处理函数 | handle_l2trade | 逐笔成交行情更新时的处理函数 |
委托回报通知函数 | handle_order | 委托回报通知函数,每个订单状态有变化时会触发。 |
成交回报通知函数 | handle_trade | 成交回报通知函数,有成交时会触发。 |
盘后处理函数 | after_trading | 盘后处理函数,每日盘后运行一次 |
有两个使用频率很高的函数:initialize函数和handle_data函数,理解了这两个函数开发策略就再也不是什么难事了,结合下面K线图来理解这两个函数。
从图中可以看出,其实一共有26个事件,即26根K线,第一根K线既对应黑色箭头,又对应灰色箭头,其余都只对应灰色箭头。Initialize函数只在第一个事件上调用,即第一根K线,因此很多初始设置可以放在Initialize函数里面。每个K线都对应灰色箭头,表示每个事件都会调用handle_data函数,即从第一根K线到最后一根K线都会运行handle_data一次,于是很多策略逻辑部分就可以放在handle_data里。
重要函数用法示例
初始化函数
初始化函数主要用于设置回测引擎的实例参数,通过实例参数可以在之后的模块中实现交易中的需求。
以下是一个示例,设置手续费,设置自定定义的持仓股票数量和每只股票的权重,对传入的数据进行排序
# m7_ 为模块编号前缀
def m7_initialize_bigquant_run(context):
from bigtrader.finance.commission import PerOrder
# 系统已经设置了默认的交易手续费和滑点,要修改手续费可使用如下函数
context.set_commission(PerOrder(buy_cost=0.0001, sell_cost=0.0013, min_cost=5))
# 设置买入的股票数量,这里买入预测股票列表排名靠前的5只
context.stock_count = 10
# 每只股票的权重平均分配
context.stock_weights = 1/context.stock_count
# 从context.data获取回测数据,如果之前没有对排序因子进行排序的话,这里可以进行排序操作
context.mydata = context.data.sort_values('score',ascending=True)
盘前处理函数
盘前处理函数通常用于订阅数据,回测引擎内置自动订阅股票日线数据。当我们需要使用高频数据,如需要分钟数据时则订阅K线,需要tick数据时则订阅tick数据。我们每日都需要提前订阅当天的行情数据,来实现最终的下单以及收益的计算。
以下是我们订阅股票分钟行情的示例:
def m7_before_trading_start_bigquant_run(context, data):
#订阅股票分钟数据
#获取全部需要订阅的股票代码
instruments = context.instruments
# 分钟回测:订阅分钟行情(一般我们只订阅当天需要的分钟数据的股票池,否则可能非常占用内存和时间)
context.subscribe_bar(instruments, '1m')
# Tick回测:订阅Tick行情
context.subscribe(instruments)
行情处理函数
K线处理函数会在每根K线运行一次,通常我们会在该函数内进行K线数据读取,并且下单。
以下是一个我们使用该函数进行数据并下单的示例:
def m7_handle_data_bigquant_run(context, data):
# 下一个交易日不是调仓日,则不生成信号,此函数和模块的调仓周期设置配合使用
if not context.rebalance_period.is_signal_date(data.current_dt.date()):
return
# 从传入的数据中读取今天的信号数据
today_df = context.mydata[context.mydata["date"] == data.current_dt.strftime('%Y-%m-%d')][0:context.stock_count]
target_instruments = set(today_df["instrument"])
# 获取当前已持有股票
holding_instruments = set([e for e, p in context.get_account_positions().items() if p.amount>0])
# 卖出不在目标持有列表中的股票
for instrument in holding_instruments - target_instruments:
context.order_target_percent(instrument, 0)
# 买入目标持有列表中的股票
for instrument in target_instruments:
context.order_target_percent(instrument, context.stock_weights)
\
实例方法介绍
查询实例方法
查询单只标的持仓信息
当查询单只标的持仓信息时,可使用 context.get_position(instrument: str, direction = Direction.NONE)
来获取该标的信息。
实例参数 | 参数类型 | 是否必填 | 参数描述 |
---|---|---|---|
instrument | str | 是 | 查询传入参数标的的持仓信息 |
direction | Direction | 否 | 可通过 direction=Direction.LONG/SHORT进行持仓方向过滤,此参数只用于期货。 |
示例:
def m7_handle_data_bigquant_run(context, data):
instrument = '000001.SZ'
#获取股票持仓信息
pos = context.get_position(instrument)
print(pos)
通过以上代码,将返回一个字典,该字典数据格式如下:
StockPosition(bkt000,002875.SZA,LONG,current_qty:2100,avail_qty:0,cost_price:9.44,last_price:9.44,margin:0.0)
返回值 | 返回值含义 | 获取方式 |
---|---|---|
current_qty | 当前持仓 | context.get_position(ins).current_qty |
avail_qty | 可用持仓 | context.get_position(ins).avail_qty |
cost_price | 持仓成本 | context.get_position(ins).cost_price |
last_price | 最新价格 | context.get_position(ins).last_price |
margin | 保证金占用 | context.get_position(ins).margin |
last_sale_date | 最后交易日 | context.get_position(ins).last_sale_date |
\
查询多只标的持仓信息
当查询多只标的持仓信息时可以使用 context.get_positions()
来获取标的的信息。
实例参数 | 参数类型 | 是否必须 | 参数描述 |
---|---|---|---|
instrument | list[str] | 是 | 标的的列表 |
direction | Direction | 否 | 可通过 direction=Direction.LONG/SHORT进行持仓方向过滤,此参数只用于期货。 |
示例:
def m7_handle_data_bigquant_run(context, data):
instruments = ['000001.SZ','000002.SZ']
#获取股票持仓信息
pos = context.get_positions(instruments)
print(pos)
通过以上代码,可以获得一个如下字典:
{'603176.SH': StockPosition(bkt000,603176.SH,LONG,current_qty:0,avail_qty:0,cost_price:0.0,last_price:2.97,margin:0.0),
'600768.SH': StockPosition(bkt000,600768.SH,LONG,current_qty:2000,avail_qty:0,cost_price:9.72,last_price:9.57,margin:0.0)}
返回值 | 返回值含义 | 获取方式 (注: instrument为股票代码,instrument_list为股票代码列表) |
---|---|---|
keys() | 全部持仓列表 | context.get_positions(instrument_list).keys() |
current_qty | 持仓数量 | context.get_positions(instrument_list).instrument.current_qty |
avail_qty | 可用持仓 | context.get_positions(instrument_list).instrument.avil_qty |
cost_price | 持仓成本 | context.get_positions(instrument_list).instrument.cost_price |
last_price | 最新价格 | context.get_positions(instrument_list).instrument.last_price |
last_sale_date | 最后交易日 | context.get_positions(instrument_list).instrument.last_sale_date |
\
查询当前日期
可以通过下列方法获取当前日期,主要用于从引擎中提取当日数据使用.
通常我们在初始化时将全部数据读取进入引擎,并将index转为日期形式,在每日k线处理函数运行时,通过data.current_dt
获取当前日期。通过当前日期从全部数据中获取当日数据。
示例:
#初始化模块中将全部数据
def m7_initialize_bigquant_run(context):
#=========================== 加载预测数据 ===================================
# 将全部数据存入 all_data.并重新设定索引
context.all_data = context.data
context.all_data.set_index('date',inplace=True) #用日期作为索引,可提高之后数据读写速度
def m7_handle_data_bigquant_run(context, data):
#将时间格式转为年月日
date = data.current_dt.strftime("%Y-%m-%d")
#读取数据,根据时间进行索引,再将索引重置。
try:
today_data = context.all_data.loc[date,:]
today_data.reset_index(inplace=True)
except:
print('获取当日数据异常',date)
return
\
查询投资组合信息
可以通过使用 context.portfolio
查询当前账户信息
实例方法 | 返回值含义 | 获取方式 |
---|---|---|
positions_value | 持仓市值 | context.portfolio.positions_value |
portfolio_value | 总资产(资金+持仓市值) | context.portfolio.portfolio_value |
cash | 可用资金 | context.portfolio.cash |
positions | 当前持仓字典 | context.portfolio.positions |
\
查询当前标的价格
可通过使用 data.history()
获取股票当前价格。
参数 | 类型 | 是否必须 | 参数含义 |
---|---|---|---|
instrument | str | 是 | 需要获取的代码 |
fields | str or list[str] | 是 | 需要获取的字段,如 “close” 或 [“close“, “volume“] |
bar_count | int | 是 | 需要的Bar条数 |
frequency | str | 默认 ‘1d’ | 可选 ‘1d’ ‘1m’ ,按照该频率返回数据 |
以下是一个在回测引擎中获取当日股票分钟数据的实例:
def m7_handle_data_bigquant_run(context, data):
#获取股票代码
instrument = '000001.SZ'
#获取该股票截止至当前分钟的全部日内分钟数据
df = data.history(instrument, ["close", "volume"], 30, '1m')
\
下单实例方法
按数量下单
可通过 context.order(instrument, volume, price=0, offset=Offset.NONE, **kwargs)
方式进行按数量下单。
实例参数 | 参数类型 | 是否必选 | 参数含义 |
---|---|---|---|
instrument | str | 是 | 需要交易的代码 |
volume | int | 是 | 需要交易的数量,>0表示买入,<0表示卖出 |
price | float | 否 | 交易的价格,默认为0表示市价单 |
order_type | OrderType | 默认为MARKET市价单 | 下单类型 LIMIT:限价单 MARKET:市价单 |
offset | Offset | 开平方向,默认为None | OPEN:开仓 CLOSE:平仓 CLOSETODAY平今 |
以下是一个使用context.order()
下单的示例:
def m7_handle_data_bigquant_run(context, data):
#获取股票代码
instrument = '000001.SZ'
#获取当前K线的价格
price = data.current(instrument, "close")
#获取当前账户现金
cash = context.portfolio.cash
#计算买入数量,结果不是整百的,交易系统会自动处理成整百
buy_num = cash//price
#买入
context.order(instrument, buy_num)
\
按目标持仓金额下单
可通过 context.order_value(instrument, value, price=0, **kwargs)
方式进行按目标持仓金额下单。
参数类型 | 是否必选 | 参数含义 | |
---|---|---|---|
instrument | str | 是 | 需要买入的代码 |
value | float | 是 | 需要买入的金额 |
price | float | 否 | 交易的价格,默认为0表示市价单 |
order_type | OrderType | 默认为MARKET市价单 | 下单类型 LIMIT:限价单 MARKET:市价单 |
以下是一个使用 context.order_value()
下单的示例:
def m7_handle_data_bigquant_run(context, data):
#获取股票代码
instrument = '000001.SZ'
#获取当前价格
price = data.current(instrument, "close")
#获取当前账户现金
cash = context.portfolio.cash
#计算要买入的现金,假如在这里为半仓买入
buy_cash = cash * 0.5
#买入
context.order_value(instrument, buy_cash)
\
按照目标持仓百分比下单
当买入某只标的是,如希望最终可以按照某百分比持仓。可通过 context.order_percent(instrument, percent, price=0, **kwargs)
方式进行按目标持仓百分比下单,通常用于买单。
参数类型 | 是否必选 | 参数含义 | |
---|---|---|---|
instrument | str | 是 | 需要买入的标的代码 |
percent | float | 是 | 目标持仓百分比 |
price | float | 否 | 交易的价格,默认为0表示市价单 |
order_type | OrderType | 默认为MARKET市价单 | 下单类型 LIMIT:限价单 MARKET:市价单 |
以下是一个使用 context.order_percent()
下单的示例:
def m7_handle_data_bigquant_run(context, data):
#获取股票代码
instrument = '000001.SZ'
#买入50%仓位
context.order_percent(instrument, 0.5)
\
按目标持仓数量下单
如希望将持仓变动到某个固定数量时可通过 context.order_target(symbol, target, price=0, order_type=OrderType.LIMIT)
实现,通常用于清空某只标的。
参数类型 | 是否必选 | 参数含义 | |
---|---|---|---|
instrument | str | 是 | 需要买入的标的代码 |
target | int | 是 | 目标持仓数量 |
price | float | 否 | 交易的价格,默认为0表示市价单 |
order_type | OrderType | 默认为MARKET市价单 | 下单类型 LIMIT:限价单 MARKET:市价单 |
以下是一个使用 context.order_target()
平仓的示例:
def m7_handle_data_bigquant_run(context, data):
#获取全部持仓股票代码
holding_list = list(context.get_positions().keys())
#全部平仓
for ins in holding_list:
context.order_target(ins, 0)
\
其他实例方法
行情订阅
可通过context.subscribe_bar()
订阅行情(日线回测可以不订阅);
订阅K行情后,可在K线处理函数中使用 data.history
的方式获取行情数据。
实例参数 | 数据类型 | 是否必须 | 参数含义 |
---|---|---|---|
instrument | list[str] | 是 | 需要订阅的标的代码 |
frequency | str | 否 默认’1m’ | 需要订阅的频率,通常为 ‘1d’ ‘1m’ |
模块配置参数说明
在可视化画布上,可以对BigTrader回测引擎进行配置。
开始时间/结束时间
表示回测的开始和结束时间,默认可以不填,使用传入的回测数据的开始和结束时间。
初始化函数
编写初始化函数的地方。
盘前处理函数
Tick处理函数
Tick回测需要在此编写逻辑。
K线处理函数
回测的主逻辑编写的地放,每根K线执行一次。
成交回报处理函数
每笔成交后,系统调用的函数,默认为空。
委托回报处理函数
每笔委托后,系统调用的函数,默认为空。
盘后处理函数
编写每日盘后处理逻辑,默认为空。
初始资金
设置回测的初始资金。
数据频率
回测频率,可以选择daily(日频),minute(分钟),tick(快照),tick2(逐笔)
产品类型
回测产品类型可以选择股票、期货、期权、基金、可转载、自动(交易引擎自己判断)
调仓周期类型
表示调仓的周期类型,可以选择交易日、周度/月度/季度/年度交易日、自然日、周度/月度/季度/年度自然日
调仓周期日期
和调仓周期类型配合使用。
如果调参周期类型选了交易日或者自然日,调参周期日期这里填入n表示每n天调一次仓。
如果调参周期类型选了周度/月度/季度/年度交易日或者自然日,调参周期日期这里填入n表示第n天调仓。
配置了调仓类型和调仓周期后,在hand_data主函数中使用如下代码来实现调仓逻辑:
# 下一个交易日不是调仓日,则不生成信号,此函数和模块的调仓周期设置配合使用
if not context.rebalance_period.is_signal_date(data.current_dt.date()):
return
回测引擎模式
可以选择标准和极速模式。极速模式使用了向量化回测的方式,速度更快,但是准确性没有标准模式高。
历史数据向前取的天数
回测引擎使用的行情数据需要前向取的天数,一般不需要,默认为0。
成交率限制
执行下单时控制成交量参数。例如设置为1时,不进行成交量检查;若设置为0.025,下单量如果超过该K线成交量的2.5%,多余的订单量会自动取消。
买入点
可以填入open(开盘),close(收盘),twap(时间加权平均价格算法),vwap(成交量加权平均价格)。
关于twap和vwap可以参考 策略回测-WAP价格回测功能
卖出点
可以填入open(开盘),close(收盘),twap(时间加权平均价格算法),vwap(成交量加权平均价格)。
基准指数
表示回测绩效曲线中基准的指数,可以选择沪深300、中证500、中证1000等。
显示回测结果图表
勾选后显示回测绩效图,否者不显示。默认勾选。
调试模式
勾选后会打印更多回测引擎自身的调试日志。默认不勾选。
只在回测模式下运行
勾选后,此策略不能在模拟环境运行。默认不勾选。
撮合与策略运行结果说明
订单撮合处理
本章节主要介绍基于历史行情的模拟撮合介绍,主要包括基于Bar行情、快照行情、逐笔行情撮合。支持上交所和深交所两大交易所上市的A股股票、基金、债券、期权、期货等品种。不支持新股申购、市值配售、增发申购、配股等交易。股票交易费用买入按0.03%计算,卖出按0.13%计算(其中默认包含0.1%的印花税),期货则按对应的品种费率计算,实际费率也可在回测模拟中设置。
通用规则
- 对于没有成交的委托,或者部分成交的委托,可以撒单。当天的委托如果没有成交,收市以后自动作废,不参加下一交易日的撮合。
- 对于市价委托,未成交部分会自动撤销(即成剩撤)。
基于Bar行情数据撮合规则
- 成交参考价格可指定为open/close,但是一般分钟回测时,买卖参考价格都为下一分钟的开盘价 open。
- 成交数量最大为当次bar的成交量,日线是一般还会加一个成交率比例。
- 委托量过大时,可能出现模拟撮合结果与真实情况严重失真的情况。
基于快照行情数据的撮合规则
主要原则是基于行情中的最新价撮合,而不是买卖盘口的价格撮合,发出订单后,使用下一笔快照行情撮合。
- 买入
- 如果最新成交价等于委托价,按照委托价成交。
- 如果最新成交价低于委托价,按照最新价成交。
- 若成交价在买一价或涨停时,不能即时成交,委托会放入撮合等待队列,并且记录当时买一量,如果阶段成交量大于买一量,可成交数量是阶段成交量和当时的买一量的差,以这种方式模拟在真实交易市场排队的情形。但未及时考虑买一上的撤单量。
- 如果涨停板被打开,价格低于委托价,则按照现价成交。
- 卖出
-
如果最新成交价等于委托价,按照委托价成交
-
如果最新价高于委托价,按照最新价撮合成交 注意,若成交价在卖一价或跌停时,不能即时成交,委托会放入撮合等待队列,并且记录当时卖一量,如果阶段成交量大于卖一量,可成交数量是阶段成交量和当时的卖一量的差,以这种方式模拟在真实交易市场排队的情形。但未及时考虑卖一上的撤单量。
-
如果跌停板被打开,价格高于委托价,则按照现价成交。 当次成交量按两个快照之间的真实成交量计算,若成交量为0,则不成交。如果真实成交数量小于委托未成交数量,则部分成交,仅撮合真实交易的成交数量,剩余的委托仍保留在撮合队列,等待新的成交明细。因此早上集合竞价期间的报单,会在 09:25:00 进行一次撮合,或 09:30:00开始进行连续竞价撮合。
例如:600804(鹏博士)上午开市后涨停,用户在10:10以涨停价委托买入100手,此时的成交量是51000手,涨停板上买一的单子是5000手,如果涨停板没有被打开,只有阶段成交量大于5000手时,用户的委托才等到可以成交。如果成交量到了56010手,则用户成交10手(56010-51000-5000),剩下的部分等待更多的成量。
-
基于逐笔成交数据的撮合规则
主要原则是基于逐笔行情中的最新成交价撮合,发出订单后,使用下一笔逐笔行情撮合,需要配合当前快照盘口信息(会在收到委托时,获取当前盘口)。
- 买入委托
- 市价委托
- 当前在涨停版上,不成交,自动撤销
- 成交,即成剩余,成交量也依次从卖一到卖五档
- 不支持FOK
- 委托价格 > 最新价:
- 成交,成交价=最新价,成交量依次从卖一到卖十档,生成多笔成交信息,FIXME:如果超出卖十档的处理,其中价格触发到涨停板的处理。
- 委托价格 == 最新价
- 成交类型主动卖,判断当前记录的排队数量,排队数量 <= 0,则成交,成交量为当次逐笔成交量,FIXME: 更逼真模式是取 逐笔成交-排队数量
- 成交类型主动买,不成交
- 撤单成交(仅适用于深交所)
- 撤单价格 == 买一价,对订单队列中的买入委托的排队数量做减少
- 其它撤单,不做处理
- 其它不成交
- 市价委托
- 卖出委托:
- 市价委托:
- 当前在跌停版上,不成交,自动撤销
- 成交,即成剩余,成交量也依次从买一到买五档
- 不支持FOK
- 委托价格 < 最新价:
- 成交,成交价=最新价,成交量依次从买一到买十档,生成多笔成交信息,FIXME:如果超出买十档的处理,其中价格触发到跌停板的处理。
- 委托价格 == 最新价:
- 成交类型主动买,判断当前记录的排队数量,排队数量 <= 0,则成交,成交量为当次逐笔成交量,FIXME: 更逼真模式是取 逐笔成交-排队数量
- 成交类型主动卖,不成交
- 撤单成交(仅适用于深交所)
- 撤单价格 == 卖一价,对订单队列中的买入委托的排队数量做减少
- 其它撤单,不做处理 其它不成交
- 市价委托:
\
回测结果分析
当我们完成一个策略回测时,我们会得到如下的一个图形:
上图为策略回测结果图,红色矩形标记部分包含了策略的主要信息,包括 收益概况、交易详情、每日持仓及收益、输出日志 。接下来,我们详细介绍这几个部分。
收益概况
收益概况以折线图的方式显示了策略在时间序列上的收益率,黄色曲线为策略收益率。同时也显示了沪深300收益率曲线作为比较基准,蓝色曲线为基准收益率。同时,最下面的绿色曲线为持仓占比,持仓占比即仓位,10%的持仓占比表示账户里股票价值只占10%。相对收益率的曲线并没有直接绘制在图上,点击图例 相对收益率,就可以将其绘制出来。
不仅如此,衡量一个策略好坏的关键指标在收益概览页面也得到展示。
-
收益率:策略整个回测时间段上的总收益率。比如,如果收益率为30%,表明起始时间是1万的本金,结束时间本金就变成1.3万了,一共赚了3000元。
-
年化收益率:该策略每一年的收益率。比如,如果回测时间段为2年,总收益率为30%,那么每年的年化收益率就在15附近(不考虑复利)。
-
基准收益率:策略需要有一个比较基准,比较基准为沪深300。若基准收益率为15%,表明在整个回测时间段,大盘本身就上涨了15%,如果策略收益率小于基准收益率,说明策略表现并不好,连大盘都没有跑赢。
-
阿尔法:衡量策略的一个重要指标,该值越大越好。
-
贝塔:衡量策略的一个重要指标,该值越小越好。
-
夏普比率:衡量策略最重要的一个指标,该指标的计算不仅考虑收益率,还考虑了风险,因此比较具有参考价值,可以理解为经过风险调整后的收益率。
-
胜率:衡量策略盈利一指标,胜率越大越好。比如10次投资中有8次获利,胜率就是80%。
-
盈亏比:衡量策略盈亏能力大小比较,盈亏比越大越好。比如投资盈利时,平均每次盈利4元,亏损时,平均每次亏损2元,那么此时的盈亏比为2。
-
收益波动率:收益率的标准差,是风险的一个指标。
-
最大回撤:策略在整个时间段上亏损最严重的时候相比净值最高值下跌的百分比。如果最大回撤为20%,表明策略在某个时间点上,相比之前的净值最高点下降了20%。最大回撤是策略评估时非常关键的一个指标,通常与风险承受能力相关。
-
信息比率:信息比率也是一个常用的策略评价指标
关于回测结果和指标更详细的分析可参照链接:策略回测结果指标详解\
交易详情
交易详情主要显示了策略在整个回测过程中每个交易日的买卖信息。包括买卖时间、股票代码、交易方向、交易数量、成交价格、交易成本。具体见下图:
每日持仓及收益
每日持仓及收益主要呈现每日持有股票代码、当日收盘价、持仓股票数量、持仓金额、收益等指标。具体见下图:
{{heading_numbering_zhCN}}