Summary: A technical guide for detecting future functions in MT4 indicators before converting them into EA strategies. Covers source code inspection methods, real-time observation techniques, and practical iCustom integration examples.




# Detecting Future Functions in Indicators: The First Step Before EA Integration

Why Future Functions Destroy Your EA



Before converting any indicator into an EA strategy, you must verify it contains no future function (also known as look-ahead bias). A future function means the indicator recalculates historical values based on current price data — effectively "cheating" by using tomorrow's news to trade yesterday.

In live trading, this results in catastrophic failure. An EA that looks perfect in backtesting will fail miserably forward because those perfect historical signals disappear in real-time.

Two Methods to Detect Future Functions



Method 1: White-Box (Source Code Inspection)



If you have access to the indicator's MQL4 source code, inspect the loop sections carefully. Look for any code that modifies historical time series arrays after they have been calculated.

Red flags include:
  • Functions that rewrite `close[]`, `high[]`, `low[]` arrays for past bars

  • Custom buffers that retroactively change values based on `shift < 0` indexing

  • Mathematical operations referencing future bars (negative shift values)


  • Method 2: Black-Box (Real-Time Observation)



    When source code isn't available, load the indicator on a 1-minute chart and observe it continuously.

    Watch for historical signal changes as new candles form. For example, a sell arrow that appeared two candles ago might suddenly change to a buy arrow after the current candle closes. This is definitive proof of a future function.

    The iCustom Function: Reading Indicator Values in Your EA



    Once you've verified the indicator is safe, use the `iCustom()` function to read its values in your EA:

    ```cpp
    double iCustom(
    string symbol, // symbol (NULL = current)
    int timeframe, // timeframe (0 = current chart)
    string name, // indicator file name
    ... , // indicator parameters
    int mode, // line index (0-7)
    int shift // shift (0 = current bar)
    );
    ```

    Practical Example: Arrow-Based Signal



    For arrow indicators, the value is `EMPTY_VALUE` (empty) when no arrow exists, and the price value when an arrow appears:

    ```cpp
    // Check for buy arrow on previous bar (safer than current bar)
    double buySignal = iCustom(NULL, 0, "MyArrowIndicator", 0, 1);
    double sellSignal = iCustom(NULL, 0, "MyArrowIndicator", 1, 1);

    if(buySignal != EMPTY_VALUE && buySignal > 0) {
    // Buy signal detected
    OrderSend(Symbol(), OP_BUY, lotSize, Ask, 3, 0, 0, "Buy Signal", magic, 0, clrGreen);
    }
    ```

    Handling Line-Based Indicators



    For line indicators (e.g., oscillators), each color/line is stored in a separate buffer:

    ```cpp
    // For a dual-color line indicator (e.g., red=overbought, green=oversold)
    double redLine = iCustom(NULL, 0, "DualColorIndicator", 0, 0);
    double greenLine = iCustom(NULL, 0, "DualColorIndicator", 1, 0);

    if(redLine > 70) { /* Overbought - consider sell */ }
    if(greenLine < 30) { /* Oversold - consider buy */ }
    ```

    Critical Backtesting Warning: The Shift 0 Trap



    A common mistake that ruins backtesting accuracy is using `shift=0` (current bar) in historical tests.

    The Problem: During backtesting, MT4 can see the `close` price of the current bar before the bar actually closes in real trading. This creates an unrealistic advantage — your EA knows the future.

    The Solution: Always use `shift=1` (previous completed bar) for entry conditions during backtesting:

    ```cpp
    // WRONG - Uses future data in backtest
    double signal = iCustom(NULL, 0, "Indicator", 0, 0);

    // CORRECT - Only uses confirmed closed bar data
    double signal = iCustom(NULL, 0, "Indicator", 0, 1);
    ```

    EA Logic Structure for Indicator-Based Strategies



    A robust EA follows this state-check flow:

    ```cpp
    void OnTick() {
    // Step 1: Check current positions
    int totalOrders = OrdersTotal();
    bool hasBuy = false, hasSell = false;

    for(int i = 0; i < totalOrders; i++) {
    if(OrderSelect(i, SELECT_BY_POS)) {
    if(OrderMagicNumber() == magic) {
    if(OrderType() == OP_BUY) hasBuy = true;
    if(OrderType() == OP_SELL) hasSell = true;
    }
    }
    }

    // Step 2: Get indicator signals (use shift=1 for reliability)
    double buySignal = iCustom(NULL, 0, "Indicator", 0, 1);
    double sellSignal = iCustom(NULL, 0, "Indicator", 1, 1);

    // Step 3: Position management
    if(hasBuy && !hasSell && sellSignal != EMPTY_VALUE) {
    // Close buy, open sell (reverse)
    OrderClose(...);
    OrderSend(Symbol(), OP_SELL, lotSize, Bid, ...);
    }
    else if(!hasBuy && !hasSell) {
    // No position - check both directions
    if(buySignal != EMPTY_VALUE) {
    OrderSend(Symbol(), OP_BUY, lotSize, Ask, ...);
    }
    else if(sellSignal != EMPTY_VALUE) {
    OrderSend(Symbol(), OP_SELL, lotSize, Bid, ...);
    }
    }
    }
    ```

    The Overfitting Trap: Why "Perfect" Backtests Fail



    A backtest showing 85% win rate and 4% drawdown turning $10,000 into $10,000,000 in one year is almost certainly overfit or using future functions.

    Prevention Measures:


    1. Use out-of-sample data - Reserve 30% of historical data for final validation only
    2. Limit optimization parameters - Test no more than 5 variables simultaneously
    3. Verify no `shift=0` - Ensure all indicator reads use completed bars
    4. Forward test on demo - Run 3 months live demo before any real money

    ---

    References:
    1. MQL4 Documentation - Variables (docs.mql4.com)
    2. FxGecko - MT4 Programming: How to Apply Indicators to EAs (2023)
    3. MetaTrader 4 Help - Expert Optimization Setup
    4. MQL4 Documentation - OrderSend Function
    5. Forex Factory - Backtesting Reliability Discussion (2007)
    6. MQL4 Documentation - Other Operations (Indexing)