//+------------------------------------------------------------------+ //| Vulkan Profit.mq5 | //| Copyright © 2023, Centaur | //| forex-station.com/memberlist.php?mode=viewprofile&u=4948703 | //+------------------------------------------------------------------+ #property copyright "Copyright © 2023, Centaur" #property link "forex-station.com/memberlist.php?mode=viewprofile&u=4948703" #property version "1.00" #property indicator_chart_window #property indicator_buffers 15 #property indicator_plots 4 //--- plot Short Term Trend Tunnel #property indicator_label1 "Short Tunnel Line 1;Short Tunnel Line 2" #property indicator_type1 DRAW_FILLING #property indicator_color1 clrDodgerBlue,clrDodgerBlue #property indicator_style1 STYLE_SOLID #property indicator_width1 1 //--- plot Long Term Trend Tunnel #property indicator_label2 "Long Tunnel Line 1;Long Tunnel Line 2" #property indicator_type2 DRAW_FILLING #property indicator_color2 clrMagenta,clrMagenta #property indicator_style2 STYLE_SOLID #property indicator_width2 1 //--- plot Buy Signal #property indicator_label3 "Buy Signal" #property indicator_type3 DRAW_ARROW #property indicator_color3 clrLimeGreen #property indicator_style3 STYLE_SOLID #property indicator_width3 1 //--- plot Sell Signal #property indicator_label4 "Sell Signal" #property indicator_type4 DRAW_ARROW #property indicator_color4 clrCrimson #property indicator_style4 STYLE_SOLID #property indicator_width4 1 //--- enumerations enum ENUM_RATES { pr_open, // Open pr_high, // High pr_low, // Low pr_close, // Close pr_median, // Median (h+l)/2 pr_typical, // Typical (h+l+c)/3 pr_weighted, // Weighted (h+l+c+c)/4 pr_average, // Average (o+h+l+c)/4 pr_medianb, // Median Body (o+c)/2 pr_tbiased, // Trend Biased pr_haopen, // Heiken Ashi Open pr_hahigh, // Heiken Ashi High pr_halow, // Heiken Ashi Low pr_haclose, // Heiken Ashi Close pr_hamedian, // Heiken Ashi Median (hah+hal)/2 pr_hatypical, // Heiken Ashi Typical (hah+hal+hac)/3 pr_haweighted, // Heiken Ashi Weighted (hah+hal+hac+hac)/4 pr_haaverage, // Heiken Ashi Average (hao+hah+hal+hac)/4 pr_hamedianb, // Heiken Ashi Median Body (hao+hac)/2 pr_hatbiased // Heiken Ashi Trend Biased }; //--- input parameters input string hd1 = "Short Term Trend Tunnel:"; // Short Term Trend Tunnel: input int inp_short_term_line_1_period = 3; // LWMA 1 Period input int inp_short_term_line_2_period = 8; // LWMA 2 Period input string hd2 = "Long Term Trend Tunnel:"; // Long Term Trend Tunnel: input int inp_long_term_line_1_period = 18; // EMA 1 Period input int inp_long_term_line_2_period = 28; // EMA 2 Period input string hd3 = "General Settings:"; // General Settings: input ENUM_RATES inp_rates = pr_close; // Applied Price input bool inp_show_tunnels = true; // Show Trend Tunnels? //--- indicator buffers double STL1Buffer[]; double STL2Buffer[]; double LTL1Buffer[]; double LTL2Buffer[]; double BuySignalBuffer[]; double SellSignalBuffer[]; double rates[]; double ratesTemp1[], ratesTemp2[], ratesTemp3[], ratesTemp4[]; double calcSTL1[]; double calcSTL2[]; double calcLTL1[]; double calcLTL2[]; //--- indicator variables int short_term_line_1_period; int short_term_line_2_period; int long_term_line_1_period; int long_term_line_2_period; static bool buy; static bool sell; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- check input parameters short_term_line_1_period = inp_short_term_line_1_period < 1 ? 1 : inp_short_term_line_1_period; short_term_line_2_period = inp_short_term_line_2_period < 1 ? 1 : inp_short_term_line_2_period; long_term_line_1_period = inp_long_term_line_1_period < 1 ? 1 : inp_long_term_line_1_period; long_term_line_2_period = inp_long_term_line_2_period < 1 ? 1 : inp_long_term_line_2_period; //--- indicator buffers mapping SetIndexBuffer(0, STL1Buffer, INDICATOR_DATA); SetIndexBuffer(1, STL2Buffer, INDICATOR_DATA); SetIndexBuffer(2, LTL1Buffer, INDICATOR_DATA); SetIndexBuffer(3, LTL2Buffer, INDICATOR_DATA); SetIndexBuffer(4, BuySignalBuffer, INDICATOR_DATA); SetIndexBuffer(5, SellSignalBuffer, INDICATOR_DATA); SetIndexBuffer(6, rates, INDICATOR_CALCULATIONS); SetIndexBuffer(7, ratesTemp1, INDICATOR_CALCULATIONS); SetIndexBuffer(8, ratesTemp2, INDICATOR_CALCULATIONS); SetIndexBuffer(9, ratesTemp3, INDICATOR_CALCULATIONS); SetIndexBuffer(10, ratesTemp4, INDICATOR_CALCULATIONS); SetIndexBuffer(11, calcSTL1, INDICATOR_CALCULATIONS); SetIndexBuffer(12, calcSTL2, INDICATOR_CALCULATIONS); SetIndexBuffer(13, calcLTL1, INDICATOR_CALCULATIONS); SetIndexBuffer(14, calcLTL2, INDICATOR_CALCULATIONS); //--- initialize buffers ArrayInitialize(STL1Buffer, EMPTY_VALUE); ArrayInitialize(STL2Buffer, EMPTY_VALUE); ArrayInitialize(LTL1Buffer, EMPTY_VALUE); ArrayInitialize(LTL2Buffer, EMPTY_VALUE); ArrayInitialize(BuySignalBuffer, EMPTY_VALUE); ArrayInitialize(SellSignalBuffer, EMPTY_VALUE); //--- set indicator accuracy IndicatorSetInteger(INDICATOR_DIGITS, _Digits + 1); //--- set indicator name display string rates_name = inp_rates == pr_open ? "Open" : inp_rates == pr_high ? "High" : inp_rates == pr_low ? "Low" : inp_rates == pr_close ? "Close" : inp_rates == pr_median ? "Median" : inp_rates == pr_typical ? "Typical" : inp_rates == pr_weighted ? "Weighted" : inp_rates == pr_average ? "Average" : inp_rates == pr_medianb ? "Median Body" : inp_rates == pr_tbiased ? "Trend Biased" : inp_rates == pr_haopen ? "HA Open" : inp_rates == pr_hahigh ? "HA High" : inp_rates == pr_halow ? "HA Low" : inp_rates == pr_haclose ? "HA Close" : inp_rates == pr_hamedian ? "HA Median" : inp_rates == pr_hatypical ? "HA Typical" : inp_rates == pr_haweighted ? "HA Weighted" : inp_rates == pr_haaverage ? "HA Average" : inp_rates == pr_hamedianb ? "HA Median Body" : inp_rates == pr_hatbiased ? "HA Trend Biased" : " "; string short_name = "Vulkan Profit (" + IntegerToString(short_term_line_1_period) + ", " + IntegerToString(short_term_line_2_period) + ", " + IntegerToString(long_term_line_1_period) + ", " + IntegerToString(long_term_line_2_period) + ", " + rates_name + ")"; IndicatorSetString(INDICATOR_SHORTNAME, short_name); //--- sets drawing lines to empty value PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, EMPTY_VALUE); PlotIndexSetDouble(1, PLOT_EMPTY_VALUE, EMPTY_VALUE); PlotIndexSetDouble(2, PLOT_EMPTY_VALUE, EMPTY_VALUE); PlotIndexSetDouble(3, PLOT_EMPTY_VALUE, EMPTY_VALUE); //--- setting a code from the Wingdings charset as the property of PLOT_ARROW PlotIndexSetInteger(2, PLOT_ARROW, 225); PlotIndexSetInteger(3, PLOT_ARROW, 226); //--- Set the vertical shift of arrows in pixels PlotIndexSetInteger(2, PLOT_ARROW_SHIFT, 20); PlotIndexSetInteger(3, PLOT_ARROW_SHIFT, -20); //--- set static variables buy = false; sell = false; //--- initialization succeeded 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[]) { //--- populate rates buffer getPrice(rates_total, prev_calculated, inp_rates, ratesTemp1, ratesTemp2, ratesTemp3, ratesTemp4, open, high, low, close, rates); //--- populate Short Term Tunnel buffers inLinearWeightedMA(rates_total, prev_calculated, short_term_line_1_period, rates, calcSTL1); inLinearWeightedMA(rates_total, prev_calculated, short_term_line_2_period, rates, calcSTL2); //--- populate Long Term Tunnel buffers inExponentialMA(rates_total, prev_calculated, long_term_line_1_period, rates, calcLTL1); inExponentialMA(rates_total, prev_calculated, long_term_line_2_period, rates, calcLTL2); //--- calculate start position int position; if(prev_calculated == 0) position = 0; else position = prev_calculated - 1; //--- main loop for(int i = position; i < rates_total && !_StopFlag; i++) { STL1Buffer[i] = inp_show_tunnels == true ? calcSTL1[i] : EMPTY_VALUE; STL2Buffer[i] = inp_show_tunnels == true ? calcSTL2[i] : EMPTY_VALUE; LTL1Buffer[i] = inp_show_tunnels == true ? calcLTL1[i] : EMPTY_VALUE; LTL2Buffer[i] = inp_show_tunnels == true ? calcLTL2[i] : EMPTY_VALUE; if(i < fmax(short_term_line_1_period, fmax(short_term_line_2_period, fmax(long_term_line_1_period, long_term_line_2_period)))) { BuySignalBuffer[i] = EMPTY_VALUE; SellSignalBuffer[i] = EMPTY_VALUE; } else { if(fmin(calcSTL1[i], calcSTL2[i]) > fmax(calcLTL1[i], calcLTL2[i]) && fmin(calcSTL1[i - 1], calcSTL2[i - 1]) <= fmax(calcLTL1[i - 1], calcLTL2[i - 1]) && buy == false) { BuySignalBuffer[i] = fmin(calcSTL1[i], fmin(calcSTL2[i], fmin(calcLTL1[i], fmin(calcLTL2[i], low[i])))); buy = true; sell = false; } if(fmax(calcSTL1[i], calcSTL2[i]) < fmin(calcLTL1[i], calcLTL2[i]) && fmax(calcSTL1[i - 1], calcSTL2[i - 1]) >= fmin(calcLTL1[i - 1], calcLTL2[i - 1]) && sell == false) { SellSignalBuffer[i] = fmax(calcSTL1[i], fmax(calcSTL2[i], fmax(calcLTL1[i], fmax(calcLTL2[i], high[i])))); buy = false; sell = true; } } } //--- return value of prev_calculated for next call return(rates_total); } //+------------------------------------------------------------------+ //| Get Price from ENUM_RATES | //+------------------------------------------------------------------+ int getPrice(const int rates_total, const int prev_calculated, const ENUM_RATES price, double &temp_ha_open[], double &temp_ha_high[], double &temp_ha_low[], double &temp_ha_close[], const double &open[], const double &high[], const double &low[], const double &close[], double &result[]) { //--- check length if(rates_total < 1) return(0); //--- calculate start position int position; if(prev_calculated == 0) position = 0; else position = prev_calculated - 1; //--- main loop for(int i = position; i < rates_total && !_StopFlag; i++) { temp_ha_close[i] = (open[i] + high[i] + low[i] + close[i]) / 4.0; temp_ha_open[i] = i < 1 ? (open[i] + close[i]) / 2 : (temp_ha_open[i - 1] + temp_ha_close[i - 1]) / 2; temp_ha_high[i] = fmax(high[i], fmax(temp_ha_open[i], temp_ha_close[i])); temp_ha_low[i] = fmin(low[i], fmin(temp_ha_open[i], temp_ha_close[i])); switch(price) { case pr_open: result[i] = open[i]; break; case pr_high: result[i] = high[i]; break; case pr_low: result[i] = low[i]; break; case pr_close: result[i] = close[i]; break; case pr_median: result[i] = (high[i] + low[i]) / 2.0; break; case pr_medianb: result[i] = (open[i] + close[i]) / 2.0; break; case pr_typical: result[i] = (high[i] + low[i] + close[i]) / 3.0; break; case pr_weighted: result[i] = (high[i] + low[i] + close[i] + close[i]) / 4.0; break; case pr_average: result[i] = (high[i] + low[i] + close[i] + open[i]) / 4.0; break; case pr_tbiased: if(close[i] > open[i]) result[i] = (high[i] + close[i]) / 2.0; else result[i] = (low[i] + close[i]) / 2.0; break; case pr_haopen: result[i] = temp_ha_open[i]; break; case pr_hahigh: result[i] = temp_ha_high[i]; break; case pr_halow: result[i] = temp_ha_low[i]; break; case pr_haclose: result[i] = temp_ha_close[i]; break; case pr_hamedian: result[i] = (temp_ha_high[i] + temp_ha_low[i]) / 2.0; break; case pr_hamedianb: result[i] = (temp_ha_open[i] + temp_ha_close[i]) / 2.0; break; case pr_hatypical: result[i] = (temp_ha_high[i] + temp_ha_low[i] + temp_ha_close[i]) / 3.0; break; case pr_haweighted: result[i] = (temp_ha_high[i] + temp_ha_low[i] + temp_ha_close[i] + temp_ha_close[i]) / 4.0; break; case pr_haaverage: result[i] = (temp_ha_high[i] + temp_ha_low[i] + temp_ha_close[i] + temp_ha_open[i]) / 4.0; break; case pr_hatbiased: if(temp_ha_close[i] > temp_ha_open[i]) result[i] = (temp_ha_high[i] + temp_ha_close[i]) / 2.0; else result[i] = (temp_ha_low[i] + temp_ha_close[i]) / 2.0; break; } } //--- return value of prev_calculated for next call return(rates_total); } //+------------------------------------------------------------------+ //| Linear Weighted Moving Average (LWMA) | //+------------------------------------------------------------------+ int inLinearWeightedMA(const int rates_total, const int prev_calculated, const int length, const double &price[], double &result[]) { //--- check length if(rates_total < length) return(0); //--- calculate start position int position; if(prev_calculated == 0) position = 0; else position = prev_calculated - 1; //--- main loop for(int i = position; i < rates_total && !_StopFlag; i++) { if(i < length) result[i] = price[i]; else { double weight = 0.0, sum_weight = 0.0, sum_weight_price = 0.0; for(int k = 0; k < length; k++) { weight = length - k; sum_weight += weight; sum_weight_price += weight * price[i - k]; } result[i] = sum_weight_price / sum_weight; } } //--- return value of prev_calculated for next call return(rates_total); } //+------------------------------------------------------------------+ //| Exponential Moving Average (EMA) | //+------------------------------------------------------------------+ int inExponentialMA(const int rates_total, const int prev_calculated, const int length, const double &price[], double &result[]) { //--- check length if(rates_total < 2) return(0); //--- calculate start position int position; double alpha = 2.0 / (1.0 + double(length)); if(prev_calculated == 0) position = 0; else position = prev_calculated - 1; //--- main loop for(int i = position; i < rates_total && !_StopFlag; i++) { if(i < 2) result[i] = price[i]; else result[i] = price[i] * alpha + result[i - 1] * (1.0 - alpha); } //--- return value of prev_calculated for next call return(rates_total); } //+------------------------------------------------------------------+