FanSimple4en_001

FanSimple4en_001

This script is designed as a multi-timeframe analysis tool for MetaTrader. Its primary purpose is to visualize the relationship between current market prices and various Moving Averages (MAs) across multiple timeframes simultaneously, providing a "snapshot" of market sentiment.

Core Logic Overview

The script operates on two main visual components: a dynamic Status Dashboard and a Moving Average Fan.

1. The Status Dashboard (Fan Status)

Instead of just showing lines on a chart, the script creates a text-based dashboard in the corner of your screen. This dashboard tracks multiple timeframes at once (e.g., M1, M5, H1, D1). For each timeframe selected, it performs the following logic:

  • Trend Alignment (Fan Status): The script looks at a group of Moving Averages for each specific timeframe. It checks if all these averages are moving in the same direction.
    • If they are all aligned upward, it displays an Up Arrow.
    • If they are all aligned downward, it displays a Down Arrow.
    • If the averages are conflicting (some up, some down), it displays a Diamond symbol to indicate a neutral or mixed trend.
  • Price Position: The script simultaneously checks where the current price sits relative to these Moving Averages for that same timeframe.
    • It uses a specific symbol (like a circle) to indicate if the price is currently above or below the "fan" of averages.

2. The Moving Average Fan (Visual Plotting)

While the dashboard gives you a high-level summary, the script also draws actual lines on your current chart:

  • It plots up to eight different Exponential Moving Averages (EMAs).
  • These lines appear as a "fan" of colors, allowing you to see the immediate visual curvature of the price trends based on the specific periods you have configured.

Key Functional Features

  • Multi-Timeframe Synchronization: You can monitor how the "M1" trend compares to the "D1" trend at a single glance without constantly switching tabs or charts.
  • Customizable Periods: Users can define exactly which timeframes to track and which Moving Average lengths (e.g., 233, 55, 21) should make up the "fan."
  • Visual Feedback: The use of Wingdings symbols and specific colors allows for quick identification of market conditions—identifying "perfect" trend alignment versus "messy" or sideways markets instantly.
  • Bar Tracking: There is an optional vertical line feature that can help track the current price bar, providing a clear reference point for where the latest data is being processed.

Summary of Workflow

  1. Initialization: The script sets up the dashboard labels and identifies which Moving Averages to calculate.
  2. Real-time Calculation: Every time the price moves (or a new candle forms), the script recalculates the MA values for every timeframe you have enabled.
  3. Status Update: It compares those values against each other to decide which arrow or symbol to show on your dashboard.
  4. Visual Rendering: It updates the lines on your chart and the symbols on your dashboard to reflect the live market state.
Price Data Components
Series array that contains close prices for each bar
Indicators Used
Moving average indicator
Miscellaneous
Implements a curve of type %1
8 Views
0 Downloads
0 Favorites
FanSimple4en_001
#include <stdlib.mqh>

/******************************************************************************/
#property indicator_chart_window

#property indicator_buffers 8

/******************************************************************************/
/******************************************************************************/
/******************************************************************************/

/* m1, m5, m15, h1, h4, d1 ïðè ïîäêëþ÷åíèè èíäèêàòîðà  */

/******************************************************************************/
/******************************************************************************/
/******************************************************************************/

/* Öâåòà íàáîðà ñðåäíèõ (âñòàâ êóðñîðîì íà èìåíè öâåòà, íàæàòü F1 è óâèäåòü èìåíà îñòàëüíûõ öâåòîâ) */
#property indicator_color1 OrangeRed
#property indicator_color2 Orange
#property indicator_color3 Yellow
#property indicator_color4 DodgerBlue
#property indicator_color5 Aqua
#property indicator_color6 Magenta
#property indicator_color7 Gray
#property indicator_color8 White

/******************************************************************************
  Indicator parameters
*/

/* Îáùèé ðóáèëüíèê îòîáðàæåíèÿ ïðàâèëüíîñòè âååðà, ïîçâîëÿåò îòðóáèòü ðàçîì îòîáðàæåíèå íàáîðà âñåõ ïåðèîäîâ */
extern bool DisplayFanStatus = true;

/* Îáùèé ðóáèëüíèê îòîáðàæåíèÿ ñðåäíèõ, ïîçâîëÿåò îòðóáèòü ðàçîì îòîáðàæåíèå íàáîðà ñðåäíèõ */
extern bool DisplayFan = true;

/* Çíà÷åíèÿ ïåðèîäîâ íàáîðà timeframe'îâ â ïîðÿäêå ñëåäîâàíèÿ ñëåâà íàïðàâî (âîçìîæíû ïîâòîðåíèÿ, 0-âûå è íåïðàâèëüíûå çíà÷åíèÿ âêëþ÷åíû â íàáîð íå áóäóò) */
extern int Timeframe1 = PERIOD_M1;
extern int Timeframe2 = PERIOD_M5;
extern int Timeframe3 = PERIOD_M15;
extern int Timeframe4 = PERIOD_H1;
extern int Timeframe5 = PERIOD_H4;
extern int Timeframe6 = PERIOD_D1;
extern int Timeframe7 = 0;
extern int Timeframe8 = 0;
extern int Timeframe9 = 0;

/* Ñäâèã â ïðîøëîå â åäèíèöàõ M1 - íàïðèìåð, ÷òîáû íà íà H1 ñëåäèòü çà òðåòüèì áàðîì, íóæíî çàäàòü 120 */
extern int Shift = 0;

/* Ðèñîâàòü ëè âåðòèêàëüíóþ ëèíèþ ÷åðåç îòñëåæèâàåìûé áàð */
extern bool Tracking = false;

/* Çíà÷åíèÿ ïåðèîäîâ íàáîðà ñðåäíèõ, ñîñòàâëÿþùèõ âååð, ïðàâèëüíîñòü êîòîðîãî îòñëåæèâàåòñÿ (0-âûå è íåïðàâèëüíûå çíà÷åíèÿ âêëþ÷åíû â íàáîð íå áóäóò) */
extern int MA1 = 233;
extern int MA2 = 55;
extern int MA3 = 21;
extern int MA4 = 5;
extern int MA5 = 0;
extern int MA6 = 0;
extern int MA7 = 0;
extern int MA8 = 0;

/* Èíäèâèäóàëüíûé ðóáèëüíèê îòîáðàæåíèÿ íà êàæäóþ ñðåäíþþ */
extern bool DisplayMA1 = true;
extern bool DisplayMA2 = true;
extern bool DisplayMA3 = true;
extern bool DisplayMA4 = true;
extern bool DisplayMA5 = true;
extern bool DisplayMA6 = true;
extern bool DisplayMA7 = true;
extern bool DisplayMA8 = true;

/* Èìÿ ôîíòà ñèìâîëîâ */
extern string FontName = "Wingdings";

/* Ðàçìåð ñèìâîëîâ */
extern int FontSize = 12;

/* Ñèìâîëû íàðèñîâàííîãî è ñò¸ðòîãî óêàçàòåëÿ ïîëîæåíèÿ öåíû îòíîñèòåëüíî âååðà */
extern int PriceOnSymbol = 108; // Circle
extern int PriceOffSymbol = 32; // Space

/* Öâåòà íàðèñîâàííîãî óêàçàòåëÿ ïîëîæåíèÿ öåíû îòíîñèòåëüíî âååðà */
extern color PriceColor = LimeGreen;

/* Ñèìâîëû óêàçàòåëÿ ïðàâèëüíîñòè âååðà */
extern int FanWrongSymbol = 117; // Diamond
extern int FanUpSymbol = 233; // Up Arrow
extern int FanDownSymbol = 234; // Down Arrow

/* Öâåòà óêàçàòåëÿ ïðàâèëüíîñòè âååðà */
extern color FanWrongColor = DarkGray;
extern color FanUpColor = DodgerBlue;
extern color FanDownColor = OrangeRed;

/* Ñìåùåíèå âëåâî (X) è âïðàâî (Y) îò ïðàâîãî âåðõíåãî óãëà */
extern int X = 0;
extern int Y = 0;

/******************************************************************************/
/******************************************************************************/
/******************************************************************************/

/******************************************************************************
  Tracking vertical line label and color
*/
#define TRACKING_NAME "bar tracking"
#define TRACKING_COLOR DarkGray

/******************************************************************************/
string RowName[3] = { "Price abowe Fan",
                      "Fan Position",
                      "Price below Fan" };

/******************************************************************************/
/******************************************************************************/
/******************************************************************************

/*** À âîò ñþäà ëàçèòü óæå íå ñëåäóåò **** À âîò ñþäà ëàçèòü óæå íå ñëåäóåò ***/
/*** À âîò ñþäà ëàçèòü óæå íå ñëåäóåò **** À âîò ñþäà ëàçèòü óæå íå ñëåäóåò ***/
/*** À âîò ñþäà ëàçèòü óæå íå ñëåäóåò **** À âîò ñþäà ëàçèòü óæå íå ñëåäóåò ***/

/******************************************************************************/
/******************************************************************************/
/******************************************************************************
  Type of rendering codes
*/
#define is_down    0
#define is_none    1
#define is_up      2

/******************************************************************************/
int Timeframe[9];
string TimeframeNames[9];
int TimeframeInUse = 0;

/******************************************************************************/
int MAs[8];
int Xlat[8];
int MAsInUse = 0;

/******************************************************************************/
double MA1Buf[], MA2Buf[], MA3Buf[], MA4Buf[], MA5Buf[], MA6Buf[], MA7Buf[], MA8Buf[];

/******************************************************************************/
string LabelName(int i, int j) { return(RowName[j] + "(" + (i + 1) + "): " + TimeframeNames[i]); }

/******************************************************************************/
int symcolor[3][2];
int syms[3][2];

/******************************************************************************/
void UpdateFanStatus(int i, int how)
{
  string s = " ";

  ObjectSetText(LabelName(i, 1), StringSetChar(s, 0, symcolor[how][0]), FontSize, FontName, symcolor[how][1]);
}

/******************************************************************************/
void UpdatePriceStatus(int i, int how)
{
  string s = " ";

  ObjectSetText(LabelName(i, 0), StringSetChar(s, 0, syms[how][0]), FontSize, FontName, PriceColor);
  ObjectSetText(LabelName(i, 2), StringSetChar(s, 0, syms[how][1]), FontSize, FontName, PriceColor);
}

/******************************************************************************/
void InitTimeframe(int &P[], int PV)
{
  if(PV != 0)
  {
    switch(PV)
    {
    case PERIOD_M1:  TimeframeNames[TimeframeInUse] = "M1";  break;
    case PERIOD_M5:  TimeframeNames[TimeframeInUse] = "M5";  break;
    case PERIOD_M15: TimeframeNames[TimeframeInUse] = "M15"; break;
    case PERIOD_M30: TimeframeNames[TimeframeInUse] = "M30"; break;
    case PERIOD_H1:  TimeframeNames[TimeframeInUse] = "H1";  break;
    case PERIOD_H4:  TimeframeNames[TimeframeInUse] = "H4";  break;
    case PERIOD_D1:  TimeframeNames[TimeframeInUse] = "D1";  break;
    case PERIOD_W1:  TimeframeNames[TimeframeInUse] = "W1";  break;
    case PERIOD_MN1: TimeframeNames[TimeframeInUse] = "MN1"; break;
    default: return;
    }

    P[TimeframeInUse] = PV; TimeframeInUse++;
  }
}

/******************************************************************************/
void InitMAs(int &P[], int MA) { if(MA > 0) { P[MAsInUse] = MA; MAsInUse++; } }

/******************************************************************************/
int init()
{
  int i, j;

  if(DisplayFanStatus)
  {
    syms[0][0] = PriceOffSymbol; syms[0][1] = PriceOnSymbol;
    syms[1][0] = PriceOffSymbol; syms[1][1] = PriceOffSymbol;
    syms[2][0] = PriceOnSymbol; syms[2][1] = PriceOffSymbol;

    symcolor[0][0] = FanDownSymbol; symcolor[0][1] = FanDownColor;
    symcolor[1][0] = FanWrongSymbol; symcolor[1][1] = FanWrongColor;
    symcolor[2][0] = FanUpSymbol; symcolor[2][1] = FanUpColor;


    InitTimeframe(Timeframe, Timeframe1); InitTimeframe(Timeframe, Timeframe2); InitTimeframe(Timeframe, Timeframe3); InitTimeframe(Timeframe, Timeframe4);
    InitTimeframe(Timeframe, Timeframe5); InitTimeframe(Timeframe, Timeframe6); InitTimeframe(Timeframe, Timeframe7); InitTimeframe(Timeframe, Timeframe8);
    InitTimeframe(Timeframe, Timeframe9);

    InitMAs(MAs, MA1); InitMAs(MAs, MA2); InitMAs(MAs, MA3); InitMAs(MAs, MA4);
    InitMAs(MAs, MA5); InitMAs(MAs, MA6); InitMAs(MAs, MA7); InitMAs(MAs, MA8);

    for(i = 0; i < MAsInUse; i++) Xlat[i] = i;

    for(i = 0; i < MAsInUse - 1; i++)
      for(j = i + 1; j < MAsInUse; j++)
        if(MAs[Xlat[i]] > MAs[Xlat[j]]) { int k = Xlat[j]; Xlat[j] = Xlat[i]; Xlat[i] = k; }

    for(i = 0; i < TimeframeInUse; i++)
      for(j = 0; j < 3; j++)
      {
        string s = LabelName(i, j);

        ObjectCreate(s, OBJ_LABEL, 0, 0, 0);   
        ObjectSet(s, OBJPROP_XDISTANCE, (TimeframeInUse - i - 1) * 13 * FontSize / 10 + 2 * FontSize / 10 + X);
        ObjectSet(s, OBJPROP_YDISTANCE, j * 16 * FontSize / 10 + 3 * FontSize / 10 + Y);
        ObjectSet(s, OBJPROP_BACK, true);
        ObjectSet(s, OBJPROP_CORNER, 1);
        ObjectSetText(s, " ", FontSize, FontName, Black);
      }

    if(Tracking != 0)
    {
      ObjectCreate(TRACKING_NAME, OBJ_VLINE, 0, Time[Shift / Period()], 0);
      ObjectSet(TRACKING_NAME, OBJPROP_COLOR, TRACKING_COLOR);
    }
  }


  if(DisplayFan)
  {
    string IndicatorName = "FanSimple(";


    if(DisplayMA1 && MA1 > 0) IndicatorName = IndicatorName + MA1; if(DisplayMA2 && MA2 > 0) IndicatorName = IndicatorName + ", " + MA2;
    if(DisplayMA3 && MA3 > 0) IndicatorName = IndicatorName + ", " + MA3; if(DisplayMA4 && MA4 > 0) IndicatorName = IndicatorName + ", " + MA4;
    if(DisplayMA5 && MA5 > 0) IndicatorName = IndicatorName + ", " + MA5; if(DisplayMA6 && MA6 > 0) IndicatorName = IndicatorName + ", " + MA6;
    if(DisplayMA7 && MA7 > 0) IndicatorName = IndicatorName + ", " + MA7; if(DisplayMA8 && MA8 > 0) IndicatorName = IndicatorName + ", " + MA8;

    IndicatorShortName(IndicatorName + ")");

    IndicatorBuffers(8);

    SetIndexBuffer(0, MA1Buf); SetIndexBuffer(1, MA2Buf); SetIndexBuffer(2, MA3Buf); SetIndexBuffer(3, MA4Buf);
    SetIndexBuffer(4, MA5Buf); SetIndexBuffer(5, MA6Buf); SetIndexBuffer(6, MA7Buf); SetIndexBuffer(7, MA8Buf);

    SetIndexLabel(0, "Fan, " + MA1 + " MA"); SetIndexLabel(1, "Fan, " + MA2 + " MA");
    SetIndexLabel(2, "Fan, " + MA3 + " MA"); SetIndexLabel(3, "Fan, " + MA4 + " MA");
    SetIndexLabel(4, "Fan, " + MA5 + " MA"); SetIndexLabel(5, "Fan, " + MA6 + " MA");
    SetIndexLabel(6, "Fan, " + MA7 + " MA"); SetIndexLabel(7, "Fan, " + MA8 + " MA");

    for(i = 0; i < 7; i++)
    {
      SetIndexStyle(i, DRAW_LINE);
      SetIndexEmptyValue(i, 0);
    }

    ArraySetAsSeries(MA1Buf, true); ArraySetAsSeries(MA2Buf, true); ArraySetAsSeries(MA3Buf, true); ArraySetAsSeries(MA4Buf, true);
    ArraySetAsSeries(MA5Buf, true); ArraySetAsSeries(MA6Buf, true); ArraySetAsSeries(MA7Buf, true); ArraySetAsSeries(MA8Buf, true);

    for(i = Bars - 1; i >= 0; i--)
    {
      MA1Buf[i] = 0; MA2Buf[i] = 0; MA3Buf[i] = 0; MA4Buf[i] = 0; MA5Buf[i] = 0; MA6Buf[i] = 0; MA7Buf[i] = 0; MA8Buf[i] = 0;
    }
  }

  return(0);
}

/******************************************************************************/
int deinit()
{
  for(int i = 0; i < TimeframeInUse; i++)
    for(int j = 0; j < 3; j++)
      ObjectDelete(LabelName(i, j));

  if(Tracking != 0)
    ObjectDelete(TRACKING_NAME);

  return(0);
}

/******************************************************************************/
int start()
{
  static datetime time = 0;

  /* For the last bar (Shift == 0) process each tick otherwise only when new bar appears */
  if(Shift == 0 || time != Time[0])
  {
    int i;

    if(DisplayFanStatus)
      for(i = 0; i < TimeframeInUse; i++)
      {
        bool Up = true, Down = true;
        bool PriceUp = true, PriceDown = true;

        int LocalShift = Shift / Timeframe[i];

        double PrevMA = 0;

        for(int j = 0; j < MAsInUse; j++)
        {
          double MA = iMA(NULL, Timeframe[i], MAs[Xlat[j]], 0, MODE_EMA, PRICE_CLOSE, LocalShift);

          if(j > 0) { if(Up && PrevMA < MA) Up = false; if(Down && PrevMA > MA) Down = false; }

          if(PriceUp && MA > iClose(Symbol(), Timeframe[i], LocalShift)) PriceUp = false;
          if(PriceDown && MA < iClose(Symbol(), Timeframe[i], LocalShift)) PriceDown = false;

          PrevMA = MA;
        }

        if(Up) UpdateFanStatus(i, is_up); else if(Down) UpdateFanStatus(i, is_down); else UpdateFanStatus(i, is_none);
        if(PriceUp) UpdatePriceStatus(i, is_up); else if(PriceDown) UpdatePriceStatus(i, is_down); else UpdatePriceStatus(i, is_none);
      }

    if(DisplayFan)
      for(i = Bars - IndicatorCounted() - 1; i >= 0; i--)
      {
        if(DisplayMA1 && MA1 > 0) MA1Buf[i] = iMA(NULL, 0, MA1, 0, MODE_EMA, PRICE_CLOSE, i);
        if(DisplayMA2 && MA2 > 0) MA2Buf[i] = iMA(NULL, 0, MA2, 0, MODE_EMA, PRICE_CLOSE, i);
        if(DisplayMA3 && MA3 > 0) MA3Buf[i] = iMA(NULL, 0, MA3, 0, MODE_EMA, PRICE_CLOSE, i);
        if(DisplayMA4 && MA4 > 0) MA4Buf[i] = iMA(NULL, 0, MA4, 0, MODE_EMA, PRICE_CLOSE, i);
        if(DisplayMA5 && MA5 > 0) MA5Buf[i] = iMA(NULL, 0, MA5, 0, MODE_EMA, PRICE_CLOSE, i);
        if(DisplayMA6 && MA6 > 0) MA6Buf[i] = iMA(NULL, 0, MA6, 0, MODE_EMA, PRICE_CLOSE, i);
        if(DisplayMA7 && MA7 > 0) MA7Buf[i] = iMA(NULL, 0, MA7, 0, MODE_EMA, PRICE_CLOSE, i);
        if(DisplayMA8 && MA8 > 0) MA8Buf[i] = iMA(NULL, 0, MA8, 0, MODE_EMA, PRICE_CLOSE, i);
      }

    if(time != Time[0]) // If new bar appeared
    {
      time = Time[0]; // Update the new bar tracking trigger

      if(Tracking != 0)
        ObjectSet(TRACKING_NAME, OBJPROP_TIME1, Time[Shift / Period()]); // Update tracking position
    }
  }

  return(0);
}

Comments