Showing posts with label Forex trading strategies. Show all posts
Showing posts with label Forex trading strategies. Show all posts

Wednesday, August 13, 2025

Introduction

The Money Flow Index Multi-Timeframe (MFI_MTF) Indicator for MetaTrader 5 calculates and scans the Money Flow Index (MFI) on all 21 standard MT5 timeframes (M1 … MN1) and displays per-timeframe signals directly on the chart. The indicator creates a native iMFI handle for every timeframe, draws Wingdings arrow labels per timeframe, and computes a single consensus summary signal (exported as PowerMove[]) when a dominant directional majority exists. An on-chart clickable panel allows instant timeframe switching without reattaching the indicator.

Key Features

  • 21-Timeframe MFI Scanning — MFI is calculated using iMFI(Symbol(), TFId[x], MFI_period, VOLUME_TICK) for each timeframe defined in TFIx[].
  • Per-timeframe Wingdings Arrow Overlay — per timeframe arrow uses windchar (char 108) and colored by inputs ArrowUp, ArrowDn, NTArrow.
  • Consensus Summary Signal — consensus computed in MFIMovementCalculation() and written to PowerMove[]. Condition: up > down + 1 → UP (1.0); down > up + 1 → DOWN (-1.0).
  • Interactive On-Chart Panel — clickable timeframe buttons (CreateButtonClick()) and panel position controls (artop / arbot), handled in OnChartEvent().
  • Customizable Appearance — control font via input f_model (Verdana or Bodoni MT Black), arrow sizes (windsize), and layout offsets (offsetX, offsetY).
  • Alerts — popup alerts plus optional email and push via UseEmailAlert and UseSendnotify. Alerts are sent in Do_Alerts() when curAlert changes.
  • EA-Friendly Output — consensus exported to index buffer: SetIndexBuffer(0, mi.PowerMove, INDICATOR_DATA) so EAs can read 1.0 / -1.0.
  • Clean resource management — all indicator handles are released in OnDeinit() with IndicatorRelease() and chart objects removed via DeletedMFIObject().
Implementation note: This article is faithful to the MFI_MTF.mq5 source (Roberto Jacobs, 2025-01-14). Variable names and behavior described below are taken directly from the source code.

Inputs and Parameters

InputDescription
BarCalcIndicator period for MFI calculation (validated; fallback to 14 if <1)
ArrowUpColor for Up arrow (default clrMediumSeaGreen)
ArrowDnColor for Down arrow (default clrDeepPink)
NTArrowColor for No-Signal arrow (default clrGold)
f_modelFont model enum (Verdana, Bodoni_MT_Black)
alertsPopup alerts toggle (enum YN)
UseEmailAlertEmail alert toggle (enum YN)
UseSendnotifyPush notification toggle (enum YN)

2. About This Indicator

The Money Flow Index Multi-Timeframe (MFI_MTF) Indicator for MetaTrader 5 utilizes a template and displays a panel on the chart.

Its function, operation, and usage are identical to the On Balance Volume Multi-Timeframe Indicator for MT5 (OBV_MTF) as detailed in the previous article. For a comprehensive guide on creating a multi-timeframe indicator, you can refer to the following resources: On Balance Volume Multi-Timeframe Indicator for MT5

🔁 Note: All multi-timeframe indicators developed by Forex Home Expert use this exact signal logic programs structure.

GBPUSDH1_MFI_MTF

How It Works (implementation details)

1. Initialization

OnInit() calls mi.MFI_MTF_Config(). The config routine defines the timeframe array TFIx[] and label array TFSc[], sets tfxar = ArraySize(TFIx), validates BarCalc to set MFI_period, computes ttlbars = BarCalc*3+3, and creates an iMFI handle for each timeframe:

hMFI[x] = iMFI(Symbol(), TFId[x], MFI_period, VOLUME_TICK);
2. Price and Buffer Management

The indicator keeps routines UpdatePrice() and RefreshPrice() to ensure arrays for OHLC, TIME, and VOLUME are prepared if needed. Crucially, MFI values are obtained from the indicator handles via CopyBuffer():

CopyBuffer(hMFI[index], 0, 0, br, MFI);
3. Per-timeframe Direction Scan

MFIDirectionScan(stf, shift) copies br = shift + 2 MFI points and compares MFI[shift] vs MFI[shift+1]:

if (MFI[shift] > MFI[shift+1]) ret = 1; // rise 
if (MFI[shift] < MFI[shift+1]) ret = -1; // down 

This uses closed buffer values (historical indices), so past signals are based on confirmed data.

4. Consensus Calculation

MFIMovementCalculation(barCnt) loops through recent bars and for each bar it scans all tfxar timeframes:

  • Initialize up=0, dw=0, set Arwcolor[x] = NTArrow.
  • Call MFIDirectionScan() for each timeframe; increment up or dw and set per-timeframe arrow color.
  • After scanning all timeframes, if up > dw + 1 then PowerMove[i] = 1.0, TColor = ArrowUp, curAlert = 1. If dw > up + 1 then PowerMove[i] = -1.0, TColor = ArrowDn, curAlert = -1.

The consensus buffer PowerMove[] is written to indicator buffer index 0 so other programs (EAs) can read consensus signals.

5. Alerts

Alerts are handled in OnCalculate() after mi.MFIMovementCalculation(limit) runs. If alerts are enabled, the indicator compares current minute (mi.ThisTime(mi.min)) with the previously alerted minute and sends alerts only when the minute changes and curAlert differs from prvAlert. Messages are sent via Do_Alerts() and contain these texts:

  • "The strength of the MFI movement appears to be Rise."
  • "The strength of the MFI movement appears to be Down."
6. UI / Panel / Interaction

DrawMFIObject() draws the main rectangle template (panel), per-timeframe arrow labels (CreateArrowLabel()), and clickable timeframe buttons (CreateButtonClick()). The big consensus arrow uses Wingdings characters (tstar=217 or bstar=218) and the per-timeframe arrows use windchar=108. Clicking a timeframe button triggers OnChartEvent() and the indicator calls ChangeChartSymbol() which runs ChartSetSymbolPeriod(CI, Symbol(), stf) to change the chart timeframe while preserving the indicator display.

How to Trade (code-faithful guidance)

  1. Attach to any chart — the indicator scans all 21 timeframes regardless of the chart timeframe.
  2. Observe per-timeframe arrows — these show the short-term direction of MFI per timeframe as computed by MFIDirectionScan().
  3. Watch the consensus (PowerMove) — a large arrow appears in the panel if up > down + 1 or down > up + 1. The consensus is the main multi-timeframe trigger for trade consideration.
  4. Use alerts — enable alerts, UseEmailAlert, or UseSendnotify to be notified when consensus changes (note: alerts fire only once per minute per change).
  5. Switch timeframe via panel — click a timeframe label to instantly change the chart timeframe while the multi-timeframe scan remains active.
  6. Programmatic access — read PowerMove[] via iCustom() inside an EA to automate decisions based on consensus values (1.0 or -1.0).

Q/A Section

Q1: Which timeframes does the indicator scan?
A: All 21 standard MT5 timeframes declared in the code’s TFIx[] array: M1, M2, M3, M4, M5, M6, M10, M12, M15, M20, M30, H1, H2, H3, H4, H6, H8, H12, D1, W1, MN1.

Q2: How is the MFI period set?
A: The BarCalc input sets the MFI period. If BarCalc < 1 the code falls back to a default MFI_period = 14 and prints a warning.

Q3: Does the indicator repaint?
A: No. The indicator uses CopyBuffer() to read closed/historical MFI buffer values and compares MFI[shift] against MFI[shift+1], so past signals are based on confirmed buffer values.

Q4: When are alerts triggered?
A: Alerts are triggered only when alerts are enabled, the minute changed since the last alert, and curAlert differs from prvAlert. The messages are generated in Do_Alerts().

Q5: How does the consensus logic decide direction?
A: After scanning all timeframes the code counts up and dw. Consensus UP is set when up > dw + 1. Consensus DOWN is set when dw > up + 1. This requires a margin greater than 1 to avoid marginal-majority triggers.

Q6: Can I change where the panel is located?
A: Yes. Use the on-panel buttons (artop / arbot) to move the panel between top and bottom; this is handled by PanelPosChange().

Q7: Can an EA read the indicator output?
A: Yes — PowerMove[] is assigned to the indicator buffer (index 0) via SetIndexBuffer(0, mi.PowerMove, INDICATOR_DATA), so external EAs can read it with iCustom().

Q8: Are external libraries required?
A: No. The indicator uses native MT5 functions only: iMFI, CopyBuffer, object creation APIs, ChartSetSymbolPeriod, SendMail, and SendNotification.

Q9: Which characters are used for arrows?
A: Per-timeframe arrows use windchar = 108 (Wingdings char 108). The summary large arrows use tstar = 217 (up) and bstar = 218 (down).

Q10: What happens at deinit?
A: OnDeinit() releases all iMFI handles (IndicatorRelease(mi.hMFI[x])), deletes drawn objects via mi.DeletedMFIObject(), and calls ChartRedraw().

Final Words

The Money Flow Index Multi-Timeframe Indicator for MT5 indicator is a robust, non-repainting multi-timeframe MFI scanner designed for MT5. Its architecture separates per-timeframe signal extraction (MFIDirectionScan()) from consensus generation (MFIMovementCalculation()), exports the consensus buffer for EA integration, and offers an interactive panel for quick exploration. The indicator cleanly manages indicator handles and drawn objects on deinit and supports popup, email, and push notifications for live monitoring.

We hope that this article and the MFI_MTF or Money Flow Index Multi-Timeframe Indicator for MT5 program will be useful for traders in learning and generating new ideas for trading, who can ultimately make money from home by trading forex.

Thanks for reading this article.

Please download the MFI_MTF indicator: Money Flow Index Multi-Timeframe Indicator for MT5

If you are subscribed to my YouTube Channel, and would like to receive the source program of this article, please send a request via the Contact Us form page, and I will send it to your email, source code: Money Flow Index Multi-Timeframe Indicator for MT5

Don't forget to stop by and subscribe to Forex Home Experts YouTube Channel:

YouTube Channel: @ForexHomeExperts

YouTube Playlist: @ForexHomeExperts YouTube Playlist

Friday, August 8, 2025

1. Introduction

Fractals are one of the classic tools introduced by legendary trader Bill Williams. These simple yet powerful markers are used to identify local swing highs and lows in price action. When used correctly, Fractals can help traders pinpoint reversal areas or breakout setups.

However, Fractals plotted on lower timeframes are often prone to noise and false signals. This is where the concept of multi-timeframe analysis becomes important.

The Fractals Multi-Timeframe Indicator for MT5 allows traders to overlay fractal signals from a higher timeframe directly onto the current chart. This provides cleaner, more reliable market structure references — without needing to constantly switch timeframes.

The Fractals Multi-Timeframe Indicator for MT5 (Fractals_MTF) Indicator for MetaTrader 5 provides directional signals from all 21 standard timeframes, ranging from M1 to MN1.

For each timeframe, it displays a directional arrow object (`OBJ_ARROW`) using Wingdings character 108:

🟢 Green arrow = upward ADX signal
🔴 Red arrow = downward ADX signal

After gathering these signals, the indicator calculates a consensus summary using a unique logic:
If the number of **up** signals is greater than **down + 1**, the indicator plots a larger **Wingdings 217** upward arrow * If the number of **down** signals is greater than **up + 1**, it plots a larger **Wingdings 218** downward arrow

This enables traders to view a high-confidence trend direction based on multi-timeframe Fractals indicator analysis directly on the main chart.

2. About This Indicator

The Fractals Multi-Timeframe Indicator for MT5 (Fractals_MTF) utilizes a template and displays a panel on the chart. Its function, operation, and usage are identical to the On Balance Volume Multi-Timeframe Indicator for MT5 (OBV_MTF) as detailed in the previous article. For a comprehensive guide on creating a multi-timeframe indicator, you can refer to the following resources: On Balance Volume Multi-Timeframe Indicator for MT5

3. Visual Example

Here is a sample chart showing the indicator in action:

NZDUSDH1_FRA_MTF

4. Key Features:

✅ 21-Timeframe Fractals Scanning
✅ Wingdings Arrows Overlay (per timeframe)
✅ Summary Arrow with Up/Down Consensus Calculation
✅ Color Customization for Each Signal
✅ Built-in Alerts (pop-up, email, mobile)
✅ Graphical Interface Panel for Timeframe Switching (via `OnChartEvent`)

Inputs and Parameters

| Input | Description |
| --------------- | ------------------------------------------ |
| `ArrowUp` | Color of up signal arrow |
| `ArrowDn` | Color of down signal arrow |
| `NTArrow` | Color of neutral arrow (default) |
| `f_model` | Font type for arrows (usually "Wingdings") |
| `alerts` | Enable/disable alert popups |
| `UseEmailAlert` | Enable email alerts |
| `UseSendnotify` | Enable push notification alerts |

Why Multi-Timeframe Fractals Matters?

Fractals are powerful in identifying **waves of price movement strength** but lack responsiveness in **trend consistency** across multiple timeframes. This custom Fractals_MTF indicator solved this:

📈 Confirm trading signals across all timeframes
⚠️ Avoid sideways or weak markets using visual confirmation
🚨 Detect strong breakouts supported by multiple timeframe trend directions

Using **all 21 timeframes** (from M1 to MN1) ensures broad trend consistency in your decision-making process.

5. Technical Overview: How the Indicator Works

Timeframe Management


   //---
   virtual void      Fractals_MTF_Config(void)
     {
      //--
      ENUM_TIMEFRAMES TFId[] = {PERIOD_M1, PERIOD_M2, ..., PERIOD_MN1};
      tfxar=ArraySize(TFIx);  // total 21 timeframes
      ArrayResize(TFId,tfxar,tfxar);
      ArrayCopy(TFId,TFIx,0,0,WHOLE_ARRAY);
      //--
      for(int x=0; x<tfxar; x++)
        hFRA[x]=iFractals(Symbol(),TFId[x]); // Handle of iFractals Indicator on each timeframe
      //--
      DeletedFRAObject();
      FRAMovementCalculation(25);
      PositionCore();
      //--
      if(display)
         DrawFRAObject();
      //---
     }
   //---
/*
Handles for all timeframe-specific Fractals  indicators are stored in `hFRA[]` and initialized inside `OnInit()` using `iFractals()` for each timeframe.
*/

Signal Extraction Logic

Each timeframe is scanned using:


   //---
   int FRADirectionScan(const ENUM_TIMEFRAMES stf,int shift) // Scan iFractals Direction
     {
      //--
      int ret=0;
      int rise=1,
          down=-1;
      //--
      int br=fbar;
      double res=0.0;
      UpdatePrice(stf);
      //--
      double FRAUp[];
      double FRADw[];
      ArrayResize(FRAUp,br,br);
      ArrayResize(FRADw,br,br);
      //--
      int xx=TFIndexArray(stf);
      CopyBuffer(hFRA[xx],0,0,br,FRAUp);
      CopyBuffer(hFRA[xx],1,0,br,FRADw);
      //--
      ArraySetAsSeries(FRAUp,true);
      ArraySetAsSeries(FRADw,true);
      //--
      int fup=br-1,
          fdw=br-1;
      //--
      for(int x=br-1; x>=0; x--)
        {
          if(FRAUp[x]!=EMPTY_VALUE) fup=x;
          if(FRADw[x]!=EMPTY_VALUE) fdw=x;
        }
      //--
      if(fdw<fup && fdw>shift) ret=rise; //
      if(fup<fdw && fup>shift) ret=down; // 
      //--
      return(ret);
      //---
     } //-end FRADirectionScan()
   //---

Consensus Calculation Logic.


   //---
   void FRAMovementCalculation(int barCnt) // Scan the direction of iFractals on each timeframe
     {
      //--
      ArrayResize(PowerMove,barCnt,barCnt);
      ArraySetAsSeries(PowerMove,true);
      //--
      for(int i=barCnt-1; i>=0; i--)
        {
         up=0;
         dw=0;
         //--
         for(int x=0; x<tfxar; x++)
           {
            Arwcolor[x]=NTArrow;
            PowerMove[i]=0.0;
            int PPM=FRADirectionScan(TFId[x],0);
            if(PPM>0)
              {
               up++;
               Arwcolor[x]=ArrowUp;
              }
            if(PPM<0)
              {
               dw++;
               Arwcolor[x]=ArrowDn;
              }
            if(x==tfxar-1)
              {
               if(up>dw+1)
                 {
                  PowerMove[i]=1.0;
                  TColor=ArrowUp;
                  curAlert=1;
                 }
               if(dw>up+1)
                 {
                  PowerMove[i]=-1.0;
                  TColor=ArrowDn;
                  curAlert=-1;
                 }
              }
           }
        }
      //--
      return;
      //---
     } //-end FRAMovementCalculation()
   //---
/*
This logic ensures that only dominant directional consensus (not slight differences) triggers a clear summary signal.
*/

Dynamic Timeframe Panel (OnChartEvent)

The indicator creates a clickable panel on the chart containing labels for all 21 timeframes. When a label (e.g., "H4") is clicked, the internal reference timeframe for analysis is updated.

This makes it easy for the user to interact with the indicator dynamically.


//+------------------------------------------------------------------+
//| ChartEvent function                                              |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
  {
//---
//--- handling CHARTEVENT_CLICK event ("Clicking the chart")
   ResetLastError();
//--
   if(id==CHARTEVENT_OBJECT_CLICK)
     {
      //--- if "X" button is click
      if(sparam=="X")
        {
         mi.DeletedFRAObject();
         //--- unpress the button
         ObjectSetInteger(mi.CI,"X",OBJPROP_STATE,false);
         ObjectSetInteger(mi.CI,"X",OBJPROP_ZORDER,0);
         //--
         mi.display=false;
         ObjectDelete(mi.CI,"X");
         mi.DisplayPanelButton();
        }
      //--- if "cstar" button is click
      if(sparam==mi.cstar)
        {
         mi.DeletedFRAObject();
         mi.DisplayPanelButton();
         //--- unpress the button
         ObjectSetInteger(mi.CI,mi.cstar,OBJPROP_STATE,false);
         ObjectSetInteger(mi.CI,mi.cstar,OBJPROP_ZORDER,0);
         if(!mi.display)
            mi.display=true;
         if(mi.corpos==mi.posbot) ObjectDelete(mi.CI,mi.arbot);
         if(mi.corpos==mi.postop) ObjectDelete(mi.CI,mi.artop);
         mi.DrawFRAObject();
         //--
         ChartRedraw(mi.CI);
        }
      //--- if "artop" button is click
      if(sparam==mi.artop)
        {
         mi.DeletedFRAObject();
         mi.DisplayPanelButton();
         //--- unpress the button
         ObjectSetInteger(mi.CI,mi.artop,OBJPROP_STATE,false);
         ObjectSetInteger(mi.CI,mi.artop,OBJPROP_ZORDER,0);
         if(!mi.display)
            mi.display=true;
         ObjectDelete(mi.CI,mi.artop);
         mi.PanelPosChange(mi.postop);
         //--
         ObjectDelete(mi.CI,"X");
         mi.DisplayButtonClick("arbot");
         mi.DrawFRAObject();
         //--
         ChartRedraw(mi.CI);
        }
      //--- if "arbot" button is click
      if(sparam==mi.arbot)
        {
         mi.DeletedFRAObject();
         mi.DisplayPanelButton();
         //--- unpress the button
         ObjectSetInteger(mi.CI,mi.arbot,OBJPROP_STATE,false);
         ObjectSetInteger(mi.CI,mi.arbot,OBJPROP_ZORDER,0);
         if(!mi.display)
            mi.display=true;
         ObjectDelete(mi.CI,mi.arbot);
         mi.PanelPosChange(mi.posbot);
         //--
         ObjectDelete(mi.CI,"X");
         mi.DisplayButtonClick("artop");
         mi.DrawFRAObject();
         //--
         ChartRedraw(mi.CI);
        }
      //--- if TF button is click
      //--
      if(sparam==mi.TFSc[0])
        {
         mi.ChangeChartSymbol(mi.TFSc[0],mi.TFId[0]);
        }
      //--
      if(sparam==mi.TFSc[1])
        {
         mi.ChangeChartSymbol(mi.TFSc[1],mi.TFId[1]);
        }
      //--
      if(sparam==mi.TFSc[2])
        {
         mi.ChangeChartSymbol(mi.TFSc[2],mi.TFId[2]);
        }
      //--
      if(sparam==mi.TFSc[3])
        {
         mi.ChangeChartSymbol(mi.TFSc[3],mi.TFId[3]);
        }
      //--
      if(sparam==mi.TFSc[4])
        {
         mi.ChangeChartSymbol(mi.TFSc[4],mi.TFId[4]);
        }
      //--
      if(sparam==mi.TFSc[5])
        {
         mi.ChangeChartSymbol(mi.TFSc[5],mi.TFId[5]);
        }
      //--
      if(sparam==mi.TFSc[6])
        {
         mi.ChangeChartSymbol(mi.TFSc[6],mi.TFId[6]);
        }
      //--
      if(sparam==mi.TFSc[7])
        {
         mi.ChangeChartSymbol(mi.TFSc[7],mi.TFId[7]);
        }
      //--
      if(sparam==mi.TFSc[8])
        {
         mi.ChangeChartSymbol(mi.TFSc[8],mi.TFId[8]);
        }
      //--
      if(sparam==mi.TFSc[9])
        {
         mi.ChangeChartSymbol(mi.TFSc[9],mi.TFId[9]);
        }
      //--
      if(sparam==mi.TFSc[10])
        {
         mi.ChangeChartSymbol(mi.TFSc[10],mi.TFId[10]);
        }
      //--
      if(sparam==mi.TFSc[11])
        {
         mi.ChangeChartSymbol(mi.TFSc[11],mi.TFId[11]);
        }
      //--
      if(sparam==mi.TFSc[12])
        {
         mi.ChangeChartSymbol(mi.TFSc[12],mi.TFId[12]);
        }
      //--
      if(sparam==mi.TFSc[13])
        {
         mi.ChangeChartSymbol(mi.TFSc[13],mi.TFId[13]);
        }
      //--
      if(sparam==mi.TFSc[14])
        {
         mi.ChangeChartSymbol(mi.TFSc[14],mi.TFId[14]);
        }
      //--
      if(sparam==mi.TFSc[15])
        {
         mi.ChangeChartSymbol(mi.TFSc[15],mi.TFId[15]);
        }
      //--
      if(sparam==mi.TFSc[16])
        {
         mi.ChangeChartSymbol(mi.TFSc[16],mi.TFId[16]);
        }
      //--
      if(sparam==mi.TFSc[17])
        {
         mi.ChangeChartSymbol(mi.TFSc[17],mi.TFId[17]);
        }
      //--
      if(sparam==mi.TFSc[18])
        {
         mi.ChangeChartSymbol(mi.TFSc[18],mi.TFId[18]);
        }
      //--
      if(sparam==mi.TFSc[19])
        {
         mi.ChangeChartSymbol(mi.TFSc[19],mi.TFId[19]);
        }
      //--
      if(sparam==mi.TFSc[20])
        {
         mi.ChangeChartSymbol(mi.TFSc[20],mi.TFId[20]);
        }
      //--
     }
//---
  } //-end OnChartEvent()
//---------//

How to Use

1. **Attach to Any Chart** (e.g., EURUSD H1)
2. **Adjust the Inputs**
3. **Observe Directional Arrows** per timeframe on your chart
4. **Watch Summary Signal Arrow** (center chart)
5. **Click Timeframe Labels** to change timeframe view instantly

6. Advantages and Limitations

Advantages:
- Adds structure to noisy lower timeframes
- Visual confirmation of support/resistance
- Doesn’t repaint once the fractal bar closes

⚠️ Limitations:
- Fractals do **repaint** until the full pattern forms (2 candles after center)
- May lag in fast-moving markets
- This limitation is overcome by using the multi-timeframe Fractal indicator.

7. Final Thoughts

The Fractals Multi-Timeframe Indicator for MT5 brings an edge to traders who rely on market structure. Whether you trade breakouts, reversals, or trends — having higher timeframe swing points in sight makes your chart more informative and actionable.

The Fractals Multi-Timeframe Indicator for MT5 offers a complete solution for traders who want to understand trend strength across all timeframes simultaneously. Using a unique formula that scans and weighs up/down movement across 21 timeframes, it delivers a summary arrow signal that simplifies complex data into an actionable visual and removes the multi-timeframe Fractal indicator limitation.

With features like dynamic chart interaction, visual arrows, alerts, and a lightweight design, this tool is ideal for discretionary and algorithmic traders alike.

Try it in your next trading session — and gain a clearer view of what the big players are watching.

We hope that this article and the Fractals_MTF or Fractals Multi-Timeframe Indicator for MT5 program will be useful for traders in learning and generating new ideas for trading, who can ultimately make money from home by trading forex.

Thanks for reading this article.

Please download the Fractals_MTF indicator: Fractals Multi-Timeframe Indicator for MT5

If you are subscribed to my YouTube Channel, and would like to receive the source program of this article, please send a request via the Contact Us form page, and I will send it to your email, source code: Fractals Multi-Timeframe Indicator for MT5

Don't forget to stop by and subscribe to Forex Home Experts YouTube Channel:

YouTube Channel: @ForexHomeExperts

YouTube Playlist: @ForexHomeExperts YouTube Playlist

Friday, January 24, 2025

In this article, I will discuss the creation of the On Balance Volume Multi Timeframe indicator for MT5. This indicator will calculate the comparison of OBV movements in percentage terms across 21 different timeframes, ranging from M1 to MN1.

The On Balance Volume Multi-Timeframe indicator for MT5 (OBV_MTF) utilizes a template and displays a panel on the chart. Its function, operation, and usage are identical to the Strength of Price Movement Multi Timeframe indicator (SPM_MTF) as detailed in the previous article. For a comprehensive guide on creating a multi-timeframe indicator, you can refer to the following resources: Strength of Price Movement Multi Timeframe indicator for MT5

Introduction of On-Balance Volume Multi-Time Frame (OBV_MTF) Indicator

The primary function of the On-Balance Volume Multi-Time Frame (OBV_MTF) indicator is to enhance the traditional On-Balance Volume (OBV) indicator by incorporating analysis across multiple time frames. This approach offers a more comprehensive view of market trends and volume dynamics.

USDCHFH1_OBV_MTF

Key Components and Functions:

  • 1. Volume Analysis: The OBV_MTF indicator utilizes trading volume as a critical parameter. By adding the volume on up days and subtracting the volume on down days, it creates a cumulative total that helps identify the strength of price movements.
  • 2. Multi-Time Frame Analysis: Unlike the traditional OBV, which operates on a single time frame, the OBV_MTF indicator aggregates volume data from multiple time frames. This broader perspective allows traders to detect longer-term trends that might be overlooked when only considering one time frame.
  • 3. Trend Confirmation: The OBV_MTF indicator aids in confirming trends by comparing OBV values across different time frames. A rising OBV across multiple time frames typically indicates strong buying pressure, while a falling OBV suggests selling pressure.
  • 4. Divergence Detection: The OBV_MTF indicator can identify divergences between price movements and volume. For instance, if prices are rising but OBV is falling across multiple time frames, it could signal a potential reversal.
  • 5. Customizable Parameters: This indicator often includes customizable settings, allowing traders to adjust time frames and other parameters to fit their trading strategies and preferences.
  • 6. Visual Representation: The OBV_MTF indicator provides visual cues, such as arrows and colors, to highlight significant changes in volume and trends, making it easier for traders to interpret the data.
  • 7. Buffering and Storage: It maintains buffers for open, high, low, close prices, and tickvolume data. It also keeps track of time and various display settings to ensure accurate and timely updates.

Before explaining the differences between the SPM_MTF indicator and the OBV_MTF indicator, it is important to note that all functions for running this multi-timeframe indicator are managed by the class program for the MTF indicator, which is contained in the MTF_Indi class.

Class for MTF indicator:


//+------------------------------------------------------------------+
//| class for MTF indicator                                          |
//+------------------------------------------------------------------+
class MTF_Indi
  {
   //---
   public:
   //--
   int               fbar;
   int               star,
                     tstar,
                     bstar;
   int               TNamex,
                     TNamexn,
                     TNamey1,
                     TNamey2,
                     TNamey3,
                     TNamey1n,
                     TNamey2n,
                     TNamey3n;
   int               tfxar;
   int               up,dw;
   int               tfhalf;
   int               maxbar;
   int               ttlbars;
   int               scaleX,
                     scaleA,
                     scaleY,
                     horizL1,
                     horizL2,
                     horizL3,
                     horizL4,
                     horizL5,
                     horizL6,
                     vertiL1,
                     vertiL2,
                     vertiL3,
                     vertiL4,
                     vertiL5,
                     vertiL6,
                     offsetX,
                     offsetY,
                     fontSize,
                     windchar,
                     windsize;
   int               corx,
                     cory,
                     txttf;
   int               curmin,
                     prvmin;
   int               corpos;
   int               pospos,
                     postop,
                     posbot;
   int               curAlert;
   int               prvAlert;
   //--
   long              CI;
   string            posisi,
                     sigpos,
                     indname,
                     msgText,
                     ObjName;
   string            cstar,
                     artop,
                     arbot;
   string            hName1,
                     hName2,
                     hName3;
   string            font_mode;
   bool              display;
   double            OPEN[],
                     HIGH[],
                     LOW[],
                     CLOSE[];
   long              VOLUME[];
   datetime          TIME[];
   datetime          cbartime;
   //--
   int               year,  // Year
                     mon,   // Month
                     day,   // Day
                     hour,  // Hour
                     min,   // Minutes
                     sec,   // Seconds
                     dow,   // Day of week (0-Sunday, 1-Monday, ... ,6-Saturday)
                     doy;   // Day number of the year (January 1st is assigned the number value of zero)
   //---- buffers
   double            PowerMove[];
   string            TFSc[];
   color             Arwcolor[];
   color             TColor;
   ENUM_TIMEFRAMES   TFId[];
   ENUM_BASE_CORNER  bcor;
   ENUM_ANCHOR_POINT ancp;
   //---
   //---
   //- Constructor
                     MTF_Indi(void):
                     year(0),
                     mon(1),
                     day(2),
                     hour(3),
                     min(4),
                     sec(5),
                     dow(6),
                     doy(7),
                     fbar(125),
                     star(181),
                     maxbar(3),
                     pospos(0),
                     postop(0),
                     posbot(1),
                     tstar(217),
                     bstar(218),
                     tfhalf(11),
                     scaleX(35),
                     scaleA(36),
                     scaleY(50),
                     offsetY(18),
                     offsetX(120),
                     fontSize(7),
                     cbartime(0),
                     posisi(""),
                     sigpos(""),
                     msgText(""),
                     curAlert(0),
                     prvAlert(0),
                     ttlbars(125),
                     windsize(12),
                     windchar(108),
                     CI(ChartID()),
                     display(false),
                     ObjName("OBV_"),
                     font_mode(FontsModel(f_model)),
                     cstar(CharToString((uchar)star)),
                     artop(CharToString((uchar)tstar)),
                     arbot(CharToString((uchar)bstar)),
                     indname(MQLInfoString(MQL_PROGRAM_NAME))
     {
     }
   //---
   //- Destructor
                    ~MTF_Indi(void)
     {
     }
   //---

Code Explanation of the MTF_Indi Class:

  • Class Definition:
    • The MTF_Indi class is designed to handle the Multi-Time Frame (MTF) indicator for trading analysis. This class encapsulates various properties and methods that are essential for analyzing and displaying trading data across multiple time frames.
  • Public Members:
    • The class defines numerous public member variables for storing values such as chart coordinates, alert settings, font details, and indicator data buffers. These variables are used throughout the class methods to perform various indicator functions.
  • Key Components and Functions:
    • 1. Public Data Members:
      • fbar: An integer representing the function bar for analysis.
      • star, tstar, bstar: Integers representing specific chart arrow or markers.
      • TNamex, TNamexn, TNamey1, TNamey2, TNamey3, TNamey1n, TNamey2n, TNamey3n: Integers for naming conventions and chart positions.
      • tfxar: An integer for time frame-related calculations.
      • up, dw: Integers for tracking upward and downward movements.
      • tfhalf: An integer representing the midpoint of a time frame.
      • maxbar: An integer for the maximum number of bars considered.
      • ttlbars: An integer for the total number of bars.
      • scaleX, scaleA, scaleY: Integers for scaling the chart in different dimensions.
      • horizL1, horizL2, horizL3, horizL4, horizL5, horizL6: Integers for horizontal line positions.
      • vertiL1, vertiL2, vertiL3, vertiL4, vertiL5, vertiL6: Integers for vertical line positions.
      • offsetX, offsetY: Integers for positional offsets.
      • fontSize: An integer for the font size used in chart displays.
      • windchar, windsize: Integers related to window characteristics.
      • corx, cory: Integers for x and y coordinates.
      • txttf: An integer for text time frame.
    • 2. Time and Alert Variables:
      • curmin, prvmin: Integers for current and previous minutes.
      • corpos: An integer for core position.
      • pospos, postop, posbot: Integers for positional tracking.
      • curAlert, prvAlert: Integers for current and previous alert states.
      • year, mon, day, hour, min, sec, dow, doy: Integers representing date and time components.
    • 3. String Members:
      • posisi, sigpos, indname, msgText, ObjName, cstar, artop, arbot, hName1, hName2, hName3, font_mode: Strings for various naming conventions, messages, and display texts.
    • 4. Boolean Member:
      • display: A boolean flag indicating whether the display is active.
    • 5. Data Buffers:
      • OPEN[], HIGH[], LOW[], CLOSE[]: Arrays for storing open, high, low, and close prices.
      • VOLUME[]: An array for storing trading volume data.
      • TIME[]: An array for storing time data.
      • cbartime: A datetime variable for bar time tracking.
      • PowerMove[]: An array for storing calculated power move values.
      • TFSc[]: An array for storing time frame string components.
      • Arwcolor[]: An array for storing arrow colors.
      • TColor: A variable for text color.
    • 6. Enumerations:
      • TFId[]: An array of enumeration type ENUM_TIMEFRAMES for different time frames.
      • bcor: An enumeration of type ENUM_BASE_CORNER for base corner positions.
      • ancp: An enumeration of type ENUM_ANCHOR_POINT for anchor points.
    • 7. Constructor: The constructor initializes the member variables with default values, ensuring that the indicator is set up correctly when instantiated.
      • MTF_Indi(void): The constructor initializes the class members with default values.
    • 8. Destructor: The destructor is defined but currently does not perform any specific actions.
      • ~MTF_Indi(void): The destructor is provided to clean up resources when the object is destroyed.

    As I explained above, the differences between the On Balance Volume Multi-Timeframe indicator (OBV_MTF) and the Strength of Price Movement Multi Timeframe indicator (SPM_MTF) lie in two key functions:

    1. UpdatePrice(ENUM_TIMEFRAMES xtf):

    • In the SPM_MTF indicator program, the UpdatePrice(ENUM_TIMEFRAMES xtf) function does not perform a TickVolume update because it is not necessary.

    2. OBVDirectionScan(const ENUM_TIMEFRAMES stf, int shift):

    • The SPM_MTF indicator program uses the PriceStrengthScan(const ENUM_TIMEFRAMES stf, int shift) function, which scans the price and compares the current bar's price to the previous bar's price in percentage terms.
    • Conversely, the OBV_MTF indicator scans the movement of the OBV value on the current bar and compares it with the OBV value on the previous bar in percentage terms.

    Additionally, the value of the On Balance Volume indicator in the OBV_MTF indicator is not obtained using the Indicator Handle. Instead, the structure and code of the On Balance Volume indicator only use the closing price plus or minus TickVolume, allowing the OBV indicator code to be easily written directly into the OBVDirectionScan() function.

    Explanation of the UpdatePrice() Function in the SPM_MTF Indicator.

    The UpdatePrice() function in the Strength of Price Movement Multi Timeframe (SPM_MTF) indicator is designed to update price data across various timeframes. Below is a detailed breakdown of each step within this function:

    
       //---
       void              UpdatePrice(ENUM_TIMEFRAMES xtf)
         {
          //-- Clear existing arrays
          ArrayFree(OPEN);
          ArrayFree(HIGH);
          ArrayFree(LOW);
          ArrayFree(CLOSE);
          ArrayFree(TIME);
          //-- Resize arrays
          ArrayResize(OPEN,maxbar,maxbar);
          ArrayResize(HIGH,maxbar,maxbar);
          ArrayResize(LOW,maxbar,maxbar);
          ArrayResize(CLOSE,maxbar,maxbar);
          ArrayResize(TIME,maxbar,maxbar);
          //-- Set arrays as series
          ArraySetAsSeries(OPEN,true);
          ArraySetAsSeries(HIGH,true);
          ArraySetAsSeries(LOW,true);
          ArraySetAsSeries(CLOSE,true);
          ArraySetAsSeries(TIME,true);
          //-- Initialize arrays
          ArrayInitialize(OPEN,0.0);
          ArrayInitialize(HIGH,0.0);
          ArrayInitialize(LOW,0.0);
          ArrayInitialize(CLOSE,0.0);
          ArrayInitialize(TIME,0);
          //-- Calculate the number of bars based on the timeframe
          int barx=PeriodSeconds(xtf)/60*maxbar;
          RefreshPrice(PERIOD_M1,maxbar);
          RefreshPrice(xtf,barx);
          //-- Copy price data from the specified symbol and timeframe
          int co=CopyOpen(Symbol(),xtf,0,maxbar,OPEN);
          int ch=CopyHigh(Symbol(),xtf,0,maxbar,HIGH);
          int cl=CopyLow(Symbol(),xtf,0,maxbar,LOW);
          int cc=CopyClose(Symbol(),xtf,0,maxbar,CLOSE);
          int ct=CopyTime(Symbol(),xtf,0,maxbar,TIME);
          //--
          return;
          //---
         } //-end UpdatePrice()
       //---
    

    Steps in the UpdatePrice() Function in the SPM_MTF Indicator:

    • 1. Clear Existing Arrays:
      • The ArrayFree() function is used to clear the existing data in the OPEN, HIGH, LOW, CLOSE, and TIME arrays.
    • 2. Resize Arrays:
      • ArrayResize() function adjusts the size of these arrays based on the maximum number of bars (maxbar).
    • 3, Set Arrays as Series:
      • ArraySetAsSeries() sets the arrays as series, meaning that the most recent element is at index 0.
    • 4. Initialize Arrays:
      • ArrayInitialize() initializes the array values. The initial values are set to 0.0 for prices and 0 for time.
    • 5. Calculate the Number of Bars:
      • int barx = PeriodSeconds(xtf) / 60 * maxbar; calculates the number of bars required based on the specified timeframe (xtf).
    • 6. Refresh Price Data:
      • RefreshPrice(PERIOD_M1, maxbar); and RefreshPrice(xtf, barx); refresh the price data for the M1 timeframe and the specified timeframe.
    • 7. Copy Price Data:
      • CopyOpen(), CopyHigh(), CopyLow(), CopyClose(), and CopyTime() functions copy the open, high, low, close, and time data into their respective arrays.

    This function helps update and manage price data for further analysis across multiple timeframes without the need for TickVolume updates, as they are not relevant to the SPM_MTF indicator.

    Explanation of the UpdatePrice() Function in the OBV_MTF Indicator.

    The UpdatePrice() function in the On Balance Volume Multi-Timeframe (OBV_MTF) indicator is designed to update price and TickVolume data across various timeframes. Below is a detailed breakdown of each step within this function:

    
       //---
       void              UpdatePrice(ENUM_TIMEFRAMES xtf)
         {
          maxbar=fbar;
          //-- Clear existing arrays
          ArrayFree(OPEN);
          ArrayFree(HIGH);
          ArrayFree(LOW);
          ArrayFree(CLOSE);
          ArrayFree(TIME);
          ArrayFree(VOLUME);
          //-- Resize arrays
          ArrayResize(OPEN,maxbar,maxbar);
          ArrayResize(HIGH,maxbar,maxbar);
          ArrayResize(LOW,maxbar,maxbar);
          ArrayResize(CLOSE,maxbar,maxbar);
          ArrayResize(TIME,maxbar,maxbar);
          ArrayResize(VOLUME,maxbar,maxbar);
          //-- Set arrays as series
          ArraySetAsSeries(OPEN,true);
          ArraySetAsSeries(HIGH,true);
          ArraySetAsSeries(LOW,true);
          ArraySetAsSeries(CLOSE,true);
          ArraySetAsSeries(TIME,true);
          ArraySetAsSeries(VOLUME,true);
          //-- Initialize arrays
          ArrayInitialize(OPEN,0.0);
          ArrayInitialize(HIGH,0.0);
          ArrayInitialize(LOW,0.0);
          ArrayInitialize(CLOSE,0.0);
          ArrayInitialize(TIME,0);
          ArrayInitialize(VOLUME,0);
          //-- Calculate the number of bars based on the timeframe
          int barx=PeriodSeconds(xtf)/60*maxbar;
          RefreshPrice(PERIOD_M1,maxbar);
          RefreshPrice(xtf,barx);
          //-- Copy price and TickVolume data from the specified symbol and timeframe
          int co=CopyOpen(Symbol(),xtf,0,maxbar,OPEN);
          int ch=CopyHigh(Symbol(),xtf,0,maxbar,HIGH);
          int cl=CopyLow(Symbol(),xtf,0,maxbar,LOW);
          int cc=CopyClose(Symbol(),xtf,0,maxbar,CLOSE);
          int ct=CopyTime(Symbol(),xtf,0,maxbar,TIME);
          int cv=CopyTickVolume(Symbol(),xtf,0,maxbar,VOLUME);
          //--
          return;
          //---
         } //-end UpdatePrice()
       //---
    

    Steps in the UpdatePrice() Function in the OBV_MTF Indicator:

    • 1. Set Maximum Bars:
      • maxbar = fbar; sets the maximum number of bars to be processed.
    • 2. Clear Existing Arrays:
      • The ArrayFree() function is used to clear the existing data in the OPEN, HIGH, LOW, CLOSE, TIME, and VOLUME arrays.
    • 3. Resize Arrays:
      • ArrayResize() adjusts the size of these arrays based on the maximum number of bars (maxbar).
    • 4. Set Arrays as Series:
      • ArraySetAsSeries() sets the arrays as series, meaning that the most recent element is at index 0.
    • 5. Initialize Arrays:
      • ArrayInitialize() initializes the array values. The initial values are set to 0.0 for prices and TickVolume, and 0 for time.
    • 6. Calculate the Number of Bars:
      • int barx = PeriodSeconds(xtf) / 60 * maxbar; calculates the number of bars required based on the specified timeframe (xtf).
    • 7. Refresh Price Data:
      • RefreshPrice(PERIOD_M1, maxbar); and RefreshPrice(xtf, barx); refresh the price data for the M1 timeframe and the specified timeframe.
    • 8. Copy Price and TickVolume Data:
      • CopyOpen(), CopyHigh(), CopyLow(), CopyClose(), CopyTime(), and CopyTickVolume() is functions copy the open, high, low, close, time, and TickVolume data into their respective arrays.

    Explanation of the PriceStrengthScan() Function in the SPM_MTF Indicator.

    The PriceStrengthScan() function in the Strength of Price Movement Multi Timeframe (SPM_MTF) indicator is designed to scan and compare price data to determine the direction of price movement in percentage terms. Below is a detailed breakdown of each step within this function:

    
    //---
       int               PriceStrengthScan(const ENUM_TIMEFRAMES stf,int shift) // Price Bar Direction in percent
         {
          //-- Initialize return value and direction indicators
          int ret=0;
          int rise=1,
              down=-1;
          //-- Set the number of bars to be scanned
          int br=shift+2;
          double res=0.0;
          double move=0.0;
          //-- Update price data for the specified timeframe
          UpdatePrice(stf);
          //-- Declare and resize the close price array
          double CL[];
          ArrayResize(CL,br,br);
          ArraySetAsSeries(CL,true);
          //-- Populate the close price array with data
          for(int x=br-1; x>=shift; x--)
             CL[x]=CLOSE[x];
          //-- Get the current and previous close prices
          double close_now  = CL[shift];
          double close_prev = CL[shift+1];
          //-- Calculate the percentage change in close prices
          if((close_now==0 || close_now==EMPTY_VALUE) || (close_prev==0 || close_prev==EMPTY_VALUE))
             res=0.0;
          else
             res=NormalizeDouble((close_now / close_prev * 100) - 100,3);
          //-- Adjust the result for percentage comparison
          res=NormalizeDouble(res*100,3); // because its value less than 1 then multiplied with 100.
          //-- Determine the direction of price movement
          if(res>move)
             ret=rise;
          if(res<move)
             ret=down;
          //--
          return(ret);
          //---
         } //-end PriceStrengthScan()
       //---
    

    Steps in the PriceStrengthScan() Function in the SPM_MTF Indicator:

    • 1. Initialization:
      • Initialize the return value (ret) to 0.
      • Define constants for rising and falling prices (rise and down).
    • 2. Set the Number of Bars to Scan:
      • Calculate the number of bars to scan (br) based on the shift parameter.
    • 3. Update Price Data:
      • Call the UpdatePrice(stf) function to update the price data for the specified timeframe (stf).
    • 4.Declare and Resize the Close Price Array:
      • Declare the CL array to store close prices.
      • Resize the CL array to accommodate the number of bars (br) and set it as a series.
    • 5. Populate the Close Price Array:
      • Use a loop to populate the CL array with close prices from the CLOSE array.
    • 6. Get the Current and Previous Close Prices:
      • Retrieve the current close price (close_now) and the previous close price (close_prev) from the CL array.
    • 7. Calculate the Percentage Change in Close Prices:
      • If either close_now or close_prev is 0 or empty, set res to 0.0.
      • Otherwise, calculate the percentage change in close prices and normalize the result.
    • 8. Adjust the Result for Percentage Comparison:
      • Multiply the result by 100 to adjust for percentage comparison.
    • 9. Determine the Direction of Price Movement:
      • Compare the result (res) with move to determine if the price is rising or falling.
      • Set the return value (ret) accordingly.

    This function helps determine the direction and strength of price movement by analyzing the percentage change in close prices across different timeframes.

    Explanation of the OBVDirectionScan() Function in the OBV_MTF Indicator.

    The OBVDirectionScan() function in the On Balance Volume Multi-Timeframe (OBV_MTF) indicator is designed to scan and compare the OBV values to determine the direction of OBV movement in percentage terms. Below is a detailed breakdown of each step within this function:

    
    //---
       int               OBVDirectionScan(const ENUM_TIMEFRAMES stf,int shift) // Scan OBV Direction
         {
          //-- Initialize return value and direction indicators
          int ret=0;
          int rise=1,
              down=-1;
          //-- Set the number of bars to be scanned
          int br=shift+2;
          double res=0.0;
          double move=0.0;
          //-- Update price data for the specified timeframe
          UpdatePrice(stf);
          //-- Declare and resize the OBV array
          double OBV[];
          ArrayResize(OBV,br,br);
          ArraySetAsSeries(OBV,true);
          //-- Retrieve volume and close prices
          double vol=(double)VOLUME[shift];
          double prev_close=CLOSE[shift+1];
          double curr_close=CLOSE[shift];
          //--- Fill OBV Buffer
          if(curr_close<prev_close)
             OBV[shift]=OBV[shift+1]-vol;
          else
            {
             if(curr_close>prev_close)
                OBV[shift]=OBV[shift+1]+vol;
             else
                OBV[shift]=OBV[shift+1];
            }
          //-- Get the current and previous OBV values
          double close_now  = OBV[shift];
          double close_prev = OBV[shift+1];
          //-- Calculate the percentage change in OBV values
          if((close_now==0 || close_now==EMPTY_VALUE) || (close_prev==0 || close_prev==EMPTY_VALUE))
             res=0.0;
          else
             res=NormalizeDouble((close_now / close_prev * 100) - 100,3);
          //-- Adjust the result for percentage comparison
          res=NormalizeDouble(res*100,3); // because its value less than 1 then multiplied with 100.
          //-- Determine the direction of OBV movement
          if(res>move)
             ret=rise;
          if(res<move)
             ret=down;
          //--
          return(ret);
          //---
         } //-end OBVDirectionScan()
       //---
    

    Steps in the OBVDirectionScan() Function in the OBV_MTF Indicator:

    • 1. Initialization:
      • Initialize the return value (ret) to 0.
      • Define constants for rising and falling OBV (rise and down).
    • 2. Set the Number of Bars to Scan:
      • Calculate the number of bars to scan (br) based on the shift parameter.
    • 3. Update Price Data:
      • Call the UpdatePrice(stf) function to update the price data for the specified timeframe (stf).
    • 4. Declare and Resize the OBV Array:
      • Declare the OBV array to store OBV values.
      • Resize the OBV array to accommodate the number of bars (br) and set it as a series.
    • 5. Retrieve Volume and Close Prices:
      • Get the volume (vol), previous close price (prev_close), and current close price (curr_close) from their respective arrays.
    • 6. Fill OBV Buffer:
      • Calculate the OBV value for the current bar based on the comparison of curr_close and prev_close.
      • Update the OBV array with the calculated OBV value.
    • 7. Get the Current and Previous OBV Values:
      • Retrieve the current OBV value (close_now) and the previous OBV value (close_prev) from the OBV array.
    • 8. Calculate the Percentage Change in OBV Values:
      • If either close_now or close_prev is 0 or empty, set res to 0.0.
      • Otherwise, calculate the percentage change in OBV values and normalize the result.
    • 9. Adjust the Result for Percentage Comparison:
      • Multiply the result by 100 to adjust for percentage comparison.
    • 10. Determine the Direction of OBV Movement:
      • Compare the result (res) with move to determine if the OBV is rising or falling.
      • Set the return value (ret) accordingly.

    This function helps determine the direction and strength of OBV movement by analyzing the percentage change in OBV values across different timeframes.

    The On Balance Volume Multi-Timeframe (OBV_MTF) indicator is designed for MetaTrader 5 (MT5). It calculates the strength of price movement as a percentage on each timeframe bar, assisting traders in analyzing market trends and making informed trading decisions.

    Key Functions of the OBV_MTF Indicator:

    • 1. Displays Multiple Timeframes: Allows traders to view various timeframes on a single chart, enhancing their ability to analyze market movements effectively.
    • 2. Identifies Market Trends: By viewing the indicator across multiple timeframes, traders can more easily identify both larger and smaller market trends.
    • 3. Supports Trading Decisions: Assists traders in making informed decisions on entering or exiting trades based on observed market conditions across different timeframes.

    Detailed Breakdown of Functions:

    • 1. OBV_MTF_Config(): Configures the multi-timeframe settings and prepares the indicator for use.
    • 2. PositionCore(): Sets up core position settings for the indicator elements on the chart.
    • 3. DrawOBVObject(): Draws various elements of the indicator on the chart.
    • 4. PanelPosChange(int inpos): Changes the panel position based on the input position value.
    • 5. UpdatePrice(ENUM_TIMEFRAMES xtf): Updates price data, including TickVolume arrays, for a given timeframe.
    • 6. RefreshPrice(ENUM_TIMEFRAMES xtf, int bars): Refreshes price data for a given timeframe and a specified number of bars.
    • 7. OBVDirectionScan(const ENUM_TIMEFRAMES stf, int shift): Scans and calculates the direction of the OBV indicator value in percentage terms.
    • 8. OBVMovementCalculation(int barCnt): Scans the direction of OBV indicator value for each timeframe, calculates how much it has moved up or down, and compares them to determine the signal strength.
    • 9. ThisTime(const int reqmode): Retrieves current time information based on the requested mode.
    • 10. Do_Alerts(string msg): Generates various types of alerts (print, alert, email, and notification) based on the provided message.
    • 11. FontsModel(int mode): Returns the font name based on the input mode.
    • 12. ChangeChartSymbol(string tf_name, ENUM_TIMEFRAMES stf): Changes the chart symbol and timeframe based on the input parameters.
    • 13. DisplayPanelButton(): Displays panel buttons on the chart.
    • 14. DisplayButtonClick(string actreq): Handles the creation and display of various buttons on the chart.
    • 15. DeletedOBVObject(): Deletes all objects related to the OBV_MTF indicator from the chart.
    • 16. strTF(ENUM_TIMEFRAMES period): Converts timeframe enumerations to string representations.
    • 17. getUninitReasonText(int reasonCode): Provides descriptive reasons for the uninitialization of the Expert Advisor (EA) based on the given reason code.
    • 18. WS(int width): Calculates the width scaling factor for buttons based on screen DPI.
    • 19. CreateButtonClick(): Creates a clickable button on the chart with specified properties.
    • 20. CreateArrowLabel(): Creates an arrow label on the chart with specified properties.
    • 21. CreateButtonTemplate(): Creates a rectangular button on the chart with specified properties.

    Main Functions of the Program:

    • 1. OnInit(): Initializes the custom indicator, configuring indicator buffers and setting indicator properties.
    • 2. OnDeinit(const int reason): Deinitializes the custom indicator, cleans up indicator objects, and prints the reason for deinitialization.
    • 3. OnCalculate(): Handles the main calculations for the indicator on every price tick, including scanning price strength and generating alerts.
    • 4. OnChartEvent(): Handles chart events, particularly button clicks, to manage the indicator's display and settings.

    Summary

    The OBV_MTF indicator is a comprehensive tool that provides traders with valuable insights into price movements across multiple timeframes. Its various functions ensure an enhanced trading experience by configuring, updating, and displaying the indicator's elements effectively. This helps traders identify market trends and make well-informed trading decisions.

    We hope that this article and the OBV_MTF or On Balance Volume Multi Timeframe indicator for MT5 program will be useful for traders in learning and generating new ideas, who can ultimately make money from home by trading forex.

    Thanks for reading this article.

    Please download the OBV_MTF indicator: On Balance Volume Multi Timeframe indicator

    If you are subscribed to my YouTube Channel, and would like to receive the source program of this article, please send a request via the Contact Us form page, and I will send it to your email, source code: On Balance Volume Multi Timeframe indicator

    Don't forget to stop by and subscribe to Forex Home Experts YouTube Channel:

    YouTube Channel: @ForexHomeExperts

    YouTube Playlist: @ForexHomeExperts YouTube Playlist

Monday, January 20, 2025

In this article I will discuss about making the Strength of Price Movement Multi Timeframe indicator for MT5, where the indicator will calculate price movement comparison in percent on each timeframe, in this case 21 timeframes from M1 to MN1.

Introduction to the Multi-Timeframe Indicator for MT5.

The multi-timeframe (MTF) indicator is an incredibly useful tool for forex traders. It allows traders to view market conditions from various timeframes on a single chart, enabling them to make more informed decisions based on a broader perspective of market trends.

Key Functions of the MTF Indicator.

  • 1. Displays Multiple Timeframes: This indicator displays various timeframes such as W1 (weekly),D1 (daily), H4 (4-hour), H1 (1-hour), and others on a single chart.
  • 2. Helps Identify Market Trends: By viewing the indicator from multiple timeframes, traders can more easily identify both larger and smaller market trends.
  • 3. Supports Trading Decisions: The indicator assists traders in making decisions to enter or exit trades based on market conditions observed across different timeframes.
USDCADH1_SPM_MTF_no_display

How the MTF Indicator Works.

The MTF indicator has a unique ability to display the condition, position, and movement of indicators and/or prices across 21 timeframes within a single user-selected timeframe. In other words, users can choose one timeframe to display information from all 21 timeframes available in MT5.

For instance, on an H1 chart, this indicator can display data from the W1, D1, H4, and 18 other timeframes. This allows traders to gain a comprehensive view of market conditions.

Additionally, the indicator uses the OnChartEvent function from MT5. This feature enables users to select the display panel with a single click to place it above the chart, below the chart, or hide it completely. The indicator will only show an arrow button for navigating the panel display, making it easier and more flexible to use.

Benefits of Using the MTF Indicator.

  • 1. Early Trend Recognition:
    • Traders can detect trend changes earlier by viewing indicators from smallest to larger timeframes.
  • 2. Better Decision-Making:
    • By viewing market conditions from multiple timeframes, traders can make more accurate and data-driven decisions.

Strategies Using Multi-Timeframe Indicator.

Utilizing a multi-timeframe (MTF) indicator in technical analysis allows traders to gain a broader and deeper perspective on market movements across different timeframes. Here are some strategies based on the key functions of the MTF indicator:

  • 1. Displays Multiple Timeframes:
    • Strategy: Leverage the indicator's ability to display multiple timeframes on a single chart to identify trends and price movements more clearly.
    • Implementation: For instance, if the weekly timeframe shows an uptrend, traders can look for buy signals on the daily or hourly timeframe when the price pulls back to major support levels.
  • 2. Helps Identify Market Trends:
    • Strategy: Use the indicator to view both larger and smaller market trends simultaneously to get a more comprehensive picture.
    • Implementation: If the daily timeframe indicates a strong uptrend, traders can use the 4-hour or 1-hour timeframe to look for buy confirmations when the price approaches support levels or when momentum indicators signal a price reversal.
  • 3. Supports Trading Decisions:
    • Strategy: Utilize information from various timeframes to make more informed trading decisions, whether it’s entering or exiting positions.
    • Implementation: If the 4-hour timeframe shows starting to see a decline in price movements, traders can verify this signal by checking the 1-hourtimeframe. If the 1-hour timeframe also shows starting to see a decline in price movements, this could be a strong signal to sell.
  • 4. Indicator Alert:
    • In addition, this indicator will also provide alerts when there is a change in position, condition and strength of price movement on all timeframes.
    • In this case, the calculation of the strength of price movement is calculated based on how many timeframes show an increase and how many timeframes show a decrease.
      • If the timeframes that show an increase are more than the timeframes that show a decrease in price, then the indicator will give a buy signal, and vice versa.

By applying these strategies, traders can leverage the advantages of the multi-timeframe indicator to optimize trading decisions and manage risk more effectively. Always remember to backtest and evaluate your strategies periodically to ensure their effectiveness under various market conditions.

  • 1. Introduction:
    • The SPM_MTF indicator, or Strength of Price Movement Multi Timeframe indicator for MT5 which is calculated price movement comparison in percent on each timeframe.
  • 2. Key Functions of the SPM_MTF Indicator:
    • Displays Multiple Timeframes:
      • The indicator displays various timeframes on a single chart, helping traders to analyze market trends and movements effectively.
    • Helps Identify Market Trends:
      • By viewing the indicator across multiple timeframes, traders can identify both larger and smaller market trends more easily.
    • Supports Trading Decisions:
      • The indicator assists traders in making informed decisions to enter or exit trades based on market conditions observed across different timeframes.
  • 3. The Multi-Timeframe Indicator Program:
  • 
    //+------------------------------------------------------------------+
    //|                                                      SPM_MTF.mq5 |
    //|        Copyright 2025, Roberto Jacobs (3rjfx) ~ Date: 2025-01-08 |
    //|                              https://www.mql5.com/en/users/3rjfx |
    //+------------------------------------------------------------------+
    #property copyright "Copyright 2025, Roberto Jacobs (3rjfx) ~ Date: 2025-01-08"
    #property link      "https://www.mql5.com/en/users/3rjfx"
    #property version   "1.00"
    #property description "SPM_MTF is the Strength of Price Movement Multi Timeframe indicator for MT5"
    #property description "which is calculated price movement comparison in percent on each timeframe."
    //---
    #property indicator_chart_window
    #property indicator_plots   1
    #property indicator_buffers 1
    //---
    //--
    enum YN
      {
       No,
       Yes
      };
    //--
    enum fonts
      {
       Verdana,
       Bodoni_MT_Black
      };
    //--
    //---
    input group   "====   Indicator Color and Font   ===="
    input color              ArrowUp = clrMediumSeaGreen; // Arrow Up Color
    input color              ArrowDn = clrDeepPink;       // Arrow Down Color
    input color              NTArrow = clrGold;           // Arrow No Signal
    input fonts              f_model = Bodoni_MT_Black;   // Select Font Model
    input group   "====  Input parameters for alerts  ===="
    input YN                  alerts = Yes;               // Display Alerts Pop-up on Chart (Yes) or (No)
    input YN           UseEmailAlert = No;                // Email Alert (Yes) or (No)
    input YN           UseSendnotify = No;                // Send Notification (Yes) or (No)
    //---
    //---------//
    
    • Code Overview:
      • The code is written in MQL5, a language used for creating custom indicators, scripts, and automated trading strategies on the MetaTrader 5 platform.
  • 4. Main Functions in the Program:
    • Function Display Timeframes:
      • This function is responsible for displaying multiple timeframes on a single chart, allowing traders to see various periods simultaneously.
    • Function Identify Trends:
      • This function helps to identify market trends by analyzing price movements across different timeframes.
    • Function Support Trading Decisions:
      • This function supports trading decisions by providing signals based on multi-timeframe analysis.
  • 5. Code Explanation:
    • Input Parameters:
      • The code defines several input parameters for customizing the indicator's appearance and alert settings, including arrow colors, font selection, and alert options.
    • Enums:
      • Two enumerations are defined: YN (Yes/No) for boolean-like input parameters and fonts for font selection.
    • Input Groups:
      • Input parameters are organized into groups for better clarity. The first group focuses on the indicator's color and font settings, while the second group handles alert settings.
    • Alerts:
      • Options for displaying alerts on the chart, sending email alerts, and sending notifications are included, providing flexibility in how traders receive alerts.
  • Example Implementation:
    • Indicator Properties:
      • The indicator's properties are defined at the beginning of the code, including copyright information, version, description, and the number of plots and buffers.
    • Indicator Buffers:
      • One buffer is declared for storing indicator values.

Class for MTF indicator:


//+------------------------------------------------------------------+
//| class for MTF indicator                                          |
//+------------------------------------------------------------------+
class MTF_Indi
  {
   //---
   public:
   //--
   int               fbar;
   int               star,
                     tstar,
                     bstar;
   int               TNamex,
                     TNamexn,
                     TNamey1,
                     TNamey2,
                     TNamey3,
                     TNamey1n,
                     TNamey2n,
                     TNamey3n;
   int               tfxar;
   int               up,dw;
   int               tfhalf;
   int               maxbar;
   int               ttlbars;
   int               scaleX,
                     scaleA,
                     scaleY,
                     horizL1,
                     horizL2,
                     horizL3,
                     horizL4,
                     horizL5,
                     horizL6,
                     vertiL1,
                     vertiL2,
                     vertiL3,
                     vertiL4,
                     vertiL5,
                     vertiL6,
                     offsetX,
                     offsetY,
                     fontSize,
                     windchar,
                     windsize;
   int               corx,
                     cory,
                     txttf;
   int               curmin,
                     prvmin;
   int               corpos;
   int               pospos,
                     postop,
                     posbot;
   int               curAlert;
   int               prvAlert;
   //--
   long              CI;
   string            posisi,
                     sigpos,
                     indname,
                     msgText,
                     ObjName;
   string            cstar,
                     artop,
                     arbot;
   string            hName1,
                     hName2,
                     hName3;
   string            font_mode;
   bool              display;
   double            OPEN[],
                     HIGH[],
                     LOW[],
                     CLOSE[];
   datetime          TIME[];
   datetime          cbartime;
   //--
   int               year,  // Year
                     mon,   // Month
                     day,   // Day
                     hour,  // Hour
                     min,   // Minutes
                     sec,   // Seconds
                     dow,   // Day of week (0-Sunday, 1-Monday, ... ,6-Saturday)
                     doy;   // Day number of the year (January 1st is assigned the number value of zero)
   //---- buffers
   double            PowerMove[];
   string            TFSc[];
   color             Arwcolor[];
   color             TColor;
   ENUM_TIMEFRAMES   TFId[];
   ENUM_BASE_CORNER  bcor;
   ENUM_ANCHOR_POINT ancp;
   //---
   //---
   //- Constructor
                     MTF_Indi(void):
                     year(0),
                     mon(1),
                     day(2),
                     hour(3),
                     min(4),
                     sec(5),
                     dow(6),
                     doy(7),
                     fbar(15),
                     star(181),
                     maxbar(3),
                     pospos(0),
                     postop(0),
                     posbot(1),
                     tstar(217),
                     bstar(218),
                     tfhalf(11),
                     scaleX(35),
                     scaleA(36),
                     scaleY(50),
                     offsetY(18),
                     offsetX(120),
                     fontSize(7),
                     cbartime(0),
                     posisi(""),
                     sigpos(""),
                     msgText(""),
                     curAlert(0),
                     prvAlert(0),
                     ttlbars(125),
                     windsize(12),
                     windchar(108),
                     CI(ChartID()),
                     display(false),
                     ObjName("SPM_"),
                     font_mode(FontsModel(f_model)),
                     cstar(CharToString((uchar)star)),
                     artop(CharToString((uchar)tstar)),
                     arbot(CharToString((uchar)bstar)),
                     indname(MQLInfoString(MQL_PROGRAM_NAME))
     {
     }
   //---
   //- Destructor
                    ~MTF_Indi(void)
     {
     }
   //---

Code Explanation of the MTF_Indi Class:

  • Class Definition:
    • The MTF_Indi class encapsulates the functionality of the multi-timeframe indicator.
  • Public Members:
    • Various public member variables are declared to store different attributes and settings related to the indicator, such as timeframe coordinates, alert settings, font size, and display parameters.
  • Constructor:
    • The constructor initializes the member variables with default values, ensuring that the indicator is set up correctly when instantiated.
  • Destructor:
    • The destructor is defined but currently does not perform any specific actions.
  • Member Variables:
    • The class defines numerous member variables for storing values such as chart coordinates, alert settings, font details, and indicator data buffers.
    • These variables are used throughout the class methods to perform various indicator functions.

Main Functions in the Program:

  • Function SPM_MTF_Config():
    • This function is responsible for configuring the multi-timeframe settings and preparing the indicator for use.
  • Code Explanation of the SPM_MTF_Config Function:
    • Timeframe Enumeration:
      • The function defines an array TFIx of different timeframes that the indicator will use.
      • 
        ENUM_TIMEFRAMES TFIx[]= {PERIOD_M1,PERIOD_M2,PERIOD_M3,PERIOD_M4,PERIOD_M5,PERIOD_M6,PERIOD_M10,PERIOD_M12,PERIOD_M15,
                                 PERIOD_M20,PERIOD_M30,PERIOD_H1,PERIOD_H2,PERIOD_H3,PERIOD_H4,PERIOD_H6,PERIOD_H8,PERIOD_H12,
                                 PERIOD_D1,PERIOD_W1,PERIOD_MN1};
        
      • Array Resizing:
        • The arrays TFId and Arwcolor are resized to match the number of timeframes defined.
        • 
                tfxar=ArraySize(TFIx);
                ArrayResize(TFId,tfxar,tfxar);
                ArrayResize(Arwcolor,tfxar,tfxar);
                ArrayCopy(TFId,TFIx,0,0,WHOLE_ARRAY);
          
    • Timeframe Labels:
      • An array TFxc of timeframe labels (e.g., "M1", "M2", "M3") is defined, and TFSc is resized and populated accordingly.
      • 
        //--
        string TFxc[]= {"M1","M2","M3","M4","M5","M6","M10","M12","M15","M20","M30","H1",
                        "H2","H3","H4","H6","H8","H12","D1","W1","MN1"}; // 21 Timeframes
        //--
        ArrayResize(TFSc,tfxar,tfxar);
        ArrayCopy(TFSc,TFxc,0,0,WHOLE_ARRAY);
        //--
        
    • Supporting Functions:
      • The function calls several other functions to complete the configuration:
        • DeletedSPMObject(): Deletes any previous objects related to the indicator.
        • CalculationStrength(25): Initializes or recalculates the strength of price movement with a given parameter.
        • PositionCore(): Sets up the core position settings for the indicator.
    • Display Conditional:
      • If the display flag is true, the DrawSPMObject() function is called to draw the indicator objects on the chart.
      • 
        if(display)
          DrawSPMObject();
        

Function PositionCore():

This function is responsible for setting up the core position settings for the indicator, including the display and layout of various elements on the chart.


   //---
   void              PositionCore(void)
     {
      corpos=pospos;
      if(corpos>-1)
        {
         if(corpos==postop)
           {
            bcor=CORNER_LEFT_UPPER;
            ancp=ANCHOR_CENTER;
            corx=155;
            cory=13;
            txttf=45;
            horizL1=8;
            horizL2=-5;
            horizL3=8;
            horizL4=-5;
            horizL5=11;
            horizL6=10;
            vertiL1=39;
            vertiL2=18;
            vertiL3=69;
            vertiL4=48;
            vertiL5=52;
            vertiL6=67;
            TNamex=554;
            TNamexn=562;
            TNamey1=30;
            TNamey2=46;
            TNamey3=62;
            TNamey1n=38;
            TNamey2n=54;
            TNamey3n=70;
            hName1="S";
            hName2="P";
            hName3="M";
            //--
            DisplayButtonClick("cstar");
            DisplayButtonClick("arbot");
            //--
           }
         if(corpos==posbot)
           {
            bcor=CORNER_LEFT_LOWER;
            ancp=ANCHOR_CENTER;
            corx=155;
            cory=74;
            txttf=45;
            horizL1=8;
            horizL2=-5;
            horizL3=8;
            horizL4=-5;
            horizL5=11;
            horizL6=10;
            vertiL1=34;
            vertiL2=29;
            vertiL3=65;
            vertiL4=59;
            vertiL5=49;
            vertiL6=61;
            TNamex=554;
            TNamexn=562;
            TNamey1=13;
            TNamey2=46;
            TNamey3=62;
            TNamey1n=18;
            TNamey2n=33;
            TNamey3n=49;
            hName1="M";
            hName2="P";
            hName3="S";
            //--
            DisplayButtonClick("cstar");
            DisplayButtonClick("artop");
            //--
           }
         display=true;
        }
     }
   //---
  • Code Explanation of the PositionCore Function:
    • Position Setup:
      • The function begins by assigning the corpos variable the value of pospos.
    • Upper Position Settings:
      • If corpos equals postop, several parameters are set to position elements in the upper left corner of the chart.
    • Lower Position Settings:
      • If corpos equals posbot, several parameters are set to position elements in the lower left corner of the chart.
    • Display Activation:
      • The display flag is set to true, indicating that the setup for displaying elements on the chart is complete.

Function DrawSPMObject(void):

This function is responsible for drawing the various elements of the indicator on the chart.


//---
void              DrawSPMObject(void)
  {
    //--   CreateButtonTemplate(CI,ObjName+"Template",397,66,STYLE_SOLID,9,BORDER_RAISED,clrMistyRose,clrLavenderBlush,clrWhite,bcor,corx,cory,true);
      for(int x=0; x<tfhalf; x++)
        {
    CreateArrowLabel(CI,ObjName+"_win_arrow_"+string(x),CharToString((uchar)windchar),"Wingdings",windsize,Arwcolor[x],bcor,
                             txttf+horizL1+(x*scaleX)+offsetX+x,vertiL1,true,"Arrow_"+TFSc[x]);
         CreateButtonClick(CI,TFSc[x],27,15,font_mode,fontSize,BORDER_FLAT,TFSc[x],clrBurlyWood,clrSilver,clrBlue,
                              bcor,txttf+horizL2+(x*scaleA)+offsetX,vertiL2,true,
                              "Change Timeframe to : "+TFSc[x]);
        }
      for(int x=tfhalf, x2=0; x<tfxar; x++, x2++)
        {       CreateArrowLabel(CI,ObjName+"_win_arrow_"+string(x),CharToString((uchar)windchar),"Wingdings",windsize,Arwcolor[x],bcor,
                             txttf+horizL3+(x2*scaleX)+offsetX+x2,vertiL3,true,"Arrow_"+TFSc[x]);
         CreateButtonClick(CI,TFSc[x],27,15,font_mode,fontSize,BORDER_FLAT,TFSc[x],clrBurlyWood,clrSilver,clrBlue,
                              bcor,txttf+horizL4+(x2*scaleA)+offsetX,vertiL4,true,
                              "Change Timeframe to : "+TFSc[x]);
         //--
         if(x==20)
           {
            int arrowChar=TColor==ArrowUp ? 200 : TColor==ArrowDn ? 202 : windchar;
            CreateArrowLabel(CI,ObjName+"_tfx_arrow_"+string(x+1),"Move",font_mode,fontSize,clrBlue,bcor,
                                519+horizL5,vertiL5,true,"Move");
            CreateArrowLabel(CI,ObjName+"_win_arrow_"+string(x+1),CharToString((uchar)arrowChar),"Wingdings",15,TColor,bcor,
                                522+horizL6,vertiL6,true,"Arrow Price Movement");
           }
        }
      DisplayButtonClick("X");
CreateButtonTemplate(CI,ObjName+"TemplateName1",17,15,STYLE_SOLID,1,BORDER_FLAT,clrMistyRose,clrLavenderBlush,clrWhite,bcor,TNamex,TNamey1,true);     CreateButtonTemplate(CI,ObjName+"TemplateName2",17,15,STYLE_SOLID,1,BORDER_FLAT,clrMistyRose,clrLavenderBlush,clrWhite,bcor,TNamex,TNamey2,true);      CreateButtonTemplate(CI,ObjName+"TemplateName3",17,15,STYLE_SOLID,1,BORDER_FLAT,clrMistyRose,clrLavenderBlush,clrWhite,bcor,TNamex,TNamey3,true);
      CreateArrowLabel(CI,ObjName+"_name1",hName1,font_mode,fontSize+1,clrBlue,bcor,TNamexn,TNamey1n,true,hName1);
      CreateArrowLabel(CI,ObjName+"_name2",hName2,font_mode,fontSize+1,clrBlue,bcor,TNamexn,TNamey2n,true,hName2);
      CreateArrowLabel(CI,ObjName+"_name3",hName3,font_mode,fontSize+1,clrBlue,bcor,TNamexn,TNamey3n,true,hName3);
      //--
      if(corpos==postop)
        {
          DisplayButtonClick("cstar");
          DisplayButtonClick("arbot");
        }
      if(corpos==posbot)
        {
          DisplayButtonClick("cstar");
          DisplayButtonClick("artop");
        }
      //--
      return;
      //---
     } //-end DrawSPMObject()
//---
  • Code Explanation of the DrawSPMObject Function:
    • Template Creation:
      • A button template is created as a base for other objects.
      • 
        CreateButtonTemplate(CI,ObjName+"Template",397,66,STYLE_SOLID,9,BORDER_RAISED,clrMistyRose,clrLavenderBlush,clrWhite,bcor,corx,cory,true);
        
    • Upper Timeframe Labels and Buttons:
      • The function iterates over the first half of the timeframes to create arrow labels and buttons.
      • 
        for(int x=0; x<tfhalf; x++)
                {
        CreateArrowLabel(CI,ObjName+"_win_arrow_"+string(x),CharToString((uchar)windchar),"Wingdings",windsize,Arwcolor[x],bcor,
                                     txttf+horizL1+(x*scaleX)+offsetX+x,vertiL1,true,"Arrow_"+TFSc[x]);
                 CreateButtonClick(CI,TFSc[x],27,15,font_mode,fontSize,BORDER_FLAT,TFSc[x],clrBurlyWood,clrSilver,clrBlue,
                                      bcor,txttf+horizL2+(x*scaleA)+offsetX,vertiL2,true,
                                      "Change Timeframe to : "+TFSc[x]);
                }
        
    • Lower Timeframe Labels and Buttons:
      • The function iterates over the remaining timeframes to create arrow labels and buttons.
      •           
        for(int x=tfhalf, x2=0; x<tfxar; x++, x2++)
                {
        CreateArrowLabel(CI,ObjName+"_win_arrow_"+string(x),CharToString((uchar)windchar),"Wingdings",windsize,Arwcolor[x],bcor,
                                     txttf+horizL3+(x2*scaleX)+offsetX+x2,vertiL3,true,"Arrow_"+TFSc[x]);
                 CreateButtonClick(CI,TFSc[x],27,15,font_mode,fontSize,BORDER_FLAT,TFSc[x],clrBurlyWood,clrSilver,clrBlue,
                                      bcor,txttf+horizL4+(x2*scaleA)+offsetX,vertiL4,true,
                                      "Change Timeframe to : "+TFSc[x]);
                 // Special case for the last timeframe
                 if(x==20)
                   {
                    int arrowChar=TColor==ArrowUp ? 200 : TColor==ArrowDn ? 202 : windchar;
                    CreateArrowLabel(CI,ObjName+"_tfx_arrow_"+string(x+1),"Move",font_mode,fontSize,clrBlue,bcor,
                                        519+horizL5,vertiL5,true,"Move");
                    CreateArrowLabel(CI,ObjName+"_win_arrow_"+string(x+1),CharToString((uchar)arrowChar),"Wingdings",15,TColor,bcor,
                                        522+horizL6,vertiL6,true,"Arrow Price Movement");
                   }
        
    • Button Templates and Labels:
      • Additional button templates and labels are created for the indicator's display.
      • 
              DisplayButtonClick("X");
        CreateButtonTemplate(CI,ObjName+"TemplateName1",17,15,STYLE_SOLID,1,BORDER_FLAT,clrMistyRose,clrLavenderBlush,clrWhite,bcor,TNamex,TNamey1,true); CreateButtonTemplate(CI,ObjName+"TemplateName2",17,15,STYLE_SOLID,1,BORDER_FLAT,clrMistyRose,clrLavenderBlush,clrWhite,bcor,TNamex,TNamey2,true);
        CreateButtonTemplate(CI,ObjName+"TemplateName3",17,15,STYLE_SOLID,1,BORDER_FLAT,clrMistyRose,clrLavenderBlush,clrWhite,bcor,TNamex,TNamey3,true);
              CreateArrowLabel(CI,ObjName+"_name1",hName1,font_mode,fontSize+1,clrBlue,bcor,TNamexn,TNamey1n,true,hName1);
              CreateArrowLabel(CI,ObjName+"_name2",hName2,font_mode,fontSize+1,clrBlue,bcor,TNamexn,TNamey2n,true,hName2);
              CreateArrowLabel(CI,ObjName+"_name3",hName3,font_mode,fontSize+1,clrBlue,bcor,TNamexn,TNamey3n,true,hName3);
              //--
        
    • Display Conditional:
      • Depending on the corpos value, specific buttons are displayed.
      • 
              if(corpos==postop)
                {
                  DisplayButtonClick("cstar");
                  DisplayButtonClick("arbot");
                }
              if(corpos==posbot)
                {
                  DisplayButtonClick("cstar");
                  DisplayButtonClick("artop");
                }
        

Function PanelPosChange(int inpos)::

This function is responsible for changing the position of the panel based on the input position value.


   void              PanelPosChange(int inpos)
     {
      corpos=inpos;
      //--
      if(inpos>=0)
        {
         if(inpos==postop)
           {
            bcor=CORNER_LEFT_UPPER;
            ancp=ANCHOR_CENTER;
            corx=155;
            cory=13;
            txttf=45;
            horizL1=8;
            horizL2=-5;
            horizL3=8;
            horizL4=-5;
            horizL5=11;
            horizL6=10;
            vertiL1=39;
            vertiL2=18;
            vertiL3=69;
            vertiL4=48;
            vertiL5=52;
            vertiL6=67;
            TNamex=554;
            TNamexn=562;
            TNamey1=30;
            TNamey2=46;
            TNamey3=62;
            TNamey1n=38;
            TNamey2n=54;
            TNamey3n=70;
            hName1="S";
            hName2="P";
            hName3="M";
            //--
            DisplayButtonClick("cstar");
            DisplayButtonClick("arbot");
            //--
           }
         if(inpos==posbot)
           {
            bcor=CORNER_LEFT_LOWER;
            ancp=ANCHOR_CENTER;
            corx=155;
            cory=74;
            txttf=45;
            horizL1=8;
            horizL2=-5;
            horizL3=8;
            horizL4=-5;
            horizL5=11;
            horizL6=10;
            vertiL1=34;
            vertiL2=29;
            vertiL3=65;
            vertiL4=59;
            vertiL5=49;
            vertiL6=61;
            TNamex=554;
            TNamexn=562;
            TNamey1=25;
            TNamey2=41;
            TNamey3=57;
            TNamey1n=18;
            TNamey2n=33;
            TNamey3n=49;
            hName1="M";
            hName2="P";
            hName3="S";
            //--
            DisplayButtonClick("cstar");
            DisplayButtonClick("artop");
            //--
           }
         display=true;
        }
      //---
     }
   //---
  • Code Explanation of the PanelPosChange Function:
    • Position Setup:
      • The function begins by assigning the corpos variable the value of inpos.
      • 
        corpos=inpos;
        
    • Upper Position Settings:
      • If inpos equals postop, several parameters are set to position elements in the upper left corner of the chart.
      • 
                 if(inpos==postop)
                   {
                    bcor=CORNER_LEFT_UPPER;
                    ancp=ANCHOR_CENTER;
                    corx=155;
                    cory=13;
                    txttf=45;
                    horizL1=8;
                    horizL2=-5;
                    horizL3=8;
                    horizL4=-5;
                    horizL5=11;
                    horizL6=10;
                    vertiL1=39;
                    vertiL2=18;
                    vertiL3=69;
                    vertiL4=48;
                    vertiL5=52;
                    vertiL6=67;
                    TNamex=554;
                    TNamexn=562;
                    TNamey1=30;
                    TNamey2=46;
                    TNamey3=62;
                    TNamey1n=38;
                    TNamey2n=54;
                    TNamey3n=70;
                    hName1="S";
                    hName2="P";
                    hName3="M";
                    //--
                    DisplayButtonClick("cstar");
                    DisplayButtonClick("arbot");
                    //--
                   }
        
    • Lower Position Settings:
      • If inpos equals posbot, several parameters are set to position elements in the lower left corner of the chart.
      • 
                 if(inpos==posbot)
                   {
                    bcor=CORNER_LEFT_LOWER;
                    ancp=ANCHOR_CENTER;
                    corx=155;
                    cory=74;
                    txttf=45;
                    horizL1=8;
                    horizL2=-5;
                    horizL3=8;
                    horizL4=-5;
                    horizL5=11;
                    horizL6=10;
                    vertiL1=34;
                    vertiL2=29;
                    vertiL3=65;
                    vertiL4=59;
                    vertiL5=49;
                    vertiL6=61;
                    TNamex=554;
                    TNamexn=562;
                    TNamey1=25;
                    TNamey2=41;
                    TNamey3=57;
                    TNamey1n=18;
                    TNamey2n=33;
                    TNamey3n=49;
                    hName1="M";
                    hName2="P";
                    hName3="S";
                    //--
                    DisplayButtonClick("cstar");
                    DisplayButtonClick("artop");
                    //--
                   }
        
    • Display Activation:
      • The display flag is set to true, indicating that the setup for displaying elements on the chart is complete.
      • 
                 display=true;
                }
        

Function UpdatePrice(ENUM_TIMEFRAMES xtf):

This function is responsible for updating the price data arrays for a given timeframe.


   //---
   void              UpdatePrice(ENUM_TIMEFRAMES xtf)
     {
      //--
      ArrayFree(OPEN);
      ArrayFree(HIGH);
      ArrayFree(LOW);
      ArrayFree(CLOSE);
      ArrayFree(TIME);
      //--
      ArrayResize(OPEN,maxbar,maxbar);
      ArrayResize(HIGH,maxbar,maxbar);
      ArrayResize(LOW,maxbar,maxbar);
      ArrayResize(CLOSE,maxbar,maxbar);
      ArrayResize(TIME,maxbar,maxbar);
      //--
      ArraySetAsSeries(OPEN,true);
      ArraySetAsSeries(HIGH,true);
      ArraySetAsSeries(LOW,true);
      ArraySetAsSeries(CLOSE,true);
      ArraySetAsSeries(TIME,true);
      //--
      ArrayInitialize(OPEN,0.0);
      ArrayInitialize(HIGH,0.0);
      ArrayInitialize(LOW,0.0);
      ArrayInitialize(CLOSE,0.0);
      ArrayInitialize(TIME,0);
      //--
      int barx=PeriodSeconds(xtf)/60*maxbar;
      RefreshPrice(PERIOD_M1,maxbar);
      RefreshPrice(xtf,barx);
      //--
      int co=CopyOpen(Symbol(),xtf,0,maxbar,OPEN);
      int ch=CopyHigh(Symbol(),xtf,0,maxbar,HIGH);
      int cl=CopyLow(Symbol(),xtf,0,maxbar,LOW);
      int cc=CopyClose(Symbol(),xtf,0,maxbar,CLOSE);
      int ct=CopyTime(Symbol(),xtf,0,maxbar,TIME);
      //--
      return;
      //---
     } //-end UpdatePrice()
   //---
  • Code Explanation of the UpdatePrice Function:
    • Array Initialization:
      • The function begins by freeing any existing arrays for open, high, low, close prices, and time.
      • 
              //--
              ArrayFree(OPEN);
              ArrayFree(HIGH);
              ArrayFree(LOW);
              ArrayFree(CLOSE);
              ArrayFree(TIME);
              //--
        
    • Array Resizing:
      • The arrays are then resized to hold the maximum number of bars (maxbar).
      • 
              //--
              ArrayResize(OPEN,maxbar,maxbar);
              ArrayResize(HIGH,maxbar,maxbar);
              ArrayResize(LOW,maxbar,maxbar);
              ArrayResize(CLOSE,maxbar,maxbar);
              ArrayResize(TIME,maxbar,maxbar);
              //--
        
    • Array Series Setting:
      • The arrays are set to behave as series, where index 0 is the most recent data.
      • 
              //--
              ArraySetAsSeries(OPEN,true);
              ArraySetAsSeries(HIGH,true);
              ArraySetAsSeries(LOW,true);
              ArraySetAsSeries(CLOSE,true);
              ArraySetAsSeries(TIME,true);
              //--
        
    • Array Initialization:
      • The arrays are initialized to default values to clear any old data.
      • 
              //--
              ArrayInitialize(OPEN,0.0);
              ArrayInitialize(HIGH,0.0);
              ArrayInitialize(LOW,0.0);
              ArrayInitialize(CLOSE,0.0);
              ArrayInitialize(TIME,0);
              //--
        
    • Price Data Refresh:
      • The function calculates the number of bars based on the specified timeframe (xtf) and calls the RefreshPrice function for both the M1 timeframe and the specified timeframe.
      • 
              //--
              int barx=PeriodSeconds(xtf)/60*maxbar;
              RefreshPrice(PERIOD_M1,maxbar);
              RefreshPrice(xtf,barx);
              //--
        
    • Copying Price Data:
      • The function copies the open, high, low, close prices, and time data into the respective arrays for the specified timeframe.
      • 
              //--
              int co=CopyOpen(Symbol(),xtf,0,maxbar,OPEN);
              int ch=CopyHigh(Symbol(),xtf,0,maxbar,HIGH);
              int cl=CopyLow(Symbol(),xtf,0,maxbar,LOW);
              int cc=CopyClose(Symbol(),xtf,0,maxbar,CLOSE);
              int ct=CopyTime(Symbol(),xtf,0,maxbar,TIME);
              //--
        

Function RefreshPrice(ENUM_TIMEFRAMES xtf, int bars):

This function is responsible for refreshing the price data for a given timeframe and a specified number of bars.

  • Code Explanation of the RefreshPrice Function:
    • Array Declaration:
      • The function begins by declaring an array parray of type MqlRates to store the price data.
      • 
        MqlRates parray[];
        
    • Array Series Setting:
      • The array is set to behave as a series, where index 0 is the most recent data.
      • 
        ArraySetAsSeries(parray,true);
        
    • Copying Price Data:
      • The CopyRates function is called to copy the price data for the specified symbol and timeframe into the parray array. The number of bars tocopy is specified by the bars parameter.
      • 
        int copied=CopyRates(Symbol(),xtf,0,bars,parray);
        

Function PriceStrengthScan(const ENUM_TIMEFRAMES stf, int shift):

This function calculates the direction of the price bar in percentage terms.

  • Code Explanation of the PriceStrengthScan Function:
    • Variable Initialization:
      • The function starts by initializing several variables to store return values, rise/fall indicators, and intermediate results.
      • 
              //--
              int ret=0;
              int rise=1,
                  down=-1;
              //--
              int br=shift+2;
              double res=0.0;
              double move=0.0;
        
    • Update Price Data:
      • The UpdatePrice function is called to refresh the price data for the specified timeframe.
      • 
        UpdatePrice(stf);
        
    • Array Initialization:
      • An array CL is resized and set as a series to store close prices.
      • 
              //--
              double CL[];
              ArrayResize(CL,br,br);
              ArraySetAsSeries(CL,true);
              //--
        
    • Populating Close Prices:
      • The close prices are copied into the CL array.
      • 
              //--
              for(int x=br-1; x>=shift; x--)
                 CL[x]=CLOSE[x];
              //--
        
    • Calculating Price Strength:
      • The function calculates the percentage change between the current and previous close prices.
      • 
              //--
              double close_now  = CL[shift];
              double close_prev = CL[shift+1];
              //--
              if((close_now==0 || close_now==EMPTY_VALUE) || (close_prev==0 || close_prev==EMPTY_VALUE))
                 res=0.0;
              else
                 res=NormalizeDouble((close_now / close_prev * 100) - 100,3);
              res=NormalizeDouble(res*100,3); // because its value less than 1 then multiplied with 100.
              //--
        
    • Determining Price Direction:
      • The function sets the return value based on whether the price has risen or fallen.
      • 
              //--
              if(res>move)
                 ret=rise;
              if(res<move)
                 ret=down;
              //--
        
    • Returning the Result:
      • The function returns the calculated direction of the price bar.
      • 
              //--
              return(ret);
              //---
        

Function CalculationStrength(int barCnt):

This function scans the direction of movement of each timeframe and calculates the strength of price movement in percentage terms.

  • Code Explanation of the CalculationStrength Function:
    • Array Initialization:
      • The function begins by resizing and setting the PowerMove array as a series to store the calculated strength values.
      • 
              //--
              ArrayResize(PowerMove,barCnt,barCnt);
              ArraySetAsSeries(PowerMove,true);
              //--
        
    • Main Calculation Loop:
      • The function loops through each bar in the specified count (barCnt) and initializes counters for up and down movements.
      • 
        for(int i=barCnt-1; i>=0; i--)
          {
           up=0;
           dw=0;
           //--
        
    • Inner Loop for Timeframes:
      • Within the main loop, the function iterates over each timeframe defined in tfxar and initializes arrow colors and power move values.
      • 
        for(int x=0; x<tfxar; x++)
          {
           Arwcolor[x]=NTArrow;
           PowerMove[i]=0.0;
           int PPM=PriceStrengthScan(TFId[x],0);
        
    • Price Strength Scan:
      • The PriceStrengthScan function is called to determine the price movement direction for each timeframe.
      • 
        int PPM=PriceStrengthScan(TFId[x],0);
        
    • Updating Counters and Arrow Colors:
      • The function updates the up and down counters and sets the appropriate arrow colors based on the result of PriceStrengthScan.
      •           
        if(PPM>0)
          {
            up++;
            Arwcolor[x]=ArrowUp;
          }
        if(PPM<0)
          {
            dw++;
            Arwcolor[x]=ArrowDn;
          }         
        
    • Final Calculation and Alert Setting:
      • After iterating through all timeframes, the function sets the PowerMove value and alert color based on the counters' comparison.
      • 
        if(x==tfxar-1)
          {
           if(up>dw+1)
             {
              PowerMove[i]=1.0;
              TColor=ArrowUp;
              curAlert=1;
             }
        if(dw>up+1)
             {
              PowerMove[i]=-1.0;
              TColor=ArrowDn;
              curAlert=-1;
             }
        

Function ThisTime(const int reqmode):

This function retrieves the current time information based on the requested mode.

  • Code Explanation of the ThisTime Function:
    • Variable Initialization:
      • The function starts by declaring a MqlDateTime structure and an integer to store the time value.
      • 
        //--
        MqlDateTime tm;
        TimeCurrent(tm);
        int valtm=0;
        //--
        
    • Switch Statement for Time Retrieval:
    • The function uses a switch statement to assign the appropriate time component based on the reqmode parameter.
    • 
            //--
            switch(reqmode)
              {
               case 0:
                  valtm=tm.year;
                  break;        // Return Year
               case 1:
                  valtm=tm.mon;
                  break;        // Return Month
               case 2:
                  valtm=tm.day;
                  break;        // Return Day
               case 3:
                  valtm=tm.hour;
                  break;        // Return Hour
               case 4:
                  valtm=tm.min;
                  break;        // Return Minutes
               case 5:
                  valtm=tm.sec;
                  break;        // Return Seconds
               case 6:
                  valtm=tm.day_of_week;
                  break;        // Return Day of week (0-Sunday, 1-Monday, ... ,6-Saturday)
               case 7:
                  valtm=tm.day_of_year;
                  break;        // Return Day number of the year (January 1st is assigned the number value of zero)
              }
            //--
      
    • Return the Time Value:
      • The function returns the time value based on the selected mode.
      • 
        return(valtm);
        

Function Do_Alerts(string msg):

This function handles the generation of various types of alerts (print, alert, email, and notification) based on the provided message.

  • Code Explanation of the Do_Alerts Function:
    • Print Alert:
      • The function begins by printing the message along with the current symbol, timeframe, and time.
      • 
        //--
        Print("--- "+Symbol()+","+strTF(Period())+": "+msg+
              "\n--- at: ",TimeToString(TimeCurrent(),TIME_DATE|TIME_MINUTES));
        //--
        
    • Chart Alert:
      • If alerts are enabled, it triggers an alert with the same message details.
      • 
        //--
        if(alerts==Yes)
          {
            Alert("--- "+Symbol()+","+strTF(Period())+": "+msg+
                  "--- at: ",TimeToString(TimeCurrent(),TIME_DATE|TIME_MINUTES));
          }
        //--
        
    • Email Alert:
      • If email alerts are enabled, it sends an email with the message details.
      • 
        //--
        if(UseEmailAlert==Yes)
           SendMail(indname,"--- "+Symbol()+" "+strTF(Period())+": "+msg+
                    "\n--- at: "+TimeToString(TimeCurrent(),TIME_DATE|TIME_MINUTES));
        //--
        
    • Notification Alert:
      • If notifications are enabled, it sends a notification with the message details.
      • 
        //--
        if(UseSendnotify==Yes)
           SendNotification(Symbol()+"--- "+Symbol()+" "+strTF(Period())+": "+msg+
                            "\n--- at: "+TimeToString(iTime(Symbol(),0,0),TIME_DATE|TIME_MINUTES));
        //--
        

Function FontsModel(int mode):

This function returns the font name based on the input mode.

  • Code Explanation of the FontsModel Function:
    • Variable Initialization:
      • The function starts by declaring a string variable str_font to store the font name.
      • 
        string str_font;
        
    • Switch Statement for Font Selection:
      • The function uses a switch statement to assign the appropriate font name based on the mode parameter.
      • 
        switch(mode)
          {
            case 0:
               str_font="Verdana";
               break;
            case 1:
               str_font="Bodoni MT Black";
               break;
          }
        //--
        
    • Return the Font Name:
      • The function returns the font name based on the selected mode.
      • 
        return(str_font);
        

Function ChangeChartSymbol(string tf_name, ENUM_TIMEFRAMES stf):

This function changes the chart's symbol and timeframe based on the input parameters.

  • Code Explanation of the ChangeChartSymbol Function:
    • Unpress Button:
      • The function starts by unpressing the button associated with the given timeframe name (tf_name).
      • 
        //--- unpress the button
        ObjectSetInteger(CI,tf_name,OBJPROP_STATE,false);
        ObjectSetInteger(CI,tf_name,OBJPROP_ZORDER,0);
        
    • Delete Existing Objects:
      • The function calls DeletedSPMObject() to delete any existing objects related to the indicator.
      • 
        DeletedSPMObject();
        
    • Change Panel Position:
      • The function updates the panel position by calling PanelPosChange(corpos).
      • 
        PanelPosChange(corpos);
        
    • Set Chart Symbol and Timeframe:
      • The chart's symbol and timeframe are updated using ChartSetSymbolPeriod.
      • 
        ChartSetSymbolPeriod(CI,Symbol(),stf);
        
    • Redraw Objects:
      • If the display flag is true, the function calls DrawSPMObject() to redraw the indicator objects on the chart.
      • 
        if(display)
          DrawOBVObject();
        
    • Redraw Chart:
      • Finally, the function calls ChartRedraw(CI) to refresh the chart display.
      • 
        ChartRedraw(CI);
        

Function DisplayPanelButton():

This function is responsible for displaying the panel buttons on the chart, allowing users to interact with the indicator.

  • Code Explanation of the DisplayPanelButton Function:
    • Deleting Existing Objects:
      • The function starts by deleting any existing panel buttons (cstar,artop, and arbot) to ensure a clean slate.
      • 
        //--
        ObjectDelete(CI,cstar);
        ObjectDelete(CI,artop);
        ObjectDelete(CI,arbot);
        //--
        
    • Creating Panel Buttons:
      • The function then creates three buttons:
        • cstar Button:
          • This button is created with the label "Open Panel Indicator" and is positioned at the top-right corner of the chart.
          • 
            CreateButtonClick(CI,cstar,20,20,"Wingdings",13,BORDER_FLAT,cstar,clrWhite,clrWhite,TColor,CORNER_RIGHT_UPPER,25,40,true,"Open Panel Indicator");
            
        • artop Button:
          • This button is created with the label "Change Panel to Top" and is positioned at the top-right corner of the chart.
          • 
            CreateButtonClick(CI,artop,18,18,"Wingdings",11,BORDER_FLAT,artop,clrWhite,clrWhite,clrGreen,CORNER_RIGHT_UPPER,24,20,true,"Change Panel to Top");
            
        • arbot Button:
          • This button is created with the label "Change Panel to Bottom" and is positioned at the top-right corner of the chart.
          • 
            CreateButtonClick(CI,arbot,18,18,"Wingdings",11,BORDER_FLAT,arbot,clrWhite,clrWhite,clrGreen,CORNER_RIGHT_UPPER,24,62,true,"Change Panel to Bottom");
            
    • Redrawing the Chart:
      • The function calls ChartRedraw(CI) to refresh the chart and display the newly created buttons.
      • 
        ChartRedraw(CI);
        

Function DisplayButtonClick(string actreq):

This function handles the creation and display of various buttons on the chart based on the action requested.

  • Code Explanation of the DisplayButtonClick Function:
    • Conditional Button Creation:
      • The function uses a series of if statements to determine which button to create based on the actreq parameter:
        • cstar Button:
          • This button is created with the label "Open Panel Indicator" and is positioned at the top-right corner of the chart.
          • 
            if(actreq=="cstar")
               CreateButtonClick(CI,cstar,20,20,"Wingdings",13,BORDER_FLAT,cstar,clrWhite,clrWhite,TColor,CORNER_RIGHT_UPPER,25,40,true,"Open Panel Indicator");
            
        • artop Button:
          • This button is created with the label "Change Panel to Top" and is positioned at the top-right corner of the chart.
          • 
            if(actreq=="artop")
               CreateButtonClick(CI,artop,18,18,"Wingdings",11,BORDER_FLAT,artop,clrWhite,clrWhite,clrGreen,CORNER_RIGHT_UPPER,24,20,true,"Change Panel to Top");
            
        • arbot Button:
          • This button is created with the label "Change Panel to Bottom" and is positioned at the top-right corner of the chart.
          • 
            if(actreq=="arbot")
               CreateButtonClick(CI,arbot,18,18,"Wingdings",11,BORDER_FLAT,arbot,clrWhite,clrWhite,clrGreen,CORNER_RIGHT_UPPER,24,62,true,"Change Panel to Bottom");
            
        • x Button:
      • arbot Button:
        • This button is created with the label "Close Panel" and is positioned based on the indicator's settings.
        • 
          if(actreq=="X")
             CreateButtonClick(CI,"X",17,15,"Arial Black",fontSize,BORDER_FLAT,"X",clrWhite,clrWhite,clrRed,bcor,txttf-7+(11*scaleA)+offsetX,cory,true,"Close Panel");
          
    • Redrawing the Chart:
      • The function calls ChartRedraw(CI) to refresh the chart and display the newly created buttons.
      • 
        ChartRedraw(CI);
        

Function DeletedSPMObject():

This function is responsible for deleting all objects related to the SPM_MTF indicator from the chart.

  • Code Explanation of the DeletedSPMObject Function:
    • Loop Through Objects:
      • The function starts by looping through all objects on the chart in reverse order.
      • 
        string name;
        for(int i=ObjectsTotal(CI,-1,-1)-1; i>=0; i--)
          {
            name=ObjectName(CI,i,-1,-1);
        
    • Delete Matching Objects:
      • If the object name contains the ObjName prefix, it is deleted.
      • 
        if(StringFind(name,ObjName,0)>-1)
           ObjectDelete(CI,name);
        
    • Delete Timeframe Specific Objects:
      • Within the outer loop, the function also checks for objects related to specific timeframes and deletes them if found.
      • 
        for(int x=0; x<tfxar; x++)
          {
           if(StringFind(name,TFSc[x],0)>-1)
              ObjectDelete(CI,name);
          }
        
    • Delete Common Objects:
      • Finally, the function deletes common panel buttons ("X",cstar,artop,arbot).
      • 
        //--
        ObjectDelete(CI,"X");
        ObjectDelete(CI,cstar);
        ObjectDelete(CI,artop);
        ObjectDelete(CI,arbot);
        

Function strTF(ENUM_TIMEFRAMES period):

This function returns the string representation of the given timeframe period.

  • Code Explanation of the strTF Function:
    • Variable Initialization:
      • The function starts by declaring a string variable intf to store the string representation of the timeframe.
      • 
        string intf="";
        
    • Switch Statement for Timeframe Conversion:
      • The function uses a switch statement to assign the appropriate string value to intf based on the period parameter.
      • 
              switch(period)
                {
                 //--
                 case PERIOD_M1:
                   {intf="M1";  break;}
                 case PERIOD_M2:
                   {intf="M2";  break;}
                 case PERIOD_M3:
                   {intf="M3";  break;}
                 case PERIOD_M4:
                   {intf="M4";  break;}
                 case PERIOD_M5:
                   {intf="M5";  break;}
                 case PERIOD_M6:
                   {intf="M6";  break;}
                 case PERIOD_M10:
                   {intf="M10"; break;}
                 case PERIOD_M12:
                   {intf="M12"; break;}
                 case PERIOD_M15:
                   {intf="M15"; break;}
                 case PERIOD_M20:
                   {intf="M20"; break;}
                 case PERIOD_M30:
                   {intf="M30"; break;}
                 case PERIOD_H1:
                   {intf="H1";  break;}
                 case PERIOD_H2:
                   {intf="H2";  break;}
                 case PERIOD_H3:
                   {intf="H3";  break;}
                 case PERIOD_H4:
                   {intf="H4";  break;}
                 case PERIOD_H6:
                   {intf="H6";  break;}
                 case PERIOD_H8:
                   {intf="H8";  break;}
                 case PERIOD_H12:
                   {intf="H12"; break;}
                 case PERIOD_D1:
                   {intf="D1";  break;}
                 case PERIOD_W1:
                   {intf="W1";  break;}
                 case PERIOD_MN1:
                   {intf="MN1"; break;}
                    //--
                }
        
    • Return the Timeframe String:
      • The function returns the string representation of the given timeframe.
      • 
        return(intf);
        

Function getUninitReasonText(int reasonCode):

This function returns a text description of the reason why the expert advisor (EA) was uninitialized based on the provided reason code.

  • Code Explanation of the getUninitReasonText Function:
    • Variable Initialization:
      • The function starts by declaring a string variable text to store the reason description.
      • 
        string text="";
        
    • Switch Statement for Reason Conversion:
      • The function uses a switch statement to assign the appropriate description to text based on the reasonCode parameter.
      • 
              //--
              switch(reasonCode)
                {
                 case REASON_PROGRAM:
                    text="The EA has stopped working calling by remove function.";
                    break;
                 case REASON_REMOVE:
                    text="Program "+__FILE__+" was removed from chart";
                    break;
                 case REASON_RECOMPILE:
                    text="Program recompiled.";
                    break;
                 case REASON_CHARTCHANGE:
                    text="Symbol or timeframe was changed";
                    break;
                 case REASON_CHARTCLOSE:
                    text="Chart was closed";
                    break;
                 case REASON_PARAMETERS:
                    text="Input-parameter was changed";
                    break;
                 case REASON_ACCOUNT:
                    text="Account was changed";
                    break;
                 case REASON_TEMPLATE:
                    text="New template was applied to chart";
                    break;
                 case REASON_INITFAILED:
                    text="The OnInit() handler returned a non-zero value.";
                    break;
                 case REASON_CLOSE:
                    text="Terminal closed.";
                    break;
                 default:
                    text="Another reason";
                    break;
                }
              //--
        
    • Return the Reason Text:
      • The function returns the text description of the uninitialization reason.
      • 
        return text;
        

Function WS(int width):

This function calculates the width scaling factor for wide buttons based on the screen's DPI.

  • Code Explanation of the WS Function:
    • Variable Initialization:
      • The function starts by declaring two integer variables res and reswidth to store the result and intermediate width respectively.
      • 
        int res=0;
        int reswidth=0;
        
    • Scaling Factor Calculation:
      • The scaling factor is calculated using the screen's DPI obtained from TerminalInfoInteger.
      • 
        //-- Calculating the scaling factor wide button on a screen
        int scale_factor=(TerminalInfoInteger(TERMINAL_SCREEN_DPI));
        
    • Width Calculation:
      • The function calculates the width in screen points for standard monitors with DPI=96 and scales it accordingly.
      • 
        //-- Use of the scaling factor
        reswidth=(width * scale_factor) / 96;
        res=(int)NormalizeDouble(reswidth*1.25,0);
        
    • Return the Scaled Width:
      • The function returns the scaled width value.
      • 
        return(res);
        

Function CreateButtonClick():

This function creates a clickable button on the chart with the specified properties.


//---
void              CreateButtonClick(long   chartid,
                                    string button_name,
                                    int    button_x_size,
                                    int    button_y_size,
                                    string button_font_model,
                                    int    button_font_size,
                                    int    button_border,
                                    string button_name_text,
                                    color  button_bord_color,
                                    color  button_bg_color,
                                    color  button_color,
                                    int    button_corner,
                                    int    button_xdist,
                                    int    button_ydist,
                                    bool   button_hidden,
                                    string tooltip)
  {
   //--
   ObjectCreate(chartid,button_name,OBJ_BUTTON,0,0,0); // create button
   ObjectSetInteger(chartid,button_name,OBJPROP_XSIZE,WS(button_x_size));
   ObjectSetInteger(chartid,button_name,OBJPROP_YSIZE,WS(button_y_size));
   ObjectSetString(chartid,button_name,OBJPROP_TEXT,button_name_text);
   ObjectSetString(chartid,button_name,OBJPROP_FONT,button_font_model);
   ObjectSetInteger(chartid,button_name,OBJPROP_FONTSIZE,WS(button_font_size));
   ObjectSetInteger(chartid,button_name,OBJPROP_BORDER_TYPE,WS(button_border));
   ObjectSetInteger(chartid,button_name,OBJPROP_BORDER_COLOR,button_bord_color);
   ObjectSetInteger(chartid,button_name,OBJPROP_BGCOLOR,button_bg_color);
   ObjectSetInteger(chartid,button_name,OBJPROP_COLOR,button_color);
   ObjectSetInteger(chartid,button_name,OBJPROP_ANCHOR,ancp);
   ObjectSetInteger(chartid,button_name,OBJPROP_CORNER,button_corner);
   ObjectSetInteger(chartid,button_name,OBJPROP_XDISTANCE,WS(button_xdist));
   ObjectSetInteger(chartid,button_name,OBJPROP_YDISTANCE,WS(button_ydist));
   ObjectSetInteger(chartid,button_name,OBJPROP_HIDDEN,button_hidden);
   ObjectSetString(chartid,button_name,OBJPROP_TOOLTIP,tooltip);
   ChartRedraw(chartid);
   //--
   return;
   //---
  } //-end CreateButtonClick()
//---
  • Code Explanation of the CreateButtonClick Function:
    • Button Creation:
      • The function starts by creating a button object on the chart using ObjectCreate.
      • 
        ObjectCreate(chartid,button_name,OBJ_BUTTON,0,0,0); // create button
        
    • Setting Button Properties:
      • The function sets various properties for the button, such as size, font, border, colors, position, and tooltip.
      • 
              ObjectSetInteger(chartid,button_name,OBJPROP_XSIZE,WS(button_x_size));
              ObjectSetInteger(chartid,button_name,OBJPROP_YSIZE,WS(button_y_size));
              ObjectSetString(chartid,button_name,OBJPROP_TEXT,button_name_text);
              ObjectSetString(chartid,button_name,OBJPROP_FONT,button_font_model);
              ObjectSetInteger(chartid,button_name,OBJPROP_FONTSIZE,WS(button_font_size));
              ObjectSetInteger(chartid,button_name,OBJPROP_BORDER_TYPE,WS(button_border));
              ObjectSetInteger(chartid,button_name,OBJPROP_BORDER_COLOR,button_bord_color);
              ObjectSetInteger(chartid,button_name,OBJPROP_BGCOLOR,button_bg_color);
              ObjectSetInteger(chartid,button_name,OBJPROP_COLOR,button_color);
              ObjectSetInteger(chartid,button_name,OBJPROP_ANCHOR,ancp);
              ObjectSetInteger(chartid,button_name,OBJPROP_CORNER,button_corner);
              ObjectSetInteger(chartid,button_name,OBJPROP_XDISTANCE,WS(button_xdist));
              ObjectSetInteger(chartid,button_name,OBJPROP_YDISTANCE,WS(button_ydist));
              ObjectSetInteger(chartid,button_name,OBJPROP_HIDDEN,button_hidden);
              ObjectSetString(chartid,button_name,OBJPROP_TOOLTIP,tooltip);
        
    • Redrawing the Chart:
      • The function calls ChartRedraw(chartid) to refresh the chart and display the newly created button.
      • 
        ChartRedraw(chartid);
        

Function CreateArrowLabel():

This function creates an arrow label on the chart with the specified properties.

  • Code Explanation of the CreateArrowLabel Function:
    • Deleting Existing Object:
      • The function starts by deleting any existing object with the same label name.
      • 
        ObjectDelete(chart_id,lable_name);
        
    • Creating the Label:
      • The function attempts to create a new label object. If the creation fails, it prints an error message and returns false.
      • 
        //--
        if(!ObjectCreate(chart_id,lable_name,OBJ_LABEL,0,0,0,0,0)) // create Label
          {
           Print(__FUNCTION__, ": failed to create \"Arrow Label\" sign! Error code = ",GetLastError());
           return(false);
          }
        //--
        
    • Setting Label Properties:
      • The function sets various properties for the label, such as text, font, size, color, position, and tooltip.
      • 
        //--
        ObjectSetString(chart_id,lable_name,OBJPROP_TEXT,label_text);
        ObjectSetString(chart_id,lable_name,OBJPROP_FONT,font_model);
        ObjectSetInteger(chart_id,lable_name,OBJPROP_FONTSIZE,WS(font_size));
        ObjectSetInteger(chart_id,lable_name,OBJPROP_COLOR,label_color);
        ObjectSetInteger(chart_id,lable_name,OBJPROP_CORNER,chart_corner);
        ObjectSetInteger(chart_id,lable_name,OBJPROP_ANCHOR,ancp);
        ObjectSetInteger(chart_id,lable_name,OBJPROP_XDISTANCE,WS(x_cor));
        ObjectSetInteger(chart_id,lable_name,OBJPROP_YDISTANCE,WS(y_cor));
        ObjectSetInteger(chart_id,lable_name,OBJPROP_HIDDEN,price_hidden);
        //--
        
    • Returning Successful Execution:
      • The function returns true to indicate successful execution.
      • 
        //-- successful execution
        return(true);
        

Function CreateButtonTemplate():

This function creates a rectangular button on the chart with the specified properties.

  • Code Explanation of the CreateButtonTemplate Function:
    • Button Creation:
      • The function starts by creating a rectangle label object on the chart using ObjectCreate.
      • 
        ObjectCreate(chartid,obj_name,OBJ_RECTANGLE_LABEL,0,0,0); // create Rectangle Label
        
    • Setting Button Properties:
      • The function sets various properties for the button, such as size, style, width, border, colors, position, and visibility.
      • 
        ObjectSetInteger(chartid,obj_name,OBJPROP_XSIZE,WS(x_size));
        ObjectSetInteger(chartid,obj_name,OBJPROP_YSIZE,WS(y_size));
        ObjectSetInteger(chartid,obj_name,OBJPROP_STYLE,style);
        ObjectSetInteger(chartid,obj_name,OBJPROP_WIDTH,WS(width));
        ObjectSetInteger(chartid,obj_name,OBJPROP_BORDER_TYPE,WS(border));
        ObjectSetInteger(chartid,obj_name,OBJPROP_BORDER_COLOR,bordcolor);
        ObjectSetInteger(chartid,obj_name,OBJPROP_BGCOLOR,bgcolor);
        ObjectSetInteger(chartid,obj_name,OBJPROP_COLOR,objcolor);
        ObjectSetInteger(chartid,obj_name,OBJPROP_CORNER,corner);
        ObjectSetInteger(chartid,obj_name,OBJPROP_XDISTANCE,WS(x_dist));
        ObjectSetInteger(chartid,obj_name,OBJPROP_YDISTANCE,WS(y_dist));
        ObjectSetInteger(chartid,obj_name,OBJPROP_HIDDEN,hidden);
        
    • Redrawing the Chart:
      • The function calls ChartRedraw(chartid) to refresh the chart and display the newly created button.
      • 
        ChartRedraw(chartid);
        

Function OnInit():

This is the custom indicator initialization function that is executed when the indicator is first loaded onto the chart.

  • Code Explanation of the OnInit Function:
    • Indicator Buffers Mapping:
      • The function starts by calling the SPM_MTF_Config method of the "mi" object to configure the multi-timeframe settings.
      • 
        mi.SPM_MTF_Config();
        
    • SetIndexBuffer:
      • The buffer for the PowerMove indicator data is set.
      • 
        SetIndexBuffer(0,mi.PowerMove,INDICATOR_DATA);
        
    • PlotIndexSetString:
      • The label for the plot index is set to "Move."
      • 
        PlotIndexSetString(0,PLOT_LABEL,"Move");
        
    • IndicatorSetString:
      • The short name of the indicator is set using the indname property of the "mi" object.
      • 
        IndicatorSetString(INDICATOR_SHORTNAME,mi.indname);
        
    • IndicatorSetInteger:
      • The number of digits displayed for the indicator values is set to 2.
      • 
        IndicatorSetInteger(INDICATOR_DIGITS,2);
        
    • Return Initialization Success:
      • The function returns INIT_SUCCEEDED to indicate that the initialization was successful.
      • 
        return(INIT_SUCCEEDED);
        

Function OnDeinit(const int reason):

This is the custom indicator deinitialization function that is executed when the indicator is removed from the chart or the platform is closed.

  • Code Explanation of the OnDeinit Function:
    • Clearing Comments:
      • The function starts by clearing any comments on the chart.
      • 
        Comment("");
        
    • Printing Deinitialization Reason:
      • The function prints the reason for deinitialization by calling the getUninitReasonText method of the "mi" object.
      • 
        Print(mi.getUninitReasonText(reason));
        
    • Deleting Indicator Objects:
      • The function calls DeletedSPMObject to delete all objects related to the SPM_MTF indicator from the chart.
      • 
        mi.DeletedSPMObject();
        
    • Redrawing the Chart:
      • The function calls ChartRedraw to refresh the chart and reflect the changes.
      • 
        ChartRedraw(mi.CI);
        
    • Returning from the Function:
      • The function ends with a return statement.
      • 
        return;
        

Function OnCalculate():

This function is executed on every new price tick and handles the main calculations for the indicator.

  • Code Explanation of the OnCalculate Function:
    • Resetting Last Error:
      • The function starts by resetting the last error using ResetLastError.
      • 
        ResetLastError();
        
    • Calculating the Limit:
      • The function calculates the limit for the number of bars to process.
      • 
        //--
        int limit;
        limit=rates_total-prev_calculated;
        if(prev_calculated>0)
           limit++;
        if(limit>mi.ttlbars)
           limit=mi.ttlbars;
        if(limit-3<=1)
           limit=3;
        //--
        
    • Calculating Strength:
      • The function calls CalculationStrength to calculate the strength of price movement.
      • 
        mi.CalculationStrength(limit);
        
    • Alert Logic:
      • If alerts are enabled, the function checks for changes in price movement direction and triggers alerts accordingly.
      • 
        //--
        mi.CalculationStrength(limit);
        //--
        if(alerts==Yes||UseEmailAlert==Yes||UseSendnotify==Yes)
          {
            mi.curmin=mi.ThisTime(mi.min);
            if(mi.curmin!=mi.prvmin && mi.curAlert==1 && mi.curAlert!=mi.prvAlert)
              {
                string AlertTxt="The strength of the price movement appears to be Rise.";
                mi.Do_Alerts(AlertTxt);
                mi.prvAlert=mi.curAlert;
                mi.prvmin=mi.curmin;
              }
            if(mi.curmin!=mi.prvmin && mi.curAlert==-1 && mi.curAlert!=mi.prvAlert)
              {
                string AlertTxt="The strength of the price movement appears to be Down.";
                mi.Do_Alerts(AlertTxt);
                mi.prvAlert=mi.curAlert;
                mi.prvmin=mi.curmin;
              }
          }
        //--
        
    • Drawing Objects:
      • If the display flag is true, the function calls DrawSPMObject to redraw the indicator objects on the chart.
      • 
        if(mi.display)
          mi.DrawSPMObject();
        
    • Returning the Total Number of Rates:
      • The function returns the total number of rates for the next call.
      • 
        return(rates_total);
        

Function OnChartEvent():

This function handles chart events, particularly button clicks, to manage the indicator's display and settings.

  • Code Explanation of the OnChartEvent Function:
    • Resetting Last Error:
      • The function starts by resetting the last error using ResetLastError.
      • 
        ResetLastError();
        
    • Handling Object Click Events:
      • The function checks if the event ID is CHARTEVENT_OBJECT_CLICK and proceeds to handle specific button clicks based on sparam.
      • 
        if(id==CHARTEVENT_OBJECT_CLICK) {...}
        
    • Handling "X" Button Click:
      • If the "X" button is clicked, the function deletes the SPM objects, unpresses the button, sets the display flag to false, and displays the panelbutton.
      • 
        //--- if "X" button is click
        if(sparam=="X")
          {
           mi.DeletedSPMObject();
           //--- unpress the button
           ObjectSetInteger(mi.CI,"X",OBJPROP_STATE,false);
           ObjectSetInteger(mi.CI,"X",OBJPROP_ZORDER,0);
           //--
           mi.display=false;
           ObjectDelete(mi.CI,"X");
           mi.DisplayPanelButton();
          }
        
    • Handling "cstar" Button Click:
      • If the "cstar" button is clicked, the function deletes the SPM objects, displays the panel button, unpresses the button, sets the display flag to true, and draws the SPM object.
      • 
        //--- if "cstar" button is click
        if(sparam==mi.cstar)
          {
           mi.DeletedSPMObject();
           mi.DisplayPanelButton();
           //--- unpress the button
           ObjectSetInteger(mi.CI,mi.cstar,OBJPROP_STATE,false);
           ObjectSetInteger(mi.CI,mi.cstar,OBJPROP_ZORDER,0);
           if(!mi.display)
              mi.display=true;
           if(mi.corpos==mi.posbot) ObjectDelete(mi.CI,mi.arbot);
           if(mi.corpos==mi.postop) ObjectDelete(mi.CI,mi.artop);
           mi.DrawSPMObject();
           //--
           ChartRedraw(mi.CI);
          }
        
    • Handling "artop" Button Click:
      • If the "artop" button is clicked, the function deletes the SPM objects, displays the panel button, unpresses the button, sets the display flag to true, changes the panel position to the top, and draws the SPM object.
      • 
        //--- if "artop" button is click
        if(sparam==mi.artop)
          {
           mi.DeletedSPMObject();
           mi.DisplayPanelButton();
           //--- unpress the button
           ObjectSetInteger(mi.CI,mi.artop,OBJPROP_STATE,false);
           ObjectSetInteger(mi.CI,mi.artop,OBJPROP_ZORDER,0);
           if(!mi.display)
              mi.display=true;
           ObjectDelete(mi.CI,mi.artop);
           mi.PanelPosChange(mi.postop);
           //--
           ObjectDelete(mi.CI,"X");
           mi.DisplayButtonClick("arbot");
           mi.DrawSPMObject();
           //--
           ChartRedraw(mi.CI);
          }
        
    • Handling "arbot" Button Click:
      • If the "arbot" button is clicked, the function deletes the SPM objects, displays the panel button, unpresses the button, sets the display flag to true, changes the panel position to the bottom, and draws the SPM object.
      • 
        //--- if "arbot" button is click
        if(sparam==mi.arbot)
          {
           mi.DeletedSPMObject();
           mi.DisplayPanelButton();
           //--- unpress the button
           ObjectSetInteger(mi.CI,mi.arbot,OBJPROP_STATE,false);
           ObjectSetInteger(mi.CI,mi.arbot,OBJPROP_ZORDER,0);
           if(!mi.display)
              mi.display=true;
           ObjectDelete(mi.CI,mi.arbot);
           mi.PanelPosChange(mi.posbot);
           //--
           ObjectDelete(mi.CI,"X");
           mi.DisplayButtonClick("artop");
           mi.DrawSPMObject();
           //--
           ChartRedraw(mi.CI);
          }
        
    • Handling Timeframe Button Clicks:
      • If any of the timeframe buttons are clicked, the function changes the chart symbol and timeframe accordingly.
      • 
              //--- if TF button is click
              //--
              if(sparam==mi.TFSc[0])
                {
                 mi.ChangeChartSymbol(mi.TFSc[0],mi.TFId[0]);
                }
              //--
              if(sparam==mi.TFSc[1])
                {
                 mi.ChangeChartSymbol(mi.TFSc[1],mi.TFId[1]);
                }
              //--
              if(sparam==mi.TFSc[2])
                {
                 mi.ChangeChartSymbol(mi.TFSc[2],mi.TFId[2]);
                }
              //--
              if(sparam==mi.TFSc[3])
                {
                 mi.ChangeChartSymbol(mi.TFSc[3],mi.TFId[3]);
                }
              //--
              if(sparam==mi.TFSc[4])
                {
                 mi.ChangeChartSymbol(mi.TFSc[4],mi.TFId[4]);
                }
              //--
              if(sparam==mi.TFSc[5])
                {
                 mi.ChangeChartSymbol(mi.TFSc[5],mi.TFId[5]);
                }
              //--
              if(sparam==mi.TFSc[6])
                {
                 mi.ChangeChartSymbol(mi.TFSc[6],mi.TFId[6]);
                }
              //--
              if(sparam==mi.TFSc[7])
                {
                 mi.ChangeChartSymbol(mi.TFSc[7],mi.TFId[7]);
                }
              //--
              if(sparam==mi.TFSc[8])
                {
                 mi.ChangeChartSymbol(mi.TFSc[8],mi.TFId[8]);
                }
              //--
              if(sparam==mi.TFSc[9])
                {
                 mi.ChangeChartSymbol(mi.TFSc[9],mi.TFId[9]);
                }
              //--
              if(sparam==mi.TFSc[10])
                {
                 mi.ChangeChartSymbol(mi.TFSc[10],mi.TFId[10]);
                }
              //--
              if(sparam==mi.TFSc[11])
                {
                 mi.ChangeChartSymbol(mi.TFSc[11],mi.TFId[11]);
                }
              //--
              if(sparam==mi.TFSc[12])
                {
                 mi.ChangeChartSymbol(mi.TFSc[12],mi.TFId[12]);
                }
              //--
              if(sparam==mi.TFSc[13])
                {
                 mi.ChangeChartSymbol(mi.TFSc[13],mi.TFId[13]);
                }
              //--
              if(sparam==mi.TFSc[14])
                {
                 mi.ChangeChartSymbol(mi.TFSc[14],mi.TFId[14]);
                }
              //--
              if(sparam==mi.TFSc[15])
                {
                 mi.ChangeChartSymbol(mi.TFSc[15],mi.TFId[15]);
                }
              //--
              if(sparam==mi.TFSc[16])
                {
                 mi.ChangeChartSymbol(mi.TFSc[16],mi.TFId[16]);
                }
              //--
              if(sparam==mi.TFSc[17])
                {
                 mi.ChangeChartSymbol(mi.TFSc[17],mi.TFId[17]);
                }
              //--
              if(sparam==mi.TFSc[18])
                {
                 mi.ChangeChartSymbol(mi.TFSc[18],mi.TFId[18]);
                }
              //--
              if(sparam==mi.TFSc[19])
                {
                 mi.ChangeChartSymbol(mi.TFSc[19],mi.TFId[19]);
                }
              //--
              if(sparam==mi.TFSc[20])
                {
                 mi.ChangeChartSymbol(mi.TFSc[20],mi.TFId[20]);
                }
              //--
             }
        

The Strength of Price Movement Multi-Timeframe (SPM_MTF) indicator is designed for MetaTrader 5 (MT5). It calculates the strength of price movement as a percentage on each timeframe bar, assisting traders in analyzing market trends and making informed trading decisions.

Key Functions of the SPM_MTF Indicator:

  • 1. Displays Multiple Timeframes: This feature allows traders to view various timeframes on a single chart, enhancing their ability to analyze marketmovements effectively.
  • 2. Helps Identify Market Trends: By viewing the indicator across multiple timeframes, traders can identify both larger and smaller market trends more easily.
  • 3. Supports Trading Decisions: The indicator assists traders in making informed decisions on entering or exiting trades based on observed market conditions across different timeframes.

Detailed Breakdown of Functions:

  • 1. SPM_MTF_Config(): Configures the multi-timeframe settings and prepares the indicator for use.
  • 2. PositionCore(): Sets up core position settings for the indicator elements on the chart.
  • 3. DrawSPMObject(): Draws various elements of the indicator on the chart.
  • 4. PanelPosChange(int inpos): Changes the panel position based on the input position value.
  • 5. UpdatePrice(ENUM_TIMEFRAMES xtf): Updates price data arrays for a given timeframe.
  • 6. RefreshPrice(ENUM_TIMEFRAMES xtf, int bars): Refreshes price data for a given timeframe and a specified number of bars.
  • 7. PriceStrengthScan(const ENUM_TIMEFRAMES stf, int shift): Calculates the direction of the price bar in percentage terms.
  • 8. CalculationStrength(int barCnt): Scans the direction of price movement for each timeframe and calculates the strength of price movement.
  • 9. ThisTime(const int reqmode): Retrieves current time information based on the requested mode
  • 10. Do_Alerts(string msg): Generates various types of alerts (print, alert, email, and notification) based on the provided message.
  • 11. FontsModel(int mode): Returns the font name based on the input mode.
  • 12. ChangeChartSymbol(string tf_name, ENUM_TIMEFRAMES stf): Changes the chart symbol and timeframe based on the input parameters.
  • 13. DisplayPanelButton(): Displays panel buttons on the chart.
  • 14. DisplayButtonClick(string actreq): Handles the creation and display of various buttons on the chart.
  • 15. DeletedSPMObject(): Deletes all objects related to the SPM_MTF indicator from the chart.
  • 16. strTF(ENUM_TIMEFRAMES period): Converts timeframe enumerations to string representations.
  • 17. getUninitReasonText(int reasonCode): Provides descriptive reasons for the uninitialization of the indicator (program) based on the given reason code.
  • 18. WS(int width): Calculates the width scaling factor for buttons based on screen DPI.
  • 19. CreateButtonClick(): Creates a clickable button on the chart with specified properties.
  • 20. CreateArrowLabel(): Creates an arrow label on the chart with specified properties.
  • 21. CreateButtonTemplate(): Creates a rectangular button on the chart with specified properties.

Main Functions of the Program:

  • OnInit(): Initializes the custom indicator, configuring indicator buffers and setting indicator properties.
  • OnDeinit(const int reason): Deinitializes the custom indicator, cleans up indicator objects, and prints the reason for deinitialization.
  • OnCalculate(): Handles the main calculations for the indicator on every price tick, including scanning price strength and generating alerts.
  • OnChartEvent(): Handles chart events, particularly button clicks, to manage the indicator's display and settings.

Summary:

The SPM_MTF indicator provides traders with a powerful tool to analyze price movements across multiple timeframes, helping them to identify market trends and make better trading decisions. The program includes various functions to configure, update, and display the indicator's elements, ensuring an enhanced trading experience.

We hope that this article and the SPM_MTF or Strength of Price Movement Multi Timeframe indicator for MT5 program will be useful for traders in learning and generating new ideas, which can ultimately make money from forex trading.

Thanks for reading this article.

Please download the SPM_MTF Indicator: Strength of Price Movement Indicator

If you are subscribed to my YouTube Channel, and would like to receive the source program of this article, please send a request via the Contact Us form page, and I will send it to your email, source code: Strength of Price Movement Indicator

Don't forget to stop by and subscribe to Forex Home Experts YouTube Channel:

YouTube Channel: @ForexHomeExperts

YouTube Playlist: @ForexHomeExperts YouTube Playlist

Featured Post

How to create a simple Multi-Currency Expert Advisor using MQL5 with Zigzag and RSI Indicators Signal

Introduction The Expert Advisor discussed in this article is a multi-currency trading robot that uses the Zigzag and RSI indicators. It fol...