//+------------------------------------------------------------------+ //| Chaos semafor 3mod.mq5 | //| Copyright 2019, MetaQuotes Software Corp. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2019, MetaQuotes Software Corp." #property link "https://www.mql5.com" #property version "1.00" #property indicator_chart_window #property indicator_buffers 6 #property indicator_plots 6 //--- plot Highest1_ #property indicator_label1 "Highest1_" #property indicator_type1 DRAW_ARROW #property indicator_color1 clrWhite #property indicator_style1 STYLE_SOLID #property indicator_width1 5 //--- plot Lowest1_ #property indicator_label2 "Lowest1_" #property indicator_type2 DRAW_ARROW #property indicator_color2 clrWhite #property indicator_style2 STYLE_SOLID #property indicator_width2 5 //--- plot Highest2_ #property indicator_label3 "Highest2_" #property indicator_type3 DRAW_ARROW #property indicator_color3 clrDodgerBlue #property indicator_style3 STYLE_SOLID #property indicator_width3 3 //--- plot lowest2_ #property indicator_label4 "lowest2_" #property indicator_type4 DRAW_ARROW #property indicator_color4 clrDodgerBlue #property indicator_style4 STYLE_SOLID #property indicator_width4 3 //--- plot Highest3_ #property indicator_label5 "Highest3_" #property indicator_type5 DRAW_ARROW #property indicator_color5 clrRed #property indicator_style5 STYLE_SOLID #property indicator_width5 2 //--- plot Lowest3_ #property indicator_label6 "Lowest3_" #property indicator_type6 DRAW_ARROW #property indicator_color6 clrLime #property indicator_style6 STYLE_SOLID #property indicator_width6 2 //--- input parameters input string dummy1; //---Large ZigZag--- input uint ExtDepth1 = 77; //Depth input uint ExtDeviation1 = 5; //Deviation input uint ExtBackstep1 = 3; //Backstep input string dummy2; //---Middle ZigZag--- input uint ExtDepth2 = 31; //Depth input uint ExtDeviation2 = 5; //Deviation input uint ExtBackstep2 = 3; //Backstep input string dummy3; //---Small ZigZag--- input uint ExtDepth3 = 9; //Depth input uint ExtDeviation3 = 5; //Deviation input uint ExtBackstep3 = 3; //Backstep input string dummy4; //--- Alert --- input bool Box_Alerts = true ; //PopUp Alert input bool Sound_Alerts = false ; //Sound Alert input bool Email_Alerts = false ; //E-mail //--- indicator buffers double Highest1_Buffer[]; double Lowest1_Buffer[]; double Highest2_Buffer[]; double Lowest2_Buffer[]; double Highest3_Buffer[]; double Lowest3_Buffer[]; int min_rates_total[3]; int LAST_lowpos[3], LAST_highpos[3]; double LAST_lowone[3], LAST_lowtwo[3]; double LAST_highone[3], LAST_hightwo[3]; bool Trigger; int OldBars = -1; string Alert_SoundFile = "buy_rob_pirate.wav"; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- indicator buffers mapping SetIndexBuffer(0, Highest1_Buffer, INDICATOR_DATA); SetIndexBuffer(1, Lowest1_Buffer, INDICATOR_DATA); SetIndexBuffer(2, Highest2_Buffer, INDICATOR_DATA); SetIndexBuffer(3, Lowest2_Buffer, INDICATOR_DATA); SetIndexBuffer(4, Highest3_Buffer, INDICATOR_DATA); SetIndexBuffer(5, Lowest3_Buffer, INDICATOR_DATA); //--- setting a code from the Wingdings charset as the property of PLOT_ARROW PlotIndexSetInteger(0, PLOT_ARROW, 93); PlotIndexSetInteger(1, PLOT_ARROW, 93); PlotIndexSetInteger(2, PLOT_ARROW, 108); PlotIndexSetInteger(3, PLOT_ARROW, 108); PlotIndexSetInteger(4, PLOT_ARROW, 167); PlotIndexSetInteger(5, PLOT_ARROW, 167); PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, 0.0); PlotIndexSetDouble(1, PLOT_EMPTY_VALUE, 0.0); PlotIndexSetDouble(2, PLOT_EMPTY_VALUE, 0.0); PlotIndexSetDouble(3, PLOT_EMPTY_VALUE, 0.0); PlotIndexSetDouble(4, PLOT_EMPTY_VALUE, 0.0); PlotIndexSetDouble(5, PLOT_EMPTY_VALUE, 0.0); ArraySetAsSeries(Lowest1_Buffer, true); ArraySetAsSeries(Highest1_Buffer, true); ArraySetAsSeries(Lowest2_Buffer, true); ArraySetAsSeries(Highest2_Buffer, true); ArraySetAsSeries(Lowest3_Buffer, true); ArraySetAsSeries(Highest3_Buffer, true); min_rates_total[0] = int(ExtDepth1 + ExtBackstep1); min_rates_total[1] = int(ExtDepth2 + ExtBackstep2); min_rates_total[2] = int(ExtDepth3 + ExtBackstep3); PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, min_rates_total[0]); PlotIndexSetInteger(1, PLOT_DRAW_BEGIN, min_rates_total[0]); PlotIndexSetInteger(2, PLOT_DRAW_BEGIN, min_rates_total[1]); PlotIndexSetInteger(3, PLOT_DRAW_BEGIN, min_rates_total[1]); PlotIndexSetInteger(4, PLOT_DRAW_BEGIN, min_rates_total[2]); PlotIndexSetInteger(5, PLOT_DRAW_BEGIN, min_rates_total[2]); IndicatorSetInteger(INDICATOR_DIGITS, _Digits); string shortname = "Chaos Semafor 3-mod(" + (string)ExtDepth1 + "," + (string)ExtDepth2 + "," + (string)ExtDepth3 + ")"; IndicatorSetString(INDICATOR_SHORTNAME, shortname); //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Custom indicator iteration function | //+------------------------------------------------------------------+ 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 < min_rates_total[0]) return(0); if (rates_total != OldBars) Trigger = true; double price_high[]; double price_low[]; ArrayCopy(price_high, high, 0, 0, WHOLE_ARRAY); ArrayCopy(price_low, low, 0, 0, WHOLE_ARRAY); ZigZag_Calc(rates_total, prev_calculated, price_high, price_low, ExtDepth1, ExtDeviation1, ExtBackstep1, Highest1_Buffer, Lowest1_Buffer, 0); ZigZag_Calc(rates_total, prev_calculated, price_high, price_low, ExtDepth2, ExtDeviation2, ExtBackstep2, Highest2_Buffer, Lowest2_Buffer, 1); ZigZag_Calc(rates_total, prev_calculated, price_high, price_low, ExtDepth3, ExtDeviation3, ExtBackstep3, Highest3_Buffer, Lowest3_Buffer, 2); string alert_level; string Chart_period = TimeFrameToString(Period()); string alert_message = Symbol() + " " + Chart_period + " at " + DoubleToString(close[0], Digits()); if (Trigger) { if (Lowest1_Buffer[0] != 0) { Trigger = false; alert_level = " ZZ: Level Low; "; if (Box_Alerts) Alert(alert_level, alert_message); if (Sound_Alerts) PlaySound(Alert_SoundFile); if (Email_Alerts) SendMail(alert_level, alert_message); } if (Highest1_Buffer[0] != 0) { Trigger = false; alert_level = " ZZ: Level High; "; if (Box_Alerts) Alert(alert_level, alert_message); if (Sound_Alerts) PlaySound(Alert_SoundFile); if (Email_Alerts) SendMail(alert_level, alert_message); } } OldBars = rates_total; //--- return value of prev_calculated for next call return(rates_total); } //+------------------------------------------------------------------+ void ZigZag_Calc(int rates_total, int prev_calculated, double& high[], double& low[], uint Depth, uint Deviation, uint Backstep, double& High_Buffer[], double& Low_Buffer[], int n) { int i, j, limit; int last_highpos, last_lowpos; double cur_low, cur_high, val, res; double last_highone[] = {NULL, NULL, NULL}, last_lowone[] = {NULL, NULL, NULL}; double last_hightwo[3], last_lowtwo[3]; if (prev_calculated > rates_total || prev_calculated <= 0) { limit = rates_total - min_rates_total[n]; last_lowtwo[n] = -1; last_hightwo[n] = -1; last_lowpos = -1; last_highpos = -1; } else { limit = rates_total - prev_calculated; last_lowone[n] = LAST_lowone[n]; last_highone[n] = LAST_highone[n]; last_lowtwo[n] = LAST_lowtwo[n]; last_hightwo[n] = LAST_hightwo[n]; last_lowpos = LAST_lowpos[n] + limit; last_highpos = LAST_highpos[n] + limit; } ArraySetAsSeries(high, true); ArraySetAsSeries(low, true); for (i = limit; i >= 0 && !IsStopped(); i--) { if (rates_total != prev_calculated && i == 0) { LAST_lowone[n] = last_lowone[n]; LAST_highone[n] = last_highone[n]; } //--- low val = low[ArrayMinimum(low, i, Depth)]; if (val == last_lowone[n]) val = NULL; else { last_lowone[n] = val; if (low[i] - val > Deviation * _Point) val = NULL; else { for (j = 1; j <= int(Backstep); j++) { res = Low_Buffer[i + j]; if (res && res > val) Low_Buffer[i + j] = NULL; } } } Low_Buffer[i] = val; //--- high val = high[ArrayMaximum(high, i, Depth)]; if (val == last_highone[n]) val = NULL; else { last_highone[n] = val; if (val - high[i] > Deviation * _Point) val = NULL; else { for (j = 1; j <= int(Backstep); j++) { res = High_Buffer[i + j]; if (res && res < val) High_Buffer[i + j] = NULL; } } } High_Buffer[i] = val; } for (i = limit; i >= 0; i--) { if (rates_total != prev_calculated && !i) { LAST_lowtwo[n] = last_lowtwo[n]; LAST_hightwo[n] = last_hightwo[n]; LAST_lowpos[n] = last_lowpos; LAST_highpos[n] = last_highpos; } cur_low = Low_Buffer[i]; cur_high = High_Buffer[i]; if (!cur_low && !cur_high) continue; if (cur_high) { if (last_hightwo[n] > 0) { if (last_hightwo[n] < cur_high) High_Buffer[last_highpos] = NULL; else High_Buffer[i] = NULL; } if (last_hightwo[n] < cur_high || last_hightwo[n] < 0) { last_hightwo[n] = cur_high; last_highpos = i; } last_lowtwo[n] = -1; } if (cur_low) { if (last_lowtwo[n] > 0) { if (last_lowtwo[n] > cur_low) Low_Buffer[last_lowpos] = NULL; else Low_Buffer[i] = NULL; } if (cur_low < last_lowtwo[n] || last_lowtwo[n] < 0) { last_lowtwo[n] = cur_low; last_lowpos = i; } last_hightwo[n] = -1; } } } //+------------------------------------------------------------------+ string TimeFrameToString(int tf) { string tfs; switch (tf) { case PERIOD_M1: tfs = "M1" ; break; case PERIOD_M5: tfs = "M5" ; break; case PERIOD_M15: tfs = "M15" ; break; case PERIOD_M30: tfs = "M30" ; break; case PERIOD_H1: tfs = "H1" ; break; case PERIOD_H4: tfs = "H4" ; break; case PERIOD_D1: tfs = "D1" ; break; case PERIOD_W1: tfs = "W1" ; break; case PERIOD_MN1: tfs = "MN"; } return(tfs); } //+------------------------------------------------------------------+