The AutoLength Moving Average is a dynamic adaptation of the traditional moving average that adjusts its length based on market conditions (author Zeiierman). Unlike standard moving averages that rely on fixed periods, this indicator intelligently modifies its length using a counter-based approach, allowing it to adapt to varying market trends. This feature makes it especially useful for traders who need a responsive yet smooth trend-following tool.
The AutoLength Moving Average is designed to dynamically adjust its smoothing period, ensuring that it reacts appropriately to market fluctuations. Here’s how it works:
This approach allows the AutoLength Moving Average to smooth price movements while being flexible enough to capture changes in trend direction efficiently.
A critical aspect of this indicator is its ability to reset or reverse the counter based on different market conditions. The trader can select from eight different reset conditions:
By selecting the appropriate reset condition, traders can fine-tune the indicator to align with their trading style, whether they prefer trend-following or mean-reversion strategies.
To enhance usability, the AutoLength Moving Average includes visual elements to indicate key trading signals:
These signals help traders quickly identify trend shifts and adjust their strategies accordingly.
To optimize the indicator for different market conditions, traders can adjust several parameters:
Each of these settings allows users to adapt the AutoLength Moving Average to their preferred trading methodology.
Below is the full ProBuilder code for the AutoLength Moving Average, which can be copied and used directly in ProRealTime:
//---------------------------------------------//
//PRC_AutoLength Moving Average (Zeiierman)
//version = 0
//10.03.2025
//Iván González @ www.prorealcode.com
//Sharing ProRealTime knowledge
//---------------------------------------------//
// Inputs
//---------------------------------------------//
src = close // Source price used for calculations
baseLen = 50 // Base length for the Moving Average
maxDynLen = 350 // Maximum dynamic length for MA
counterbreak = 70 // Threshold for counter reversal
reverseCounter = 0 // 1=true, 0=false -> Reverses counter after break
trendingCol = 10 // Length of trend confirmation
// Selection of Reset Condition Type
resetConditiontype = 1
// 1 = Based on Moving Average Slope
// 2 = Based on RSI Overbought/Oversold levels
// 3 = Based on Volume SMA
// 4 = Based on Bollinger Bands (Price Breakout)
// 5 = Based on MACD Line and Signal Line Crossover
// 6 = Based on Stochastic Overbought/Oversold levels
// 7 = Based on CCI Overbought/Oversold levels
// 8 = Based on Momentum (Rate of Change)
// Ma
slopeOB = 50 // Length for MA slope calculation
//RSI
rsiLength = 14 // RSI period length
rsiOB = 60 // RSI Overbought level
rsiOS = 40 // RSI Oversold level
//Volume
volSmaLength = 20 // Volume SMA length
//Bollinger
bblength = 200 // Bollinger Bands length
bbMult = 1.1 // Bollinger Bands multiplier
//Macd
macdfastLength = 50 // Fast length for MACD calculation
macdSlowLength = 100 // Slow length for MACD calculation
macdSignalLength = 25 // Signal length for MACD
//Stochastic
stochLength = 50 // Stochastic period length
stochOB = 60 // Stochastic Overbought level
stochOS = 40 // Stochastic Oversold level
//CCI
cciLength = 100 // Commodity Channel Index (CCI) length
cciOB = 10 // CCI Overbought threshold
cciOS = -10 // CCI Oversold threshold
//Momentum
momentumLength = 140 // Momentum period length
//Trend
length = 20 // Trend smoothing length
trendSmoothing = 0.8 // Smoothing weight for trend adaptation
trending = 20 // Trending periods for confirmation
//---------------------------------------------//
// Calculate indicators
//---------------------------------------------//
// RSI
rsivalue=rsi[rsilength](src)
// Volume SMA
volSMA = average[volSmaLength,2](volume)
// MACD
mymacdline=MACDline[macdfastLength,macdSlowLength,macdSignalLength](src)
mysignalline=MACDSignal[macdfastLength,macdSlowLength,macdSignalLength](src)
// Stochastic
stochK=Stochastic[stochLength,3](close)
// CCI
ccivalue=cci[cciLength](src)
// Momentum (rate of change)
mymomentum=roc[momentumLength](src)
// Bollinger bands
basisBB=average[bblength](src)
bbStd=std[bblength](src)
bbupper=basisBB+bbMult*bbStd
bblower=basisBB-bbMult*bbStd
//---------------------------------------------//
// Dynamic MA and counter variables
//---------------------------------------------//
once counter=1
once prevState=0
dynLen=min(baseLen+(counter-1),maxDynLen)
ma=average[dynLen](src)
//---------------------------------------------//
// Get the current condition state
//---------------------------------------------//
once state=0
if resetConditiontype=1 then
if ma>ma[slopeOB] then
state=1
elsif ma<ma[slopeOB] then
state=-1
else
state=0
endif
elsif resetConditiontype=2 then
if rsiValue>rsiOB then
state=1
elsif rsiValue<rsiOS then
state=-1
else
state=0
endif
elsif resetConditiontype=3 then
if average[20](volume)>volSMA then
state=1
elsif average[20](volume)<volSMA then
state=-1
else
state=0
endif
elsif resetConditiontype=4 then
if close>bbupper then
state=1
elsif close<bblower then
state=-1
else
state=0
endif
elsif resetConditiontype=5 then
if mymacdline>mysignalline then
state=1
elsif mymacdline<mysignalline then
state=-1
else
state=0
endif
elsif resetConditiontype=6 then
if stochk>stochOB then
state=1
elsif stochk<stochOS then
state=-1
else
state=0
endif
elsif resetConditiontype=7 then
if ccivalue>cciOB then
state=1
elsif ccivalue<cciOS then
state=-1
else
state=0
endif
elsif resetConditiontype=8 then
if mymomentum>0 then
state=1
elsif mymomentum<0 then
state=-1
else
state=0
endif
endif
currentState = state
//---------------------------------------------//
// Update the counter with reverse counting option
//---------------------------------------------//
once counterIncreasing=1
if currentState<>0 then
if currentState<>prevState then
counter=1
counterIncreasing=1
else
if reverseCounter then
if counterIncreasing then
if counter<counterbreak then
counter=1+counter
else
counterIncreasing=0
counter=counter-1
endif
else
if counter>1 then
counter=counter-1
else
counterIncreasing=1
counter=1+counter
endif
endif
else
counter=1+counter
endif
endif
else
counter=1
counterIncreasing=1
endif
prevState=currentState
//---------------------------------------------//
// Recalculate th dynamic MA based on the updated counter
//---------------------------------------------//
dynLen=min(baseLen+(counter-1),maxDynLen)
ma=average[dynLen](src)
//---------------------------------------------//
// Trend Direction
//---------------------------------------------//
once trend=0
if close crosses over ma then
trend=1
elsif close crosses under ma then
trend =0
endif
trendChange=trend<>trend[1]
//---------------------------------------------//
// Adaptative Trend calculations
//---------------------------------------------//
atrThreshold=averagetruerange[200](close)
freq=2*3.1416/length
smoothfactor=trendSmoothing*freq
responseFactor=exp(-smoothfactor)
if barindex<counter+baseLen then
primaryFilter=0
secondaryFilter=0
else
primaryFilter=primaryfilter[1]+smoothFactor*(ma-primaryFilter[1])
secondaryFilter=secondaryfilter[1]*responseFactor+(1-responseFactor)*primaryfilter
endif
filteredTrend=(primaryFilter+secondaryFilter)/2
//---------------------------------------------//
// Track Trend stregth changes
//---------------------------------------------//
once trendUp=0
once trendDown=0
isUptrend=filteredTrend>filteredTrend[2]
isDownTrend=filteredTrend<filteredTrend[2]
//reset trend counters when direction changes
if isUptrend then
trendUp=trendUp+1
trendDown=0
elsif isDowntrend then
trendUp=0
trendDown=trendDown+1
endif
//---------------------------------------------//
// Colours and Signals
//---------------------------------------------//
ConfirmedUptrend=trendDown>=trending
ConfirmedDownTrend=trendUp>=trending
ConfirmedUptrendCol=trendUp>=trendingCol
ConfirmedDowntrendCol=trenddown>=trendingCol
PosTrendStart=ConfirmedUptrend and ConfirmedUptrend[1]=0
NegTrendStart=ConfirmedDownTrend and ConfirmedDownTrend[1]=0
circleUp=filteredTrend+atrThreshold
circleDn=filteredTrend-atrThreshold
if ConfirmedUptrendCol then
r=0
g=230
b=118
elsif ConfirmedDowntrendCol then
r=255
g=82
b=82
else
r=212
g=218
b=44
alphaDn=0
alphaUp=0
endif
if PosTrendStart then
drawtext("▼",barindex,circleUp)coloured("orange",255)
drawpoint(barindex,circleUp,5)coloured("orange",30)
alphaDn=0
alphaUp=125
elsif NegTrendStart then
drawtext("▲",barindex,circleDn)coloured("lime",255)
drawpoint(barindex,circleDn,5)coloured("lime",30)
alphaDn=125
alphaUp=0
endif
//---------------------------------------------//
return ma as "Dynamic MA" coloured(r,g,b)style(line,2), circleUp style(point,2)coloured("orange",alphaUp), circleDn style(point,2)coloured("Lime",alphaDn)
The AutoLength Moving Average is a powerful and flexible moving average designed for traders who require dynamic adaptation to market conditions. With its intelligent counter-based length adjustment and customizable reset conditions, it provides an edge over traditional moving averages by offering both smoothness and responsiveness.
This indicator is especially beneficial for trend traders, swing traders, and those who prefer adaptive technical analysis tools to improve their decision-making process.