MACrossAlerter

Price Data Components
Indicators Used
Moving average indicator
Miscellaneous
It plays sound alerts
0 Views
0 Downloads
0 Favorites
MACrossAlerter
//+------------------------------------------------------------------+
//|                                         SlowMA_alerter_phade.mq5 |
//|                             https://www.mql5.com/en/users/phade/ |
//+------------------------------------------------------------------+

#property copyright "Copyright 2023, https://www.mql5.com/en/users/phade/"
#property link      "https://www.mql5.com/en/users/phade/"
#property version   "1.01"

#property indicator_chart_window
#property indicator_buffers 1
#property indicator_plots   1

#property indicator_type1    DRAW_LINE
#property indicator_color1   clrGray // change to clrNONE to hide the line
#property indicator_style1   STYLE_DOT
#property indicator_label1   "Line"
#property indicator_width1   1
#define OBJ_PREFIX MQLInfoString(MQL_PROGRAM_NAME)


ENUM_TIMEFRAMES prevPeriod = PERIOD_CURRENT;
input int slowPeriod = 44; // Moving Average Length
double indvalue[];
double slowma[];
int handle;
int max_bars;
double arrowDistance = 250.0; // Desired distance


input string Audio_Alert_Sound = "alert.wav"; //Audio alert sample
string audioFilePath = "\\Files\\" + Audio_Alert_Sound;
static datetime last_playsound_time = TimeCurrent();
input bool Audio_Alert_On_Signals = false; // Enable audio alerts
input int pointNum = 100; // Amount of points on MA crossover that should enable a signal
input color LongSignalColor = clrPurple;  // Set the up arrow color (long signals)
input color ShortSignalColor = clrBlack;  // Set the down arrow color (short signals)

double gLongSignal = 0.0;
double gShortSignal = 0.0;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
{
   // ChartSetInteger(0, CHART_FOREGROUND, false);
    SetIndexBuffer(0, indvalue, INDICATOR_DATA);

    handle = iMA(_Symbol, PERIOD_CURRENT, slowPeriod, 0, MODE_SMA, PRICE_CLOSE);

    if (handle == INVALID_HANDLE)
    {
        Print("Get MA Handle failed!");
        return INIT_FAILED;
    }

    max_bars = Bars(Symbol(), Period());  
    
    ArrayResize(slowma, max_bars);
    ArrayResize(indvalue, max_bars);

    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[])
{
    // Calculate the number of bars to copy
    int to_copy = rates_total - prev_calculated;
    if (to_copy <= 0)
        to_copy = max_bars;
        
    int limit = MathMin(rates_total - prev_calculated, rates_total);

    // Copy data from indicator buffers
    CopyBuffer(handle, 0, 0, to_copy, slowma);

    if (ChartPeriod() != prevPeriod) {
        prevPeriod = ChartPeriod(); // Store the current timeframe for comparison in the next calculation
        ChartRedraw(); // Refresh the chart to remove previous objects
    }

    if (_Period == PERIOD_M1) {
        arrowDistance = 5.0; // Change the distance for the 1-minute timeframe
    } else if (_Period == PERIOD_M2) {
        arrowDistance = 5.0; // Change the distance for the 2-minute timeframe
    } else if (_Period == PERIOD_M5) {
        arrowDistance = 20.0; // Change the distance for the 5-minute timeframe
    } else if (_Period == PERIOD_M15) {
        arrowDistance = 20.0; // Change the distance for the 15-minute timeframe
    } else if (_Period == PERIOD_M30) {
        arrowDistance = 20.0; // Change the distance for the 30-minute timeframe
    } else if (_Period == PERIOD_H1) {
        arrowDistance = 40.0; // Change the distance for the 1-hour timeframe
    } else if (_Period == PERIOD_H4) {
        arrowDistance = 40.0; // Change the distance for the 4-hour timeframe
    } else if (_Period == PERIOD_D1) {
        arrowDistance = 40.0; // Change the distance for the daily timeframe
    } else if (_Period == PERIOD_W1) {
        arrowDistance = 40.0; // Change the distance for the weekly timeframe
    } else if (_Period == PERIOD_MN1) {
        arrowDistance = 40.0; // Change the distance for the monthly timeframe
    }

    // Calculate the indicator values
    for (int i = prev_calculated - (rates_total==prev_calculated); i < limit; i++)
    {
        indvalue[i] = slowma[i];
        
     //   longSignalBuffer[i] = 0;    // Set long signal to 0
     //   shortSignalBuffer[i] = 0;   // Set short signal to 0
        
        bool noSidewaysMarket = false;
        bool significantLiquidity = false;
        
        if(i > 0){
            noSidewaysMarket = (MathAbs(close[i] - close[i-1]) > 10 * _Point);
        }
        
        if(i > 3){
            significantLiquidity = (MathAbs(close[i] - close[i-3]) > 8 * _Point);
        }
        
        bool greenCandleFormation = (close[i] > open[i]);
        bool redCandleFormation = (close[i] < open[i]);
        

        // Check for MA crossovers
        if (i > 0 && (i - 2) >= 0 && close[i] > (indvalue[i] + pointNum * _Point) && close[i - 2] < indvalue[i])
        {
            string bullArrow = OBJ_PREFIX + IntegerToString(i); // Unique name for the arrow object based on bar index
            double bullArrowPrice = low[i] - (arrowDistance * _Point);
       
            if(EntryValid(open, close, high, low, i, time, rates_total) && greenCandleFormation && noSidewaysMarket && significantLiquidity){
            
               gLongSignal = 1;
               gShortSignal = 0;

               if (Audio_Alert_On_Signals) {
                   if (last_playsound_time < time[i])
                   {
                       PlaySound(audioFilePath);
   
                       // Update last_playsound_time to the start of the current minute
                       last_playsound_time = time[i] - (time[i] % PeriodSeconds());
                   }
               }
   
               ObjectCreate(0, bullArrow, OBJ_ARROW, 0, time[i], bullArrowPrice);
               ObjectSetInteger(0, bullArrow, OBJPROP_ARROWCODE, 233);
               ObjectSetInteger(0, bullArrow, OBJPROP_BACK, false);
               ObjectSetInteger(0, bullArrow, OBJPROP_COLOR, LongSignalColor); // Set the color of the arrow
               ObjectSetInteger(0, bullArrow, OBJPROP_ANCHOR, ANCHOR_TOP); // Set the anchor point of the arrow
               ObjectSetInteger(0, bullArrow, OBJPROP_WIDTH, 2); // Set the width of the arrow
            }

        } 
        else if (i > 0 && (i - 2) >= 0 && close[i] < (indvalue[i] - pointNum * _Point) && close[i - 2] > indvalue[i])
        {
            string bearArrow = OBJ_PREFIX + IntegerToString(i); // Unique name for the arrow object based on bar index
            double bearArrowPrice = high[i] + (arrowDistance * _Point);       
            
            if(EntryValid(open, close, high, low, i, time, rates_total) && redCandleFormation && noSidewaysMarket && significantLiquidity){
                
               gLongSignal = 0;
               gShortSignal = 1;
   
               if (Audio_Alert_On_Signals) {
                   if (last_playsound_time < time[i])
                   {
                       PlaySound(audioFilePath);
   
                       // Update last_playsound_time to the start of the current minute
                       last_playsound_time = time[i] - (time[i] % PeriodSeconds());
                   }
               }
   
               ObjectCreate(0, bearArrow, OBJ_ARROW, 0, time[i], bearArrowPrice);
               ObjectSetInteger(0, bearArrow, OBJPROP_ARROWCODE, 234);
               ObjectSetInteger(0, bearArrow, OBJPROP_BACK, false);
               ObjectSetInteger(0, bearArrow, OBJPROP_COLOR, ShortSignalColor); // Set the color of the arrow
               ObjectSetInteger(0, bearArrow, OBJPROP_ANCHOR, ANCHOR_BOTTOM); // Set the anchor point of the arrow
               ObjectSetInteger(0, bearArrow, OBJPROP_WIDTH, 2); // Set the width of the arrow
            }
        }   
    }

    // Return value of prev_calculated for the next call
    return rates_total;
}



bool EntryValid(const double& open[], const double& close[], const double& high[], const double& low[], int idx, const datetime& time[], const int bars){

  double pointSize = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
  bool valid = true;
  
  double liquidityCheck_a = MathAbs(close[idx-1] - close[idx-2])/pointSize; // analyze previous candle closes       
  double liquidityCheck_b = MathAbs(close[idx-3] - close[idx-4])/pointSize;  // analyze even older candle closes     
  double liquidityCheck_c = MathAbs(open[idx] - close[idx])/pointSize; // compare current candle open and close
  double liquidityCheck_d = MathAbs(high[idx] - low[idx])/pointSize; // compare current candle high and low
  double liquidityCheck_e = MathAbs(open[idx-1] - close[idx-1])/pointSize; // compare previous candle open and close
  double liquidityCheck_f = MathAbs(high[idx-1] - low[idx-1])/pointSize; // compare previous candle high and low 
  double liquidityCheck_g = MathAbs(close[idx-2] - close[idx-8])/pointSize;  // analyze even older candle closes     
   
   // remove signals on weak candles (market uncertainty)
   if(liquidityCheck_d < 25){
      valid = false;
   } 
   else if(liquidityCheck_e < 10){
      
      if(MathAbs(high[idx] - low[idx])/pointSize > 15){
         valid = true;
      }
      else{
         valid = false;
      } 
   } 
   else if(liquidityCheck_g < 10){
      valid = false;
   }

   return valid;
}



//+------------------------------------------------------------------+

void OnDeinit(const int reason)
{
    ObjectsDeleteAll(0, OBJ_PREFIX);
    IndicatorRelease(handle);
}


Comments

Markdown supported. Formatting help

Markdown Formatting Guide

Element Markdown Syntax
Heading # H1
## H2
### H3
Bold **bold text**
Italic *italicized text*
Link [title](https://www.example.com)
Image ![alt text](image.jpg)
Code `code`
Code Block ```
code block
```
Quote > blockquote
Unordered List - Item 1
- Item 2
Ordered List 1. First item
2. Second item
Horizontal Rule ---