FanSimple4en
Download scriptThis script functions as a multi-dimensional market analysis tool that visualizes trend alignment across different timeframes and price layers. Instead of looking at just one chart, it synthesizes data from multiple time horizons simultaneously to provide a comprehensive "snapshot" of market health.
The logic can be broken down into three primary components:
1. Multi-Timeframe Synchronization
The tool is designed to monitor up to nine different timeframes at once (e.g., from 1-minute charts to Daily charts). It calculates the status of the market across these various scales, allowing a trader to see if a short-term trend aligns with a long-term trend. By using a "Shift" parameter, it ensures that the data being analyzed on higher timeframes remains synchronized with the current price action on the active chart.
2. The "Fan" Trend Analysis
The core of the script revolves around a set of Moving Averages (the "Fan").
- Trend Alignment: The logic checks if these Moving Averages are stacked in a specific order. If they are perfectly aligned (e.g., all pointing upward or downward in a sequence), the tool identifies a strong trend.
- Visual Feedback: It translates this mathematical alignment into visual symbols on your screen. It uses different icons to indicate whether the "Fan" is moving up, moving down, or if the alignment is currently broken (neutral/mixed).
3. Price Positioning Logic
Beyond just looking at the averages, the script tracks where the actual market price sits in relation to that "Fan."
- Above/Below Status: It monitors whether the current price is trading above or below the moving averages.
- Status Reporting: The tool provides a dedicated display area (labels) that communicates three specific pieces of information for every timeframe selected:
- Whether the current price is above the trend fan.
- The current directional status of the fan itself.
- Whether the current price is below the trend fan.
Summary of User Experience
For a non-programmer, this script acts as a dashboard. Instead of manually switching between charts to see if the M15 trend matches the H4 trend, the script creates a text-based status board on your main screen. It automatically calculates the moving averages for all selected periods and updates symbols (arrows, circles, etc.) in real-time to tell you: "Is the market currently trending? Is it aligned across timeframes? And where is the price relative to those trends?"
#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_M30;
extern int Timeframe5 = PERIOD_H1;
extern int Timeframe6 = PERIOD_H4;
extern int Timeframe7 = PERIOD_D1;
extern int Timeframe8 = 0;
extern int Timeframe9 = 0;
/* Ñäâèã â ïðîøëîå â åäèíèöàõ M1 - íàïðèìåð, ÷òîáû íà íà H1 ñëåäèòü çà òðåòüèì áàðîì, íóæíî çàäàòü 120 */
extern int Shift = 0;
/* Ðèñîâàòü ëè âåðòèêàëüíóþ ëèíèþ ÷åðåç îòñëåæèâàåìûé áàð */
extern bool Tracking = false;
/* Çíà÷åíèÿ ïåðèîäîâ íàáîðà ñðåäíèõ, ñîñòàâëÿþùèõ âååð, ïðàâèëüíîñòü êîòîðîãî îòñëåæèâàåòñÿ (0-âûå è íåïðàâèëüíûå çíà÷åíèÿ âêëþ÷åíû â íàáîð íå áóäóò) */
extern int MA1 = 89;
extern int MA2 = 55;
extern int MA3 = 34;
extern int MA4 = 21;
extern int MA5 = 13;
extern int MA6 = 8;
extern int MA7 = 5;
extern int MA8 = 3;
/* Èíäèâèäóàëüíûé ðóáèëüíèê îòîáðàæåíèÿ íà êàæäóþ ñðåäíþþ */
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