Auto Fibonacci MQL5 Indicator: Automatic Retracement & Extension Levels
Draw one MT5 Fibonacci object between a recent confirmed swing high and low. This educational indicator uses strict left/right pivots and filters each pivot candle by its own range relative to ATR. It plots optional extension levels but has no verified trading results or automatic entry/exit system.
How the indicator signal works
Calculation and signal conditions
The indicator waits for InpLookbackRight completed bars after a candidate pivot, checks its left/right neighbors, then requires that pivot candle’s high-low range meet InpMinSwingATR times ATR. This is a candle-range filter, not the distance between two swings. Among the latest 300 bars it selects the most recent qualifying high and low, which need not form an alternating swing sequence.
Interpretation and limitations
Only one Fibonacci object is drawn, with configurable color and optional 127.2%/161.8% levels. No SMA/RSI/candlestick entry confirmation, limit orders, position sizing, partial exits or trailing stops are implemented. New qualifying pivots can move the anchors and all levels. A historical pivot marker appears only after right-side confirmation; it was not available at the pivot time.
MQL5 Custom Indicator Code
//+------------------------------------------------------------------+
//| AutoFibonacci.mq5 |
//| Auto Fibonacci Retracement & Extension Indicator |
//| For educational purposes only. Not financial advice. |
//+------------------------------------------------------------------+
#property copyright "Pineify — pineify.app"
#property link "https://pineify.app"
#property version "1.00"
#property indicator_chart_window
#property indicator_buffers 4
#property indicator_plots 2
#property indicator_type1 DRAW_ARROW
#property indicator_type2 DRAW_ARROW
#property indicator_color1 LimeGreen
#property indicator_color2 Tomato
#property indicator_width1 2
#property indicator_width2 2
//--- Input parameters
input int InpLookbackLeft = 3; // Left bars for swing detection
input int InpLookbackRight = 3; // Right bars for swing detection
input double InpMinSwingATR = 2.0; // Minimum swing in ATR(14) units
input bool InpShowExtensions = true; // Show 127.2% and 161.8% levels
input color InpFibColor = clrGold; // Fibonacci line color
input int InpATRPeriod = 14; // ATR period for swing filter
input string InpObjPrefix = "AF_"; // Object prefix for cleanup
//--- Indicator buffers
double swingHighBuffer[];
double swingLowBuffer[];
double atrCalcBuffer[];
double priceRangeBuffer[];
//--- Global handles
int atrHandle=INVALID_HANDLE;
string fibObjectName="";
//+------------------------------------------------------------------+
int OnInit()
{
if(InpLookbackLeft<1 || InpLookbackRight<1 || InpATRPeriod<1 || InpMinSwingATR<0 || StringLen(InpObjPrefix)>25) return INIT_PARAMETERS_INCORRECT;
fibObjectName=InpObjPrefix+IntegerToString(ChartID())+"_"+IntegerToString(GetTickCount64());
SetIndexBuffer(0, swingHighBuffer, INDICATOR_DATA);
SetIndexBuffer(1, swingLowBuffer, INDICATOR_DATA);
SetIndexBuffer(2, atrCalcBuffer, INDICATOR_CALCULATIONS);
SetIndexBuffer(3, priceRangeBuffer, INDICATOR_CALCULATIONS);
PlotIndexSetInteger(0, PLOT_ARROW, 218); // down-arrow above swing highs
PlotIndexSetInteger(1, PLOT_ARROW, 217); // up-arrow below swing lows
PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, 0);
PlotIndexSetDouble(1, PLOT_EMPTY_VALUE, 0);
IndicatorSetString(INDICATOR_SHORTNAME,
"AutoFib(" + string(InpLookbackLeft) + "," +
string(InpLookbackRight) + ")");
atrHandle = iATR(_Symbol, _Period, InpATRPeriod);
if(atrHandle == INVALID_HANDLE)
{
Print("ERROR: iATR handle failed. Code: ", GetLastError());
return INIT_FAILED;
}
ArraySetAsSeries(swingHighBuffer, true);
ArraySetAsSeries(swingLowBuffer, true);
ArraySetAsSeries(atrCalcBuffer, true);
ArraySetAsSeries(priceRangeBuffer, true);
Print("AutoFib initialized on ", _Symbol, " ", EnumToString(_Period),
" | ATR ", InpATRPeriod, " | min swing ", InpMinSwingATR, "x");
return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
if(atrHandle != INVALID_HANDLE) IndicatorRelease(atrHandle);
if(fibObjectName!="") ObjectDelete(0,fibObjectName);
Print("AutoFib removed. Reason: ", reason);
}
//+------------------------------------------------------------------+
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[])
{
ArraySetAsSeries(time, true);
ArraySetAsSeries(high, true);
ArraySetAsSeries(low, true);
ArraySetAsSeries(close, true);
if(rates_total < InpLookbackLeft + InpLookbackRight + InpATRPeriod + 30)
return 0;
int start=rates_total-InpLookbackLeft-InpATRPeriod-1;
ArrayInitialize(swingHighBuffer,0);
ArrayInitialize(swingLowBuffer,0);
if(CopyBuffer(atrHandle, 0, 0, rates_total, atrCalcBuffer) < rates_total)
return prev_calculated;
for(int i=start;i>=InpLookbackRight+1;i--)
{
priceRangeBuffer[i] = high[i] - low[i];
swingHighBuffer[i] = 0;
swingLowBuffer[i] = 0;
if(i < InpLookbackRight || i >= rates_total - InpLookbackLeft)
continue;
//--- Swing high check
bool isHigh = true;
for(int l = 1; l <= InpLookbackLeft && isHigh; l++)
if(high[i] <= high[i + l]) isHigh = false;
for(int r = 1; r <= InpLookbackRight && isHigh; r++)
if(high[i] <= high[i - r]) isHigh = false;
if(isHigh && atrCalcBuffer[i] > 0
&& priceRangeBuffer[i] >= InpMinSwingATR * atrCalcBuffer[i])
swingHighBuffer[i] = high[i];
//--- Swing low check
bool isLow = true;
for(int l = 1; l <= InpLookbackLeft && isLow; l++)
if(low[i] >= low[i + l]) isLow = false;
for(int r = 1; r <= InpLookbackRight && isLow; r++)
if(low[i] >= low[i - r]) isLow = false;
if(isLow && atrCalcBuffer[i] > 0
&& priceRangeBuffer[i] >= InpMinSwingATR * atrCalcBuffer[i])
swingLowBuffer[i] = low[i];
}
DrawFibonacciLevels(time, rates_total);
return rates_total;
}
//+------------------------------------------------------------------+
void DrawFibonacciLevels(const datetime &time[], int rates_total)
{
int highIdx = -1, lowIdx = -1;
double highVal = 0, lowVal = 0;
int found = 0;
int scan = MathMin(rates_total, 300);
for(int i = 0; i < scan && found < 2; i++)
{
if(swingHighBuffer[i] > 0 && highIdx < 0)
{ highIdx = i; highVal = swingHighBuffer[i]; found++; }
if(swingLowBuffer[i] > 0 && lowIdx < 0)
{ lowIdx = i; lowVal = swingLowBuffer[i]; found++; }
}
if(highIdx<0 || lowIdx<0 || highIdx==lowIdx)
{ ObjectDelete(0,fibObjectName); return; }
datetime t1, t2;
double p1, p2;
if(lowIdx > highIdx)
{ t1 = time[highIdx]; p1 = highVal; t2 = time[lowIdx]; p2 = lowVal; }
else
{ t1 = time[lowIdx]; p1 = lowVal; t2 = time[highIdx]; p2 = highVal; }
string fibName=fibObjectName;
if(ObjectFind(0,fibName)<0)
{
if(!ObjectCreate(0,fibName,OBJ_FIBO,0,t1,p1,t2,p2))
{ Print("OBJ_FIBO create error: ",GetLastError()); return; }
}
else if(!ObjectMove(0,fibName,0,t1,p1) || !ObjectMove(0,fibName,1,t2,p2))
{ Print("OBJ_FIBO move error: ",GetLastError()); return; }
ObjectSetInteger(0, fibName, OBJPROP_COLOR, InpFibColor);
ObjectSetInteger(0, fibName, OBJPROP_WIDTH, 1);
ObjectSetInteger(0, fibName, OBJPROP_BACK, false);
ObjectSetInteger(0, fibName, OBJPROP_SELECTABLE, true);
ObjectSetInteger(0, fibName, OBJPROP_RAY_RIGHT, false);
double fibVals[];
string fibDescs[];
int fibCount = InpShowExtensions ? 9 : 7;
ArrayResize(fibVals, fibCount);
ArrayResize(fibDescs, fibCount);
string levelDefs[] = {
"0.0%:0.0", "23.6%:0.236", "38.2%:0.382", "50.0%:0.5",
"61.8%:0.618", "78.6%:0.786", "100.0%:1.0",
"127.2%:1.272", "161.8%:1.618"
};
for(int j = 0; j < fibCount; j++)
{
string parts[];
StringSplit(levelDefs[j], ':', parts);
fibDescs[j] = parts[0];
fibVals[j] = StringToDouble(parts[1]);
}
ObjectSetInteger(0, fibName, OBJPROP_LEVELS, fibCount);
for(int j = 0; j < fibCount; j++)
{
ObjectSetDouble(0, fibName, OBJPROP_LEVELVALUE, j, fibVals[j]);
ObjectSetString(0, fibName, OBJPROP_LEVELTEXT, j, fibDescs[j]);
ObjectSetInteger(0, fibName, OBJPROP_LEVELCOLOR, j, InpFibColor);
}
}
//+------------------------------------------------------------------+
Copy this code into MetaEditor, save it in the MQL5/Indicators folder, and compile with F7.
Change the settings or add your own signal filter
Describe the inputs, buffers, alerts, visual style, or confirmation filter you want. Pineify generates editable MQL5 source code that you can inspect and compile in MetaEditor.
Frequently Asked Questions
Related MQL5 pages
Technical references
Risk and testing note
These educational examples require independent compilation and testing. A compile pass or an illustrative setting does not establish execution correctness or profitability. Any reported performance must be supported by reproducible data and test settings; past results do not predict future returns. Trading involves significant risk of loss. This content is not financial advice.