Overview
The Higher Timeframe Weighted Moving Average Zone Breakout Quantitative Trading Strategy is a trading system based on price zone breakouts, combining higher timeframe weighted moving averages (WMA) with percentage-based zones to construct trading areas. The strategy generates entry signals by identifying price breakouts above the upper line or below the lower line, and applies staged profit-taking and stop-loss settings to manage risk. The core of the strategy is using weighted moving averages on a higher timeframe to filter out short-term market noise, then building trading zones on the current timeframe, making trading decisions more robust and reliable.
Strategy Principles
The basic principle of this strategy is to use weighted moving averages from a higher timeframe to construct price action zones. The specific implementation steps are as follows:
- First, the strategy calculates weighted moving averages (WMA) of the open, high, low, and close prices, with periods based on the user-defined minimum period parameter (default is 60).
- Then, the strategy transfers these WMA values from a higher timeframe (default is monthly) to the current trading timeframe.
- It calculates the midpoint of the high and low weighted moving averages as the center price.
- Based on the center price and a user-defined percentage ratio (default is 0.1 or 10%), it constructs upper (resistance) and lower (support) lines.
- When price breaks above the upper line, a long signal is triggered; when price breaks below the lower line, a short signal is triggered.
- The strategy sets two take-profit targets (default at 10% and 20%), each closing a portion of the position (default 50% each).
- It also sets a stop-loss (default at 5%) to limit potential losses.
The strategy uses visual elements such as background color changes, custom candles, and entry/exit markers to help traders visually identify trading zones and current market conditions. Additionally, the strategy displays the percentage change of the current position with an applied multiplier factor (default is 20) to highlight price movements.
Strategy Advantages
Analyzing the strategy code in depth, we can identify the following significant advantages:
Higher Timeframe Filtering: By using weighted moving averages from a higher timeframe, the strategy effectively filters out short-term market noise, capturing more meaningful price movements and reducing false signals.
Dynamic Trading Zones: The strategy dynamically constructs trading zones based on price midpoints and percentage ratios, adapting to different market conditions and volatility, avoiding the limitations of fixed support/resistance levels.
Clear Entry and Exit Rules: The strategy provides clear entry signals (breakouts above/below lines) and exit rules (staged take-profits and stop-loss), eliminating subjectivity in trading decisions.
Integrated Risk Management: The built-in stop-loss and staged take-profit mechanisms help protect capital and lock in profits, making it a complete trading system.
Rich Visual Feedback: The strategy provides rich visual elements, including trading zone background colors, percentage change labels, and entry/exit markers, helping traders quickly assess market conditions.
Flexible Parameter Settings: Users can adjust multiple parameters based on personal preferences and different market conditions, including timeframes, moving average periods, ratio percentages, take-profit/stop-loss levels, and visual elements.
Multi-Timeframe Coordination: The strategy combines the signal quality of higher timeframes with the execution precision of the current timeframe, achieving multi-timeframe coordination.
Strategy Risks
Despite its many advantages, the strategy also has the following potential risks:
False Breakout Signals: Price may briefly break through zone boundaries before reverting, leading to false trading signals. To mitigate this risk, consider adding confirmation mechanisms, such as requiring price to hold for a period after breakout, or combining with other indicators for confirmation.
Unsuitable for Highly Volatile Markets: In highly volatile markets, price may frequently break through zone boundaries, leading to excessive trading and potential losses. In such cases, increasing the zone ratio or switching to a higher timeframe may help.
Fixed Percentage Stop-Loss/Take-Profit Lack Flexibility: Market volatility changes over time, and fixed percentage stop-loss/take-profit may not always be optimal. Consider dynamically adjusting stop-loss/take-profit levels based on volatility indicators such as ATR.
Parameter Sensitivity: Strategy performance may be highly sensitive to parameter settings, such as WMA periods, zone ratios, and take-profit/stop-loss percentages. Thorough historical backtesting and parameter optimization are necessary.
Over-Optimization Risk: Overfitting to specific historical data may lead to poor future performance. It is recommended to backtest across multiple markets and time periods, and keep parameters relatively stable.
Market Trend Change Adaptability: The strategy does not adjust its zones based on new market trends after a breakout, which may lead to incorrect signals in strong trending markets. Consider adding trend filters or dynamically adjusting zones.
Strategy Optimization Directions
Based on in-depth analysis of the code, the strategy can be optimized in the following directions:
Add Breakout Confirmation Mechanism: To reduce false breakouts, additional confirmation conditions can be added, such as requiring closing price after breakout, volume confirmation, or cross-verification using other technical indicators (like RSI, MACD).
Dynamic Stop-Loss Settings: Replace fixed percentage stop-losses with volatility-based dynamic stop-losses, such as using multiples of ATR (Average True Range) to set stop-loss levels, making the strategy better adapt to different market conditions.
Add Trend Filters: Add trend identification components, such as long-term moving averages or ADX indicators, to adjust trading behavior in strong trending markets, for example, only going long in uptrends and short in downtrends.
Optimize Entry Timing: The current strategy enters immediately when price breaks through zone boundaries; consider waiting for pullbacks or specific pattern confirmations to improve entry quality.
Enhance Money Management Module: Implement more sophisticated position size calculations based on account size, market volatility, and current trade risk, rather than using fixed positions.
Add Market State Filtering: Identify market states (such as trending, ranging, or high volatility) and adjust strategy parameters or pause trading based on different market states.
Implement Adaptive Parameters: Allow key parameters such as zone ratios, WMA periods, etc., to automatically adjust based on historical volatility or other market characteristics, improving strategy adaptability.
Integrate Multi-Timeframe Signals: Not only use higher timeframe WMAs to construct zones, but also analyze price behavior and indicators across multiple timeframes for more comprehensive market analysis and trading decisions.
Summary
The Higher Timeframe Weighted Moving Average Zone Breakout Quantitative Trading Strategy is a well-structured trading system that captures price breakout opportunities by combining higher timeframe weighted moving averages with dynamic zone construction. The strategy's strengths lie in its higher timeframe filtering capability, clear trading rules, built-in risk management mechanisms, and rich visual feedback. However, it also faces challenges such as false breakout signals, parameter sensitivity, and market adaptability.
By implementing the suggested optimization directions, such as adding breakout confirmation mechanisms, dynamic stop-loss settings, trend filtering, and adaptive parameters, the strategy's robustness and profitability can be further enhanced. Most importantly, traders should fully understand the strategy principles and conduct thorough historical backtesting, adjusting parameters according to specific markets and personal risk preferences to fully unleash the strategy's potential.
This zone breakout-based strategy is suitable for medium to long-term traders, especially those seeking to capture significant price breakouts while maintaining risk control. Through continuous optimization and adjustment, this strategy can become a powerful weapon in a trader's toolbox.
Strategy source code
/*backtest
start: 2025-01-01 00:00:00
end: 2025-05-25 00:00:00
period: 2h
basePeriod: 2h
exchanges: [{"eid":"Futures_Binance","currency":"SOL_USDT"}]
*/
//@version=5
strategy('ZONE FLOW', overlay=true)
// Input parameters
src = close
src1 = open
src2 = low
src3 = high
Min = input(60, title='Minimum Period')
len = timeframe.isintraday and timeframe.multiplier >= 1 ? Min / timeframe.multiplier * 7 : timeframe.isintraday and timeframe.multiplier < 60 ? 60 / timeframe.multiplier * 24 * 7 : 7
c1 = ta.wma(src, len)
o1 = ta.wma(src1, len)
l1 = ta.wma(src2, len)
h1 = ta.wma(src3, len)
HTF = input.timeframe('M', title='Higher Time Frame')
ti = ta.change(time(HTF)) != 0
c = fixnan(ti ? c1 : na)
o = fixnan(ti ? o1 : na)
h = fixnan(ti ? h1 : na)
l = fixnan(ti ? l1 : na)
// Calculating mid-point
m = (h + l) / 2
// Calculating ratio lines
ratio = input.float(0.1, title='% ratio', minval=0.001, maxval=10)
r1 = m * ratio
u = m + r1
d = m - r1
// Take profit settings
takeProfitPercentage1 = input.float(10.0, title='Take Profit 1 (%)', minval=0.1, maxval=100.0) / 100
takeProfitQuantity1 = input.float(50.0, title='Take Profit 1 Quantity (%)', minval=0.1, maxval=100.0) / 100
takeProfitPercentage2 = input.float(20.0, title='Take Profit 2 (%)', minval=0.1, maxval=100.0) / 100
takeProfitQuantity2 = input.float(50.0, title='Take Profit 2 Quantity (%)', minval=0.1, maxval=100.0) / 100
// Stop loss settings
stopLossPercentage = input.float(5.0, title='Stop Loss (%)', minval=0.1, maxval=100.0) / 100
// Number of bars to extend lines
extensionBars = input.int(5, title='Number of Bars to Extend Lines', minval=1)
// Number of bars to offset the percentage label
percentOffsetBars = input.int(25, title='Number of Bars to Offset Percentage Label', minval=1)
// Input for multiplying the percentage change
multiplierFactor = input.int(20, title='Multiplier for Percentage Change', minval=1)
// Input for background colors
bgColor1 = input(color.new(color.blue, 90), title='Background Color 1')
bgColor2 = input(color.new(color.orange, 90), title='Background Color 2')
// Plot high, low, and ratio lines
ppo = plot(u, color=color.new(color.blue, 0), title='Upper Line (Resistance)', style=plot.style_stepline)
ppc = plot(d, color=color.new(color.orange, 0), title='Lower Line (Support)', style=plot.style_stepline)
plot(u, color=color.new(color.blue, 0), title='Upper Line (Resistance)', style=plot.style_circles, linewidth=2)
plot(d, color=color.new(color.orange, 0), title='Lower Line (Support)', style=plot.style_circles, linewidth=2)
// Fill the background between ratio lines with two different colors
fill(ppo, ppc, color=bgColor1)
// Calculate mid-point for background color switching
midPoint = (u + d) / 2
bgColorSwitch = close >= midPoint ? bgColor1 : bgColor2
fill(ppo, ppc, color=bgColorSwitch, transp=90)
// Initialize variables for lines and labels
var line tp1Line = na
var line tp2Line = na
var line stopLossLine = na
var line entryLine = na
var label tp1Label = na
var label tp2Label = na
var label stopLossLabel = na
var label entryLabel = na
var label percentLabel = na
// Variable to store the entry bar index
var int entryBarIndexLong = na
var int entryBarIndexShort = na
// Function to delete old labels and lines
deleteOldLinesAndLabels() =>
if not na(tp1Line)
line.delete(tp1Line)
if not na(tp2Line)
line.delete(tp2Line)
if not na(stopLossLine)
line.delete(stopLossLine)
if not na(entryLine)
line.delete(entryLine)
if not na(tp1Label)
label.delete(tp1Label)
if not na(tp2Label)
label.delete(tp2Label)
if not na(stopLossLabel)
label.delete(stopLossLabel)
if not na(entryLabel)
label.delete(entryLabel)
if not na(percentLabel)
label.delete(percentLabel)
// Strategy logic
longCondition = ta.crossover(close, u)
shortCondition = ta.crossunder(close, d)
if longCondition
strategy.entry('Long', strategy.long)
entryBarIndexLong := bar_index
entryBarIndexLong
if shortCondition
strategy.entry('Short', strategy.short)
entryBarIndexShort := bar_index
entryBarIndexShort
// Calculate take profit and stop loss levels for long positions
if strategy.position_size > 0 // Check if there's an open long position
takeProfitLevelLong1 = strategy.position_avg_price * (1 + takeProfitPercentage1)
takeProfitLevelLong2 = strategy.position_avg_price * (1 + takeProfitPercentage2)
stopLossLevelLong = strategy.position_avg_price * (1 - stopLossPercentage)
entryPrice = strategy.position_avg_price
// Delete existing lines and labels if they exist
deleteOldLinesAndLabels()
// Exit a portion of the position at each take profit level
strategy.exit('TP1', 'Long', limit=takeProfitLevelLong1, qty=strategy.position_size * takeProfitQuantity1)
strategy.exit('TP2', 'Long', limit=takeProfitLevelLong2, qty=strategy.position_size * takeProfitQuantity2)
strategy.exit('Stop Loss', 'Long', stop=stopLossLevelLong)
// Display percentage change from entry price
percentChange = (close - strategy.position_avg_price) / strategy.position_avg_price * 100
percentMultiplied = percentChange * multiplierFactor
percentColor = percentChange >= 0 ? color.green : color.red
// Update label position to follow price line with larger text size
percentLabel := label.new(x=bar_index + percentOffsetBars, y=close, text=str.tostring(percentMultiplied, format.percent) + '%', color=percentColor, textcolor=color.white, size=size.large, style=label.style_label_down)
percentLabel
if strategy.position_size < 0 // Check if there's an open short position
takeProfitLevelShort1 = strategy.position_avg_price * (1 - takeProfitPercentage1)
takeProfitLevelShort2 = strategy.position_avg_price * (1 - takeProfitPercentage2)
stopLossLevelShort = strategy.position_avg_price * (1 + stopLossPercentage)
entryPrice = strategy.position_avg_price
// Delete existing lines and labels if they exist
deleteOldLinesAndLabels()
// Exit a portion of the position at each take profit level
strategy.exit('TP1', 'Short', limit=takeProfitLevelShort1, qty=strategy.position_size * takeProfitQuantity1)
strategy.exit('TP2', 'Short', limit=takeProfitLevelShort2, qty=strategy.position_size * takeProfitQuantity2)
strategy.exit('Stop Loss', 'Short', stop=stopLossLevelShort)
// Display percentage change from entry price
percentChange = (strategy.position_avg_price - close) / strategy.position_avg_price * 100
percentMultiplied = percentChange * multiplierFactor
percentColor = percentChange >= 0 ? color.green : color.red
// Update label position to follow price line with larger text size
percentLabel := label.new(x=bar_index + percentOffsetBars, y=close, text=str.tostring(percentMultiplied, format.percent) + '%', color=percentColor, textcolor=color.white, size=size.large, style=label.style_label_down)
percentLabel
// Add buy and sell signals with shapes
plotshape(series=longCondition, title='Buy Signal', location=location.belowbar, color=color.new(color.green, 0), style=shape.labelup, text='.')
plotshape(series=shortCondition, title='Sell Signal', location=location.abovebar, color=color.new(color.red, 0), style=shape.labeldown, text='.')
// Remove old labels when they go out of scope
if bar_index % 50 == 0
deleteOldLinesAndLabels()
// Define colors for candles based on background color
candleColorBull = bgColorSwitch // Use background color for bullish candles
candleColorBear = bgColorSwitch // Use background color for bearish candles
borderColorBull = color.black // Border color for bullish candles
borderColorBear = color.black // Border color for bearish candles
// Plot candles with custom colors
plotcandle(open, high, low, close, color=close >= open ? candleColorBull : candleColorBear, bordercolor=close >= open ? borderColorBull : borderColorBear, wickcolor=color.gray)
Strategy parameters
The original address: Higher Timeframe Weighted Moving Average Zone Breakout Quantitative Trading Strategy
Love how this strategy accounts for higher timeframe bias - finally something smarter than my 'buy high, sell low' technique! 😅 Though I'd add a 'coffee spill indicator' for those volatile mornings. Seriously though, systematic approaches > gut feelings!