基于ATR和突破的ETF交易策略


创建日期: 2023-12-26 16:05:55 最后修改: 2023-12-26 16:05:55
复制: 1 点击次数: 505
avatar of ChaoZhang ChaoZhang
1
关注
1240
关注者

基于ATR和突破的ETF交易策略

概述

该策略是一个基于平均真实波幅(ATR)和价格突破的ETF自动交易策略。它使用ATR来计算止损位和止盈位,并在价格突破一定周期最高价或最低价时开仓做多或做空。

策略原理

该策略主要基于以下原理:

  1. 使用一定周期(如20根K线)的最高价和最低价来判断价格走势和方向。当价格突破周期最高价时,做多;当价格突破周期最低价时,做空。

  2. 使用ATR来动态计算止损位。止损位距离入场价一个ATR周期的ATR值乘以系数(如2)。

  3. 使用ATR来计算止盈位。止盈距离入场价为一个ATR周期的ATR值乘以系数(如1)。

  4. 使用ATRtrailer多因子来跟踪止损。当价格向不利方向突破trailer止损位时,平仓止损。

该策略简单可靠,既考虑了价格趋势的方向,有利于及时捕捉价格趋势;又设置了止损和止盈位,有利于把握盈利机会并控制风险。

优势分析

该策略具有以下优势:

  1. 策略思路简单清晰,容易理解和实施。

  2. 利用ATR计算止盈止损位,可以动态调整仓位规模,灵活控制风险。

  3. 周期突破判断策略容易捕捉价格趋势,收益较好。

  4. Trailer止损可以及时止损,避免承担过大风险。

  5. 适用于趋势较明显的品种,如ETF、股票等。

风险分析

该策略也存在以下风险:

  1. 价格震荡时,可能出现较多的错误信号和反向开仓。

  2. 周期参数设置不当可能错过价格趋势或虚惊交易次数过多。

  3. 系数参数设置不当,可能导致止损或止盈过于激进或保守,影响盈利。

  4. ETF本身具有的风险,如政策风险、溢价风险等也会对策略带来影响。

对应解决方法: 1. 优化参数,降低虚拟交易率。 2. 结合多个因子和过滤器来确定交易信号。 3. 按不同市场调整参数。 4. 分散投资,控制单只ETF的仓位。

优化方向

该策略可以从以下几个方面进一步优化:

  1. 结合移动均线等指标来过滤虚假信号。

  2. 增加适应性参数优化模块,根据不同周期和品种自动优化参数。

  3. 增加机器学习模型预测下一根K线的高点和低点,来判断突破信号。

  4. 考虑交易量溢出等指标,防范假突破。

  5. 优化开仓仓位大小和比例,不同品种和市场环境适应性开仓。

总结

该策略整体思路清晰简洁,核心机制突破和ATR动态止盈止损可以有效控制风险和锁定盈利。通过参数优化和结合更多过滤指标,可以进一步增强策略Profit因子和风险控制能力,是一个值得入手和持续优化的量化策略。

策略源码
/*backtest
start: 2023-12-18 00:00:00
end: 2023-12-21 03:00:00
period: 1m
basePeriod: 1m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © FX_minds

//@version=4
strategy("ETF tradedr", overlay=true, pyramiding=100, default_qty_type=strategy.percent_of_equity, default_qty_value=100)

//------------------------------ get user input
lookback                   = input(title="HH LL lookback", type=input.integer, defval=20)
ATR_periode                = input(title="ATR period", type=input.integer, defval=14)
ATR_SL_multiplier          = input(title="ATR SL multiplier", type=input.float, defval=2)
ATR_TP_multiplier          = input(title="ATR TP multiplier", type=input.float, defval=1)
trailing_SL_ATR_multiplier = input(title="ATR trailing SL multiplier", type=input.float, defval=3.5)
lookback_trailing_SL       = input(title="trailing SL lookback", type=input.integer, defval=4)
max_sequel_trades          = input(title="max sequel trades", type=input.float, defval=1)
trade_long                 = input(title= "trade long ?", type=input.bool, defval=true)
trade_short                = input(title= "trade short ?", type=input.bool, defval=false)

//------------------------------ determine entry conditions
long_condition   = barstate.isconfirmed and crossover(high, highest(high, lookback)[1])
short_condition  = barstate.isconfirmed and crossunder(low, lowest(low, lookback)[1])


//------------------------------ count open long trades
count_open_longs = 0
count_open_longs := nz(count_open_longs[1])

if (long_condition) 
    count_open_longs := count_open_longs +1
    //label.new(bar_index, low, tostring(count_open_longs, "#"), xloc.bar_index, yloc.belowbar, color.green, label.style_none, color.green, size.large)

if (short_condition)
    count_open_longs := 0


//------------------------------ count open short trades
count_open_shorts = 0
count_open_shorts := nz(count_open_shorts[1])

if (short_condition)
    count_open_shorts := count_open_shorts +1
    //label.new(bar_index, low, tostring(count_open_shorts, "#"), xloc.bar_index, yloc.belowbar, color.red, label.style_none, color.red, size.large)

if (long_condition)
    count_open_shorts := 0


//------------------------------ calculate entryprice
entryprice_long = long_condition ? close : na
entryprice_short = short_condition ? close : na


//------------------------------ calculate SL & TP
SL_distance = atr(ATR_periode) * ATR_SL_multiplier
TP_distance  = atr(ATR_periode) * ATR_TP_multiplier
trailing_SL_distance = atr(ATR_periode) * trailing_SL_ATR_multiplier

SL_long = entryprice_long - SL_distance
SL_short = entryprice_short + SL_distance

trailing_SL_short = lowest(close, lookback_trailing_SL) + trailing_SL_distance
trailing_SL_long  = highest(close, lookback_trailing_SL) - trailing_SL_distance

trailing_SL_short_signal = crossover(high, trailing_SL_short[1])
trailing_SL_long_signal = crossunder(low, trailing_SL_long[1])


//------------------------------ plot entry price & SL  
plot(entryprice_long, style=plot.style_linebr, color=color.white)
plot(SL_long, style=plot.style_linebr, color=color.red)
plot(SL_short, style=plot.style_linebr, color=color.green)
plot(trailing_SL_short, style=plot.style_linebr, color=color.red)
plot(trailing_SL_long, style=plot.style_linebr, color=color.green)


//------------------------------ submit entry orders
if (long_condition) and (count_open_longs <= max_sequel_trades) and (trade_long == true)
    strategy.entry("Long" + tostring(count_open_longs, "#"), strategy.long)
    strategy.exit("SL Long"+ tostring(count_open_longs, "#"), 
     from_entry="Long" + tostring(count_open_longs, "#"), stop=SL_long)

if (short_condition) and (count_open_shorts <= max_sequel_trades) and (trade_short == true)
    strategy.entry("Short" + tostring(count_open_shorts, "#"), strategy.short)
    strategy.exit("SL Short" + tostring(count_open_shorts, "#"), 
     from_entry="Short" + tostring(count_open_shorts, "#"), stop=SL_short)
    

//------------------------------ submit exit conditions
if (trailing_SL_long_signal)
    strategy.close("Long" + tostring(count_open_longs, "#"))
    strategy.close("Long" + tostring(count_open_longs-1, "#"))
    strategy.close("Long" + tostring(count_open_longs-2, "#"))
    strategy.close("Long" + tostring(count_open_longs-4, "#"))
    strategy.close("Long" + tostring(count_open_longs-5, "#"))
    strategy.close("Long" + tostring(count_open_longs-6, "#"))
    strategy.close("Long" + tostring(count_open_longs-7, "#"))
    strategy.close("Long" + tostring(count_open_longs-8, "#"))
    strategy.close("Long" + tostring(count_open_longs-9, "#"))
    
if (trailing_SL_short_signal)
    strategy.close("Short" + tostring(count_open_shorts, "#"))
    strategy.close("Short" + tostring(count_open_shorts-1, "#"))
    strategy.close("Short" + tostring(count_open_shorts-2, "#"))
    strategy.close("Short" + tostring(count_open_shorts-3, "#"))
    strategy.close("Short" + tostring(count_open_shorts-4, "#"))
    strategy.close("Short" + tostring(count_open_shorts-5, "#"))
    strategy.close("Short" + tostring(count_open_shorts-6, "#"))
    strategy.close("Short" + tostring(count_open_shorts-7, "#"))
    strategy.close("Short" + tostring(count_open_shorts-8, "#"))
    strategy.close("Short" + tostring(count_open_shorts-9, "#"))