360 lines
25 KiB
Plaintext
360 lines
25 KiB
Plaintext
//+------------------------------------------------------------------+
|
|
//|Based on TradersDynamicIndex.mq4 by Dean Malone |
|
|
//| TradersDynamicIndex.mq5 |
|
|
//| Copyright © 2015-2019, EarnForex.com |
|
|
//| https://www.earnforex.com/ |
|
|
//+------------------------------------------------------------------+
|
|
#property copyright "Copyright © 2015-2019, www.EarnForex.com"
|
|
#property link "https://www.earnforex.com/metatrader-indicators/Traders-Dynamic-Index/"
|
|
#property version "1.03"
|
|
|
|
#property description "Shows trend direction, strength, and volatility."
|
|
#property description "Green line - RSI Price line."
|
|
#property description "Red line - Trade Signal line."
|
|
#property description "Blue lines - Volatility Band."
|
|
#property description "Yellow line - Market Base line."
|
|
|
|
#property indicator_separate_window
|
|
#property indicator_buffers 8
|
|
#property indicator_plots 5
|
|
#property indicator_level1 32
|
|
#property indicator_level2 50
|
|
#property indicator_level3 68
|
|
#property indicator_levelcolor clrDimGray
|
|
#property indicator_levelstyle STYLE_DOT
|
|
#property indicator_levelwidth 1
|
|
#property indicator_color1 clrMediumBlue
|
|
#property indicator_label1 "VB High"
|
|
#property indicator_type1 DRAW_LINE
|
|
#property indicator_width1 1
|
|
#property indicator_style1 STYLE_SOLID
|
|
#property indicator_color2 clrYellow
|
|
#property indicator_label2 "Market Base Line"
|
|
#property indicator_type2 DRAW_LINE
|
|
#property indicator_width2 2
|
|
#property indicator_style2 STYLE_SOLID
|
|
#property indicator_color3 clrMediumBlue
|
|
#property indicator_label3 "VB Low"
|
|
#property indicator_type3 DRAW_LINE
|
|
#property indicator_width3 1
|
|
#property indicator_style3 STYLE_SOLID
|
|
#property indicator_color4 clrGreen
|
|
#property indicator_label4 "RSI Price Line"
|
|
#property indicator_type4 DRAW_LINE
|
|
#property indicator_width4 2
|
|
#property indicator_style4 STYLE_SOLID
|
|
#property indicator_color5 clrRed
|
|
#property indicator_label5 "Trade Signal Line"
|
|
#property indicator_type5 DRAW_LINE
|
|
#property indicator_width5 2
|
|
#property indicator_style5 STYLE_SOLID
|
|
|
|
input int RSI_Period = 13; // RSI_Period: 8-25
|
|
input ENUM_APPLIED_PRICE RSI_Price = PRICE_CLOSE;
|
|
input int Volatility_Band = 34; // Volatility_Band: 20-40
|
|
input double StdDev = 1.6185; // Standard Deviations: 1-3
|
|
input int RSI_Price_Line = 2;
|
|
input ENUM_MA_METHOD RSI_Price_Type = MODE_SMA;
|
|
input int Trade_Signal_Line = 7;
|
|
input ENUM_MA_METHOD Trade_Signal_Type = MODE_SMA;
|
|
input bool AlertNative = false; // AlertNative: Alert popup inside platform.
|
|
input bool AlertSound = false; // AlertSound: Play a sound on alert.
|
|
input bool AlertEmail = false; // AlertEmail: Send an email on alert.
|
|
input bool AlertNotification = false; // AlertNotification: Send a push notification on alert.
|
|
|
|
double RSIBuf[], RSIBufPos[], RSIBufNeg[], UpZone[], MdZone[], DnZone[], MaBuf[], MbBuf[];
|
|
|
|
int MaxPeriod = 0;
|
|
|
|
datetime AlertPlayed = 0;
|
|
|
|
int RSI_handle;
|
|
|
|
//
|
|
|
|
#include <AZ-INVEST/SDK/RSI.mqh>
|
|
#include <AZ-INVEST/CustomBarConfig.mqh>
|
|
|
|
//
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Custom indicator initialization function |
|
|
//+------------------------------------------------------------------+
|
|
void OnInit()
|
|
{
|
|
IndicatorSetString(INDICATOR_SHORTNAME, "TDI(" + IntegerToString(RSI_Period) + "," + IntegerToString(Volatility_Band) + "," + IntegerToString(RSI_Price_Line) + "," + IntegerToString(Trade_Signal_Line) + ")");
|
|
|
|
SetIndexBuffer(0, UpZone, INDICATOR_DATA);
|
|
SetIndexBuffer(1, MdZone, INDICATOR_DATA);
|
|
SetIndexBuffer(2, DnZone, INDICATOR_DATA);
|
|
SetIndexBuffer(3, MaBuf, INDICATOR_DATA);
|
|
SetIndexBuffer(4, MbBuf, INDICATOR_DATA);
|
|
SetIndexBuffer(5, RSIBuf, INDICATOR_CALCULATIONS);
|
|
SetIndexBuffer(6, RSIBufPos, INDICATOR_CALCULATIONS);
|
|
SetIndexBuffer(7, RSIBufNeg, INDICATOR_CALCULATIONS);
|
|
|
|
ArraySetAsSeries(UpZone, true);
|
|
ArraySetAsSeries(MdZone, true);
|
|
ArraySetAsSeries(DnZone, true);
|
|
ArraySetAsSeries(MaBuf, true);
|
|
ArraySetAsSeries(MbBuf, true);
|
|
ArraySetAsSeries(RSIBuf, true);
|
|
ArraySetAsSeries(RSIBufPos, true);
|
|
ArraySetAsSeries(RSIBufNeg, true);
|
|
|
|
PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, 0);
|
|
PlotIndexSetDouble(1, PLOT_EMPTY_VALUE, 0);
|
|
PlotIndexSetDouble(2, PLOT_EMPTY_VALUE, 0);
|
|
PlotIndexSetDouble(3, PLOT_EMPTY_VALUE, 0);
|
|
PlotIndexSetDouble(4, PLOT_EMPTY_VALUE, 0);
|
|
|
|
IndicatorSetInteger(INDICATOR_DIGITS, 1);
|
|
|
|
//RSI_handle = iRSI(Symbol(), Period(), RSI_Period, RSI_Price);
|
|
//RSI_handle = iCustom(_Symbol, _Period, "MedianRenko\\Indicators\\MedianRenko_RSI2", RSI_Period, RSI_Price ,true); // my debug environment
|
|
// RSI_handle = iCustom(_Symbol, _Period, "MedianRenko\\MedianRenko_RSI2", RSI_Period, RSI_Price ,true);
|
|
|
|
MaxPeriod = Volatility_Band + RSI_Period;
|
|
|
|
PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, MaxPeriod);
|
|
PlotIndexSetInteger(1, PLOT_DRAW_BEGIN, MaxPeriod);
|
|
PlotIndexSetInteger(2, PLOT_DRAW_BEGIN, MaxPeriod);
|
|
PlotIndexSetInteger(3, PLOT_DRAW_BEGIN, MaxPeriod + RSI_Price_Line);
|
|
PlotIndexSetInteger(4, PLOT_DRAW_BEGIN, MaxPeriod + Trade_Signal_Line);
|
|
|
|
customChartIndicator.SetGetTimeFlag();
|
|
customChartIndicator.SetUseAppliedPriceFlag(RSI_Price);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Traders Dynamic Index |
|
|
//+------------------------------------------------------------------+
|
|
int OnCalculate(const int rates_total,
|
|
const int prev_calculated,
|
|
const datetime& Time[],
|
|
const double& open[],
|
|
const double& high[],
|
|
const double& low[],
|
|
const double& close[],
|
|
const long& tick_volume[],
|
|
const long& volume[],
|
|
const int& spread[]
|
|
)
|
|
{
|
|
double MA, RSI[];
|
|
ArrayResize(RSI, Volatility_Band);
|
|
ArraySetAsSeries(customChartIndicator.Time, true);
|
|
|
|
//
|
|
// Process data through MedianRenko indicator
|
|
//
|
|
|
|
if(!customChartIndicator.OnCalculate(rates_total,prev_calculated,Time,close))
|
|
return(0);
|
|
|
|
if(!customChartIndicator.BufferSynchronizationCheck(close))
|
|
return(0);
|
|
|
|
int _prev_calculated = customChartIndicator.GetPrevCalculated();
|
|
|
|
|
|
int i;
|
|
int counted_bars = _prev_calculated;
|
|
|
|
// Too few bars to work with.
|
|
if (rates_total < MaxPeriod) return(0);
|
|
|
|
i = rates_total - counted_bars;
|
|
if (i > rates_total - MaxPeriod - 1) i = rates_total - MaxPeriod - 1;
|
|
|
|
// int RSI_bars = CopyBuffer(RSI_handle, 0, 0, rates_total, RSIBuf); // todo?
|
|
// if (RSI_bars == -1) return(0);
|
|
|
|
RsiOnBuffer(rates_total, _prev_calculated, counted_bars, RSI_Period, customChartIndicator.Price, RSIBuf, RSIBufPos, RSIBufNeg);
|
|
|
|
// Calculate BB on RSI.
|
|
while (i >= 0)
|
|
{
|
|
MA = 0;
|
|
for (int x = i; x < i + Volatility_Band; x++)
|
|
{
|
|
RSI[x - i] = RSIBuf[x];
|
|
MA += RSIBuf[x] / Volatility_Band;
|
|
}
|
|
double SD = StdDev * StDev(RSI, Volatility_Band);
|
|
UpZone[i] = MA + SD;
|
|
DnZone[i] = MA - SD;
|
|
MdZone[i] = (UpZone[i] + DnZone[i]) / 2;
|
|
|
|
i--;
|
|
}
|
|
|
|
i = rates_total - counted_bars;
|
|
if (i > rates_total - MaxPeriod - 1) i = rates_total - MaxPeriod - 1;
|
|
|
|
// Calculate MAs of RSI.
|
|
while (i >= 0)
|
|
{
|
|
MaBuf[i] = iMAOnArray(RSIBuf, 0, RSI_Price_Line, 0, RSI_Price_Type, i);
|
|
MbBuf[i] = iMAOnArray(RSIBuf, 0, Trade_Signal_Line, 0, Trade_Signal_Type, i);
|
|
|
|
i--;
|
|
}
|
|
|
|
if ((MbBuf[0] > MdZone[0]) && (MbBuf[1] <= MdZone[1]) && (AlertPlayed != customChartIndicator.Time[0]))
|
|
{
|
|
if (AlertNative) Alert("Bullish cross");
|
|
if (AlertSound) PlaySound("alert.wav");
|
|
if (AlertEmail)
|
|
{
|
|
SendMail("TDI Alert: BUY " + _Symbol + " @ " + PeriodToString(_Period), "Current rate = " + DoubleToString(SymbolInfoDouble(_Symbol, SYMBOL_BID), _Digits) + "/" + DoubleToString(SymbolInfoDouble(_Symbol, SYMBOL_ASK), _Digits) + "\nIndicator buffers:\nVB High = " + DoubleToString(UpZone[0], 1) + "\nMarket Base Line = " + DoubleToString(MdZone[0], 1) + "\nVB Low = " + DoubleToString(DnZone[0], 1) + "\nRSI Price Line = " + DoubleToString(MaBuf[0], 1) + "\nTrade Signal Line = " + DoubleToString(MbBuf[0], 1));
|
|
}
|
|
if (AlertNotification) SendNotification("TDI Alert: BUY " + _Symbol + " @ " + PeriodToString(_Period));
|
|
AlertPlayed = customChartIndicator.Time[0];
|
|
}
|
|
if ((MbBuf[0] < MdZone[0]) && (MbBuf[1] >= MdZone[1]) && (AlertPlayed != customChartIndicator.Time[0]))
|
|
{
|
|
if (AlertNative) Alert("Bearish cross");
|
|
if (AlertSound) PlaySound("alert.wav");
|
|
if (AlertEmail)
|
|
{
|
|
SendMail("TDI Alert: SELL " + _Symbol + " @ " + PeriodToString(_Period), "Current rate = " + DoubleToString(SymbolInfoDouble(_Symbol, SYMBOL_BID), _Digits) + "/" + DoubleToString(SymbolInfoDouble(_Symbol, SYMBOL_ASK), _Digits) + "\nIndicator buffers:\nVB High = " + DoubleToString(UpZone[0], 1) + "\nMarket Base Line = " + DoubleToString(MdZone[0], 1) + "\nVB Low = " + DoubleToString(DnZone[0], 1) + "\nRSI Price Line = " + DoubleToString(MaBuf[0], 1) + "\nTrade Signal Line = " + DoubleToString(MbBuf[0], 1));
|
|
}
|
|
if (AlertNotification) SendNotification("TDI Alert: SELL " + _Symbol + " @ " + PeriodToString(_Period));
|
|
AlertPlayed = customChartIndicator.Time[0];
|
|
}
|
|
return(rates_total);
|
|
}
|
|
|
|
// Standard Deviation function.
|
|
double StDev(double& Data[], int Per)
|
|
{
|
|
return(MathSqrt(Variance(Data, Per)));
|
|
}
|
|
|
|
// Math Variance function.
|
|
double Variance(double& Data[], int Per)
|
|
{
|
|
double sum = 0, ssum = 0;
|
|
for (int i = 0; i < Per; i++)
|
|
{
|
|
sum += Data[i];
|
|
ssum += MathPow(Data[i], 2);
|
|
}
|
|
return((ssum * Per - sum * sum) / (Per * (Per - 1)));
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Based on http://www.mql5.com/en/articles/81 |
|
|
//| Simplified SMA calculation. |
|
|
//+------------------------------------------------------------------+
|
|
double iMAOnArray(double &Array[], int total, int iMAPeriod, int ma_shift, ENUM_MA_METHOD ma_method, int Shift)
|
|
{
|
|
double buf[];
|
|
if ((total > 0) && (total <= iMAPeriod)) return(0);
|
|
if (total == 0) total = ArraySize(Array);
|
|
if (ArrayResize(buf, total) < 0) return(0);
|
|
|
|
switch(ma_method)
|
|
{
|
|
// Simplified SMA. No longer works with ma_shift parameter.
|
|
case MODE_SMA:
|
|
{
|
|
double sum = 0;
|
|
for (int i = Shift; i < Shift + iMAPeriod; i++)
|
|
sum += Array[i] / iMAPeriod;
|
|
return(sum);
|
|
}
|
|
case MODE_EMA:
|
|
{
|
|
double pr = 2.0 / (iMAPeriod + 1);
|
|
int pos = total - 2;
|
|
while (pos >= 0)
|
|
{
|
|
if (pos == total - 2) buf[pos + 1] = Array[pos + 1];
|
|
buf[pos] = Array[pos] * pr + buf[pos + 1] * (1 - pr);
|
|
pos--;
|
|
}
|
|
return(buf[Shift + ma_shift]);
|
|
}
|
|
case MODE_SMMA:
|
|
{
|
|
double sum = 0;
|
|
int i, k, pos;
|
|
pos = total - iMAPeriod;
|
|
while (pos >= 0)
|
|
{
|
|
if (pos == total - iMAPeriod)
|
|
{
|
|
for (i = 0, k = pos; i < iMAPeriod; i++, k++)
|
|
{
|
|
sum += Array[k];
|
|
buf[k] = 0;
|
|
}
|
|
}
|
|
else sum = buf[pos + 1] * (iMAPeriod - 1) + Array[pos];
|
|
buf[pos] = sum / iMAPeriod;
|
|
pos--;
|
|
}
|
|
return(buf[Shift + ma_shift]);
|
|
}
|
|
case MODE_LWMA:
|
|
{
|
|
double sum = 0.0, lsum = 0.0;
|
|
double price;
|
|
int i, weight = 0, pos = total - 1;
|
|
for (i = 1; i <= iMAPeriod; i++, pos--)
|
|
{
|
|
price = Array[pos];
|
|
sum += price * i;
|
|
lsum += price;
|
|
weight += i;
|
|
}
|
|
pos++;
|
|
i = pos + iMAPeriod;
|
|
while (pos >= 0)
|
|
{
|
|
buf[pos] = sum / weight;
|
|
if (pos == 0) break;
|
|
pos--;
|
|
i--;
|
|
price = Array[pos];
|
|
sum = sum - lsum + price * iMAPeriod;
|
|
lsum -= Array[i];
|
|
lsum += price;
|
|
}
|
|
return(buf[Shift + ma_shift]);
|
|
}
|
|
default: return(0);
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
// For alerts.
|
|
string PeriodToString(int per)
|
|
{
|
|
switch (per)
|
|
{
|
|
case 60:
|
|
return("H1");
|
|
case 240:
|
|
return("H4");
|
|
case 1440:
|
|
return("D1");
|
|
case 10080:
|
|
return("W1");
|
|
case 43200:
|
|
return("MN1");
|
|
case 30:
|
|
return("M30");
|
|
case 15:
|
|
return("M15");
|
|
case 5:
|
|
return("M5");
|
|
case 1:
|
|
return("M1");
|
|
}
|
|
return("");
|
|
}
|
|
//+------------------------------------------------------------------+ |