Price Data Components
Indicators Used
Miscellaneous
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 Formatting Guide
# H1
## H2
### H3
**bold text**
*italicized text*
[title](https://www.example.com)

`code`
```
code block
```
> blockquote
- Item 1
- Item 2
1. First item
2. Second item
---