
支撑阻力突破策略与趋势-ADX滤波器量化交易系统是一种结合了技术分析中的支撑阻力位识别、趋势确认和市场强度验证的综合性交易策略。该策略基于市场价格对关键价格水平的突破行为,并通过移动平均线和平均方向指数(ADX)作为滤波器,提高交易信号的可靠性。系统采用1小时时间框架,通过识别枢轴高点和低点来构建动态支撑阻力区域,在价格突破这些区域时发出交易信号,同时设置了固定百分比的止盈止损机制以控制风险。
该策略的核心原理基于价格在关键支撑阻力位的突破行为,结合趋势方向和市场强度过滤,形成一个完整的交易系统。具体实现原理包括:
支撑阻力位识别: 系统利用枢轴点方法(Pivot Points)来识别重要的价格水平。通过ta.pivothigh和ta.pivotlow函数,以5周期为默认参数计算枢轴高点和低点,并将这些点位作为潜在的阻力位和支撑位。
动态区域管理: 系统使用数组结构supportLevels和resistanceLevels存储支撑阻力位,并通过自定义函数f_add_level智能管理这些价格水平。该函数确保新添加的水平与现有水平有足够的距离(默认2%),防止区域过度拥挤,同时限制最多保留5个最新的水平。
趋势确认滤波器: 策略使用50周期简单移动平均线(SMA)作为趋势方向指标。只有当价格位于均线上方时才考虑做多,位于均线下方时才考虑做空,从而顺应总体市场趋势。
市场强度验证: 通过自定义的ADX(平均方向指数)函数评估市场强度。ADX值必须高于设定阈值(默认25),确保只在市场有足够强度的情况下入场交易,避免弱市场环境下的假突破。
入场信号生成:
风险管理机制: 策略采用固定百分比的止盈止损设置,多头默认设置15%止盈和10%止损,空头默认设置10%止盈和10%止损。一旦价格达到这些水平,系统自动平仓并重置交易状态。
基于对代码的深入分析,该策略具有以下显著优势:
多重确认机制: 通过结合支撑阻力突破、趋势方向和ADX强度三重确认,有效降低假突破风险。与单一指标相比,多重确认机制提高了交易信号的可靠性。
动态支撑阻力区域: 系统动态识别和管理支撑阻力位,能够适应不同市场环境。最多保留5个最新的支撑阻力位,确保策略关注最相关的价格水平。
智能区域聚类: 通过最大区域宽度百分比参数(maxZoneWidthPct),避免了过于接近的支撑阻力位重复计算,减少冗余信号。
自定义ADX计算: 策略使用自定义ADX函数,通过直接计算真实波幅、方向移动和平滑处理,确保指标计算的准确性和灵活性。
灵活的参数配置: 策略提供多个可调参数,包括枢轴长度、回溯周期、最大区域宽度、止盈止损百分比以及ADX阈值等,使用户可以根据不同市场条件和交易偏好进行优化。
风险控制明确: 通过预设的止盈止损百分比,为每笔交易提供明确的风险管理框架,防止单笔交易的过度亏损,同时锁定合理利润。
直观的可视化: 策略在图表上标记支撑阻力位及交易信号,通过颜色编码(支撑位绿色,阻力位红色)和标签(LONG、SHORT、EXIT)提供直观的视觉反馈,便于回测分析和实时监控。
尽管该策略设计合理,但仍存在以下潜在风险和局限性:
高波动市场中的假突破: 在高波动市场环境下,价格可能频繁突破支撑阻力位后又回到原区间,导致假突破信号增多。解决方法:可以考虑增加确认周期,要求价格在突破后保持一定时间或形成特定形态才确认信号。
过度依赖历史支撑阻力位: 策略基于历史形成的支撑阻力位,在市场结构发生根本性变化时(如重大新闻事件),这些历史水平可能失效。解决方法:可以考虑增加动态调整机制,根据市场波动率自动调整支撑阻力位的有效期。
固定百分比止盈止损的局限性: 固定百分比的止盈止损可能不适合所有市场环境,在波动率较低的市场中可能过大,在波动率较高的市场中可能过小。解决方法:可以考虑基于ATR(真实波幅)动态调整止盈止损水平。
趋势反转风险: 使用50周期SMA作为趋势指标可能在趋势反转初期反应滞后,导致在趋势即将结束时仍然顺势入场。解决方法:可以考虑增加更敏感的短期趋势指标或动量指标作为辅助判断。
计算密集型策略: 策略需要实时计算和维护多个数组和指标,在高频交易或资源有限的环境中可能面临性能挑战。解决方法:优化算法效率,减少不必要的计算,或考虑降低更新频率。
参数敏感性: 策略性能对参数设置(如枢轴长度、ADX阈值)较为敏感,参数选择不当可能导致过度交易或错过机会。解决方法:通过回测不同市场条件下的参数表现,建立参数优化框架。
基于策略代码的深入分析,以下是潜在的优化方向:
自适应参数机制: 引入根据市场波动率自动调整关键参数的机制。例如,在高波动期间增加ADX阈值或支撑阻力区域宽度,在低波动期间降低这些参数,使策略更好地适应不同市场环境。这样可以减少在不适合的市场条件下的错误交易。
多时间框架分析: 增加更高时间框架的支撑阻力位确认。通过检查日线或周线图表上的支撑阻力位是否与当前1小时图表上的水平一致,可以识别更强的、多时间框架认可的关键价格区域,提高信号质量。
交易量确认: 结合交易量分析验证突破的有效性。真正有效的突破通常伴随着交易量的显著增加,通过添加交易量过滤条件,可以减少低交易量导致的假突破风险。
动态止盈止损: 基于市场波动率(如ATR)动态设置止盈止损水平,而非固定百分比。这使风险管理更加灵活,能够根据当前市场条件自动调整保护水平,在波动性高的市场中设置更宽松的止损,在波动性低的市场中设置更紧密的止损。
部分利润锁定机制: 引入分段获利机制,允许在达到一定利润水平后移动止损至成本价或锁定部分利润。这种方法可以在保持高收益潜力的同时降低回撤风险。
整合情绪指标: 考虑整合市场情绪指标(如VIX或相对强弱指标)作为额外过滤条件。市场情绪往往影响突破的可持续性,通过增加情绪分析维度,可以提高策略对市场状态的理解。
支撑阻力强度分级: 引入支撑阻力位强度评估机制,基于历史测试次数、形成时间长度等因素对各个水平进行强度评分。这样可以优先关注更强、更有可能产生有效反应的价格水平。
机器学习优化: 考虑使用机器学习方法优化参数选择和信号生成。通过分析历史数据中成功和失败的交易模式,机器学习算法可以帮助识别最有效的参数组合和市场条件。
支撑阻力突破策略与趋势-ADX滤波器量化交易系统是一个设计完善的综合性交易系统,结合了技术分析中的多种关键元素。该策略通过动态识别和监控支撑阻力位,结合趋势方向和市场强度过滤,创建了一个相对可靠的交易信号生成机制。
策略的核心优势在于其多重确认机制和完善的风险管理框架,有效降低了假突破风险并限制了单笔交易的潜在损失。同时,策略提供了丰富的参数配置选项,使交易者能够根据个人风险偏好和市场环境进行灵活调整。
然而,该策略也面临一些挑战,如高波动市场中的假突破风险、固定止盈止损的局限性以及参数敏感性等。通过引入自适应参数机制、多时间框架分析、交易量确认和动态风险管理等优化措施,策略性能有望进一步提升。
总的来说,这是一个逻辑清晰、设计合理的量化交易策略,适合对技术分析和市场结构有一定理解的交易者使用。通过持续优化和适应市场变化,该策略有潜力在不同市场环境中保持稳定表现。
/*backtest
start: 2024-05-30 00:00:00
end: 2025-05-29 00:00:00
period: 3d
basePeriod: 3d
exchanges: [{"eid":"Futures_Binance","currency":"ETH_USDT"}]
*/
//@version=6
strategy("S/R Breakout Strategy (1H) with Trend and ADX Filter", overlay=true, default_qty_type=strategy.percent_of_equity, default_qty_value=100)
// ─────────────────────────────────────────────────────────────
// INPUTS
// ─────────────────────────────────────────────────────────────
pivotLen = input.int(5, title="Pivot Length")
lookbackBars = input.int(300, title="Lookback Bars")
maxZoneWidthPct = input.float(2.0, title="Max Zone Width %")
tpLong = input.float(0.15, title="Take Profit % (Long)")
slLong = input.float(0.10, title="Stop Loss % (Long)")
tpShort = input.float(0.10, title="Take Profit % (Short)")
slShort = input.float(0.10, title="Stop Loss % (Short)")
allowLong = input.bool(true, title="Allow Long Trades")
allowShort = input.bool(true, title="Allow Short Trades")
// ADX settings
adxThreshold = input.float(25.0, title="ADX Threshold")
adxLen = input.int(14, title="ADX Length")
// Trend filter: 50-period moving average
ma50 = ta.sma(close, 50)
// ─────────────────────────────────────────────────────────────
// CUSTOM ADX FUNCTION
// ─────────────────────────────────────────────────────────────
// This function calculates ADX using the common method based on true range,
// directional movement and smoothing it with the RMA.
f_adx(len) =>
// true range for the current bar
tr = ta.tr
// Calculate upward and downward moves
upMove = high - high[1]
downMove = low[1] - low
// Determine directional movements
plusDM = (upMove > downMove and upMove > 0) ? upMove : 0.0
minusDM = (downMove > upMove and downMove > 0) ? downMove : 0.0
// Smooth the values using RMA (running moving average)
smPlusDM = ta.rma(plusDM, len)
smMinusDM = ta.rma(minusDM, len)
smTR = ta.rma(tr, len)
// Calculate the directional indicators, avoid division by zero
plusDI = (smTR != 0) ? 100 * smPlusDM / smTR : 0.0
minusDI = (smTR != 0) ? 100 * smMinusDM / smTR : 0.0
diSum = plusDI + minusDI
dx = (diSum != 0) ? 100 * math.abs(plusDI - minusDI) / diSum : 0.0
// Smooth the DX to get ADX
ta.rma(dx, len)
// Compute ADX value using the custom function
adxValue = f_adx(adxLen)
// ─────────────────────────────────────────────────────────────
// PIVOT DETECTION & SUPPORT/RESISTANCE LEVELS
// ─────────────────────────────────────────────────────────────
pivotHigh = ta.pivothigh(high, pivotLen, pivotLen)
pivotLow = ta.pivotlow(low, pivotLen, pivotLen)
// Declare arrays for support and resistance levels
var float[] supportLevels = array.new_float()
var float[] resistanceLevels = array.new_float()
// Function to add a level into the provided array if it meets the criteria.
// Always returns a float (0.0) for consistency.
f_add_level(arr, newLevel) =>
if array.size(arr) == 0
array.push(arr, newLevel)
else
shouldAdd = true
for i = 0 to (array.size(arr) - 1)
existing = array.get(arr, i)
if math.abs(existing - newLevel) / newLevel * 100 <= maxZoneWidthPct
shouldAdd := false
if shouldAdd
array.push(arr, newLevel)
if array.size(arr) > 5
array.shift(arr)
0.0
// Update support and resistance arrays once sufficient bars have formed
if bar_index > pivotLen * 2
if not na(pivotLow)
f_add_level(supportLevels, pivotLow)
if not na(pivotHigh)
f_add_level(resistanceLevels, pivotHigh)
// ─────────────────────────────────────────────────────────────
// TRADE MANAGEMENT VARIABLES
// ─────────────────────────────────────────────────────────────
var bool inTrade = false
var bool isLong = false
var float entryPrice = na
// Signal flags
longSignal = false
shortSignal = false
// Detect long signal: price crosses above support level
if array.size(supportLevels) > 0
for i = 0 to (array.size(supportLevels) - 1)
lvl = array.get(supportLevels, i)
if low < lvl and close > lvl
longSignal := true
// Detect short signal: price crosses below resistance level
if array.size(resistanceLevels) > 0
for i = 0 to (array.size(resistanceLevels) - 1)
lvl = array.get(resistanceLevels, i)
if high > lvl and close < lvl
shortSignal := true
// ─────────────────────────────────────────────────────────────
// ENTRY CONDITIONS & EXECUTION
// ─────────────────────────────────────────────────────────────
if not inTrade
// Long entry: require long signal, price above 50MA, and ADX above threshold
if allowLong and longSignal and close > ma50 and adxValue > adxThreshold
strategy.entry("Long", strategy.long)
label.new(x=bar_index, y=low, text="LONG", xloc=xloc.bar_index, style=label.style_label_up, color=color.green, textcolor=color.white)
entryPrice := close
isLong := true
inTrade := true
// Short entry: require short signal, price below 50MA, and ADX above threshold
else if allowShort and shortSignal and close < ma50 and adxValue > adxThreshold
strategy.entry("Short", strategy.short)
label.new(x=bar_index, y=high, text="SHORT", xloc=xloc.bar_index, style=label.style_label_down, color=color.red, textcolor=color.white)
entryPrice := close
isLong := false
inTrade := true
// ─────────────────────────────────────────────────────────────
// EXIT CONDITIONS
// ─────────────────────────────────────────────────────────────
if inTrade
ret = isLong ? (close - entryPrice) / entryPrice : (entryPrice - close) / entryPrice
tp = isLong ? tpLong : tpShort
sl = isLong ? slLong : slShort
if ret >= tp or ret <= -sl
strategy.close_all()
label.new(x=bar_index, y=close, text="EXIT", xloc=xloc.bar_index, style=label.style_label_left, color=color.orange, textcolor=color.black)
inTrade := false
entryPrice := na
// ─────────────────────────────────────────────────────────────
// ALERT CONDITIONS
// ─────────────────────────────────────────────────────────────
alertcondition(longSignal and allowLong, title="Long Breakout", message="🚀 Long breakout on {{ticker}} at {{close}}")
alertcondition(shortSignal and allowShort, title="Short Breakout", message="🔻 Short breakout on {{ticker}} at {{close}}")