Advertisement IC Markets

The Self-Adjusting Trendline: Kaufman’s Adaptive Moving Average (KAMA) + MT4/MT5 Code

Optimize MetaTrader 4, MetaTrader 5, cTrader, and TradingView for speed. Discuss Level II Market Depth (DOM), custom hotkeys, and volume indicators.
PTScalper
Site Admin
Posts: 3027
Joined: Mon Jul 20, 2026 1:28 pm

Re: The Self-Adjusting Trendline: Kaufman’s Adaptive Moving Average (KAMA) + MT4/MT5 Code

Post by PTScalper »

Engineering Mechanics

The Repainting Fix: When Strict Non-Repainting is checked, the script evaluates f_er(i_lookback)[1] alongside barmerge.lookahead_on. This forces the 1-minute chart to evaluate only the ER of the previous fully closed 15-minute candle. It introduces up to a 15-minute lag by design, but completely prevents a scenario where an intraday volume spike flashes a false "green light" that vanishes before the candle closes.

Visual Integration: The indicator plots in a lower pane to measure the raw ER value, but casts a faint green bgcolor on the main chart whenever the HTF threshold is cleared. This allows you to hide the oscillator pane entirely and just trade price action continuations when the background is green.

Gold vs. EURUSD: You can load this twice on the same chart layout. Set one to a 0.35 threshold for standard spot pairs, and crank the other up to 0.50+ when stepping into a high-volatility environment to aggressively filter out the two-sided sweeps.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Recommended broker for automated trading & scalping IC Markets
PTScalper
Site Admin
Posts: 3027
Joined: Mon Jul 20, 2026 1:28 pm

Re: The Self-Adjusting Trendline: Kaufman’s Adaptive Moving Average (KAMA) + MT4/MT5 Code

Post by PTScalper »

Here is the institutional-grade implementation. To make this production-ready for an algorithmic environment, the script is upgraded from a binary toggle into a Ternary State Machine (Chop, Transition, Trend) with vector directionality, signal smoothing to prevent micro-flicking, and tuple-optimized MTF fetching to reduce computational overhead.

Code: Select all

//@version=5
indicator("Institutional MTF ER Regime Filter", shorttitle="Inst. ER Regime", overlay=false)

// =========================================================================
// INPUTS & ARCHITECTURE
// =========================================================================
grp_er = "Efficiency Ratio Engine"
i_len      = input.int(14, "ER Lookback", minval=1, group=grp_er)
i_smooth   = input.int(3, "Signal Smoothing (EMA)", minval=1, group=grp_er, tooltip="Applies an EMA to the ER to prevent threshold flickering.")

grp_mtf = "Multi-Timeframe & Execution"
i_htf      = input.timeframe("15", "HTF Vector", group=grp_mtf)
i_strict   = input.bool(true, "Strict Non-Repainting", group=grp_mtf, tooltip="Locks evaluation to the last fully closed HTF bar.")

grp_regime = "Regime Thresholds"
i_th_chop  = input.float(0.25, "Chop Ceiling (Max)", step=0.05, group=grp_regime)
i_th_trend = input.float(0.40, "Trend Floor (Min)", step=0.05, group=grp_regime)

grp_ui = "UI & Automation"
i_show_hud = input.bool(true, "Show Dashboard HUD", group=grp_ui)

// =========================================================================
// CORE ENGINE: TUPLE-BASED CALCULATION
// =========================================================================
// Calculating ER, Smoothed ER, and Direction simultaneously
f_regime_engine(len, smooth) =>
    change = close - close[len]
    vol    = math.sum(math.abs(close - close[1]), len)
    
    // Raw Efficiency
    raw_er = vol == 0 ? 0 : math.abs(change) / vol
    
    // Smoothed Signal (Prevents micro-whipsaws around the threshold)
    sig_er = ta.ema(raw_er, smooth)
    
    // Vector (1 = Bullish flow, -1 = Bearish flow)
    dir    = change > 0 ? 1 : change < 0 ? -1 : 0
    
    [raw_er, sig_er, dir]

// Single request.security call returning a Tuple (Highly optimized for Pine VM)
[htf_raw, htf_sig, htf_dir] = request.security(
     syminfo.tickerid, 
     i_htf, 
     i_strict ? f_regime_engine(i_len, i_smooth)[1] : f_regime_engine(i_len, i_smooth), 
     lookahead = i_strict ? barmerge.lookahead_on : barmerge.lookahead_off
 )

// =========================================================================
// STATE MACHINE & ROUTING
// =========================================================================
// Define the 3 operational states
bool is_chop  = htf_sig < i_th_chop
bool is_trend = htf_sig >= i_th_trend
bool is_trans = not is_chop and not is_trend

// Color routing based on Vector + State
color c_bull_strong = color.new(#00E676, 10)
color c_bear_strong = color.new(#FF5252, 10)
color c_trans       = color.new(#FFB74D, 30) // Orange for transition/caution
color c_chop        = color.new(#787B86, 60)

color state_color = is_chop ? c_chop : is_trans ? c_trans : (htf_dir == 1 ? c_bull_strong : c_bear_strong)

// =========================================================================
// VISUALIZATION
// =========================================================================
// Histogram mapping the smoothed ER
plot(htf_sig, "Regime Signal", color=state_color, style=plot.style_columns, linewidth=2)
plot(htf_raw, "Raw ER (Ghost)", color=color.new(state_color, 80), style=plot.style_line) // Faint underlying raw data

// Threshold barriers
hline(i_th_trend, "Trend Floor", color=color.new(#00E676, 50), linestyle=hline.style_dashed)
hline(i_th_chop, "Chop Ceiling", color=color.new(#FF5252, 50), linestyle=hline.style_dotted)

// Main chart background integration
bgcolor(is_trend ? color.new(state_color, 90) : na, title="Trend Lock Highlight")

// =========================================================================
// HEADS UP DISPLAY (HUD)
// =========================================================================
var table hud = table.new(position.top_right, 2, 2, bgcolor=color.new(#131722, 20), border_width=1, border_color=color.new(#363A45, 50))

if i_show_hud and barstate.islast
    string regime_str = is_chop ? "STAND ASIDE (CHOP)" : is_trans ? "CAUTION (BUILDING)" : "ACTIVE (EFFICIENT)"
    string dir_str    = htf_dir == 1 ? "BULLISH" : htf_dir == -1 ? "BEARISH" : "FLAT"
    
    table.cell(hud, 0, 0, "HTF REGIME", text_color=color.gray, text_size=size.small, text_halign=text.align_left)
    table.cell(hud, 1, 0, regime_str, text_color=state_color, text_size=size.small, text_halign=text.align_right)
    
    table.cell(hud, 0, 1, "ORDER FLOW", text_color=color.gray, text_size=size.small, text_halign=text.align_left)
    table.cell(hud, 1, 1, is_chop ? "N/A" : dir_str, text_color=is_chop ? color.gray : state_color, text_size=size.small, text_halign=text.align_right)

// =========================================================================
// ALERTS (Webhook / Automated Execution Ready)
// =========================================================================
alertcondition(is_trend and not is_trend[1], title="Regime: Trend Started", message='{"Regime": "Trend", "Action": "Unlock Pullbacks"}')
alertcondition(is_chop and not is_chop[1], title="Regime: Chop Started", message='{"Regime": "Chop", "Action": "Lockdown"}')
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 3027
Joined: Mon Jul 20, 2026 1:28 pm

Re: The Self-Adjusting Trendline: Kaufman’s Adaptive Moving Average (KAMA) + MT4/MT5 Code

Post by PTScalper »

Pro-Level Engineering Upgrades

1. Tuple-Based Security Fetching (Performance Optimization)

Instead of calling request.security multiple times for the raw ER, smoothed ER, and direction (which bogs down the Pine Virtual Machine), the f_regime_engine method packs all three calculations into an array [raw_er, sig_er, dir]. A single MTF call fetches the entire tuple, drastically reducing script execution time on an M1 chart.

2. Ternary State Machine with Dead-Zones

Binary toggles (above/below 0.35) cause strategy whiplash. This script splits the regime into three distinct phases:

Chop Ceiling (< 0.25): Hard lockdown. Mean reversion only.

Transition Dead-Zone (0.25 - 0.40): Caution. The market is waking up, but the noise-to-signal ratio is too dangerous for heavy position sizing.

Trend Floor (> 0.40): Full authorization for directional pullback continuations.

3. Vector Directionality

Efficiency without direction is dangerous—you might buy a pullback when the HTF is actually in a highly efficient, aggressive bear sequence. By tracking the htf_dir vector, the script colors the efficient states Green (Bullish) or Red (Bearish), ensuring you only take scalps aligned with the HTF order flow.

4. Signal Smoothing (The EMA Filter)

Raw ER is inherently jagged. Applying a fast EMA (e.g., length of 3) to the ER calculation creates the htf_sig. This signal line absorbs micro-fluctuations, preventing the indicator from dropping out of an "Efficient" regime just because a single HTF candle printed a doji.

5. Webhook-Ready Alert Conditions

The alertcondition blocks at the bottom are configured to send JSON payloads. If you port this logic to cAlgo or a trade manager, you can capture these webhook transitions to automatically enable/disable your lower timeframe execution scripts based on the MTF state.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 3027
Joined: Mon Jul 20, 2026 1:28 pm

Re: The Self-Adjusting Trendline: Kaufman’s Adaptive Moving Average (KAMA) + MT4/MT5 Code

Post by PTScalper »

Here are the implementations for both MQL5 and MQL4.

Translating the Pine Script architecture into MQL requires a specific approach to handle Multi-Timeframe (MTF) data synchronization. Instead of trying to maintain and sync multiple HTF arrays (which causes 90% of repainting bugs in retail MQL indicators), these implementations use On-Demand Historical Querying. We calculate the ER natively inside the OnCalculate loop by fetching the exact HTF slice required for that specific bar using CopyClose (MQL5) or iClose (MQL4).

1. MQL5 Implementation (Modern, Array-Optimized)

MQL5 allows for dynamic color histograms using DRAW_COLOR_HISTOGRAM.

Code: Select all

//+------------------------------------------------------------------+
//|                                       Inst_MTF_ER_Regime.mq5     |
//|                                     Strict Non-Repainting Filter |
//+------------------------------------------------------------------+
#property indicator_separate_window
#property indicator_buffers 2
#property indicator_plots   1

// Histogram Plot
#property indicator_label1  "ER Regime"
#property indicator_type1   DRAW_COLOR_HISTOGRAM
#property indicator_color1  clrMediumSeaGreen, clrCrimson, clrGoldenrod, clrDimGray
#property indicator_style1  STYLE_SOLID
#property indicator_width1  2

//--- Inputs
input ENUM_TIMEFRAMES InpHTF         = PERIOD_M15; // HTF Vector
input int             InpLookback    = 14;         // ER Lookback
input double          InpTrendThresh = 0.40;       // Trend Floor (Min)
input double          InpChopThresh  = 0.25;       // Chop Ceiling (Max)
input bool            InpStrict      = true;       // Strict Non-Repainting (Closed Bar Only)

//--- Buffers
double ExtERBuffer[];
double ExtColorBuffer[];

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
{
    SetIndexBuffer(0, ExtERBuffer, INDICATOR_DATA);
    SetIndexBuffer(1, ExtColorBuffer, INDICATOR_COLOR_INDEX);
    
    IndicatorSetDouble(INDICATOR_MINIMUM, 0.0);
    IndicatorSetDouble(INDICATOR_MAXIMUM, 1.0);
    
    // Set Threshold Levels
    IndicatorSetInteger(INDICATOR_LEVELS, 2);
    IndicatorSetDouble(INDICATOR_LEVELVALUE, 0, InpTrendThresh);
    IndicatorSetDouble(INDICATOR_LEVELVALUE, 1, InpChopThresh);
    
    return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
{
    int limit = prev_calculated == 0 ? 0 : prev_calculated - 1;

    for(int i = limit; i < rates_total; i++)
    {
        // 1. Find the corresponding HTF bar index for the current LTF time
        int htf_shift = iBarShift(_Symbol, InpHTF, time[i], false);
        if(htf_shift < 0) continue;
        
        // 2. Apply Strict Non-Repainting (Shift by 1 to use closed HTF bar)
        int calc_shift = InpStrict ? htf_shift + 1 : htf_shift;
        
        // 3. Fetch HTF Closes
        double htf_closes[];
        ArraySetAsSeries(htf_closes, true);
        if(CopyClose(_Symbol, InpHTF, calc_shift, InpLookback + 1, htf_closes) <= 0) continue;
        
        // 4. Calculate ER Core Engine
        double net_change = htf_closes[0] - htf_closes[InpLookback];
        double abs_change = MathAbs(net_change);
        double volatility = 0.0;
        
        for(int j = 0; j < InpLookback; j++) {
            volatility += MathAbs(htf_closes[j] - htf_closes[j+1]);
        }
        
        double raw_er = (volatility == 0) ? 0.0 : abs_change / volatility;
        int direction = (net_change > 0) ? 1 : (net_change < 0) ? -1 : 0;
        
        // 5. Assign to Buffers
        ExtERBuffer[i] = raw_er;
        
        // 6. State Machine & Color Routing
        if(raw_er < InpChopThresh) {
            ExtColorBuffer[i] = 3; // Chop (Gray)
        } 
        else if(raw_er >= InpTrendThresh) {
            ExtColorBuffer[i] = (direction == 1) ? 0 : 1; // Trend (Green/Red)
        } 
        else {
            ExtColorBuffer[i] = 2; // Transition (Orange)
        }
    }
    
    return(rates_total);
}
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 3027
Joined: Mon Jul 20, 2026 1:28 pm

Re: The Self-Adjusting Trendline: Kaufman’s Adaptive Moving Average (KAMA) + MT4/MT5 Code

Post by PTScalper »

2. MQL4 Implementation (Legacy System)

MQL4 handles buffers differently. Since it lacks a native DRAW_COLOR_HISTOGRAM (which maps one data array to multiple colors via an index), we must define four separate histogram buffers, overlapping them visually.

Code: Select all

//+------------------------------------------------------------------+
//|                                       Inst_MTF_ER_Regime.mq4     |
//|                                     Strict Non-Repainting Filter |
//+------------------------------------------------------------------+
#property indicator_separate_window
#property indicator_buffers 4
#property indicator_color1  clrMediumSeaGreen // Bull Trend
#property indicator_color2  clrCrimson        // Bear Trend
#property indicator_color3  clrGoldenrod      // Transition
#property indicator_color4  clrDimGray        // Chop
#property indicator_minimum 0.0
#property indicator_maximum 1.0
#property indicator_level1  0.40
#property indicator_level2  0.25

//--- Inputs
extern int    InpHTF         = 15;   // HTF Vector (in minutes, e.g., 15 for M15)
extern int    InpLookback    = 14;   // ER Lookback
extern double InpTrendThresh = 0.40; // Trend Floor
extern double InpChopThresh  = 0.25; // Chop Ceiling
extern bool   InpStrict      = true; // Strict Non-Repainting

//--- Buffers
double BufBull[];
double BufBear[];
double BufTrans[];
double BufChop[];

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
{
    SetIndexStyle(0, DRAW_HISTOGRAM, STYLE_SOLID, 2); SetIndexBuffer(0, BufBull);
    SetIndexStyle(1, DRAW_HISTOGRAM, STYLE_SOLID, 2); SetIndexBuffer(1, BufBear);
    SetIndexStyle(2, DRAW_HISTOGRAM, STYLE_SOLID, 2); SetIndexBuffer(2, BufTrans);
    SetIndexStyle(3, DRAW_HISTOGRAM, STYLE_SOLID, 2); SetIndexBuffer(3, BufChop);
    
    IndicatorShortName("MTF ER Regime");
    return(0);
}

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
{
    int limit = Bars - IndicatorCounted() - 1;
    if(limit < 0) limit = 0;

    for(int i = limit; i >= 0; i--)
    {
        // 1. Time Synchronization
        int htf_shift = iBarShift(NULL, InpHTF, Time[i], false);
        if(htf_shift < 0) continue;
        
        // 2. Strict Non-Repainting
        int calc_shift = InpStrict ? htf_shift + 1 : htf_shift;
        
        // 3. Calculate Volatility & Change via native iClose
        double current_close = iClose(NULL, InpHTF, calc_shift);
        double old_close     = iClose(NULL, InpHTF, calc_shift + InpLookback);
        
        double net_change = current_close - old_close;
        double abs_change = MathAbs(net_change);
        double volatility = 0.0;
        
        for(int j = 0; j < InpLookback; j++) {
            volatility += MathAbs(iClose(NULL, InpHTF, calc_shift + j) - iClose(NULL, InpHTF, calc_shift + j + 1));
        }
        
        // 4. Calculate ER
        double raw_er = (volatility == 0) ? 0.0 : abs_change / volatility;
        int direction = (net_change > 0) ? 1 : (net_change < 0) ? -1 : 0;
        
        // 5. Reset all buffers for this bar
        BufBull[i] = EMPTY_VALUE;
        BufBear[i] = EMPTY_VALUE;
        BufTrans[i] = EMPTY_VALUE;
        BufChop[i] = EMPTY_VALUE;
        
        // 6. Color Routing via Buffer Selection
        if(raw_er < InpChopThresh) {
            BufChop[i] = raw_er;
        } 
        else if(raw_er >= InpTrendThresh) {
            if(direction == 1) BufBull[i] = raw_er;
            else               BufBear[i] = raw_er;
        } 
        else {
            BufTrans[i] = raw_er;
        }
    }
    
    return(0);
}
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 3027
Joined: Mon Jul 20, 2026 1:28 pm

Re: The Self-Adjusting Trendline: Kaufman’s Adaptive Moving Average (KAMA) + MT4/MT5 Code

Post by PTScalper »

Architectural Notes

The Repainting Fix (InpStrict): The engine uses iBarShift to match the exact minute of the lower timeframe bar to its parent HTF bar. By adding + 1 to htf_shift, the indicator mathematically forces the MT4/MT5 terminal to look at the last completely closed M15 candle. This guarantees that what you see historically is exactly what the engine saw in real-time execution.

On-Demand Arrays: Instead of trying to calculate an EMA over the ER recursively (which is notoriously difficult to synchronize across timeframes in MQL), this version calculates the raw ER structurally on the fly using CopyClose or iClose loops. Because lookbacks are short (e.g., 14), this loop runs instantaneously even on every M1 tick.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 3027
Joined: Mon Jul 20, 2026 1:28 pm

Re: The Self-Adjusting Trendline: Kaufman’s Adaptive Moving Average (KAMA) + MT4/MT5 Code

Post by PTScalper »

When migrating from an indicator to an Expert Advisor (EA), you should abandon iCustom() calls entirely. Calling an external indicator file on every tick introduces I/O overhead and complicates VPS deployment.

Because EAs only care about the live edge of the market (not historical plotting), the logic becomes drastically simpler. You no longer need to map lower timeframe bars to higher timeframe bars historically. If you are using the "Strict Non-Repainting" method, you only need to look at index 1 (the last closed bar) of the HTF.

Furthermore, an ER based on a closed M15 bar only changes once every 15 minutes. Calculating it on every M1 tick is a waste of CPU.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 3027
Joined: Mon Jul 20, 2026 1:28 pm

Re: The Self-Adjusting Trendline: Kaufman’s Adaptive Moving Average (KAMA) + MT4/MT5 Code

Post by PTScalper »

Here is the institutional-grade MQL5 execution architecture that caches the HTF state and natively computes the ER without external files:

The Native EA Implementation (MQL5)

Code: Select all

//+------------------------------------------------------------------+
//| 1. Define Regime States                                          |
//+------------------------------------------------------------------+
enum ENUM_REGIME_STATE 
{
    REGIME_CHOP       = 0,
    REGIME_TRANSITION = 1,
    REGIME_BULL_TREND = 2,
    REGIME_BEAR_TREND = 3,
    REGIME_ERROR      = -1
};

//+------------------------------------------------------------------+
//| 2. Native ER Calculation Function                                |
//+------------------------------------------------------------------+
ENUM_REGIME_STATE GetNativeMTFRegime(string symbol, ENUM_TIMEFRAMES htf, int lookback, double chop_th, double trend_th, bool strict_closed)
{
    // If strict_closed is true, we start at index 1 (ignoring the active repainting bar)
    int start_idx = strict_closed ? 1 : 0;
    
    double closes[];
    ArraySetAsSeries(closes, true);
    
    // Fetch lookback + 1 to get the start and end prices for the net change
    if(CopyClose(symbol, htf, start_idx, lookback + 1, closes) <= 0) 
    {
        Print("Failed to fetch HTF data. Error: ", GetLastError());
        return REGIME_ERROR; // Fail-safe state
    }
    
    double net_change = closes[0] - closes[lookback];
    double abs_change = MathAbs(net_change);
    double volatility = 0.0;
    
    // Accumulate the bar-to-bar volatility
    for(int i = 0; i < lookback; i++) 
    {
        volatility += MathAbs(closes[i] - closes[i+1]);
    }
    
    // Guard against division by zero in flat markets
    double er = (volatility == 0.0) ? 0.0 : (abs_change / volatility);
    
    // State Routing
    if(er < chop_th) return REGIME_CHOP;
    if(er >= trend_th) return (net_change > 0) ? REGIME_BULL_TREND : REGIME_BEAR_TREND;
    
    return REGIME_TRANSITION;
}

//+------------------------------------------------------------------+
//| 3. The OnTick() Execution Loop with State Caching                |
//+------------------------------------------------------------------+
// Global or static variables to cache the regime state
datetime          Global_LastHTFTime = 0;
ENUM_REGIME_STATE Global_CurrentRegime = REGIME_CHOP;

void OnTick()
{
    // 1. Check if a new HTF bar has opened
    datetime current_htf_time = iTime(_Symbol, PERIOD_M15, 0);
    
    // 2. Only recalculate the ER once every 15 minutes
    if(current_htf_time != Global_LastHTFTime)
    {
        Global_CurrentRegime = GetNativeMTFRegime(_Symbol, PERIOD_M15, 14, 0.25, 0.40, true);
        
        // Update the cache time if successful
        if(Global_CurrentRegime != REGIME_ERROR) 
        {
            Global_LastHTFTime = current_htf_time;
        }
    }

    // 3. Playbook Execution Logic
    if(Global_CurrentRegime == REGIME_CHOP || Global_CurrentRegime == REGIME_ERROR) 
    {
        // Lockdown: Do not evaluate pullback continuations
        // Optional: Manage trailing stops or execute mean-reversion only
        return; 
    }

    if(Global_CurrentRegime == REGIME_BULL_TREND) 
    {
        // 4a. Run your M1 price action / long pullback entry logic here
        // if(IsBullishPullbackOver()) OrderSend(...);
    }
    else if(Global_CurrentRegime == REGIME_BEAR_TREND) 
    {
        // 4b. Run your M1 price action / short pullback entry logic here
        // if(IsBearishPullbackOver()) OrderSend(...);
    }
    else if(Global_CurrentRegime == REGIME_TRANSITION) 
    {
        // Caution zone: You might allow trades but cut position sizing in half
    }
}
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 3027
Joined: Mon Jul 20, 2026 1:28 pm

Re: The Self-Adjusting Trendline: Kaufman’s Adaptive Moving Average (KAMA) + MT4/MT5 Code

Post by PTScalper »

MQL4 Adaptation Notes

If you port this to an MQL4 .mq4 EA, the structural logic remains identical. The only change required is swapping the CopyClose array implementation in step 2 for a direct iClose() loop, which is natively supported in MQL4:

Code: Select all

// MQL4 adaptation for the data fetch
double current_close = iClose(symbol, htf, start_idx);
double old_close     = iClose(symbol, htf, start_idx + lookback);

double net_change = current_close - old_close;
double abs_change = MathAbs(net_change);
double volatility = 0.0;

for(int i = 0; i < lookback; i++) 
{
    volatility += MathAbs(iClose(symbol, htf, start_idx + i) - iClose(symbol, htf, start_idx + i + 1));
}
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 3027
Joined: Mon Jul 20, 2026 1:28 pm

Re: The Self-Adjusting Trendline: Kaufman’s Adaptive Moving Average (KAMA) + MT4/MT5 Code

Post by PTScalper »

Architectural Advantages for Automated Trading

Zero-Lag State Caching: By checking iTime(_Symbol, PERIOD_M15, 0), the EA only spends CPU cycles calculating the array math on the exact tick a new 15-minute candle opens. For the next ~14.9 minutes (thousands of ticks), it skips the math and instantly routes your logic via the cached Global_CurrentRegime.

Crash Resilience: The REGIME_ERROR state ensures that if your terminal temporarily loses connection to the broker's history server and CopyClose fails, the EA halts execution instead of accidentally reading a malformed array and firing a bad trade.

Directional Safety: Isolating REGIME_BULL_TREND and REGIME_BEAR_TREND forces the EA to obey the higher timeframe order flow. If your M1 logic spots a bullish pullback, but the M15 ER indicates a highly efficient bear trend, the EA drops the trade entirely.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Post Reply