From 74bb289a92083007a5c3926ac9345404764135ac Mon Sep 17 00:00:00 2001 From: EarnForex <48102957+EarnForex@users.noreply.github.com> Date: Mon, 21 Mar 2022 14:02:02 +0200 Subject: [PATCH] 1.01 --- ...ion-index-some-spot-on-trend-reversals.png | Bin 0 -> 7536 bytes RangeExpansionIndex.mq4 | 140 +++++++++++++++++ RangeExpansionIndex.mq5 | 142 ++++++++++++++++++ 3 files changed, 282 insertions(+) create mode 100644 README_Images/range-expansion-index-some-spot-on-trend-reversals.png create mode 100644 RangeExpansionIndex.mq4 create mode 100644 RangeExpansionIndex.mq5 diff --git a/README_Images/range-expansion-index-some-spot-on-trend-reversals.png b/README_Images/range-expansion-index-some-spot-on-trend-reversals.png new file mode 100644 index 0000000000000000000000000000000000000000..1ac4f9c4fa930a81d601c62a454336e252d52b6a GIT binary patch literal 7536 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 0) counted_bars--; + int limit = Bars - counted_bars; + if (limit > Bars - (8 + REI_Period) - 1) limit = Bars - (8 + REI_Period) - 1; + + for (int i = 0; i <= limit; i++) + { + double SubValueSum = 0; + double AbsDailyValueSum = 0; + for (int j = 0; j < REI_Period; j++) + { + SubValueSum += SubValue(i + j); + AbsDailyValueSum += AbsDailyValue(i + j); + } + if (AbsDailyValueSum != 0) REI[i] = SubValueSum / AbsDailyValueSum * 100; + else REI[i] = 0; + } + + // Alerts + if (((TriggerCandle > 0) && (Time[0] > LastAlertTime)) || (TriggerCandle == 0)) + { + string Text; + // Level 60 + if ((REI[TriggerCandle] < 60) && (REI[TriggerCandle + 1] >= 60)) + { + Text = "REI: " + Symbol() + " - " + StringSubstr(EnumToString((ENUM_TIMEFRAMES)Period()), 7) + " - Crossed 60 from above."; + if (EnableNativeAlerts) Alert(Text); + if (EnableEmailAlerts) SendMail("REI Alert", Text); + if (EnablePushAlerts) SendNotification(Text); + LastAlertTime = Time[0]; + } + // Level -60 + if ((REI[TriggerCandle] > -60) && (REI[TriggerCandle + 1] <= -60)) + { + Text = "REI: " + Symbol() + " - " + StringSubstr(EnumToString((ENUM_TIMEFRAMES)Period()), 7) + " - Crossed -60 from below."; + if (EnableNativeAlerts) Alert(Text); + if (EnableEmailAlerts) SendMail("REI Alert", Text); + if (EnablePushAlerts) SendNotification(Text); + LastAlertTime = Time[0]; + } + } + + return rates_total; +} + +//+------------------------------------------------------------------+ +//| Calculate the Conditional Value | +//+------------------------------------------------------------------+ +double SubValue(int i) +{ + double diff1 = High[i] - High[i + 2]; + double diff2 = Low[i] - Low[i + 2]; + int num_zero1, num_zero2; + + if ((High[i + 2] < Close[i + 7]) && (High[i + 2] < Close[i + 8]) && (High[i] < High[i + 5]) && (High[i] < High[i + 6])) + num_zero1 = 0; + else + num_zero1 = 1; + + if ((Low[i + 2] > Close[i + 7]) && (Low[i + 2] > Close[i + 8]) && (Low[i] > Low[i + 5]) && (Low[i] > Low[i + 6])) + num_zero2 = 0; + else + num_zero2 = 1; + + return (num_zero1 * num_zero2 * (diff1 + diff2)); +} + +//+------------------------------------------------------------------+ +//| Calculate the Absolute Value | +//+------------------------------------------------------------------+ +double AbsDailyValue(int i = 0) +{ + double diff1 = MathAbs(High[i] - High[i + 2]); + double diff2 = MathAbs(Low[i] - Low[i + 2]); + + return (diff1 + diff2); +} +//+------------------------------------------------------------------+ \ No newline at end of file diff --git a/RangeExpansionIndex.mq5 b/RangeExpansionIndex.mq5 new file mode 100644 index 0000000..b211e67 --- /dev/null +++ b/RangeExpansionIndex.mq5 @@ -0,0 +1,142 @@ +//+------------------------------------------------------------------+ +//| RangeExpansionIndex.mq5 | +//| Copyright © 2010-2022, EarnForex.com | +//| https://www.earnforex.com/ | +//+------------------------------------------------------------------+ +#property copyright "Copyright © 2010-2022, EarnForex.com" +#property link "https://www.earnforex.com/metatrader-indicators/Range-Expansion-Index/" +#property version "1.01" + +#property description "Calculates Tom DeMark's Range Expansion Index." +#property description "Going above 60 and then dropping below 60 signals price weakness." +#property description "Going below -60 and the rising above -60 signals price strength." +#property description "For more info see The New Science of Technical Analysis." + +#property indicator_separate_window +#property indicator_buffers 1 +#property indicator_plots 1 +#property indicator_color1 clrBlue +#property indicator_type1 DRAW_LINE +#property indicator_level1 60 +#property indicator_level2 -60 + +enum enum_candle_to_check +{ + Current, + Previous +}; + +input int REI_Period = 8; // REI Period +input bool EnableNativeAlerts = false; +input bool EnableEmailAlerts = false; +input bool EnablePushAlerts = false; +input enum_candle_to_check TriggerCandle = Previous; + +// Buffers: +double REI[]; + +// Global variables: +datetime LastAlertTime = D'01.01.1970'; + +void OnInit() +{ + IndicatorSetString(INDICATOR_SHORTNAME, "REI(" + IntegerToString(REI_Period) + ")"); + IndicatorSetInteger(INDICATOR_DIGITS, 2); + SetIndexBuffer(0, REI, INDICATOR_DATA); + PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, REI_Period + 8); +} + +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[]) +{ + int limit; + + // Too few bars to do anything. + if (rates_total <= REI_Period + 8) return 0; + // If we don't have enough bars to count as specified in the input. + int counted_bars = prev_calculated; + if (counted_bars < 8 + REI_Period) limit = 8 + REI_Period; + else limit = rates_total - 1; + + for (int i = rates_total - 1; i >= limit; i--) + { + double SubValueSum = 0; + double AbsDailyValueSum = 0; + for (int j = 0; j < REI_Period; j++) + { + SubValueSum += SubValue(i - j, High, Low, Close); + AbsDailyValueSum += AbsDailyValue(i - j, High, Low, Close); + } + if (AbsDailyValueSum != 0) REI[i] = SubValueSum / AbsDailyValueSum * 100; + else REI[i] = 0; + } + + // Alerts + if (((TriggerCandle > 0) && (Time[rates_total - 1] > LastAlertTime)) || (TriggerCandle == 0)) + { + string Text; + // Level 60 + if ((REI[rates_total - 1 - TriggerCandle] < 60) && (REI[rates_total - 2 - TriggerCandle] >= 60)) + { + Text = "REI: " + Symbol() + " - " + StringSubstr(EnumToString((ENUM_TIMEFRAMES)Period()), 7) + " - Crossed 60 from above."; + if (EnableNativeAlerts) Alert(Text); + if (EnableEmailAlerts) SendMail("REI Alert", Text); + if (EnablePushAlerts) SendNotification(Text); + LastAlertTime = Time[rates_total - 1]; + } + // Level -60 + if ((REI[rates_total - 1 - TriggerCandle] > -60) && (REI[rates_total - 2 - TriggerCandle] <= -60)) + { + Text = "REI: " + Symbol() + " - " + StringSubstr(EnumToString((ENUM_TIMEFRAMES)Period()), 7) + " - Crossed -60 from below."; + if (EnableNativeAlerts) Alert(Text); + if (EnableEmailAlerts) SendMail("REI Alert", Text); + if (EnablePushAlerts) SendNotification(Text); + LastAlertTime = Time[rates_total - 1]; + } + } + + return rates_total; +} + +//+------------------------------------------------------------------+ +//| Calculate the Conditional Value | +//+------------------------------------------------------------------+ +double SubValue(const int i, const double &High[], const double &Low[], const double &Close[]) +{ + int num_zero1, num_zero2; + + double diff1 = High[i] - High[i - 2]; + double diff2 = Low[i] - Low[i - 2]; + + if ((High[i - 2] < Close[i - 7]) && (High[i - 2] < Close[i - 8]) && (High[i] < High[i - 5]) && (High[i] < High[i - 6])) + num_zero1 = 0; + else + num_zero1 = 1; + + if ((Low[i - 2] > Close[i - 7]) && (Low[i - 2] > Close[i - 8]) && (Low[i] > Low[i - 5]) && (Low[i] > Low[i - 6])) + num_zero2 = 0; + else + num_zero2 = 1; + + return (num_zero1 * num_zero2 * (diff1 + diff2)); +} + +//+------------------------------------------------------------------+ +//| Calculate the Absolute Value | +//+------------------------------------------------------------------+ +double AbsDailyValue(const int i, const double &High[], const double &Low[], const double &Close[]) +{ + double diff1 = MathAbs(High[i] - High[i - 2]); + double diff2 = MathAbs(Low[i] - Low[i - 2]); + + return (diff1 + diff2); +} +//+------------------------------------------------------------------+ \ No newline at end of file