//+------------------------------------------------------------------+ //| 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