Composite Trend Average - Advanced Trading Indicator

Composite Trend Average

The Ultimate Multi-Indicator Trading System

Six powerful indicators. One unified signal. Maximum confidence.

Why Composite Trend Average?

Trading decisions shouldn't rely on a single indicator. The Composite Trend Average combines six of the most sophisticated trend-following indicators into one powerful consensus signal. By averaging HalfTrend, T3, FRAMA, MAMA/FAMA, McGinley Dynamic, and KAMA, you get a robust trend line that filters out noise and provides high-confidence trading signals.

🎯 Key Features

  • 6 Advanced Indicators Combined
  • Consensus Zone Visualization
  • Smart Color-Coded Signals
  • Customizable Sensitivity
  • Built-in Alert System
  • Works on All Timeframes

💡 Benefits

  • Reduced False Signals
  • Clearer Trend Direction
  • Better Entry/Exit Timing
  • Adaptive to Market Conditions
  • Easy to Read & Understand
  • Professional Grade Analysis

⚙️ Technical Advantages

  • HLC3 Source for Accuracy
  • Adjustable Sensitivity Presets
  • Individual Indicator Control
  • Consensus Zone Fill
  • Sticky Color Logic
  • Multiple Alert Conditions

Live Chart Preview

See the Composite Trend Average in action on a live TradingView chart. The indicator overlays directly on your price chart, showing the composite average line and consensus zone.

How It Works

The Composite Trend Average combines six advanced technical indicators, each with unique strengths:

HalfTrend

Trend-following indicator that adapts to market volatility using ATR-based calculations.

T3 Moving Average

Triple-smoothed exponential moving average that reduces lag while maintaining responsiveness.

FRAMA

Fractal Adaptive Moving Average that adjusts its period based on market fractal dimension.

MAMA/FAMA

Mesa Adaptive Moving Average using Hilbert Transform for phase detection and adaptation.

McGinley Dynamic

Self-adjusting moving average that automatically adapts to price velocity and volatility.

KAMA

Kaufman Adaptive Moving Average that adjusts based on market efficiency ratio.

The Consensus Zone

The shaded area between the highest and lowest indicator values represents the consensus zone. When price is above this zone, all indicators agree on a bullish trend. When price is below, all indicators agree on a bearish trend. The color changes only when price definitively breaks above or below all indicators, providing clear, high-confidence signals.

PineScript Code

Copy the complete PineScript code below and paste it into TradingView's Pine Editor to use this indicator.

//@version=6
indicator("Composite Trend Average", shorttitle="Composite Trend Average", overlay=true)


// ========== INPUTS ==========
src = hlc3  // H+L+C/3 source for all indicators


// Sensitivity preset
sensitivity = input.string("Medium", "Sensitivity", options=["Low", "Medium", "High"], group="Global Settings")


// Calculate multiplier based on sensitivity
sensitivityMult = sensitivity == "Low" ? 2.333 : sensitivity == "High" ? 0.333 : 1.0  // Low=21/9, High=3/9, Medium=1.0


// HalfTrend inputs
htAmplitude = input.int(2, "HalfTrend Amplitude", minval=1, group="HalfTrend")


// T3 inputs
t3Length = input.int(6, "T3 Length", minval=1, group="T3")
t3Hot = input.float(0.4, "T3 Coefficient", group="T3")


// FRAMA inputs
framaLen = input.int(21, "FRAMA Period", minval=1, group="FRAMA")
framaFC = input.int(1, "FRAMA Fast MA", minval=1, group="FRAMA")
framaSC = input.int(200, "FRAMA Slow MA", minval=1, group="FRAMA")


// MAMA/FAMA inputs
mamaFastLimit = input.float(0.5, "MAMA Fast Limit", step=0.01, group="MAMA/FAMA")
mamaSlowLimit = input.float(0.05, "MAMA Slow Limit", step=0.01, group="MAMA/FAMA")


// McGinley Dynamic inputs
mdPeriod = input.float(9, "McGinley Period", minval=1, step=0.5, group="McGinley")
mdFormula = input.string("Modern", "McGinley Formula", options=["Modern", "Original", "Custom k"], group="McGinley")
mdKCustom = input.float(0.6, "McGinley Custom k", minval=0.3, step=0.05, group="McGinley")
mdExponent = input.float(4.0, "McGinley Exponent", minval=1.0, step=0.1, group="McGinley")


// KAMA inputs
kamaLength = input.int(9, "KAMA Length", minval=1, group="KAMA")
kamaFastMA = input.int(2, "KAMA Fast MA", minval=1, group="KAMA")
kamaSlowMA = input.int(30, "KAMA Slow MA", minval=1, group="KAMA")


// PSAR inputs
psarStart = input.float(0.02, "PSAR Start", step=0.001, group="PSAR")
psarIncrement = input.float(0.02, "PSAR Increment", step=0.001, group="PSAR")
psarMaximum = input.float(0.2, "PSAR Maximum", step=0.01, group="PSAR")


// Apply sensitivity multiplier to main period inputs
t3LengthAdj = math.round(t3Length * sensitivityMult)
framaLenAdj = math.round(framaLen * sensitivityMult)
mdPeriodAdj = mdPeriod * sensitivityMult
kamaLengthAdj = math.round(kamaLength * sensitivityMult)


// Display options
showIndividual = input.bool(false, "Show Individual Indicators", group="Display")
showAverage = input.bool(true, "Show Composite Average", group="Display")
showZone = input.bool(true, "Show Consensus Zone (High/Low Fill)", group="Display")


// ========== HALFTREND ==========
var int trend = 0
var int nextTrend = 0
var float maxLowPrice = na
var float minHighPrice = na
var float up = na
var float down = na
atr2 = ta.atr(14) / 2


highPrice = ta.highest(high, htAmplitude)
lowPrice = ta.lowest(low, htAmplitude)
highma = ta.sma(high, htAmplitude)
lowma = ta.sma(low, htAmplitude)


if nextTrend == 1
   maxLowPrice := na(maxLowPrice) ? lowPrice : math.max(lowPrice, maxLowPrice)
   if highma < maxLowPrice and src < nz(low[1], low)
       trend := 1
       nextTrend := 0
       minHighPrice := highPrice
       minHighPrice
else
   minHighPrice := na(minHighPrice) ? highPrice : math.min(highPrice, minHighPrice)
   if lowma > minHighPrice and src > nz(high[1], high)
       trend := 0
       nextTrend := 1
       maxLowPrice := lowPrice
       maxLowPrice


if trend == 0
   if not na(trend[1]) and trend[1] != 0
       up := na(down[1]) ? down : down[1]
   else
       up := na(up[1]) ? maxLowPrice : math.max(maxLowPrice, up[1])
       up
else
   if not na(trend[1]) and trend[1] != 1
       down := na(up[1]) ? up : up[1]
   else
       down := na(down[1]) ? minHighPrice : math.min(minHighPrice, down[1])
       down


halftrend = trend == 0 ? up : down


// ========== T3 ==========
t3_calc(source, p, hot) =>
   e1 = ta.ema(source, p)
   e2 = ta.ema(e1, p)
   e3 = ta.ema(e2, p)
   e4 = ta.ema(e3, p)
   e5 = ta.ema(e4, p)
   e6 = ta.ema(e5, p)
   b2 = hot * hot
   b3 = hot * hot * hot
   c1 = -b3
   c2 = 3 * b2 + 3 * b3
   c3 = -6 * b2 - 3 * hot - 3 * b3
   c4 = 1 + 3 * hot + b3 + 3 * b2
   ret = c1 * e6 + c2 * e5 + c3 * e4 + c4 * e3
   ret


t3 = t3_calc(src, t3LengthAdj, t3Hot)


// ========== FRAMA ==========
FRAMA(source, len, FC, SC) =>
   len1 = len / 2
   w = -4.6
   H1 = ta.highest(high, len1)
   L1 = ta.lowest(low, len1)
   N1 = (H1 - L1) / len1
   H2 = ta.highest(high, len1)[len1]
   L2 = ta.lowest(low, len1)[len1]
   N2 = (H2 - L2) / len1
   H3 = ta.highest(high, len)
   L3 = ta.lowest(low, len)
   N3 = (H3 - L3) / len
   dimen1 = (math.log(N1 + N2) - math.log(N3)) / math.log(2)
   dimen = 0.0
   dimen := N1 > 0 and N2 > 0 and N3 > 0 ? dimen1 : dimen
   alpha1 = math.exp(w * (dimen - 1))
   oldalpha = alpha1 > 1 ? 1 : alpha1 < 0.01 ? 0.01 : alpha1
   oldN = (2 - oldalpha) / oldalpha
   N = (SC - FC) * (oldN - 1) / (SC - 1) + FC
   alpha_ = 2 / (N + 1)
   alpha = alpha_ < 2 / (SC + 1) ? 2 / (SC + 1) : alpha_ > 1 ? 1 : alpha_
   out = 0.0
   out := (1 - alpha) * nz(out[1]) + alpha * source
   out


frama = FRAMA(src, framaLenAdj, framaFC, framaSC)


// ========== MAMA/FAMA ==========
var float PI = 2 * math.asin(1)


_hilbertTransform(source) =>
   out = 0.0962 * source + 0.5769 * nz(source[2]) - 0.5769 * nz(source[4]) - 0.0962 * nz(source[6])
   out


_computeComponent(source, mesaPeriodMult) =>
   out = _hilbertTransform(source) * mesaPeriodMult
   out


_smoothComponent(source) =>
   out = 0.2 * source + 0.8 * nz(source[1])
   out


_computeAlpha(source, fastLimit, slowLimit) =>
   mesaPeriod = 0.0
   mesaPeriodMult = 0.075 * nz(mesaPeriod[1]) + 0.54
   smooth = (4 * source + 3 * nz(source[1]) + 2 * nz(source[2]) + nz(source[3])) / 10
   detrender = _computeComponent(smooth, mesaPeriodMult)
   I1 = nz(detrender[3])
   Q1 = _computeComponent(detrender, mesaPeriodMult)
   jI = _computeComponent(I1, mesaPeriodMult)
   jQ = _computeComponent(Q1, mesaPeriodMult)
   I2 = I1 - jQ
   Q2 = Q1 + jI
   I2 := _smoothComponent(I2)
   Q2 := _smoothComponent(Q2)
   Re = I2 * nz(I2[1], I2) + Q2 * nz(Q2[1], Q2)
   Im = I2 * nz(Q2[1], Q2) - Q2 * nz(I2[1], I2)
   Re := _smoothComponent(Re)
   Im := _smoothComponent(Im)
   if Re != 0 and Im != 0
       mesaPeriod := 2 * PI / math.atan(Im / Re)
   mesaPeriod := math.min(mesaPeriod, 1.5 * nz(mesaPeriod[1], mesaPeriod))
   mesaPeriod := math.max(mesaPeriod, 0.67 * nz(mesaPeriod[1], mesaPeriod))
   mesaPeriod := math.min(math.max(mesaPeriod, 6), 50)
   mesaPeriod := _smoothComponent(mesaPeriod)
   phase = 0.0
   if I1 != 0
       phase := 180 / PI * math.atan(Q1 / I1)
   deltaPhase = nz(phase[1], phase) - phase
   deltaPhase := math.max(deltaPhase, 1)
   alpha = math.max(fastLimit / deltaPhase, slowLimit)
   out = alpha
   out


alpha = _computeAlpha(src, mamaFastLimit, mamaSlowLimit)
alpha2 = alpha / 2
mama = 0.0
mama := alpha * src + (1 - alpha) * nz(mama[1])
fama = 0.0
fama := alpha2 * mama + (1 - alpha2) * nz(fama[1])


// ========== MCGINLEY DYNAMIC ==========
imd(Series, fPeriod, fK, fExponent) =>
   period = math.max(1.0, fPeriod)
   float return_1 = na
   priorMD = nz(return_1[1], Series)
   return_1 := priorMD + (Series - priorMD) / math.min(period, math.max(1.0, fK * period * math.pow(Series / priorMD, fExponent)))
   return_1


var mdK = mdFormula == "Modern" ? 0.6 : mdFormula == "Original" ? 1.0 : mdKCustom
mcginley = imd(src, mdPeriodAdj, mdK, mdExponent)


// ========== KAMA ==========
volatility = math.sum(math.abs(src - src[1]), kamaLengthAdj)
change = math.abs(src - src[kamaLengthAdj - 1])
er = volatility != 0 ? change / volatility : 0
fastSC = 2 / (kamaFastMA + 1)
slowSC = 2 / (kamaSlowMA + 1)
sc = math.pow((er * (fastSC - slowSC)) + slowSC, 2)
var float kama = na
kama := nz(kama[1]) + (sc * (src - nz(kama[1])))


// ========== COMPOSITE AVERAGE ==========
// Average all 6 indicators
composite = (halftrend + t3 + frama + mama + mcginley + kama) / 6


// ========== CONSENSUS ZONE ==========
// Find highest and lowest values among all indicators
upperZone = math.max(halftrend, math.max(t3, math.max(frama, math.max(mama, math.max(mcginley, kama)))))
lowerZone = math.min(halftrend, math.min(t3, math.min(frama, math.min(mama, math.min(mcginley, kama)))))


// ========== PLOTS ==========
// Sticky color logic - only changes when close breaks above ALL or below ALL
var color allColor = color.red
if close > upperZone
   allColor := color.green
else if close < lowerZone
   allColor := color.red


// Consensus zone
upperPlot = plot(showZone ? upperZone : na, "Upper Zone", color=color.new(allColor, 40), linewidth=1)
lowerPlot = plot(showZone ? lowerZone : na, "Lower Zone", color=color.new(allColor, 40), linewidth=1)
fill(upperPlot, lowerPlot, color=color.new(allColor, 85), title="Consensus Zone")


// Individual indicators
plot(showIndividual ? halftrend : na, "HalfTrend", color=color.new(color.red, 30), linewidth=1)
plot(showIndividual ? t3 : na, "T3", color=color.new(color.orange, 30), linewidth=1)
plot(showIndividual ? frama : na, "FRAMA", color=color.new(color.yellow, 30), linewidth=1)
plot(showIndividual ? mama : na, "MAMA", color=color.new(color.green, 30), linewidth=1)
plot(showIndividual ? mcginley : na, "McGinley", color=color.new(color.blue, 30), linewidth=1)
plot(showIndividual ? kama : na, "KAMA", color=color.new(color.purple, 30), linewidth=1)


// Composite average - uses same color logic
plot(showAverage ? composite : na, "Composite Average", color=allColor, linewidth=3, style=plot.style_line)


// Price reference
plot(close, "Close", color=color.new(color.gray, 70), linewidth=1, display=display.none)


// ========== ALERTS ==========
bullishCross = ta.crossover(close, composite)
bearishCross = ta.crossunder(close, composite)
trendUp = composite > composite[1] and composite[1] > composite[2]
trendDown = composite < composite[1] and composite[1] < composite[2]


alertcondition(bullishCross, title="Price Crosses Above Composite", message="Price crossed above Composite Trend Average")
alertcondition(bearishCross, title="Price Crosses Below Composite", message="Price crossed below Composite Trend Average")
alertcondition(trendUp, title="Strong Uptrend", message="Composite showing strong uptrend")
alertcondition(trendDown, title="Strong Downtrend", message="Composite showing strong downtrend")

Ready to Elevate Your Trading?

Get started with the Composite Trend Average indicator today and experience the power of multi-indicator consensus trading.

Add to TradingView

© 2024 Composite Trend Average. Professional trading indicator for TradingView.

Disclaimer: This indicator is for educational purposes only. Always do your own research and risk management.