今天我们构建的量化模型,尝试用python搭建,首先它把数据拆分重构,使用15分钟或者更低颗粒度的K线,重构成为1小时线或者半日线。然后在重构的K线上,搭建ATR自适应通道交易模型。

如果说后半部分模型开发是很多软件都可以做的,前半部分就并非如此了。我们要以每天中午12点,下午15点为切分点,把每天的时间序列切分成3段。

让我们从最简单的模型本体交易逻辑开始讲。

一、模型本体——ATR自适应通道

很多做期货动量交易的人都明白,通道突破类策略是典型的趋势策略,这类策略指导构建的交易模型也比较简单清晰,并且将标准差等波动率表达方式考虑到模型中,有助于提升绩效。这里说的提升绩效,一方面是通过通道的中轨确定大致方向,另一方面是通过标准差等波动率指标,确认通道宽度。

首当其中的就是布林带,这个经典指标已经几十年被使用,基本上没人敢说这套系统不能用,但是它毕竟太过于古老,需要改进,这是共识。

典型的通道突破类策略是Aberration,实际上就是布林带,它被翻译理解为“失常、离开正路、越轨”等含义。该模型在均线上,构建了上下两个通道,通过波动率高低调节通道大小,如果价格突破上轨,就做多,如果价格突破下轨,就做空,价格回到中轨平仓,达到一定的自适应突破效果。

它的原理是这样:

// 中轨AverageMA,此处的Length是计算均线的窗口期

AverageMA = Average(Close1,Length);

// 价格序列的标准差

StdValue = StandardDev(Close1,Length);

// 上轨和下轨,此处的StdDev是标准差倍数

UpperBand = Avema StdDev StdValue;

LowerBand = Avema - StdDev StdValue;

今天的改进针对标准差部分,我们发现ATR比标准差更能够反应波动率的真伪,毕竟ATR采用的时间序列信息含量更高。

标准差是一个统计工具,不再叙述。ATR概念由威尔德(J. Welles Wilder)1978年于《New Concepts in Technical Trading Systems》书中提出,它取一定时间周期内的价格波动幅度的移动平均值,和你看到的网络上的注解不同,它并不是主要用于研判买卖时机,也不是做什么反趋势指标,它能感知到波动率。

海通证券测试了ATR和标准差的性能差异,这四种情况虽然特殊,但是以极端方式,体现了标准差和ATR的区别。

图1,标准差的表现力更强,因为价格确实出现了波动幅度变化。

图2,和研报观点相同,ATR可以稳定的保持着较高的水平,能对新的价格运行方向上的波动状态进行有效的刻画,但是标准差不行。

图3,标准差在适应新趋势时又一次表现出对趋势逆转时波动率提升的错误描述,它在新趋势刚开始出现时先缓慢下降,此时很容易造成通道类突破系统做出错误判断。

图4,很罕见的情况,但是ATR采用了最高最低价,而标准差没有,所以它对于波动率的分析显然错了。

所以,我们要使用ATR改进布林带了,改进完的这套系统,应该被称作肯特纳通道,网上会有很多资料,这里使用公众号《量化投资训练营》的结果,来体现两者的细微差距。

我们关闭掉模型中其他条件,仅以布林带或者说使用ATR为逻辑的Keltner Band作为开平仓条件进行测试。测试目标是螺纹钢RB000,2010年开始指数合约,沪深300指数2010年开始时间序列。频率都在1小时。

为了公平起见,参数统一为20周日ATR或者标准差。且为了得到均等的参数面绩效,我们令中轨周期参数Length在30~200之间波动,间隔5,。令Offset上下轨宽度参数在1~3之间波动,间隔0.5.。这样既可得到一个约180组绩效。

TOP组的意思是取按净利润排列,前30个绩效。ALL组的意思是所有绩效。

螺纹钢参数面测试结果

沪深300参数面测试结果

经过测试发现,商品期货上性能差异不够明显,但是到了股指方面,ATR的优势进一步显现。这其中最核心的因素恰巧是交易次数,带来的绩效IR提升,这里我们定义的IR和信息广度有关,我们认为信号数量是对于绩效可信度的考察方式。

ATR通道,在螺纹钢和沪深300指数上,信号数量是标准差的1.14倍和1.05倍,且同时绩效略好,所以导致这里定义的绩效IR = 绩效*SQRT(交易次数)差别更显著。

该部分逻辑,使用python语言撰写效果如下:

# ATR计算  g.low = g.AM[IndexFuture].exportArray('low')[-g.TodayBar[IndexFuture]*g.Window-1:]g.high = g.AM[IndexFuture].exportArray('high')[-g.TodayBar[IndexFuture]*g.Window-1:]g.close = g.AM[IndexFuture].exportArray('close')[-g.TodayBar[IndexFuture]*g.Window-1:]# 为了防止ATR误算,如果出现大面积的空数据,则不计算ATRif 0 in g.close:passelse:g.ATR[IndexFuture] = talib.ATR(g.high,g.low,g.close, timeperiod = g.TodayBar[IndexFuture]*g.Window)[-1]print(g.ATR[IndexFuture])# 布林带计算g.MidLine = g.close[-g.Window*g.TodayBar[IndexFuture]:].mean()g.BollUp = g.MidLine   g.offset*g.ATR[IndexFuture]g.BollDown = g.MidLine - g.offset*g.ATR[IndexFuture]# 交易信号计算if g.close[-1] > g.BollUp:g.Cross = 1elif g.close[-1] < g.BollDown:g.Cross = -1else:g.Cross = 0#判断交易信号:布林带突破 可二次入场条件成立if  g.Cross == 1 and g.Reentry_long == False:g.Signal = 1elif g.Cross == -1 and g.Reentry_short == False:g.Signal = -1else:g.Signal = 0# 执行交易Trade(context,RealFuture,IndexFuture)# 运行防止充入模块Dont_Re_entry(context,IndexFuture,ins)# 计数器 1g.Times[IndexFuture]  = 1

需要注意的是,我们肯定要在模型中放入止损逻辑,也肯定要放入止损后的防止重入逻辑,这两部分大家应该都熟悉了。

还有一个重点变量计算:TodayBar,它可以帮助我们获取每天的bar数量,以此来得到均线的参数,ATR的参数。

# 吊灯止损模块
def TrailingStop(context,RealFuture,IndexFuture):# 仓位状态long_positions = context.portfolio.long_positionsshort_positions = context.portfolio.short_positions# 多头进场后最高价 空头进场后最低价g.HighPrice[IndexFuture] = max(g.HighPrice[IndexFuture],g.close[-1])g.LowPrice[IndexFuture] = min(g.LowPrice[IndexFuture],g.close[-1])if RealFuture in long_positions.keys():if long_positions[RealFuture].total_amount > 0:if g.HighPrice[IndexFuture]:if g.close[-1]  < g.HighPrice[IndexFuture]  - g.NATRstop*g.ATR[IndexFuture]:log.info('多头止损:\t'    RealFuture)order_target(RealFuture,0,side = 'long')g.Reentry_long = Trueif RealFuture in short_positions.keys():if short_positions[RealFuture].total_amount > 0:if g.LowPrice[IndexFuture]:if g.close[-1]  > g.LowPrice[IndexFuture]   g.NATRstop*g.ATR[IndexFuture]:log.info('空头止损:\t'   RealFuture)order_target(RealFuture,0,side = 'short')g.Reentry_short = True

还有就是移仓换月,我在比较早的帖子里已经写了它的逻辑,大家可以通过源码理解,其实不难,但是刚开始写确实有难度,好在以后聚宽会把这部分做成官方函数,各位就不用费心思写了。

二、数据重构——分钟线拼接为半日线

数据重构是量化交易中的重要工作,我觉得有这样几个原因:

1、大部分交易者在关键时间点上发单,会产生交易拥挤。 2、很多K线并不是我们想要的长度,因为其时间含金量不同。比如夜盘从21点到某些品种的凌晨2点半,交易清淡,但是依然占据等时间划分的K线并不科学。 3、除了改变时间颗粒度之外,还可以通过成交量、波动率等方法,重构K线,带来非常意外的超额收益。

这些功能,基本上是传统的期货软件不具备的,它们都需要使用更精密地编程语言完成,python就是这样一个工具,这里有它的价值,也是我们和身边很多朋友都要转移到python平台上开发交易策略的原因。

我们可以在【研究】平台打印出某品种的15分钟K线看看效果:

之后我们和聚宽技术客服沟通了解到:使用get_bars函数能够更好地获取到每天都是9点开始的数据,这样使用较大粒度的K线,如1小时线,也可以完成拼接,且效率更高。

这套模型中,我们首先在DataPrepare函数中,读取了15分钟K线,每次取50个样本进入之后要介绍的ArrayManager模块。

g.LastPrice[IndexFuture] = attribute_history(IndexFuture,50, unit='15m',fields = ['close','open','high','low'])

然后构建了ArrayManager,该模块用于拼接K线的类,该策略基于不均匀的K线完成,在固定时间输出bar(日内,如早盘收盘时)。而当前平台未推出该功能,因而自定义ArrayManager类来实现,完整代码在模型中可看到。

class ArrayManager(object):# 初始化函数,设定基准等等def __init__(self, size=100):# 设定Array的缓存大小self.size = size  # 基本指标与基本指标的Array字典初始化(用于K线按收盘时间分割)# 在这里VarArrays指的是全新K线的数据,以字典的形式存放,Vars是更新K线前的缓存self.Vars = {'close':False,'open':False,'high':False,'low':False}self.VarsArrays = {'close':np.zeros(size),'open':np.zeros(size),'high':np.zeros(size),'low':np.zeros(size)}# 更新Array,形成新的bar数据,后续指标等都是基于该Array进行计算    def updateBarArray(self):for var in self.VarsArrays.keys():self.VarsArrays[var][0:self.size-1] = self.VarsArrays[var][1:self.size]self.VarsArrays[var][-1] = self.Vars[var]

在拼接数据前,我们做了一个小的识别,看数据是有有夜盘,有夜盘的品种我们可以定todaybar=3,没有夜盘的品种,我们定todaybar=2。该变量用于在模型里帮助计算参数。这部分逻辑放在before_market_open函数中。g.TodayBar[IndexFuture]作为全局变量在模型里传递。

# 以下逻辑判断该品种是否有夜盘,并计算TodayBarg.Data[IndexFuture] = attribute_history(IndexFuture,120, unit='60m',fields = ['close'])HourList = [x.strftime('%H') for x in g.Data[IndexFuture].index[:]]if '21' in HourList: g.TodayBar[IndexFuture] = 3else:g.TodayBar[IndexFuture] = 2

然后就是在DataPrepare函数中,拼接数据:

# 如果当前时间在该品种实际交易时间内(基于15分钟bar),则执行拼接if str(context.current_dt.time()) in [x.strftime('%H:%M:%S') for x in g.LastPrice[IndexFuture].index[:]]:# 初始化if IndexFuture not in g.AM.keys():g.AM[IndexFuture] = ArrayManager()g.AM[IndexFuture].updateBar(g.LastPrice[IndexFuture]['close'][-1],g.LastPrice[IndexFuture]['high'][-1],g.LastPrice[IndexFuture]['low'][-1],g.LastPrice[IndexFuture]['open'][-1])else:# 收盘时间时输出新Barif g.LastPrice[IndexFuture].index[-1].strftime('%H%M') in g.CloseMarket :# 没有夜盘的品种在9点15分不输出新Barif g.TodayBar[IndexFuture] == 2 and g.LastPrice[IndexFuture].index[-1].strftime('%H%M') == '0915':passelse:

这部分的关键语句就是g.LastPrice[IndexFuture].index[-1].strftime('%H%M') in g.CloseMarket : 数据开始切分,g.CloseMarket被我们定义为['0915','1130','1500'],在这3个时间点上,模型通过updateBarArray产生新的拼接完毕后的K线。每次拼接完毕后,要执行数据删除clear函数。

updateBar函数用于更新数据,这里不用更新open数据,因为一个重构后的K线的open等于最初传入的open。close数据始终更新,因为要取到最后切分那一刻之前的close。最高和最低价,自然要寻找这段时间的最高最低点了,所以进行max和min比较方法。

模型中其他逻辑都比较简单易懂,所以搞懂此部分,基本上就能完成计算所需的数据支撑。下面我们进行参数组合测试,发现全过程表现较优质的参数。因为数据拼接涉及到IO量大,计算速度较慢,所以我建议从2014年测试,且如果你想要得到一个完整、可信度高的参数表现,要和之前测试动量模型一样,测试大约25个以上的品种。

三、绩效测试

今天的文章仅演示6个品种。多组资金曲线的回测,是通过【研究】调用【回测】得到的,具体过程在这里讲过:

【量化课堂】多回测运行和参数分析框架

多组(参数)绩效如上图所示。

单组绩效如上图所示。

对于每个期货模型,因为很强的动量效应存在,结果都是比较理想的。但是其中也不免一些参数由于设置不合理,导致性能偏低。还是建议大家在品种数量更多的环境下,且最好能够分离训练集和测试集,找到合适的实盘参数。

我们将全部源码放在原文链接部分,需要的朋友们可以点击获取。

分钟K线数据重构 ATR自适应通道 请高手来迭代相关推荐

  1. 5分钟k线数据 存储_成功率极高的“分时K线战法”:15分钟K线战法+30分钟K线战法...

    实战看盘最常用的就是日.周.月等K线图.这些图形对于我们分析个股走势的确帮助很大,然而遇到调整时,就显示了其宏观有余.微观不足的缺点.但假如我们用分时K线图进行微观的观察与分析,就可以找到一些个股在调 ...

  2. 5分钟k线数据 存储_短线高效炒股——60分钟K线买卖法,抓住买卖时机,看完受益匪浅!...

    (本文由公众号越声攻略(yslc688)整理,仅供参考,不构成操作建议.如自行操作,注意仓位控制和 风险自负.) 按时间来分,K线可分为短周期K线和中长期K线. 其中短周期K线包括5分钟K线.15分钟 ...

  3. matlab1分钟数据转5分钟,把股票的5分钟k线数据转换成matlab的day文件

    %StockInformationSHaseImportRoot是钱龙保存5分钟线的数据的文件路径,这里我选用600080 StockInformationSHaseImportRoot = 'D:\ ...

  4. TuShare获取K线数据

    Tushare是一个免费.开源的python财经数据接口包.主要实现对股票等金融数据从数据采集.清洗加工 到 数据存储的过程,能够为金融分析人员提供快速.整洁.和多样的便于分析的数据,为他们在数据获取 ...

  5. 通达信k线数据免费获取

    通达信软件官方免费提供沪深京日线.5分钟.1分钟k线数据下载,每日盘后提供当日数据下载,数据更新时间也很快,对于想要免费获取可靠数据进行投资的朋友来说是一个不错的选择 数据下载 通达信数据免费下载操作 ...

  6. 【TWS API 问题2】如何用盈透证券的TWS API持续获取5分钟K线的问题?

    有一个读者付费咨询了一个问题: 请问在请求实时交易数据后,是否可以持续实时地获得"特定周期"的K线呢?比如发起请求指令后,每五分钟更新一次5min的k线值? 目前,IB不提供简单的 ...

  7. Ctp接口 Tick数据转换成3秒钟,5秒钟,15秒钟,1分钟,3分钟,5分钟,n分钟周期的K线数据

    Ctp接口 Tick数据转换成3秒钟,5秒钟,15秒钟,1分钟,3分钟,5分钟,n分钟周期的K线数据 图片为5秒钟 合成效果 完整源码 """ 关注公众号: Ctp接口量 ...

  8. 用AkShare获取沪深京A股分钟级K线数据

    前面已经讲解了如何通过AkShare获取实时K线数据和沪深京A股历史数据.但是在现实做策略回测的过程,经常会用到分钟级数据计算买卖点.下面我们讲讲如何用AkShare获取沪深京A股分钟级K线数据. 一 ...

  9. ccxt k线数据_机器学习系列:深度探秘K线结构新维度

    标星★公众号,第一时间获取最新研究 来源:光大证券金工团队独家授权 作者:胡骥聪 近期原创文章: ♥ 基于无监督学习的期权定价异常检测(代码+数据) ♥ 5种机器学习算法在预测股价的应用(代码+数据) ...

最新文章

  1. arcgis for android离线编辑,ArcGIS for Android离线数据编辑实现原理
  2. python argsort排序结果_numpy.argsort()可以对元组或列表进行排序
  3. Pandas (GeoPandas)笔记:set_index reset_index
  4. Delphi编辑器使用指南
  5. python如何读取配置文件获取url以及hhead_python爬虫小工具:(模块:copyhreaders,直接复制头文件,无须挨个添加双引号)...
  6. linux自动挂起什么意思,Linux中进行挂起(待机)的命令说明
  7. java面试题七 char转int
  8. javaweb学习总结(十九):JSP标签
  9. 投资银行对Java进行的二十大核心面试问答
  10. Proe Top-Down设计演示
  11. 图灵社区 : 阅读 : 谁说Vim不是IDE?(三)
  12. Bootstrap 警告框(Alert)插件
  13. 利用单壁路由实现vlan间路由
  14. 系统学习NLP(二十九)--BERT
  15. 自定义LinkedList实现
  16. C++ TLV格式解析
  17. 帝国cms发布文章对哪些数据表做了操作
  18. 最美的公式:你也能懂的麦克斯韦方程组
  19. Discrete regularity for graph Laplacians --Jeff Calder 读书笔记 part1 待更
  20. 电子器件系列二:IGBT

热门文章

  1. 详述微信内推广H5和棋牌类APP如何做好域名防封处理
  2. 苏宁易购获得商品详情API,Onebound电商数据
  3. 对计算机的过度依赖英语作文,不要过度依赖手机英语作文范文
  4. QGIS计算共享边长
  5. 华为云数据库 RDS for MySQL,用心保障企业数字化发展
  6. 小学计算机室信息化实施方案,牛镇镇中心学校教育信息化建设实施方案
  7. 瞬时功率理论(3)_matlab仿真验证
  8. 用Excel制作不一样的百分比信息图表
  9. java springboot汽车租赁系统小程序-uniapp
  10. python 下载/上载文件到Synology群晖