Page 1 of 1

Custom Fibonacci retracement indicator for Forex

Posted: Thu Aug 06, 2026 10:16 pm
by FTtrader
Hi scalpers,

i prepared for you another custom indicator, which is based on Fibonacci retracement.

Here is a complete, custom MQL4 indicator that automatically calculates and draws Fibonacci retracement and extension levels based on dynamic market highs and lows.

Because MQL4 shares structural similarities with C#, you will notice the event-driven architecture immediately. The OnCalculate function acts like a standard event handler that fires on every tick, continuously evaluating the arrays to keep the retracement perfectly anchored to the most recent price action.

I have embedded your name and domain directly into the metadata so the file is ready for your own production environment.

Code: Select all

//+------------------------------------------------------------------+
//|                                                  AutoFibo.mq4    |
//|                                  Copyright 2026, Pavel Tuček     |
//|                                     https://aiprofisolutions.com |
//+------------------------------------------------------------------+
#property copyright "Pavel Tuček"
#property link      "https://aiprofisolutions.com"
#property version   "1.00"
#property strict
#property indicator_chart_window

//--- Input parameters
input int    LookbackPeriod = 100;         // Lookback Period (Bars)
input color  FiboColor      = clrGoldenrod;// Fibonacci Lines Color
input bool   ShowExtensions = true;        // Show 161.8% and 261.8%
input ENUM_LINE_STYLE FiboStyle = STYLE_SOLID; // Line Style

//--- Global variables
string fiboName = "AutoFibo_Custom";

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
   // Validate the lookback period
   if(LookbackPeriod <= 0)
     {
      Print("LookbackPeriod must be greater than 0");
      return(INIT_PARAMETERS_INCORRECT);
     }
   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   // Clean up the graphical object when the indicator is removed 
   ObjectDelete(0, fiboName);
  }

//+------------------------------------------------------------------+
//| 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[])
  {
   // Wait until the chart has enough historical bars
   if(rates_total < LookbackPeriod) return(0);

   // Ensure time series indexing (Index 0 is the current active bar)
   ArraySetAsSeries(high, true);
   ArraySetAsSeries(low, true);
   ArraySetAsSeries(time, true);

   // Find the highest and lowest points within the defined lookback window
   int highestIdx = ArrayMaximum(high, LookbackPeriod, 0);
   int lowestIdx  = ArrayMinimum(low, LookbackPeriod, 0);

   double highestPrice = high[highestIdx];
   double lowestPrice  = low[lowestIdx];

   datetime timeHigh = time[highestIdx];
   datetime timeLow  = time[lowestIdx];

   // Time variables for Fibonacci anchor points
   datetime time1, time2;
   double price1, price2;

   // Establish trend direction for proper Fibonacci projection
   if(highestIdx > lowestIdx)
     {
      // High index is larger -> High occurred further back in time -> Downtrend
      time1 = timeHigh; price1 = highestPrice;
      time2 = timeLow;  price2 = lowestPrice;
     }
   else
     {
      // Low index is larger -> Low occurred further back in time -> Uptrend
      time1 = timeLow;  price1 = lowestPrice;
      time2 = timeHigh; price2 = highestPrice;
     }

   // Initialize or update the OBJ_FIBO graphic object
   if(ObjectFind(0, fiboName) < 0)
     {
      ObjectCreate(0, fiboName, OBJ_FIBO, 0, time1, price1, time2, price2);
      
      // Core styling
      ObjectSetInteger(0, fiboName, OBJPROP_COLOR, FiboColor);
      ObjectSetInteger(0, fiboName, OBJPROP_STYLE, FiboStyle);
      ObjectSetInteger(0, fiboName, OBJPROP_BACK, true); 
      ObjectSetInteger(0, fiboName, OBJPROP_SELECTABLE, false);
      ObjectSetInteger(0, fiboName, OBJPROP_HIDDEN, true);
      
      // Define the retracement levels
      int numLevels = ShowExtensions ? 8 : 6;
      ObjectSetInteger(0, fiboName, OBJPROP_LEVELS, numLevels);
      
      // The '%$' token dynamically prints the precise price level on the chart
      ObjectSetDouble(0, fiboName, OBJPROP_LEVELVALUE, 0, 0.0);   ObjectSetString(0, fiboName, OBJPROP_LEVELTEXT, 0, "0.0 (%$)");
      ObjectSetDouble(0, fiboName, OBJPROP_LEVELVALUE, 1, 0.236); ObjectSetString(0, fiboName, OBJPROP_LEVELTEXT, 1, "23.6 (%$)");
      ObjectSetDouble(0, fiboName, OBJPROP_LEVELVALUE, 2, 0.382); ObjectSetString(0, fiboName, OBJPROP_LEVELTEXT, 2, "38.2 (%$)");
      ObjectSetDouble(0, fiboName, OBJPROP_LEVELVALUE, 3, 0.5);   ObjectSetString(0, fiboName, OBJPROP_LEVELTEXT, 3, "50.0 (%$)");
      ObjectSetDouble(0, fiboName, OBJPROP_LEVELVALUE, 4, 0.618); ObjectSetString(0, fiboName, OBJPROP_LEVELTEXT, 4, "61.8 (%$)");
      ObjectSetDouble(0, fiboName, OBJPROP_LEVELVALUE, 5, 1.0);   ObjectSetString(0, fiboName, OBJPROP_LEVELTEXT, 5, "100.0 (%$)");
      
      // Define expansion levels for profit targets
      if(ShowExtensions)
        {
         ObjectSetDouble(0, fiboName, OBJPROP_LEVELVALUE, 6, 1.618); ObjectSetString(0, fiboName, OBJPROP_LEVELTEXT, 6, "161.8 (%$)");
         ObjectSetDouble(0, fiboName, OBJPROP_LEVELVALUE, 7, 2.618); ObjectSetString(0, fiboName, OBJPROP_LEVELTEXT, 7, "261.8 (%$)");
        }
     }
   else
     {
      // Update anchors on every tick as the lookback window shifts
      ObjectSetInteger(0, fiboName, OBJPROP_TIME, 0, time1);
      ObjectSetDouble(0, fiboName, OBJPROP_PRICE, 0, price1);
      ObjectSetInteger(0, fiboName, OBJPROP_TIME, 1, time2);
      ObjectSetDouble(0, fiboName, OBJPROP_PRICE, 1, price2);
     }

   return(rates_total);
  }
//+------------------------------------------------------------------+

Re: Custom Fibonacci retracement indicator for Forex

Posted: Thu Aug 06, 2026 10:17 pm
by FTtrader
How the Logic WorksTime Series Indexing:

MT4 arrays do not strictly guarantee reverse indexing out of the box depending on the build. Calling ArraySetAsSeries(..., true) forces the arrays to behave like a C# List<T>, ensuring index [0] is always the active, currently forming candlestick.Trend Detection: The script uses ArrayMaximum and ArrayMinimum to locate the highest and lowest points within the LookbackPeriod. By comparing their array indices, the indicator determines whether the high or the low occurred further back in time—automatically establishing the drawing direction for uptrends versus downtrends.Dynamic Price Tags: The %$ token passed to the OBJPROP_LEVELTEXT string instructs the MetaTrader engine to dynamically calculate and render the exact currency exchange price next to the Fibonacci percentage.

1.Open MetaEditor:Press F4 while inside your MT4 terminal.

2.Create the File:Click New -> Custom Indicator and name it AutoFibo_Custom.

3.Compile the Code:Overwrite the default template with the provided code and press F7 to compile.4.Attach to Chart:Drag the indicator onto any currency pair. It will run silently in the background, updating the anchors dynamically as new ticks arrive.

Re: Custom Fibonacci retracement indicator for Forex

Posted: Thu Aug 06, 2026 10:19 pm
by FTtrader
For IC trader traders:

Moving from MT4 to IC Markets' cTrader platform means shifting from MQL4 into a proper C# .NET environment. You will feel right at home here—cTrader's Automate API is built entirely on the .NET framework, giving you full access to standard C# memory management, object-oriented principles, and standard libraries.

Here is the equivalent dynamic Fibonacci indicator written in C#. I have set up the corporate namespace and header for your production use.

Code: Select all

//+------------------------------------------------------------------+
//| AutoFibo.cs                                                      |
//| Copyright 2026, Pavel Tuček                                      |
//| https://aiprofisolutions.com                                     |
//+------------------------------------------------------------------+

using System;
using cAlgo.API;
using cAlgo.API.Internals;
using cAlgo.API.Indicators;

namespace AIProfiSolutions.Indicators
{
    [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class AutoFibo : Indicator
    {
        [Parameter("Lookback Period (Bars)", DefaultValue = 100, MinValue = 10)]
        public int LookbackPeriod { get; set; }

        private const string FiboObjectName = "AutoFibo_Dynamic";

        protected override void Initialize()
        {
            // Fired once when the indicator is attached to the chart
        }

        public override void Calculate(int index)
        {
            // To optimize .NET garbage collection and CPU cycles on high-frequency 
            // market data, we restrict the drawing logic strictly to the active forming bar.
            if (!IsLastBar || index < LookbackPeriod) 
                return;

            int startIndex = index - LookbackPeriod;
            
            double highestPrice = double.MinValue;
            double lowestPrice = double.MaxValue;
            int highestIndex = index;
            int lowestIndex = index;

            // A standard `for` loop is utilized here instead of LINQ extensions (.Max() / .Min()) 
            // to avoid unnecessary memory allocations on every tick.
            for (int i = startIndex; i <= index; i++)
            {
                if (Bars.HighPrices[i] > highestPrice)
                {
                    highestPrice = Bars.HighPrices[i];
                    highestIndex = i;
                }
                
                if (Bars.LowPrices[i] < lowestPrice)
                {
                    lowestPrice = Bars.LowPrices[i];
                    lowestIndex = i;
                }
            }

            int index1, index2;
            double price1, price2;

            // Establish trend direction for the anchor points
            if (highestIndex < lowestIndex)
            {
                // High occurred further back in time -> Downtrend
                index1 = highestIndex;
                price1 = highestPrice;
                index2 = lowestIndex;
                price2 = lowestPrice;
            }
            else
            {
                // Low occurred further back in time -> Uptrend
                index1 = lowestIndex;
                price1 = lowestPrice;
                index2 = highestIndex;
                price2 = highestPrice;
            }

            // cTrader's native API handles the rendering of all standard retracement 
            // and extension levels automatically via this single method call.
            Chart.DrawFibonacciRetracement(FiboObjectName, index1, price1, index2, price2, Color.Goldenrod);
        }
    }
}

Re: Custom Fibonacci retracement indicator for Forex

Posted: Thu Aug 06, 2026 10:20 pm
by FTtrader
Key Differences in cTrader (C#)Event Loop Optimization:

In MT4, OnCalculate passes arrays of data. In cTrader, the Calculate(int index) method fires for every historical bar upon initialization, and then fires on every tick for the live bar. By wrapping the logic in if (!IsLastBar), we skip redundant calculations on historical data and only update the Fibonacci anchors on the live edge of the chart.Native Fibonacci Object: cTrader's Chart.DrawFibonacciRetracement is a high-level API call that automatically draws the 23.6%, 38.2%, 50%, and 61.8% levels. (Any custom extensions like 161.8% are managed globally in the user's cTrader chart settings rather than being hardcoded into the indicator script).
Performance: I opted for a standard for loop over the lookback window. While LINQ operations like Bars.HighPrices.Last(LookbackPeriod).Max() look cleaner in C#, they allocate enumerators on the heap, which can cause micro-stutters during heavy GC collection in live tick trading.

1.Open Automate Tab:In the left-hand menu of cTrader, click on the Automate application icon.

2.Create New Indicator:Click the + New button at the top of the indicators list and name it AutoFibo.

3.Paste and Build:Overwrite the default code with the script above. Click the Build button (or press Ctrl+B) to compile the .NET assembly.

4.Add an Instance:Click the + Add Instance button to apply the indicator directly to your active chart.

Re: Custom Fibonacci retracement indicator for Forex

Posted: Thu Aug 06, 2026 10:21 pm
by FTtrader
And this is for MT5:

Moving to MetaTrader 5 (MQL5) brings you to a much more rigorous, C++ style environment compared to MQL4.

While the syntax looks nearly identical to the MT4 version on the surface, there are structural differences under the hood. For instance, MQL5 does not assume time-series indexing by default, and it requires explicit #property indicator_plots 0 if you are only drawing graphical objects without using indicator buffers.

As a developer, you will also spot the classic MT4-to-MT5 "gotcha" here: the parameters for ArrayMaximum and ArrayMinimum are swapped in MQL5. They take (array, start, count) instead of MQL4's (array, count, start).

Here is the fully adapted MQL5 source code, properly templated for your environment.

Code: Select all

//+------------------------------------------------------------------+
//|                                                  AutoFibo.mq5    |
//|                                  Copyright 2026, Pavel Tuček     |
//|                                     https://aiprofisolutions.com |
//+------------------------------------------------------------------+
#property copyright "Pavel Tuček"
#property link      "https://aiprofisolutions.com"
#property version   "1.00"
#property indicator_chart_window
#property indicator_plots 0 // Explicitly tell MT5 we are not using data buffers

//--- Input parameters
input int    LookbackPeriod = 100;         // Lookback Period (Bars)
input color  FiboColor      = clrGoldenrod;// Fibonacci Lines Color
input bool   ShowExtensions = true;        // Show 161.8% and 261.8%
input ENUM_LINE_STYLE FiboStyle = STYLE_SOLID; // Line Style

//--- Global variables
string fiboName = "AutoFibo_MT5";

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
   // Validate the lookback period
   if(LookbackPeriod <= 0)
     {
      Print("LookbackPeriod must be greater than 0");
      return(INIT_PARAMETERS_INCORRECT);
     }
   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   // Clean up the graphical object when the indicator is removed 
   ObjectDelete(0, fiboName);
  }

//+------------------------------------------------------------------+
//| 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[])
  {
   // Wait until the chart has enough historical bars
   if(rates_total < LookbackPeriod) return(0);

   // MQL5 requires manual enforcement of time series indexing (Index 0 = current bar)
   ArraySetAsSeries(high, true);
   ArraySetAsSeries(low, true);
   ArraySetAsSeries(time, true);

   // Find highest/lowest points. 
   // Note the MQL5 signature change: ArrayMaximum(array, start_index, count)
   int highestIdx = ArrayMaximum(high, 0, LookbackPeriod);
   int lowestIdx  = ArrayMinimum(low, 0, LookbackPeriod);

   // Safety check for invalid indices
   if(highestIdx < 0 || lowestIdx < 0) return(0);

   double highestPrice = high[highestIdx];
   double lowestPrice  = low[lowestIdx];

   datetime timeHigh = time[highestIdx];
   datetime timeLow  = time[lowestIdx];

   // Time variables for Fibonacci anchor points
   datetime time1, time2;
   double price1, price2;

   // Establish trend direction for proper Fibonacci projection
   if(highestIdx > lowestIdx)
     {
      // High index is larger -> High occurred further back in time -> Downtrend
      time1 = timeHigh; price1 = highestPrice;
      time2 = timeLow;  price2 = lowestPrice;
     }
   else
     {
      // Low index is larger -> Low occurred further back in time -> Uptrend
      time1 = timeLow;  price1 = lowestPrice;
      time2 = timeHigh; price2 = highestPrice;
     }

   // Initialize or update the OBJ_FIBO graphic object
   if(ObjectFind(0, fiboName) < 0)
     {
      ObjectCreate(0, fiboName, OBJ_FIBO, 0, time1, price1, time2, price2);
      
      // Core styling
      ObjectSetInteger(0, fiboName, OBJPROP_COLOR, FiboColor);
      ObjectSetInteger(0, fiboName, OBJPROP_STYLE, FiboStyle);
      ObjectSetInteger(0, fiboName, OBJPROP_BACK, true); 
      ObjectSetInteger(0, fiboName, OBJPROP_SELECTABLE, false);
      ObjectSetInteger(0, fiboName, OBJPROP_HIDDEN, true);
      
      // Define the retracement levels
      int numLevels = ShowExtensions ? 8 : 6;
      ObjectSetInteger(0, fiboName, OBJPROP_LEVELS, numLevels);
      
      // The '%$' token dynamically prints the precise price level on the chart
      ObjectSetDouble(0, fiboName, OBJPROP_LEVELVALUE, 0, 0.0);   ObjectSetString(0, fiboName, OBJPROP_LEVELTEXT, 0, "0.0 (%$)");
      ObjectSetDouble(0, fiboName, OBJPROP_LEVELVALUE, 1, 0.236); ObjectSetString(0, fiboName, OBJPROP_LEVELTEXT, 1, "23.6 (%$)");
      ObjectSetDouble(0, fiboName, OBJPROP_LEVELVALUE, 2, 0.382); ObjectSetString(0, fiboName, OBJPROP_LEVELTEXT, 2, "38.2 (%$)");
      ObjectSetDouble(0, fiboName, OBJPROP_LEVELVALUE, 3, 0.5);   ObjectSetString(0, fiboName, OBJPROP_LEVELTEXT, 3, "50.0 (%$)");
      ObjectSetDouble(0, fiboName, OBJPROP_LEVELVALUE, 4, 0.618); ObjectSetString(0, fiboName, OBJPROP_LEVELTEXT, 4, "61.8 (%$)");
      ObjectSetDouble(0, fiboName, OBJPROP_LEVELVALUE, 5, 1.0);   ObjectSetString(0, fiboName, OBJPROP_LEVELTEXT, 5, "100.0 (%$)");
      
      // Define expansion levels for profit targets
      if(ShowExtensions)
        {
         ObjectSetDouble(0, fiboName, OBJPROP_LEVELVALUE, 6, 1.618); ObjectSetString(0, fiboName, OBJPROP_LEVELTEXT, 6, "161.8 (%$)");
         ObjectSetDouble(0, fiboName, OBJPROP_LEVELVALUE, 7, 2.618); ObjectSetString(0, fiboName, OBJPROP_LEVELTEXT, 7, "261.8 (%$)");
        }
     }
   else
     {
      // Update anchors dynamically
      ObjectSetInteger(0, fiboName, OBJPROP_TIME, 0, time1);
      ObjectSetDouble(0, fiboName, OBJPROP_PRICE, 0, price1);
      ObjectSetInteger(0, fiboName, OBJPROP_TIME, 1, time2);
      ObjectSetDouble(0, fiboName, OBJPROP_PRICE, 1, price2);
     }

   return(rates_total);
  }
//+------------------------------------------------------------------+

Re: Custom Fibonacci retracement indicator for Forex

Posted: Thu Aug 06, 2026 10:22 pm
by FTtrader
Steps to start it:

1.Open MetaEditor 5:Press F4 while inside your MT5 terminal.

2.Create the File:Click New -> Custom Indicator. You can skip the data buffer setup wizard entirely since we are using indicator_plots 0 for direct chart rendering. Name it AutoFibo_MT5.

3.Compile the Code:Overwrite the default template with the script above and press F7 to compile it into an .ex5 executable.

4.Attach to Chart:Drag the indicator from the MT5 Navigator window onto any active trading chart.

I hope, that you will like it.
Take a care and have a good night :-)