generated from LengKundee/UA6-9V_VL6-N9
248 lines
9.8 KiB
MQL5
248 lines
9.8 KiB
MQL5
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| 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);
|
||
|
|
}
|
||
|
|
|
||
|
|
|