189 8069 5689

python如何实现动态阶梯突破策略

这篇文章给大家分享的是有关python如何实现动态阶梯突破策略的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。

公司主营业务:成都网站设计、成都网站建设、移动网站开发等业务。帮助企业客户真正实现互联网宣传,提高企业的竞争能力。创新互联是一支青春激扬、勤奋敬业、活力青春激扬、勤奋敬业、活力澎湃、和谐高效的团队。公司秉承以“开放、自由、严谨、自律”为核心的企业文化,感谢他们对我们的高要求,感谢他们从不同领域给我们带来的挑战,让我们激情的团队有机会用头脑与智慧不断的给客户带来惊喜。创新互联推出夏邑免费做网站回馈大家。

什么是突破策略

我们知道,期货市场的价格以趋势和震荡交替的方式演变,如果我们只使用一种方法抓住趋势,就能赚到趋势行情的钱。那么,用什么方式来抓住趋势呢?比较简单的一种方法就是用突破策略。通过设置价格的上下轨,或者支撑位、压力位,当价格超过上轨,我们认为行情即将启动,开仓做多,反之亦然。

市面上有很多不同种类的突破策略,大致可以分为:形态突破(包括:双肩型、头肩型、颈线、趋势线等等)、指标突破(均线、KDJ、ATR等等)、通道突破(新高和新低、支撑线和阻力线)、量能突破(成交量、能量潮)。其中在量化交易中,最常用的是:指标突破和通道突破。

突破策略理论

在逻辑学中,有一个“充分不必要条件”的概念,也就是说:如果有A不一定有B,但如果有B就必定有A。那么B就是A的充分而不必要的条件,即充分不必要条件,A是B的必要不充分条件。所以站在结果的角度讲,价格突破关键点位后未必形成趋势,但趋势上涨或下跌必然会突破其间的关键价格位置。

另外,从突破的原因上讲,市场涨跌取决于买卖双方实力对比。当价位冲破上一时段的最高点时,在上一时段任何价位做空头的人都无一例外被套牢,它当中肯定有一部分要认赔平仓出局,反过来又给升势推波助澜。相反,当行情跌破上一时段的最低价时,在上一时段任何一点做多头的统统都出现浮动亏损,其中一定有部分要止损作平仓卖出,正好对跌势落井下石。

策略逻辑

阶梯策略,这是一个比较土的名字,因为其在图表上的外形类似台阶而得名,最初的灵感来自于阶梯止损。相信有过实盘经验的人应该深有体会:当市场进行横向整理或者摇摆不定的时候,对交叉类系统的打击很大,往往会买在高点,卖在低点。如果行情一直持续,则会出现连续亏损,连续的亏损信号将对交易者造成严重的心理负担和资金回撤压力。如下图:

python如何实现动态阶梯突破策略

通过利用,通道技术则可以过滤或者减少价格反复缠绕,减少部分虚假信号,对于降低无效交易有巨大帮助。本策略并非传统的通道策略。而是根据前期最高价和最低价,反向建立自适应通道。这里提到的自适应是指回溯日期会根据我们的逻辑进行调整,具体来说本策略是由市场波动的变动率来变化。

大部分通道策略的组成是由两个因子决定,第一个就是中轨,然后再根据中轨算出通道宽度,即上下轨。比如常见的布林带通道( BollingerBand ),先是由一条均线当中心线,而通道宽度是由标准差所决定。阶梯策略的通道并不是以中轨得来,与之相反的是:先根据市场波动率计算出通道上下轨,然后再根据通道宽度算出中轨。

另外,在判定最高点和最低点的 K 线条数取决于我们愿意给交易多少变化空间,我们用来越多的 K 线条数来确定上下轨,我们给予程序化交易的变化空间越大,相应的,在触发止损前盈利回撤的幅度也会越大。使用越近的高点或低点,止损被触发的速度也越快。想让通道窄一点就设定小一点,想让通道宽一点就设定大一点。

python如何实现动态阶梯突破策略

设置通道

  • 上轨:如果当根K线最低价小于上根K线最低价,上轨就等于前N根K线最高价的最高价

  • 下轨:如果当根K线最高价大于上根K线最高价,下轨就等于前N根K线最低价的最低价

  • 中轨:上轨和下轨的平均值

入场条件

  • 多头入场:如果当前没有持仓,并且价格大于上轨,买入开仓。

  • 空头入场:如果当前没有持仓,并且价格小于下轨,卖出开仓。

出场条件

  • 多头出场:如果当前持有多单,并且价格小于中轨,卖出平仓。

  • 空头出场:如果当前持有空单,兵器价格大于中轨,买入平仓。

为了避免过度拟合,在设计策略的时候,只给定了一个参数。虽然仅有一个参数,但却不失策略在市场中的灵活性。不仅如此,阶梯策略既能适应国内外商品期货,还可以应用于 A 股 ETF ,包括外盘 ETF 和反向杠杆 ETF,以及外汇市场。当然只是适应部分品种,从全品种统计来看,这是一个普适性比较强的策略。

策略编写

根据上面的策略逻辑,我们可以在发明者量化交易平台上实现交易策略。依次打开:fmz.com > 登录 > 控制中心 > 策略库 > 新建策略 > 点击右上角下拉菜单选择Python语言,开始编写策略,注意看下面代码中的注释。

第1步:编写策略框架

这个在之前的章节已经学习过,一个是onTick函数,另一个是main函数,其中在main函数中无限循环执行onTick函数,如下:

def onTick():
    pass

def main():
    while True:
        onTick()
        Sleep(1000)

第2步:定义全局变量

首先定义策略中的上轨、下轨,因为我们的策略中上轨、下轨时是根据一定的条件来计算的,也就是说:当前的最高价大于前面K线的最高价时,才重新计算下轨;当前的最低价小于前面K线的最低价时,才重新计算上轨。所以我们必须把上轨和下轨变量定义在onTick主函数外面。

up_line = 0  # 上轨
under_line = 0  # 下轨
mp = 0  # 用于控制虚拟持仓

另外,我们还需要定义全局变量虚拟持仓mp,策略运行之初默认是空仓mp=0,当开多单后把虚拟持仓重置为mp=1,当开空单后把虚拟持仓重置为,mp=-1,当平多单或空单后把虚拟持仓重置为mp=0。这样我们在判断构建逻辑获取仓位时,只需要判断mp的值就可以了。

第3步:计算上轨、下轨、中轨

因为在计算这些数据之前,肯定要先获取历史的K线基础数据,这些基础数据的获取方式也很简单,首先订阅期货品种,然后调用发明者量化API中的GetRecords方法。接着因为在计算上轨和下轨的时候需要用到talib库中的Highest和Lowest方法,这两个方法都要传入周期参数,但如果K线数据不够的时候,就不能正常计算其值,所以在这里就要判断K线数据的长度,如果K线的长度不足以计算其值时,就直接返回跳过。

接着,我们分别获取当前K线和上根K线的最高价和最低价,通过对比当前K线最高价与上根K线最高价来定义下轨的值,如果当前的最高价大于前面K线的最高价时,就重新计算下轨;同理如果当前的最低价小于前面K线的最低价时,就重新计算上轨。最后上轨和下轨的平均值就是中轨。

exchange.SetContractType("rb000")  # 订阅期货品种
bars = exchange.GetRecords()  # 获取K线数组
if len(bars) < cycle_length + 1:  # 如果K线数组的长度太小,所以直接返回
    return
close0 = bars[len(bars) - 1].Close;  # 获取当根K线收盘价
high0 = bars[len(bars) - 1].High;  # 获取当根K线最高价
high2 = bars[len(bars) - 2].High;  # 获取上根K线最高价
low0 = bars[len(bars) - 1].Low;  # 获取当根K线最低价
low1 = bars[len(bars) - 2].Low;  # 获取上根K线最低价
highs = TA.Highest(bars, cycle_length, 'High');  # 获取前cycle_length根K线最高价的最高价
lows = TA.Lowest(bars, cycle_length, 'Low');  # 获取前cycle_length根K线最低价的最低价
global up_line, under_line, mp  # 使用全局变量
if high0 > high2:  # 如果当根K线最高价大于上根K线最高价
    under_line = lows  # 把下轨重新赋值为:前cycle_length根K线最低价的最低价
if low0 < low1:  # 如果当根K线最低价小于上根K线最低价
    up_line = highs  # 把上轨重新赋值为:前cycle_length根K线最高价的最高价
middle_line = (lows + highs) / 2;  # 计算中轨的值

这里有一个地方需要注意,可能细心的朋友已经发现了,我们在计算上轨和下轨的时候,用到了talib库中的Highest和Lowest函数,因为在发明者量化软件中已经内置了这两个常用的函数,所以我们不需要像前几节那样在策略开头导入talib库,并且在使用内置函数的时候,其写法也略有不同,具体可以查看下方的代码。

第4步:下单交易

有了上轨、下轨、中轨的值,就可以配合当前的最新价格开平仓交易了,我们可以回过头再看下之前设计的交易逻辑:如果当前没有持仓,并且价格大于上轨 * 1.05,买入开仓。如果当前没有持仓,并且价格小于下轨 * 0.95,卖出开仓。如果当前持有多单,并且价格小于中轨,卖出平仓。如果当前持有空单,兵器价格大于中轨,买入平仓。

if mp == 0 and close0 > up_line:  # 如果当前空仓,并且最新价大于上轨
    exchange.SetDirection("buy")  # 设置交易方向和类型
    exchange.Buy(close0, 1)  # 开多单
    mp = 1  # 设置虚拟持仓的值,即有多单
    
if mp == 0 and close0 < under_line:  # 如果当前空仓,并且最新价小于下轨
    exchange.SetDirection("sell")  # 设置交易方向和类型
    exchange.Sell(close0 - 1, 1)  # 开空单
    mp = -1  # 设置虚拟持仓的值,即有空单
    
if mp > 0 and close0 < middle_line:  # 如果当前持有多单,并且最新价小于中轨
    exchange.SetDirection("closebuy")  # 设置交易方向和类型
    exchange.Sell(close0 - 1, 1)  # 平多单
    mp = 0  # 设置虚拟持仓的值,即空仓
    
if mp < 0 and close0 > middle_line:  # 如果当前持有空单,并且最新价大于中轨
    exchange.SetDirection("closesell")  # 设置交易方向和类型
    exchange.Buy(close0, 1)  # 平空单
    mp = 0  # 设置虚拟持仓的值,即空仓

下单交易使用if语句,如果条件为真,就先设置交易方向和类型,即:开多、开空、平多、平空。然后调用发明者量化软件中的Buy或Sell下单函数,最后下单之后重置虚拟持仓的状态。

完整策略代码

'''backtest
start: 2015-02-22 00:00:00
end: 2019-10-29 00:00:00
period: 1h
exchanges: [{"eid":"Futures_CTP","currency":"FUTURES"}]
'''


# 外部参数
cycle_length = 100


# 定义全局变量
up_line = 0  # 上轨
under_line = 0  # 下轨
mp = 0  # 用于控制虚拟持仓


def onTick():
    exchange.SetContractType("rb000")  # 订阅期货品种
    bars = exchange.GetRecords()  # 获取K线数组
    if len(bars) < cycle_length + 1:  # 如果K线数组的长度太小,所以直接返回
        return
    close0 = bars[len(bars) - 1].Close;  # 获取当根K线收盘价
    high0 = bars[len(bars) - 1].High;  # 获取当根K线最高价
    high2 = bars[len(bars) - 2].High;  # 获取上根K线最高价
    low0 = bars[len(bars) - 1].Low;  # 获取当根K线最低价
    low1 = bars[len(bars) - 2].Low;  # 获取上根K线最低价
    highs = TA.Highest(bars, cycle_length, 'High');  # 获取前cycle_length根K线最高价的最高价
    lows = TA.Lowest(bars, cycle_length, 'Low');  # 获取前cycle_length根K线最低价的最低价
    global up_line, under_line, mp  # 使用全局变量
    if high0 > high2:  # 如果当根K线最高价大于上根K线最高价
        under_line = lows  # 把下轨重新赋值为:前cycle_length根K线最低价的最低价
    if low0 < low1:  # 如果当根K线最低价小于上根K线最低价
        up_line = highs  # 把上轨重新赋值为:前cycle_length根K线最高价的最高价
    middle_line = (lows + highs) / 2;  # 计算中轨的值
    
    if mp == 0 and close0 > up_line:  # 如果当前空仓,并且最新价大于上轨
        exchange.SetDirection("buy")  # 设置交易方向和类型
        exchange.Buy(close0, 1)  # 开多单
        mp = 1  # 设置虚拟持仓的值,即有多单
        
    if mp == 0 and close0 < under_line:  # 如果当前空仓,并且最新价小于下轨
        exchange.SetDirection("sell")  # 设置交易方向和类型
        exchange.Sell(close0 - 1, 1)  # 开空单
        mp = -1  # 设置虚拟持仓的值,即有空单
        
    if mp > 0 and close0 < middle_line:  # 如果当前持有多单,并且最新价小于中轨
        exchange.SetDirection("closebuy")  # 设置交易方向和类型
        exchange.Sell(close0 - 1, 1)  # 平多单
        mp = 0  # 设置虚拟持仓的值,即空仓
        
    if mp < 0 and close0 > middle_line:  # 如果当前持有空单,并且最新价大于中轨
        exchange.SetDirection("closesell")  # 设置交易方向和类型
        exchange.Buy(close0, 1)  # 平空单
        mp = 0  # 设置虚拟持仓的值,即空仓
    

def main():
    while True:
        onTick()
        Sleep(1000)

感谢各位的阅读!关于“python如何实现动态阶梯突破策略”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!


网站名称:python如何实现动态阶梯突破策略
网页URL:http://jkwzsj.com/article/pohijd.html

其他资讯