Page 2 of 2

Re: Advanced Algorithmic Filtering: The Fractal Adaptive Moving Average (FRAMA) + MQL Code

Posted: Sat Sep 12, 2026 4:17 pm
by PTScalper
The Pine Script Implementation

This script builds an ATR channel around KAMA and paints arrows when a candle successfully closes outside the volatility bands.

Code: Select all

 //@version=5
indicator("KAMA + ATR Breakout Channel", overlay=true)

// --- KAMA Inputs ---
kLength = input.int(14, "KAMA Lookback", group="KAMA Settings")
kFast   = input.int(2,  "KAMA Fast EMA", group="KAMA Settings")
kSlow   = input.int(30, "KAMA Slow EMA", group="KAMA Settings")

// --- Channel Inputs ---
atrLen  = input.int(14,  "ATR Length", group="Channel Settings")
atrMult = input.float(2.0, "ATR Multiplier", step=0.1, group="Channel Settings")

// ==========================================
// KAMA CALCULATION
// ==========================================
direction  = math.abs(close - close[kLength])
volatility = math.sum(math.abs(close - close[1]), kLength)
er         = volatility != 0 ? direction / volatility : 0

fastAlpha = 2 / (kFast + 1)
slowAlpha = 2 / (kSlow + 1)
sc        = math.pow((er * (fastAlpha - slowAlpha)) + slowAlpha, 2)

var float kama = na
kama := na(kama[1]) ? close : kama[1] + sc * (close - kama[1])

// ==========================================
// ATR BANDS CALCULATION
// ==========================================
// Using built-in ATR for pure volatility distance
currentAtr = ta.atr(atrLen)

upperBand = kama + (currentAtr * atrMult)
lowerBand = kama - (currentAtr * atrMult)

// ==========================================
// PLOTTING & SIGNALS
// ==========================================
// Draw KAMA and Channels
plot(kama, color=color.rgb(41, 98, 255), linewidth=2, title="KAMA Base")
uPlot = plot(upperBand, color=color.new(color.gray, 50), title="Upper ATR Band")
lPlot = plot(lowerBand, color=color.new(color.gray, 50), title="Lower ATR Band")
fill(uPlot, lPlot, color=color.new(color.rgb(41, 98, 255), 92), title="Channel Fill")

// Breakout Logic (Close outside the bands)
longBreakout  = ta.crossover(close, upperBand)
shortBreakout = ta.crossunder(close, lowerBand)

// Paint signals on the chart
plotshape(longBreakout,  title="Long Breakout",  style=shape.triangleup,   location=location.belowbar, color=color.rgb(0, 230, 119), size=size.small)
plotshape(shortBreakout, title="Short Breakout", style=shape.triangledown, location=location.abovebar, color=color.rgb(255, 82, 82), size=size.small)

Re: Advanced Algorithmic Filtering: The Fractal Adaptive Moving Average (FRAMA) + MQL Code

Posted: Sat Sep 12, 2026 4:18 pm
by PTScalper
Tuning tip for live trading: A 2.0 ATR multiplier is the standard starting point. If you trade pairs prone to heavy wicks (like GBP/JPY or XAU/USD), bump the multiplier to 2.5 or 3.0 to prevent the algorithm from interpreting a liquidity sweep as a true breakout.

Re: Advanced Algorithmic Filtering: The Fractal Adaptive Moving Average (FRAMA) + MQL Code

Posted: Sat Sep 12, 2026 4:20 pm
by PTScalper
By anchoring the trailing stop to KAMA instead of price, your stop-loss follows the structural trend rather than the extreme noise. Since KAMA flatlines during chop, your trailing stop will also flatline, giving the market room to breathe during mid-trend consolidations without stopping you out.

The Ratchet Mechanic
A trailing stop must have a "ratchet" mechanism: it can only move in the direction of profit.
For Longs: The stop is ⁠KAMA - (ATR * Trailing_Multiplier)⁠. If KAMA rises, the stop rises. If KAMA drops, the stop holds its previous highest value.
For Shorts: The stop is ⁠KAMA + (ATR * Trailing_Multiplier)⁠. It only ratchets down.

Re: Advanced Algorithmic Filtering: The Fractal Adaptive Moving Average (FRAMA) + MQL Code

Posted: Sat Sep 12, 2026 4:21 pm
by PTScalper
The Pine Script Implementation

This script merges the breakout filter from earlier with a state machine that tracks active trades. Once a breakout triggers, a trailing stop line appears on the chart and ratchets behind the price until it is hit.

Code: Select all

 //@version=5
indicator("KAMA + ATR Breakout & Trailing Stop", overlay=true)

// --- KAMA Inputs ---
kLength = input.int(14, "KAMA Lookback", group="KAMA Settings")
kFast   = input.int(2,  "KAMA Fast EMA", group="KAMA Settings")
kSlow   = input.int(30, "KAMA Slow EMA", group="KAMA Settings")

// --- Breakout Channel Inputs ---
atrLen  = input.int(14,  "ATR Length", group="Channel Settings")
atrMult = input.float(2.0, "Entry Channel Multiplier", step=0.1, group="Channel Settings")

// --- Trailing Stop Inputs ---
trailMult = input.float(1.5, "Trailing Stop Multiplier", step=0.1, group="Trailing Stop Settings", tooltip="Usually tighter than the entry multiplier to protect profits.")

// ==========================================
// 1. KAMA & ATR CALCULATION
// ==========================================
direction  = math.abs(close - close[kLength])
volatility = math.sum(math.abs(close - close[1]), kLength)
er         = volatility != 0 ? direction / volatility : 0

sc = math.pow((er * (2/(kFast+1) - 2/(kSlow+1))) + 2/(kSlow+1), 2)

var float kama = na
kama := na(kama[1]) ? close : kama[1] + sc * (close - kama[1])

currentAtr = ta.atr(atrLen)
upperBand  = kama + (currentAtr * atrMult)
lowerBand  = kama - (currentAtr * atrMult)

// ==========================================
// 2. STATE MACHINE & TRAILING STOP LOGIC
// ==========================================
var int   position  = 0   // 1 = Long, -1 = Short, 0 = Flat
var float trailStop = na  // Holds the current stop level

longBreakout  = ta.crossover(close, upperBand)
shortBreakout = ta.crossunder(close, lowerBand)

// Entry Logic
if position == 0
    if longBreakout
        position  := 1
        trailStop := kama - (currentAtr * trailMult)
    else if shortBreakout
        position  := -1
        trailStop := kama + (currentAtr * trailMult)

// Trailing Logic (Ratchet) & Exit Logic
if position == 1
    // Calculate new stop and ratchet UP only
    newStop   = kama - (currentAtr * trailMult)
    trailStop := math.max(trailStop, newStop)
    
    // Exit if price crosses below the ratcheted stop
    if close < trailStop
        position  := 0
        trailStop := na

if position == -1
    // Calculate new stop and ratchet DOWN only
    newStop   = kama + (currentAtr * trailMult)
    trailStop := math.min(trailStop, newStop)
    
    // Exit if price crosses above the ratcheted stop
    if close > trailStop
        position  := 0
        trailStop := na

// ==========================================
// 3. PLOTTING
// ==========================================
// Base KAMA and Channel
plot(kama, color=color.rgb(41, 98, 255), title="KAMA Base")
uPlot = plot(upperBand, color=color.new(color.gray, 70), title="Upper ATR Band")
lPlot = plot(lowerBand, color=color.new(color.gray, 70), title="Lower ATR Band")
fill(uPlot, lPlot, color=color.new(color.rgb(41, 98, 255), 95), title="Channel Fill")

// Entry Signals
plotshape(position == 1 and position[1] == 0,  title="Long Entry",  style=shape.triangleup,   location=location.belowbar, color=color.rgb(0, 230, 119), size=size.small)
plotshape(position == -1 and position[1] == 0, title="Short Entry", style=shape.triangledown, location=location.abovebar, color=color.rgb(255, 82, 82), size=size.small)

// Exit Signals
plotshape(position == 0 and position[1] == 1,  title="Long Exit",  style=shape.xcross, location=location.abovebar, color=color.rgb(255, 204, 0), size=size.small)
plotshape(position == 0 and position[1] == -1, title="Short Exit", style=shape.xcross, location=location.belowbar, color=color.rgb(255, 204, 0), size=size.small)

// Trailing Stop Line (Only plots when in a trade)
plot(position != 0 ? trailStop : na, color=position == 1 ? color.rgb(0, 230, 119) : color.rgb(255, 82, 82), style=plot.style_circles, linewidth=2, title="Trailing Stop")

Re: Advanced Algorithmic Filtering: The Fractal Adaptive Moving Average (FRAMA) + MQL Code

Posted: Sat Sep 12, 2026 4:23 pm
by PTScalper
Tuning the Multipliers:

Notice there are now two separate multipliers. You generally want the Entry Multiplier to be wider (e.g., 2.0 or 2.5) to ensure you are only buying true structural breakouts. Once you are in the trade, you use the Trailing Stop Multiplier (e.g., 1.5) to tuck your stop slightly closer to KAMA, allowing you to lock in profits faster when the trend inevitably exhausts.

Re: Advanced Algorithmic Filtering: The Fractal Adaptive Moving Average (FRAMA) + MQL Code

Posted: Sat Sep 12, 2026 8:12 pm
by LondonScalper
PTScalper wrote:During a sustained London trend or tight Asia chop, they vote the exact same way. But... sudden, violent liquidity grabs—and that is exactly where FRAMA breaks down and KAMA shines.
That’s the distinction I wanted. Same vote in grind; different vote when the book gets yanked.

If both agree on a clean London trend or a dead Asia box, I don’t care which acronym printed the line. The failure mode that matters is the grab: FRAMA adapting into the spike and then lagging the reclaim. KAMA staying stubborn is less pretty and more usable for “was that a sweep or did the filter just eat the wick.”

Practical: I still won’t let either MA pull the trigger. They are a regime hint. Entry stays price + invalidation. If your FRAMA code flips mid-grab and you size it like an A+ trend ticket, the math didn’t fail — the job description did.