该策略是一个基于平均真实波幅(ATR)和价格突破的ETF自动交易策略。它使用ATR来计算止损位和止盈位,并在价格突破一定周期最高价或最低价时开仓做多或做空。
该策略主要基于以下原理:
使用一定周期(如20根K线)的最高价和最低价来判断价格走势和方向。当价格突破周期最高价时,做多;当价格突破周期最低价时,做空。
使用ATR来动态计算止损位。止损位距离入场价一个ATR周期的ATR值乘以系数(如2)。
使用ATR来计算止盈位。止盈距离入场价为一个ATR周期的ATR值乘以系数(如1)。
使用ATRtrailer多因子来跟踪止损。当价格向不利方向突破trailer止损位时,平仓止损。
该策略简单可靠,既考虑了价格趋势的方向,有利于及时捕捉价格趋势;又设置了止损和止盈位,有利于把握盈利机会并控制风险。
该策略具有以下优势:
策略思路简单清晰,容易理解和实施。
利用ATR计算止盈止损位,可以动态调整仓位规模,灵活控制风险。
周期突破判断策略容易捕捉价格趋势,收益较好。
Trailer止损可以及时止损,避免承担过大风险。
适用于趋势较明显的品种,如ETF、股票等。
该策略也存在以下风险:
价格震荡时,可能出现较多的错误信号和反向开仓。
周期参数设置不当可能错过价格趋势或虚惊交易次数过多。
系数参数设置不当,可能导致止损或止盈过于激进或保守,影响盈利。
ETF本身具有的风险,如政策风险、溢价风险等也会对策略带来影响。
对应解决方法: 1. 优化参数,降低虚拟交易率。 2. 结合多个因子和过滤器来确定交易信号。 3. 按不同市场调整参数。 4. 分散投资,控制单只ETF的仓位。
该策略可以从以下几个方面进一步优化:
结合移动均线等指标来过滤虚假信号。
增加适应性参数优化模块,根据不同周期和品种自动优化参数。
增加机器学习模型预测下一根K线的高点和低点,来判断突破信号。
考虑交易量溢出等指标,防范假突破。
优化开仓仓位大小和比例,不同品种和市场环境适应性开仓。
该策略整体思路清晰简洁,核心机制突破和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, "#"))