//+------------------------------------------------------------------+ //| ExpertSignal.mqh | //| Copyright 2000-2025, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #include "ExpertBase.mqh" //+------------------------------------------------------------------+ //| Macro definitions. | //+------------------------------------------------------------------+ //--- check if a market model is used #define IS_PATTERN_USAGE(p) ((m_patterns_usage&(((int)1)<
=m_threshold_open)
{
//--- there's a signal
result=true;
//--- try to get the levels of opening
if(!OpenLongParams(price,sl,tp,expiration))
result=false;
}
//--- zeroize the base price
m_base_price=0.0;
//--- return the result
return(result);
}
//+------------------------------------------------------------------+
//| Generating a sell signal |
//+------------------------------------------------------------------+
bool CExpertSignal::CheckOpenShort(double &price,double &sl,double &tp,datetime &expiration)
{
bool result =false;
//--- the "prohibition" signal
if(m_direction==EMPTY_VALUE)
return(false);
//--- check of exceeding the threshold value
if(-m_direction>=m_threshold_open)
{
//--- there's a signal
result=true;
//--- try to get the levels of opening
if(!OpenShortParams(price,sl,tp,expiration))
result=false;
}
//--- zeroize the base price
m_base_price=0.0;
//--- return the result
return(result);
}
//+------------------------------------------------------------------+
//| Detecting the levels for buying |
//+------------------------------------------------------------------+
bool CExpertSignal::OpenLongParams(double &price,double &sl,double &tp,datetime &expiration)
{
CExpertSignal *general=(m_general!=-1) ? m_filters.At(m_general) : NULL;
//---
if(general==NULL)
{
//--- if a base price is not specified explicitly, take the current market price
double base_price=(m_base_price==0.0) ? m_symbol.Ask() : m_base_price;
price =m_symbol.NormalizePrice(base_price-m_price_level*PriceLevelUnit());
sl =(m_stop_level==0.0) ? 0.0 : m_symbol.NormalizePrice(price-m_stop_level*PriceLevelUnit());
tp =(m_take_level==0.0) ? 0.0 : m_symbol.NormalizePrice(price+m_take_level*PriceLevelUnit());
expiration+=m_expiration*PeriodSeconds(m_period);
return(true);
}
//---
return(general.OpenLongParams(price,sl,tp,expiration));
}
//+------------------------------------------------------------------+
//| Detecting the levels for selling |
//+------------------------------------------------------------------+
bool CExpertSignal::OpenShortParams(double &price,double &sl,double &tp,datetime &expiration)
{
CExpertSignal *general=(m_general!=-1) ? m_filters.At(m_general) : NULL;
//---
if(general==NULL)
{
//--- if a base price is not specified explicitly, take the current market price
double base_price=(m_base_price==0.0) ? m_symbol.Bid() : m_base_price;
price =m_symbol.NormalizePrice(base_price+m_price_level*PriceLevelUnit());
sl =(m_stop_level==0.0) ? 0.0 : m_symbol.NormalizePrice(price+m_stop_level*PriceLevelUnit());
tp =(m_take_level==0.0) ? 0.0 : m_symbol.NormalizePrice(price-m_take_level*PriceLevelUnit());
expiration+=m_expiration*PeriodSeconds(m_period);
return(true);
}
//---
return(general.OpenShortParams(price,sl,tp,expiration));
}
//+------------------------------------------------------------------+
//| Generating a signal for closing of a long position |
//+------------------------------------------------------------------+
bool CExpertSignal::CheckCloseLong(double &price)
{
bool result =false;
//--- the "prohibition" signal
if(m_direction==EMPTY_VALUE)
return(false);
//--- check of exceeding the threshold value
if(-m_direction>=m_threshold_close)
{
//--- there's a signal
result=true;
//--- try to get the level of closing
if(!CloseLongParams(price))
result=false;
}
//--- zeroize the base price
m_base_price=0.0;
//--- return the result
return(result);
}
//+------------------------------------------------------------------+
//| Generating a signal for closing a short position |
//+------------------------------------------------------------------+
bool CExpertSignal::CheckCloseShort(double &price)
{
bool result =false;
//--- the "prohibition" signal
if(m_direction==EMPTY_VALUE)
return(false);
//--- check of exceeding the threshold value
if(m_direction>=m_threshold_close)
{
//--- there's a signal
result=true;
//--- try to get the level of closing
if(!CloseShortParams(price))
result=false;
}
//--- zeroize the base price
m_base_price=0.0;
//--- return the result
return(result);
}
//+------------------------------------------------------------------+
//| Detecting the levels for closing a long position |
//+------------------------------------------------------------------+
bool CExpertSignal::CloseLongParams(double &price)
{
CExpertSignal *general=(m_general!=-1) ? m_filters.At(m_general) : NULL;
//---
if(general==NULL)
{
//--- if a base price is not specified explicitly, take the current market price
price=(m_base_price==0.0) ? m_symbol.Bid() : m_base_price;
return(true);
}
//---
return(general.CloseLongParams(price));
}
//+------------------------------------------------------------------+
//| Detecting the levels for closing a short position |
//+------------------------------------------------------------------+
bool CExpertSignal::CloseShortParams(double &price)
{
CExpertSignal *general=(m_general!=-1) ? m_filters.At(m_general) : NULL;
//---
if(general==NULL)
{
//--- if a base price is not specified explicitly, take the current market price
price=(m_base_price==0.0)?m_symbol.Ask():m_base_price;
return(true);
}
//--- ok
return(general.CloseShortParams(price));
}
//+------------------------------------------------------------------+
//| Generating a signal for reversing a long position |
//+------------------------------------------------------------------+
bool CExpertSignal::CheckReverseLong(double &price,double &sl,double &tp,datetime &expiration)
{
double c_price;
//--- check the signal of closing a long position
if(!CheckCloseLong(c_price))
return(false);
//--- check the signal of opening a short position
if(!CheckOpenShort(price,sl,tp,expiration))
return(false);
//--- difference between the close and open prices must not exceed two spreads
if(c_price!=price)
return(false);
//--- there's a signal
return(true);
}
//+------------------------------------------------------------------+
//| Generating a signal for reversing a short position |
//+------------------------------------------------------------------+
bool CExpertSignal::CheckReverseShort(double &price,double &sl,double &tp,datetime &expiration)
{
double c_price;
//--- check the signal of closing a short position
if(!CheckCloseShort(c_price))
return(false);
//--- check the signal of opening a long position
if(!CheckOpenLong(price,sl,tp,expiration))
return(false);
//--- difference between the close and open prices must not exceed two spreads
if(c_price!=price)
return(false);
//--- there's a signal
return(true);
}
//+------------------------------------------------------------------+
//| Detecting the "weighted" direction |
//+------------------------------------------------------------------+
double CExpertSignal::Direction(void)
{
long mask;
double direction;
double result=m_weight*(LongCondition()-ShortCondition());
int number=(result==0.0)? 0 : 1; // number of "voted"
//---
int total=m_filters.Total();
//--- loop by filters
for(int i=0;i