[et_pb_section fb_built=”1″ theme_builder_area=”post_content” _builder_version=”4.27.4″ _module_preset=”default”][et_pb_row _builder_version=”4.27.4″ _module_preset=”default” theme_builder_area=”post_content”][et_pb_column _builder_version=”4.27.4″ _module_preset=”default” type=”4_4″ theme_builder_area=”post_content”][et_pb_text _builder_version=”4.27.4″ _module_preset=”default” theme_builder_area=”post_content” hover_enabled=”0″ sticky_enabled=”0″]
//+———————————————————————+
//| Murrey_Math_Line_X.mq4 |
//| Copyright © 2024 |
//+———————————————————————+
#property link „https://t.me/ForexEaPremium”
#property version „1.05”
#property strict
#property description „Murrey Math Line X – support and resistance lines according to Murrey Math rules.”
#property indicator_chart_window
#property indicator_plots 0
// ============================================================================================
// * Line 8/8 и 0/8 (Ultimate Support and Ultimate Resistance).
// * Those lines are the most strong concerning Support and resistance.
// ============================================================================================
//* Line 7/8 (Weak, Place to Stop and Reverse).
//* This line is weak. If suddenly the price was going too fast and too far and stops around this line
//* it means the price will reverse down very soon. If the price did not stop near this line this price
//* will continue the movement to the line 8/8.
// ============================================================================================
//* Line 1/8 (Weak, Place to Stop and Reverse).
//* This line is weak. If suddenly the price was going too fast and too far and stops around this line
//* it means the price will reverse up very soon. If the price did not stop near this line this price
//* will continue the movement down to the line 0/8.
// ============================================================================================
//* Line 2/8 and 6/8 (Pivot, Reverse)
//* Those two lines yield the line 4/8 only to the strength to reverse the price movement.
// ============================================================================================
//* Line 5/8 (Top of Trading Range)
//* The price is spending the about 40% of the time on the movement between the lines 5/8 and 3/8.
//* If the price is moving near line 5/8 and stopping near the line during the 10 – 12 days so it means
//* that it is necessary to sell in this „bonus zone” (some people are doing like this) but if the price is keeping the tendency to stay above
//* 5/8 line, so it means that the price will be above. But if the price is dropping below 5/8 line it means that the price will continue
//* falling to the next level of resistance.
// ============================================================================================
//* Line 3/8 (Bottom of Trading Range).
//* If the price is below this line and in uptrend it means that it will be very difficult for the price to break this level.
//* If the price broke this line during the uptrend and staying above during the 10 12 days it means that the price will be above this line
//* during the 40% of its time moving between this line and 5/8 line.
// ============================================================================================
//* Line 4/8 (Major Support/Resistance Line).
//* It is the major line concerning support and resistance. This level is the better for the new sell or buy.
//* It is the strong level of support of the price is above 4/8. It is the fine resistance line if the price is below this 4/8 line.
// ============================================================================================
enum enum_side
{
Left,
Right
};
enum ENUM_CANDLE_TO_CHECK
{
Current,
Previous
};
input int period = 64; // Period
input ENUM_TIMEFRAMES UpperTimeframe = PERIOD_D1;
input int StepBack = 0;
input enum_side LabelSide = Left;
input color mml_clr_m_2_8 = clrWhite; // [-2]/8 Color
input color mml_clr_m_1_8 = clrWhite; // [-1]/8 Color
input color mml_clr_0_8 = clrAqua; // [0]/8 Color
input color mml_clr_1_8 = clrYellow; // [1]/8 Color
input color mml_clr_2_8 = clrRed; // [2]/8 Color
input color mml_clr_3_8 = clrGreen; // [3]/8 Color
input color mml_clr_4_8 = clrBlue; // [4]/8 Color
input color mml_clr_5_8 = clrGreen; // [5]/8 Color
input color mml_clr_6_8 = clrRed; // [6]/8 Color
input color mml_clr_7_8 = clrYellow; // [7]/8 Color
input color mml_clr_8_8 = clrAqua; // [8]/8 Color
input color mml_clr_p_1_8 = clrWhite; // [+1]/8 Color
input color mml_clr_p_2_8 = clrWhite; // [+2]/8 Color
input int mml_wdth_m_2_8 = 2; // [-2]/8 Width
input int mml_wdth_m_1_8 = 1; // [-1]/8 Width
input int mml_wdth_0_8 = 1; // [0]/8 Width
input int mml_wdth_1_8 = 1; // [1]/8 Width
input int mml_wdth_2_8 = 1; // [2]/8 Width
input int mml_wdth_3_8 = 1; // [3]/8 Width
input int mml_wdth_4_8 = 1; // [4]/8 Width
input int mml_wdth_5_8 = 1; // [5]/8 Width
input int mml_wdth_6_8 = 1; // [6]/8 Width
input int mml_wdth_7_8 = 1; // [7]/8 Width
input int mml_wdth_8_8 = 1; // [8]/8 Width
input int mml_wdth_p_1_8 = 1; // [+1]/8 Width
input int mml_wdth_p_2_8 = 2; // [+2]/8 Width
input color MarkColor = clrBlue;
input int MarkNumber = 217;
input string FontFace = „Verdana”;
input int FontSize = 10;
input string ObjectPrefix = „MML-„;
input ENUM_CANDLE_TO_CHECK TriggerCandle = Previous;
input bool NativeAlerts = false;
input bool EmailAlerts = false;
input bool NotificationAlerts = false;
string ln_txt[13];
int
OctLinesCnt = 13,
mml_clr[13],
mml_wdth[13];
double mml[13];
datetime nTime = 0;
int NewPeriod = 0;
// For alerts. Each line can have its own signal.
datetime LastAlertTime[13];
int prevSignal[13];
void OnInit()
{
ArrayInitialize(LastAlertTime, 0);
ArrayInitialize(prevSignal, 42); // To avoid trigger on attachment.
if ((UpperTimeframe != PERIOD_CURRENT) && (UpperTimeframe != Period()))
{
NewPeriod = period * (int)MathCeil(PeriodSeconds(UpperTimeframe) / PeriodSeconds(Period()));
}
else
{
NewPeriod = period;
}
ln_txt[0] = „[-2/8]P Extreme Overshoot [-2/8]”;
ln_txt[1] = „[-1/8]P Overshoot [-1/8]”;
ln_txt[2] = „[0/8]P Ultimate Support – extremely oversold [0/8]”;
ln_txt[3] = „[1/8]P Weak, Place to Stop and Reverse [1/8]”;
ln_txt[4] = „[2/8]P Pivot, Reverse – major [2/8]”;
ln_txt[5] = „[3/8]P Bottom of Trading Range [3/8] – BUY Premium Zone”;
ln_txt[6] = „[4/8]P Major S/R Pivot Point [4/8] – Best New BUY or SELL level”;
ln_txt[7] = „[5/8]P Top of Trading Range [5/8] – SELL Premium Zone”;
ln_txt[8] = „[6/8]P Pivot, Reverse – major [6/8]”;
ln_txt[9] = „[7/8]P Weak, Place to Stop and Reverse [7/8]”;
ln_txt[10] = „[8/8]P Ultimate Resistance – extremely overbought [8/8]”;
ln_txt[11] = „[+1/8]P Overshoot [+1/8]”;
ln_txt[12] = „[+2/8]P Extreme Overshoot [+2/8]”;
// Initial setting of the lines’ colors and width
mml_clr[0] = mml_clr_m_2_8;
mml_wdth[0] = mml_wdth_m_2_8; // [-2]/8
mml_clr[1] = mml_clr_m_1_8;
mml_wdth[1] = mml_wdth_m_1_8; // [-1]/8
mml_clr[2] = mml_clr_0_8;
mml_wdth[2] = mml_wdth_0_8; // [0]/8
mml_clr[3] = mml_clr_1_8;
mml_wdth[3] = mml_wdth_1_8; // [1]/8
mml_clr[4] = mml_clr_2_8;
mml_wdth[4] = mml_wdth_2_8; // [2]/8
mml_clr[5] = mml_clr_3_8;
mml_wdth[5] = mml_wdth_3_8; // [3]/8
mml_clr[6] = mml_clr_4_8;
mml_wdth[6] = mml_wdth_4_8; // [4]/8
mml_clr[7] = mml_clr_5_8;
mml_wdth[7] = mml_wdth_5_8; // [5]/8
mml_clr[8] = mml_clr_6_8;
mml_wdth[8] = mml_wdth_6_8; // [6]/8
mml_clr[9] = mml_clr_7_8;
mml_wdth[9] = mml_wdth_7_8; // [7]/8
mml_clr[10] = mml_clr_8_8;
mml_wdth[10] = mml_wdth_8_8; // [8]/8
mml_clr[11] = mml_clr_p_1_8;
mml_wdth[11] = mml_wdth_p_1_8; // [+1]/8
mml_clr[12] = mml_clr_p_2_8;
mml_wdth[12] = mml_wdth_p_2_8; // [+2]/8
}
void OnDeinit(const int reason)
{
ObjectsDeleteAll(ChartID(), ObjectPrefix);
}
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[])
{
if (nTime < Time[0])
{
// Price
int bn_v1 = iLowest(Symbol(), Period(), MODE_LOW, NewPeriod + StepBack, StepBack);
int bn_v2 = iHighest(Symbol(), Period(), MODE_HIGH, NewPeriod + StepBack, StepBack);
double v1 = Low[bn_v1];
double v2 = High[bn_v2];
double fractal = 0;
// Determine fractal
if ((v2 <= 250000) && (v2 > 25000))
fractal = 100000;
else if ((v2 <= 25000) && (v2 > 2500))
fractal = 10000;
else if ((v2 <= 2500) && (v2 > 250))
fractal = 1000;
else if ((v2 <= 250) && (v2 > 25))
fractal = 100;
else if ((v2 <= 25) && (v2 > 12.5))
fractal = 12.5;
else if ((v2 <= 12.5) && (v2 > 6.25))
fractal = 12.5;
else if ((v2 <= 6.25) && (v2 > 3.125))
fractal = 6.25;
else if ((v2 <= 3.125) && (v2 > 1.5625))
fractal = 3.125;
else if ((v2 <= 1.5625) && (v2 > 0.390625))
fractal = 1.5625;
else if ((v2 <= 0.390625) && (v2 > 0))
fractal = 0.1953125;
double range = v2 – v1;
double sum = MathFloor(MathLog(fractal / range) / MathLog(2));
double octave = fractal * (MathPow(0.5, sum));
double mn = MathFloor(v1 / octave) * octave;
double mx;
if (mn + octave > v2) mx = mn + octave;
else mx = mn + (2 * octave);
// Calculating X’s
double x1, x2, x3, x4, x5, x6;
// x2
if ((v1 >= (3 * (mx – mn) / 16 + mn)) && (v2 <= (9 * (mx – mn) / 16 + mn)))
x2 = mn + (mx – mn) / 2;
else
x2 = 0;
// x1
if ((v1 >= (mn – (mx – mn) / 8)) && (v2 <= (5 * (mx – mn) / 8 + mn)) && (x2 == 0))
x1 = mn + (mx – mn) / 2;
else
x1 = 0;
// x4
if ((v1 >= (mn + 7 * (mx – mn) / 16)) && (v2 <= (13 * (mx – mn) / 16 + mn)))
x4 = mn + 3 * (mx – mn) / 4;
else x4 = 0;
// x5
if ((v1 >= (mn + 3 * (mx – mn) / 8)) && (v2 <= (9 * (mx – mn) / 8 + mn)) && (x4 == 0))
x5 = mx;
else
x5 = 0;
// x3
if ((v1 >= (mn + (mx – mn) / 8)) && (v2 <= (7 * (mx – mn) / 8 + mn)) && (x1 == 0) && (x2 == 0) && (x4 == 0) && (x5 == 0))
x3 = mn + 3 * (mx – mn) / 4;
else
x3 = 0;
// x6
if ((x1 + x2 + x3 + x4 + x5) == 0)
x6 = mx;
else
x6 = 0;
double finalH = x1 + x2 + x3 + x4 + x5 + x6;
// Calculating Y’s
double y1, y2, y3, y4, y5, y6;
// y1
if (x1 > 0)
y1 = mn;
else
y1 = 0;
// y2
if (x2 > 0)
y2 = mn + (mx – mn) / 4;
else
y2 = 0;
// y3
if (x3 > 0)
y3 = mn + (mx – mn) / 4;
else
y3 = 0;
// y4
if (x4 > 0)
y4 = mn + (mx – mn) / 2;
else
y4 = 0;
// y5
if (x5 > 0)
y5 = mn + (mx – mn) / 2;
else
y5 = 0;
// y6
if ((finalH > 0) && ((y1 + y2 + y3 + y4 + y5) == 0))
y6 = mn;
else
y6 = 0;
double finalL = y1 + y2 + y3 + y4 + y5 + y6;
double dmml = (finalH – finalL) / 8;
mml[0] = (finalL – dmml * 2); //-2/8
for (int i = 1; i < OctLinesCnt; i++)
mml[i] = mml[i – 1] + dmml;
int first_bar = (int)ChartGetInteger(0, CHART_FIRST_VISIBLE_BAR);
if (first_bar == 0) return 0; // Data not ready.
if (LabelSide == Right) first_bar = 1;
for (int i = 0; i < OctLinesCnt; i++)
{
string name = ObjectPrefix + IntegerToString(i);
if (ObjectFind(0, name) == -1)
{
ObjectCreate(0, name, OBJ_HLINE, 0, Time[0], mml[i]);
ObjectSetInteger(0, name, OBJPROP_STYLE, STYLE_SOLID);
ObjectSetInteger(0, name, OBJPROP_COLOR, mml_clr[i]);
ObjectSetInteger(0, name, OBJPROP_WIDTH, mml_wdth[i]);
}
else ObjectMove(0, name, 0, Time[0], mml[i]);
name = ObjectPrefix + „txt” + IntegerToString(i);
if (ObjectFind(0, name) == -1)
{
ObjectCreate(0, name, OBJ_TEXT, 0, Time[first_bar – 1], mml[i]);
ObjectSetString(0, name, OBJPROP_TEXT, ln_txt[i]);
ObjectSetInteger(0, name, OBJPROP_FONTSIZE, FontSize);
ObjectSetString(0, name, OBJPROP_FONT, FontFace);
ObjectSetInteger(0, name, OBJPROP_COLOR, mml_clr[i]);
ObjectSetInteger(0, name, OBJPROP_ANCHOR, ANCHOR_LEFT_UPPER);
}
else ObjectMove(0, name, 0, Time[first_bar – 1], mml[i]);
}
string name = ObjectPrefix + „LatestCalcBar”;
if (ObjectFind(0, name) == -1)
{
ObjectCreate(0, name, OBJ_ARROW, 0, Time[StepBack], Low[StepBack] – 2 * _Point);
ObjectSetInteger(0, name, OBJPROP_ARROWCODE, MarkNumber);
ObjectSetInteger(0, name, OBJPROP_COLOR, MarkColor);
}
else ObjectMove(0, name, 0, Time[StepBack], Low[StepBack] – 2 * _Point);
nTime = Time[0];
}
if ((!NativeAlerts) && (!EmailAlerts) && (!NotificationAlerts)) return rates_total;
for (int i = 0; i < 13; i++) // Process alerts for each line.
{
// Current Signal calculation.
int Signal = 0; // No signal at all.
// UP: Current Close above the Line while either current Open is below the Line or previous Close is below the Line.
if (Close[TriggerCandle] > mml[i])
{
if (((Open[TriggerCandle] <= mml[i])) || (Close[TriggerCandle + 1] <= mml[i])) Signal = 1;
}
// DOWN: Current Close below the Line while either current Open is above the Line or previous Close is above the Line.
else if (Close[TriggerCandle] < mml[i])
{
if (((Open[TriggerCandle] >= mml[i])) || (Close[TriggerCandle + 1] >= mml[i])) Signal = -1;
}
if (prevSignal[i] == 42) // Avoiding initial alert.
{
prevSignal[i] = Signal;
continue;
}
if (((TriggerCandle > 0) && (Time[TriggerCandle] > LastAlertTime[i])) || (TriggerCandle == 0))
{
string Text;
// UP signal.
if ((Signal == 1) && (prevSignal[i] != 1))
{
Text = „MMLX: ” + Symbol() + ” – ” + StringSubstr(EnumToString((ENUM_TIMEFRAMES)Period()), 7) + ” – Breach Up: ” + ln_txt[i] + ” at ” + DoubleToString(mml[i], _Digits) + „.”;
DoAlerts(Text);
LastAlertTime[i] = Time[TriggerCandle];
}
// DOWN signal.
else if ((Signal == -1) && (prevSignal[i] != -1))
{
Text = „MMLX: ” + Symbol() + ” – ” + StringSubstr(EnumToString((ENUM_TIMEFRAMES)Period()), 7) + ” – Breach Down: ” + ln_txt[i] + ” at ” + DoubleToString(mml[i], _Digits) + „.”;
DoAlerts(Text);
LastAlertTime[i] = Time[TriggerCandle];
}
}
prevSignal[i] = Signal;
}
return rates_total;
}
void DoAlerts(string Text)
{
if (NativeAlerts) Alert(Text);
if (EmailAlerts) SendMail(Text, Text);
if (NotificationAlerts) SendNotification(Text);
}
//+——————————————————————+
//+——————————————————————+
//| Support and Resistance.mq4 |
//| https://t.me/ForexEaPremium |
//+——————————————————————+
#property copyright „https://t.me/ForexEaPremium”
#property version „2.02”
#property strict
#property description „Blue and red support and resistance levels displayed directly on the chart.”
#property description „Alerts for close above resistance and close below support.”
#property indicator_chart_window
#property indicator_buffers 2
#property indicator_color1 clrRed
#property indicator_width1 2
#property indicator_type1 DRAW_ARROW
#property indicator_label1 „Resistance”
#property indicator_color2 clrBlue
#property indicator_width2 2
#property indicator_type2 DRAW_ARROW
#property indicator_label2 „Support”
enum enum_candle_to_check
{
Current,
Previous
};
input bool EnableNativeAlerts = false;
input bool EnableEmailAlerts = false;
input bool EnablePushAlerts = false;
input enum_candle_to_check TriggerCandle = Previous;
double Resistance[];
double Support[];
datetime LastAlertTime = D’01.01.1970′;
void OnInit()
{
SetIndexBuffer(0, Resistance);
SetIndexBuffer(1, Support);
SetIndexArrow(0, 119);
SetIndexArrow(1, 119);
SetIndexDrawBegin(0, 5);
SetIndexDrawBegin(1, 5);
}
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[]
)
{
if (rates_total < 5) return 0;
for (int i = rates_total – 2; i >= 0; i–)
{
double upper_fractal = iFractals(NULL, 0, MODE_UPPER, i);
if (upper_fractal > 0)
Resistance[i] = High[i];
else
Resistance[i] = Resistance[i + 1];
double lower_fractal = iFractals(NULL, 0, MODE_LOWER, i);
if (lower_fractal > 0)
Support[i] = Low[i];
else
Support[i] = Support[i + 1];
}
// Alerts
if (((TriggerCandle > 0) && (Time[0] > LastAlertTime)) || (TriggerCandle == 0))
{
string Text;
// Resistance.
if ((Close[TriggerCandle] > Resistance[TriggerCandle]) && (Close[TriggerCandle + 1] <= Resistance[TriggerCandle]))
{
Text = „S&R: ” + Symbol() + ” – ” + StringSubstr(EnumToString((ENUM_TIMEFRAMES)Period()), 7) + ” – Closed above Resistance: ” + DoubleToString(Resistance[TriggerCandle], _Digits) + „.”;
if (EnableNativeAlerts) Alert(Text);
if (EnableEmailAlerts) SendMail(„S&R Alert”, Text);
if (EnablePushAlerts) SendNotification(Text);
LastAlertTime = Time[0];
}
// Support.
if ((Close[TriggerCandle] < Support[TriggerCandle]) && (Close[TriggerCandle + 1] >= Support[TriggerCandle]))
{
Text = „S&R: ” + Symbol() + ” – ” + StringSubstr(EnumToString((ENUM_TIMEFRAMES)Period()), 7) + ” – Closed below Support: ” + DoubleToString(Support[TriggerCandle], _Digits) + „.”;
if (EnableNativeAlerts) Alert(Text);
if (EnableEmailAlerts) SendMail(„S&R Alert”, Text);
if (EnablePushAlerts) SendNotification(Text);
LastAlertTime = Time[0];
}
}
return rates_total;
}
//+——————————————————————+
//+——————————————————————+
//| TotalPowerIndicator.mq4 |
//| https://t.me/ForexEaPremium |
//+——————————————————————+
#property copyright „https://t.me/ForexEaPremium”
#property link „https://t.me/ForexEaPremium”
#property version „1.01”
#property strict
#property description „Displays the concentration of bull power periods, bear power periods, and total periods when either bulls or bears had prevalence.”
#property description „Supports two events for alerts:”
#property description „1. Bull/Bear Power == 100, which is a strong reversal signal.”
#property description „2. Bull/Bear Crossover, which is a strong trend signal.”
#property indicator_separate_window
#property indicator_minimum -10
#property indicator_maximum 110
#property indicator_level1 50
#property indicator_level2 100
#property indicator_buffers 3
#property indicator_color1 clrLightSeaGreen
#property indicator_type1 DRAW_LINE
#property indicator_width1 2
#property indicator_label1 „Total Power”
#property indicator_color2 clrCrimson
#property indicator_type2 DRAW_LINE
#property indicator_width2 2
#property indicator_label2 „Bear Power”
#property indicator_color3 clrDarkGreen
#property indicator_type3 DRAW_LINE
#property indicator_width3 2
#property indicator_label3 „Bull Power”
enum enum_candle_to_check
{
Current,
Previous
};
input int Lookback_Period = 45; // Lookback Period
input int Power_Period = 10; // Power Period
input bool AlertOn100Power = false; // Alert on 100 Power
input bool AlertOnCrossover = false; // Alert on Crossover
input bool EnableNativeAlerts = false;
input bool EnableEmailAlerts = false;
input bool EnablePushAlerts = false;
input enum_candle_to_check TriggerCandle = Previous;
double Power[];
double Bears[];
double Bulls[];
datetime LastAlertTime = D’01.01.1970′;
void OnInit()
{
SetIndexBuffer(0, Power);
SetIndexBuffer(1, Bears);
SetIndexBuffer(2, Bulls);
PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, Power_Period + Lookback_Period);
PlotIndexSetInteger(1, PLOT_DRAW_BEGIN, Power_Period + Lookback_Period);
PlotIndexSetInteger(2, PLOT_DRAW_BEGIN, Power_Period + Lookback_Period);
IndicatorSetInteger(INDICATOR_DIGITS, 2);
IndicatorSetString(INDICATOR_SHORTNAME, „TPI (” + IntegerToString(Lookback_Period) + „, ” + IntegerToString(Power_Period) + „)”);
}
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 counted_bars = IndicatorCounted();
if (Bars <= Power_Period + Lookback_Period) return 0; // Not enough bars.
int limit = Bars – counted_bars – 1;
if (limit >= Bars – Lookback_Period) limit = Bars – Lookback_Period; // Cannot start that far.
for (int i = limit; i >= 0; i–)
{
int bearcount = 0;
int bullcount = 0;
for (int j = 0; j <= Lookback_Period – 1; j++)
{
if (iBearsPower(NULL, 0, Power_Period, PRICE_CLOSE, j + i) < 0) bearcount++;
if (iBullsPower(NULL, 0, Power_Period, PRICE_CLOSE, j + i) > 0) bullcount++;
}
Power[i] = MathAbs(bullcount – bearcount) * 100 / Lookback_Period;
Bears[i] = bearcount * 100 / Lookback_Period;
Bulls[i] = bullcount * 100 / Lookback_Period;
}
// Alerts
if (((TriggerCandle > 0) && (Time[0] > LastAlertTime)) || (TriggerCandle == 0))
{
string Text;
if (AlertOn100Power)
{
// 100 Bull Power.
if ((Bulls[TriggerCandle] == 100) && (Bulls[TriggerCandle + 1] < 100))
{
Text = „TPI: ” + Symbol() + ” – ” + StringSubstr(EnumToString((ENUM_TIMEFRAMES)Period()), 7) + ” – Bull Power = 100!”;
if (EnableNativeAlerts) Alert(Text);
if (EnableEmailAlerts) SendMail(„TPI Alert”, Text);
if (EnablePushAlerts) SendNotification(Text);
LastAlertTime = Time[0];
}
// 100 Bear Power
if ((Bears[TriggerCandle] == 100) && (Bears[TriggerCandle + 1] < 100))
{
Text = „TPI: ” + Symbol() + ” – ” + StringSubstr(EnumToString((ENUM_TIMEFRAMES)Period()), 7) + ” – Bear Power = 100!”;
if (EnableNativeAlerts) Alert(Text);
if (EnableEmailAlerts) SendMail(„TPI Alert”, Text);
if (EnablePushAlerts) SendNotification(Text);
LastAlertTime = Time[0];
}
}
if (AlertOnCrossover)
{
// Bull > Bear.
if ((Bulls[TriggerCandle] > Bears[TriggerCandle]) && (Bulls[TriggerCandle + 1] <= Bears[TriggerCandle + 1]))
{
Text = „TPI: ” + Symbol() + ” – ” + StringSubstr(EnumToString((ENUM_TIMEFRAMES)Period()), 7) + ” – Bull Power is now greater than Bear Power.”;
if (EnableNativeAlerts) Alert(Text);
if (EnableEmailAlerts) SendMail(„TPI Alert”, Text);
if (EnablePushAlerts) SendNotification(Text);
LastAlertTime = Time[0];
}
// Bear > Bull.
if ((Bulls[TriggerCandle] < Bears[TriggerCandle]) && (Bulls[TriggerCandle + 1] >= Bears[TriggerCandle + 1]))
{
Text = „TPI: ” + Symbol() + ” – ” + StringSubstr(EnumToString((ENUM_TIMEFRAMES)Period()), 7) + ” – Bear Power is now greater than Bull Power.”;
if (EnableNativeAlerts) Alert(Text);
if (EnableEmailAlerts) SendMail(„TPI Alert”, Text);
if (EnablePushAlerts) SendNotification(Text);
LastAlertTime = Time[0];
}
}
}
return rates_total;
}
//+——————————————————————+
//+——————————————————————+
//| TD Sequential Ultimate |
//| https://t.me/ForexEaPremium |
//+——————————————————————+
#property copyright „https://t.me/ForexEaPremium”
#property link „https://t.me/ForexEaPremium”
#property version „1.03”
#property strict
#property description „Shows setups and countdowns based on Tom DeMark’s Sequential method.”
#property description „TDST support and resistance levels are marked too.”
#property description „Optional alerts available.”
/*
For iCustom():
Buffer #0 – TDST Resistance: actual price level. EMPTY_VALUE on empty value.
Buffer #1 – TDST Support: actual price level. EMPTY_VALUE on empty value.
Buffer #2 – Setup: candle number – positive for Buy Setup, negative for Sell Setup. 0 on empty value.
Buffer #3 – Countdown: candle number – positive for Buy Countdown, negative for Sell Countdown. 0 on empty value.
Buffer #4 – Setup Perfection: 1.0 for Buy Setup Perfection, -1.0 for Sell Setup Perfection. 0 on empty value.
*/
#property indicator_chart_window
#property indicator_buffers 5 // +3 buffers for usage with iCustom(), they won’t be displayed by the indicator.
#property indicator_plots 5
#property indicator_color1 clrRed
#property indicator_type1 DRAW_ARROW // Arrows are better because line support/resistance have vertical connections.
#property indicator_width1 1
#property indicator_label1 „TDST Resistance”
#property indicator_color2 clrGreen
#property indicator_type2 DRAW_ARROW
#property indicator_width2 1
#property indicator_label2 „TDST Support”
#property indicator_color3 clrNONE
#property indicator_type3 DRAW_NONE
#property indicator_color4 clrNONE
#property indicator_type4 DRAW_NONE
#property indicator_color5 clrNONE
#property indicator_type5 DRAW_NONE
//input group „Calculation”
input int MaxBars = 1000; // MaxBars: how many bars to calculate; 0 = all bars.
//input group „Display”
input color BuySetupColor = clrLime;
input color SellSetupColor = clrRed;
input color CountdownColor = clrOrange;
input string FontFace = „Verdana”;
input int FontSize = 12;
input int ArrowWidth = 2;
input int PixelDistance = 3;
input string Prefix = „TDS_”;
//input group „Alerts”
input bool AlertOnSetup = false;
input bool AlertOnPerfecting = false;
input bool AlertOnCountdown13 = false;
input bool AlertOnSupportResistance = false;
input bool AlertNative = false;
input bool AlertEmail = false;
input bool AlertNotification = false;
// Support and resistance buffers – shown on the chart.
double Resistance[], Support[];
// These buffers will be used only by other indicators or EAs calling this one via iCustom().
double Setup[], Countdown[], Perfection[];
uint FontPixelHeight;
enum ENUM_COUNT_TYPE
{
COUNT_TYPE_BUY_SETUP,
COUNT_TYPE_SELL_SETUP,
COUNT_TYPE_BUY_COUNTDOWN,
COUNT_TYPE_SELL_COUNTDOWN,
COUNT_TYPE_BUY_PERFECTION,
COUNT_TYPE_SELL_PERFECTION
};
enum ENUM_ALERT_TYPE
{
ALERT_TYPE_SETUP_BUY,
ALERT_TYPE_SETUP_SELL,
ALERT_TYPE_PERFECTING_BUY,
ALERT_TYPE_PERFECTING_SELL,
ALERT_TYPE_COUNT13_BUY,
ALERT_TYPE_COUNT13_SELL,
ALERT_TYPE_SUPPORT,
ALERT_TYPE_RESISTANCE
};
int OnInit()
{
SetIndexBuffer(0, Resistance, INDICATOR_DATA);
SetIndexBuffer(1, Support, INDICATOR_DATA);
SetIndexBuffer(2, Setup, INDICATOR_DATA);
SetIndexBuffer(3, Countdown, INDICATOR_DATA);
SetIndexBuffer(4, Perfection, INDICATOR_DATA);
SetIndexArrow(0, 158);
SetIndexArrow(1, 158);
PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, EMPTY_VALUE);
PlotIndexSetDouble(1, PLOT_EMPTY_VALUE, EMPTY_VALUE);
// Calculate the height of the font in pixels – will be needed later to space counts and arrows.
string text = „0”; // Any dummy digit text to get its height.
// Get the height of the text based on font and its size. Negative because OS-dependent, *10 because set in 1/10 of pt.
TextSetFont(FontFace, FontSize * -10);
uint w; // Dummy variable, not used anywhere except this call.
TextGetSize(text, w, FontPixelHeight);
return(INIT_SUCCEEDED);
}
void OnDeinit(const int reason)
{
ObjectsDeleteAll(0, Prefix);
}
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[])
{
static double Preceding_Close = 0;
static bool Use_Preceding_Close = false;
static int Setup_Buy = 0;
static datetime Setup_Buy_First_Candle = 0;
static double Setup_Buy_Highest_High = 0;
static double Setup_Buy_Highest_High_Candidate = 0;
static double Setup_Buy_6_Low = 0;
static double Setup_Buy_7_Low = 0;
static bool No_More_Countdown_Buy_Until_Next_Buy_Setup = false;
static bool Setup_Buy_Perfected = false;
static bool Setup_Buy_Needs_Perfecting = false;
static int Countdown_Buy = 0;
static double Countdown_Buy_8_Close = 0;
static int Setup_Sell = 0;
static datetime Setup_Sell_First_Candle = 0;
static double Setup_Sell_Lowest_Low = 0;
static double Setup_Sell_Lowest_Low_Candidate = 0;
static double Setup_Sell_6_High = 0;
static double Setup_Sell_7_High = 0;
static bool No_More_Countdown_Sell_Until_Next_Sell_Setup = false;
static bool Setup_Sell_Perfected = false;
static bool Setup_Sell_Needs_Perfecting = false;
static int Countdown_Sell = 0;
static double Countdown_Sell_8_Close = 0;
if (rates_total < 7) return(0); // Not enough bars to start anything.
int counted_bars = prev_calculated > 0 ? prev_calculated – 1 : 0;
if (counted_bars < 0) return(-1);
int limit = MathMin(rates_total – 1 – counted_bars, rates_total – 6); // „- 6” because „+ 5” is used in the cycle.
if (limit < 1) return(prev_calculated); // Data not yet ready.
// Need to reset everything because prev_calculated is set to 0 when big chunks of new data are synced.
if (prev_calculated == 0)
{
Setup_Buy = 0;
Setup_Buy_First_Candle = 0;
Setup_Buy_Highest_High = 0;
Setup_Buy_6_Low = 0;
Setup_Buy_7_Low = 0;
No_More_Countdown_Buy_Until_Next_Buy_Setup = false;
Setup_Buy_Perfected = false;
Setup_Buy_Needs_Perfecting = false;
Countdown_Buy = 0;
Countdown_Buy_8_Close = 0;
Setup_Sell = 0;
Setup_Sell_First_Candle = 0;
Setup_Sell_Lowest_Low = 0;
Setup_Sell_6_High = 0;
Setup_Sell_7_High = 0;
No_More_Countdown_Sell_Until_Next_Sell_Setup = false;
Setup_Sell_Perfected = false;
Setup_Sell_Needs_Perfecting = false;
Countdown_Sell = 0;
Countdown_Sell_8_Close = 0;
ObjectsDeleteAll(0, Prefix);
for (int i = 0; i < rates_total; i++)
{
Setup[i] = 0;
Countdown[i] = 0;
Perfection[i] = 0;
Support[i] = EMPTY_VALUE;
Resistance[i] = EMPTY_VALUE;
}
}
limit = MathMin(limit, MaxBars);
for (int i = limit; i > 0; i–)
{
Setup[i] = 0;
Countdown[i] = 0;
Perfection[i] = 0;
// Cancel S/R or propagate them:
if ((Resistance[i + 1] != EMPTY_VALUE) && (Close[i] > Resistance[i + 1]))
{
Resistance[i] = EMPTY_VALUE;
if (AlertOnSupportResistance) DoAlert(i, ALERT_TYPE_RESISTANCE);
}
else Resistance[i] = Resistance[i + 1];
if ((Support[i + 1] != EMPTY_VALUE) && (Close[i] < Support[i + 1]))
{
Support[i] = EMPTY_VALUE;
if (AlertOnSupportResistance) DoAlert(i, ALERT_TYPE_SUPPORT);
}
else Support[i] = Support[i + 1];
// Buy Setup.
// Price Flip check +
// First Buy Setup candle +
// Setup_Buy == 0 for when no previous Buy Setup present. Setup_Buy == 9 for when one Buy Setup follows another:
if ((Close[i + 1] >= Close[i + 5]) && (Close[i] < Close[i + 4]) && ((Setup_Buy == 0) || (Setup_Buy == 9)))
{
// Remember Close before the Setup’s first bar (needed further for TDST Resistance).
Preceding_Close = Close[i + 1];
Use_Preceding_Close = false;
// Set initial values.
Setup_Buy = 1;
PutCount(COUNT_TYPE_BUY_SETUP, IntegerToString(Setup_Buy), Time[i], Low[i]);
Setup_Buy_First_Candle = Time[i]; // Remember the first candle to wipe the Setup if it fails before completing.
Setup_Buy_Highest_High_Candidate = High[i];
Setup[i] = Setup_Buy;
}
// Buy Setup candles – second through nine:
else if ((Close[i] < Close[i + 4]) && (Setup_Buy > 0) && (Setup_Buy < 9))
{
Setup_Buy++;
Setup[i] = Setup_Buy;
PutCount(COUNT_TYPE_BUY_SETUP, IntegerToString(Setup_Buy), Time[i], Low[i]);
if (Setup_Buy_Highest_High_Candidate < High[i]) Setup_Buy_Highest_High_Candidate = High[i];
// These are needed for perfection checks.
if (Setup_Buy == 6) Setup_Buy_6_Low = Low[i];
if (Setup_Buy == 7) Setup_Buy_7_Low = Low[i];
if (Setup_Buy == 9)
{
if (Countdown_Sell > 0)
{
Countdown_Sell = 0; // Reset Sell Countdown.
RemoveCount(COUNT_TYPE_SELL_COUNTDOWN, Time[i]);
}
No_More_Countdown_Sell_Until_Next_Sell_Setup = true;
if (AlertOnSetup) DoAlert(i, ALERT_TYPE_SETUP_BUY);
Setup_Buy_Perfected = false; // Will be checked farther.
Setup_Buy_Needs_Perfecting = true;
No_More_Countdown_Buy_Until_Next_Buy_Setup = false;
Setup_Sell = 0;
if (Preceding_Close > Setup_Buy_Highest_High_Candidate)
{
Setup_Buy_Highest_High = Preceding_Close;
Use_Preceding_Close = true;
}
else Setup_Buy_Highest_High = Setup_Buy_Highest_High_Candidate;
int res_count = 9;
if (Use_Preceding_Close) res_count = 10; // If preceding bar’s Close is used to draw the Resistance line, it should be started at that bar’s Close.
for (int j = i; j < i + res_count; j++)
{
Resistance[j] = Setup_Buy_Highest_High;
if (High[j] == Setup_Buy_Highest_High) break;
}
// Check perfecting:
// Setup candle #8:
if ((Low[i + 1] < Setup_Buy_6_Low) && (Low[i + 1] < Setup_Buy_7_Low))
{
Setup_Buy_Perfected = true;
Setup_Buy_Needs_Perfecting = false;
Perfection[i + 1] = 1;
PutCount(COUNT_TYPE_BUY_PERFECTION, „233”, Time[i + 1], High[i + 1]); // Arrow up.
if (AlertOnPerfecting) DoAlert(i + 1, ALERT_TYPE_PERFECTING_BUY);
}
// Countdown can also start on this candle but farther in the code.
}
}
// Buy Setup broken:
else if ((Close[i] >= Close[i + 4]) && (Setup_Buy != 9) && (Setup_Buy != 0))
{
RemoveCount(COUNT_TYPE_BUY_SETUP, Setup_Buy_First_Candle, Setup_Buy); // Remove number objects for this Buy Setup.
Setup_Buy = 0;
Setup_Buy_First_Candle = 0;
Setup_Buy_Highest_High_Candidate = 0;
Setup_Buy_Needs_Perfecting = false;
Setup_Buy_Perfected = false;
}
// Buy Countdown check.
if ((!No_More_Countdown_Buy_Until_Next_Buy_Setup) && ((Setup_Buy == 9) || (Countdown_Buy > 0))) // Have a completed Buy Setup or a started Countdown.
{
if (Countdown_Buy < 13)
{
if (Close[i] <= Low[i + 2])
{
if (Countdown_Buy < 12) // Normal condition for Countdown candles from 1 through 12.
{
Countdown_Buy++;
if (Countdown_Buy == 8) Countdown_Buy_8_Close = Close[i]; // Remember 8th Countdown close for checking the 13th.
Countdown[i] = Countdown_Buy;
PutCount(COUNT_TYPE_BUY_COUNTDOWN, IntegerToString(Countdown_Buy), Time[i], Low[i]);
}
else if (Low[i] < Countdown_Buy_8_Close) // Special condition for Countdown candle 13.
{
Countdown_Buy++;
Countdown[i] = Countdown_Buy;
PutCount(COUNT_TYPE_BUY_COUNTDOWN, IntegerToString(Countdown_Buy), Time[i], Low[i]);
if (AlertOnCountdown13) DoAlert(i, ALERT_TYPE_COUNT13_BUY);
Countdown_Buy = 0; // Reset Countdown as we have already reached count 13.
No_More_Countdown_Buy_Until_Next_Buy_Setup = true;
}
else // Failed Countdown candles 13 are marked with +.
{
Countdown[i] = 14;
PutCount(COUNT_TYPE_BUY_COUNTDOWN, „+”, Time[i], Low[i]);
}
}
}
}
// Check if Countdown is broken.
if (Countdown_Buy > 0) // Have a Buy Countdown that can be interrupted.
{
if ((Low[i] > Setup_Buy_Highest_High) && (Close[i + 1] > Setup_Buy_Highest_High))
{
Countdown_Buy = 0;
RemoveCount(COUNT_TYPE_BUY_COUNTDOWN, Time[i]);
Setup_Buy = 0;
}
}
// Check if Setup is perfected.
if ((!Setup_Buy_Perfected) && (Setup_Buy_Needs_Perfecting)) // Setup Buy candles #9+.
{
if ((Low[i] < Setup_Buy_6_Low) && (Low[i] < Setup_Buy_7_Low))
{
Setup_Buy_Perfected = true;
Setup_Buy_Needs_Perfecting = false;
Perfection[i] = 1;
PutCount(COUNT_TYPE_BUY_PERFECTION, „233”, Time[i], High[i]); // Arrow up.
if (AlertOnPerfecting) DoAlert(i, ALERT_TYPE_PERFECTING_BUY);
}
}
// Sell Setup.
// Price Flip check +
// First Sell Setup candle +
// Setup_Sell == 0 for when no previous Sell Setup present. Setup_Sell == 9 for when one Sell Setup follows another:
if ((Close[i + 1] <= Close[i + 5]) && (Close[i] > Close[i + 4]) && ((Setup_Sell == 0) || (Setup_Sell == 9)))
{
// Remember Close before the Setup’s first bar (needed further for TDST Support).
Preceding_Close = Close[i + 1];
Use_Preceding_Close = false;
// Set initial values.
Setup_Sell = 1;
PutCount(COUNT_TYPE_SELL_SETUP, IntegerToString(Setup_Sell), Time[i], High[i]);
Setup_Sell_First_Candle = Time[i]; // Remember the first candle to wipe the Setup if it fails before completing.
Setup_Sell_Lowest_Low_Candidate = Low[i];
Setup[i] = -Setup_Sell;
}
// Sell Setup candles – second through nine:
else if ((Close[i] > Close[i + 4]) && (Setup_Sell > 0) && (Setup_Sell < 9))
{
Setup_Sell++;
Setup[i] = -Setup_Sell;
PutCount(COUNT_TYPE_SELL_SETUP, IntegerToString(Setup_Sell), Time[i], High[i]);
if (Setup_Sell_Lowest_Low_Candidate > Low[i]) Setup_Sell_Lowest_Low_Candidate = Low[i];
// These are needed for perfection checks.
if (Setup_Sell == 6) Setup_Sell_6_High = High[i];
if (Setup_Sell == 7) Setup_Sell_7_High = High[i];
if (Setup_Sell == 9)
{
if (Countdown_Buy > 0)
{
Countdown_Buy = 0; // Reset Buy Countdown.
RemoveCount(COUNT_TYPE_BUY_COUNTDOWN, Time[i]);
}
No_More_Countdown_Buy_Until_Next_Buy_Setup = true;
if (AlertOnSetup) DoAlert(i, ALERT_TYPE_SETUP_SELL);
Setup_Sell_Perfected = false; // Will be checked farther.
Setup_Sell_Needs_Perfecting = true;
No_More_Countdown_Sell_Until_Next_Sell_Setup = false;
Setup_Buy = 0;
if (Preceding_Close < Setup_Sell_Lowest_Low_Candidate)
{
Setup_Sell_Lowest_Low = Preceding_Close;
Use_Preceding_Close = true;
}
else Setup_Sell_Lowest_Low = Setup_Sell_Lowest_Low_Candidate;
int supp_count = 9;
if (Use_Preceding_Close) supp_count = 10; // If preceding bar’s Close is used to draw the Support line, it should be started at that bar’s Close.
for (int j = i; j < i + supp_count; j++)
{
Support[j] = Setup_Sell_Lowest_Low;
if (Low[j] == Setup_Sell_Lowest_Low) break;
}
// Check perfecting:
// Setup candle #8:
if ((High[i + 1] > Setup_Sell_6_High) && (High[i + 1] > Setup_Sell_7_High))
{
Setup_Sell_Perfected = true;
Setup_Sell_Needs_Perfecting = false;
Perfection[i + 1] = -1;
PutCount(COUNT_TYPE_SELL_PERFECTION, „234”, Time[i + 1], Low[i + 1]); // Arrow down.
if (AlertOnPerfecting) DoAlert(i + 1, ALERT_TYPE_PERFECTING_SELL);
}
// Countdown can also start on this candle but farther in the code.
}
}
// Sell Setup broken:
else if ((Close[i] <= Close[i + 4]) && (Setup_Sell != 9) && (Setup_Sell != 0))
{
RemoveCount(COUNT_TYPE_SELL_SETUP, Setup_Sell_First_Candle, Setup_Sell); // Remove number objects for this Sell Setup.
Setup_Sell = 0;
Setup_Sell_First_Candle = 0;
Setup_Sell_Lowest_Low_Candidate = 0;
Setup_Sell_Needs_Perfecting = false;
Setup_Sell_Perfected = false;
}
// Sell Countdown check.
if ((!No_More_Countdown_Sell_Until_Next_Sell_Setup) && ((Setup_Sell == 9) || (Countdown_Sell > 0))) // Have a completed Sell Setup or a started Countdown.
{
if (Countdown_Sell < 13)
{
if (Close[i] >= High[i + 2])
{
if (Countdown_Sell < 12) // Normal condition for Countdown candles from 1 through 12.
{
Countdown_Sell++;
if (Countdown_Sell == 8) Countdown_Sell_8_Close = Close[i]; // Remember 8th Countdown close for checking the 13th.
Countdown[i] = -Countdown_Sell;
PutCount(COUNT_TYPE_SELL_COUNTDOWN, IntegerToString(Countdown_Sell), Time[i], High[i]);
}
else if (High[i] > Countdown_Sell_8_Close) // Special condition for Countdown candle 13.
{
Countdown_Sell++;
Countdown[i] = -Countdown_Sell;
PutCount(COUNT_TYPE_SELL_COUNTDOWN, IntegerToString(Countdown_Sell), Time[i], High[i]);
if (AlertOnCountdown13) DoAlert(i, ALERT_TYPE_COUNT13_SELL);
Countdown_Sell = 0; // Reset Countdown as we have already reached count 13.
No_More_Countdown_Sell_Until_Next_Sell_Setup = true;
}
else // Failed Countdown candles 13 are marked with +.
{
Countdown[i] = -14;
PutCount(COUNT_TYPE_SELL_COUNTDOWN, „+”, Time[i], High[i]);
}
}
}
}
// Check if Countdown is broken.
if (Countdown_Sell > 0) // Have a Sell Countdown that can be interrupted.
{
if ((High[i] < Setup_Sell_Lowest_Low) && (Close[i + 1] < Setup_Sell_Lowest_Low))
{
Countdown_Sell = 0;
RemoveCount(COUNT_TYPE_SELL_COUNTDOWN, Time[i]);
Setup_Sell = 0;
}
}
// Check if Setup is perfected.
if ((!Setup_Sell_Perfected) && (Setup_Sell_Needs_Perfecting)) // Setup Sell candles #9+.
{
if ((High[i] > Setup_Sell_6_High) && (High[i] > Setup_Sell_7_High))
{
Setup_Sell_Perfected = true;
Setup_Sell_Needs_Perfecting = false;
Perfection[i] = -1;
PutCount(COUNT_TYPE_SELL_PERFECTION, „234”, Time[i], Low[i]); // Arrow down.
if (AlertOnPerfecting) DoAlert(i, ALERT_TYPE_PERFECTING_SELL);
}
}
}
return(rates_total);
}
void OnChartEvent(const int id,
const long &lparam,
const double &dparam,
const string &sparam)
{
if ((id == CHARTEVENT_CHART_CHANGE) || (id == CHARTEVENT_CLICK)) RedrawVisibleLabels();
}
void PutCount(const ENUM_COUNT_TYPE count_type, const string s, const datetime time, const double price)
{
string name = Prefix;
color colour = clrNONE;
int level = 0;
ENUM_OBJECT object_type = OBJ_TEXT;
bool adjust_for_height = false;
switch(count_type)
{
case COUNT_TYPE_BUY_SETUP:
name += „BS”;
colour = BuySetupColor;
level = 1;
break;
case COUNT_TYPE_SELL_SETUP:
name += „SS”;
colour = SellSetupColor;
level = -1;
adjust_for_height = true;
break;
case COUNT_TYPE_BUY_COUNTDOWN:
name += „BC”;
colour = CountdownColor;
level = 2;
break;
case COUNT_TYPE_SELL_COUNTDOWN:
name += „SC”;
colour = CountdownColor;
level = -2;
adjust_for_height = true;
break;
case COUNT_TYPE_BUY_PERFECTION:
name += „BP”;
colour = BuySetupColor;
level = 3;
object_type = OBJ_ARROW;
break;
case COUNT_TYPE_SELL_PERFECTION:
name += „SP”;
colour = SellSetupColor;
level = -3;
object_type = OBJ_ARROW;
adjust_for_height = true;
break;
}
name += IntegerToString((int)time);
ObjectCreate(0, name, object_type, 0, time, price);
ObjectSetInteger(0, name, OBJPROP_COLOR, colour);
ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
ObjectSetInteger(0, name, OBJPROP_HIDDEN, false);
if ((count_type == COUNT_TYPE_BUY_PERFECTION) || (count_type == COUNT_TYPE_SELL_PERFECTION))
{
ObjectSetInteger(0, name, OBJPROP_ARROWCODE, StringToInteger(s));
ObjectSetInteger(0, name, OBJPROP_WIDTH, ArrowWidth);
}
else
{
ObjectSetInteger(0, name, OBJPROP_FONTSIZE, FontSize);
ObjectSetString(0, name, OBJPROP_FONT, FontFace);
ObjectSetString(0, name, OBJPROP_TEXT, s);
ObjectSetInteger(0, name, OBJPROP_ANCHOR, ANCHOR_UPPER);
}
RedrawOneWickLabel(name, time, price, level);
}
// level – positional level above (-) and below the candles (+).
void RedrawOneWickLabel(const string name, const datetime time, const double price, const int level)
{
int x, y, cw;
datetime t;
double p;
if (ObjectFind(0, name) == -1) return;
int distance = 0;
if (level < 0) distance = level * (int)FontPixelHeight + level * PixelDistance; // Objects above the candle should be additionally adjusted for their own height.
else distance = (level – 1) * (int)FontPixelHeight + level * PixelDistance;
// Needed only for y; x is used as a dummy.
ChartTimePriceToXY(0, 0, time, price, x, y);
ChartXYToTimePrice(0, x, y + distance, cw, t, p);
ObjectSetDouble(0, name, OBJPROP_PRICE, p);
}
void RedrawVisibleLabels()
{
int visible_bars = (int)ChartGetInteger(0, CHART_VISIBLE_BARS);
int first_bar = (int)ChartGetInteger(0, CHART_FIRST_VISIBLE_BAR);
int last_bar = first_bar – visible_bars + 1;
// Process all bars on the current screen.
// Cycle through all possible object names based on prefix + count_type_name + timestamp.
for (int i = first_bar; i >= last_bar; i–)
{
datetime time = Time[i];
double low = Low[i];
double high = High[i];
string time_string = IntegerToString((int)time);
RedrawOneWickLabel(Prefix + „BS” + time_string, time, low, 1);
RedrawOneWickLabel(Prefix + „SS” + time_string, time, high, -1);
RedrawOneWickLabel(Prefix + „BC” + time_string, time, low, 2);
RedrawOneWickLabel(Prefix + „SC” + time_string, time, high, -2);
RedrawOneWickLabel(Prefix + „BP” + time_string, time, low, 3);
RedrawOneWickLabel(Prefix + „SP” + time_string, time, high, -3);
}
}
// Remove number objects for a given setup or countdown.
void RemoveCount(const ENUM_COUNT_TYPE count_type, const datetime begin, const int n = 0)
{
string name_start = Prefix;
if (count_type == COUNT_TYPE_BUY_SETUP) name_start += „BS”;
else if (count_type == COUNT_TYPE_SELL_SETUP) name_start += „SS”;
else if (count_type == COUNT_TYPE_BUY_COUNTDOWN) name_start += „BC”;
else if (count_type == COUNT_TYPE_SELL_COUNTDOWN) name_start += „SC”;
int begin_candle = iBarShift(Symbol(), Period(), begin, true);
if (begin_candle == -1) return; // Some data error.
// Setup
if ((count_type == COUNT_TYPE_BUY_SETUP) || (count_type == COUNT_TYPE_SELL_SETUP))
{
for (int i = begin_candle; i > begin_candle – n; i–)
{
string name = name_start + IntegerToString(Time[i]);
ObjectDelete(0, name);
}
}
// Countdown
else if ((count_type == COUNT_TYPE_BUY_COUNTDOWN) || (count_type == COUNT_TYPE_SELL_COUNTDOWN))
{
// The number of countdown objects is unknown.
for (int i = begin_candle; i < Bars; i++)
{
string name = name_start + IntegerToString(Time[i]);
if (ObjectGetString(ChartID(), name, OBJPROP_TEXT) == „1”) // The last one.
{
ObjectDelete(0, name);
return;
}
ObjectDelete(0, name); // Attempt to delete even if it doesn’t exist.
}
}
}
void DoAlert(int i, ENUM_ALERT_TYPE alert_type)
{
if (i > 2) return; // i == 2 the earliest possible alert event that should be reacted on.
string main_text = „Sequential: ” + Symbol() + ” @ ” + EnumToString((ENUM_TIMEFRAMES)Period());
string email_subject = main_text;
//string
switch(alert_type)
{
case ALERT_TYPE_SETUP_BUY:
main_text += ” Buy Setup completed by ” + TimeToString(Time[i]) + ” candle.”;
email_subject += ” Buy Setup”;
break;
case ALERT_TYPE_SETUP_SELL:
main_text += ” Sell Setup completed by ” + TimeToString(Time[i]) + ” candle.”;
email_subject += ” Sell Setup”;
break;
case ALERT_TYPE_PERFECTING_BUY:
main_text += ” Buy Setup Perfected by ” + TimeToString(Time[i]) + ” candle.”;
email_subject += ” Buy Perfecting”;
break;
case ALERT_TYPE_PERFECTING_SELL:
main_text += ” Sell Setup Perfected by ” + TimeToString(Time[i]) + ” candle.”;
email_subject += ” Sell Perfecting”;
break;
case ALERT_TYPE_COUNT13_BUY:
main_text += ” Buy Countdown completed by ” + TimeToString(Time[i]) + ” candle.”;
email_subject += ” Buy Countdown”;
break;
case ALERT_TYPE_COUNT13_SELL:
main_text += ” Sell Countdown completed by ” + TimeToString(Time[i]) + ” candle.”;
email_subject += ” Sell Countdown”;
break;
case ALERT_TYPE_RESISTANCE:
main_text += ” TDST Resistance broken by ” + TimeToString(Time[i]) + ” candle.”;
email_subject += ” Buy TDST Resistance”;
break;
case ALERT_TYPE_SUPPORT:
main_text += ” TDST Support broken by ” + TimeToString(Time[i]) + ” candle.”;
email_subject += ” TDST Support”;
break;
}
if (AlertNative) Alert(main_text);
if (AlertEmail) SendMail(email_subject, main_text);
if (AlertNotification) SendNotification(main_text);
}
//+——————————————————————+
//+——————————————————————+
//| GainLossInfo.mq4 |
//+——————————————————————+
#property version „1.01”
#property strict
#property description „Shows percentage and point gain/loss for a candle.”
#property description „Can calculate gain/loss compared either to the previous Close or to the current Open.”
// The indicator uses only objects for display, but the line below is required for it to work.
#property indicator_chart_window
input double PercentageLimit = 1.0; // PercentageLimit – Will not display number if percentage gain/loss is below limit.
input int PointsLimit = 1000; // PointsLimit – Will not display number if points gain/loss is below limit.
// If true, will compare Close of the current candle to Close of the previous one. Otherwise compares current Close to current Open.
input bool CloseToClose = true;
input color DisplayLossColor = clrRed;
input color DisplayGainColor = clrLimeGreen;
input int DisplayDistance = 100; // DisplayDistance – Distance in points from High/Low to percentage display.
input int MaxBars = 100; // MaxBars: More bars – more objects – more lag and memory usage.
input string FontFace = „Verdana”;
input int FontSize = 10;
input string ObjectPrefix = „GLI-„;
void OnDeinit(const int reason)
{
ObjectsDeleteAll(0, ObjectPrefix, -1, OBJ_TEXT);
}
void OnChartEvent(const int id,
const long &lparam,
const double &dparam,
const string &sparam)
{
// Redraw visible labels.
if (id == CHARTEVENT_CHART_CHANGE) RedrawVisibleLabels();
}
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[])
{
string perc, points, name;
double start;
int counted_bars = IndicatorCounted();
if (counted_bars > 0) counted_bars–;
int limit = Bars – counted_bars;
if (limit > MaxBars) limit = MaxBars – 1;
for (int i = 0; i <= limit; i++)
{
if ((CloseToClose) && (i + 1 < Bars)) start = Close[i + 1];
else start = Open[i];
name = ObjectPrefix + „Percent-” + TimeToStr(Time[i], TIME_DATE | TIME_MINUTES);
ObjectDelete(name);
if (((Close[i] – start) / start) * 100 >= PercentageLimit) // Gain percent display
{
perc = DoubleToStr(((Close[i] – start) / start) * 100, 1) + „%”;
ObjectCreate(name, OBJ_TEXT, 0, Time[i], High[i]);
ObjectSetText(name, perc, FontSize, FontFace, DisplayGainColor);
int visible_bars = (int)ChartGetInteger(0, CHART_VISIBLE_BARS);
int first_bar = (int)ChartGetInteger(0, CHART_FIRST_VISIBLE_BAR);
int last_bar = first_bar – visible_bars + 1;
if ((i <= first_bar) && (i >= last_bar)) RedrawOneLabel(i, last_bar);
ObjectSetInteger(0, name, OBJPROP_ANCHOR, ANCHOR_UPPER);
ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
ObjectSetInteger(0, name, OBJPROP_HIDDEN, true);
}
else if (((start – Close[i]) / start) * 100 >= PercentageLimit) // Loss percent display
{
perc = DoubleToStr(((start – Close[i]) / start) * 100, 1) + „%”;
ObjectCreate(name, OBJ_TEXT, 0, Time[i], High[i]);
ObjectSetText(name, perc, FontSize, FontFace, DisplayLossColor);
int visible_bars = (int)ChartGetInteger(0, CHART_VISIBLE_BARS);
int first_bar = (int)ChartGetInteger(0, CHART_FIRST_VISIBLE_BAR);
int last_bar = first_bar – visible_bars + 1;
if ((i <= first_bar) && (i >= last_bar)) RedrawOneLabel(i, last_bar);
ObjectSetInteger(0, name, OBJPROP_ANCHOR, ANCHOR_UPPER);
ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
ObjectSetInteger(0, name, OBJPROP_HIDDEN, true);
}
name = ObjectPrefix + „Points-” + TimeToStr(Time[i], TIME_DATE | TIME_MINUTES);
ObjectDelete(name);
if ((Close[i] – start) / Point >= PointsLimit) // Gain points display
{
points = DoubleToStr((Close[i] – start) / Point, 0);
ObjectCreate(name, OBJ_TEXT, 0, Time[i], Low[i]);
ObjectSetText(name, points, FontSize, FontFace, DisplayGainColor);
ObjectSetInteger(0, name, OBJPROP_ANCHOR, ANCHOR_UPPER);
ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
ObjectSetInteger(0, name, OBJPROP_HIDDEN, true);
}
else if ((start – Close[i]) / Point >= PointsLimit) // Loss points display
{
points = DoubleToStr((start – Close[i]) / Point, 0);
ObjectCreate(name, OBJ_TEXT, 0, Time[i], Low[i]);
ObjectSetText(name, points, FontSize, FontFace, DisplayLossColor);
ObjectSetInteger(0, name, OBJPROP_ANCHOR, ANCHOR_UPPER);
ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
ObjectSetInteger(0, name, OBJPROP_HIDDEN, true);
}
}
return rates_total;
}
// Required only for labels above High.
void RedrawVisibleLabels()
{
int visible_bars = (int)ChartGetInteger(0, CHART_VISIBLE_BARS);
int first_bar = (int)ChartGetInteger(0, CHART_FIRST_VISIBLE_BAR);
int last_bar = first_bar – visible_bars + 1;
// Process all bars on the current screen.
for (int i = first_bar; i >= last_bar; i–) RedrawOneLabel(i, last_bar);
}
void RedrawOneLabel(const int i, const int last_bar)
{
int x, y, cw;
uint w, h;
datetime t;
double p;
string length, name;
name = GenerateObjectName(„Percent-„, Time[i]);
if (ObjectFind(0, name) == -1) return;
// Needed only for y; x is used as a dummy.
ChartTimePriceToXY(0, 0, Time[last_bar], High[i], x, y);
// Get the height of the text based on font and its size. Negative because OS-dependent, *10 because set in 1/10 of pt.
TextSetFont(FontFace, FontSize * -10);
length = DoubleToString(MathRound((High[i] – MathMax(Open[i], Close[i])) / Point), 0);
TextGetSize(length, w, h);
ChartXYToTimePrice(0, x, y – h – 2, cw, t, p);
ObjectSetDouble(0, name, OBJPROP_PRICE, p);
}
string GenerateObjectName(const string prefix, const datetime time)
{
return ObjectPrefix + prefix + TimeToStr(time, TIME_DATE | TIME_MINUTES);
}
//+——————————————————————+
//+——————————————————————+
// SchaffTrendCycle.mq4 |
//| https://t.me/ForexEaPremium |
//+——————————————————————+
#property copyright „https://t.me/ForexEaPremium”
#property link „https://t.me/ForexEaPremium”
#property version „1.04”
#property strict
#property description „Schaff Trend Cycle – Cyclical Stochastic over Stochastic over MACD.”
#property description „Falling below 75 is a sell signal.”
#property description „Rising above 25 is a buy signal.”
#property description „Four kinds of alert: arrows, text, sound, email, and push.”
#property indicator_separate_window
#property indicator_buffers 3
#property indicator_plots 1
#property indicator_minimum 0
#property indicator_maximum 100
#property indicator_level1 25
#property indicator_level2 75
#property indicator_width1 2
#property indicator_type1 DRAW_LINE
#property indicator_style1 STYLE_SOLID
#property indicator_color1 clrDarkOrchid
#property indicator_label1 „Schaff Trend Cycle”
#property indicator_color2 clrNONE
#property indicator_color3 clrNONE
//—- Input Parameters
input int MAShort = 23;
input int MALong = 50;
input int Cycle = 10;
input bool ShowArrows = false;
input color UpColor = clrBlue;
input color DownColor = clrRed;
input bool ShowAlerts = false;
input bool SoundAlerts = false;
input bool EmailAlerts = false;
input bool PushAlerts = false;
//—- Global Variables
double Factor = 0.5;
int BarsRequired;
datetime LastAlert = D’1980.01.01′;
//—- Buffers
double MACD[];
double ST[];
double ST2[];
//+——————————————————————+
//| Custom indicator initialization function |
//+——————————————————————+
void OnInit()
{
IndicatorShortName(„STC(” + IntegerToString(MAShort) + „,” + IntegerToString(MALong) + „,” + IntegerToString(Cycle) + „)”);
IndicatorBuffers(3);
SetIndexBuffer(0, ST2);
SetIndexBuffer(1, ST);
SetIndexBuffer(2, MACD);
SetIndexDrawBegin(0, MALong + Cycle * 2);
IndicatorDigits(0);
BarsRequired = MALong + Cycle * 2;
}
//+——————————————————————+
//| Custom indicator deinitialization function |
//+——————————————————————+
void OnDeinit(const int reason)
{
ObjectsDeleteAll(0, „ST_down_”);
ObjectsDeleteAll(0, „ST_up_”);
}
//+——————————————————————+
//| Schaff Trend Cycle |
//+——————————————————————+
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[]
)
{
if (Bars <= BarsRequired) return(0);
int counted_bars = IndicatorCounted();
double LLV = 0, HHV = 0;
int shift, n = 1, i;
// Static variables are used to flag that we already have calculated curves from the previous indicator run.
static bool st1_pass = false;
static bool st2_pass = false;
int st1_count = 0;
bool check_st1 = false, check_st2 = false;
if (counted_bars < BarsRequired)
{
for (i = 1; i <= BarsRequired; i++) ST2[Bars – i] = 0;
for (i = 1; i <= BarsRequired; i++) ST[Bars – i] = 0;
}
if (counted_bars > 0) counted_bars–;
shift = Bars – counted_bars + BarsRequired – MALong;
if (shift > Bars – 1) shift = Bars – 1;
while (shift >= 0)
{
double MA_Short = iMA(NULL, 0, MAShort, 0, MODE_EMA, PRICE_CLOSE, shift);
double MA_Long = iMA(NULL, 0, MALong, 0, MODE_EMA, PRICE_CLOSE, shift);
MACD[shift] = MA_Short – MA_Long;
if (n >= Cycle) check_st1 = true;
else n++;
if (check_st1)
{
// Finding Max and Min on Cycle of MA differences (MACD).
for (i = 0; i < Cycle; i++)
{
if (i == 0)
{
LLV = MACD[shift + i];
HHV = MACD[shift + i];
}
else
{
if (LLV > MACD[shift + i]) LLV = MACD[shift + i];
if (HHV < MACD[shift + i]) HHV = MACD[shift + i];
}
}
// Calculating first Stochastic.
if (HHV – LLV != 0) ST[shift] = ((MACD[shift] – LLV) / (HHV – LLV)) * 100;
else ST[shift] = ST[shift + 1];
// Smoothing first Stochastic.
if (st1_pass) ST[shift] = Factor * (ST[shift] – ST[shift + 1]) + ST[shift + 1];
st1_pass = true;
// Have enough elements of first Stochastic to proceed to second.
if (st1_count >= Cycle) check_st2 = true;
else st1_count++;
if (check_st2)
{
// Finding Max and Min on Cycle of first smoothed Stochastic.
for (i = 0; i < Cycle; i++)
{
if (i == 0)
{
LLV = ST[shift + i];
HHV = ST[shift + i];
}
else
{
if (LLV > ST[shift + i]) LLV = ST[shift + i];
if (HHV < ST[shift + i]) HHV = ST[shift + i];
}
}
// Calculating second Stochastic.
if (HHV – LLV != 0) ST2[shift] = ((ST[shift] – LLV) / (HHV – LLV)) * 100;
else ST2[shift] = ST2[shift + 1];
// Smoothing second Stochastic.
if (st2_pass) ST2[shift] = Factor * (ST2[shift] – ST2[shift + 1]) + ST2[shift + 1];
st2_pass = true;
Sleep(1);
}
}
if (shift < Bars – 1)
{
if ((ST2[shift] < 75) && (ST2[shift + 1] >= 75))
{
if (ShowArrows)
{
string name = „ST_down_” + TimeToString(Time[shift]);
double offset = (High[shift] – Low[shift]) / 2;
ObjectCreate(0, name, OBJ_ARROW, 0, Time[shift], High[shift] + offset + MarketInfo(Symbol(), MODE_SPREAD) * Point);
ObjectSet(name, OBJPROP_ARROWCODE, 234);
ObjectSet(name, OBJPROP_COLOR, DownColor);
ObjectSet(name, OBJPROP_SELECTABLE, false);
}
if ((shift == 1) && (LastAlert != Time[0]))
{
if (ShowAlerts) Alert(„Bearish signal on ” + Symbol() + „.”);
if (SoundAlerts) PlaySound(„alert.wav”);
if (EmailAlerts) SendMail(„Schaff Trend Cycle Alert”, „Bearish signal on ” + TimeToString(Time[0]) + ” on ” + Symbol() + „.”);
if (PushAlerts) SendNotification(„STC Alert: Bearish signal on ” + TimeToString(Time[0]) + ” on ” + Symbol() + „.”);
LastAlert = Time[0];
}
}
else if ((ST2[shift] > 25) && (ST2[shift + 1] <= 25))
{
if (ShowArrows)
{
string name = „ST_up_” + TimeToString(Time[shift]);
double offset = (High[shift] – Low[shift]) / 2;
ObjectCreate(0, name, OBJ_ARROW, 0, Time[shift], Low[shift] – offset);
ObjectSet(name, OBJPROP_ARROWCODE, 233);
ObjectSet(name, OBJPROP_COLOR, UpColor);
ObjectSet(name, OBJPROP_SELECTABLE, false);
}
if ((shift == 1) && (LastAlert != Time[0]))
{
if (ShowAlerts) Alert(„Bullish signal on ” + Symbol() + „.”);
if (SoundAlerts) PlaySound(„alert.wav”);
if (EmailAlerts) SendMail(„Schaff Trend Cycle Alert”, „Bullish signal on ” + TimeToString(Time[0]) + ” on ” + Symbol() + „.”);
if (PushAlerts) SendNotification(„STC Alert: Bullish signal on ” + TimeToString(Time[0]) + ” on ” + Symbol() + „.”);
LastAlert = Time[0];
}
}
}
shift–;
}
return(rates_total);
}
//+——————————————————————+
//+——————————————————————+
//| QQE.mq4 |
//| Copyright © 2010-2022, https://t.me/ForexEaPremium |
//+——————————————————————+
#property copyright „https://t.me/ForexEaPremium”
#property link „https://t.me/ForexEaPremium”
#property version „1.03”
#property strict
#property description „QQE – Qualitative Quantitative Estimation.”
#property description „Calculated as two indicators:”
#property description „1) MA on RSI”
#property description „2) Difference of MA on RSI and MA of MA of ATR of MA of RSI”
#property description „The signal for buy is when blue line crosses level 50 from below after crossing the yellow line from below.”
#property description „The signal for sell is when blue line crosses level 50 from above after crossing the yellow line from above.”
#property indicator_separate_window
#property indicator_buffers 5
#property indicator_color1 clrDodgerBlue
#property indicator_width1 2
#property indicator_label1 „RSI MA”
#property indicator_color2 clrYellow
#property indicator_style2 STYLE_DOT
#property indicator_label2 „Smoothed”
#property indicator_type3 DRAW_NONE
#property indicator_type4 DRAW_NONE
#property indicator_type5 DRAW_NONE
#property indicator_level1 50
#property indicator_levelcolor clrAqua
#property indicator_levelstyle STYLE_DOT
// Inputs
input int SF = 5; // Smoothing Factor
input bool AlertOnCrossover = false;
input bool AlertOnLevel = false;
input int AlertLevel = 50;
input bool ArrowsOnCrossover = true;
input color CrossoverUpArrow = clrGreen;
input color CrossoverDnArrow = clrRed;
input bool ArrowsOnLevel = true;
input color LevelUpArrow = clrGreen;
input color LevelDnArrow = clrRed;
input bool NativeAlerts = false;
input bool EmailAlerts = false;
input bool NotificationAlerts = false;
input ENUM_TIMEFRAMES UpperTimeframe = PERIOD_CURRENT;
input string ObjectPrefix = „QQE-„;
// Global variables:
int RSI_Period = 14;
int Wilders_Period;
int StartBar;
datetime LastAlertTimeCross, LastAlertTimeLevel;
// For MTF support:
string IndicatorFileName;
// Buffers:
double TrLevelSlow[];
double AtrRsi[];
double MaAtrRsi[];
double Rsi[];
double RsiMa[];
void OnInit()
{
LastAlertTimeCross = 0;
LastAlertTimeLevel = 0;
Wilders_Period = RSI_Period * 2 – 1;
StartBar = MathMax(SF, Wilders_Period);
SetIndexBuffer(0, RsiMa);
SetIndexDrawBegin(0, StartBar);
SetIndexBuffer(1, TrLevelSlow);
SetIndexDrawBegin(1, StartBar);
SetIndexBuffer(2, AtrRsi);
SetIndexBuffer(3, MaAtrRsi);
SetIndexBuffer(4, Rsi);
IndicatorShortName(StringConcatenate(„QQE(„, SF, „)”));
IndicatorSetInteger(INDICATOR_DIGITS, 2);
if (PeriodSeconds(UpperTimeframe) < PeriodSeconds())
{
Print(„UpperTimeframe should be above the current timeframe.”);
IndicatorFileName = „”;
}
else if (PeriodSeconds(UpperTimeframe) > PeriodSeconds()) IndicatorFileName = WindowExpertName();
else IndicatorFileName = „”;
}
void OnDeinit(const int reason)
{
ObjectsDeleteAll(ChartID(), ObjectPrefix);
}
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[])
{
if (Bars <= StartBar) return 0;
int counted = IndicatorCounted();
if (counted < 1)
{
for (int i = Bars – StartBar; i < Bars; i++)
{
TrLevelSlow[i] = 0.0;
AtrRsi[i] = 0.0;
MaAtrRsi[i] = 0.0;
Rsi[i] = 0.0;
RsiMa[i] = 0.0;
}
}
if ((counted > 0) && (IndicatorFileName != „”)) counted -= PeriodSeconds(UpperTimeframe) / PeriodSeconds(); // Make the indicator redraw all current bars that constitute the upper timeframe bar.
else counted = Bars – counted – 1;
if (counted > Bars – StartBar – 1) counted = Bars – StartBar – 1;
if (IndicatorFileName == „”)
{
for (int i = counted; i >= 0; i–)
{
Rsi[i] = iRSI(Symbol(), Period(), RSI_Period, PRICE_CLOSE, i);
}
}
for (int i = counted; i >= 0; i–)
{
if (IndicatorFileName == „”) RsiMa[i] = iMAOnArray(Rsi, 0, SF, 0, MODE_EMA, i);
else
{
int shift = iBarShift(Symbol(), UpperTimeframe, Time[i]); // Get the upper timeframe shift based on the current timeframe bar’s time.
RsiMa[i] = iCustom(Symbol(), UpperTimeframe, IndicatorFileName, SF, false, false, AlertLevel, false, LevelUpArrow, LevelDnArrow, false, CrossoverUpArrow, CrossoverDnArrow, false, false, false, UpperTimeframe, ObjectPrefix, 0, shift);
}
if (IndicatorFileName == „”) AtrRsi[i] = MathAbs(RsiMa[i + 1] – RsiMa[i]);
}
if (IndicatorFileName == „”)
{
for (int i = counted; i >= 0; i–)
{
MaAtrRsi[i] = iMAOnArray(AtrRsi, 0, Wilders_Period, 0, MODE_EMA, i);
}
}
int i = counted + 1;
double tr = 0, rsi1 = 0;
if (IndicatorFileName == „”)
{
tr = TrLevelSlow[i];
rsi1 = iMAOnArray(Rsi, 0, SF, 0, MODE_EMA, i);
}
while (i > 0)
{
i–;
if (IndicatorFileName == „”)
{
double rsi0 = iMAOnArray(Rsi, 0, SF, 0, MODE_EMA, i);
double dar = iMAOnArray(MaAtrRsi, 0, Wilders_Period, 0, MODE_EMA, i) * 4.236;
double dv = tr;
if (rsi0 < tr)
{
tr = rsi0 + dar;
if ((rsi1 < dv) && (tr > dv)) tr = dv;
}
else if (rsi0 > tr)
{
tr = rsi0 – dar;
if ((rsi1 > dv) && (tr < dv)) tr = dv;
}
rsi1 = rsi0;
TrLevelSlow[i] = tr;
}
else
{
int shift = iBarShift(Symbol(), UpperTimeframe, Time[i]); // Get the upper timeframe shift based on the current timeframe bar’s time.
TrLevelSlow[i] = iCustom(Symbol(), UpperTimeframe, IndicatorFileName, SF, false, false, AlertLevel, false, LevelUpArrow, LevelDnArrow, false, CrossoverUpArrow, CrossoverDnArrow, false, false, false, UpperTimeframe, ObjectPrefix, 1, shift);
}
// Arrows:
if ((i > 0) || (IndicatorFileName != „”)) // In MTF mode, check as soon as possible.
{
// Prepare for multi-timeframe mode.
int cur_i = i;
int pre_i = i + 1;
// Actual MTF (to avoid non-existing signals):
if ((IndicatorFileName != „”) && (i < PeriodSeconds(UpperTimeframe) / PeriodSeconds())) // Can safely skip this step if processing old bars.
{
// Find the bar that corresponds to the upper timeframe’s latest finished bar.
int customIndex = iBarShift(Symbol(), UpperTimeframe, Time[cur_i]);
cur_i++;
while (iBarShift(Symbol(), UpperTimeframe, Time[cur_i]) == customIndex)
{
cur_i++;
}
// Find the bar that corresponds to the upper timeframe’s pre-latest finished bar.
customIndex = iBarShift(Symbol(), UpperTimeframe, Time[cur_i]);
pre_i = cur_i + 1;
while (iBarShift(Symbol(), UpperTimeframe, Time[pre_i]) == customIndex)
{
pre_i++;
}
cur_i = pre_i – 1; // Use oldest lower timeframe bar inside that upper timeframe bar.
}
if (ArrowsOnCrossover)
{
string name = ObjectPrefix + „CArrow” + TimeToString(Time[cur_i]);
if ((RsiMa[pre_i] < TrLevelSlow[pre_i]) && (RsiMa[cur_i] > TrLevelSlow[cur_i]))
{
ObjectCreate(ChartID(), name, OBJ_ARROW_THUMB_UP, 0, Time[cur_i], Low[cur_i] – 1 * _Point);
ObjectSetInteger(ChartID(), name, OBJPROP_COLOR, LevelUpArrow);
ObjectSetInteger(ChartID(), name, OBJPROP_ANCHOR, ANCHOR_TOP);
ObjectSetInteger(ChartID(), name, OBJPROP_WIDTH, 5);
}
else if ((RsiMa[pre_i] > TrLevelSlow[pre_i]) && (RsiMa[cur_i] < TrLevelSlow[cur_i]))
{
ObjectCreate(ChartID(), name, OBJ_ARROW_THUMB_DOWN, 0, Time[cur_i], High[cur_i] + 1 * _Point);
ObjectSetInteger(ChartID(), name, OBJPROP_COLOR, LevelDnArrow);
ObjectSetInteger(ChartID(), name, OBJPROP_ANCHOR, ANCHOR_BOTTOM);
ObjectSetInteger(ChartID(), name, OBJPROP_WIDTH, 5);
}
}
if (ArrowsOnLevel)
{
string name = ObjectPrefix + „LArrow” + TimeToString(Time[cur_i]);
if ((RsiMa[pre_i] < AlertLevel) && (RsiMa[cur_i] > AlertLevel))
{
ObjectCreate(ChartID(), name, OBJ_ARROW_UP, 0, Time[cur_i], Low[cur_i] – 1 * _Point);
ObjectSetInteger(ChartID(), name, OBJPROP_COLOR, LevelUpArrow);
ObjectSetInteger(ChartID(), name, OBJPROP_ANCHOR, ANCHOR_TOP);
ObjectSetInteger(ChartID(), name, OBJPROP_WIDTH, 5);
}
else if ((RsiMa[pre_i] > AlertLevel) && (RsiMa[cur_i] < AlertLevel))
{
ObjectCreate(ChartID(), name, OBJ_ARROW_DOWN, 0, Time[cur_i], High[cur_i] + 1 * _Point);
ObjectSetInteger(ChartID(), name, OBJPROP_COLOR, LevelDnArrow);
ObjectSetInteger(ChartID(), name, OBJPROP_ANCHOR, ANCHOR_BOTTOM);
ObjectSetInteger(ChartID(), name, OBJPROP_WIDTH, 5);
}
}
}
}
if ((!NativeAlerts) && (!EmailAlerts) && (!NotificationAlerts)) return rates_total;
if ((!AlertOnCrossover) && (!AlertOnLevel)) return rates_total;
// Prepare for multi-timeframe mode.
int pre_i = 2;
if (IndicatorFileName != „”)
{
// Find the bar that corresponds to the upper timeframe’s latest finished bar.
int cnt = 1;
int customIndex = iBarShift(Symbol(), UpperTimeframe, Time[0]);
while (iBarShift(Symbol(), UpperTimeframe, Time[cnt]) == customIndex)
{
cnt++;
}
i = cnt;
// Find the bar that corresponds to the upper timeframe’s pre-latest finished bar.
customIndex = iBarShift(Symbol(), UpperTimeframe, Time[cnt]);
cnt++;
while (iBarShift(Symbol(), UpperTimeframe, Time[cnt]) == customIndex)
{
cnt++;
}
pre_i = cnt;
}
else i = 1; // Non-MTF.
if (AlertOnLevel)
{
if ((LastAlertTimeLevel > 0) && (((RsiMa[pre_i] < AlertLevel) && (RsiMa[i] > AlertLevel)) || ((RsiMa[pre_i] > AlertLevel) && (RsiMa[i] < AlertLevel))) && (Time[i – 1] > LastAlertTimeLevel))
{
string base = „QQE ” + Symbol() + „, TF: ” + TimeframeToString((ENUM_TIMEFRAMES)Period());
string text = base + „, ” + IntegerToString(AlertLevel) + ” level Cross Up”;
if ((RsiMa[pre_i] > AlertLevel) && (RsiMa[i] < AlertLevel)) text = base + ” ” + IntegerToString(AlertLevel) + ” level Cross Down”;
DoAlerts(text);
LastAlertTimeLevel = Time[i – 1];
}
}
if (AlertOnCrossover)
{
if ((LastAlertTimeCross > 0) && (((RsiMa[pre_i] < TrLevelSlow[pre_i]) && (RsiMa[i] > TrLevelSlow[i])) || ((RsiMa[pre_i] > TrLevelSlow[pre_i]) && (RsiMa[i] < TrLevelSlow[i]))) && (Time[i – 1] > LastAlertTimeCross))
{
string base = „QQE ” + Symbol() + „, TF: ” + TimeframeToString((ENUM_TIMEFRAMES)Period());
string text = base + „, RSI MA crossed Smoothed Line from below.”;
if ((RsiMa[pre_i] > TrLevelSlow[pre_i]) && (RsiMa[i] < TrLevelSlow[i])) text = base + „, RSI MA crossed Smoothed Line from above.”;
DoAlerts(text);
LastAlertTimeCross = Time[i – 1];
}
}
if (LastAlertTimeLevel == 0) LastAlertTimeLevel = Time[0];
if (LastAlertTimeCross == 0) LastAlertTimeCross = Time[0];
return rates_total;
}
void DoAlerts(const string msgText)
{
if (NativeAlerts) Alert(msgText);
if (EmailAlerts) SendMail(msgText, msgText);
if (NotificationAlerts) SendNotification(msgText);
}
string TimeframeToString(ENUM_TIMEFRAMES P)
{
return StringSubstr(EnumToString(P), 7);
}
//+——————————————————————+
[/et_pb_text][/et_pb_column][/et_pb_row][/et_pb_section]