Add files via upload

This commit is contained in:
amirghadiri1987
2025-02-07 19:08:31 +03:30
committed by GitHub
parent c33ac55f2f
commit a9340e5d4e
85 changed files with 15214 additions and 0 deletions
BIN
View File
Binary file not shown.
+715
View File
@@ -0,0 +1,715 @@
//+------------------------------------------------------------------+
//| ExpertBase.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Trade\SymbolInfo.mqh>
#include <Trade\AccountInfo.mqh>
#include <Trade\PositionInfo.mqh>
#include <Trade\OrderInfo.mqh>
#include <Trade\DealInfo.mqh>
#include <Trade\HistoryOrderInfo.mqh>
#include <Indicators\Indicators.mqh>
//+------------------------------------------------------------------+
//| enumerations |
//+------------------------------------------------------------------+
//--- constants of identification of trend
enum ENUM_TYPE_TREND
{
TYPE_TREND_HARD_DOWN =0, // strong down trend
TYPE_TREND_DOWN =1, // down trend
TYPE_TREND_SOFT_DOWN =2, // weak down trend
TYPE_TREND_FLAT =3, // no trend
TYPE_TREND_SOFT_UP =4, // weak up trend
TYPE_TREND_UP =5, // up trend
TYPE_TREND_HARD_UP =6 // strong up trend
};
//--- flags of used timeseries
enum ENUM_USED_SERIES
{
USE_SERIES_OPEN =0x1,
USE_SERIES_HIGH =0x2,
USE_SERIES_LOW =0x4,
USE_SERIES_CLOSE =0x8,
USE_SERIES_SPREAD =0x10,
USE_SERIES_TIME =0x20,
USE_SERIES_TICK_VOLUME=0x40,
USE_SERIES_REAL_VOLUME=0x80
};
//--- phases of initialization of an object
enum ENUM_INIT_PHASE
{
INIT_PHASE_FIRST =0, // start phase (only Init(...) can be called)
INIT_PHASE_TUNING =1, // phase of tuning (set in Init(...))
INIT_PHASE_VALIDATION =2, // phase of checking of parameters(set in ValidationSettings(...))
INIT_PHASE_COMPLETE =3 // end phase (set in InitIndicators(...))
};
//+------------------------------------------------------------------+
//| Macro definitions. |
//+------------------------------------------------------------------+
//--- check the use of timeseries
#define IS_OPEN_SERIES_USAGE ((m_used_series&USE_SERIES_OPEN)!=0)
#define IS_HIGH_SERIES_USAGE ((m_used_series&USE_SERIES_HIGH)!=0)
#define IS_LOW_SERIES_USAGE ((m_used_series&USE_SERIES_LOW)!=0)
#define IS_CLOSE_SERIES_USAGE ((m_used_series&USE_SERIES_CLOSE)!=0)
#define IS_SPREAD_SERIES_USAGE ((m_used_series&USE_SERIES_SPREAD)!=0)
#define IS_TIME_SERIES_USAGE ((m_used_series&USE_SERIES_TIME)!=0)
#define IS_TICK_VOLUME_SERIES_USAGE ((m_used_series&USE_SERIES_TICK_VOLUME)!=0)
#define IS_REAL_VOLUME_SERIES_USAGE ((m_used_series&USE_SERIES_REAL_VOLUME)!=0)
//+------------------------------------------------------------------+
//| Class CExpertBase. |
//| Purpose: Base class of component of Expert Advisor. |
//| Derives from class CObject. |
//+------------------------------------------------------------------+
class CExpertBase : public CObject
{
protected:
//--- variables
ulong m_magic; // expert magic number
ENUM_INIT_PHASE m_init_phase; // the phase (stage) of initialization of object
bool m_other_symbol; // flag of a custom work symbols (different from one of the Expert Advisor)
CSymbolInfo *m_symbol; // pointer to the object-symbol
bool m_other_period; // flag of a custom timeframe (different from one of the Expert Advisor)
ENUM_TIMEFRAMES m_period; // work timeframe
double m_adjusted_point; // "weight" 2/4 of a point
CAccountInfo m_account; // object-deposit
ENUM_ACCOUNT_MARGIN_MODE m_margin_mode; // netting or hedging
ENUM_TYPE_TREND m_trend_type; // identifier of trend
bool m_every_tick; // flag of starting the analysis from current (incomplete) bar
//--- timeseries
int m_used_series; // flags of using of series
CiOpen *m_open; // pointer to the object for access to open prices of bars
CiHigh *m_high; // pointer to the object for access to high prices of bars
CiLow *m_low; // pointer to the object for access to low prices of bars
CiClose *m_close; // pointer to the object for access to close prices of bars
CiSpread *m_spread; // pointer to the object for access to spreads
CiTime *m_time; // pointer to the object for access to time of closing of bars
CiTickVolume *m_tick_volume; // pointer to the object for access to tick volumes of bars
CiRealVolume *m_real_volume; // pointer to the object for access to real volumes of bars
public:
CExpertBase(void);
~CExpertBase(void);
//--- methods of access to protected data
ENUM_INIT_PHASE InitPhase(void) const { return(m_init_phase); }
void TrendType(ENUM_TYPE_TREND value) { m_trend_type=value; }
int UsedSeries(void) const;
void EveryTick(bool value) { m_every_tick=value; }
//--- methods of access to protected data
double Open(int ind) const;
double High(int ind) const;
double Low(int ind) const;
double Close(int ind) const;
int Spread(int ind) const;
datetime Time(int ind) const;
long TickVolume(int ind) const;
long RealVolume(int ind) const;
//--- methods of initialization of the object
virtual bool Init(CSymbolInfo *symbol,ENUM_TIMEFRAMES period,double point);
bool Symbol(string name);
bool Period(ENUM_TIMEFRAMES value);
void Magic(ulong value) { m_magic=value; }
void SetMarginMode(void) { m_margin_mode=(ENUM_ACCOUNT_MARGIN_MODE)AccountInfoInteger(ACCOUNT_MARGIN_MODE); }
//--- method of verification of settings
virtual bool ValidationSettings();
//--- methods of creating the indicator and timeseries
virtual bool SetPriceSeries(CiOpen *open,CiHigh *high,CiLow *low,CiClose *close);
virtual bool SetOtherSeries(CiSpread *spread,CiTime *time,CiTickVolume *tick_volume,CiRealVolume *real_volume);
virtual bool InitIndicators(CIndicators *indicators=NULL);
protected:
//--- methods initialization of timeseries
bool InitOpen(CIndicators *indicators);
bool InitHigh(CIndicators *indicators);
bool InitLow(CIndicators *indicators);
bool InitClose(CIndicators *indicators);
bool InitSpread(CIndicators *indicators);
bool InitTime(CIndicators *indicators);
bool InitTickVolume(CIndicators *indicators);
bool InitRealVolume(CIndicators *indicators);
//--- method of getting the measure units of price levels
virtual double PriceLevelUnit(void) { return(m_adjusted_point); }
//--- method of getting index of bar the analysis starts with
virtual int StartIndex(void) { return((m_every_tick?0:1)); }
virtual bool CompareMagic(ulong magic) { return(m_magic==magic); }
bool IsHedging(void) const { return(m_margin_mode==ACCOUNT_MARGIN_MODE_RETAIL_HEDGING); }
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
void CExpertBase::CExpertBase(void) : m_magic(0),
m_margin_mode(ACCOUNT_MARGIN_MODE_RETAIL_NETTING),
m_init_phase(INIT_PHASE_FIRST),
m_other_symbol(false),
m_symbol(NULL),
m_other_period(false),
m_period(PERIOD_CURRENT),
m_adjusted_point(1.0),
m_trend_type(TYPE_TREND_FLAT),
m_every_tick(false),
m_used_series(0),
m_open(NULL),
m_high(NULL),
m_low(NULL),
m_close(NULL),
m_spread(NULL),
m_time(NULL),
m_tick_volume(NULL),
m_real_volume(NULL)
{
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
void CExpertBase::~CExpertBase(void)
{
//--- if the symbol is "custom", delete it
if(m_other_symbol && m_symbol!=NULL)
delete m_symbol;
//--- release of "custom" timeseries
if(m_other_symbol || m_other_period)
{
if(IS_OPEN_SERIES_USAGE && CheckPointer(m_open)==POINTER_DYNAMIC)
delete m_open;
if(IS_HIGH_SERIES_USAGE && CheckPointer(m_high)==POINTER_DYNAMIC)
delete m_high;
if(IS_LOW_SERIES_USAGE && CheckPointer(m_low)==POINTER_DYNAMIC)
delete m_low;
if(IS_CLOSE_SERIES_USAGE && CheckPointer(m_close)==POINTER_DYNAMIC)
delete m_close;
if(IS_SPREAD_SERIES_USAGE && CheckPointer(m_spread)==POINTER_DYNAMIC)
delete m_spread;
if(IS_TIME_SERIES_USAGE && CheckPointer(m_time)==POINTER_DYNAMIC)
delete m_time;
if(IS_TICK_VOLUME_SERIES_USAGE && CheckPointer(m_tick_volume)==POINTER_DYNAMIC)
delete m_tick_volume;
if(IS_REAL_VOLUME_SERIES_USAGE && CheckPointer(m_real_volume)==POINTER_DYNAMIC)
delete m_real_volume;
}
}
//+------------------------------------------------------------------+
//| Get flags of used timeseries |
//+------------------------------------------------------------------+
int CExpertBase::UsedSeries(void) const
{
if(m_other_symbol || m_other_period)
return(0);
//---
return(m_used_series);
}
//+------------------------------------------------------------------+
//| Initialization of object. |
//+------------------------------------------------------------------+
bool CExpertBase::Init(CSymbolInfo *symbol,ENUM_TIMEFRAMES period,double point)
{
//--- check the initialization phase
if(m_init_phase!=INIT_PHASE_FIRST)
{
Print(__FUNCTION__+": attempt of re-initialization");
return(false);
}
//--- check of pointer
if(symbol==NULL)
{
Print(__FUNCTION__+": error initialization");
return(false);
}
//--- initialization
m_symbol =symbol;
m_period =period;
m_adjusted_point=point;
m_other_symbol =false;
m_other_period =false;
SetMarginMode();
//--- primary initialization is successful, pass to the phase of tuning
m_init_phase=INIT_PHASE_TUNING;
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Changing work symbol. |
//+------------------------------------------------------------------+
bool CExpertBase::Symbol(string name)
{
//--- check the initialization phase
if(m_init_phase!=INIT_PHASE_TUNING)
{
Print(__FUNCTION__+": changing of symbol is forbidden");
return(false);
}
if(m_symbol!=NULL)
{
//--- symbol has been already set
if(m_symbol.Name()==name)
return(true);
//--- symbol is not the one required, but is already "custom"
if(m_other_symbol)
{
if(!m_symbol.Name(name))
{
//--- failed to initialize the symbol
delete m_symbol;
return(false);
}
return(true);
}
}
m_symbol=new CSymbolInfo;
//--- check of pointer
if(m_symbol==NULL)
{
Print(__FUNCTION__+": error of changing of symbol");
return(false);
}
if(!m_symbol.Name(name))
{
//--- failed to initialize the symbol
delete m_symbol;
return(false);
}
m_other_symbol=true;
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Changing work timeframe. |
//+------------------------------------------------------------------+
bool CExpertBase::Period(ENUM_TIMEFRAMES value)
{
//--- check the initialization phase
if(m_init_phase!=INIT_PHASE_TUNING)
{
Print(__FUNCTION__+": changing of timeframe is forbidden");
return(false);
}
if(m_period==value)
return(true);
//--- change work timeframe
m_period=value;
m_other_period=true;
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Checking adjustable parameters |
//+------------------------------------------------------------------+
bool CExpertBase::ValidationSettings()
{
//--- rechecking parameters
if(m_init_phase==INIT_PHASE_VALIDATION)
return(true);
//--- check the initialization phase
if(m_init_phase!=INIT_PHASE_TUNING)
{
Print(__FUNCTION__+": not the right time to check parameters");
return(false);
}
//--- initial check of parameters is successful, phase of tuning is over
m_init_phase=INIT_PHASE_VALIDATION;
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Setting pointers of price timeseries. |
//+------------------------------------------------------------------+
bool CExpertBase::SetPriceSeries(CiOpen *open,CiHigh *high,CiLow *low,CiClose *close)
{
//--- check the initialization phase
if(m_init_phase!=INIT_PHASE_VALIDATION)
{
Print(__FUNCTION__+": changing of timeseries is forbidden");
return(false);
}
//--- check pointers
if((IS_OPEN_SERIES_USAGE && open==NULL) ||
(IS_HIGH_SERIES_USAGE && high==NULL) ||
(IS_LOW_SERIES_USAGE && low==NULL) ||
(IS_CLOSE_SERIES_USAGE && close==NULL))
{
Print(__FUNCTION__+": NULL pointer");
return(false);
}
m_open =open;
m_high =high;
m_low =low;
m_close=close;
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Setting pointers of other timeseries. |
//+------------------------------------------------------------------+
bool CExpertBase::SetOtherSeries(CiSpread *spread,CiTime *time,CiTickVolume *tick_volume,CiRealVolume *real_volume)
{
//--- check the initialization phase
if(m_init_phase!=INIT_PHASE_VALIDATION)
{
Print(__FUNCTION__+": changing of timeseries is forbidden");
return(false);
}
//--- check pointers
if((IS_SPREAD_SERIES_USAGE && spread==NULL) ||
(IS_TIME_SERIES_USAGE && time==NULL) ||
(IS_TICK_VOLUME_SERIES_USAGE && tick_volume==NULL) ||
(IS_REAL_VOLUME_SERIES_USAGE && real_volume==NULL))
{
Print(__FUNCTION__+": NULL pointer");
return(false);
}
m_spread =spread;
m_time =time;
m_tick_volume=tick_volume;
m_real_volume=real_volume;
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Initialization of indicators and timeseries. |
//+------------------------------------------------------------------+
bool CExpertBase::InitIndicators(CIndicators *indicators)
{
//--- this call is for compatibility with the previous version
if(!ValidationSettings())
return(false);
//--- check the initialization phase
if(m_init_phase!=INIT_PHASE_VALIDATION)
{
Print(__FUNCTION__+": parameters of setting are not checked");
return(false);
}
if(!m_other_symbol && !m_other_period)
return(true);
//--- check pointers
if(m_symbol==NULL)
return(false);
if(indicators==NULL)
return(false);
//--- initialization of required timeseries
if(IS_OPEN_SERIES_USAGE && !InitOpen(indicators))
return(false);
if(IS_HIGH_SERIES_USAGE && !InitHigh(indicators))
return(false);
if(IS_LOW_SERIES_USAGE && !InitLow(indicators))
return(false);
if(IS_CLOSE_SERIES_USAGE && !InitClose(indicators))
return(false);
if(IS_SPREAD_SERIES_USAGE && !InitSpread(indicators))
return(false);
if(IS_TIME_SERIES_USAGE && !InitTime(indicators))
return(false);
if(IS_TICK_VOLUME_SERIES_USAGE && !InitTickVolume(indicators))
return(false);
if(IS_REAL_VOLUME_SERIES_USAGE && !InitRealVolume(indicators))
return(false);
//--- initialization of object (from the point of view of the base class) has been performed successfully
//--- now it's impossible to change anything in the settings
m_init_phase=INIT_PHASE_COMPLETE;
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Access to data of the Open timeseries. |
//+------------------------------------------------------------------+
double CExpertBase::Open(int ind) const
{
//--- check pointer
if(m_open==NULL)
return(EMPTY_VALUE);
//--- return the result
return(m_open.GetData(ind));
}
//+------------------------------------------------------------------+
//| Access to data of the High timeseries. |
//+------------------------------------------------------------------+
double CExpertBase::High(int ind) const
{
//--- check pointer
if(m_high==NULL)
return(EMPTY_VALUE);
//--- return the result
return(m_high.GetData(ind));
}
//+------------------------------------------------------------------+
//| Access to data of the Low timeseries. |
//+------------------------------------------------------------------+
double CExpertBase::Low(int ind) const
{
//--- check pointer
if(m_low==NULL)
return(EMPTY_VALUE);
//--- return the result
return(m_low.GetData(ind));
}
//+------------------------------------------------------------------+
//| Access to data of the Close timeseries. |
//+------------------------------------------------------------------+
double CExpertBase::Close(int ind) const
{
//--- check pointer
if(m_close==NULL)
return(EMPTY_VALUE);
//--- return the result
return(m_close.GetData(ind));
}
//+------------------------------------------------------------------+
//| Access to data of the Spread timeseries. |
//+------------------------------------------------------------------+
int CExpertBase::Spread(int ind) const
{
//--- check pointer
if(m_spread==NULL)
return(INT_MAX);
//--- return the result
return(m_spread.GetData(ind));
}
//+------------------------------------------------------------------+
//| Access to data of the Time timeseries. |
//+------------------------------------------------------------------+
datetime CExpertBase::Time(int ind) const
{
//--- check pointer
if(m_time==NULL)
return(0);
//--- return the result
return(m_time.GetData(ind));
}
//+------------------------------------------------------------------+
//| Access to data of the TickVolume timeseries. |
//+------------------------------------------------------------------+
long CExpertBase::TickVolume(int ind) const
{
//--- check pointer
if(m_tick_volume==NULL)
return(0);
//--- return the result
return(m_tick_volume.GetData(ind));
}
//+------------------------------------------------------------------+
//| Access to data of the RealVolume timeseries. |
//+------------------------------------------------------------------+
long CExpertBase::RealVolume(int ind) const
{
//--- check pointer
if(m_real_volume==NULL)
return(0);
//--- return the result
return(m_real_volume.GetData(ind));
}
//+------------------------------------------------------------------+
//| Initialization of the Open timeseries. |
//+------------------------------------------------------------------+
bool CExpertBase::InitOpen(CIndicators *indicators)
{
//--- create object
if((m_open=new CiOpen)==NULL)
{
Print(__FUNCTION__+": error creating object");
return(false);
}
//--- add object to collection
if(!indicators.Add(m_open))
{
Print(__FUNCTION__+": error adding object");
delete m_open;
return(false);
}
//--- initialize object
if(!m_open.Create(m_symbol.Name(),m_period))
{
Print(__FUNCTION__+": error initializing object");
return(false);
}
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Initialization of the High timeseries. |
//+------------------------------------------------------------------+
bool CExpertBase::InitHigh(CIndicators *indicators)
{
//--- create object
if((m_high=new CiHigh)==NULL)
{
Print(__FUNCTION__+": error creating object");
return(false);
}
//--- add object to collection
if(!indicators.Add(m_high))
{
Print(__FUNCTION__+": error adding object");
delete m_high;
return(false);
}
//--- initialize object
if(!m_high.Create(m_symbol.Name(),m_period))
{
Print(__FUNCTION__+": error initializing object");
return(false);
}
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Initialization of the Low timeseries. |
//+------------------------------------------------------------------+
bool CExpertBase::InitLow(CIndicators *indicators)
{
//--- create object
if((m_low=new CiLow)==NULL)
{
Print(__FUNCTION__+": error creating object");
return(false);
}
//--- add object to collection
if(!indicators.Add(m_low))
{
Print(__FUNCTION__+": error adding object");
delete m_low;
return(false);
}
//--- initialize object
if(!m_low.Create(m_symbol.Name(),m_period))
{
Print(__FUNCTION__+": error initializing object");
return(false);
}
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Initialization of the Close timeseries. |
//+------------------------------------------------------------------+
bool CExpertBase::InitClose(CIndicators *indicators)
{
//--- create object
if((m_close=new CiClose)==NULL)
{
Print(__FUNCTION__+": error creating object");
return(false);
}
//--- add object to collection
if(!indicators.Add(m_close))
{
Print(__FUNCTION__+": error adding object");
delete m_close;
return(false);
}
//--- initialize object
if(!m_close.Create(m_symbol.Name(),m_period))
{
Print(__FUNCTION__+": error initializing object");
return(false);
}
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Initialization of the Spread timeseries. |
//+------------------------------------------------------------------+
bool CExpertBase::InitSpread(CIndicators *indicators)
{
//--- create object
if((m_spread=new CiSpread)==NULL)
{
Print(__FUNCTION__+": error creating object");
return(false);
}
//--- add object to collection
if(!indicators.Add(m_spread))
{
Print(__FUNCTION__+": error adding object");
delete m_spread;
return(false);
}
//--- initialize object
if(!m_spread.Create(m_symbol.Name(),m_period))
{
Print(__FUNCTION__+": error initializing object");
return(false);
}
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Initialization of the Time timeseries. |
//+------------------------------------------------------------------+
bool CExpertBase::InitTime(CIndicators *indicators)
{
//--- create object
if((m_time=new CiTime)==NULL)
{
Print(__FUNCTION__+": error creating object");
return(false);
}
//--- add object to collection
if(!indicators.Add(m_time))
{
Print(__FUNCTION__+": error adding object");
delete m_time;
return(false);
}
//--- initialize object
if(!m_time.Create(m_symbol.Name(),m_period))
{
Print(__FUNCTION__+": error initializing object");
return(false);
}
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Initialization of the TickVolume timeseries. |
//+------------------------------------------------------------------+
bool CExpertBase::InitTickVolume(CIndicators *indicators)
{
//--- create object
if((m_tick_volume=new CiTickVolume)==NULL)
{
Print(__FUNCTION__+": error creating object");
return(false);
}
//--- add object to collection
if(!indicators.Add(m_tick_volume))
{
Print(__FUNCTION__+": error adding object");
delete m_tick_volume;
return(false);
}
//--- initialize object
if(!m_tick_volume.Create(m_symbol.Name(),m_period))
{
Print(__FUNCTION__+": error initializing object");
return(false);
}
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Initialization of the RealVolume timeseries. |
//+------------------------------------------------------------------+
bool CExpertBase::InitRealVolume(CIndicators *indicators)
{
//--- create object
if((m_real_volume=new CiRealVolume)==NULL)
{
Print(__FUNCTION__+": error creating object");
return(false);
}
//--- add object to collection
if(!indicators.Add(m_real_volume))
{
Print(__FUNCTION__+": error adding object");
delete m_real_volume;
return(false);
}
//--- initialize object
if(!m_real_volume.Create(m_symbol.Name(),m_period))
{
Print(__FUNCTION__+": error initializing object");
return(false);
}
//--- ok
return(true);
}
//+------------------------------------------------------------------+
+124
View File
@@ -0,0 +1,124 @@
//+------------------------------------------------------------------+
//| ExpertMoney.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include "ExpertBase.mqh"
//+------------------------------------------------------------------+
//| Class CExpertMoney. |
//| Purpose: Base class money managment. |
//| Derives from class CExpertBase. |
//+------------------------------------------------------------------+
class CExpertMoney : public CExpertBase
{
protected:
//--- input parameters
double m_percent;
public:
CExpertMoney(void);
~CExpertMoney(void);
//--- methods of setting adjustable parameters
void Percent(double percent) { m_percent=percent; }
//--- method of verification of settings
virtual bool ValidationSettings();
//---
virtual double CheckOpenLong(double price,double sl);
virtual double CheckOpenShort(double price,double sl);
virtual double CheckReverse(CPositionInfo *position,double sl);
virtual double CheckClose(CPositionInfo *position);
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
void CExpertMoney::CExpertMoney(void) : m_percent(10.0)
{
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
void CExpertMoney::~CExpertMoney(void)
{
}
//+------------------------------------------------------------------+
//| Validation settings protected data. |
//+------------------------------------------------------------------+
bool CExpertMoney::ValidationSettings()
{
if(!CExpertBase::ValidationSettings())
return(false);
//--- initial data checks
if(m_percent<0.0 || m_percent>100.0)
{
printf(__FUNCTION__+": percentage of risk should be in the range from 0 to 100 inclusive");
return(false);
}
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Getting lot size for open long position. |
//+------------------------------------------------------------------+
double CExpertMoney::CheckOpenLong(double price,double sl)
{
if(m_symbol==NULL)
return(0.0);
//---
double lot;
if(price==0.0)
lot=m_account.MaxLotCheck(m_symbol.Name(),ORDER_TYPE_BUY,m_symbol.Ask(),m_percent);
else
lot=m_account.MaxLotCheck(m_symbol.Name(),ORDER_TYPE_BUY,price,m_percent);
if(lot<m_symbol.LotsMin())
return(0.0);
//---
return(m_symbol.LotsMin());
}
//+------------------------------------------------------------------+
//| Getting lot size for open short position. |
//+------------------------------------------------------------------+
double CExpertMoney::CheckOpenShort(double price,double sl)
{
if(m_symbol==NULL)
return(0.0);
//---
double lot;
if(price==0.0)
lot=m_account.MaxLotCheck(m_symbol.Name(),ORDER_TYPE_SELL,m_symbol.Bid(),m_percent);
else
lot=m_account.MaxLotCheck(m_symbol.Name(),ORDER_TYPE_SELL,price,m_percent);
if(lot<m_symbol.LotsMin())
return(0.0);
//---
return(m_symbol.LotsMin());
}
//+------------------------------------------------------------------+
//| Getting lot size for reverse. |
//+------------------------------------------------------------------+
double CExpertMoney::CheckReverse(CPositionInfo *position,double sl)
{
double lots=0.0;
//---
if(position.PositionType()==POSITION_TYPE_BUY)
lots=CheckOpenShort(m_symbol.Bid(),sl);
if(position.PositionType()==POSITION_TYPE_SELL)
lots=CheckOpenLong(m_symbol.Ask(),sl);
//---
if(lots!=0.0) lots+=position.Volume();
//---
return(lots);
}
//+------------------------------------------------------------------+
//| Getting lot size for close. |
//+------------------------------------------------------------------+
double CExpertMoney::CheckClose(CPositionInfo *position)
{
if(m_percent==0.0)
return(0.0);
//---
if(-position.Profit()>m_account.Balance()*m_percent/100.0)
return(position.Volume());
//---
return(0.0);
}
//+------------------------------------------------------------------+
+464
View File
@@ -0,0 +1,464 @@
//+------------------------------------------------------------------+
//| ExpertSignal.mqh |
//| Copyright 2000-2024, 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)<<p))!=0)
//+------------------------------------------------------------------+
//| Class CExpertSignal. |
//| Purpose: Base class trading signals. |
//| Derives from class CExpertBase. |
//+------------------------------------------------------------------+
class CExpertSignal : public CExpertBase
{
protected:
//--- variables
double m_base_price; // base price for detection of level of entering (and/or exit?)
//--- variables for working with additional filters
CArrayObj m_filters; // array of additional filters (maximum number of fileter is 64)
//--- Adjusted parameters
double m_weight; // "weight" of a signal in a combined filter
int m_patterns_usage; // bit mask of using of the market models of signals
int m_general; // index of the "main" signal (-1 - no)
long m_ignore; // bit mask of "ignoring" the additional filter
long m_invert; // bit mask of "inverting" the additional filter
int m_threshold_open; // threshold value for opening
int m_threshold_close;// threshold level for closing
double m_price_level; // level of placing a pending orders relatively to the base price
double m_stop_level; // level of placing of the "stop loss" order relatively to the open price
double m_take_level; // level of placing of the "take profit" order relatively to the open price
int m_expiration; // time of expiration of a pending order in bars
double m_direction; // weighted direction
public:
CExpertSignal(void);
~CExpertSignal(void);
//--- methods of access to protected data
void BasePrice(double value) { m_base_price=value; }
int UsedSeries(void);
//--- methods of setting adjustable parameters
void Weight(double value) { m_weight=value; }
void PatternsUsage(int value) { m_patterns_usage=value; }
void General(int value) { m_general=value; }
void Ignore(long value) { m_ignore=value; }
void Invert(long value) { m_invert=value; }
void ThresholdOpen(int value) { m_threshold_open=value; }
void ThresholdClose(int value) { m_threshold_close=value; }
void PriceLevel(double value) { m_price_level=value; }
void StopLevel(double value) { m_stop_level=value; }
void TakeLevel(double value) { m_take_level=value; }
void Expiration(int value) { m_expiration=value; }
//--- method of initialization of the object
void Magic(ulong value);
//--- method of verification of settings
virtual bool ValidationSettings(void);
//--- method of creating the indicator and timeseries
virtual bool InitIndicators(CIndicators *indicators);
//--- methods for working with additional filters
virtual bool AddFilter(CExpertSignal *filter);
//--- methods for generating signals of entering the market
virtual bool CheckOpenLong(double &price,double &sl,double &tp,datetime &expiration);
virtual bool CheckOpenShort(double &price,double &sl,double &tp,datetime &expiration);
//--- methods for detection of levels of entering the market
virtual bool OpenLongParams(double &price,double &sl,double &tp,datetime &expiration);
virtual bool OpenShortParams(double &price,double &sl,double &tp,datetime &expiration);
//--- methods for generating signals of exit from the market
virtual bool CheckCloseLong(double &price);
virtual bool CheckCloseShort(double &price);
//--- methods for detection of levels of exit from the market
virtual bool CloseLongParams(double &price);
virtual bool CloseShortParams(double &price);
//--- methods for generating signals of reversal of positions
virtual bool CheckReverseLong(double &price,double &sl,double &tp,datetime &expiration);
virtual bool CheckReverseShort(double &price,double &sl,double &tp,datetime &expiration);
//--- methods for generating signals of modification of pending orders
virtual bool CheckTrailingOrderLong(COrderInfo *order,double &price) { return(false); }
virtual bool CheckTrailingOrderShort(COrderInfo *order,double &price) { return(false); }
//--- methods of checking if the market models are formed
virtual int LongCondition(void) { return(0); }
virtual int ShortCondition(void) { return(0); }
virtual double Direction(void);
void SetDirection(void) { m_direction=Direction(); }
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CExpertSignal::CExpertSignal(void) : m_base_price(0.0),
m_general(-1), // no "main" signal
m_weight(1.0),
m_patterns_usage(-1), // all models are used
m_ignore(0), // all additional filters are used
m_invert(0),
m_threshold_open(50),
m_threshold_close(100),
m_price_level(0.0),
m_stop_level(0.0),
m_take_level(0.0),
m_expiration(0),
m_direction(EMPTY_VALUE)
{
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CExpertSignal::~CExpertSignal(void)
{
}
//+------------------------------------------------------------------+
//| Get flags of used timeseries |
//+------------------------------------------------------------------+
int CExpertSignal::UsedSeries(void)
{
if(m_other_symbol || m_other_period)
return(0);
//--- check of the flags of using timeseries in the additional filters
int total=m_filters.Total();
//--- loop by the additional filters
for(int i=0;i<total;i++)
{
CExpertSignal *filter=m_filters.At(i);
//--- check pointer
if(filter==NULL)
return(false);
m_used_series|=filter.UsedSeries();
}
//---
return(m_used_series);
}
//+------------------------------------------------------------------+
//| Sets magic number for object and its dependent objects |
//+------------------------------------------------------------------+
void CExpertSignal::Magic(ulong value)
{
int total=m_filters.Total();
//--- loop by the additional filters
for(int i=0;i<total;i++)
{
CExpertSignal *filter=m_filters.At(i);
//--- check pointer
if(filter==NULL)
continue;
filter.Magic(value);
}
//---
CExpertBase::Magic(value);
}
//+------------------------------------------------------------------+
//| Validation settings protected data |
//+------------------------------------------------------------------+
bool CExpertSignal::ValidationSettings(void)
{
if(!CExpertBase::ValidationSettings())
return(false);
//--- check of parameters in the additional filters
int total=m_filters.Total();
//--- loop by the additional filters
for(int i=0;i<total;i++)
{
CExpertSignal *filter=m_filters.At(i);
//--- check pointer
if(filter==NULL)
return(false);
if(!filter.ValidationSettings())
return(false);
}
//--- succeed
return(true);
}
//+------------------------------------------------------------------+
//| Create indicators |
//+------------------------------------------------------------------+
bool CExpertSignal::InitIndicators(CIndicators *indicators)
{
//--- check pointer
if(indicators==NULL)
return(false);
//---
CExpertSignal *filter;
int total=m_filters.Total();
//--- gather information about using of timeseries
for(int i=0;i<total;i++)
{
filter=m_filters.At(i);
m_used_series|=filter.UsedSeries();
}
//--- create required timeseries
if(!CExpertBase::InitIndicators(indicators))
return(false);
//--- initialization of indicators and timeseries in the additional filters
for(int i=0;i<total;i++)
{
filter=m_filters.At(i);
filter.SetPriceSeries(m_open,m_high,m_low,m_close);
filter.SetOtherSeries(m_spread,m_time,m_tick_volume,m_real_volume);
if(!filter.InitIndicators(indicators))
return(false);
}
//--- succeed
return(true);
}
//+------------------------------------------------------------------+
//| Setting an additional filter |
//+------------------------------------------------------------------+
bool CExpertSignal::AddFilter(CExpertSignal *filter)
{
//--- check pointer
if(filter==NULL)
return(false);
//--- primary initialization of the filter
if(!filter.Init(m_symbol,m_period,m_adjusted_point))
return(false);
//--- add the filter to the array of filters
if(!m_filters.Add(filter))
return(false);
filter.EveryTick(m_every_tick);
filter.Magic(m_magic);
//--- succeed
return(true);
}
//+------------------------------------------------------------------+
//| Generating a buy signal |
//+------------------------------------------------------------------+
bool CExpertSignal::CheckOpenLong(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(!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<total;i++)
{
//--- mask for bit maps
mask=((long)1)<<i;
//--- check of the flag of ignoring the signal of filter
if((m_ignore&mask)!=0)
continue;
CExpertSignal *filter=m_filters.At(i);
//--- check pointer
if(filter==NULL)
continue;
direction=filter.Direction();
//--- the "prohibition" signal
if(direction==EMPTY_VALUE)
return(EMPTY_VALUE);
//--- check of flag of inverting the signal of filter
if((m_invert&mask)!=0)
result-=direction;
else
result+=direction;
number++;
}
//--- normalization
if(number!=0)
result/=number;
//--- return the result
return(result);
}
//+------------------------------------------------------------------+
+171
View File
@@ -0,0 +1,171 @@
//+------------------------------------------------------------------+
//| ExpertTrade.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Trade\SymbolInfo.mqh>
#include <Trade\PositionInfo.mqh>
#include <Trade\OrderInfo.mqh>
#include <Trade\AccountInfo.mqh>
#include <Trade\Trade.mqh>
//+------------------------------------------------------------------+
//| Class CExpertTrade. |
//| Appointment: Class simple trade operations. |
//| Derives from class CTrade. |
//+------------------------------------------------------------------+
class CExpertTrade : public CTrade
{
protected:
ENUM_ORDER_TYPE_TIME m_order_type_time;
datetime m_order_expiration;
CSymbolInfo *m_symbol; // symbol object
CAccountInfo m_account; // account object
public:
CExpertTrade(void);
~CExpertTrade(void);
//--- methods for easy trade
bool SetSymbol(CSymbolInfo *symbol);
bool SetOrderTypeTime(ENUM_ORDER_TYPE_TIME order_type_time);
bool SetOrderExpiration(datetime order_expiration);
bool Buy(double volume,double price,double sl,double tp,const string comment="");
bool Sell(double volume,double price,double sl,double tp,const string comment="");
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
void CExpertTrade::CExpertTrade(void) : m_symbol(NULL),
m_order_type_time(ORDER_TIME_GTC),
m_order_expiration(0)
{
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CExpertTrade::~CExpertTrade(void)
{
}
//+------------------------------------------------------------------+
//| Setting working symbol for easy trade operations. |
//+------------------------------------------------------------------+
bool CExpertTrade::SetSymbol(CSymbolInfo *symbol)
{
if(symbol!=NULL)
{
m_symbol=symbol;
return(true);
}
//---
return(false);
}
//+------------------------------------------------------------------+
//| Setting order expiration type for easy trade operations |
//+------------------------------------------------------------------+
bool CExpertTrade::SetOrderTypeTime(ENUM_ORDER_TYPE_TIME order_type_time)
{
if(m_symbol==NULL)
return(false);
//---
if(order_type_time==ORDER_TIME_SPECIFIED)
{
if((m_symbol.TradeTimeFlags()&SYMBOL_EXPIRATION_SPECIFIED)==0)
{
m_order_type_time =ORDER_TIME_GTC;
m_order_expiration=0;
return(false);
}
}
//---
m_order_type_time=order_type_time;
//--- succeed
return(true);
}
//+------------------------------------------------------------------+
//| Setting order expiration time for easy trade operations |
//+------------------------------------------------------------------+
bool CExpertTrade::SetOrderExpiration(datetime order_expiration)
{
if(m_symbol==NULL)
return(false);
//--- check expiration
if(order_expiration>=TimeCurrent()+60)
{
if(!SetOrderTypeTime(ORDER_TIME_SPECIFIED))
return(false);
m_order_expiration=order_expiration;
}
else
{
m_order_type_time=ORDER_TIME_GTC;
m_order_expiration=0;
}
//--- succeed
return(true);
}
//+------------------------------------------------------------------+
//| Easy LONG trade operation |
//+------------------------------------------------------------------+
bool CExpertTrade::Buy(double volume,double price,double sl,double tp,const string comment="")
{
double ask,stops_level;
//--- checking
if(m_symbol==NULL)
return(false);
string symbol=m_symbol.Name();
if(symbol=="")
return(false);
//---
ask=m_symbol.Ask();
stops_level=m_symbol.StopsLevel()*m_symbol.Point();
if(price!=0.0)
{
if(price>ask+stops_level)
{
//--- send "BUY_STOP" order
return(OrderOpen(symbol,ORDER_TYPE_BUY_STOP,volume,0.0,price,sl,tp,
m_order_type_time,m_order_expiration,comment));
}
if(price<ask-stops_level)
{
//--- send "BUY_LIMIT" order
return(OrderOpen(symbol,ORDER_TYPE_BUY_LIMIT,volume,0.0,price,sl,tp,
m_order_type_time,m_order_expiration,comment));
}
}
//---
return(PositionOpen(symbol,ORDER_TYPE_BUY,volume,ask,sl,tp,comment));
}
//+------------------------------------------------------------------+
//| Easy SHORT trade operation |
//+------------------------------------------------------------------+
bool CExpertTrade::Sell(double volume,double price,double sl,double tp,const string comment="")
{
double bid,stops_level;
//--- checking
if(m_symbol==NULL)
return(false);
string symbol=m_symbol.Name();
if(symbol=="")
return(false);
//---
bid=m_symbol.Bid();
stops_level=m_symbol.StopsLevel()*m_symbol.Point();
if(price!=0.0)
{
if(price>bid+stops_level)
{
//--- send "SELL_LIMIT" order
return(OrderOpen(symbol,ORDER_TYPE_SELL_LIMIT,volume,0.0,price,sl,tp,
m_order_type_time,m_order_expiration,comment));
}
if(price<bid-stops_level)
{
//--- send "SELL_STOP" order
return(OrderOpen(symbol,ORDER_TYPE_SELL_STOP,volume,0.0,price,sl,tp,
m_order_type_time,m_order_expiration,comment));
}
}
//---
return(PositionOpen(symbol,ORDER_TYPE_SELL,volume,bid,sl,tp,comment));
}
//+------------------------------------------------------------------+
+33
View File
@@ -0,0 +1,33 @@
//+------------------------------------------------------------------+
//| ExpertTrailing.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include "ExpertBase.mqh"
//+------------------------------------------------------------------+
//| Class CExpertTrailing. |
//| Purpose: Base class traling stops. |
//| Derives from class CExpertBase. |
//+------------------------------------------------------------------+
class CExpertTrailing : public CExpertBase
{
public:
CExpertTrailing(void);
~CExpertTrailing(void);
//---
virtual bool CheckTrailingStopLong(CPositionInfo *position,double &sl,double &tp) { return(false); }
virtual bool CheckTrailingStopShort(CPositionInfo *position,double &sl,double &tp) { return(false); }
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CExpertTrailing::CExpertTrailing(void)
{
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CExpertTrailing::~CExpertTrailing(void)
{
}
//+------------------------------------------------------------------+
+73
View File
@@ -0,0 +1,73 @@
//+------------------------------------------------------------------+
//| MoneyFixedLot.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Expert\ExpertMoney.mqh>
// wizard description start
//+------------------------------------------------------------------+
//| Description of the class |
//| Title=Trading with fixed trade volume |
//| Type=Money |
//| Name=FixLot |
//| Class=CMoneyFixedLot |
//| Page= |
//| Parameter=Percent,double,10.0,Percent |
//| Parameter=Lots,double,0.1,Fixed volume |
//+------------------------------------------------------------------+
// wizard description end
//+------------------------------------------------------------------+
//| Class CMoneyFixedLot. |
//| Purpose: Class of money management with fixed lot. |
//| Derives from class CExpertMoney. |
//+------------------------------------------------------------------+
class CMoneyFixedLot : public CExpertMoney
{
protected:
//--- input parameters
double m_lots;
public:
CMoneyFixedLot(void);
~CMoneyFixedLot(void);
//---
void Lots(double lots) { m_lots=lots; }
virtual bool ValidationSettings(void);
//---
virtual double CheckOpenLong(double price,double sl) { return(m_lots); }
virtual double CheckOpenShort(double price,double sl) { return(m_lots); }
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
void CMoneyFixedLot::CMoneyFixedLot(void) : m_lots(0.1)
{
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
void CMoneyFixedLot::~CMoneyFixedLot(void)
{
}
//+------------------------------------------------------------------+
//| Validation settings protected data. |
//+------------------------------------------------------------------+
bool CMoneyFixedLot::ValidationSettings(void)
{
if(!CExpertMoney::ValidationSettings())
return(false);
//--- initial data checks
if(m_lots<m_symbol.LotsMin() || m_lots>m_symbol.LotsMax())
{
printf(__FUNCTION__+": lots amount must be in the range from %f to %f",m_symbol.LotsMin(),m_symbol.LotsMax());
return(false);
}
if(MathAbs(m_lots/m_symbol.LotsStep()-MathRound(m_lots/m_symbol.LotsStep()))>1.0E-10)
{
printf(__FUNCTION__+": lots amount is not corresponding with lot step %f",m_symbol.LotsStep());
return(false);
}
//--- ok
return(true);
}
//+------------------------------------------------------------------+
+76
View File
@@ -0,0 +1,76 @@
//+------------------------------------------------------------------+
//| MoneyFixedMargin.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Expert\ExpertMoney.mqh>
// wizard description start
//+------------------------------------------------------------------+
//| Description of the class |
//| Title=Trading with fixed margin |
//| Type=Money |
//| Name=FixMargin |
//| Class=CMoneyFixedMargin |
//| Page= |
//| Parameter=Percent,double,10.0,Percentage of margin |
//+------------------------------------------------------------------+
// wizard description end
//+------------------------------------------------------------------+
//| Class CMoneyFixedMargin. |
//| Purpose: Class of money management with fixed percent margin. |
//| Derives from class CExpertMoney. |
//+------------------------------------------------------------------+
class CMoneyFixedMargin : public CExpertMoney
{
public:
CMoneyFixedMargin(void);
~CMoneyFixedMargin(void);
//---
virtual double CheckOpenLong(double price,double sl);
virtual double CheckOpenShort(double price,double sl);
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
void CMoneyFixedMargin::CMoneyFixedMargin(void)
{
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
void CMoneyFixedMargin::~CMoneyFixedMargin(void)
{
}
//+------------------------------------------------------------------+
//| Getting lot size for open long position. |
//+------------------------------------------------------------------+
double CMoneyFixedMargin::CheckOpenLong(double price,double sl)
{
if(m_symbol==NULL)
return(0.0);
//--- select lot size
double lot;
if(price==0.0)
lot=m_account.MaxLotCheck(m_symbol.Name(),ORDER_TYPE_BUY,m_symbol.Ask(),m_percent);
else
lot=m_account.MaxLotCheck(m_symbol.Name(),ORDER_TYPE_BUY,price,m_percent);
//--- return trading volume
return(lot);
}
//+------------------------------------------------------------------+
//| Getting lot size for open short position. |
//+------------------------------------------------------------------+
double CMoneyFixedMargin::CheckOpenShort(double price,double sl)
{
if(m_symbol==NULL)
return(0.0);
//--- select lot size
double lot;
if(price==0.0)
lot=m_account.MaxLotCheck(m_symbol.Name(),ORDER_TYPE_SELL,m_symbol.Bid(),m_percent);
else
lot=m_account.MaxLotCheck(m_symbol.Name(),ORDER_TYPE_SELL,price,m_percent);
//--- return trading volume
return(lot);
}
//+------------------------------------------------------------------+
+109
View File
@@ -0,0 +1,109 @@
//+------------------------------------------------------------------+
//| MoneyFixedRisk.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Expert\ExpertMoney.mqh>
// wizard description start
//+------------------------------------------------------------------+
//| Description of the class |
//| Title=Trading with fixed risk |
//| Type=Money |
//| Name=FixRisk |
//| Class=CMoneyFixedRisk |
//| Page= |
//| Parameter=Percent,double,10.0,Risk percentage |
//+------------------------------------------------------------------+
// wizard description end
//+------------------------------------------------------------------+
//| Class CMoneyFixedRisk. |
//| Purpose: Class of money management with fixed percent risk. |
//| Derives from class CExpertMoney. |
//+------------------------------------------------------------------+
class CMoneyFixedRisk : public CExpertMoney
{
public:
CMoneyFixedRisk(void);
~CMoneyFixedRisk(void);
//---
virtual double CheckOpenLong(double price,double sl);
virtual double CheckOpenShort(double price,double sl);
virtual double CheckClose(CPositionInfo *position) { return(0.0); }
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
void CMoneyFixedRisk::CMoneyFixedRisk(void)
{
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
void CMoneyFixedRisk::~CMoneyFixedRisk(void)
{
}
//+------------------------------------------------------------------+
//| Getting lot size for open long position. |
//+------------------------------------------------------------------+
double CMoneyFixedRisk::CheckOpenLong(double price,double sl)
{
if(m_symbol==NULL)
return(0.0);
//--- select lot size
double lot;
double minvol=m_symbol.LotsMin();
if(sl==0.0)
lot=minvol;
else
{
double loss;
if(price==0.0)
loss=-m_account.OrderProfitCheck(m_symbol.Name(),ORDER_TYPE_BUY,1.0,m_symbol.Ask(),sl);
else
loss=-m_account.OrderProfitCheck(m_symbol.Name(),ORDER_TYPE_BUY,1.0,price,sl);
double stepvol=m_symbol.LotsStep();
lot=MathFloor(m_account.Balance()*m_percent/loss/100.0/stepvol)*stepvol;
}
//---
if(lot<minvol)
lot=minvol;
//---
double maxvol=m_symbol.LotsMax();
if(lot>maxvol)
lot=maxvol;
//--- return trading volume
return(lot);
}
//+------------------------------------------------------------------+
//| Getting lot size for open short position. |
//+------------------------------------------------------------------+
double CMoneyFixedRisk::CheckOpenShort(double price,double sl)
{
if(m_symbol==NULL)
return(0.0);
//--- select lot size
double lot;
double minvol=m_symbol.LotsMin();
if(sl==0.0)
lot=minvol;
else
{
double loss;
if(price==0.0)
loss=-m_account.OrderProfitCheck(m_symbol.Name(),ORDER_TYPE_SELL,1.0,m_symbol.Bid(),sl);
else
loss=-m_account.OrderProfitCheck(m_symbol.Name(),ORDER_TYPE_SELL,1.0,price,sl);
double stepvol=m_symbol.LotsStep();
lot=MathFloor(m_account.Balance()*m_percent/loss/100.0/stepvol)*stepvol;
}
//---
if(lot<minvol)
lot=minvol;
//---
double maxvol=m_symbol.LotsMax();
if(lot>maxvol)
lot=maxvol;
//--- return trading volume
return(lot);
}
//+------------------------------------------------------------------+
+71
View File
@@ -0,0 +1,71 @@
//+------------------------------------------------------------------+
//| MoneyNone.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Expert\ExpertMoney.mqh>
// wizard description start
//+------------------------------------------------------------------+
//| Description of the class |
//| Title=Trading with minimal allowed trade volume |
//| Type=Money |
//| Name=MinLot |
//| Class=CMoneyNone |
//| Page= |
//+------------------------------------------------------------------+
// wizard description end
//+------------------------------------------------------------------+
//| Class CMoneyNone. |
//| Appointment: Class no money managment. |
//| Derives from class CExpertMoney. |
//+------------------------------------------------------------------+
class CMoneyNone : public CExpertMoney
{
public:
CMoneyNone(void);
~CMoneyNone(void);
//---
virtual bool ValidationSettings(void);
//---
virtual double CheckOpenLong(double price,double sl);
virtual double CheckOpenShort(double price,double sl);
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
void CMoneyNone::CMoneyNone(void)
{
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
void CMoneyNone::~CMoneyNone(void)
{
}
//+------------------------------------------------------------------+
//| Validation settings protected data. |
//+------------------------------------------------------------------+
bool CMoneyNone::ValidationSettings(void)
{
Percent(100.0);
//--- initial data checks
if(!CExpertMoney::ValidationSettings())
return(false);
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Getting lot size for open long position. |
//+------------------------------------------------------------------+
double CMoneyNone::CheckOpenLong(double price,double sl)
{
return(m_symbol.LotsMin());
}
//+------------------------------------------------------------------+
//| Getting lot size for open short position. |
//+------------------------------------------------------------------+
double CMoneyNone::CheckOpenShort(double price,double sl)
{
return(m_symbol.LotsMin());
}
//+------------------------------------------------------------------+
+155
View File
@@ -0,0 +1,155 @@
//+------------------------------------------------------------------+
//| MoneySizeOptimized.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Expert\ExpertMoney.mqh>
#include <Trade\DealInfo.mqh>
// wizard description start
//+------------------------------------------------------------------+
//| Description of the class |
//| Title=Trading with optimized trade volume |
//| Type=Money |
//| Name=SizeOptimized |
//| Class=CMoneySizeOptimized |
//| Page= |
//| Parameter=DecreaseFactor,double,3.0,Decrease factor |
//| Parameter=Percent,double,10.0,Percent |
//+------------------------------------------------------------------+
// wizard description end
//+------------------------------------------------------------------+
//| Class CMoneySizeOptimized. |
//| Purpose: Class of money management with size optimized. |
//| Derives from class CExpertMoney. |
//+------------------------------------------------------------------+
class CMoneySizeOptimized : public CExpertMoney
{
protected:
double m_decrease_factor;
public:
CMoneySizeOptimized(void);
~CMoneySizeOptimized(void);
//---
void DecreaseFactor(double decrease_factor) { m_decrease_factor=decrease_factor; }
virtual bool ValidationSettings(void);
//---
virtual double CheckOpenLong(double price,double sl);
virtual double CheckOpenShort(double price,double sl);
protected:
double Optimize(double lots);
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
void CMoneySizeOptimized::CMoneySizeOptimized(void) : m_decrease_factor(3.0)
{
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
void CMoneySizeOptimized::~CMoneySizeOptimized(void)
{
}
//+------------------------------------------------------------------+
//| Validation settings protected data. |
//+------------------------------------------------------------------+
bool CMoneySizeOptimized::ValidationSettings(void)
{
if(!CExpertMoney::ValidationSettings())
return(false);
//--- initial data checks
if(m_decrease_factor<=0.0)
{
printf(__FUNCTION__+": decrease factor must be greater then 0");
return(false);
}
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Getting lot size for open long position. |
//+------------------------------------------------------------------+
double CMoneySizeOptimized::CheckOpenLong(double price,double sl)
{
if(m_symbol==NULL)
return(0.0);
//--- select lot size
double lot;
if(price==0.0)
lot=m_account.MaxLotCheck(m_symbol.Name(),ORDER_TYPE_BUY,m_symbol.Ask(),m_percent);
else
lot=m_account.MaxLotCheck(m_symbol.Name(),ORDER_TYPE_BUY,price,m_percent);
//--- return trading volume
return(Optimize(lot));
}
//+------------------------------------------------------------------+
//| Getting lot size for open short position. |
//+------------------------------------------------------------------+
double CMoneySizeOptimized::CheckOpenShort(double price,double sl)
{
if(m_symbol==NULL)
return(0.0);
//--- select lot size
double lot;
if(price==0.0)
lot=m_account.MaxLotCheck(m_symbol.Name(),ORDER_TYPE_SELL,m_symbol.Bid(),m_percent);
else
lot=m_account.MaxLotCheck(m_symbol.Name(),ORDER_TYPE_SELL,price,m_percent);
//--- return trading volume
return(Optimize(lot));
}
//+------------------------------------------------------------------+
//| Optimizing lot size for open. |
//+------------------------------------------------------------------+
double CMoneySizeOptimized::Optimize(double lots)
{
double lot=lots;
//--- calculate number of losses orders without a break
if(m_decrease_factor>0)
{
//--- select history for access
HistorySelect(0,TimeCurrent());
//---
int orders=HistoryDealsTotal(); // total history deals
int losses=0; // number of consequent losing orders
CDealInfo deal;
//---
for(int i=orders-1;i>=0;i--)
{
deal.Ticket(HistoryDealGetTicket(i));
if(deal.Ticket()==0)
{
Print("CMoneySizeOptimized::Optimize: HistoryDealGetTicket failed, no trade history");
break;
}
//--- check symbol
if(deal.Symbol()!=m_symbol.Name())
continue;
//--- check profit
double profit=deal.Profit();
if(profit>0.0)
break;
if(profit<0.0)
losses++;
}
//---
if(losses>1)
lot=NormalizeDouble(lot-lot*losses/m_decrease_factor,2);
}
//--- normalize and check limits
double stepvol=m_symbol.LotsStep();
lot=stepvol*NormalizeDouble(lot/stepvol,0);
//---
double minvol=m_symbol.LotsMin();
if(lot<minvol)
lot=minvol;
//---
double maxvol=m_symbol.LotsMax();
if(lot>maxvol)
lot=maxvol;
//---
return(lot);
}
//+------------------------------------------------------------------+
+173
View File
@@ -0,0 +1,173 @@
//+------------------------------------------------------------------+
//| SignalAC.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Expert\ExpertSignal.mqh>
// wizard description start
//+------------------------------------------------------------------+
//| Description of the class |
//| Title=Signals of indicator 'Accelerator Oscillator' |
//| Type=SignalAdvanced |
//| Name=Accelerator Oscillator |
//| ShortName=AC |
//| Class=CSignalAC |
//| Page=signal_ac |
//+------------------------------------------------------------------+
// wizard description end
//+------------------------------------------------------------------+
//| Class CSignalAC. |
//| Purpose: Class of generator of trade signals based on |
//| the 'Accelerator Oscillator' indicator. |
//| Is derived from the CExpertSignal class. |
//+------------------------------------------------------------------+
class CSignalAC : public CExpertSignal
{
protected:
CiAC m_ac; // object-indicator
//--- "weights" of market models (0-100)
int m_pattern_0; // model 0 "first analyzed bar has required color"
int m_pattern_1; // model 1 "there is a condition for entering the market"
int m_pattern_2; // model 2 "condition for entering the market has just appeared"
public:
CSignalAC(void);
~CSignalAC(void);
//--- methods of adjusting "weights" of market models
void Pattern_0(int value) { m_pattern_0=value; }
void Pattern_1(int value) { m_pattern_1=value; }
void Pattern_2(int value) { m_pattern_2=value; }
//--- method of creating the indicator and timeseries
virtual bool InitIndicators(CIndicators *indicators);
//--- methods of checking if the market models are formed
virtual int LongCondition(void);
virtual int ShortCondition(void);
protected:
//--- method of initialization of the indicator
bool InitAC(CIndicators *indicators);
//--- methods of getting data
double AC(int ind) { return(m_ac.Main(ind)); }
double DiffAC(int ind) { return(AC(ind)-AC(ind+1)); }
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CSignalAC::CSignalAC(void) : m_pattern_0(90),
m_pattern_1(50),
m_pattern_2(30)
{
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CSignalAC::~CSignalAC(void)
{
}
//+------------------------------------------------------------------+
//| Create indicators. |
//+------------------------------------------------------------------+
bool CSignalAC::InitIndicators(CIndicators *indicators)
{
//--- check pointer
if(indicators==NULL)
return(false);
//--- initialization of indicators and timeseries of additional filters
if(!CExpertSignal::InitIndicators(indicators))
return(false);
//--- create and initialize AC indicator
if(!InitAC(indicators))
return(false);
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Initialize AC indicators. |
//+------------------------------------------------------------------+
bool CSignalAC::InitAC(CIndicators *indicators)
{
//--- check pointer
if(indicators==NULL)
return(false);
//--- add object to collection
if(!indicators.Add(GetPointer(m_ac)))
{
printf(__FUNCTION__+": error adding object");
return(false);
}
//--- initialize object
if(!m_ac.Create(m_symbol.Name(),m_period))
{
printf(__FUNCTION__+": error initializing object");
return(false);
}
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| "Voting" that price will grow. |
//+------------------------------------------------------------------+
int CSignalAC::LongCondition(void)
{
int result=0;
int idx =StartIndex();
//--- if the first analyzed bar is "red", don't "vote" for buying
if(DiffAC(idx++)<0.0)
return(result);
//--- first analyzed bar is "green" (the indicator has no objections to buying)
if(IS_PATTERN_USAGE(0))
result=m_pattern_0;
//--- if the second analyzed bar is "red", there is no condition for buying
if(DiffAC(idx)<0.0)
return(result);
//--- second analyzed bar is "green" (the condition for buying may be fulfilled)
//--- if the second analyzed bar is less than zero, we need to analyzed the third bar
if(AC(idx++)<0.0)
{
//--- if the third analyzed bar is "red", there is no condition for buying
if(DiffAC(idx++)<0.0)
return(result);
}
//--- there is a condition for buying
if(IS_PATTERN_USAGE(1))
result=m_pattern_1;
//--- if the previously analyzed bar is "red", the condition for buying has just been fulfilled
if(IS_PATTERN_USAGE(2) && DiffAC(idx)<0.0)
result=m_pattern_2;
//--- return the result
return(result);
}
//+------------------------------------------------------------------+
//| "Voting" that price will fall. |
//+------------------------------------------------------------------+
int CSignalAC::ShortCondition(void)
{
int result=0;
int idx =StartIndex();
//--- if the first analyzed bar is "green", don't "vote" for selling
if(DiffAC(idx++)>0.0)
return(result);
//--- first analyzed bar is "red" (the indicator has no objections to selling)
if(IS_PATTERN_USAGE(0))
result=m_pattern_0;
//--- if the second analyzed bar is "green", there is no condition for selling
if(DiffAC(idx)>0.0)
return(result);
//--- second analyzed bar is "red" (the condition for selling may be fulfilled)
//--- if the second analyzed bar is greater than zero, we need to analyze the third bar
if(AC(idx++)>0.0)
{
//--- if the third analyzed bar is "green", there is no condition for selling
if(DiffAC(idx++)>0.0)
return(result);
}
//--- there us a condition for selling
if(IS_PATTERN_USAGE(1))
result=m_pattern_1;
//--- if the previously analyzed bar is "green", the condition for selling has just been fulfilled
if(IS_PATTERN_USAGE(2) && DiffAC(idx)>0.0)
result=m_pattern_2;
//--- return the result
return(result);
}
//+------------------------------------------------------------------+
+265
View File
@@ -0,0 +1,265 @@
//+------------------------------------------------------------------+
//| SignalAMA.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Expert\ExpertSignal.mqh>
// wizard description start
//+------------------------------------------------------------------+
//| Description of the class |
//| Title=Signals of indicator 'Adaptive Moving Average' |
//| Type=SignalAdvanced |
//| Name=Adaptive Moving Average |
//| ShortName=AMA |
//| Class=CSignalAMA |
//| Page=signal_ama |
//| Parameter=PeriodMA,int,10,Period of averaging |
//| Parameter=PeriodFast,int,2,Period of fast EMA |
//| Parameter=PeriodSlow,int,30,Period of slow EMA |
//| Parameter=Shift,int,0,Time shift |
//| Parameter=Applied,ENUM_APPLIED_PRICE,PRICE_CLOSE,Prices series |
//+------------------------------------------------------------------+
// wizard description end
//+------------------------------------------------------------------+
//| Class CSignalAMA. |
//| Purpose: Class of generator of trade signals based on |
//| the 'Adaptive Moving Average' indicator. |
//| Is derived from the CExpertSignal class. |
//+------------------------------------------------------------------+
class CSignalAMA : public CExpertSignal
{
protected:
CiAMA m_ma; // object-indicator
//--- adjusted parameters
int m_ma_period; // the "period of averaging" parameter of the indicator
int m_period_fast; // the "period of fast EMA" parameter of the indicator
int m_period_slow; // the "period of slow EMA" parameter of the indicator
int m_ma_shift; // the "time shift" parameter of the indicator
ENUM_APPLIED_PRICE m_ma_applied; // the "object of averaging" parameter" of the indicator
//--- "weights" of market models (0-100)
int m_pattern_0; // model 0 "price is on the necessary side from the indicator"
int m_pattern_1; // model 1 "price crossed the indicator with opposite direction"
int m_pattern_2; // model 2 "price crossed the indicator with the same direction"
int m_pattern_3; // model 3 "piercing"
public:
CSignalAMA(void);
~CSignalAMA(void);
//--- methods of setting adjustable parameters
void PeriodMA(int value) { m_ma_period=value; }
void PeriodFast(int value) { m_period_fast=value; }
void PeriodSlow(int value) { m_period_slow=value; }
void Shift(int value) { m_ma_shift=value; }
void Applied(ENUM_APPLIED_PRICE value) { m_ma_applied=value; }
//--- methods of adjusting "weights" of market models
void Pattern_0(int value) { m_pattern_0=value; }
void Pattern_1(int value) { m_pattern_1=value; }
void Pattern_2(int value) { m_pattern_2=value; }
void Pattern_3(int value) { m_pattern_3=value; }
//--- method of verification of settings
virtual bool ValidationSettings(void);
//--- method of creating the indicator and timeseries
virtual bool InitIndicators(CIndicators *indicators);
//--- methods of checking if the market models are formed
virtual int LongCondition(void);
virtual int ShortCondition(void);
protected:
//--- method of initialization of the indicator
bool InitMA(CIndicators *indicators);
//--- methods of getting data
double MA(int ind) { return(m_ma.Main(ind)); }
double DiffMA(int ind) { return(MA(ind)-MA(ind+1)); }
double DiffOpenMA(int ind) { return(Open(ind)-MA(ind)); }
double DiffHighMA(int ind) { return(High(ind)-MA(ind)); }
double DiffLowMA(int ind) { return(Low(ind)-MA(ind)); }
double DiffCloseMA(int ind) { return(Close(ind)-MA(ind)); }
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CSignalAMA::CSignalAMA(void) : m_ma_period(10),
m_ma_shift(0),
m_period_fast(2),
m_period_slow(30),
m_ma_applied(PRICE_CLOSE),
m_pattern_0(10),
m_pattern_1(70),
m_pattern_2(100),
m_pattern_3(60)
{
//--- initialization of protected data
m_used_series=USE_SERIES_OPEN+USE_SERIES_HIGH+USE_SERIES_LOW+USE_SERIES_CLOSE;
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CSignalAMA::~CSignalAMA(void)
{
}
//+------------------------------------------------------------------+
//| Validation settings protected data. |
//+------------------------------------------------------------------+
bool CSignalAMA::ValidationSettings(void)
{
//--- call of the method of the parent class
if(!CExpertSignal::ValidationSettings())
return(false);
//--- initial data checks
if(m_ma_period<=0)
{
printf(__FUNCTION__+": period MA must be greater than 0");
return(false);
}
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Create indicators. |
//+------------------------------------------------------------------+
bool CSignalAMA::InitIndicators(CIndicators *indicators)
{
//--- check pointer
if(indicators==NULL)
return(false);
//--- initialization of indicators and timeseries of additional filters
if(!CExpertSignal::InitIndicators(indicators))
return(false);
//--- create and initialize AMA indicator
if(!InitMA(indicators))
return(false);
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Create MA indicators. |
//+------------------------------------------------------------------+
bool CSignalAMA::InitMA(CIndicators *indicators)
{
//--- check pointer
if(indicators==NULL)
return(false);
//--- add object to collection
if(!indicators.Add(GetPointer(m_ma)))
{
printf(__FUNCTION__+": error adding object");
return(false);
}
//--- initialize object
if(!m_ma.Create(m_symbol.Name(),m_period,m_ma_period,m_period_fast,m_period_slow,m_ma_shift,m_ma_applied))
{
printf(__FUNCTION__+": error initializing object");
return(false);
}
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| "Voting" that price will grow. |
//+------------------------------------------------------------------+
int CSignalAMA::LongCondition(void)
{
int result=0;
int idx =StartIndex();
//--- analyze positional relationship of the close price and the indicator at the first analyzed bar
if(DiffCloseMA(idx)<0.0)
{
//--- the close price is below the indicator
if(IS_PATTERN_USAGE(1) && DiffOpenMA(idx)>0.0 && DiffMA(idx)>0.0)
{
//--- the open price is above the indicator (i.e. there was an intersection), but the indicator is directed upwards
result=m_pattern_1;
//--- consider that this is an unformed "piercing" and suggest to enter the market at the current price
m_base_price=0.0;
}
}
else
{
//--- the close price is above the indicator (the indicator has no objections to buying)
if(IS_PATTERN_USAGE(0))
result=m_pattern_0;
//--- if the indicator is directed upwards
if(DiffMA(idx)>0.0)
{
if(DiffOpenMA(idx)<0.0)
{
//--- if the model 2 is used
if(IS_PATTERN_USAGE(2))
{
//--- the open price is below the indicator (i.e. there was an intersection)
result=m_pattern_2;
//--- suggest to enter the market at the "roll back"
m_base_price=m_symbol.NormalizePrice(MA(idx));
}
}
else
{
//--- if the model 3 is used and the open price is above the indicator
if(IS_PATTERN_USAGE(3) && DiffLowMA(idx)<0.0)
{
//--- the low price is below the indicator
result=m_pattern_3;
//--- consider that this is a formed "piercing" and suggest to enter the market at the current price
m_base_price=0.0;
}
}
}
}
//--- return the result
return(result);
}
//+------------------------------------------------------------------+
//| "Voting" that price will fall. |
//+------------------------------------------------------------------+
int CSignalAMA::ShortCondition(void)
{
int result=0;
int idx =StartIndex();
//--- analyze positional relationship of the close price and the indicator at the first analyzed bar
if(DiffCloseMA(idx)>0.0)
{
//--- the close price is above the indicator
if(IS_PATTERN_USAGE(1) && DiffOpenMA(idx)<0.0 && DiffMA(idx)<0.0)
{
//--- the open price is below the indicator (i.e. there was an intersection), but the indicator is directed downwards
result=m_pattern_1;
//--- consider that this is an unformed "piercing" and suggest to enter the market at the current price
m_base_price=0.0;
}
}
else
{
//--- the close price is below the indicator (the indicator has no objections to buying)
if(IS_PATTERN_USAGE(0))
result=m_pattern_0;
//--- the indicator is directed downwards
if(DiffMA(idx)<0.0)
{
if(DiffOpenMA(idx)>0.0)
{
//--- if the model 2 is used
if(IS_PATTERN_USAGE(2))
{
//--- the open price is above the indicator (i.e. there was an intersection)
result=m_pattern_2;
//--- suggest to enter the market at the "roll back"
m_base_price=m_symbol.NormalizePrice(MA(idx));
}
}
else
{
//--- if the model 3 is used and the open price is below the indicator
if(IS_PATTERN_USAGE(3) && DiffHighMA(idx)>0.0)
{
//--- the high price is above the indicator
result=m_pattern_3;
//--- consider that this is a formed "piercing" and suggest to enter the market at the current price
m_base_price=0.0;
}
}
}
}
//--- return the result
return(result);
}
//+------------------------------------------------------------------+
+339
View File
@@ -0,0 +1,339 @@
//+------------------------------------------------------------------+
//| SignalAO.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Expert\ExpertSignal.mqh>
// wizard description start
//+------------------------------------------------------------------+
//| Description of the class |
//| Title=Signals of indicator 'Awesome Oscillator' |
//| Type=SignalAdvanced |
//| Name=Awesome Oscillator |
//| ShortName=AO |
//| Class=CSignalAO |
//| Page=signal_ao |
//+------------------------------------------------------------------+
// wizard description end
//+------------------------------------------------------------------+
//| Class CSignalAO. |
//| Purpose: Class of generator of trade signals based on |
//| the 'Awesome Oscillator' indicator. |
//| Is derived from the CExpertSignal class. |
//+------------------------------------------------------------------+
class CSignalAO : public CExpertSignal
{
protected:
CiAO m_ao; // object-indicator
//--- "weights" of market models (0-100)
int m_pattern_0; // model 0 "first analyzed bar has required color"
int m_pattern_1; // model 1 "the 'saucer' signal"
int m_pattern_2; // model 2 "the 'crossing of the zero line' signal"
int m_pattern_3; // model 2 "the 'divergence' signal"
//--- variables
double m_extr_osc[10]; // array of values of extremums of the oscillator
double m_extr_pr[10]; // array of values of the corresponding extremums of price
int m_extr_pos[10]; // array of shifts of extremums (in bars)
uint m_extr_map; // resulting bit-map of ratio of extremums of the oscillator and the price
public:
CSignalAO(void);
~CSignalAO(void);
//--- methods of adjusting "weights" of market models
void Pattern_0(int value) { m_pattern_0=value; }
void Pattern_1(int value) { m_pattern_1=value; }
void Pattern_2(int value) { m_pattern_2=value; }
void Pattern_3(int value) { m_pattern_3=value; }
//--- method of creating the indicator and timeseries
virtual bool InitIndicators(CIndicators *indicators);
//--- methods of checking if the market models are formed
virtual int LongCondition(void);
virtual int ShortCondition(void);
protected:
//--- method of initialization of the indicator
bool InitAO(CIndicators *indicators);
//--- methods of getting data
double AO(int ind) { return(m_ao.Main(ind)); }
double DiffAO(int ind) { return(AO(ind)-AO(ind+1)); }
int StateAO(int ind);
bool ExtStateAO(int ind);
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CSignalAO::CSignalAO(void) : m_pattern_0(30),
m_pattern_1(20),
m_pattern_2(70),
m_pattern_3(90)
{
//--- initialization of protected data
m_used_series=USE_SERIES_HIGH+USE_SERIES_LOW;
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CSignalAO::~CSignalAO(void)
{
}
//+------------------------------------------------------------------+
//| Create indicators. |
//+------------------------------------------------------------------+
bool CSignalAO::InitIndicators(CIndicators *indicators)
{
//--- check pointer
if(indicators==NULL)
return(false);
//--- initialization of indicators and timeseries of additional filters
if(!CExpertSignal::InitIndicators(indicators))
return(false);
//--- create and initialize AO indicator
if(!InitAO(indicators))
return(false);
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Initialize AO indicators. |
//+------------------------------------------------------------------+
bool CSignalAO::InitAO(CIndicators *indicators)
{
//--- check pointer
if(indicators==NULL)
return(false);
//--- add object to collection
if(!indicators.Add(GetPointer(m_ao)))
{
printf(__FUNCTION__+": error adding object");
return(false);
}
//--- initialize object
if(!m_ao.Create(m_symbol.Name(),m_period))
{
printf(__FUNCTION__+": error initializing object");
return(false);
}
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Check of the indicator state. |
//+------------------------------------------------------------------+
int CSignalAO::StateAO(int ind)
{
int res=0;
double var;
//---
for(int i=ind;;i++)
{
if(AO(i+1)==EMPTY_VALUE)
break;
var=DiffAO(i);
if(res>0)
{
if(var<0)
break;
res++;
continue;
}
if(res<0)
{
if(var>0)
break;
res--;
continue;
}
if(var>0)
res++;
if(var<0)
res--;
}
//---
return(res);
}
//+------------------------------------------------------------------+
//| Extended check of the oscillator state consists |
//| in forming a bit-map according to certain rules, |
//| which shows ratios of extremums of the oscillator and price. |
//+------------------------------------------------------------------+
bool CSignalAO::ExtStateAO(int ind)
{
//--- operation of this method results in a bit-map of extremums
//--- practically, the bit-map of extremums is an "array" of 4-bit fields
//--- each "element of the array" definitely describes the ratio
//--- of current extremums of the oscillator and the price with previous ones
//--- purpose of bits of an element of the analyzed bit-map
//--- bit 3 - not used (always 0)
//--- bit 2 - is equal to 1 if the current extremum of the oscillator is "more extreme" than the previous one
//--- (a higher peak or a deeper valley), otherwise - 0
//--- bit 1 - not used (always 0)
//--- bit 0 - is equal to 1 if the current extremum of price is "more extreme" than the previous one
//--- (a higher peak or a deeper valley), otherwise - 0
//--- in addition to them, the following is formed:
//--- array of values of extremums of the oscillator,
//--- array of values of price extremums and
//--- array of "distances" between extremums of the oscillator (in bars)
//--- it should be noted that when using the results of the extended check of state,
//--- you should consider, which extremum of the oscillator (peak or valley)
//--- is the "reference point" (i.e. was detected first during the analysis)
//--- if a peak is detected first then even elements of all arrays
//--- will contain information about peaks, and odd elements will contain information about valleys
//--- if a valley is detected first, then respectively in reverse
int pos=ind,off,index;
uint map; // intermediate bit-map for one extremum
//---
m_extr_map=0;
for(int i=0;i<10;i++)
{
off=StateAO(pos);
if(off>0)
{
//--- minimum of the oscillator is detected
pos+=off;
m_extr_pos[i]=pos;
m_extr_osc[i]=AO(pos);
if(i>1)
{
m_extr_pr[i]=m_low.MinValue(pos-2,5,index);
//--- form the intermediate bit-map
map=0;
if(m_extr_pr[i-2]<m_extr_pr[i])
map+=1; // set bit 0
if(m_extr_osc[i-2]<m_extr_osc[i])
map+=4; // set bit 2
//--- add the result
m_extr_map+=map<<(4*(i-2));
}
else
m_extr_pr[i]=m_low.MinValue(pos-1,4,index);
}
else
{
//--- maximum of the oscillator is detected
pos-=off;
m_extr_pos[i]=pos;
m_extr_osc[i]=AO(pos);
if(i>1)
{
m_extr_pr[i]=m_high.MaxValue(pos-2,5,index);
//--- form the intermediate bit-map
map=0;
if(m_extr_pr[i-2]>m_extr_pr[i])
map+=1; // set bit 0
if(m_extr_osc[i-2]>m_extr_osc[i])
map+=4; // set bit 2
//--- add the result
m_extr_map+=map<<(4*(i-2));
}
else
m_extr_pr[i]=m_high.MaxValue(pos-1,4,index);
}
}
//---
return(true);
}
//+------------------------------------------------------------------+
//| "Voting" that price will grow. |
//+------------------------------------------------------------------+
int CSignalAO::LongCondition(void)
{
int result=0;
int idx =StartIndex();
//--- if the first analyzed bar is "red", don't "vote" for buying
if(DiffAO(idx)<0.0)
return(result);
//--- first analyzed bar is "green" (the indicator has no objections to buying)
if(IS_PATTERN_USAGE(0))
result=m_pattern_0;
if(AO(idx++)>0.0)
{
//--- first analyzed bar is greater than zero, search for the "saucer" and "crosing of the zero line" signals
if(IS_PATTERN_USAGE(1) && DiffAO(idx)<0.0)
{
//--- the "saucer" signal
//--- there is a condition for buying
return(m_pattern_1);
}
if(IS_PATTERN_USAGE(2) && AO(idx)<0.0)
{
//--- the "crossing of the zero line" signal
//--- there is a condition for buying
return(m_pattern_2);
}
}
else
{
//--- first analyzed bar is less than zero, search for the "divergence" signal
//--- if the second analyzed bar is "red", the condition for buying may be fulfilled
if(IS_PATTERN_USAGE(3) && DiffAO(idx)<0.0)
{
idx=StartIndex();
//--- search for the "divergence" signal
ExtStateAO(idx);
if((m_extr_map&0xF)==1)
{
if(m_extr_osc[0]<0.0 && m_extr_osc[1]<0.0 && m_extr_osc[2]<0.0)
{
//--- both valleys are below zero, the peak is between them and it hasn't raised above zero
//--- we suppose that this is "divergence"
return(m_pattern_3);
}
}
}
}
//--- return the result
return(result);
}
//+------------------------------------------------------------------+
//| "Voting" that price will fall. |
//+------------------------------------------------------------------+
int CSignalAO::ShortCondition(void)
{
int result=0;
int idx =StartIndex();
//--- if the first analyzed bar is "green", don't "vote" for selling
if(DiffAO(idx)>0.0)
return(result);
//--- first analyzed bar is "red" (the indicator has no objections to selling)
if(IS_PATTERN_USAGE(0))
result=m_pattern_0;
if(AO(idx++)<0.0)
{
//--- first analyzed bar is below zero, search for the "saucer" and "crossing of the zero line" signals
if(IS_PATTERN_USAGE(1) && DiffAO(idx)>0.0)
{
//--- the "saucer" signal
//--- there is a condition for buying
return(m_pattern_1);
}
if(IS_PATTERN_USAGE(2) && AO(idx)>0.0)
{
//--- the "crossing of the zero line" signal
//--- there is a condition for buying
return(m_pattern_2);
}
}
else
{
//--- first analyzed bar is above zero, search for the "divergence" signal
//--- if the second analyzed bar is "green", the condition for buying may be fulfilled
if(IS_PATTERN_USAGE(3) && DiffAO(idx)>0.0)
{
idx=StartIndex();
//--- search for the "divergence" signal
ExtStateAO(idx);
if((m_extr_map&0xF)==1)
{
if(m_extr_osc[0]>0.0 && m_extr_osc[1]>0.0 && m_extr_osc[2]>0.0)
{
//--- both peaks are above zero and the valley between them hasn't fallen below zero
//--- we suppose that this is "divergence"
return(m_pattern_3);
}
}
}
}
//--- return the result
return(result);
}
//+------------------------------------------------------------------+
+289
View File
@@ -0,0 +1,289 @@
//+------------------------------------------------------------------+
//| SignalBearsPower.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Expert\ExpertSignal.mqh>
// wizard description start
//+------------------------------------------------------------------+
//| Description of the class |
//| Title=Signals of oscillator 'Bears Power' |
//| Type=SignalAdvanced |
//| Name=Bears Power |
//| ShortName=BearsPower |
//| Class=CSignalBearsPower |
//| Page=signal_bears |
//| Parameter=PeriodBears,int,13,Period of calculation |
//+------------------------------------------------------------------+
// wizard description end
//+------------------------------------------------------------------+
//| Class CSignalBearsPower. |
//| Purpose: Class of generator of trade signals based on |
//| the 'Bears Power' oscillator. |
//| Is derived from the CExpertSignal class. |
//+------------------------------------------------------------------+
class CSignalBearsPower : public CExpertSignal
{
protected:
CiBearsPower m_bears; // object-oscillator
//--- adjusted parameters
int m_period_bears; // the "period of calculation" parameter of the oscillator
//--- "weights" of market models (0-100)
int m_pattern_0; // model 0 "reverse of the oscillator to required direction"
int m_pattern_1; // model 1 "divergence of the oscillator and price"
//--- variables
double m_extr_osc[10]; // array of values of extremums of the oscillator
double m_extr_pr[10]; // array of values of the corresponding extremums of price
int m_extr_pos[10]; // array of shifts of extremums (in bars)
uint m_extr_map; // resulting bit-map of ratio of extremums of the oscillator and the price
public:
CSignalBearsPower(void);
~CSignalBearsPower(void);
//--- methods of setting adjustable parameters
void PeriodBears(int value) { m_period_bears=value; }
//--- methods of adjusting "weights" of market models
void Pattern_0(int value) { m_pattern_0=value; }
void Pattern_1(int value) { m_pattern_1=value; }
//--- method of verification of settings
virtual bool ValidationSettings(void);
//--- method of creating the indicator and timeseries
virtual bool InitIndicators(CIndicators *indicators);
//--- methods of checking if the market models are formed
virtual int LongCondition(void);
//--- the oscillator doesn't identify conditions for selling
protected:
//--- method of initialization of the oscillator
bool InitBears(CIndicators *indicators);
//--- methods of getting data
double Bears(int ind) { return(m_bears.Main(ind)); }
double DiffBears(int ind) { return(Bears(ind)-Bears(ind+1)); }
int StateBears(int ind);
bool ExtStateBears(int ind);
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CSignalBearsPower::CSignalBearsPower(void) : m_period_bears(13),
m_pattern_0(20),
m_pattern_1(80)
{
//--- initialization of protected data
m_used_series=USE_SERIES_HIGH+USE_SERIES_LOW;
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CSignalBearsPower::~CSignalBearsPower(void)
{
}
//+------------------------------------------------------------------+
//| Validation settings protected data. |
//+------------------------------------------------------------------+
bool CSignalBearsPower::ValidationSettings(void)
{
//--- validation settings of additional filters
if(!CExpertSignal::ValidationSettings())
return(false);
//--- initial data checks
if(m_period_bears<=0)
{
printf(__FUNCTION__+": period Bears must be greater than 0");
return(false);
}
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Create indicators. |
//+------------------------------------------------------------------+
bool CSignalBearsPower::InitIndicators(CIndicators *indicators)
{
//--- check pointer
if(indicators==NULL)
return(false);
//--- initialization of indicators and timeseries of additional filters
if(!CExpertSignal::InitIndicators(indicators))
return(false);
//--- create and initialize BearsPower oscillator
if(!InitBears(indicators))
return(false);
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Initialize BearsPower oscillators. |
//+------------------------------------------------------------------+
bool CSignalBearsPower::InitBears(CIndicators *indicators)
{
//--- check pointer
if(indicators==NULL)
return(false);
//--- add object to collection
if(!indicators.Add(GetPointer(m_bears)))
{
printf(__FUNCTION__+": error adding object");
return(false);
}
//--- initialize object
if(!m_bears.Create(m_symbol.Name(),m_period,m_period_bears))
{
printf(__FUNCTION__+": error initializing object");
return(false);
}
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Check of the oscillator state. |
//+------------------------------------------------------------------+
int CSignalBearsPower::StateBears(int ind)
{
int res=0;
double var;
//---
for(int i=ind;;i++)
{
if(Bears(i+1)==EMPTY_VALUE)
break;
var=DiffBears(i);
if(res>0)
{
if(var<0)
break;
res++;
continue;
}
if(res<0)
{
if(var>0)
break;
res--;
continue;
}
if(var>0)
res++;
if(var<0)
res--;
}
//--- return the result
return(res);
}
//+------------------------------------------------------------------+
//| Extended check of the oscillator state consists |
//| in forming a bit-map according to certain rules, |
//| which shows ratios of extremums of the oscillator and price. |
//+------------------------------------------------------------------+
bool CSignalBearsPower::ExtStateBears(int ind)
{
//--- operation of this method results in a bit-map of extremums
//--- practically, the bit-map of extremums is an "array" of 4-bit fields
//--- each "element of the array" definitely describes the ratio
//--- of current extremums of the oscillator and the price with previous ones
//--- purpose of bits of an element of the analyzed bit-map
//--- bit 3 - not used (always 0)
//--- bit 2 - is equal to 1 if the current extremum of the oscillator is "more extreme" than the previous one
//--- (a higher peak or a deeper valley), otherwise - 0
//--- bit 1 - not used (always 0)
//--- bit 0 - is equal to 1 if the current extremum of price is "more extreme" than the previous one
//--- (a higher peak or a deeper valley), otherwise - 0
//--- in addition to them, the following is formed:
//--- array of values of extremums of the oscillator,
//--- array of values of price extremums and
//--- array of "distances" between extremums of the oscillator (in bars)
//--- it should be noted that when using the results of the extended check of state,
//--- you should consider, which extremum of the oscillator (peak or valley)
//--- is the "reference point" (i.e. was detected first during the analysis)
//--- if a peak is detected first then even elements of all arrays
//--- will contain information about peaks, and odd elements will contain information about valleys
//--- if a valley is detected first, then respectively in reverse
int pos=ind,off,index;
uint map; // intermediate bit-map for one extremum
//---
m_extr_map=0;
for(int i=0;i<10;i++)
{
off=StateBears(pos);
if(off>0)
{
//--- minimum of the oscillator is detected
pos+=off;
m_extr_pos[i]=pos;
m_extr_osc[i]=Bears(pos);
if(i>1)
{
m_extr_pr[i]=m_low.MinValue(pos-2,5,index);
//--- form the intermediate bit-map
map=0;
if(m_extr_pr[i-2]<m_extr_pr[i])
map+=1; // set bit 0
if(m_extr_osc[i-2]<m_extr_osc[i])
map+=4; // set bit 2
//--- add the result
m_extr_map+=map<<(4*(i-2));
}
else
m_extr_pr[i]=m_low.MinValue(pos-1,4,index);
}
else
{
//--- maximum of the oscillator is detected
pos-=off;
m_extr_pos[i]=pos;
m_extr_osc[i]=Bears(pos);
if(i>1)
{
m_extr_pr[i]=m_high.MaxValue(pos-2,5,index);
//--- form the intermediate bit-map
map=0;
if(m_extr_pr[i-2]>m_extr_pr[i])
map+=1; // set bit 0
if(m_extr_osc[i-2]>m_extr_osc[i])
map+=4; // set bit 2
//--- add the result
m_extr_map+=map<<(4*(i-2));
}
else
m_extr_pr[i]=m_high.MaxValue(pos-1,4,index);
}
}
//---
return(true);
}
//+------------------------------------------------------------------+
//| "Voting" that price will grow. |
//+------------------------------------------------------------------+
int CSignalBearsPower::LongCondition(void)
{
int result=0;
int idx =StartIndex();
//--- if the oscillator is above zero, don't "vote" for buying
if(Bears(idx)>0.0)
return(result);
//--- the oscillator is below zero
if(StateBears(idx)>0)
{
//--- the oscillator has turned upwards at a previous bar
//--- there is a condition for buying
if(IS_PATTERN_USAGE(0))
result=m_pattern_0;
//--- if the model 1 is used, search for the "divergence" signal
if(IS_PATTERN_USAGE(1))
{
ExtStateBears(idx);
if((m_extr_map&0xF)==1)
{
if(m_extr_osc[0]<0.0 && m_extr_osc[2]<0.0)
{
//--- both valleys are below zero
//--- we suppose that this is "divergence"
result=m_pattern_1;
}
}
}
}
//--- return the result
return(result);
}
//+------------------------------------------------------------------+
+289
View File
@@ -0,0 +1,289 @@
//+------------------------------------------------------------------+
//| SignalBullsPower.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Expert\ExpertSignal.mqh>
// wizard description start
//+------------------------------------------------------------------+
//| Description of the class |
//| Title=Signals of oscillator 'Bulls Power' |
//| Type=SignalAdvanced |
//| Name=Bulls Power |
//| ShortName=BullsPower |
//| Class=CSignalBullsPower |
//| Page=signal_bulls |
//| Parameter=PeriodBulls,int,13,Period of calculation |
//+------------------------------------------------------------------+
// wizard description end
//+------------------------------------------------------------------+
//| Class CSignalBullsPower. |
//| Purpose: Class of generator of trade signals based on |
//| the 'Bulls Power' oscillator. |
//| Is derived from the CExpertSignal class. |
//+------------------------------------------------------------------+
class CSignalBullsPower : public CExpertSignal
{
protected:
CiBullsPower m_bulls; // object-oscillator
//--- adjusted parameters
int m_period_bulls; // the "period of calculation" parameter of the oscillator
//--- "weights" of market models (0-100)
int m_pattern_0; // model 0 "reverse of the oscillator to required direction"
int m_pattern_1; // model 1 "divergence of the oscillator and price"
//--- variables
double m_extr_osc[10]; // array of values of extremums of the oscillator
double m_extr_pr[10]; // array of values of the corresponding extremums of price
int m_extr_pos[10]; // array of shifts of extremums (in bars)
uint m_extr_map; // resulting bit-map of ratio of extremums of the oscillator and the price
public:
CSignalBullsPower(void);
~CSignalBullsPower(void);
//--- methods of setting adjustable parameters
void PeriodBulls(int value) { m_period_bulls=value; }
//--- methods of adjusting "weights" of market models
void Pattern_0(int value) { m_pattern_0=value; }
void Pattern_1(int value) { m_pattern_1=value; }
//--- method of verification of settings
virtual bool ValidationSettings(void);
//--- method of creating the indicator and timeseries
virtual bool InitIndicators(CIndicators *indicators);
//--- methods of checking if the market models are formed
virtual int ShortCondition(void);
//--- the oscillator doesn't identify conditions for buying
protected:
//--- method of initialization of the oscillator
bool InitBears(CIndicators *indicators);
//--- methods of getting data
double Bulls(int ind) { return(m_bulls.Main(ind)); }
double DiffBulls(int ind) { return(Bulls(ind)-Bulls(ind+1)); }
int StateBulls(int ind);
bool ExtStateBulls(int ind);
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CSignalBullsPower::CSignalBullsPower(void) : m_period_bulls(13),
m_pattern_0(20),
m_pattern_1(80)
{
//--- initialization of protected data
m_used_series=USE_SERIES_HIGH+USE_SERIES_LOW;
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CSignalBullsPower::~CSignalBullsPower(void)
{
}
//+------------------------------------------------------------------+
//| Validation settings protected data. |
//+------------------------------------------------------------------+
bool CSignalBullsPower::ValidationSettings(void)
{
//--- validation settings of additional filters
if(!CExpertSignal::ValidationSettings())
return(false);
//--- initial data checks
if(m_period_bulls<=0)
{
printf(__FUNCTION__+": period Bulls must be greater than 0");
return(false);
}
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Create indicators. |
//+------------------------------------------------------------------+
bool CSignalBullsPower::InitIndicators(CIndicators *indicators)
{
//--- check pointer
if(indicators==NULL)
return(false);
//--- initialization of indicators and timeseries of additional filters
if(!CExpertSignal::InitIndicators(indicators))
return(false);
//--- create and initialize BullsPower oscillator
if(!InitBears(indicators))
return(false);
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Initialize BearsPower oscillators. |
//+------------------------------------------------------------------+
bool CSignalBullsPower::InitBears(CIndicators *indicators)
{
//--- check pointer
if(indicators==NULL)
return(false);
//--- add object to collection
if(!indicators.Add(GetPointer(m_bulls)))
{
printf(__FUNCTION__+": error adding object");
return(false);
}
//--- initialize object
if(!m_bulls.Create(m_symbol.Name(),m_period,m_period_bulls))
{
printf(__FUNCTION__+": error initializing object");
return(false);
}
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Check of the oscillator state. |
//+------------------------------------------------------------------+
int CSignalBullsPower::StateBulls(int ind)
{
int res=0;
double var;
//---
for(int i=ind;;i++)
{
if(Bulls(i+1)==EMPTY_VALUE)
break;
var=DiffBulls(i);
if(res>0)
{
if(var<0)
break;
res++;
continue;
}
if(res<0)
{
if(var>0)
break;
res--;
continue;
}
if(var>0)
res++;
if(var<0)
res--;
}
//--- return the result
return(res);
}
//+------------------------------------------------------------------+
//| Extended check of the oscillator state consists |
//| in forming a bit-map according to certain rules, |
//| which shows ratios of extremums of the oscillator and price. |
//+------------------------------------------------------------------+
bool CSignalBullsPower::ExtStateBulls(int ind)
{
//--- operation of this method results in a bit-map of extremums
//--- practically, the bit-map of extremums is an "array" of 4-bit fields
//--- each "element of the array" definitely describes the ratio
//--- of current extremums of the oscillator and the price with previous ones
//--- purpose of bits of an element of the analyzed bit-map
//--- bit 3 - not used (always 0)
//--- bit 2 - is equal to 1 if the current extremum of the oscillator is "more extreme" than the previous one
//--- (a higher peak or a deeper valley), otherwise - 0
//--- bit 1 - not used (always 0)
//--- bit 0 - is equal to 1 if the current extremum of price is "more extreme" than the previous one
//--- (a higher peak or a deeper valley), otherwise - 0
//--- in addition to them, the following is formed:
//--- array of values of extremums of the oscillator,
//--- array of values of price extremums and
//--- array of "distances" between extremums of the oscillator (in bars)
//--- it should be noted that when using the results of the extended check of state,
//--- you should consider, which extremum of the oscillator (peak or valley)
//--- is the "reference point" (i.e. was detected first during the analysis)
//--- if a peak is detected first then even elements of all arrays
//--- will contain information about peaks, and odd elements will contain information about valleys
//--- if a valley is detected first, then respectively in reverse
int pos=ind,off,index;
uint map; // intermediate bit-map for one extremum
//---
m_extr_map=0;
for(int i=0;i<10;i++)
{
off=StateBulls(pos);
if(off>0)
{
//--- minimum of the oscillator is detected
pos+=off;
m_extr_pos[i]=pos;
m_extr_osc[i]=Bulls(pos);
if(i>1)
{
m_extr_pr[i]=m_low.MinValue(pos-2,5,index);
//--- form the intermediate bit-map
map=0;
if(m_extr_pr[i-2]<m_extr_pr[i])
map+=1; // set bit 0
if(m_extr_osc[i-2]<m_extr_osc[i])
map+=4; // set bit 2
//--- add the result
m_extr_map+=map<<(4*(i-2));
}
else
m_extr_pr[i]=m_low.MinValue(pos-1,4,index);
}
else
{
//--- maximum of the oscillator is detected
pos-=off;
m_extr_pos[i]=pos;
m_extr_osc[i]=Bulls(pos);
if(i>1)
{
m_extr_pr[i]=m_high.MaxValue(pos-2,5,index);
//--- form the intermediate bit-map
map=0;
if(m_extr_pr[i-2]>m_extr_pr[i])
map+=1; // set bit 0
if(m_extr_osc[i-2]>m_extr_osc[i])
map+=4; // set bit 2
//--- add the result
m_extr_map+=map<<(4*(i-2));
}
else
m_extr_pr[i]=m_high.MaxValue(pos-1,4,index);
}
}
//---
return(true);
}
//+------------------------------------------------------------------+
//| "Voting" that price will fall. |
//+------------------------------------------------------------------+
int CSignalBullsPower::ShortCondition(void)
{
int result=0;
int idx =StartIndex();
//--- if the oscillator is below zero, don't "vote" for selling
if(Bulls(idx)<0.0)
return(result);
//--- the oscillator is above zero
if(StateBulls(idx)<0)
{
//--- the oscillator has turned downwards at a previous bar
//--- there us a condition for selling
if(IS_PATTERN_USAGE(0))
result=m_pattern_0;
//--- if the model 1 is used, search for the "divergence" signal
if(IS_PATTERN_USAGE(1))
{
ExtStateBulls(idx);
if((m_extr_map&0xF)==1)
{
if(m_extr_osc[0]>0.0 && m_extr_osc[2]>0.0)
{
//--- both peaks are above zero
//--- we suppose that this is "divergence"
result=m_pattern_1;
}
}
}
}
//--- return the result
return(result);
}
//+------------------------------------------------------------------+
+382
View File
@@ -0,0 +1,382 @@
//+------------------------------------------------------------------+
//| SignalCCI.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Expert\ExpertSignal.mqh>
// wizard description start
//+------------------------------------------------------------------+
//| Description of the class |
//| Title=Signals of oscilator 'Commodity Channel Index' |
//| Type=SignalAdvanced |
//| Name=Commodity Channel Index |
//| ShortName=CCI |
//| Class=CSignalCCI |
//| Page=signal_cci |
//| Parameter=PeriodCCI,int,8,Period of calculation |
//| Parameter=Applied,ENUM_APPLIED_PRICE,PRICE_CLOSE,Prices series |
//+------------------------------------------------------------------+
// wizard description end
//+------------------------------------------------------------------+
//| Class CSignalCCI. |
//| Purpose: Class of generator of trade signals based on |
//| the 'Commodity Channel Index' oscillator. |
//| Is derived from the CExpertSignal class. |
//+------------------------------------------------------------------+
class CSignalCCI : public CExpertSignal
{
protected:
CiCCI m_cci; // object-oscillator
//--- adjusted parameters
int m_periodCCI; // the "period of calculation" parameter of the oscillator
ENUM_APPLIED_PRICE m_applied; // the "prices series" parameter of the oscillator
//--- "weights" of market models (0-100)
int m_pattern_0; // model 0 "the oscillator has required direction"
int m_pattern_1; // model 1 "reverse behind the level of overbuying/overselling"
int m_pattern_2; // model 2 "divergence of the oscillator and price"
int m_pattern_3; // model 3 "double divergence of the oscillator and price"
//--- variables
double m_extr_osc[10]; // array of values of extremums of the oscillator
double m_extr_pr[10]; // array of values of the corresponding extremums of price
int m_extr_pos[10]; // array of shifts of extremums (in bars)
uint m_extr_map; // resulting bit-map of ratio of extremums of the oscillator and the price
public:
CSignalCCI(void);
~CSignalCCI(void);
//--- methods of setting adjustable parameters
void PeriodCCI(int value) { m_periodCCI=value; }
void Applied(ENUM_APPLIED_PRICE value) { m_applied=value; }
//--- methods of adjusting "weights" of market models
void Pattern_0(int value) { m_pattern_0=value; }
void Pattern_1(int value) { m_pattern_1=value; }
void Pattern_2(int value) { m_pattern_2=value; }
void Pattern_3(int value) { m_pattern_3=value; }
//--- method of verification of settings
virtual bool ValidationSettings(void);
//--- method of creating the indicator and timeseries
virtual bool InitIndicators(CIndicators *indicators);
//--- methods of checking if the market models are formed
virtual int LongCondition(void);
virtual int ShortCondition(void);
protected:
//--- method of initialization of the oscillator
bool InitStoch(CIndicators *indicators);
//--- methods of getting data
double CCI(int ind) { return(m_cci.Main(ind)); }
double Diff(int ind) { return(CCI(ind)-CCI(ind+1)); }
int State(int ind);
bool ExtState(int ind);
bool CompareMaps(int map,int count,bool minimax=false,int start=0);
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CSignalCCI::CSignalCCI(void) : m_periodCCI(14),
m_applied(PRICE_CLOSE),
m_pattern_0(90),
m_pattern_1(60),
m_pattern_2(100),
m_pattern_3(50)
{
//--- initialization of protected data
m_used_series=USE_SERIES_HIGH+USE_SERIES_LOW;
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CSignalCCI::~CSignalCCI(void)
{
}
//+------------------------------------------------------------------+
//| Validation settings protected data. |
//+------------------------------------------------------------------+
bool CSignalCCI::ValidationSettings(void)
{
//--- validation settings of additional filters
if(!CExpertSignal::ValidationSettings())
return(false);
//--- initial data checks
if(m_periodCCI<=0)
{
printf(__FUNCTION__+": period of the CCI oscillator must be greater than 0");
return(false);
}
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Create indicators. |
//+------------------------------------------------------------------+
bool CSignalCCI::InitIndicators(CIndicators *indicators)
{
//--- check pointer
if(indicators==NULL)
return(false);
//--- initialization of indicators and timeseries of additional filters
if(!CExpertSignal::InitIndicators(indicators))
return(false);
//--- create and initialize CCI oscillator
if(!InitStoch(indicators))
return(false);
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Initialize CCI oscillators. |
//+------------------------------------------------------------------+
bool CSignalCCI::InitStoch(CIndicators *indicators)
{
//--- check pointer
if(indicators==NULL)
return(false);
//--- add object to collection
if(!indicators.Add(GetPointer(m_cci)))
{
printf(__FUNCTION__+": error adding object");
return(false);
}
//--- initialize object
if(!m_cci.Create(m_symbol.Name(),m_period,m_periodCCI,m_applied))
{
printf(__FUNCTION__+": error initializing object");
return(false);
}
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Check of the oscillator state. |
//+------------------------------------------------------------------+
int CSignalCCI::State(int ind)
{
int res=0;
double var;
//---
for(int i=ind;;i++)
{
if(CCI(i+1)==EMPTY_VALUE)
break;
var=Diff(i);
if(res>0)
{
if(var<0)
break;
res++;
continue;
}
if(res<0)
{
if(var>0)
break;
res--;
continue;
}
if(var>0)
res++;
if(var<0)
res--;
}
//--- return the result
return(res);
}
//+------------------------------------------------------------------+
//| Extended check of the oscillator state consists |
//| in forming a bit-map according to certain rules, |
//| which shows ratios of extremums of the oscillator and price. |
//+------------------------------------------------------------------+
bool CSignalCCI::ExtState(int ind)
{
//--- operation of this method results in a bit-map of extremums
//--- practically, the bit-map of extremums is an "array" of 4-bit fields
//--- each "element of the array" definitely describes the ratio
//--- of current extremums of the oscillator and the price with previous ones
//--- purpose of bits of an element of the analyzed bit-map
//--- bit 3 - not used (always 0)
//--- bit 2 - is equal to 1 if the current extremum of the oscillator is "more extreme" than the previous one
//--- (a higher peak or a deeper valley), otherwise - 0
//--- bit 1 - not used (always 0)
//--- bit 0 - is equal to 1 if the current extremum of price is "more extreme" than the previous one
//--- (a higher peak or a deeper valley), otherwise - 0
//--- in addition to them, the following is formed:
//--- array of values of extremums of the oscillator,
//--- array of values of price extremums and
//--- array of "distances" between extremums of the oscillator (in bars)
//--- it should be noted that when using the results of the extended check of state,
//--- you should consider, which extremum of the oscillator (peak or valley)
//--- is the "reference point" (i.e. was detected first during the analysis)
//--- if a peak is detected first then even elements of all arrays
//--- will contain information about peaks, and odd elements will contain information about valleys
//--- if a valley is detected first, then respectively in reverse
int pos=ind,off,index;
uint map; // intermediate bit-map for one extremum
//---
m_extr_map=0;
for(int i=0;i<10;i++)
{
off=State(pos);
if(off>0)
{
//--- minimum of the oscillator is detected
pos+=off;
m_extr_pos[i]=pos;
m_extr_osc[i]=CCI(pos);
if(i>1)
{
m_extr_pr[i]=m_low.MinValue(pos-2,5,index);
//--- form the intermediate bit-map
map=0;
if(m_extr_pr[i-2]<m_extr_pr[i])
map+=1; // set bit 0
if(m_extr_osc[i-2]<m_extr_osc[i])
map+=4; // set bit 2
//--- add the result
m_extr_map+=map<<(4*(i-2));
}
else
m_extr_pr[i]=m_low.MinValue(pos-1,3,index);
}
else
{
//--- maximum of the oscillator is detected
pos-=off;
m_extr_pos[i]=pos;
m_extr_osc[i]=CCI(pos);
if(i>1)
{
m_extr_pr[i]=m_high.MaxValue(pos-2,5,index);
//--- form the intermediate bit-map
map=0;
if(m_extr_pr[i-2]>m_extr_pr[i])
map+=1; // set bit 0
if(m_extr_osc[i-2]>m_extr_osc[i])
map+=4; // set bit 2
//--- add the result
m_extr_map+=map<<(4*(i-2));
}
else
m_extr_pr[i]=m_high.MaxValue(pos-1,3,index);
}
}
//---
return(true);
}
//+------------------------------------------------------------------+
//| Comparing the bit-map of extremums with pattern. |
//+------------------------------------------------------------------+
bool CSignalCCI::CompareMaps(int map,int count,bool minimax,int start)
{
int step =(minimax)?4:8;
int total=step*(start+count);
//--- check input parameters for a possible going out of range of the bit-map
if(total>32)
return(false);
//--- bit-map of the patter is an "array" of 4-bit fields
//--- each "element of the array" definitely describes the desired ratio
//--- of current extremums of the oscillator and the price with previous ones
//--- purpose of bits of an elements of the pattern of the bit-map pattern
//--- bit 3 - is equal to if the ratio of extremums of the oscillator is insignificant for us
//--- is equal to 0 if we want to "find" the ratio of extremums of the oscillator determined by the value of bit 2
//--- bit 2 - is equal to 1 if we want to "discover" the situation when the current extremum of the "oscillator" is "more extreme" than the previous one
//--- (current peak is higher or current valley is deeper)
//--- is equal to 0 if we want to "discover" the situation when the current extremum of the oscillator is "less extreme" than the previous one
//--- (current peak is lower or current valley is less deep)
//--- bit 1 - is equal to 1 if the ratio of extremums is insignificant for us
//--- it is equal to 0 if we want to "find" the ratio of price extremums determined by the value of bit 0
//--- bit 0 - is equal to 1 if we want to "discover" the situation when the current price extremum is "more extreme" than the previous one
//--- (current peak is higher or current valley is deeper)
//--- it is equal to 0 if we want to "discover" the situation when the current price extremum is "less extreme" than the previous one
//--- (current peak is lower or current valley is less deep)
uint inp_map,check_map;
int i,j;
//--- loop by extremums (4 minimums and 4 maximums)
//--- price and the oscillator are checked separately (thus, there are 16 checks)
for(i=step*start,j=0;i<total;i+=step,j+=4)
{
//--- "take" two bits - patter of the corresponding extremum of the price
inp_map=(map>>j)&3;
//--- if the higher-order bit=1, then any ratio is suitable for us
if(inp_map<2)
{
//--- "take" two bits of the corresponding extremum of the price (higher-order bit is always 0)
check_map=(m_extr_map>>i)&3;
if(inp_map!=check_map)
return(false);
}
//--- "take" two bits - pattern of the corresponding oscillator extremum
inp_map=(map>>(j+2))&3;
//--- if the higher-order bit=1, then any ratio is suitable for us
if(inp_map>=2)
continue;
//--- "take" two bits of the corresponding oscillator extremum (higher-order bit is always 0)
check_map=(m_extr_map>>(i+2))&3;
if(inp_map!=check_map)
return(false);
}
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| "Voting" that price will grow. |
//+------------------------------------------------------------------+
int CSignalCCI::LongCondition(void)
{
int result=0;
int idx =StartIndex();
//---
if(Diff(idx)>0.0)
{
//--- the oscillator is directed upwards confirming the possibility of price growth
if(IS_PATTERN_USAGE(0))
result=m_pattern_0; // "confirming" signal number 0
//--- if the model 1 is used, search for a reverse of the oscillator upwards behind the level of overselling
if(IS_PATTERN_USAGE(1) && Diff(idx+1)<0.0 && CCI(idx+1)<-100.0)
result=m_pattern_1; // signal number 1
//--- if the model 2 or 3 is used, perform the extended analysis of the oscillator state
if(IS_PATTERN_USAGE(2) || IS_PATTERN_USAGE(3))
{
ExtState(idx);
//--- if the model 2 is used, search for the "divergence" signal
if(IS_PATTERN_USAGE(2) && CompareMaps(1,1)) // 00000001b
result=m_pattern_2; // signal number 2
//--- if the model 3 is used, search for the "double divergence" signal
if(IS_PATTERN_USAGE(3) && CompareMaps(0x11,2)) // 00010001b
return(m_pattern_3); // signal number 3
}
}
//--- return the result
return(result);
}
//+------------------------------------------------------------------+
//| "Voting" that price will fall. |
//+------------------------------------------------------------------+
int CSignalCCI::ShortCondition(void)
{
int result=0;
int idx =StartIndex();
//---
if(Diff(idx)<0.0)
{
//--- the oscillator is directed downwards confirming the possibility of falling of price
if(IS_PATTERN_USAGE(0))
result=m_pattern_0; // "confirming" signal number 0
//--- if the model 1 is used, search for a reverse of the oscillator downwards behind the level of overbuying
if(IS_PATTERN_USAGE(1) && Diff(idx+1)>0.0 && CCI(idx+1)>100.0)
result=m_pattern_1; // signal number 1
//--- if the model 2 or 3 is used, perform the extended analysis of the oscillator state
if(IS_PATTERN_USAGE(2) || IS_PATTERN_USAGE(3))
{
ExtState(idx);
//--- if the model 2 is used, search for the "divergence" signal
if(IS_PATTERN_USAGE(2) && CompareMaps(1,1)) // 00000001b
result=m_pattern_2; // signal number 2
//--- if the model 3 is used, search for the "double divergence" signal
if(IS_PATTERN_USAGE(3) && CompareMaps(0x11,2)) // 00010001b
return(m_pattern_3); // signal number 3
}
}
//--- return the result
return(result);
}
//+------------------------------------------------------------------+
+257
View File
@@ -0,0 +1,257 @@
//+------------------------------------------------------------------+
//| SignalDEMA.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Expert\ExpertSignal.mqh>
// wizard description start
//+------------------------------------------------------------------+
//| Description of the class |
//| Title=Signals of indicator 'Double Exponential Moving Average' |
//| Type=SignalAdvanced |
//| Name=Double Exponential Moving Average |
//| ShortName=DEMA |
//| Class=CSignalDEMA |
//| Page=signal_dema |
//| Parameter=PeriodMA,int,12,Period of averaging |
//| Parameter=Shift,int,0,Time shift |
//| Parameter=Applied,ENUM_APPLIED_PRICE,PRICE_CLOSE,Prices series |
//+------------------------------------------------------------------+
// wizard description end
//+------------------------------------------------------------------+
//| Class CSignalDEMA. |
//| Purpose: Class of generator of trade signals based on |
//| the 'Double Exponential Moving Average' indicator. |
//| Is derived from the CExpertSignal class. |
//+------------------------------------------------------------------+
class CSignalDEMA : public CExpertSignal
{
protected:
CiDEMA m_ma; // object-indicator
//--- adjusted parameters
int m_ma_period; // the "period of averaging" parameter of the indicator
int m_ma_shift; // the "time shift" parameter of the indicator
ENUM_APPLIED_PRICE m_ma_applied; // the "object of averaging" parameter" of the indicator
//--- "weights" of market models (0-100)
int m_pattern_0; // model 0 "price is on the necessary side from the indicator"
int m_pattern_1; // model 1 "price crossed the indicator with opposite direction"
int m_pattern_2; // model 2 "price crossed the indicator with the same direction"
int m_pattern_3; // model 3 "piercing"
public:
CSignalDEMA(void);
~CSignalDEMA(void);
//--- methods of setting adjustable parameters
void PeriodMA(int value) { m_ma_period=value; }
void Shift(int value) { m_ma_shift=value; }
void Applied(ENUM_APPLIED_PRICE value) { m_ma_applied=value; }
//--- methods of adjusting "weights" of market models
void Pattern_0(int value) { m_pattern_0=value; }
void Pattern_1(int value) { m_pattern_1=value; }
void Pattern_2(int value) { m_pattern_2=value; }
void Pattern_3(int value) { m_pattern_3=value; }
//--- method of verification of settings
virtual bool ValidationSettings(void);
//--- method of creating the indicator and timeseries
virtual bool InitIndicators(CIndicators *indicators);
//--- methods of checking if the market models are formed
virtual int LongCondition(void);
virtual int ShortCondition(void);
protected:
//--- method of initialization of the indicator
bool InitMA(CIndicators *indicators);
//--- methods of getting data
double MA(int ind) { return(m_ma.Main(ind)); }
double DiffMA(int ind) { return(MA(ind)-MA(ind+1)); }
double DiffOpenMA(int ind) { return(Open(ind)-MA(ind)); }
double DiffHighMA(int ind) { return(High(ind)-MA(ind)); }
double DiffLowMA(int ind) { return(Low(ind)-MA(ind)); }
double DiffCloseMA(int ind) { return(Close(ind)-MA(ind)); }
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CSignalDEMA::CSignalDEMA(void) : m_ma_period(12),
m_ma_shift(0),
m_ma_applied(PRICE_CLOSE),
m_pattern_0(20),
m_pattern_1(60),
m_pattern_2(80),
m_pattern_3(60)
{
//--- initialization of protected data
m_used_series=USE_SERIES_OPEN+USE_SERIES_HIGH+USE_SERIES_LOW+USE_SERIES_CLOSE;
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CSignalDEMA::~CSignalDEMA(void)
{
}
//+------------------------------------------------------------------+
//| Validation settings protected data. |
//+------------------------------------------------------------------+
bool CSignalDEMA::ValidationSettings(void)
{
//--- call of the method of the parent class
if(!CExpertSignal::ValidationSettings())
return(false);
//--- initial data checks
if(m_ma_period<=0)
{
printf(__FUNCTION__+": period MA must be greater than 0");
return(false);
}
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Create indicators. |
//+------------------------------------------------------------------+
bool CSignalDEMA::InitIndicators(CIndicators *indicators)
{
//--- check pointer
if(indicators==NULL)
return(false);
//--- initialization of indicators and timeseries of additional filters
if(!CExpertSignal::InitIndicators(indicators))
return(false);
//--- create and initialize DEMA indicator
if(!InitMA(indicators))
return(false);
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Create MA indicators. |
//+------------------------------------------------------------------+
bool CSignalDEMA::InitMA(CIndicators *indicators)
{
//--- check pointer
if(indicators==NULL)
return(false);
//--- add indicator to collection
if(!indicators.Add(GetPointer(m_ma)))
{
printf(__FUNCTION__+": error adding object");
return(false);
}
//--- initialize indicator
if(!m_ma.Create(m_symbol.Name(),m_period,m_ma_period,m_ma_shift,m_ma_applied))
{
printf(__FUNCTION__+": error initializing object");
return(false);
}
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| "Voting" that price will grow. |
//+------------------------------------------------------------------+
int CSignalDEMA::LongCondition(void)
{
int result=0;
int idx =StartIndex();
//--- analyze positional relationship of the close price and the indicator at the first analyzed bar
if(DiffCloseMA(idx)<0.0)
{
//--- the close price is below the indicator
if(IS_PATTERN_USAGE(1) && DiffOpenMA(idx)>0.0 && DiffMA(idx)>0.0)
{
//--- the open price is above the indicator (i.e. there was an intersection), but the indicator is directed upwards
result=m_pattern_1;
//--- consider that this is an unformed "piercing" and suggest to enter the market at the current price
m_base_price=0.0;
}
}
else
{
//--- the close price is above the indicator (the indicator has no objections to buying)
if(IS_PATTERN_USAGE(0))
result=m_pattern_0;
//--- if the indicator is directed upwards
if(DiffMA(idx)>0.0)
{
if(DiffOpenMA(idx)<0.0)
{
//--- if the model 2 is used
if(IS_PATTERN_USAGE(2))
{
//--- the open price is below the indicator (i.e. there was an intersection)
result=m_pattern_2;
//--- suggest to enter the market at the "roll back"
m_base_price=m_symbol.NormalizePrice(MA(idx));
}
}
else
{
//--- if the model 3 is used and the open price is above the indicator
if(IS_PATTERN_USAGE(3) && DiffLowMA(idx)<0.0)
{
//--- the low price is below the indicator
result=m_pattern_3;
//--- consider that this is a formed "piercing" and suggest to enter the market at the current price
m_base_price=0.0;
}
}
}
}
//--- return the result
return(result);
}
//+------------------------------------------------------------------+
//| "Voting" that price will fall. |
//+------------------------------------------------------------------+
int CSignalDEMA::ShortCondition(void)
{
int result=0;
int idx =StartIndex();
//--- analyze positional relationship of the close price and the indicator at the first analyzed bar
if(DiffCloseMA(idx)>0.0)
{
//--- the close price is above the indicator
if(IS_PATTERN_USAGE(1) && DiffOpenMA(idx)<0.0 && DiffMA(idx)<0.0)
{
//--- the open price is below the indicator (i.e. there was an intersection), but the indicator is directed downwards
result=m_pattern_1;
//--- consider that this is an unformed "piercing" and suggest to enter the market at the current price
m_base_price=0.0;
}
}
else
{
//--- the close price is below the indicator (the indicator has no objections to buying)
if(IS_PATTERN_USAGE(0))
result=m_pattern_0;
//--- the indicator is directed downwards
if(DiffMA(idx)<0.0)
{
if(DiffOpenMA(idx)>0.0)
{
//--- if the model 2 is used
if(IS_PATTERN_USAGE(2))
{
//--- the open price is above the indicator (i.e. there was an intersection)
result=m_pattern_2;
//--- suggest to enter the market at the "roll back"
m_base_price=m_symbol.NormalizePrice(MA(idx));
}
}
else
{
//--- if the model 3 is used and the open price is below the indicator
if(IS_PATTERN_USAGE(3) && DiffHighMA(idx)>0.0)
{
//--- the high price is above the indicator
result=m_pattern_3;
//--- consider that this is a formed "piercing" and suggest to enter the market at the current price
m_base_price=0.0;
}
}
}
}
//--- return the result
return(result);
}
//+------------------------------------------------------------------+
+378
View File
@@ -0,0 +1,378 @@
//+------------------------------------------------------------------+
//| SignalDeMarker.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Expert\ExpertSignal.mqh>
// wizard description start
//+------------------------------------------------------------------+
//| Description of the class |
//| Title=Signals of oscillator 'DeMarker' |
//| Type=SignalAdvanced |
//| Name=DeMarker |
//| ShortName=DeM |
//| Class=CSignalDeM |
//| Page=signal_demarker |
//| Parameter=PeriodDeM,int,8,Period of calculation |
//+------------------------------------------------------------------+
// wizard description end
//+------------------------------------------------------------------+
//| Class CSignalDeM. |
//| Purpose: Class of generator of trade signals based on |
//| the 'Commodity Channel Index' oscillator. |
//| Is derived from the CExpertSignal class. |
//+------------------------------------------------------------------+
class CSignalDeM : public CExpertSignal
{
protected:
CiDeMarker m_dem; // object-oscillator
//--- adjusted parameters
int m_periodDeM; // the "period of calculation" parameter of the oscillator
//--- "weights" of market models (0-100)
int m_pattern_0; // model 0 "the oscillator has required direction"
int m_pattern_1; // model 1 "reverse behind the level of overbuying/overselling"
int m_pattern_2; // model 2 "divergence of the oscillator and price"
int m_pattern_3; // model 3 "double divergence of the oscillator and price"
//--- variables
double m_extr_osc[10]; // array of values of extremums of the oscillator
double m_extr_pr[10]; // array of values of the corresponding extremums of price
int m_extr_pos[10]; // array of shifts of extremums (in bars)
uint m_extr_map; // resulting bit-map of ratio of extremums of the oscillator and the price
public:
CSignalDeM(void);
~CSignalDeM(void);
//--- methods of setting adjustable parameters
void PeriodDeM(int value) { m_periodDeM=value; }
//--- methods of adjusting "weights" of market models
void Pattern_0(int value) { m_pattern_0=value; }
void Pattern_1(int value) { m_pattern_1=value; }
void Pattern_2(int value) { m_pattern_2=value; }
void Pattern_3(int value) { m_pattern_3=value; }
//--- method of verification of settings
virtual bool ValidationSettings(void);
//--- method of creating the indicator and timeseries
virtual bool InitIndicators(CIndicators *indicators);
//--- methods of checking if the market models are formed
virtual int LongCondition(void);
virtual int ShortCondition(void);
protected:
//--- method of initialization of the oscillator
bool InitStoch(CIndicators *indicators);
//--- methods of getting data
double DeM(int ind) { return(m_dem.Main(ind)); }
double DiffDeM(int ind) { return(DeM(ind)-DeM(ind+1)); }
int StateDeM(int ind);
bool ExtStateDeM(int ind);
bool CompareMaps(int map,int count,bool minimax=false,int start=0);
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CSignalDeM::CSignalDeM(void) : m_periodDeM(14),
m_pattern_0(90),
m_pattern_1(60),
m_pattern_2(100),
m_pattern_3(80)
{
//--- initialization of protected data
m_used_series=USE_SERIES_HIGH+USE_SERIES_LOW;
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CSignalDeM::~CSignalDeM(void)
{
}
//+------------------------------------------------------------------+
//| Validation settings protected data. |
//+------------------------------------------------------------------+
bool CSignalDeM::ValidationSettings(void)
{
//--- validation settings of additional filters
if(!CExpertSignal::ValidationSettings())
return(false);
//--- initial data checks
if(m_periodDeM<=0)
{
printf(__FUNCTION__+": period of the DeMarker oscillator must be greater than 0");
return(false);
}
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Create indicators. |
//+------------------------------------------------------------------+
bool CSignalDeM::InitIndicators(CIndicators *indicators)
{
//--- check pointer
if(indicators==NULL)
return(false);
//--- initialization of indicators and timeseries of additional filters
if(!CExpertSignal::InitIndicators(indicators))
return(false);
//--- create and initialize DeMarker oscillator
if(!InitStoch(indicators))
return(false);
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Initialize DeMarker oscillators. |
//+------------------------------------------------------------------+
bool CSignalDeM::InitStoch(CIndicators *indicators)
{
//--- check pointer
if(indicators==NULL)
return(false);
//--- add object to collection
if(!indicators.Add(GetPointer(m_dem)))
{
printf(__FUNCTION__+": error adding object");
return(false);
}
//--- initialize object
if(!m_dem.Create(m_symbol.Name(),m_period,m_periodDeM))
{
printf(__FUNCTION__+": error initializing object");
return(false);
}
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Check of the oscillator state. |
//+------------------------------------------------------------------+
int CSignalDeM::StateDeM(int ind)
{
int res=0;
double var;
//---
for(int i=ind;;i++)
{
if(DeM(i+1)==EMPTY_VALUE)
break;
var=DiffDeM(i);
if(res>0)
{
if(var<0)
break;
res++;
continue;
}
if(res<0)
{
if(var>0)
break;
res--;
continue;
}
if(var>0)
res++;
if(var<0)
res--;
}
//---
return(res);
}
//+------------------------------------------------------------------+
//| Extended check of the oscillator state consists |
//| in forming a bit-map according to certain rules, |
//| which shows ratios of extremums of the oscillator and price. |
//+------------------------------------------------------------------+
bool CSignalDeM::ExtStateDeM(int ind)
{
//--- operation of this method results in a bit-map of extremums
//--- practically, the bit-map of extremums is an "array" of 4-bit fields
//--- each "element of the array" definitely describes the ratio
//--- of current extremums of the oscillator and the price with previous ones
//--- purpose of bits of an element of the analyzed bit-map
//--- bit 3 - not used (always 0)
//--- bit 2 - is equal to 1 if the current extremum of the oscillator is "more extreme" than the previous one
//--- (a higher peak or a deeper valley), otherwise - 0
//--- bit 1 - not used (always 0)
//--- bit 0 - is equal to 1 if the current extremum of price is "more extreme" than the previous one
//--- (a higher peak or a deeper valley), otherwise - 0
//--- in addition to them, the following is formed:
//--- array of values of extremums of the oscillator,
//--- array of values of price extremums and
//--- array of "distances" between extremums of the oscillator (in bars)
//--- it should be noted that when using the results of the extended check of state,
//--- you should consider, which extremum of the oscillator (peak or valley)
//--- is the "reference point" (i.e. was detected first during the analysis)
//--- if a peak is detected first then even elements of all arrays
//--- will contain information about peaks, and odd elements will contain information about valleys
//--- if a valley is detected first, then respectively in reverse
int pos=ind,off,index;
uint map; // intermediate bit-map for one extremum
//---
m_extr_map=0;
for(int i=0;i<10;i++)
{
off=StateDeM(pos);
if(off>0)
{
//--- minimum of the oscillator is detected
pos+=off;
m_extr_pos[i]=pos;
m_extr_osc[i]=DeM(pos);
if(i>1)
{
m_extr_pr[i]=m_low.MinValue(pos-2,5,index);
//--- form the intermediate bit-map
map=0;
if(m_extr_pr[i-2]<m_extr_pr[i])
map+=1; // set bit 0
if(m_extr_osc[i-2]<m_extr_osc[i])
map+=4; // set bit 2
//--- add the result
m_extr_map+=map<<(4*(i-2));
}
else
m_extr_pr[i]=m_low.MinValue(pos-1,4,index);
}
else
{
//--- maximum of the oscillator is detected
pos-=off;
m_extr_pos[i]=pos;
m_extr_osc[i]=DeM(pos);
if(i>1)
{
m_extr_pr[i]=m_high.MaxValue(pos-2,5,index);
//--- form the intermediate bit-map
map=0;
if(m_extr_pr[i-2]>m_extr_pr[i])
map+=1; // set bit 0
if(m_extr_osc[i-2]>m_extr_osc[i])
map+=4; // set bit 2
//--- add the result
m_extr_map+=map<<(4*(i-2));
}
else
m_extr_pr[i]=m_high.MaxValue(pos-1,4,index);
}
}
//---
return(true);
}
//+------------------------------------------------------------------+
//| Comparing the bit-map of extremums with pattern. |
//+------------------------------------------------------------------+
bool CSignalDeM::CompareMaps(int map,int count,bool minimax,int start)
{
int step =(minimax)?4:8;
int total=step*(start+count);
//--- check input parameters for a possible going out of range of the bit-map
if(total>32)
return(false);
//--- bit-map of the patter is an "array" of 4-bit fields
//--- each "element of the array" definitely describes the desired ratio
//--- of current extremums of the oscillator and the price with previous ones
//--- purpose of bits of an elements of the pattern of the bit-map pattern
//--- bit 3 - is equal to if the ratio of extremums of the oscillator is insignificant for us
//--- is equal to 0 if we want to "find" the ratio of extremums of the oscillator determined by the value of bit 2
//--- bit 2 - is equal to 1 if we want to "discover" the situation when the current extremum of the "oscillator" is "more extreme" than the previous one
//--- (current peak is higher or current valley is deeper)
//--- is equal to 0 if we want to "discover" the situation when the current extremum of the oscillator is "less extreme" than the previous one
//--- (current peak is lower or current valley is less deep)
//--- bit 1 - is equal to 1 if the ratio of extremums is insignificant for us
//--- it is equal to 0 if we want to "find" the ratio of price extremums determined by the value of bit 0
//--- bit 0 - is equal to 1 if we want to "discover" the situation when the current price extremum is "more extreme" than the previous one
//--- (current peak is higher or current valley is deeper)
//--- it is equal to 0 if we want to "discover" the situation when the current price extremum is "less extreme" than the previous one
//--- (current peak is lower or current valley is less deep)
uint inp_map,check_map;
int i,j;
//--- loop by extremums (4 minimums and 4 maximums)
//--- price and the oscillator are checked separately (thus, there are 16 checks)
for(i=step*start,j=0;i<total;i+=step,j+=4)
{
//--- "take" two bits - patter of the corresponding extremum of the price
inp_map=(map>>j)&3;
//--- if the higher-order bit=1, then any ratio is suitable for us
if(inp_map<2)
{
//--- "take" two bits of the corresponding extremum of the price (higher-order bit is always 0)
check_map=(m_extr_map>>i)&3;
if(inp_map!=check_map)
return(false);
}
//--- "take" two bits - pattern of the corresponding oscillator extremum
inp_map=(map>>(j+2))&3;
//--- if the higher-order bit=1, then any ratio is suitable for us
if(inp_map>=2)
continue;
//--- "take" two bits of the corresponding oscillator extremum (higher-order bit is always 0)
check_map=(m_extr_map>>(i+2))&3;
if(inp_map!=check_map)
return(false);
}
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| "Voting" that price will grow. |
//+------------------------------------------------------------------+
int CSignalDeM::LongCondition(void)
{
int result=0;
int idx =StartIndex();
//--- check direction of the main line
if(DiffDeM(idx)>0.0)
{
//--- the oscillator is directed upwards confirming the possibility of price growth
if(IS_PATTERN_USAGE(0))
result=m_pattern_0; // "confirming" signal number 0
//--- if the model 1 is used, search for a reverse of the oscillator upwards behind the level of overselling
if(IS_PATTERN_USAGE(1) && DiffDeM(idx+1)<0.0 && DeM(idx+1)<0.3)
result=m_pattern_1; // signal number 1
//--- if the model 2 or 3 is used, perform the extended analysis of the oscillator state
if(IS_PATTERN_USAGE(2) || IS_PATTERN_USAGE(3))
{
ExtStateDeM(idx);
//--- if the model 2 is used, search for the "divergence" signal
if(IS_PATTERN_USAGE(2) && CompareMaps(1,1)) // 00000001b
result=m_pattern_2; // signal number 2
//--- if the model 3 is used, search for the "double divergence" signal
if(IS_PATTERN_USAGE(3) && CompareMaps(0x11,2)) // 00010001b
return(m_pattern_3); // signal number 3
}
}
//--- return the result
return(result);
}
//+------------------------------------------------------------------+
//| "Voting" that price will fall. |
//+------------------------------------------------------------------+
int CSignalDeM::ShortCondition(void)
{
int result=0;
int idx =StartIndex();
//--- check direction of the main line
if(DiffDeM(idx)<0.0)
{
//--- the oscillator is directed downwards confirming the possibility of falling of price
if(IS_PATTERN_USAGE(0))
result=m_pattern_0; // "confirming" signal number 0
//--- if the model 1 is used, search for a reverse of the oscillator downwards behind the level of overbuying
if(IS_PATTERN_USAGE(1) && DiffDeM(idx+1)>0.0 && DeM(idx+1)>0.7)
result=m_pattern_1; // signal number 1
//--- if the model 2 or 3 is used, perform the extended analysis of the oscillator state
if(IS_PATTERN_USAGE(2) || IS_PATTERN_USAGE(3))
{
ExtStateDeM(idx);
//--- if the model 2 is used, search for the "divergence" signal
if(IS_PATTERN_USAGE(2) && CompareMaps(1,1)) // 00000001b
result=m_pattern_2; // signal number 2
//--- if the model 3 is used, search for the "double divergence" signal
if(IS_PATTERN_USAGE(3) && CompareMaps(0x11,2)) // 00010001b
return(m_pattern_3); // signal number 3
}
}
//--- return the result
return(result);
}
//+------------------------------------------------------------------+
+193
View File
@@ -0,0 +1,193 @@
//+------------------------------------------------------------------+
//| SignalEnvelopes.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Expert\ExpertSignal.mqh>
// wizard description start
//+------------------------------------------------------------------+
//| Description of the class |
//| Title=Signals of indicator 'Envelopes' |
//| Type=SignalAdvanced |
//| Name=Envelopes |
//| ShortName=Envelopes |
//| Class=CSignalEnvelopes |
//| Page=signal_envelopes |
//| Parameter=PeriodMA,int,45,Period of averaging |
//| Parameter=Shift,int,0,Time shift |
//| Parameter=Method,ENUM_MA_METHOD,MODE_SMA,Method of averaging |
//| Parameter=Applied,ENUM_APPLIED_PRICE,PRICE_CLOSE,Prices series |
//| Parameter=Deviation,double,0.15,Deviation |
//+------------------------------------------------------------------+
// wizard description end
//+------------------------------------------------------------------+
//| Class CSignalEnvelopes. |
//| Purpose: Class of generator of trade signals based on |
//| the 'Envelopes' indicator. |
//| Is derived from the CExpertSignal class. |
//+------------------------------------------------------------------+
class CSignalEnvelopes : public CExpertSignal
{
protected:
CiEnvelopes m_env; // object-indicator
//--- adjusted parameters
int m_ma_period; // the "period of averaging" parameter of the indicator
int m_ma_shift; // the "time shift" parameter of the indicator
ENUM_MA_METHOD m_ma_method; // the "method of averaging" parameter of the indicator
ENUM_APPLIED_PRICE m_ma_applied; // the "object of averaging" parameter of the indicator
double m_deviation; // the "deviation" parameter of the indicator
double m_limit_in; // threshold sensitivity of the 'rollback zone'
double m_limit_out; // threshold sensitivity of the 'break through zone'
//--- "weights" of market models (0-100)
int m_pattern_0; // model 0 "price is near the necessary border of the envelope"
int m_pattern_1; // model 1 "price crossed a border of the envelope"
public:
CSignalEnvelopes(void);
~CSignalEnvelopes(void);
//--- methods of setting adjustable parameters
void PeriodMA(int value) { m_ma_period=value; }
void Shift(int value) { m_ma_shift=value; }
void Method(ENUM_MA_METHOD value) { m_ma_method=value; }
void Applied(ENUM_APPLIED_PRICE value) { m_ma_applied=value; }
void Deviation(double value) { m_deviation=value; }
void LimitIn(double value) { m_limit_in=value; }
void LimitOut(double value) { m_limit_out=value; }
//--- methods of adjusting "weights" of market models
void Pattern_0(int value) { m_pattern_0=value; }
void Pattern_1(int value) { m_pattern_1=value; }
//--- method of verification of settings
virtual bool ValidationSettings(void);
//--- method of creating the indicator and timeseries
virtual bool InitIndicators(CIndicators *indicators);
//--- methods of checking if the market models are formed
virtual int LongCondition(void);
virtual int ShortCondition(void);
protected:
//--- method of initialization of the indicator
bool InitMA(CIndicators *indicators);
//--- methods of getting data
double Upper(int ind) { return(m_env.Upper(ind)); }
double Lower(int ind) { return(m_env.Lower(ind)); }
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CSignalEnvelopes::CSignalEnvelopes(void) : m_ma_period(45),
m_ma_shift(0),
m_ma_method(MODE_SMA),
m_ma_applied(PRICE_CLOSE),
m_deviation(0.15),
m_limit_in(0.2),
m_limit_out(0.2),
m_pattern_0(90),
m_pattern_1(70)
{
//--- initialization of protected data
m_used_series=USE_SERIES_OPEN+USE_SERIES_HIGH+USE_SERIES_LOW+USE_SERIES_CLOSE;
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CSignalEnvelopes::~CSignalEnvelopes(void)
{
}
//+------------------------------------------------------------------+
//| Validation settings protected data. |
//+------------------------------------------------------------------+
bool CSignalEnvelopes::ValidationSettings(void)
{
//--- validation settings of additional filters
if(!CExpertSignal::ValidationSettings())
return(false);
//--- initial data checks
if(m_ma_period<=0)
{
printf(__FUNCTION__+": period MA must be greater than 0");
return(false);
}
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Create indicators. |
//+------------------------------------------------------------------+
bool CSignalEnvelopes::InitIndicators(CIndicators *indicators)
{
//--- check pointer
if(indicators==NULL)
return(false);
//--- initialization of indicators and timeseries of additional filters
if(!CExpertSignal::InitIndicators(indicators))
return(false);
//--- create and initialize MA indicator
if(!InitMA(indicators))
return(false);
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Initialize MA indicators. |
//+------------------------------------------------------------------+
bool CSignalEnvelopes::InitMA(CIndicators *indicators)
{
//--- check pointer
if(indicators==NULL)
return(false);
//--- add object to collection
if(!indicators.Add(GetPointer(m_env)))
{
printf(__FUNCTION__+": error adding object");
return(false);
}
//--- initialize object
if(!m_env.Create(m_symbol.Name(),m_period,m_ma_period,m_ma_shift,m_ma_method,m_ma_applied,m_deviation))
{
printf(__FUNCTION__+": error initializing object");
return(false);
}
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| "Voting" that price will grow. |
//+------------------------------------------------------------------+
int CSignalEnvelopes::LongCondition(void)
{
int result=0;
int idx =StartIndex();
double close=Close(idx);
double upper=Upper(idx);
double lower=Lower(idx);
double width=upper-lower;
//--- if the model 0 is used and price is in the rollback zone, then there is a condition for buying
if(IS_PATTERN_USAGE(0) && close<lower+m_limit_in*width && close>lower-m_limit_out*width)
result=m_pattern_0;
//--- if the model 1 is used and price is above the rollback zone, then there is a condition for buying
if(IS_PATTERN_USAGE(1) && close>upper+m_limit_out*width)
result=m_pattern_1;
//--- return the result
return(result);
}
//+------------------------------------------------------------------+
//| "Voting" that price will fall. |
//+------------------------------------------------------------------+
int CSignalEnvelopes::ShortCondition(void)
{
int result =0;
int idx =StartIndex();
double close=Close(idx);
double upper=Upper(idx);
double lower=Lower(idx);
double width=upper-lower;
//--- if the model 0 is used and price is in the rollback zone, then there is a condition for selling
if(IS_PATTERN_USAGE(0) && close>upper-m_limit_in*width && close<upper+m_limit_out*width)
result=m_pattern_0;
//--- if the model 1 is used and price is above the rollback zone, then there is a condition for selling
if(IS_PATTERN_USAGE(1) && close<lower-m_limit_out*width)
result=m_pattern_1;
//--- return the result
return(result);
}
//+------------------------------------------------------------------+
+257
View File
@@ -0,0 +1,257 @@
//+------------------------------------------------------------------+
//| SignalFrAMA.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Expert\ExpertSignal.mqh>
// wizard description start
//+------------------------------------------------------------------+
//| Description of the class |
//| Title=Signals of indicator 'Fractal Adaptive Moving Average' |
//| Type=SignalAdvanced |
//| Name=Fractal Adaptive Moving Average |
//| ShortName=FraMA |
//| Class=CSignalFrAMA |
//| Page=signal_frama |
//| Parameter=PeriodMA,int,12,Period of averaging |
//| Parameter=Shift,int,0,Time shift |
//| Parameter=Applied,ENUM_APPLIED_PRICE,PRICE_CLOSE,Prices series |
//+------------------------------------------------------------------+
// wizard description end
//+------------------------------------------------------------------+
//| Class CSignalFrAMA. |
//| Purpose: Class of generator of trade signals based on |
//| the 'Fractal Adaptive Moving Average' indicator. |
//| Is derived from the CExpertSignal class. |
//+------------------------------------------------------------------+
class CSignalFrAMA : public CExpertSignal
{
protected:
CiFrAMA m_ma; // object-indicator
//--- adjusted parameters
int m_ma_period; // the "period of averaging" parameter of the indicator
int m_ma_shift; // the "time shift" parameter of the indicator
ENUM_APPLIED_PRICE m_ma_applied; // the "object of averaging" parameter" of the indicator
//--- "weights" of market models (0-100)
int m_pattern_0; // model 0 "price is on the necessary side from the indicator"
int m_pattern_1; // model 1 "price crossed the indicator with opposite direction"
int m_pattern_2; // model 2 "price crossed the indicator with the same direction"
int m_pattern_3; // model 3 "piercing"
public:
CSignalFrAMA(void);
~CSignalFrAMA(void);
//--- methods of setting adjustable parameters
void PeriodMA(int value) { m_ma_period=value; }
void Shift(int value) { m_ma_shift=value; }
void Applied(ENUM_APPLIED_PRICE value) { m_ma_applied=value; }
//--- methods of adjusting "weights" of market models
void Pattern_0(int value) { m_pattern_0=value; }
void Pattern_1(int value) { m_pattern_1=value; }
void Pattern_2(int value) { m_pattern_2=value; }
void Pattern_3(int value) { m_pattern_3=value; }
//--- method of verification of settings
virtual bool ValidationSettings(void);
//--- method of creating the indicator and timeseries
virtual bool InitIndicators(CIndicators *indicators);
//--- methods of checking if the market models are formed
virtual int LongCondition(void);
virtual int ShortCondition(void);
protected:
//--- method of initialization of the indicator
bool InitMA(CIndicators *indicators);
//--- methods of getting data
double MA(int ind) { return(m_ma.Main(ind)); }
double DiffMA(int ind) { return(MA(ind)-MA(ind+1)); }
double DiffOpenMA(int ind) { return(Open(ind)-MA(ind)); }
double DiffHighMA(int ind) { return(High(ind)-MA(ind)); }
double DiffLowMA(int ind) { return(Low(ind)-MA(ind)); }
double DiffCloseMA(int ind) { return(Close(ind)-MA(ind)); }
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CSignalFrAMA::CSignalFrAMA(void) : m_ma_period(12),
m_ma_shift(0),
m_ma_applied(PRICE_CLOSE),
m_pattern_0(90),
m_pattern_1(100),
m_pattern_2(80),
m_pattern_3(60)
{
//--- initialization of protected data
m_used_series=USE_SERIES_OPEN+USE_SERIES_HIGH+USE_SERIES_LOW+USE_SERIES_CLOSE;
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CSignalFrAMA::~CSignalFrAMA(void)
{
}
//+------------------------------------------------------------------+
//| Validation settings protected data. |
//+------------------------------------------------------------------+
bool CSignalFrAMA::ValidationSettings(void)
{
//--- call of the method of the parent class
if(!CExpertSignal::ValidationSettings())
return(false);
//--- initial data checks
if(m_ma_period<=0)
{
printf(__FUNCTION__+": period MA must be greater than 0");
return(false);
}
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Create indicators. |
//+------------------------------------------------------------------+
bool CSignalFrAMA::InitIndicators(CIndicators *indicators)
{
//--- check pointer
if(indicators==NULL)
return(false);
//--- initialization of indicators and timeseries of additional filters
if(!CExpertSignal::InitIndicators(indicators))
return(false);
//--- create and initialize FrAMA indicator
if(!InitMA(indicators))
return(false);
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Create MA indicators. |
//+------------------------------------------------------------------+
bool CSignalFrAMA::InitMA(CIndicators *indicators)
{
//--- check pointer
if(indicators==NULL)
return(false);
//--- add indicator to collection
if(!indicators.Add(GetPointer(m_ma)))
{
printf(__FUNCTION__+": error adding object");
return(false);
}
//--- initialize indicator
if(!m_ma.Create(m_symbol.Name(),m_period,m_ma_period,m_ma_shift,m_ma_applied))
{
printf(__FUNCTION__+": error initializing object");
return(false);
}
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| "Voting" that price will grow. |
//+------------------------------------------------------------------+
int CSignalFrAMA::LongCondition(void)
{
int result=0;
int idx =StartIndex();
//--- analyze positional relationship of the close price and the indicator at the first analyzed bar
if(DiffCloseMA(idx)<0.0)
{
//--- the close price is below the indicator
if(IS_PATTERN_USAGE(1) && DiffOpenMA(idx)>0.0 && DiffMA(idx)>0.0)
{
//--- the open price is above the indicator (i.e. there was an intersection), but the indicator is directed upwards
result=m_pattern_1;
//--- consider that this is an unformed "piercing" and suggest to enter the market at the current price
m_base_price=0.0;
}
}
else
{
//--- the close price is above the indicator (the indicator has no objections to buying)
if(IS_PATTERN_USAGE(0))
result=m_pattern_0;
//--- if the indicator is directed upwards
if(DiffMA(idx)>0.0)
{
if(DiffOpenMA(idx)<0.0)
{
//--- if the model 2 is used
if(IS_PATTERN_USAGE(2))
{
//--- the open price is below the indicator (i.e. there was an intersection)
result=m_pattern_2;
//--- suggest to enter the market at the "roll back"
m_base_price=m_symbol.NormalizePrice(MA(idx));
}
}
else
{
//--- if the model 3 is used and the open price is above the indicator
if(IS_PATTERN_USAGE(3) && DiffLowMA(idx)<0.0)
{
//--- the low price is below the indicator
result=m_pattern_3;
//--- consider that this is a formed "piercing" and suggest to enter the market at the current price
m_base_price=0.0;
}
}
}
}
//--- return the result
return(result);
}
//+------------------------------------------------------------------+
//| "Voting" that price will fall. |
//+------------------------------------------------------------------+
int CSignalFrAMA::ShortCondition(void)
{
int result=0;
int idx =StartIndex();
//--- analyze positional relationship of the close price and the indicator at the first analyzed bar
if(DiffCloseMA(idx)>0.0)
{
//--- the close price is above the indicator
if(IS_PATTERN_USAGE(1) && DiffOpenMA(idx)<0.0 && DiffMA(idx)<0.0)
{
//--- the open price is below the indicator (i.e. there was an intersection), but the indicator is directed downwards
result=m_pattern_1;
//--- consider that this is an unformed "piercing" and suggest to enter the market at the current price
m_base_price=0.0;
}
}
else
{
//--- the close price is below the indicator (the indicator has no objections to buying)
if(IS_PATTERN_USAGE(0))
result=m_pattern_0;
//--- the indicator is directed downwards
if(DiffMA(idx)<0.0)
{
if(DiffOpenMA(idx)>0.0)
{
//--- if the model 2 is used
if(IS_PATTERN_USAGE(2))
{
//--- the open price is above the indicator (i.e. there was an intersection)
result=m_pattern_2;
//--- suggest to enter the market at the "roll back"
m_base_price=m_symbol.NormalizePrice(MA(idx));
}
}
else
{
//--- if the model 3 is used and the open price is below the indicator
if(IS_PATTERN_USAGE(3) && DiffHighMA(idx)>0.0)
{
//--- the high price is above the indicator
result=m_pattern_3;
//--- consider that this is a formed "piercing" and suggest to enter the market at the current price
m_base_price=0.0;
}
}
}
}
//--- return the result
return(result);
}
//+------------------------------------------------------------------+
+91
View File
@@ -0,0 +1,91 @@
//+------------------------------------------------------------------+
//| SignalITF.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Expert\ExpertSignal.mqh>
// wizard description start
//+------------------------------------------------------------------+
//| Description of the class |
//| Title=Signals of intraday time filter |
//| Type=SignalAdvanced |
//| Name=IntradayTimeFilter |
//| ShortName=ITF |
//| Class=CSignalITF |
//| Page=signal_time_filter |
//| Parameter=GoodHourOfDay,int,-1,Good hour |
//| Parameter=BadHoursOfDay,int,0,Bad hours (bit-map) |
//| Parameter=GoodDayOfWeek,int,-1,Good day of week |
//| Parameter=BadDaysOfWeek,int,0,Bad days of week (bit-map) |
//+------------------------------------------------------------------+
// wizard description end
//+------------------------------------------------------------------+
//| Class CSignalITF. |
//| Appointment: Class trading signals time filter. |
//| Derives from class CExpertSignal. |
//+------------------------------------------------------------------+
class CSignalITF : public CExpertSignal
{
protected:
//--- input parameters
int m_good_minute_of_hour;
long m_bad_minutes_of_hour;
int m_good_hour_of_day;
int m_bad_hours_of_day;
int m_good_day_of_week;
int m_bad_days_of_week;
public:
CSignalITF(void);
~CSignalITF(void);
//--- methods initialize protected data
void GoodMinuteOfHour(int value) { m_good_minute_of_hour=value; }
void BadMinutesOfHour(long value) { m_bad_minutes_of_hour=value; }
void GoodHourOfDay(int value) { m_good_hour_of_day=value; }
void BadHoursOfDay(int value) { m_bad_hours_of_day=value; }
void GoodDayOfWeek(int value) { m_good_day_of_week=value; }
void BadDaysOfWeek(int value) { m_bad_days_of_week=value; }
//--- methods of checking conditions of entering the market
virtual double Direction(void);
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CSignalITF::CSignalITF(void) : m_good_minute_of_hour(-1),
m_bad_minutes_of_hour(0),
m_good_hour_of_day(-1),
m_bad_hours_of_day(0),
m_good_day_of_week(-1),
m_bad_days_of_week(0)
{
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CSignalITF::~CSignalITF(void)
{
}
//+------------------------------------------------------------------+
//| Check conditions for time filter. |
//+------------------------------------------------------------------+
double CSignalITF::Direction(void)
{
MqlDateTime s_time;
//---
TimeCurrent(s_time);
//--- check days conditions
if(!((m_good_day_of_week==-1 || m_good_day_of_week==s_time.day_of_week) &&
!(m_bad_days_of_week&(1<<s_time.day_of_week))))
return(EMPTY_VALUE);
//--- check hours conditions
if(!((m_good_hour_of_day==-1 || m_good_hour_of_day==s_time.hour) &&
!(m_bad_hours_of_day&(1<<s_time.hour))))
return(EMPTY_VALUE);
//--- check minutes conditions
if(!((m_good_minute_of_hour==-1 || m_good_minute_of_hour==s_time.min) &&
!(m_bad_minutes_of_hour&(1<<s_time.min))))
return(EMPTY_VALUE);
//--- condition OK
return(0.0);
}
//+------------------------------------------------------------------+
+261
View File
@@ -0,0 +1,261 @@
//+------------------------------------------------------------------+
//| SignalMA.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Expert\ExpertSignal.mqh>
// wizard description start
//+------------------------------------------------------------------+
//| Description of the class |
//| Title=Signals of indicator 'Moving Average' |
//| Type=SignalAdvanced |
//| Name=Moving Average |
//| ShortName=MA |
//| Class=CSignalMA |
//| Page=signal_ma |
//| Parameter=PeriodMA,int,12,Period of averaging |
//| Parameter=Shift,int,0,Time shift |
//| Parameter=Method,ENUM_MA_METHOD,MODE_SMA,Method of averaging |
//| Parameter=Applied,ENUM_APPLIED_PRICE,PRICE_CLOSE,Prices series |
//+------------------------------------------------------------------+
// wizard description end
//+------------------------------------------------------------------+
//| Class CSignalMA. |
//| Purpose: Class of generator of trade signals based on |
//| the 'Moving Average' indicator. |
//| Is derived from the CExpertSignal class. |
//+------------------------------------------------------------------+
class CSignalMA : public CExpertSignal
{
protected:
CiMA m_ma; // object-indicator
//--- adjusted parameters
int m_ma_period; // the "period of averaging" parameter of the indicator
int m_ma_shift; // the "time shift" parameter of the indicator
ENUM_MA_METHOD m_ma_method; // the "method of averaging" parameter of the indicator
ENUM_APPLIED_PRICE m_ma_applied; // the "object of averaging" parameter of the indicator
//--- "weights" of market models (0-100)
int m_pattern_0; // model 0 "price is on the necessary side from the indicator"
int m_pattern_1; // model 1 "price crossed the indicator with opposite direction"
int m_pattern_2; // model 2 "price crossed the indicator with the same direction"
int m_pattern_3; // model 3 "piercing"
public:
CSignalMA(void);
~CSignalMA(void);
//--- methods of setting adjustable parameters
void PeriodMA(int value) { m_ma_period=value; }
void Shift(int value) { m_ma_shift=value; }
void Method(ENUM_MA_METHOD value) { m_ma_method=value; }
void Applied(ENUM_APPLIED_PRICE value) { m_ma_applied=value; }
//--- methods of adjusting "weights" of market models
void Pattern_0(int value) { m_pattern_0=value; }
void Pattern_1(int value) { m_pattern_1=value; }
void Pattern_2(int value) { m_pattern_2=value; }
void Pattern_3(int value) { m_pattern_3=value; }
//--- method of verification of settings
virtual bool ValidationSettings(void);
//--- method of creating the indicator and timeseries
virtual bool InitIndicators(CIndicators *indicators);
//--- methods of checking if the market models are formed
virtual int LongCondition(void);
virtual int ShortCondition(void);
protected:
//--- method of initialization of the indicator
bool InitMA(CIndicators *indicators);
//--- methods of getting data
double MA(int ind) { return(m_ma.Main(ind)); }
double DiffMA(int ind) { return(MA(ind)-MA(ind+1)); }
double DiffOpenMA(int ind) { return(Open(ind)-MA(ind)); }
double DiffHighMA(int ind) { return(High(ind)-MA(ind)); }
double DiffLowMA(int ind) { return(Low(ind)-MA(ind)); }
double DiffCloseMA(int ind) { return(Close(ind)-MA(ind)); }
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CSignalMA::CSignalMA(void) : m_ma_period(12),
m_ma_shift(0),
m_ma_method(MODE_SMA),
m_ma_applied(PRICE_CLOSE),
m_pattern_0(80),
m_pattern_1(10),
m_pattern_2(60),
m_pattern_3(60)
{
//--- initialization of protected data
m_used_series=USE_SERIES_OPEN+USE_SERIES_HIGH+USE_SERIES_LOW+USE_SERIES_CLOSE;
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CSignalMA::~CSignalMA(void)
{
}
//+------------------------------------------------------------------+
//| Validation settings protected data. |
//+------------------------------------------------------------------+
bool CSignalMA::ValidationSettings(void)
{
//--- validation settings of additional filters
if(!CExpertSignal::ValidationSettings())
return(false);
//--- initial data checks
if(m_ma_period<=0)
{
printf(__FUNCTION__+": period MA must be greater than 0");
return(false);
}
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Create indicators. |
//+------------------------------------------------------------------+
bool CSignalMA::InitIndicators(CIndicators *indicators)
{
//--- check pointer
if(indicators==NULL)
return(false);
//--- initialization of indicators and timeseries of additional filters
if(!CExpertSignal::InitIndicators(indicators))
return(false);
//--- create and initialize MA indicator
if(!InitMA(indicators))
return(false);
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Initialize MA indicators. |
//+------------------------------------------------------------------+
bool CSignalMA::InitMA(CIndicators *indicators)
{
//--- check pointer
if(indicators==NULL)
return(false);
//--- add object to collection
if(!indicators.Add(GetPointer(m_ma)))
{
printf(__FUNCTION__+": error adding object");
return(false);
}
//--- initialize object
if(!m_ma.Create(m_symbol.Name(),m_period,m_ma_period,m_ma_shift,m_ma_method,m_ma_applied))
{
printf(__FUNCTION__+": error initializing object");
return(false);
}
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| "Voting" that price will grow. |
//+------------------------------------------------------------------+
int CSignalMA::LongCondition(void)
{
int result=0;
int idx =StartIndex();
//--- analyze positional relationship of the close price and the indicator at the first analyzed bar
if(DiffCloseMA(idx)<0.0)
{
//--- the close price is below the indicator
if(IS_PATTERN_USAGE(1) && DiffOpenMA(idx)>0.0 && DiffMA(idx)>0.0)
{
//--- the open price is above the indicator (i.e. there was an intersection), but the indicator is directed upwards
result=m_pattern_1;
//--- consider that this is an unformed "piercing" and suggest to enter the market at the current price
m_base_price=0.0;
}
}
else
{
//--- the close price is above the indicator (the indicator has no objections to buying)
if(IS_PATTERN_USAGE(0))
result=m_pattern_0;
//--- if the indicator is directed upwards
if(DiffMA(idx)>0.0)
{
if(DiffOpenMA(idx)<0.0)
{
//--- if the model 2 is used
if(IS_PATTERN_USAGE(2))
{
//--- the open price is below the indicator (i.e. there was an intersection)
result=m_pattern_2;
//--- suggest to enter the market at the "roll back"
m_base_price=m_symbol.NormalizePrice(MA(idx));
}
}
else
{
//--- if the model 3 is used and the open price is above the indicator
if(IS_PATTERN_USAGE(3) && DiffLowMA(idx)<0.0)
{
//--- the low price is below the indicator
result=m_pattern_3;
//--- consider that this is a formed "piercing" and suggest to enter the market at the current price
m_base_price=0.0;
}
}
}
}
//--- return the result
return(result);
}
//+------------------------------------------------------------------+
//| "Voting" that price will fall. |
//+------------------------------------------------------------------+
int CSignalMA::ShortCondition(void)
{
int result=0;
int idx =StartIndex();
//--- analyze positional relationship of the close price and the indicator at the first analyzed bar
if(DiffCloseMA(idx)>0.0)
{
//--- the close price is above the indicator
if(IS_PATTERN_USAGE(1) && DiffOpenMA(idx)<0.0 && DiffMA(idx)<0.0)
{
//--- the open price is below the indicator (i.e. there was an intersection), but the indicator is directed downwards
result=m_pattern_1;
//--- consider that this is an unformed "piercing" and suggest to enter the market at the current price
m_base_price=0.0;
}
}
else
{
//--- the close price is below the indicator (the indicator has no objections to buying)
if(IS_PATTERN_USAGE(0))
result=m_pattern_0;
//--- the indicator is directed downwards
if(DiffMA(idx)<0.0)
{
if(DiffOpenMA(idx)>0.0)
{
//--- if the model 2 is used
if(IS_PATTERN_USAGE(2))
{
//--- the open price is above the indicator (i.e. there was an intersection)
result=m_pattern_2;
//--- suggest to enter the market at the "roll back"
m_base_price=m_symbol.NormalizePrice(MA(idx));
}
}
else
{
//--- if the model 3 is used and the open price is below the indicator
if(IS_PATTERN_USAGE(3) && DiffHighMA(idx)>0.0)
{
//--- the high price is above the indicator
result=m_pattern_3;
//--- consider that this is a formed "piercing" and suggest to enter the market at the current price
m_base_price=0.0;
}
}
}
}
//--- return the result
return(result);
}
//+------------------------------------------------------------------+
+408
View File
@@ -0,0 +1,408 @@
//+------------------------------------------------------------------+
//| SignalMACD.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Expert\ExpertSignal.mqh>
// wizard description start
//+------------------------------------------------------------------+
//| Description of the class |
//| Title=Signals of oscillator 'MACD' |
//| Type=SignalAdvanced |
//| Name=MACD |
//| ShortName=MACD |
//| Class=CSignalMACD |
//| Page=signal_macd |
//| Parameter=PeriodFast,int,12,Period of fast EMA |
//| Parameter=PeriodSlow,int,24,Period of slow EMA |
//| Parameter=PeriodSignal,int,9,Period of averaging of difference |
//| Parameter=Applied,ENUM_APPLIED_PRICE,PRICE_CLOSE,Prices series |
//+------------------------------------------------------------------+
// wizard description end
//+------------------------------------------------------------------+
//| Class CSignalMACD. |
//| Purpose: Class of generator of trade signals based on |
//| the 'Moving Average Convergence/Divergence' oscillator. |
//| Is derived from the CExpertSignal class. |
//+------------------------------------------------------------------+
class CSignalMACD : public CExpertSignal
{
protected:
CiMACD m_MACD; // object-oscillator
//--- adjusted parameters
int m_period_fast; // the "period of fast EMA" parameter of the oscillator
int m_period_slow; // the "period of slow EMA" parameter of the oscillator
int m_period_signal; // the "period of averaging of difference" parameter of the oscillator
ENUM_APPLIED_PRICE m_applied; // the "price series" parameter of the oscillator
//--- "weights" of market models (0-100)
int m_pattern_0; // model 0 "the oscillator has required direction"
int m_pattern_1; // model 1 "reverse of the oscillator to required direction"
int m_pattern_2; // model 2 "crossing of main and signal line"
int m_pattern_3; // model 3 "crossing of main line an the zero level"
int m_pattern_4; // model 4 "divergence of the oscillator and price"
int m_pattern_5; // model 5 "double divergence of the oscillator and price"
//--- variables
double m_extr_osc[10]; // array of values of extremums of the oscillator
double m_extr_pr[10]; // array of values of the corresponding extremums of price
int m_extr_pos[10]; // array of shifts of extremums (in bars)
uint m_extr_map; // resulting bit-map of ratio of extremums of the oscillator and the price
public:
CSignalMACD(void);
~CSignalMACD(void);
//--- methods of setting adjustable parameters
void PeriodFast(int value) { m_period_fast=value; }
void PeriodSlow(int value) { m_period_slow=value; }
void PeriodSignal(int value) { m_period_signal=value; }
void Applied(ENUM_APPLIED_PRICE value) { m_applied=value; }
//--- methods of adjusting "weights" of market models
void Pattern_0(int value) { m_pattern_0=value; }
void Pattern_1(int value) { m_pattern_1=value; }
void Pattern_2(int value) { m_pattern_2=value; }
void Pattern_3(int value) { m_pattern_3=value; }
void Pattern_4(int value) { m_pattern_4=value; }
void Pattern_5(int value) { m_pattern_5=value; }
//--- method of verification of settings
virtual bool ValidationSettings(void);
//--- method of creating the indicator and timeseries
virtual bool InitIndicators(CIndicators *indicators);
//--- methods of checking if the market models are formed
virtual int LongCondition(void);
virtual int ShortCondition(void);
protected:
//--- method of initialization of the oscillator
bool InitMACD(CIndicators *indicators);
//--- methods of getting data
double Main(int ind) { return(m_MACD.Main(ind)); }
double Signal(int ind) { return(m_MACD.Signal(ind)); }
double DiffMain(int ind) { return(Main(ind)-Main(ind+1)); }
int StateMain(int ind);
double State(int ind) { return(Main(ind)-Signal(ind)); }
bool ExtState(int ind);
bool CompareMaps(int map,int count,bool minimax=false,int start=0);
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CSignalMACD::CSignalMACD(void) : m_period_fast(12),
m_period_slow(24),
m_period_signal(9),
m_applied(PRICE_CLOSE),
m_pattern_0(10),
m_pattern_1(30),
m_pattern_2(80),
m_pattern_3(50),
m_pattern_4(60),
m_pattern_5(100)
{
//--- initialization of protected data
m_used_series=USE_SERIES_HIGH+USE_SERIES_LOW;
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CSignalMACD::~CSignalMACD(void)
{
}
//+------------------------------------------------------------------+
//| Validation settings protected data. |
//+------------------------------------------------------------------+
bool CSignalMACD::ValidationSettings(void)
{
//--- validation settings of additional filters
if(!CExpertSignal::ValidationSettings())
return(false);
//--- initial data checks
if(m_period_fast>=m_period_slow)
{
printf(__FUNCTION__+": slow period must be greater than fast period");
return(false);
}
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Create indicators. |
//+------------------------------------------------------------------+
bool CSignalMACD::InitIndicators(CIndicators *indicators)
{
//--- check of pointer is performed in the method of the parent class
//---
//--- initialization of indicators and timeseries of additional filters
if(!CExpertSignal::InitIndicators(indicators))
return(false);
//--- create and initialize MACD oscilator
if(!InitMACD(indicators))
return(false);
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Initialize MACD oscillators. |
//+------------------------------------------------------------------+
bool CSignalMACD::InitMACD(CIndicators *indicators)
{
//--- add object to collection
if(!indicators.Add(GetPointer(m_MACD)))
{
printf(__FUNCTION__+": error adding object");
return(false);
}
//--- initialize object
if(!m_MACD.Create(m_symbol.Name(),m_period,m_period_fast,m_period_slow,m_period_signal,m_applied))
{
printf(__FUNCTION__+": error initializing object");
return(false);
}
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Check of the oscillator state. |
//+------------------------------------------------------------------+
int CSignalMACD::StateMain(int ind)
{
int res=0;
double var;
//---
for(int i=ind;;i++)
{
if(Main(i+1)==EMPTY_VALUE)
break;
var=DiffMain(i);
if(res>0)
{
if(var<0)
break;
res++;
continue;
}
if(res<0)
{
if(var>0)
break;
res--;
continue;
}
if(var>0)
res++;
if(var<0)
res--;
}
//---
return(res);
}
//+------------------------------------------------------------------+
//| Extended check of the oscillator state consists |
//| in forming a bit-map according to certain rules, |
//| which shows ratios of extremums of the oscillator and price. |
//+------------------------------------------------------------------+
bool CSignalMACD::ExtState(int ind)
{
//--- operation of this method results in a bit-map of extremums
//--- practically, the bit-map of extremums is an "array" of 4-bit fields
//--- each "element of the array" definitely describes the ratio
//--- of current extremums of the oscillator and the price with previous ones
//--- purpose of bits of an element of the analyzed bit-map
//--- bit 3 - not used (always 0)
//--- bit 2 - is equal to 1 if the current extremum of the oscillator is "more extreme" than the previous one
//--- (a higher peak or a deeper valley), otherwise - 0
//--- bit 1 - not used (always 0)
//--- bit 0 - is equal to 1 if the current extremum of price is "more extreme" than the previous one
//--- (a higher peak or a deeper valley), otherwise - 0
//--- in addition to them, the following is formed:
//--- array of values of extremums of the oscillator,
//--- array of values of price extremums and
//--- array of "distances" between extremums of the oscillator (in bars)
//--- it should be noted that when using the results of the extended check of state,
//--- you should consider, which extremum of the oscillator (peak or valley)
//--- is the "reference point" (i.e. was detected first during the analysis)
//--- if a peak is detected first then even elements of all arrays
//--- will contain information about peaks, and odd elements will contain information about valleys
//--- if a valley is detected first, then respectively in reverse
int pos=ind,off,index;
uint map; // intermediate bit-map for one extremum
//---
m_extr_map=0;
for(int i=0;i<10;i++)
{
off=StateMain(pos);
if(off>0)
{
//--- minimum of the oscillator is detected
pos+=off;
m_extr_pos[i]=pos;
m_extr_osc[i]=Main(pos);
if(i>1)
{
m_extr_pr[i]=m_low.MinValue(pos-2,5,index);
//--- form the intermediate bit-map
map=0;
if(m_extr_pr[i-2]<m_extr_pr[i])
map+=1; // set bit 0
if(m_extr_osc[i-2]<m_extr_osc[i])
map+=4; // set bit 2
//--- add the result
m_extr_map+=map<<(4*(i-2));
}
else
m_extr_pr[i]=m_low.MinValue(pos-1,4,index);
}
else
{
//--- maximum of the oscillator is detected
pos-=off;
m_extr_pos[i]=pos;
m_extr_osc[i]=Main(pos);
if(i>1)
{
m_extr_pr[i]=m_high.MaxValue(pos-2,5,index);
//--- form the intermediate bit-map
map=0;
if(m_extr_pr[i-2]>m_extr_pr[i])
map+=1; // set bit 0
if(m_extr_osc[i-2]>m_extr_osc[i])
map+=4; // set bit 2
//--- add the result
m_extr_map+=map<<(4*(i-2));
}
else
m_extr_pr[i]=m_high.MaxValue(pos-1,4,index);
}
}
//---
return(true);
}
//+------------------------------------------------------------------+
//| Comparing the bit-map of extremums with pattern. |
//+------------------------------------------------------------------+
bool CSignalMACD::CompareMaps(int map,int count,bool minimax,int start)
{
int step =(minimax)?4:8;
int total=step*(start+count);
//--- check input parameters for a possible going out of range of the bit-map
if(total>32)
return(false);
//--- bit-map of the patter is an "array" of 4-bit fields
//--- each "element of the array" definitely describes the desired ratio
//--- of current extremums of the oscillator and the price with previous ones
//--- purpose of bits of an elements of the pattern of the bit-map pattern
//--- bit 3 - is equal to if the ratio of extremums of the oscillator is insignificant for us
//--- is equal to 0 if we want to "find" the ratio of extremums of the oscillator determined by the value of bit 2
//--- bit 2 - is equal to 1 if we want to "discover" the situation when the current extremum of the "oscillator" is "more extreme" than the previous one
//--- (current peak is higher or current valley is deeper)
//--- is equal to 0 if we want to "discover" the situation when the current extremum of the oscillator is "less extreme" than the previous one
//--- (current peak is lower or current valley is less deep)
//--- bit 1 - is equal to 1 if the ratio of extremums is insignificant for us
//--- it is equal to 0 if we want to "find" the ratio of price extremums determined by the value of bit 0
//--- bit 0 - is equal to 1 if we want to "discover" the situation when the current price extremum is "more extreme" than the previous one
//--- (current peak is higher or current valley is deeper)
//--- it is equal to 0 if we want to "discover" the situation when the current price extremum is "less extreme" than the previous one
//--- (current peak is lower or current valley is less deep)
uint inp_map,check_map;
int i,j;
//--- loop by extremums (4 minimums and 4 maximums)
//--- price and the oscillator are checked separately (thus, there are 16 checks)
for(i=step*start,j=0;i<total;i+=step,j+=4)
{
//--- "take" two bits - patter of the corresponding extremum of the price
inp_map=(map>>j)&3;
//--- if the higher-order bit=1, then any ratio is suitable for us
if(inp_map<2)
{
//--- "take" two bits of the corresponding extremum of the price (higher-order bit is always 0)
check_map=(m_extr_map>>i)&3;
if(inp_map!=check_map)
return(false);
}
//--- "take" two bits - pattern of the corresponding oscillator extremum
inp_map=(map>>(j+2))&3;
//--- if the higher-order bit=1, then any ratio is suitable for us
if(inp_map>=2)
continue;
//--- "take" two bits of the corresponding oscillator extremum (higher-order bit is always 0)
check_map=(m_extr_map>>(i+2))&3;
if(inp_map!=check_map)
return(false);
}
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| "Voting" that price will grow. |
//+------------------------------------------------------------------+
int CSignalMACD::LongCondition(void)
{
int result=0;
int idx =StartIndex();
//--- check direction of the main line
if(DiffMain(idx)>0.0)
{
//--- the main line is directed upwards, and it confirms the possibility of price growth
if(IS_PATTERN_USAGE(0))
result=m_pattern_0; // "confirming" signal number 0
//--- if the model 1 is used, look for a reverse of the main line
if(IS_PATTERN_USAGE(1) && DiffMain(idx+1)<0.0)
result=m_pattern_1; // signal number 1
//--- if the model 2 is used, look for an intersection of the main and signal line
if(IS_PATTERN_USAGE(2) && State(idx)>0.0 && State(idx+1)<0.0)
result=m_pattern_2; // signal number 2
//--- if the model 3 is used, look for an intersection of the main line and the zero level
if(IS_PATTERN_USAGE(3) && Main(idx)>0.0 && Main(idx+1)<0.0)
result=m_pattern_3; // signal number 3
//--- if the models 4 or 5 are used and the main line turned upwards below the zero level, look for divergences
if((IS_PATTERN_USAGE(4) || IS_PATTERN_USAGE(5)) && Main(idx)<0.0)
{
//--- perform the extended analysis of the oscillator state
ExtState(idx);
//--- if the model 4 is used, look for the "divergence" signal
if(IS_PATTERN_USAGE(4) && CompareMaps(1,1)) // 0000 0001b
result=m_pattern_4; // signal number 4
//--- if the model 5 is used, look for the "double divergence" signal
if(IS_PATTERN_USAGE(5) && CompareMaps(0x11,2)) // 0001 0001b
return(m_pattern_5); // signal number 5
}
}
//--- return the result
return(result);
}
//+------------------------------------------------------------------+
//| "Voting" that price will fall. |
//+------------------------------------------------------------------+
int CSignalMACD::ShortCondition(void)
{
int result=0;
int idx =StartIndex();
//--- check direction of the main line
if(DiffMain(idx)<0.0)
{
//--- main line is directed downwards, confirming a possibility of falling of price
if(IS_PATTERN_USAGE(0))
result=m_pattern_0; // "confirming" signal number 0
//--- if the model 1 is used, look for a reverse of the main line
if(IS_PATTERN_USAGE(1) && DiffMain(idx+1)>0.0)
result=m_pattern_1; // signal number 1
//--- if the model 2 is used, look for an intersection of the main and signal line
if(IS_PATTERN_USAGE(2) && State(idx)<0.0 && State(idx+1)>0.0)
result=m_pattern_2; // signal number 2
//--- if the model 3 is used, look for an intersection of the main line and the zero level
if(IS_PATTERN_USAGE(3) && Main(idx)<0.0 && Main(idx+1)>0.0)
result=m_pattern_3; // signal number 3
//--- if the models 4 or 5 are used and the main line turned downwards above the zero level, look for divergences
if((IS_PATTERN_USAGE(4) || IS_PATTERN_USAGE(5)) && Main(idx)>0.0)
{
//--- perform the extended analysis of the oscillator state
ExtState(idx);
//--- if the model 4 is used, look for the "divergence" signal
if(IS_PATTERN_USAGE(4) && CompareMaps(1,1)) // 0000 0001b
result=m_pattern_4; // signal number 4
//--- if the model 5 is used, look for the "double divergence" signal
if(IS_PATTERN_USAGE(5) && CompareMaps(0x11,2)) // 0001 0001b
return(m_pattern_5); // signal number 5
}
}
//--- return the result
return(result);
}
//+------------------------------------------------------------------+
+400
View File
@@ -0,0 +1,400 @@
//+------------------------------------------------------------------+
//| SignalRSI.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Expert\ExpertSignal.mqh>
// wizard description start
//+------------------------------------------------------------------+
//| Description of the class |
//| Title=Signals of oscillator 'Relative Strength Index' |
//| Type=SignalAdvanced |
//| Name=Relative Strength Index |
//| ShortName=RSI |
//| Class=CSignalRSI |
//| Page=signal_rsi |
//| Parameter=PeriodRSI,int,8,Period of calculation |
//| Parameter=Applied,ENUM_APPLIED_PRICE,PRICE_CLOSE,Prices series |
//+------------------------------------------------------------------+
// wizard description end
//+------------------------------------------------------------------+
//| Class CSignalRSI. |
//| Purpose: Class of generator of trade signals based on |
//| the 'Relative Strength Index' oscillator. |
//| Is derived from the CExpertSignal class. |
//+------------------------------------------------------------------+
class CSignalRSI : public CExpertSignal
{
protected:
CiRSI m_rsi; // object-oscillator
//--- adjusted parameters
int m_periodRSI; // the "period of calculation" parameter of the oscillator
ENUM_APPLIED_PRICE m_applied; // the "prices series" parameter of the oscillator
//--- "weights" of market models (0-100)
int m_pattern_0; // model 0 "the oscillator has required direction"
int m_pattern_1; // model 1 "reverse behind the level of overbuying/overselling"
int m_pattern_2; // model 2 "failed swing"
int m_pattern_3; // model 3 "divergence of the oscillator and price"
int m_pattern_4; // model 4 "double divergence of the oscillator and price"
int m_pattern_5; // model 5 "head/shoulders"
//--- variables
double m_extr_osc[10]; // array of values of extremums of the oscillator
double m_extr_pr[10]; // array of values of the corresponding extremums of price
int m_extr_pos[10]; // array of shifts of extremums (in bars)
uint m_extr_map; // resulting bit-map of ratio of extremums of the oscillator and the price
public:
CSignalRSI(void);
~CSignalRSI(void);
//--- methods of setting adjustable parameters
void PeriodRSI(int value) { m_periodRSI=value; }
void Applied(ENUM_APPLIED_PRICE value) { m_applied=value; }
//--- methods of adjusting "weights" of market models
void Pattern_0(int value) { m_pattern_0=value; }
void Pattern_1(int value) { m_pattern_1=value; }
void Pattern_2(int value) { m_pattern_2=value; }
void Pattern_3(int value) { m_pattern_3=value; }
void Pattern_4(int value) { m_pattern_4=value; }
void Pattern_5(int value) { m_pattern_5=value; }
//--- method of verification of settings
virtual bool ValidationSettings(void);
//--- method of creating the indicator and timeseries
virtual bool InitIndicators(CIndicators *indicators);
//--- methods of checking if the market models are formed
virtual int LongCondition(void);
virtual int ShortCondition(void);
protected:
//--- method of initialization of the oscillator
bool InitRSI(CIndicators *indicators);
//--- methods of getting data
double RSI(int ind) { return(m_rsi.Main(ind)); }
double DiffRSI(int ind) { return(RSI(ind)-RSI(ind+1)); }
int StateRSI(int ind);
bool ExtStateRSI(int ind);
bool CompareMaps(int map,int count,bool minimax=false,int start=0);
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CSignalRSI::CSignalRSI(void) : m_periodRSI(14),
m_applied(PRICE_CLOSE),
m_pattern_0(70),
m_pattern_1(100),
m_pattern_2(90),
m_pattern_3(80),
m_pattern_4(100),
m_pattern_5(20)
{
//--- initialization of protected data
m_used_series=USE_SERIES_HIGH+USE_SERIES_LOW;
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CSignalRSI::~CSignalRSI(void)
{
}
//+------------------------------------------------------------------+
//| Validation settings protected data. |
//+------------------------------------------------------------------+
bool CSignalRSI::ValidationSettings(void)
{
//--- validation settings of additional filters
if(!CExpertSignal::ValidationSettings())
return(false);
//--- initial data checks
if(m_periodRSI<=0)
{
printf(__FUNCTION__+": period of the RSI oscillator must be greater than 0");
return(false);
}
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Create indicators. |
//+------------------------------------------------------------------+
bool CSignalRSI::InitIndicators(CIndicators *indicators)
{
//--- check pointer
if(indicators==NULL)
return(false);
//--- initialization of indicators and timeseries of additional filters
if(!CExpertSignal::InitIndicators(indicators))
return(false);
//--- create and initialize RSI oscillator
if(!InitRSI(indicators))
return(false);
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Initialize RSI oscillators. |
//+------------------------------------------------------------------+
bool CSignalRSI::InitRSI(CIndicators *indicators)
{
//--- check pointer
if(indicators==NULL)
return(false);
//--- add object to collection
if(!indicators.Add(GetPointer(m_rsi)))
{
printf(__FUNCTION__+": error adding object");
return(false);
}
//--- initialize object
if(!m_rsi.Create(m_symbol.Name(),m_period,m_periodRSI,m_applied))
{
printf(__FUNCTION__+": error initializing object");
return(false);
}
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Check of the oscillator state. |
//+------------------------------------------------------------------+
int CSignalRSI::StateRSI(int ind)
{
int res=0;
double var;
//---
for(int i=ind;;i++)
{
if(RSI(i+1)==EMPTY_VALUE)
break;
var=DiffRSI(i);
if(res>0)
{
if(var<0)
break;
res++;
continue;
}
if(res<0)
{
if(var>0)
break;
res--;
continue;
}
if(var>0)
res++;
if(var<0)
res--;
}
//---
return(res);
}
//+------------------------------------------------------------------+
//| Extended check of the oscillator state consists |
//| in forming a bit-map according to certain rules, |
//| which shows ratios of extremums of the oscillator and price. |
//+------------------------------------------------------------------+
bool CSignalRSI::ExtStateRSI(int ind)
{
//--- operation of this method results in a bit-map of extremums
//--- practically, the bit-map of extremums is an "array" of 4-bit fields
//--- each "element of the array" definitely describes the ratio
//--- of current extremums of the oscillator and the price with previous ones
//--- purpose of bits of an element of the analyzed bit-map
//--- bit 3 - not used (always 0)
//--- bit 2 - is equal to 1 if the current extremum of the oscillator is "more extreme" than the previous one
//--- (a higher peak or a deeper valley), otherwise - 0
//--- bit 1 - not used (always 0)
//--- bit 0 - is equal to 1 if the current extremum of price is "more extreme" than the previous one
//--- (a higher peak or a deeper valley), otherwise - 0
//--- in addition to them, the following is formed:
//--- array of values of extremums of the oscillator,
//--- array of values of price extremums and
//--- array of "distances" between extremums of the oscillator (in bars)
//--- it should be noted that when using the results of the extended check of state,
//--- you should consider, which extremum of the oscillator (peak or valley)
//--- is the "reference point" (i.e. was detected first during the analysis)
//--- if a peak is detected first then even elements of all arrays
//--- will contain information about peaks, and odd elements will contain information about valleys
//--- if a valley is detected first, then respectively in reverse
int pos=ind,off,index;
uint map; // intermediate bit-map for one extremum
//---
m_extr_map=0;
for(int i=0;i<10;i++)
{
off=StateRSI(pos);
if(off>0)
{
//--- minimum of the oscillator is detected
pos+=off;
m_extr_pos[i]=pos;
m_extr_osc[i]=RSI(pos);
if(i>1)
{
m_extr_pr[i]=m_low.MinValue(pos-2,5,index);
//--- form the intermediate bit-map
map=0;
if(m_extr_pr[i-2]<m_extr_pr[i])
map+=1; // set bit 0
if(m_extr_osc[i-2]<m_extr_osc[i])
map+=4; // set bit 2
//--- add the result
m_extr_map+=map<<(4*(i-2));
}
else
m_extr_pr[i]=m_low.MinValue(pos-1,4,index);
}
else
{
//--- maximum of the oscillator is detected
pos-=off;
m_extr_pos[i]=pos;
m_extr_osc[i]=RSI(pos);
if(i>1)
{
m_extr_pr[i]=m_high.MaxValue(pos-2,5,index);
//--- form the intermediate bit-map
map=0;
if(m_extr_pr[i-2]>m_extr_pr[i])
map+=1; // set bit 0
if(m_extr_osc[i-2]>m_extr_osc[i])
map+=4; // set bit 2
//--- add the result
m_extr_map+=map<<(4*(i-2));
}
else
m_extr_pr[i]=m_high.MaxValue(pos-1,4,index);
}
}
//---
return(true);
}
//+------------------------------------------------------------------+
//| Comparing the bit-map of extremums with pattern. |
//+------------------------------------------------------------------+
bool CSignalRSI::CompareMaps(int map,int count,bool minimax,int start)
{
int step =(minimax)?4:8;
int total=step*(start+count);
//--- check input parameters for a possible going out of range of the bit-map
if(total>32)
return(false);
//--- bit-map of the patter is an "array" of 4-bit fields
//--- each "element of the array" definitely describes the desired ratio
//--- of current extremums of the oscillator and the price with previous ones
//--- purpose of bits of an elements of the pattern of the bit-map pattern
//--- bit 3 - is equal to if the ratio of extremums of the oscillator is insignificant for us
//--- is equal to 0 if we want to "find" the ratio of extremums of the oscillator determined by the value of bit 2
//--- bit 2 - is equal to 1 if we want to "discover" the situation when the current extremum of the "oscillator" is "more extreme" than the previous one
//--- (current peak is higher or current valley is deeper)
//--- is equal to 0 if we want to "discover" the situation when the current extremum of the oscillator is "less extreme" than the previous one
//--- (current peak is lower or current valley is less deep)
//--- bit 1 - is equal to 1 if the ratio of extremums is insignificant for us
//--- it is equal to 0 if we want to "find" the ratio of price extremums determined by the value of bit 0
//--- bit 0 - is equal to 1 if we want to "discover" the situation when the current price extremum is "more extreme" than the previous one
//--- (current peak is higher or current valley is deeper)
//--- it is equal to 0 if we want to "discover" the situation when the current price extremum is "less extreme" than the previous one
//--- (current peak is lower or current valley is less deep)
uint inp_map,check_map;
int i,j;
//--- loop by extremums (4 minimums and 4 maximums)
//--- price and the oscillator are checked separately (thus, there are 16 checks)
for(i=step*start,j=0;i<total;i+=step,j+=4)
{
//--- "take" two bits - patter of the corresponding extremum of the price
inp_map=(map>>j)&3;
//--- if the higher-order bit=1, then any ratio is suitable for us
if(inp_map<2)
{
//--- "take" two bits of the corresponding extremum of the price (higher-order bit is always 0)
check_map=(m_extr_map>>i)&3;
if(inp_map!=check_map)
return(false);
}
//--- "take" two bits - pattern of the corresponding oscillator extremum
inp_map=(map>>(j+2))&3;
//--- if the higher-order bit=1, then any ratio is suitable for us
if(inp_map>=2)
continue;
//--- "take" two bits of the corresponding oscillator extremum (higher-order bit is always 0)
check_map=(m_extr_map>>(i+2))&3;
if(inp_map!=check_map)
return(false);
}
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| "Voting" that price will grow. |
//+------------------------------------------------------------------+
int CSignalRSI::LongCondition(void)
{
int result=0;
int idx =StartIndex();
//---
if(DiffRSI(idx)>0.0)
{
//--- the oscillator is directed upwards confirming the possibility of price growth
if(IS_PATTERN_USAGE(0))
result=m_pattern_0; // "confirming" signal number 0
//--- if the model 1 is used, search for a reverse of the oscillator upwards behind the level of overselling
if(IS_PATTERN_USAGE(1) && DiffRSI(idx+1)<0.0 && RSI(idx+1)<30.0)
result=m_pattern_1; // signal number 1
//--- if the model 2, 3, 4 or 5 is used, perform the extended analysis of the oscillator state
if(IS_PATTERN_USAGE(2) || IS_PATTERN_USAGE(3) || IS_PATTERN_USAGE(4) || IS_PATTERN_USAGE(5))
{
ExtStateRSI(idx);
//--- search for the "failed swing" signal
if(IS_PATTERN_USAGE(2) && RSI(idx)>m_extr_osc[1])
result=m_pattern_2; // signal number 2
//--- search for the "divergence" signal
if(IS_PATTERN_USAGE(3) && CompareMaps(1,1)) // 0000 0001b
result=m_pattern_3; // signal number 3
//--- search for the "double divergence" signal
if(IS_PATTERN_USAGE(4) && CompareMaps(0x11,2)) // 0001 0001b
return(m_pattern_4); // signal number 4
//--- search for the "head/shoulders" signal
if(IS_PATTERN_USAGE(5) && CompareMaps(0x62662,5,true) && RSI(idx)>m_extr_osc[1]) // 01100010011001100010b
result=m_pattern_5; // signal number 5
}
}
//--- return the result
return(result);
}
//+------------------------------------------------------------------+
//| "Voting" that price will fall. |
//+------------------------------------------------------------------+
int CSignalRSI::ShortCondition(void)
{
int result=0;
int idx =StartIndex();
//---
if(DiffRSI(idx)<0.0)
{
//--- the oscillator is directed downwards confirming the possibility of falling of price
if(IS_PATTERN_USAGE(0))
result=m_pattern_0; // "confirming" signal number 0
//--- if the model 1 is used, search for a reverse of the oscillator downwards behind the level of overbuying
if(IS_PATTERN_USAGE(1) && DiffRSI(idx+1)>0.0 && RSI(idx+1)>70.0)
result=m_pattern_1; // signal number 1
//--- if the model 2, 3, 4 or 5 is used, perform the extended analysis of the oscillator state
if(IS_PATTERN_USAGE(2) || IS_PATTERN_USAGE(3) || IS_PATTERN_USAGE(4) || IS_PATTERN_USAGE(5))
{
ExtStateRSI(idx);
//--- search for the "failed swing" signal
if(IS_PATTERN_USAGE(2) && RSI(idx)<m_extr_osc[1])
result=m_pattern_2; // signal number 2
//--- search for the "divergence" signal
if(IS_PATTERN_USAGE(3) && CompareMaps(1,1)) // 0000 0001b
result=m_pattern_3; // signal number 3
//--- search for the "double divergence" signal
if(IS_PATTERN_USAGE(4) && CompareMaps(0x11,2)) // 0001 0001b
return(m_pattern_4); // signal number 4
//--- search for the "head/shoulders" signal
if(IS_PATTERN_USAGE(5) && CompareMaps(0x62662,5,true) && RSI(idx)<m_extr_osc[1]) // 01100010011001100010b
result=m_pattern_5; // signal number 5
}
}
//--- return the result
return(result);
}
//+------------------------------------------------------------------+
+180
View File
@@ -0,0 +1,180 @@
//+------------------------------------------------------------------+
//| SignalRVI.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Expert\ExpertSignal.mqh>
// wizard description start
//+------------------------------------------------------------------+
//| Description of the class |
//| Title=Signals of oscillator 'Relative Vigor Index' |
//| Type=SignalAdvanced |
//| Name=Relative Vigor Index |
//| ShortName=RVI |
//| Class=CSignalRVI |
//| Page=signal_rvi |
//| Parameter=PeriodRVI,int,10,Period of calculation |
//+------------------------------------------------------------------+
// wizard description end
//+------------------------------------------------------------------+
//| Class CSignalRVI. |
//| Purpose: Class of generator of trade signals based on |
//| the 'Relative Vigor Index' oscillator. |
//| Is derived from the CExpertSignal class. |
//+------------------------------------------------------------------+
class CSignalRVI : public CExpertSignal
{
protected:
CiRVI m_rvi; // object-oscillator
//--- adjusted parameters
int m_periodRVI; // the "period of calculation" parameter of the oscillator
//--- "weights" of market models (0-100)
int m_pattern_0; // model 0 "the oscillator has required direction"
int m_pattern_1; // model 1 "crossing of main and signal line"
public:
CSignalRVI(void);
~CSignalRVI(void);
//--- methods of setting adjustable parameters
void PeriodRVI(int value) { m_periodRVI=value; }
//--- methods of adjusting "weights" of market models
void Pattern_0(int value) { m_pattern_0=value; }
void Pattern_1(int value) { m_pattern_1=value; }
//--- method of verification of settings
virtual bool ValidationSettings(void);
//--- method of creating the indicator and timeseries
virtual bool InitIndicators(CIndicators *indicators);
//--- methods of checking if the market models are formed
virtual int LongCondition(void);
virtual int ShortCondition(void);
protected:
//--- method of initialization of the oscillator
bool InitRVI(CIndicators *indicators);
//--- methods of getting data
double Main(int ind) { return(m_rvi.Main(ind)); }
double DiffMain(int ind) { return(Main(ind)-Main(ind+1)); }
double Signal(int ind) { return(m_rvi.Signal(ind)); }
double DiffSignal(int ind) { return(Signal(ind)-Signal(ind+1)); }
double DiffMainSignal(int ind) { return(Main(ind)-Signal(ind)); }
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CSignalRVI::CSignalRVI(void) : m_periodRVI(10),
m_pattern_0(60),
m_pattern_1(100)
{
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CSignalRVI::~CSignalRVI(void)
{
}
//+------------------------------------------------------------------+
//| Validation settings protected data. |
//+------------------------------------------------------------------+
bool CSignalRVI::ValidationSettings(void)
{
//--- validation settings of additional filters
if(!CExpertSignal::ValidationSettings())
return(false);
//--- initial data checks
if(m_periodRVI<=0)
{
printf(__FUNCTION__+": the period of calculation of the RVI oscillator must be greater than 0");
return(false);
}
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Create indicators. |
//+------------------------------------------------------------------+
bool CSignalRVI::InitIndicators(CIndicators *indicators)
{
//--- check pointer
if(indicators==NULL)
return(false);
//--- initialization of indicators and timeseries of additional filters
if(!CExpertSignal::InitIndicators(indicators))
return(false);
//--- create and initialize RVI oscillator
if(!InitRVI(indicators))
return(false);
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Initialize RVI oscillators. |
//+------------------------------------------------------------------+
bool CSignalRVI::InitRVI(CIndicators *indicators)
{
//--- check pointer
if(indicators==NULL)
return(false);
//--- add object to collection
if(!indicators.Add(GetPointer(m_rvi)))
{
printf(__FUNCTION__+": error adding object");
return(false);
}
//--- initialize object
if(!m_rvi.Create(m_symbol.Name(),m_period,m_periodRVI))
{
printf(__FUNCTION__+": error initializing object");
return(false);
}
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| "Voting" that price will grow. |
//+------------------------------------------------------------------+
int CSignalRVI::LongCondition(void)
{
int result=0;
int idx =StartIndex();
//---
if(DiffMain(idx)>0.0)
{
//--- the main line of the oscillator is directed upwards confirming the possibility of price growth
if(IS_PATTERN_USAGE(0))
result=m_pattern_0; // "confirming" signal
//--- if the main line crosses the signal line upwards, this is a signal for buying
if(DiffMainSignal(idx)>0 && DiffMainSignal(idx+1)<0)
{
//--- the main line of the oscillator has crossed the signal line upwards (signal for buying)
if(IS_PATTERN_USAGE(1))
result=m_pattern_1; // signal number 1
}
}
//--- return the result
return(result);
}
//+------------------------------------------------------------------+
//| "Voting" that price will fall. |
//+------------------------------------------------------------------+
int CSignalRVI::ShortCondition(void)
{
int result=0;
int idx =StartIndex();
//---
if(DiffMain(idx)<0.0)
{
//--- the main line of the oscillator is directed downwards confirming the possibility of falling of price
if(IS_PATTERN_USAGE(0))
result=m_pattern_0; // "confirming" signal
//--- if the main line crosses the signal line from top downwards, this is a signal for selling
if(DiffMainSignal(idx)<0 && DiffMainSignal(idx+1)>0)
{
//--- the main line of the oscillator has crossed the signal line from top downwards (signal for selling)
if(IS_PATTERN_USAGE(1))
result=m_pattern_1; // signal number 1
}
}
//--- return the result
return(result);
}
//+------------------------------------------------------------------+
+168
View File
@@ -0,0 +1,168 @@
//+------------------------------------------------------------------+
//| SignalSAR.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Expert\ExpertSignal.mqh>
// wizard description start
//+------------------------------------------------------------------+
//| Description of the class |
//| Title=Signals of indicator 'Parabolic SAR' |
//| Type=SignalAdvanced |
//| Name=Parabolic SAR |
//| ShortName=SAR |
//| Class=CSignalSAR |
//| Page=signal_sar |
//| Parameter=Step,double,0.02,Speed increment |
//| Parameter=Maximum,double,0.2,Maximum rate |
//+------------------------------------------------------------------+
// wizard description end
//+------------------------------------------------------------------+
//| Class CSignalSAR. |
//| Purpose: Class of generator of trade signals based on |
//| the 'Parabolic SAR' indicator. |
//| Is derived from the CExpertSignal class. |
//+------------------------------------------------------------------+
class CSignalSAR : public CExpertSignal
{
protected:
CiSAR m_sar; // object-indicator
//--- adjusted parameters
double m_step; // the "speed increment" parameter of the indicator
double m_maximum; // the "maximum rate" parameter of the indicator
//--- "weights" of market models (0-100)
int m_pattern_0; // model 0 "the parabolic is on the necessary side from the price"
int m_pattern_1; // model 1 "the parabolic has 'switched'"
public:
CSignalSAR(void);
~CSignalSAR(void);
//--- methods of setting adjustable parameters
void Step(double value) { m_step=value; }
void Maximum(double value) { m_maximum=value; }
//--- methods of adjusting "weights" of market models
void Pattern_0(int value) { m_pattern_0=value; }
void Pattern_1(int value) { m_pattern_1=value; }
//--- method of verification of settings
virtual bool ValidationSettings(void);
//--- method of creating the indicator and timeseries
virtual bool InitIndicators(CIndicators *indicators);
//--- methods of checking if the market models are formed
virtual int LongCondition(void);
virtual int ShortCondition(void);
protected:
//--- method of initialization of the indicator
bool InitSAR(CIndicators *indicators);
//--- methods of getting data
double SAR(int ind) { return(m_sar.Main(ind)); }
double Close(int ind) { return(m_close.GetData(ind)); }
double DiffClose(int ind) { return(Close(ind)-SAR(ind)); }
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CSignalSAR::CSignalSAR(void) : m_step(0.02),
m_maximum(0.2),
m_pattern_0(40),
m_pattern_1(90)
{
//--- initialization of protected data
m_used_series=USE_SERIES_CLOSE;
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CSignalSAR::~CSignalSAR(void)
{
}
//+------------------------------------------------------------------+
//| Validation settings protected data. |
//+------------------------------------------------------------------+
bool CSignalSAR::ValidationSettings(void)
{
//--- call of the method of the parent class
if(!CExpertSignal::ValidationSettings())
return(false);
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Create indicators. |
//+------------------------------------------------------------------+
bool CSignalSAR::InitIndicators(CIndicators *indicators)
{
//--- check pointer
if(indicators==NULL)
return(false);
//--- initialization of indicators and timeseries of additional filters
if(!CExpertSignal::InitIndicators(indicators))
return(false);
//--- create and initialize SAR indicator
if(!InitSAR(indicators))
return(false);
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Create SAR indicators. |
//+------------------------------------------------------------------+
bool CSignalSAR::InitSAR(CIndicators *indicators)
{
//--- check pointer
if(indicators==NULL)
return(false);
//--- add object to collection
if(!indicators.Add(GetPointer(m_sar)))
{
printf(__FUNCTION__+": error adding object");
return(false);
}
//--- initialize object
if(!m_sar.Create(m_symbol.Name(),m_period,m_step,m_maximum))
{
printf(__FUNCTION__+": error initializing object");
return(false);
}
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| "Voting" that price will grow. |
//+------------------------------------------------------------------+
int CSignalSAR::LongCondition(void)
{
int result=0;
int idx =StartIndex();
//--- if the indicator is above the price at the first analyzed bar, don't 'vote' buying
if(DiffClose(idx++)<0.0)
return(result);
//--- the indicator is below the price at the first analyzed bar (the indicator has no objections to buying)
if(IS_PATTERN_USAGE(0))
result=m_pattern_0;
//--- if the indicator is above the price at the second analyzed bar, then there is a condition for buying
if(IS_PATTERN_USAGE(1) && DiffClose(idx)<0.0)
return(m_pattern_1);
//--- return the result
return(result);
}
//+------------------------------------------------------------------+
//| "Voting" that price will fall. |
//+------------------------------------------------------------------+
int CSignalSAR::ShortCondition(void)
{
int result=0;
int idx =StartIndex();
//--- if the indicator is below the price at the first analyzed bar, don't "vote" for selling
if(DiffClose(idx++)>0.0)
return(result);
//--- the indicator is above the price at the first analyzed bar (the indicator has no objections to selling)
if(IS_PATTERN_USAGE(0))
result=m_pattern_0;
//--- if the indicator is below the price at the second analyzed bar, then there is a condition for selling
if(IS_PATTERN_USAGE(1) && DiffClose(idx)>0.0)
return(m_pattern_1);
//--- return the result
return(result);
}
//+------------------------------------------------------------------+
+426
View File
@@ -0,0 +1,426 @@
//+------------------------------------------------------------------+
//| SignalStoch.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Expert\ExpertSignal.mqh>
// wizard description start
//+------------------------------------------------------------------+
//| Description of the class |
//| Title=Signals of oscillator 'Stochastic' |
//| Type=SignalAdvanced |
//| Name=Stochastic |
//| ShortName=Stoch |
//| Class=CSignalStoch |
//| Page=signal_stochastic |
//| Parameter=PeriodK,int,8,K-period |
//| Parameter=PeriodD,int,3,D-period |
//| Parameter=PeriodSlow,int,3,Period of slowing |
//| Parameter=Applied,ENUM_STO_PRICE,STO_LOWHIGH,Prices to apply to |
//+------------------------------------------------------------------+
// wizard description end
//+------------------------------------------------------------------+
//| Class CSignalStoch. |
//| Purpose: Class of generator of trade signals based on |
//| the 'Stochastic' oscillator. |
//| Is derived from the CExpertSignal class. |
//+------------------------------------------------------------------+
class CSignalStoch : public CExpertSignal
{
protected:
CiStochastic m_stoch; // object-oscillator
CPriceSeries *m_app_price_high; // pointer to the object-timeseries for determining divergences directed downwards
CPriceSeries *m_app_price_low; // pointer to the object-timeseries for determining divergences directed upwards
//--- adjusted parameters
int m_periodK; // the "period %K" parameter of the oscillator
int m_periodD; // the "period %D" parameter of the oscillator
int m_period_slow; // the "period of slowing" parameter of the oscillator
ENUM_STO_PRICE m_applied; // the "apply to" parameter of the oscillator
//--- "weights" of market models (0-100)
int m_pattern_0; // model 0 "the oscillator has required direction"
int m_pattern_1; // model 1 "reverse of the oscillator to required direction"
int m_pattern_2; // model 2 "crossing of main and signal line"
int m_pattern_3; // model 3 "divergence of the oscillator and price"
int m_pattern_4; // model 4 "double divergence of the oscillator and price"
//--- variables
double m_extr_osc[10]; // array of values of extremums of the oscillator
double m_extr_pr[10]; // array of values of the corresponding extremums of price
int m_extr_pos[10]; // array of shifts of extremums (in bars)
uint m_extr_map; // resulting bit-map of ratio of extremums of the oscillator and the price
public:
CSignalStoch(void);
~CSignalStoch(void);
//--- methods of setting adjustable parameters
void PeriodK(int value) { m_periodK=value; }
void PeriodD(int value) { m_periodD=value; }
void PeriodSlow(int value) { m_period_slow=value; }
void Applied(ENUM_STO_PRICE value) { m_applied=value; }
//--- methods of adjusting "weights" of market models
void Pattern_0(int value) { m_pattern_0=value; }
void Pattern_1(int value) { m_pattern_1=value; }
void Pattern_2(int value) { m_pattern_2=value; }
void Pattern_3(int value) { m_pattern_3=value; }
void Pattern_4(int value) { m_pattern_4=value; }
//--- method of verification of settings
virtual bool ValidationSettings(void);
//--- method of creating the indicator and timeseries
virtual bool InitIndicators(CIndicators *indicators);
//--- methods of checking if the market models are formed
virtual int LongCondition(void);
virtual int ShortCondition(void);
protected:
//--- method of initialization of the oscillator
bool InitStoch(CIndicators *indicators);
//--- methods of getting data
double Main(int ind) { return(m_stoch.Main(ind)); }
double DiffMain(int ind) { return(Main(ind)-Main(ind+1)); }
double Signal(int ind) { return(m_stoch.Signal(ind)); }
double DiffSignal(int ind) { return(Signal(ind)-Signal(ind+1)); }
double DiffMainSignal(int ind) { return(Main(ind)-Signal(ind)); }
int StateStoch(int ind);
bool ExtStateStoch(int ind);
bool CompareMaps(int map,int count,bool minimax=false,int start=0);
void DiverDebugPrint();
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CSignalStoch::CSignalStoch(void) : m_periodK(8),
m_periodD(3),
m_period_slow(3),
m_applied(STO_LOWHIGH),
m_pattern_0(30),
m_pattern_1(60),
m_pattern_2(50),
m_pattern_3(100),
m_pattern_4(90)
{
//--- initialization of protected data
m_used_series=USE_SERIES_OPEN+USE_SERIES_HIGH+USE_SERIES_LOW+USE_SERIES_CLOSE;
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CSignalStoch::~CSignalStoch(void)
{
}
//+------------------------------------------------------------------+
//| Validation settings protected data. |
//+------------------------------------------------------------------+
bool CSignalStoch::ValidationSettings(void)
{
//--- validation settings of additional filters
if(!CExpertSignal::ValidationSettings())
return(false);
//--- initial data checks
if(m_periodK<=0)
{
printf(__FUNCTION__+": the period %K of the Stochastic oscillator must be greater than 0");
return(false);
}
if(m_periodD<=0)
{
printf(__FUNCTION__+": the period %D of the Stochastic oscillator must be greater than 0");
return(false);
}
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Create indicators. |
//+------------------------------------------------------------------+
bool CSignalStoch::InitIndicators(CIndicators *indicators)
{
//--- check pointer
if(indicators==NULL)
return(false);
//--- initialization of indicators and timeseries of additional filters
if(!CExpertSignal::InitIndicators(indicators))
return(false);
//--- create and initialize Stochastic oscillator
if(!InitStoch(indicators))
return(false);
if(m_applied==STO_CLOSECLOSE)
{
//--- copying the Close timeseries
m_app_price_high=GetPointer(m_close);
//--- copying the Close timeseries
m_app_price_low=GetPointer(m_close);
}
else
{
//--- copying the High timeseries
m_app_price_high=GetPointer(m_high);
//--- copying the Low timeseries
m_app_price_low=GetPointer(m_low);
}
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Initialize Stochastic oscillators. |
//+------------------------------------------------------------------+
bool CSignalStoch::InitStoch(CIndicators *indicators)
{
//--- check pointer
if(indicators==NULL)
return(false);
//--- add object to collection
if(!indicators.Add(GetPointer(m_stoch)))
{
printf(__FUNCTION__+": error adding object");
return(false);
}
//--- initialize object
if(!m_stoch.Create(m_symbol.Name(),m_period,m_periodK,m_periodD,m_period_slow,MODE_SMA,m_applied))
{
printf(__FUNCTION__+": error initializing object");
return(false);
}
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Check of the oscillator state. |
//+------------------------------------------------------------------+
int CSignalStoch::StateStoch(int ind)
{
int res=0;
double var;
//---
for(int i=ind;;i++)
{
if(Main(i+1)==EMPTY_VALUE)
break;
var=DiffMain(i);
if(res>0)
{
if(var<0)
break;
res++;
continue;
}
if(res<0)
{
if(var>0)
break;
res--;
continue;
}
if(var>0)
res++;
if(var<0)
res--;
}
//---
return(res);
}
//+------------------------------------------------------------------+
//| Extended check of the oscillator state consists |
//| in forming a bit-map according to certain rules, |
//| which shows ratios of extremums of the oscillator and price. |
//+------------------------------------------------------------------+
bool CSignalStoch::ExtStateStoch(int ind)
{
//--- operation of this method results in a bit-map of extremums
//--- practically, the bit-map of extremums is an "array" of 4-bit fields
//--- each "element of the array" definitely describes the ratio
//--- of current extremums of the oscillator and the price with previous ones
//--- purpose of bits of an element of the analyzed bit-map
//--- bit 3 - not used (always 0)
//--- bit 2 - is equal to 1 if the current extremum of the oscillator is "more extreme" than the previous one
//--- (a higher peak or a deeper valley), otherwise - 0
//--- bit 1 - not used (always 0)
//--- bit 0 - is equal to 1 if the current extremum of price is "more extreme" than the previous one
//--- (a higher peak or a deeper valley), otherwise - 0
//--- in addition to them, the following is formed:
//--- array of values of extremums of the oscillator,
//--- array of values of price extremums and
//--- array of "distances" between extremums of the oscillator (in bars)
//--- it should be noted that when using the results of the extended check of state,
//--- you should consider, which extremum of the oscillator (peak or valley)
//--- is the "reference point" (i.e. was detected first during the analysis)
//--- if a peak is detected first then even elements of all arrays
//--- will contain information about peaks, and odd elements will contain information about valleys
//--- if a valley is detected first, then respectively in reverse
int pos=ind,off,index;
uint map; // intermediate bit-map for one extremum
//---
m_extr_map=0;
for(int i=0;i<10;i++)
{
off=StateStoch(pos);
if(off>0)
{
//--- minimum of the oscillator is detected
pos+=off;
m_extr_pos[i]=pos;
m_extr_osc[i]=Main(pos);
if(i>1)
{
m_extr_pr[i]=m_low.MinValue(pos-2,5,index);
//--- form the intermediate bit-map
map=0;
if(m_extr_pr[i-2]<m_extr_pr[i])
map+=1; // set bit 0
if(m_extr_osc[i-2]<m_extr_osc[i])
map+=4; // set bit 2
//--- add the result
m_extr_map+=map<<(4*(i-2));
}
else
m_extr_pr[i]=m_low.MinValue(pos-1,4,index);
}
else
{
//--- maximum of the oscillator is detected
pos-=off;
m_extr_pos[i]=pos;
m_extr_osc[i]=Main(pos);
if(i>1)
{
m_extr_pr[i]=m_high.MaxValue(pos-2,5,index);
//--- form the intermediate bit-map
map=0;
if(m_extr_pr[i-2]>m_extr_pr[i])
map+=1; // set bit 0
if(m_extr_osc[i-2]>m_extr_osc[i])
map+=4; // set bit 2
//--- add the result
m_extr_map+=map<<(4*(i-2));
}
else
m_extr_pr[i]=m_high.MaxValue(pos-1,4,index);
}
}
//---
return(true);
}
//+------------------------------------------------------------------+
//| Comparing the bit-map of extremums with pattern. |
//+------------------------------------------------------------------+
bool CSignalStoch::CompareMaps(int map,int count,bool minimax=false,int start=0)
{
int step =(minimax)?4:8;
int total=step*(start+count);
//--- check input parameters for a possible going out of range of the bit-map
if(total>32)
return(false);
//--- bit-map of the patter is an "array" of 4-bit fields
//--- each "element of the array" definitely describes the desired ratio
//--- of current extremums of the oscillator and the price with previous ones
//--- purpose of bits of an elements of the pattern of the bit-map pattern
//--- bit 3 - is equal to if the ratio of extremums of the oscillator is insignificant for us
//--- is equal to 0 if we want to "find" the ratio of extremums of the oscillator determined by the value of bit 2
//--- bit 2 - is equal to 1 if we want to "discover" the situation when the current extremum of the "oscillator" is "more extreme" than the previous one
//--- (current peak is higher or current valley is deeper)
//--- is equal to 0 if we want to "discover" the situation when the current extremum of the oscillator is "less extreme" than the previous one
//--- (current peak is lower or current valley is less deep)
//--- bit 1 - is equal to 1 if the ratio of extremums is insignificant for us
//--- it is equal to 0 if we want to "find" the ratio of price extremums determined by the value of bit 0
//--- bit 0 - is equal to 1 if we want to "discover" the situation when the current price extremum is "more extreme" than the previous one
//--- (current peak is higher or current valley is deeper)
//--- it is equal to 0 if we want to "discover" the situation when the current price extremum is "less extreme" than the previous one
//--- (current peak is lower or current valley is less deep)
uint inp_map,check_map;
int i,j;
//--- loop by extremums (4 minimums and 4 maximums)
//--- price and the oscillator are checked separately (thus, there are 16 checks)
for(i=step*start,j=0;i<total;i+=step,j+=4)
{
//--- "take" two bits - patter of the corresponding extremum of the price
inp_map=(map>>j)&3;
//--- if the higher-order bit=1, then any ratio is suitable for us
if(inp_map<2)
{
//--- "take" two bits of the corresponding extremum of the price (higher-order bit is always 0)
check_map=(m_extr_map>>i)&3;
if(inp_map!=check_map)
return(false);
}
//--- "take" two bits - pattern of the corresponding oscillator extremum
inp_map=(map>>(j+2))&3;
//--- if the higher-order bit=1, then any ratio is suitable for us
if(inp_map>=2)
continue;
//--- "take" two bits of the corresponding oscillator extremum (higher-order bit is always 0)
check_map=(m_extr_map>>(i+2))&3;
if(inp_map!=check_map)
return(false);
}
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| "Voting" that price will grow. |
//+------------------------------------------------------------------+
int CSignalStoch::LongCondition(void)
{
int result=0;
int idx =StartIndex();
//--- check direction of the main line
if(DiffMain(idx)>0.0)
{
//--- the main line is directed upwards, and it confirms the possibility of price growth
if(IS_PATTERN_USAGE(0))
result=m_pattern_0; // "confirming" signal number 0
//--- if the model 1 is used, look for a reverse of the main line
if(IS_PATTERN_USAGE(1) && DiffMain(idx+1)<0.0)
result=m_pattern_1; // signal number 1
//--- if the model 2 is used, look for an intersection of the main and signal line
if(IS_PATTERN_USAGE(2) && DiffMainSignal(idx)>0.0 && DiffMainSignal(idx+1)<0.0)
result=m_pattern_2; // signal number 2
//--- if the models 3 or 4 are used, look for divergences
if((IS_PATTERN_USAGE(3) || IS_PATTERN_USAGE(4)))
{
//--- perform the extended analysis of the oscillator state
ExtStateStoch(idx);
//--- if the model 3 is used, look for the "divergence" signal
if(IS_PATTERN_USAGE(3) && CompareMaps(1,1)) // 0000 0001b
result=m_pattern_3; // signal number 3
//--- if the model 4 is used, look for the "double divergence" signal
if(IS_PATTERN_USAGE(4) && CompareMaps(0x11,2)) // 0001 0001b
return(m_pattern_4); // signal number 4
}
}
//--- return the result
return(result);
}
//+------------------------------------------------------------------+
//| "Voting" that price will fall. |
//+------------------------------------------------------------------+
int CSignalStoch::ShortCondition(void)
{
int result=0;
int idx =StartIndex();
//--- check direction of the main line
if(DiffMain(idx)<0.0)
{
//--- main line is directed downwards, confirming a possibility of falling of price
if(IS_PATTERN_USAGE(0))
result=m_pattern_0; // "confirming" signal number 0
//--- if the model 1 is used, look for a reverse of the main line
if(IS_PATTERN_USAGE(1) && DiffMain(idx+1)>0.0)
result=m_pattern_1; // signal number 1
//--- if the model 2 is used, look for an intersection of the main and signal line
if(IS_PATTERN_USAGE(2) && DiffMainSignal(idx)<0.0 && DiffMainSignal(idx+1)>0.0)
result=m_pattern_2; // signal number 2
//--- if the models 3 or 4 are used, look for divergences
if((IS_PATTERN_USAGE(3) || IS_PATTERN_USAGE(4)))
{
//--- perform the extended analysis of the oscillator state
ExtStateStoch(idx);
//--- if the model 3 is used, look for the "divergence" signal
if(IS_PATTERN_USAGE(3) && CompareMaps(1,1)) // 0000 0001b
result=m_pattern_3; // signal number 3
//--- if the model 4 is used, look for the "double divergence" signal
if(IS_PATTERN_USAGE(4) && CompareMaps(0x11,2)) // 0001 0001b
return(m_pattern_4); // signal number 4
}
}
//--- return the result
return(result);
}
//+------------------------------------------------------------------+
+257
View File
@@ -0,0 +1,257 @@
//+------------------------------------------------------------------+
//| SignalTEMA.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Expert\ExpertSignal.mqh>
// wizard description start
//+------------------------------------------------------------------+
//| Description of the class |
//| Title=Signals of indicator 'Triple Exponential Moving Average' |
//| Type=SignalAdvanced |
//| Name=Triple Exponential Moving Average |
//| ShortName=TEMA |
//| Class=CSignalTEMA |
//| Page=signal_tema |
//| Parameter=PeriodMA,int,12,Period of averaging |
//| Parameter=Shift,int,0,Time shift |
//| Parameter=Applied,ENUM_APPLIED_PRICE,PRICE_CLOSE,Prices series |
//+------------------------------------------------------------------+
// wizard description end
//+------------------------------------------------------------------+
//| Class CSignalTEMA. |
//| Purpose: Class of generator of trade signals based on |
//| the 'Triple Exponential Moving Average' indicator. |
//| Is derived from the CExpertSignal class. |
//+------------------------------------------------------------------+
class CSignalTEMA : public CExpertSignal
{
protected:
CiTEMA m_ma; // object-indicator
//--- adjusted parameters
int m_ma_period; // the "period of averaging" parameter of the indicator
int m_ma_shift; // the "time shift" parameter of the indicator
ENUM_APPLIED_PRICE m_ma_applied; // the "object of averaging" parameter" of the indicator
//--- "weights" of market models (0-100)
int m_pattern_0; // model 0 "price is on the necessary side from the indicator"
int m_pattern_1; // model 1 "price crossed the indicator with opposite direction"
int m_pattern_2; // model 2 "price crossed the indicator with the same direction"
int m_pattern_3; // model 3 "piercing"
public:
CSignalTEMA(void);
~CSignalTEMA(void);
//--- methods of setting adjustable parameters
void PeriodMA(int value) { m_ma_period=value; }
void Shift(int value) { m_ma_shift=value; }
void Applied(ENUM_APPLIED_PRICE value) { m_ma_applied=value; }
//--- methods of adjusting "weights" of market models
void Pattern_0(int value) { m_pattern_0=value; }
void Pattern_1(int value) { m_pattern_1=value; }
void Pattern_2(int value) { m_pattern_2=value; }
void Pattern_3(int value) { m_pattern_3=value; }
//--- method of verification of settings
virtual bool ValidationSettings(void);
//--- method of creating the indicator and timeseries
virtual bool InitIndicators(CIndicators *indicators);
//--- methods of checking if the market models are formed
virtual int LongCondition(void);
virtual int ShortCondition(void);
protected:
//--- method of initialization of the indicator
bool InitMA(CIndicators *indicators);
//--- methods of getting data
double MA(int ind) { return(m_ma.Main(ind)); }
double DiffMA(int ind) { return(MA(ind)-MA(ind+1)); }
double DiffOpenMA(int ind) { return(Open(ind)-MA(ind)); }
double DiffHighMA(int ind) { return(High(ind)-MA(ind)); }
double DiffLowMA(int ind) { return(Low(ind)-MA(ind)); }
double DiffCloseMA(int ind) { return(Close(ind)-MA(ind)); }
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CSignalTEMA::CSignalTEMA(void) : m_ma_period(12),
m_ma_shift(0),
m_ma_applied(PRICE_CLOSE),
m_pattern_0(50),
m_pattern_1(10),
m_pattern_2(60),
m_pattern_3(60)
{
//--- initialization of protected data
m_used_series=USE_SERIES_OPEN+USE_SERIES_HIGH+USE_SERIES_LOW+USE_SERIES_CLOSE;
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CSignalTEMA::~CSignalTEMA(void)
{
}
//+------------------------------------------------------------------+
//| Validation settings protected data. |
//+------------------------------------------------------------------+
bool CSignalTEMA::ValidationSettings(void)
{
//--- call of the method of the parent class
if(!CExpertSignal::ValidationSettings())
return(false);
//--- initial data checks
if(m_ma_period<=0)
{
printf(__FUNCTION__+": period MA must be greater than 0");
return(false);
}
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Create indicators. |
//+------------------------------------------------------------------+
bool CSignalTEMA::InitIndicators(CIndicators *indicators)
{
//--- check pointer
if(indicators==NULL)
return(false);
//--- initialization of indicators and timeseries of additional filters
if(!CExpertSignal::InitIndicators(indicators))
return(false);
//--- create and initialize TEMA indicator
if(!InitMA(indicators))
return(false);
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Create MA indicators. |
//+------------------------------------------------------------------+
bool CSignalTEMA::InitMA(CIndicators *indicators)
{
//--- check pointer
if(indicators==NULL)
return(false);
//--- add object to collection
if(!indicators.Add(GetPointer(m_ma)))
{
printf(__FUNCTION__+": error adding object");
return(false);
}
//--- initialize object
if(!m_ma.Create(m_symbol.Name(),m_period,m_ma_period,m_ma_shift,m_ma_applied))
{
printf(__FUNCTION__+": error initializing object");
return(false);
}
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| "Voting" that price will grow. |
//+------------------------------------------------------------------+
int CSignalTEMA::LongCondition(void)
{
int result=0;
int idx =StartIndex();
//--- analyze positional relationship of the close price and the indicator at the first analyzed bar
if(DiffCloseMA(idx)<0.0)
{
//--- the close price is below the indicator
if(IS_PATTERN_USAGE(1) && DiffOpenMA(idx)>0.0 && DiffMA(idx)>0.0)
{
//--- the open price is above the indicator (i.e. there was an intersection), but the indicator is directed upwards
result=m_pattern_1;
//--- consider that this is an unformed "piercing" and suggest to enter the market at the current price
m_base_price=0.0;
}
}
else
{
//--- the close price is above the indicator (the indicator has no objections to buying)
if(IS_PATTERN_USAGE(0))
result=m_pattern_0;
//--- if the indicator is directed upwards
if(DiffMA(idx)>0.0)
{
if(DiffOpenMA(idx)<0.0)
{
//--- if the model 2 is used
if(IS_PATTERN_USAGE(2))
{
//--- the open price is below the indicator (i.e. there was an intersection)
result=m_pattern_2;
//--- suggest to enter the market at the "roll back"
m_base_price=m_symbol.NormalizePrice(MA(idx));
}
}
else
{
//--- if the model 3 is used and the open price is above the indicator
if(IS_PATTERN_USAGE(3) && DiffLowMA(idx)<0.0)
{
//--- the low price is below the indicator
result=m_pattern_3;
//--- consider that this is a formed "piercing" and suggest to enter the market at the current price
m_base_price=0.0;
}
}
}
}
//--- return the result
return(result);
}
//+------------------------------------------------------------------+
//| "Voting" that price will fall. |
//+------------------------------------------------------------------+
int CSignalTEMA::ShortCondition(void)
{
int result=0;
int idx =StartIndex();
//--- analyze positional relationship of the close price and the indicator at the first analyzed bar
if(DiffCloseMA(idx)>0.0)
{
//--- the close price is above the indicator
if(IS_PATTERN_USAGE(1) && DiffOpenMA(idx)<0.0 && DiffMA(idx)<0.0)
{
//--- the open price is below the indicator (i.e. there was an intersection), but the indicator is directed downwards
result=m_pattern_1;
//--- consider that this is an unformed "piercing" and suggest to enter the market at the current price
m_base_price=0.0;
}
}
else
{
//--- the close price is below the indicator (the indicator has no objections to buying)
if(IS_PATTERN_USAGE(0))
result=m_pattern_0;
//--- the indicator is directed downwards
if(DiffMA(idx)<0.0)
{
if(DiffOpenMA(idx)>0.0)
{
//--- if the model 2 is used
if(IS_PATTERN_USAGE(2))
{
//--- the open price is above the indicator (i.e. there was an intersection)
result=m_pattern_2;
//--- suggest to enter the market at the "roll back"
m_base_price=m_symbol.NormalizePrice(MA(idx));
}
}
else
{
//--- if the model 3 is used and the open price is below the indicator
if(IS_PATTERN_USAGE(3) && DiffHighMA(idx)>0.0)
{
//--- the high price is above the indicator
result=m_pattern_3;
//--- consider that this is a formed "piercing" and suggest to enter the market at the current price
m_base_price=0.0;
}
}
}
}
//--- return the result
return(result);
}
//+------------------------------------------------------------------+
+395
View File
@@ -0,0 +1,395 @@
//+------------------------------------------------------------------+
//| SignalTRIX.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Expert\ExpertSignal.mqh>
// wizard description start
//+------------------------------------------------------------------+
//| Description of the class |
//| Title=Signals of oscillator 'Triple Exponential Average' |
//| Type=SignalAdvanced |
//| Name=Triple Exponential Average |
//| ShortName=TriX |
//| Class=CSignalTriX |
//| Page=signal_trix |
//| Parameter=PeriodTriX,int,14,Period of calculation |
//| Parameter=Applied,ENUM_APPLIED_PRICE,PRICE_CLOSE,Prices series |
//+------------------------------------------------------------------+
// wizard description end
//+------------------------------------------------------------------+
//| Class CSignalTriX. |
//| Purpose: Class of generator of trade signals based on |
//| the 'Triple Exponential Average' oscillator. |
//| Is derived from the CExpertSignal class. |
//+------------------------------------------------------------------+
class CSignalTriX : public CExpertSignal
{
protected:
CiTriX m_trix; // object-oscillator
//--- adjusted parameters
int m_period_trix; // the "period of calculation" parameter of the oscillator
ENUM_APPLIED_PRICE m_applied; // the "price series" parameter of the oscillator
//--- "weights" of market models (0-100)
int m_pattern_0; // model 0 "the oscillator has required direction"
int m_pattern_1; // model 1 "reverse of the oscillator to required direction"
int m_pattern_2; // model 2 "crossing of main line an the zero level"
int m_pattern_3; // model 3 "divergence of the oscillator and price"
//--- variables
double m_extr_osc[10]; // array of values of extremums of the oscillator
double m_extr_pr[10]; // array of values of the corresponding extremums of price
int m_extr_pos[10]; // array of shifts of extremums (in bars)
uint m_extr_map; // resulting bit-map of ratio of extremums of the oscillator and the price
public:
CSignalTriX(void);
~CSignalTriX(void);
//--- methods of setting adjustable parameters
void PeriodTriX(int value) { m_period_trix=value; }
void Applied(ENUM_APPLIED_PRICE value) { m_applied=value; }
//--- methods of adjusting "weights" of market models
void Pattern_0(int value) { m_pattern_0=value; }
void Pattern_1(int value) { m_pattern_1=value; }
void Pattern_2(int value) { m_pattern_2=value; }
void Pattern_3(int value) { m_pattern_3=value; }
//--- method of verification of settings
virtual bool ValidationSettings(void);
//--- method of creating the indicator and timeseries
virtual bool InitIndicators(CIndicators *indicators);
//--- methods of checking if the market models are formed
virtual int LongCondition(void);
virtual int ShortCondition(void);
protected:
//--- method of initialization of the oscillator
bool InitTriX(CIndicators *indicators);
//--- methods of getting data
double TriX(int ind) { return(m_trix.Main(ind)); }
double DiffTriX(int ind) { return(TriX(ind)-TriX(ind+1)); }
int State(int ind);
bool ExtState(int ind);
bool CompareMaps(int map,int count,bool minimax=false,int start=0);
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CSignalTriX::CSignalTriX(void) : m_period_trix(12),
m_applied(PRICE_CLOSE),
m_pattern_0(20),
m_pattern_1(80),
m_pattern_2(100),
m_pattern_3(70)
{
//--- initialization of protected data
m_used_series=USE_SERIES_HIGH+USE_SERIES_LOW;
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CSignalTriX::~CSignalTriX(void)
{
}
//+------------------------------------------------------------------+
//| Validation settings protected data. |
//+------------------------------------------------------------------+
bool CSignalTriX::ValidationSettings(void)
{
if(!CExpertSignal::ValidationSettings())
return(false);
//---
if(m_period_trix<=0)
{
printf(__FUNCTION__+": period must be greater than 0");
return(false);
}
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Create indicators. |
//+------------------------------------------------------------------+
bool CSignalTriX::InitIndicators(CIndicators *indicators)
{
//--- check pointer
if(indicators==NULL)
return(false);
//--- initialization of indicators and timeseries of additional filters
if(!CExpertSignal::InitIndicators(indicators))
return(false);
//--- create and initialize TriX oscilator
if(!InitTriX(indicators))
return(false);
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Initialize TriX oscillators. |
//+------------------------------------------------------------------+
bool CSignalTriX::InitTriX(CIndicators *indicators)
{
//--- check pointer
if(indicators==NULL)
return(false);
//--- add object to collection
if(!indicators.Add(GetPointer(m_trix)))
{
printf(__FUNCTION__+": error adding object");
return(false);
}
//--- initialize object
if(!m_trix.Create(m_symbol.Name(),m_period,m_period_trix,m_applied))
{
printf(__FUNCTION__+": error initializing object");
return(false);
}
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Check of the oscillator state. |
//+------------------------------------------------------------------+
int CSignalTriX::State(int ind)
{
int res=0;
double var;
//---
for(int i=ind;;i++)
{
if(TriX(i+1)==EMPTY_VALUE)
break;
var=DiffTriX(i);
if(res>0)
{
if(var<0)
break;
res++;
continue;
}
if(res<0)
{
if(var>0)
break;
res--;
continue;
}
if(var>0)
res++;
if(var<0)
res--;
}
//---
return(res);
}
//+------------------------------------------------------------------+
//| Extended check of the oscillator state consists |
//| in forming a bit-map according to certain rules, |
//| which shows ratios of extremums of the oscillator and price. |
//+------------------------------------------------------------------+
bool CSignalTriX::ExtState(int ind)
{
//--- operation of this method results in a bit-map of extremums
//--- practically, the bit-map of extremums is an "array" of 4-bit fields
//--- each "element of the array" definitely describes the ratio
//--- of current extremums of the oscillator and the price with previous ones
//--- purpose of bits of an element of the analyzed bit-map
//--- bit 3 - not used (always 0)
//--- bit 2 - is equal to 1 if the current extremum of the oscillator is "more extreme" than the previous one
//--- (a higher peak or a deeper valley), otherwise - 0
//--- bit 1 - not used (always 0)
//--- bit 0 - is equal to 1 if the current extremum of price is "more extreme" than the previous one
//--- (a higher peak or a deeper valley), otherwise - 0
//--- in addition to them, the following is formed:
//--- array of values of extremums of the oscillator,
//--- array of values of price extremums and
//--- array of "distances" between extremums of the oscillator (in bars)
//--- it should be noted that when using the results of the extended check of state,
//--- you should consider, which extremum of the oscillator (peak or valley)
//--- is the "reference point" (i.e. was detected first during the analysis)
//--- if a peak is detected first then even elements of all arrays
//--- will contain information about peaks, and odd elements will contain information about valleys
//--- if a valley is detected first, then respectively in reverse
int pos=ind,off,index;
uint map; // intermediate bit-map for one extremum
//---
m_extr_map=0;
for(int i=0;i<10;i++)
{
off=State(pos);
if(off>0)
{
//--- minimum of the oscillator is detected
pos+=off;
m_extr_pos[i]=pos;
m_extr_osc[i]=TriX(pos);
if(i>1)
{
m_extr_pr[i]=m_low.MinValue(pos-2,5,index);
//--- form the intermediate bit-map
map=0;
if(m_extr_pr[i-2]<m_extr_pr[i])
map+=1; // set bit 0
if(m_extr_osc[i-2]<m_extr_osc[i])
map+=4; // set bit 2
//--- add the result
m_extr_map+=map<<(4*(i-2));
}
else
m_extr_pr[i]=m_low.MinValue(pos-1,4,index);
}
else
{
//--- maximum of the oscillator is detected
pos-=off;
m_extr_pos[i]=pos;
m_extr_osc[i]=TriX(pos);
if(i>1)
{
m_extr_pr[i]=m_high.MaxValue(pos-2,5,index);
//--- form the intermediate bit-map
map=0;
if(m_extr_pr[i-2]>m_extr_pr[i])
map+=1; // set bit 0
if(m_extr_osc[i-2]>m_extr_osc[i])
map+=4; // set bit 2
//--- add the result
m_extr_map+=map<<(4*(i-2));
}
else
m_extr_pr[i]=m_high.MaxValue(pos-1,4,index);
}
}
//---
return(true);
}
//+------------------------------------------------------------------+
//| Comparing the bit-map of extremums with pattern. |
//+------------------------------------------------------------------+
bool CSignalTriX::CompareMaps(int map,int count,bool minimax,int start)
{
int step =(minimax)?4:8;
int total=step*(start+count);
//--- check input parameters for a possible going out of range of the bit-map
if(total>32)
return(false);
//--- bit-map of the patter is an "array" of 4-bit fields
//--- each "element of the array" definitely describes the desired ratio
//--- of current extremums of the oscillator and the price with previous ones
//--- purpose of bits of an elements of the pattern of the bit-map pattern
//--- bit 3 - is equal to if the ratio of extremums of the oscillator is insignificant for us
//--- is equal to 0 if we want to "find" the ratio of extremums of the oscillator determined by the value of bit 2
//--- bit 2 - is equal to 1 if we want to "discover" the situation when the current extremum of the "oscillator" is "more extreme" than the previous one
//--- (current peak is higher or current valley is deeper)
//--- is equal to 0 if we want to "discover" the situation when the current extremum of the oscillator is "less extreme" than the previous one
//--- (current peak is lower or current valley is less deep)
//--- bit 1 - is equal to 1 if the ratio of extremums is insignificant for us
//--- it is equal to 0 if we want to "find" the ratio of price extremums determined by the value of bit 0
//--- bit 0 - is equal to 1 if we want to "discover" the situation when the current price extremum is "more extreme" than the previous one
//--- (current peak is higher or current valley is deeper)
//--- it is equal to 0 if we want to "discover" the situation when the current price extremum is "less extreme" than the previous one
//--- (current peak is lower or current valley is less deep)
uint inp_map,check_map;
int i,j;
//--- loop by extremums (4 minimums and 4 maximums)
//--- price and the oscillator are checked separately (thus, there are 16 checks)
for(i=step*start,j=0;i<total;i+=step,j+=4)
{
//--- "take" two bits - patter of the corresponding extremum of the price
inp_map=(map>>j)&3;
//--- if the higher-order bit=1, then any ratio is suitable for us
if(inp_map<2)
{
//--- "take" two bits of the corresponding extremum of the price (higher-order bit is always 0)
check_map=(m_extr_map>>i)&3;
if(inp_map!=check_map)
return(false);
}
//--- "take" two bits - pattern of the corresponding oscillator extremum
inp_map=(map>>(j+2))&3;
//--- if the higher-order bit=1, then any ratio is suitable for us
if(inp_map>=2)
continue;
//--- "take" two bits of the corresponding oscillator extremum (higher-order bit is always 0)
check_map=(m_extr_map>>(i+2))&3;
if(inp_map!=check_map)
return(false);
}
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| "Voting" that price will grow. |
//+------------------------------------------------------------------+
int CSignalTriX::LongCondition(void)
{
int result=0;
int idx =StartIndex();
//--- check direction of the oscillator
if(DiffTriX(idx)>0.0)
{
//--- the oscillator is directed upwards confirming the possibility of price growth
if(IS_PATTERN_USAGE(0))
result=m_pattern_0; // "confirming" signal number 0
//--- if the model 1 is used, search for a reverse of the oscillator
if(IS_PATTERN_USAGE(1) && DiffTriX(idx)>0.0 && DiffTriX(idx+1)<0.0)
result=m_pattern_1; // signal number 1
//--- if the model 2 is used, search for an intersection of the oscillator line and the zero level
if(IS_PATTERN_USAGE(2) && TriX(idx)>0.0 && TriX(idx+1)<0.0)
result=m_pattern_2; // signal number 2
//--- if the model 3 is used, and the oscillator turned up below the zero level, search for the divergence
if(IS_PATTERN_USAGE(3) && TriX(idx)<0.0)
{
//--- perform the extended analysis of the oscillator state
ExtState(idx);
//--- search for the "divergence" signal
if(CompareMaps(1,1)) // 0000 0001b
{
if(m_extr_osc[0]<0.0 && m_extr_osc[1]<0.0 && m_extr_osc[2]<0.0)
{
//--- both valleys of the oscillator are below zero and the peak between them hasn't raised above zero
result=m_pattern_3; // signal number 3
}
}
}
}
//--- return the result
return(result);
}
//+------------------------------------------------------------------+
//| "Voting" that price will fall. |
//+------------------------------------------------------------------+
int CSignalTriX::ShortCondition(void)
{
int result=0;
int idx =StartIndex();
//--- check direction of the main line
if(DiffTriX(idx)<0.0)
{
//--- main line is directed downwards, confirming a possibility of falling of price
if(IS_PATTERN_USAGE(0))
result=m_pattern_0; // "confirming" signal number 0
//--- if the model 1 is used, search for a reverse of the main line
if(IS_PATTERN_USAGE(1) && DiffTriX(idx)<0.0 && DiffTriX(idx+1)>0.0)
result=m_pattern_1; // signal number 1
//--- if the model 2 is used, search for an intersection of the main line and the zero level
if(IS_PATTERN_USAGE(2) && TriX(idx)<0.0 && TriX(idx+1)>0.0)
result=m_pattern_2; // signal number 2
//--- if the model 3 is used and the main line turned down above the zero level, search for the divergence
if(IS_PATTERN_USAGE(3) && TriX(idx)>0.0)
{
//--- perform the extended analysis of the oscillator state
ExtState(idx);
//--- search for the "divergence" signal
if(CompareMaps(1,1)) // 0000 0001b
{
if(m_extr_osc[0]>0.0 && m_extr_osc[1]>0.0 && m_extr_osc[2]>0.0)
{
//--- both peaks of the oscillator are above zero and the valley between them hasn't fallen below zero
result=m_pattern_3; // signal number 3
}
}
}
}
//--- return the result
return(result);
}
//+------------------------------------------------------------------+
+371
View File
@@ -0,0 +1,371 @@
//+------------------------------------------------------------------+
//| SignalWPR.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Expert\ExpertSignal.mqh>
// wizard description start
//+------------------------------------------------------------------+
//| Description of the class |
//| Title=Signals of oscillator 'Williams Percent Range' |
//| Type=SignalAdvanced |
//| Name=Williams Percent Range |
//| ShortName=WPR |
//| Class=CSignalWPR |
//| Page=signal_wpr |
//| Parameter=PeriodWPR,int,8,Period of calculation |
//+------------------------------------------------------------------+
// wizard description end
//+------------------------------------------------------------------+
//| Class CSignalWPR. |
//| Purpose: Class of generator of trade signals based on |
//| the 'Williams Percent Range' oscillator. |
//| Is derived from the CExpertSignal class. |
//+------------------------------------------------------------------+
class CSignalWPR : public CExpertSignal
{
protected:
CiWPR m_wpr; // object-oscillator
//--- adjusted parameters
int m_period_wpr; // the "period of calculation" parameter of the oscillator
//--- "weights" of market models (0-100)
int m_pattern_0; // model 0 "the oscillator has required direction"
int m_pattern_1; // model 1 "reverse behind the level of overbuying/overselling"
int m_pattern_2; // model 2 "divergence of the oscillator and price"
//--- variables
double m_extr_osc[10]; // array of values of extremums of the oscillator
double m_extr_pr[10]; // array of values of the corresponding extremums of price
int m_extr_pos[10]; // array of shifts of extremums (in bars)
uint m_extr_map; // resulting bit-map of ratio of extremums of the oscillator and the price
public:
CSignalWPR(void);
~CSignalWPR(void);
//--- methods of setting adjustable parameters
void PeriodWPR(int value) { m_period_wpr=value; }
//--- methods of adjusting "weights" of market models
void Pattern_0(int value) { m_pattern_0=value; }
void Pattern_1(int value) { m_pattern_1=value; }
void Pattern_2(int value) { m_pattern_2=value; }
//--- method of verification of settings
virtual bool ValidationSettings(void);
//--- method of creating the indicator and timeseries
virtual bool InitIndicators(CIndicators *indicators);
//--- methods of checking if the market models are formed
virtual int LongCondition(void);
virtual int ShortCondition(void);
protected:
//--- method of initialization of the oscillator
bool InitWPR(CIndicators *indicators);
//--- methods of getting data
// double WPR(int ind);
double WPR(int ind) { return(m_wpr.Main(ind)); }
double Diff(int ind) { return(WPR(ind)-WPR(ind+1)); }
int State(int ind);
bool ExtState(int ind);
bool CompareMaps(int map,int count,bool minimax=false,int start=0);
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CSignalWPR::CSignalWPR(void) : m_period_wpr(14),
m_pattern_0(80),
m_pattern_1(70),
m_pattern_2(90)
{
//--- initialization of protected data
m_used_series=USE_SERIES_HIGH+USE_SERIES_LOW;
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CSignalWPR::~CSignalWPR(void)
{
}
//+------------------------------------------------------------------+
//| Validation settings protected data. |
//+------------------------------------------------------------------+
bool CSignalWPR::ValidationSettings(void)
{
//--- validation settings of additional filters
if(!CExpertSignal::ValidationSettings())
return(false);
//--- initial data checks
if(m_period_wpr<=0)
{
printf(__FUNCTION__+": period of the WPR oscillator must be greater than 0");
return(false);
}
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Create indicators. |
//+------------------------------------------------------------------+
bool CSignalWPR::InitIndicators(CIndicators *indicators)
{
//--- check pointer
if(indicators==NULL)
return(false);
//--- initialization of indicators and timeseries of additional filters
if(!CExpertSignal::InitIndicators(indicators))
return(false);
//--- create and initialize WPR oscillator
if(!InitWPR(indicators))
return(false);
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Initialize WPR oscillators. |
//+------------------------------------------------------------------+
bool CSignalWPR::InitWPR(CIndicators *indicators)
{
//--- check pointer
if(indicators==NULL) return(false);
//--- add object to collection
if(!indicators.Add(GetPointer(m_wpr)))
{
printf(__FUNCTION__+": error adding object");
return(false);
}
//--- initialize object
if(!m_wpr.Create(m_symbol.Name(),m_period,m_period_wpr))
{
printf(__FUNCTION__+": error initializing object");
return(false);
}
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Check of the oscillator state. |
//+------------------------------------------------------------------+
int CSignalWPR::State(int ind)
{
int res=0;
double var;
//---
for(int i=ind;;i++)
{
if(WPR(i+1)==EMPTY_VALUE)
break;
var=Diff(i);
if(res>0)
{
if(var<0)
break;
res++;
continue;
}
if(res<0)
{
if(var>0)
break;
res--;
continue;
}
if(var>0)
res++;
if(var<0)
res--;
}
//---
return(res);
}
//+------------------------------------------------------------------+
//| Extended check of the oscillator state consists |
//| in forming a bit-map according to certain rules, |
//| which shows ratios of extremums of the oscillator and price. |
//+------------------------------------------------------------------+
bool CSignalWPR::ExtState(int ind)
{
//--- operation of this method results in a bit-map of extremums
//--- practically, the bit-map of extremums is an "array" of 4-bit fields
//--- each "element of the array" definitely describes the ratio
//--- of current extremums of the oscillator and the price with previous ones
//--- purpose of bits of an element of the analyzed bit-map
//--- bit 3 - not used (always 0)
//--- bit 2 - is equal to 1 if the current extremum of the oscillator is "more extreme" than the previous one
//--- (a higher peak or a deeper valley), otherwise - 0
//--- bit 1 - not used (always 0)
//--- bit 0 - is equal to 1 if the current extremum of price is "more extreme" than the previous one
//--- (a higher peak or a deeper valley), otherwise - 0
//--- in addition to them, the following is formed:
//--- array of values of extremums of the oscillator,
//--- array of values of price extremums and
//--- array of "distances" between extremums of the oscillator (in bars)
//--- it should be noted that when using the results of the extended check of state,
//--- you should consider, which extremum of the oscillator (peak or valley)
//--- is the "reference point" (i.e. was detected first during the analysis)
//--- if a peak is detected first then even elements of all arrays
//--- will contain information about peaks, and odd elements will contain information about valleys
//--- if a valley is detected first, then respectively in reverse
int pos=ind,off,index;
uint map; // intermediate bit-map for one extremum
//---
m_extr_map=0;
for(int i=0;i<10;i++)
{
off=State(pos);
if(off>0)
{
//--- minimum of the oscillator is detected
pos+=off;
m_extr_pos[i]=pos;
m_extr_osc[i]=WPR(pos);
if(i>1)
{
m_extr_pr[i]=m_low.MinValue(pos-2,5,index);
//--- form the intermediate bit-map
map=0;
if(m_extr_pr[i-2]<m_extr_pr[i])
map+=1; // set bit 0
if(m_extr_osc[i-2]<m_extr_osc[i])
map+=4; // set bit 2
//--- add the result
m_extr_map+=map<<(4*(i-2));
}
else
m_extr_pr[i]=m_low.MinValue(pos-1,4,index);
}
else
{
//--- maximum of the oscillator is detected
pos-=off;
m_extr_pos[i]=pos;
m_extr_osc[i]=WPR(pos);
if(i>1)
{
m_extr_pr[i]=m_high.MaxValue(pos-2,5,index);
//--- form the intermediate bit-map
map=0;
if(m_extr_pr[i-2]>m_extr_pr[i])
map+=1; // set bit 0
if(m_extr_osc[i-2]>m_extr_osc[i])
map+=4; // set bit 2
//--- add the result
m_extr_map+=map<<(4*(i-2));
}
else
m_extr_pr[i]=m_high.MaxValue(pos-1,4,index);
}
}
//---
return(true);
}
//+------------------------------------------------------------------+
//| Comparing the bit-map of extremums with pattern. |
//+------------------------------------------------------------------+
bool CSignalWPR::CompareMaps(int map,int count,bool minimax,int start)
{
int step =(minimax)?4:8;
int total=step*(start+count);
//--- check input parameters for a possible going out of range of the bit-map
if(total>32)
return(false);
//--- bit-map of the patter is an "array" of 4-bit fields
//--- each "element of the array" definitely describes the desired ratio
//--- of current extremums of the oscillator and the price with previous ones
//--- purpose of bits of an elements of the pattern of the bit-map pattern
//--- bit 3 - is equal to if the ratio of extremums of the oscillator is insignificant for us
//--- is equal to 0 if we want to "find" the ratio of extremums of the oscillator determined by the value of bit 2
//--- bit 2 - is equal to 1 if we want to "discover" the situation when the current extremum of the "oscillator" is "more extreme" than the previous one
//--- (current peak is higher or current valley is deeper)
//--- is equal to 0 if we want to "discover" the situation when the current extremum of the oscillator is "less extreme" than the previous one
//--- (current peak is lower or current valley is less deep)
//--- bit 1 - is equal to 1 if the ratio of extremums is insignificant for us
//--- it is equal to 0 if we want to "find" the ratio of price extremums determined by the value of bit 0
//--- bit 0 - is equal to 1 if we want to "discover" the situation when the current price extremum is "more extreme" than the previous one
//--- (current peak is higher or current valley is deeper)
//--- it is equal to 0 if we want to "discover" the situation when the current price extremum is "less extreme" than the previous one
//--- (current peak is lower or current valley is less deep)
uint inp_map,check_map;
int i,j;
//--- loop by extremums (4 minimums and 4 maximums)
//--- price and the oscillator are checked separately (thus, there are 16 checks)
for(i=step*start,j=0;i<total;i+=step,j+=4)
{
//--- "take" two bits - patter of the corresponding extremum of the oscillator
inp_map=(map>>i)&3;
//--- if the higher-order bit=1, then any ratio is suitable for us
if(inp_map<2)
{
//--- "take" two bits of the corresponding extremum of the oscillator (higher-order bit is always 0)
check_map=(m_extr_map>>j)&3;
if(inp_map!=check_map)
return(false);
}
//--- "take" two bits - pattern of the corresponding price extremum
inp_map=(map>>(i+2))&3;
//--- if the higher-order bit=1, then any ratio is suitable for us
if(inp_map>=2)
continue;
//--- "take" two bits of the corresponding price extremum (higher-order bit is always 0)
check_map=(m_extr_map>>(j+2))&3;
if(inp_map!=check_map)
return(false);
}
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| "Voting" that price will grow. |
//+------------------------------------------------------------------+
int CSignalWPR::LongCondition(void)
{
int result=0;
int idx =StartIndex();
//---
if(Diff(idx)>0.0)
{
//--- the oscillator is directed upwards confirming the possibility of price growth
if(IS_PATTERN_USAGE(0))
result=m_pattern_0; // "confirming" signal number 0
//--- if the model 1 is used, search for a reverse of the oscillator upwards behind the level of overselling
if(IS_PATTERN_USAGE(1) && Diff(idx+1)<0.0 && WPR(idx+1)>-80.0)
result=m_pattern_1; // signal number 1
//--- if the model 2 or 3 is used, search for the divergences
if(IS_PATTERN_USAGE(2))
{
//--- perform the extended analysis of the oscillator state
ExtState(idx);
//--- if the model 2 is used, search for the "divergence" signal
if(CompareMaps(1,1)) // 00000001b
result=m_pattern_2; // signal number 2
}
}
//--- return the result
return(result);
}
//+------------------------------------------------------------------+
//| "Voting" that price will fall. |
//+------------------------------------------------------------------+
int CSignalWPR::ShortCondition(void)
{
int result=0;
int idx =StartIndex();
//---
if(Diff(idx)<0.0)
{
//--- the oscillator is directed downwards confirming the possibility of falling of price
if(IS_PATTERN_USAGE(0))
result=m_pattern_0; // "confirming" signal number 0
//--- if the model 1 is used, search for a reverse of the oscillator downwards behind the level of overbuying
if(IS_PATTERN_USAGE(1) && Diff(idx+1)>0.0 && WPR(idx+1)<-20.0)
result=m_pattern_1; // signal number 1
//--- if the model 2 or 3 is used, search for the divergences
if(IS_PATTERN_USAGE(2))
{
//--- perform the extended analysis of the oscillator state
ExtState(idx);
//--- if the model 2 is used, search for the "divergence" signal
if(CompareMaps(1,1)) // 00000001b
result=m_pattern_2; // signal number 2
}
}
//--- return the result
return(result);
}
//+------------------------------------------------------------------+
@@ -0,0 +1,278 @@
//+------------------------------------------------------------------+
//| SuperTrendSignal.mqh |
//| Copyright © 2011, Nikolay Kositsin |
//| Khabarovsk, farria@mail.redcom.ru |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2011, Nikolay Kositsin"
#property link "farria@mail.redcom.ru"
//+------------------------------------------------------------------+
//| Included files |
//+------------------------------------------------------------------+
#property tester_indicator "SuperTrend.ex5"
#include <Expert\ExpertSignal.mqh>
//--- wizard description start
//+------------------------------------------------------------------+
//| Declaration of constants |
//+------------------------------------------------------------------+
#define OPEN_LONG 80 // The constant for returning the buy command to the Expert Advisor
#define OPEN_SHORT 80 // The constant for returning the sell command to the Expert Advisor
#define CLOSE_LONG 40 // The constant for returning the command to close a long position to the Expert Advisor
#define CLOSE_SHORT 40 // The constant for returning the command to close a short position to the Expert Advisor
#define REVERSE_LONG 100 // The constant for returning the command to reverse a long position to the Expert Advisor
#define REVERSE_SHORT 100 // The constant for returning the command to reverse a short position to the Expert Advisor
#define NO_SIGNAL 0 // The constant for returning the absence of a signal to the Expert Advisor
//+---------------------------------------------------------------------+
//| Description of the class |
//| Title=The signals based on SuperTrend indicator |
//| Type=SignalAdvanced |
//| Name=SuperTrend |
//| Class=CSuperTrendSignal |
//| Page= |
//| Parameter=BuyPosOpen,bool,true,Permission to buy |
//| Parameter=SellPosOpen,bool,true,Permission to sell |
//| Parameter=BuyPosClose,bool,true,Permission to exit a long position |
//| Parameter=SellPosClose,bool,true,Permission to exit a short position|
//| Parameter=Ind_Timeframe,ENUM_TIMEFRAMES,PERIOD_H4,Timeframe |
//| Parameter=CCIPeriod,uint,50, CCI indicator period |
//| Parameter=ATRPeriod,uint,5,ATR indicator period |
//| Parameter=Level,uint,0,CCI activation level |
//| Parameter=SignalBar,uint,1,Bar index for entry signal |
//+---------------------------------------------------------------------+
//--- wizard description end
//+---------------------------------------------------------------------+
//| CSuperTrendSignal class. |
//| Purpose: Class of generator of trade signals based on |
//| SuperTrend indicator values http://www.mql5.com/ru/code/527/. |
//| Is derived from the CExpertSignal class. |
//+---------------------------------------------------------------------+
class CSuperTrendSignal : public CExpertSignal
{
protected:
CiCustom m_indicator; // the object for access to SuperTrend values
//--- adjusted parameters
bool m_BuyPosOpen; // permission to buy
bool m_SellPosOpen; // permission to sell
bool m_BuyPosClose; // permission to exit a long position
bool m_SellPosClose; // permission to exit a short position
ENUM_TIMEFRAMES m_Ind_Timeframe; // indicator chart timeframe
uint m_CCIPeriod; // CCI indicator period
uint m_ATRPeriod; // ATR indicator period
uint m_Level; // CCI activation level
uint m_SignalBar; // bar index for getting entry signal
public:
CSuperTrendSignal();
//--- methods of setting adjustable parameters
void BuyPosOpen(bool value) { m_BuyPosOpen=value; }
void SellPosOpen(bool value) { m_SellPosOpen=value; }
void BuyPosClose(bool value) { m_BuyPosClose=value; }
void SellPosClose(bool value) { m_SellPosClose=value; }
//--- indicator input parameters
void Ind_Timeframe(ENUM_TIMEFRAMES value) { m_Ind_Timeframe=value; }
void CCIPeriod(uint value) { m_CCIPeriod=value; }
void ATRPeriod(uint value) { m_ATRPeriod=value; }
void Level(uint value) { m_Level=value; }
//---
void SignalBar(uint value) { m_SignalBar=value; }
//--- adjustable parameters validation method
virtual bool ValidationSettings();
//--- adjustable parameters validation method
virtual bool InitIndicators(CIndicators *indicators); // indicators initialization
//--- market entry signals generation method
virtual int LongCondition();
virtual int ShortCondition();
bool InitSuperTrend(CIndicators *indicators); // SuperTrend indicator initializing method
protected:
};
//+------------------------------------------------------------------+
//| CSuperTrendSignal constructor. |
//| INPUT: no. |
//| OUTPUT: no. |
//| REMARK: no. |
//+------------------------------------------------------------------+
void CSuperTrendSignal::CSuperTrendSignal()
{
//--- setting default parameters
m_BuyPosOpen=true;
m_SellPosOpen=true;
m_BuyPosClose=true;
m_SellPosClose=true;
//--- indicator input parameters
m_Ind_Timeframe=PERIOD_H4;
m_CCIPeriod=50;
m_ATRPeriod=5;
m_Level=0;
//---
m_SignalBar=1;
m_used_series=USE_SERIES_OPEN+USE_SERIES_HIGH+USE_SERIES_LOW+USE_SERIES_CLOSE;
}
//+------------------------------------------------------------------+
//| Checking adjustable parameters. |
//| INPUT: no. |
//| OUTPUT: true if the settings are valid, false - if not. |
//| REMARK: no. |
//+------------------------------------------------------------------+
bool CSuperTrendSignal::ValidationSettings()
{
//--- checking parameters
if(m_CCIPeriod<=0)
{
printf(__FUNCTION__+": CCI indicator period must be greater than zero");
return(false);
}
if(m_ATRPeriod<=0)
{
printf(__FUNCTION__+": ATR indicator period must be greater than zero");
return(false);
}
//--- successful completion
return(true);
}
//+------------------------------------------------------------------+
//| Initialization of indicators and time series. |
//| INPUT: indicators - pointer to an object-collection |
//| of indicators and time series. |
//| OUTPUT: true - in case of successful, otherwise - false. |
//| REMARK: no. |
//+------------------------------------------------------------------+
bool CSuperTrendSignal::InitIndicators(CIndicators *indicators)
{
//--- check of pointer
if(indicators==NULL) return(false);
//--- indicator initialization
if(!InitSuperTrend(indicators)) return(false);
//--- successful completion
return(true);
}
//+------------------------------------------------------------------+
//| SuperTrend indicator initialization. |
//| INPUT: indicators - pointer to an object-collection |
//| of indicators and time series. |
//| OUTPUT: true - in case of successful, otherwise - false. |
//| REMARK: no. |
//+------------------------------------------------------------------+
bool CSuperTrendSignal::InitSuperTrend(CIndicators *indicators)
{
//--- check of pointer
if(indicators==NULL) return(false);
//--- adding an object to the collection
if(!indicators.Add(GetPointer(m_indicator)))
{
printf(__FUNCTION__+": error of adding the object");
return(false);
}
//--- setting the indicator parameters
MqlParam parameters[5];
parameters[0].type=TYPE_STRING;
parameters[0].string_value="SuperTrend.ex5";
parameters[1].type=TYPE_UINT;
parameters[1].integer_value=m_CCIPeriod;
parameters[2].type=TYPE_UINT;
parameters[2].integer_value=m_ATRPeriod;
parameters[3].type=TYPE_UINT;
parameters[3].integer_value=m_Level;
parameters[4].type=TYPE_UINT;
parameters[4].integer_value=m_Level;
//---
if(!m_indicator.Create(m_symbol.Name(),m_Ind_Timeframe,IND_CUSTOM,5,parameters))
{
printf(__FUNCTION__+": object initialization error");
return(false);
}
//--- number of buffers
if(!m_indicator.NumBuffers(4)) return(false);
//--- SuperTrend indicator initialized successfully
return(true);
}
//+------------------------------------------------------------------+
//| Checking conditions for opening a long position and |
//| closing a short one |
//| INPUT: no |
//| OUTPUT: Vote weight from 0 to 100 |
//| REMARK: no. |
//+------------------------------------------------------------------+
int CSuperTrendSignal::LongCondition()
{
//--- buy signal is determined by buffer 2 of the SuperTrend indicator
double Signal=m_indicator.GetData(2,m_SignalBar);
//--- getting a trading signal
if(Signal && Signal!=EMPTY_VALUE)
{
if(m_BuyPosOpen)
{
if(m_SellPosClose) return(REVERSE_SHORT);
else return(OPEN_LONG);
}
else
{
if(m_SellPosClose) return(CLOSE_SHORT);
}
}
//--- searching for signals for closing a short position
if(!m_SellPosClose) return(NO_SIGNAL);
//--- trend signal is determined by buffer 0 of the SuperTrend indicator
Signal=m_indicator.GetData(0,m_SignalBar);
if(Signal && Signal!=EMPTY_VALUE) return(CLOSE_SHORT);
//--- no trading signal
return(NO_SIGNAL);
}
//+------------------------------------------------------------------+
//| Checking conditions for opening a short position and |
//| closing a long one |
//| INPUT: no |
//| OUTPUT: Vote weight from 0 to 100 |
//| REMARK: no. |
//+------------------------------------------------------------------+
int CSuperTrendSignal::ShortCondition()
{
//--- sell signal is determined by buffer 3 of the SuperTrend indicator
double Signal=m_indicator.GetData(3,m_SignalBar);
//--- getting a trading signal
if(Signal && Signal!=EMPTY_VALUE)
{
if(m_SellPosOpen)
{
if(m_BuyPosClose) return(REVERSE_LONG);
else return(OPEN_SHORT);
}
else
{
if(m_BuyPosClose) return(CLOSE_LONG);
}
}
//--- searching for signals for closing a short position
if(!m_BuyPosClose) return(NO_SIGNAL);
//--- trend signal is determined by buffer 1 of the SuperTrend indicator
Signal=m_indicator.GetData(1,m_SignalBar);
if(Signal && Signal!=EMPTY_VALUE) return(CLOSE_LONG);
//--- no trading signal
return(NO_SIGNAL);
}
//+------------------------------------------------------------------+
+246
View File
@@ -0,0 +1,246 @@
//+------------------------------------------------------------------+
//| SignalCrossEMA.mqh |
//| Copyright © 2010, MetaQuotes Software Corp. |
//| http://www.metaquotes.net |
//| Revision 2010.10.12 |
//+------------------------------------------------------------------+
#include <Expert\ExpertSignal.mqh>
// wizard description start
//+------------------------------------------------------------------+
//| Description of the class |
//| Title=Signals based on crossover of two EMA |
//| Type=Signal |
//| Name=CrossEMA |
//| Class=CSignalCrossEMA |
//| Page= |
//| Parameter=FastPeriod,int,12 |
//| Parameter=SlowPeriod,int,24 |
//+------------------------------------------------------------------+
// wizard description end
//+------------------------------------------------------------------+
//| Class CSignalCrossEMA. |
//| Appointment: Class trading signals cross two EMA. |
//| Derives from class CExpertSignal. |
//+------------------------------------------------------------------+
class CSignalCrossEMA : public CExpertSignal
{
protected:
CiMA *m_FastEMA;
CiMA *m_SlowEMA;
//--- input parameters
int m_fast_period;
int m_slow_period;
public:
CSignalCrossEMA();
~CSignalCrossEMA();
//--- methods initialize protected data
void FastPeriod(int period) { m_fast_period=period; }
void SlowPeriod(int period) { m_slow_period=period; }
virtual bool InitIndicators(CIndicators* indicators);
virtual bool ValidationSettings();
//---
virtual bool CheckOpenLong(double& price,double& sl,double& tp,datetime& expiration);
virtual bool CheckCloseLong(double& price);
virtual bool CheckOpenShort(double& price,double& sl,double& tp,datetime& expiration);
virtual bool CheckCloseShort(double& price);
protected:
bool InitFastEMA(CIndicators* indicators);
bool InitSlowEMA(CIndicators* indicators);
//---
double FastEMA(int ind) { return(m_FastEMA.Main(ind)); }
double SlowEMA(int ind) { return(m_SlowEMA.Main(ind)); }
double StateFastEMA(int ind) { return(FastEMA(ind)-FastEMA(ind+1)); }
double StateSlowEMA(int ind) { return(SlowEMA(ind)-SlowEMA(ind+1)); }
double StateEMA(int ind) { return(FastEMA(ind)-SlowEMA(ind)); }
};
//+------------------------------------------------------------------+
//| Constructor CSignalCrossEMA. |
//| INPUT: no. |
//| OUTPUT: no. |
//| REMARK: no. |
//+------------------------------------------------------------------+
void CSignalCrossEMA::CSignalCrossEMA()
{
//--- initialize protected data
m_FastEMA =NULL;
m_SlowEMA =NULL;
//--- set default inputs
m_fast_period =12;
m_slow_period =24;
}
//+------------------------------------------------------------------+
//| Destructor CSignalCrossEMA. |
//| INPUT: no. |
//| OUTPUT: no. |
//| REMARK: no. |
//+------------------------------------------------------------------+
void CSignalCrossEMA::~CSignalCrossEMA()
{
//---
}
//+------------------------------------------------------------------+
//| Validation settings protected data. |
//| INPUT: no. |
//| OUTPUT: true-if settings are correct, false otherwise. |
//| REMARK: no. |
//+------------------------------------------------------------------+
bool CSignalCrossEMA::ValidationSettings()
{
if(m_fast_period>=m_slow_period)
{
printf(__FUNCTION__+": period of slow EMA must be greater than period of fast EMA");
return(false);
}
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Create indicators. |
//| INPUT: indicators -pointer of indicator collection. |
//| OUTPUT: true-if successful, false otherwise. |
//| REMARK: no. |
//+------------------------------------------------------------------+
bool CSignalCrossEMA::InitIndicators(CIndicators* indicators)
{
//--- check
if(indicators==NULL) return(false);
//--- create and initialize fast EMA indicator
if(!InitFastEMA(indicators)) return(false);
//--- create and initialize slow EMA indicator
if(!InitSlowEMA(indicators)) return(false);
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Create fast EMA indicators. |
//| INPUT: indicators -pointer of indicator collection. |
//| OUTPUT: true-if successful, false otherwise. |
//| REMARK: no. |
//+------------------------------------------------------------------+
bool CSignalCrossEMA::InitFastEMA(CIndicators* indicators)
{
//--- create fast EMA indicator
if(m_FastEMA==NULL)
if((m_FastEMA=new CiMA)==NULL)
{
printf(__FUNCTION__+": error creating object");
return(false);
}
//--- add fast EMA indicator to collection
if(!indicators.Add(m_FastEMA))
{
printf(__FUNCTION__+": error adding object");
delete m_FastEMA;
return(false);
}
//--- initialize fast EMA indicator
if(!m_FastEMA.Create(m_symbol.Name(),m_period,m_fast_period,0,MODE_EMA,PRICE_CLOSE))
{
printf(__FUNCTION__+": error initializing object");
return(false);
}
m_FastEMA.BufferResize(1000);
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Create slow EMA indicators. |
//| INPUT: indicators -pointer of indicator collection. |
//| OUTPUT: true-if successful, false otherwise. |
//| REMARK: no. |
//+------------------------------------------------------------------+
bool CSignalCrossEMA::InitSlowEMA(CIndicators* indicators)
{
//--- create slow EMA indicator
if(m_SlowEMA==NULL)
if((m_SlowEMA=new CiMA)==NULL)
{
printf(__FUNCTION__+": error creating object");
return(false);
}
//--- add slow EMA indicator to collection
if(!indicators.Add(m_SlowEMA))
{
printf(__FUNCTION__+": error adding object");
delete m_SlowEMA;
return(false);
}
//--- initialize slow EMA indicator
if(!m_SlowEMA.Create(m_symbol.Name(),m_period,m_slow_period,0,MODE_EMA,PRICE_CLOSE))
{
printf(__FUNCTION__+": error initializing object");
return(false);
}
m_SlowEMA.BufferResize(1000);
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Check conditions for long position open. |
//| INPUT: price - refernce for price, |
//| sl - refernce for stop loss, |
//| tp - refernce for take profit, |
//| expiration - refernce for expiration. |
//| OUTPUT: true-if condition performed, false otherwise. |
//| REMARK: no. |
//+------------------------------------------------------------------+
bool CSignalCrossEMA::CheckOpenLong(double& price,double& sl,double& tp,datetime& expiration)
{
if(!(StateEMA(2)<0 && StateEMA(1)>0)) return(false);
//---
price=0.0;
sl =0.0;
tp =0.0;
//---
return(true);
}
//+------------------------------------------------------------------+
//| Check conditions for long position close. |
//| INPUT: price - refernce for price. |
//| OUTPUT: true-if condition performed, false otherwise. |
//| REMARK: no. |
//+------------------------------------------------------------------+
bool CSignalCrossEMA::CheckCloseLong(double& price)
{
if(!(StateEMA(2)>0 && StateEMA(1)<0)) return(false);
//---
price=0.0;
//---
return(true);
}
//+------------------------------------------------------------------+
//| Check conditions for short position open. |
//| INPUT: price - refernce for price, |
//| sl - refernce for stop loss, |
//| tp - refernce for take profit, |
//| expiration - refernce for expiration. |
//| OUTPUT: true-if condition performed, false otherwise. |
//| REMARK: no. |
//+------------------------------------------------------------------+
bool CSignalCrossEMA::CheckOpenShort(double& price,double& sl,double& tp,datetime& expiration)
{
if(!(StateEMA(2)>0 && StateEMA(1)<0)) return(false);
//---
price=0.0;
sl =0.0;
tp =0.0;
//---
return(true);
}
//+------------------------------------------------------------------+
//| Check conditions for short position close. |
//| INPUT: price - refernce for price. |
//| OUTPUT: true-if condition performed, false otherwise. |
//| REMARK: no. |
//+------------------------------------------------------------------+
bool CSignalCrossEMA::CheckCloseShort(double& price)
{
if(!(StateEMA(2)<0 && StateEMA(1)>0)) return(false);
//---
price=0.0;
//---
return(true);
}
//+------------------------------------------------------------------+
+132
View File
@@ -0,0 +1,132 @@
//+------------------------------------------------------------------+
//| TrailingFixedPips.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Expert\ExpertTrailing.mqh>
// wizard description start
//+----------------------------------------------------------------------+
//| Description of the class |
//| Title=Trailing Stop based on fixed Stop Level |
//| Type=Trailing |
//| Name=FixedPips |
//| Class=CTrailingFixedPips |
//| Page= |
//| Parameter=StopLevel,int,30,Stop Loss trailing level (in points) |
//| Parameter=ProfitLevel,int,50,Take Profit trailing level (in points) |
//+----------------------------------------------------------------------+
// wizard description end
//+------------------------------------------------------------------+
//| Class CTrailingFixedPips. |
//| Purpose: Class of trailing stops with fixed stop level in pips. |
//| Derives from class CExpertTrailing. |
//+------------------------------------------------------------------+
class CTrailingFixedPips : public CExpertTrailing
{
protected:
//--- input parameters
int m_stop_level;
int m_profit_level;
public:
CTrailingFixedPips(void);
~CTrailingFixedPips(void);
//--- methods of initialization of protected data
void StopLevel(int stop_level) { m_stop_level=stop_level; }
void ProfitLevel(int profit_level) { m_profit_level=profit_level; }
virtual bool ValidationSettings(void);
//---
virtual bool CheckTrailingStopLong(CPositionInfo *position,double &sl,double &tp);
virtual bool CheckTrailingStopShort(CPositionInfo *position,double &sl,double &tp);
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
void CTrailingFixedPips::CTrailingFixedPips(void) : m_stop_level(30),
m_profit_level(50)
{
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CTrailingFixedPips::~CTrailingFixedPips(void)
{
}
//+------------------------------------------------------------------+
//| Validation settings protected data. |
//+------------------------------------------------------------------+
bool CTrailingFixedPips::ValidationSettings(void)
{
if(!CExpertTrailing::ValidationSettings())
return(false);
//--- initial data checks
if(m_profit_level!=0 && m_profit_level*(m_adjusted_point/m_symbol.Point())<m_symbol.StopsLevel())
{
printf(__FUNCTION__+": trailing Profit Level must be 0 or greater than %d",m_symbol.StopsLevel());
return(false);
}
if(m_stop_level!=0 && m_stop_level*(m_adjusted_point/m_symbol.Point())<m_symbol.StopsLevel())
{
printf(__FUNCTION__+": trailing Stop Level must be 0 or greater than %d",m_symbol.StopsLevel());
return(false);
}
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Checking trailing stop and/or profit for long position. |
//+------------------------------------------------------------------+
bool CTrailingFixedPips::CheckTrailingStopLong(CPositionInfo *position,double &sl,double &tp)
{
//--- check
if(position==NULL)
return(false);
if(m_stop_level==0)
return(false);
//---
double delta;
double pos_sl=position.StopLoss();
double base =(pos_sl==0.0) ? position.PriceOpen() : pos_sl;
double price =m_symbol.Bid();
//---
sl=EMPTY_VALUE;
tp=EMPTY_VALUE;
delta=m_stop_level*m_adjusted_point;
if(price-base>delta)
{
sl=price-delta;
if(m_profit_level!=0)
tp=price+m_profit_level*m_adjusted_point;
}
//---
return(sl!=EMPTY_VALUE);
}
//+------------------------------------------------------------------+
//| Checking trailing stop and/or profit for short position. |
//+------------------------------------------------------------------+
bool CTrailingFixedPips::CheckTrailingStopShort(CPositionInfo *position,double &sl,double &tp)
{
//--- check
if(position==NULL)
return(false);
if(m_stop_level==0)
return(false);
//---
double delta;
double pos_sl=position.StopLoss();
double base =(pos_sl==0.0) ? position.PriceOpen() : pos_sl;
double price =m_symbol.Ask();
//---
sl=EMPTY_VALUE;
tp=EMPTY_VALUE;
delta=m_stop_level*m_adjusted_point;
if(base-price>delta)
{
sl=price+delta;
if(m_profit_level!=0)
tp=price-m_profit_level*m_adjusted_point;
}
//---
return(sl!=EMPTY_VALUE);
}
//+------------------------------------------------------------------+
+157
View File
@@ -0,0 +1,157 @@
//+------------------------------------------------------------------+
//| TrailingMA.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Expert\ExpertTrailing.mqh>
// wizard description start
//+------------------------------------------------------------------+
//| Description of the class |
//| Title=Trailing Stop based on MA |
//| Type=Trailing |
//| Name=MA |
//| Class=CTrailingMA |
//| Page= |
//| Parameter=Period,int,12,Period of MA |
//| Parameter=Shift,int,0,Shift of MA |
//| Parameter=Method,ENUM_MA_METHOD,MODE_SMA,Method of averaging |
//| Parameter=Applied,ENUM_APPLIED_PRICE,PRICE_CLOSE,Prices series |
//+------------------------------------------------------------------+
// wizard description end
//+------------------------------------------------------------------+
//| Class CTrailingMA. |
//| Purpose: Class of trailing stops based on MA. |
//| Derives from class CExpertTrailing. |
//+------------------------------------------------------------------+
class CTrailingMA : public CExpertTrailing
{
protected:
CiMA *m_MA;
//--- input parameters
int m_ma_period;
int m_ma_shift;
ENUM_MA_METHOD m_ma_method;
ENUM_APPLIED_PRICE m_ma_applied;
public:
CTrailingMA(void);
~CTrailingMA(void);
//--- methods of initialization of protected data
void Period(int period) { m_ma_period=period; }
void Shift(int shift) { m_ma_shift=shift; }
void Method(ENUM_MA_METHOD method) { m_ma_method=method; }
void Applied(ENUM_APPLIED_PRICE applied) { m_ma_applied=applied; }
virtual bool InitIndicators(CIndicators *indicators);
virtual bool ValidationSettings(void);
//---
virtual bool CheckTrailingStopLong(CPositionInfo *position,double &sl,double &tp);
virtual bool CheckTrailingStopShort(CPositionInfo *position,double &sl,double &tp);
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
void CTrailingMA::CTrailingMA(void) : m_MA(NULL),
m_ma_period(12),
m_ma_shift(0),
m_ma_method(MODE_SMA),
m_ma_applied(PRICE_CLOSE)
{
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
void CTrailingMA::~CTrailingMA(void)
{
}
//+------------------------------------------------------------------+
//| Validation settings protected data. |
//+------------------------------------------------------------------+
bool CTrailingMA::ValidationSettings(void)
{
if(!CExpertTrailing::ValidationSettings())
return(false);
//--- initial data checks
if(m_ma_period<=0)
{
printf(__FUNCTION__+": period MA must be greater than 0");
return(false);
}
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Checking for input parameters and setting protected data. |
//+------------------------------------------------------------------+
bool CTrailingMA::InitIndicators(CIndicators *indicators)
{
//--- check
if(indicators==NULL)
return(false);
//--- create MA indicator
if(m_MA==NULL)
if((m_MA=new CiMA)==NULL)
{
printf(__FUNCTION__+": error creating object");
return(false);
}
//--- add MA indicator to collection
if(!indicators.Add(m_MA))
{
printf(__FUNCTION__+": error adding object");
delete m_MA;
return(false);
}
//--- initialize MA indicator
if(!m_MA.Create(m_symbol.Name(),m_period,m_ma_period,m_ma_shift,m_ma_method,m_ma_applied))
{
printf(__FUNCTION__+": error initializing object");
return(false);
}
m_MA.BufferResize(3+m_ma_shift);
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Checking trailing stop and/or profit for long position. |
//+------------------------------------------------------------------+
bool CTrailingMA::CheckTrailingStopLong(CPositionInfo *position,double &sl,double &tp)
{
//--- check
if(position==NULL)
return(false);
//---
double level =NormalizeDouble(m_symbol.Bid()-m_symbol.StopsLevel()*m_symbol.Point(),m_symbol.Digits());
double new_sl=NormalizeDouble(m_MA.Main(1),m_symbol.Digits());
double pos_sl=position.StopLoss();
double base =(pos_sl==0.0) ? position.PriceOpen() : pos_sl;
//---
sl=EMPTY_VALUE;
tp=EMPTY_VALUE;
if(new_sl>base && new_sl<level)
sl=new_sl;
//---
return(sl!=EMPTY_VALUE);
}
//+------------------------------------------------------------------+
//| Checking trailing stop and/or profit for short position. |
//+------------------------------------------------------------------+
bool CTrailingMA::CheckTrailingStopShort(CPositionInfo *position,double &sl,double &tp)
{
//--- check
if(position==NULL)
return(false);
//---
double level =NormalizeDouble(m_symbol.Ask()+m_symbol.StopsLevel()*m_symbol.Point(),m_symbol.Digits());
double new_sl=NormalizeDouble(m_MA.Main(1)+m_symbol.Spread()*m_symbol.Point(),m_symbol.Digits());
double pos_sl=position.StopLoss();
double base =(pos_sl==0.0) ? position.PriceOpen() : pos_sl;
//---
sl=EMPTY_VALUE;
tp=EMPTY_VALUE;
if(new_sl<base && new_sl>level)
sl=new_sl;
//---
return(sl!=EMPTY_VALUE);
}
//+------------------------------------------------------------------+
+40
View File
@@ -0,0 +1,40 @@
//+------------------------------------------------------------------+
//| TrailingNone.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Expert\ExpertTrailing.mqh>
// wizard description start
//+------------------------------------------------------------------+
//| Description of the class |
//| Title=Trailing Stop not used |
//| Type=Trailing |
//| Name=None |
//| Class=CTrailingNone |
//| Page= |
//+------------------------------------------------------------------+
// wizard description end
//+------------------------------------------------------------------+
//| Class CTrailingNone. |
//| Appointment: Class no traling stops. |
//| Derives from class CExpertTrailing. |
//+------------------------------------------------------------------+
class CTrailingNone : public CExpertTrailing
{
public:
CTrailingNone(void);
~CTrailingNone(void);
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CTrailingNone::CTrailingNone(void)
{
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CTrailingNone::~CTrailingNone(void)
{
}
//+------------------------------------------------------------------+
+123
View File
@@ -0,0 +1,123 @@
//+------------------------------------------------------------------+
//| TrailingParabolicSAR.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Expert\ExpertTrailing.mqh>
// wizard description start
//+------------------------------------------------------------------+
//| Description of the class |
//| Title=Trailing Stop based on Parabolic SAR |
//| Type=Trailing |
//| Name=ParabolicSAR |
//| Class=CTrailingPSAR |
//| Page= |
//| Parameter=Step,double,0.02,Speed increment |
//| Parameter=Maximum,double,0.2,Maximum rate |
//+------------------------------------------------------------------+
// wizard description end
//+------------------------------------------------------------------+
//| Class CTrailingPSAR. |
//| Appointment: Class traling stops with Parabolic SAR. |
//| Derives from class CExpertTrailing. |
//+------------------------------------------------------------------+
class CTrailingPSAR : public CExpertTrailing
{
protected:
CiSAR m_sar; // object-indicator
//--- adjusted parameters
double m_step; // the "speed increment" parameter of the indicator
double m_maximum; // the "maximum rate" parameter of the indicator
public:
CTrailingPSAR(void);
~CTrailingPSAR(void);
//--- methods of setting adjustable parameters
void Step(double step) { m_step=step; }
void Maximum(double maximum) { m_maximum=maximum; }
//--- method of creating the indicator and timeseries
virtual bool InitIndicators(CIndicators *indicators);
//---
virtual bool CheckTrailingStopLong(CPositionInfo *position,double &sl,double &tp);
virtual bool CheckTrailingStopShort(CPositionInfo *position,double &sl,double &tp);
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
void CTrailingPSAR::CTrailingPSAR(void) : m_step(0.02),
m_maximum(0.2)
{
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
void CTrailingPSAR::~CTrailingPSAR(void)
{
}
//+------------------------------------------------------------------+
//| Create indicators. |
//+------------------------------------------------------------------+
bool CTrailingPSAR::InitIndicators(CIndicators *indicators)
{
//--- check pointer
if(indicators==NULL)
return(false);
//--- add object to collection
if(!indicators.Add(GetPointer(m_sar)))
{
printf(__FUNCTION__+": error adding object");
return(false);
}
//--- initialize object
if(!m_sar.Create(m_symbol.Name(),m_period,m_step,m_maximum))
{
printf(__FUNCTION__+": error initializing object");
return(false);
}
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Checking trailing stop and/or profit for long position. |
//+------------------------------------------------------------------+
bool CTrailingPSAR::CheckTrailingStopLong(CPositionInfo *position,double &sl,double &tp)
{
//--- check
if(position==NULL)
return(false);
//---
double level =NormalizeDouble(m_symbol.Bid()-m_symbol.StopsLevel()*m_symbol.Point(),m_symbol.Digits());
double new_sl=NormalizeDouble(m_sar.Main(1),m_symbol.Digits());
double pos_sl=position.StopLoss();
double base =(pos_sl==0.0) ? position.PriceOpen() : pos_sl;
//---
sl=EMPTY_VALUE;
tp=EMPTY_VALUE;
if(new_sl>base && new_sl<level)
sl=new_sl;
//---
return(sl!=EMPTY_VALUE);
}
//+------------------------------------------------------------------+
//| Checking trailing stop and/or profit for short position. |
//+------------------------------------------------------------------+
bool CTrailingPSAR::CheckTrailingStopShort(CPositionInfo *position,double &sl,double &tp)
{
//--- check
if(position==NULL)
return(false);
//---
double level =NormalizeDouble(m_symbol.Ask()+m_symbol.StopsLevel()*m_symbol.Point(),m_symbol.Digits());
double new_sl=NormalizeDouble(m_sar.Main(1)+m_symbol.Spread()*m_symbol.Point(),m_symbol.Digits());
double pos_sl=position.StopLoss();
double base =(pos_sl==0.0) ? position.PriceOpen() : pos_sl;
//---
sl=EMPTY_VALUE;
tp=EMPTY_VALUE;
if(new_sl<base && new_sl>level)
sl=new_sl;
//---
return(sl!=EMPTY_VALUE);
}
//+------------------------------------------------------------------+
+292
View File
@@ -0,0 +1,292 @@
//+------------------------------------------------------------------+
//| File.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Object.mqh>
//+------------------------------------------------------------------+
//| Class CFile. |
//| Purpose: Base class of file operations. |
//| Derives from class CObject. |
//+------------------------------------------------------------------+
class CFile : public CObject
{
protected:
int m_handle; // handle of file
string m_name; // name of opened file
int m_flags; // flags of opened file
public:
CFile(void);
~CFile(void);
//--- methods of access to protected data
int Handle(void) const { return(m_handle); };
string FileName(void) const { return(m_name); };
int Flags(void) const { return(m_flags); };
void SetUnicode(const bool unicode);
void SetCommon(const bool common);
//--- general methods for working with files
int Open(const string file_name,int open_flags,const short delimiter='\t');
void Close(void);
void Delete(void);
ulong Size(void);
ulong Tell(void);
void Seek(const long offset,const ENUM_FILE_POSITION origin);
void Flush(void);
bool IsEnding(void);
bool IsLineEnding(void);
//--- general methods for working with files
void Delete(const string file_name,const int common_flag=0);
bool IsExist(const string file_name,const int common_flag=0);
bool Copy(const string src_name,const int common_flag,const string dst_name,const int mode_flags);
bool Move(const string src_name,const int common_flag,const string dst_name,const int mode_flags);
//--- general methods of working with folders
bool FolderCreate(const string folder_name);
bool FolderDelete(const string folder_name);
bool FolderClean(const string folder_name);
//--- general methods of finding files
long FileFindFirst(const string file_filter,string &returned_filename);
bool FileFindNext(const long search_handle,string &returned_filename);
void FileFindClose(const long search_handle);
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CFile::CFile(void) : m_handle(INVALID_HANDLE),
m_name(""),
m_flags(FILE_ANSI)
{
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CFile::~CFile(void)
{
//--- check handle
if(m_handle!=INVALID_HANDLE)
Close();
}
//+------------------------------------------------------------------+
//| Set the FILE_UNICODE flag |
//+------------------------------------------------------------------+
void CFile::SetUnicode(const bool unicode)
{
//--- check handle
if(m_handle==INVALID_HANDLE)
{
if(unicode)
m_flags|=FILE_UNICODE;
else
m_flags&=~FILE_UNICODE;
}
}
//+------------------------------------------------------------------+
//| Set the "Common Folder" flag |
//+------------------------------------------------------------------+
void CFile::SetCommon(const bool common)
{
//--- check handle
if(m_handle==INVALID_HANDLE)
{
if(common)
m_flags|=FILE_COMMON;
else
m_flags&=~FILE_COMMON;
}
}
//+------------------------------------------------------------------+
//| Open the file |
//+------------------------------------------------------------------+
int CFile::Open(const string file_name,int open_flags,const short delimiter)
{
//--- check handle
if(m_handle!=INVALID_HANDLE)
Close();
//--- action
if((open_flags &(FILE_BIN|FILE_CSV))==0)
open_flags|=FILE_TXT;
//--- open
m_handle=FileOpen(file_name,open_flags|m_flags,delimiter);
if(m_handle!=INVALID_HANDLE)
{
//--- store options of the opened file
m_flags|=open_flags;
m_name=file_name;
}
//--- result
return(m_handle);
}
//+------------------------------------------------------------------+
//| Close the file |
//+------------------------------------------------------------------+
void CFile::Close(void)
{
//--- check handle
if(m_handle!=INVALID_HANDLE)
{
//--- closing the file and resetting all the variables to the initial state
FileClose(m_handle);
m_handle=INVALID_HANDLE;
m_name="";
//--- reset all flags except the text
m_flags&=FILE_ANSI|FILE_UNICODE;
}
}
//+------------------------------------------------------------------+
//| Deleting an open file |
//+------------------------------------------------------------------+
void CFile::Delete(void)
{
//--- check handle
if(m_handle!=INVALID_HANDLE)
{
string file_name=m_name;
int common_flag=m_flags&FILE_COMMON;
//--- close before deleting
Close();
//--- delete
FileDelete(file_name,common_flag);
}
}
//+------------------------------------------------------------------+
//| Get size of opened file |
//+------------------------------------------------------------------+
ulong CFile::Size(void)
{
//--- check handle
if(m_handle!=INVALID_HANDLE)
return(FileSize(m_handle));
//--- failure
return(0);
}
//+------------------------------------------------------------------+
//| Get current position of pointer in file |
//+------------------------------------------------------------------+
ulong CFile::Tell(void)
{
//--- check handle
if(m_handle!=INVALID_HANDLE)
return(FileTell(m_handle));
//--- failure
return(0);
}
//+------------------------------------------------------------------+
//| Set position of pointer in file |
//+------------------------------------------------------------------+
void CFile::Seek(const long offset,const ENUM_FILE_POSITION origin)
{
//--- check handle
if(m_handle!=INVALID_HANDLE)
FileSeek(m_handle,offset,origin);
}
//+------------------------------------------------------------------+
//| Flush data from the file buffer of input-output to disk |
//+------------------------------------------------------------------+
void CFile::Flush(void)
{
//--- check handle
if(m_handle!=INVALID_HANDLE)
FileFlush(m_handle);
}
//+------------------------------------------------------------------+
//| Detect the end of file |
//+------------------------------------------------------------------+
bool CFile::IsEnding(void)
{
//--- check handle
if(m_handle!=INVALID_HANDLE)
return(FileIsEnding(m_handle));
//--- failure
return(false);
}
//+------------------------------------------------------------------+
//| Detect the end of string |
//+------------------------------------------------------------------+
bool CFile::IsLineEnding(void)
{
//--- checking
if(m_handle!=INVALID_HANDLE)
if((m_flags&FILE_BIN)==0)
return(FileIsLineEnding(m_handle));
//--- failure
return(false);
}
//+------------------------------------------------------------------+
//| Deleting a file |
//+------------------------------------------------------------------+
void CFile::Delete(const string file_name,const int common_flag)
{
//--- checking
if(file_name==m_name)
{
int flag=m_flags&FILE_COMMON;
if(flag==common_flag)
Close();
}
//--- delete
FileDelete(file_name,common_flag);
}
//+------------------------------------------------------------------+
//| Check if file exists |
//+------------------------------------------------------------------+
bool CFile::IsExist(const string file_name,const int common_flag)
{
return(FileIsExist(file_name,common_flag));
}
//+------------------------------------------------------------------+
//| Copying file |
//+------------------------------------------------------------------+
bool CFile::Copy(const string src_name,const int common_flag,const string dst_name,const int mode_flags)
{
return(FileCopy(src_name,common_flag,dst_name,mode_flags));
}
//+------------------------------------------------------------------+
//| Move/rename file |
//+------------------------------------------------------------------+
bool CFile::Move(const string src_name,const int common_flag,const string dst_name,const int mode_flags)
{
return(FileMove(src_name,common_flag,dst_name,mode_flags));
}
//+------------------------------------------------------------------+
//| Create folder |
//+------------------------------------------------------------------+
bool CFile::FolderCreate(const string folder_name)
{
return(::FolderCreate(folder_name,m_flags));
}
//+------------------------------------------------------------------+
//| Delete folder |
//+------------------------------------------------------------------+
bool CFile::FolderDelete(const string folder_name)
{
return(::FolderDelete(folder_name,m_flags));
}
//+------------------------------------------------------------------+
//| Clean folder |
//+------------------------------------------------------------------+
bool CFile::FolderClean(const string folder_name)
{
return(::FolderClean(folder_name,m_flags));
}
//+------------------------------------------------------------------+
//| Start search of files |
//+------------------------------------------------------------------+
long CFile::FileFindFirst(const string file_filter,string &returned_filename)
{
return(::FileFindFirst(file_filter,returned_filename,m_flags));
}
//+------------------------------------------------------------------+
//| Continue search of files |
//+------------------------------------------------------------------+
bool CFile::FileFindNext(const long search_handle,string &returned_filename)
{
return(::FileFindNext(search_handle,returned_filename));
}
//+------------------------------------------------------------------+
//| End search of files |
//+------------------------------------------------------------------+
void CFile::FileFindClose(const long search_handle)
{
::FileFindClose(search_handle);
}
//+------------------------------------------------------------------+
+183
View File
@@ -0,0 +1,183 @@
//+------------------------------------------------------------------+
//| FileBMP.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Object.mqh>
//+------------------------------------------------------------------+
//| Bitmap headers |
//+------------------------------------------------------------------+
struct BITMAPFILEHEADER
{
ushort bfType;
uint bfSize;
ushort bfReserved1;
ushort bfReserved2;
uint bfOffBits;
};
struct BITMAPINFOHEADER
{
uint biSize;
int biWidth;
int biHeight;
ushort biPlanes;
ushort biBitCount;
uint biCompression;
uint biSizeImage;
int biXPelsPerMeter;
int biYPelsPerMeter;
uint biClrUsed;
uint biClrImportant;
};
#define BM 0x4D42
//+------------------------------------------------------------------+
//| Class CFileBMP |
//| Purpose: Special class to read and write bmp file |
//| Derives from class CObject. |
//+------------------------------------------------------------------+
class CFileBMP : public CObject
{
protected:
int m_handle;
BITMAPFILEHEADER m_file_header;
BITMAPINFOHEADER m_info_header;
public:
CFileBMP(void);
~CFileBMP(void);
int OpenWrite(const string file_name,bool common_flag=false);
int OpenRead(const string file_name,bool common_flag=false);
int Write32BitsArray(uint& uint_array[],const int width,const int height);
int Read32BitsArray(uint& uint_array[],int& width,int& height);
void Close(void);
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CFileBMP::CFileBMP(void) : m_handle(INVALID_HANDLE)
{
ZeroMemory(m_file_header);
ZeroMemory(m_info_header);
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CFileBMP::~CFileBMP(void)
{
Close();
}
//+------------------------------------------------------------------+
//| Open the file |
//+------------------------------------------------------------------+
int CFileBMP::OpenWrite(const string file_name,bool common_flag)
{
Close();
//--- action
int open_flags=FILE_BIN|FILE_WRITE|FILE_SHARE_READ|FILE_SHARE_WRITE;
if(common_flag)
open_flags|=FILE_COMMON;
//--- open
m_handle=FileOpen(file_name,open_flags);
//--- result
return(m_handle);
}
//+------------------------------------------------------------------+
//| Open the file |
//+------------------------------------------------------------------+
int CFileBMP::OpenRead(const string file_name,bool common_flag)
{
Close();
//--- action
int open_flags=FILE_BIN|FILE_READ|FILE_SHARE_READ|FILE_SHARE_WRITE;
if(common_flag)
open_flags|=FILE_COMMON;
//--- open
m_handle=FileOpen(file_name,open_flags);
//--- check bmp headers
if(m_handle!=INVALID_HANDLE)
{
uint fileheader_size=FileReadStruct(m_handle,m_file_header);
uint infoheader_size=FileReadStruct(m_handle,m_info_header);
//--- it should be a simple 32-bit bmp
if(fileheader_size!=sizeof(m_file_header) ||
infoheader_size!=sizeof(m_info_header) ||
m_file_header.bfType!=BM ||
m_file_header.bfOffBits!=sizeof(m_file_header)+sizeof(m_info_header) ||
m_info_header.biBitCount!=32 ||
m_info_header.biClrUsed!=0)
Close();
}
//--- result
return(m_handle);
}
//+------------------------------------------------------------------+
//| Write the file |
//+------------------------------------------------------------------+
int CFileBMP::Write32BitsArray(uint& uint_array[],const int width,const int height)
{
if(m_handle==INVALID_HANDLE)
return(-1);
//--- check size
int size=width*height;
if(size==0)
return(0);
if(size<0)
size=-size;
if(ArraySize(uint_array)<size)
return(-2);
//--- prepare headers
ZeroMemory(m_file_header);
ZeroMemory(m_info_header);
m_file_header.bfType=BM;
m_file_header.bfSize=sizeof(m_file_header)+sizeof(m_info_header)+size*sizeof(uint);
m_file_header.bfOffBits=sizeof(m_file_header)+sizeof(m_info_header);
m_info_header.biSize=sizeof(m_info_header);
m_info_header.biWidth=width;
m_info_header.biHeight=height;
m_info_header.biPlanes=1;
m_info_header.biBitCount=32;
m_info_header.biSizeImage=size*32;
//--- write bmp-file
FileSeek(m_handle,0,SEEK_SET);
FileWriteStruct(m_handle,m_file_header);
FileWriteStruct(m_handle,m_info_header);
uint written=FileWriteArray(m_handle,uint_array,0,size);
//--- bytes written
return((int)written*sizeof(uint));
}
//+------------------------------------------------------------------+
//| Read the file |
//+------------------------------------------------------------------+
int CFileBMP::Read32BitsArray(uint& uint_array[],int& width,int& height)
{
if(m_handle==INVALID_HANDLE)
return(-1);
//--- store dimensions from header
width=m_info_header.biWidth;
height=m_info_header.biHeight;
//--- check size
int size=width*height;
if(size==0)
return(0);
if(size<0)
size=-size;
//--- read bmp-file
FileSeek(m_handle,sizeof(m_file_header)+sizeof(m_info_header),SEEK_SET);
uint read=FileReadArray(m_handle,uint_array,0,size);
//--- bytes read
return((int)read*sizeof(uint));
}
//+------------------------------------------------------------------+
//| Close the file |
//+------------------------------------------------------------------+
void CFileBMP::Close(void)
{
//--- check handle
if(m_handle!=INVALID_HANDLE)
{
FileClose(m_handle);
m_handle=INVALID_HANDLE;
}
}
//+------------------------------------------------------------------+
+517
View File
@@ -0,0 +1,517 @@
//+------------------------------------------------------------------+
//| FileBin.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include "File.mqh"
//+------------------------------------------------------------------+
//| Class CFileBin |
//| Purpose: Class of operations with binary files |
//| Derives from class CFile |
//+------------------------------------------------------------------+
class CFileBin : public CFile
{
public:
CFileBin(void);
~CFileBin(void);
//--- methods for working with files
int Open(const string file_name,const int open_flags);
//--- methods for writing data
uint WriteChar(const char value);
uint WriteShort(const short value);
uint WriteInteger(const int value);
uint WriteLong(const long value);
uint WriteFloat(const float value);
uint WriteDouble(const double value);
uint WriteString(const string value);
uint WriteString(const string value,const int size);
uint WriteCharArray(const char &array[],const int start_item=0,const int items_count=WHOLE_ARRAY);
uint WriteShortArray(const short& array[],const int start_item=0,const int items_count=WHOLE_ARRAY);
uint WriteIntegerArray(const int& array[],const int start_item=0,const int items_count=WHOLE_ARRAY);
uint WriteLongArray(const long &array[],const int start_item=0,const int items_count=WHOLE_ARRAY);
uint WriteFloatArray(const float &array[],const int start_item=0,const int items_count=WHOLE_ARRAY);
uint WriteDoubleArray(const double &array[],const int start_item=0,const int items_count=WHOLE_ARRAY);
template<typename T>
uint WriteArray(T &array[],const int start_item=0,const int items_count=WHOLE_ARRAY);
template<typename T>
uint WriteStruct(T &data);
bool WriteObject(CObject *object);
template<typename T>
uint WriteEnum(const T value) { return(WriteInteger((int)value)); }
//--- methods for reading data
bool ReadChar(char &value);
bool ReadShort(short &value);
bool ReadInteger(int &value);
bool ReadLong(long &value);
bool ReadFloat(float &value);
bool ReadDouble(double &value);
bool ReadString(string &value);
bool ReadString(string &value,const int size);
uint ReadCharArray(char &array[],const int start_item=0,const int items_count=WHOLE_ARRAY);
uint ReadShortArray(short& array[],const int start_item=0,const int items_count=WHOLE_ARRAY);
uint ReadIntegerArray(int& array[],const int start_item=0,const int items_count=WHOLE_ARRAY);
uint ReadLongArray(long &array[],const int start_item=0,const int items_count=WHOLE_ARRAY);
uint ReadFloatArray(float &array[],const int start_item=0,const int items_count=WHOLE_ARRAY);
uint ReadDoubleArray(double &array[],const int start_item=0,const int items_count=WHOLE_ARRAY);
template<typename T>
uint ReadArray(T &array[],const int start_item=0,const int items_count=WHOLE_ARRAY);
template<typename T>
uint ReadStruct(T &data);
bool ReadObject(CObject *object);
template<typename T>
bool ReadEnum(T &value);
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CFileBin::CFileBin(void)
{
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CFileBin::~CFileBin(void)
{
}
//+------------------------------------------------------------------+
//| Opening a binary file |
//+------------------------------------------------------------------+
int CFileBin::Open(const string file_name,const int open_flags)
{
return(CFile::Open(file_name,open_flags|FILE_BIN));
}
//+------------------------------------------------------------------+
//| Write a variable of char or uchar type |
//+------------------------------------------------------------------+
uint CFileBin::WriteChar(const char value)
{
//--- check handle
if(m_handle!=INVALID_HANDLE)
return(FileWriteInteger(m_handle,value,sizeof(char)));
//--- failure
return(0);
}
//+------------------------------------------------------------------+
//| Write a variable of short or ushort type |
//+------------------------------------------------------------------+
uint CFileBin::WriteShort(const short value)
{
//--- check handle
if(m_handle!=INVALID_HANDLE)
return(FileWriteInteger(m_handle,value,sizeof(short)));
//--- failure
return(0);
}
//+------------------------------------------------------------------+
//| Write a variable of int or uint type |
//+------------------------------------------------------------------+
uint CFileBin::WriteInteger(const int value)
{
//--- check handle
if(m_handle!=INVALID_HANDLE)
return(FileWriteInteger(m_handle,value,sizeof(int)));
//--- failure
return(0);
}
//+------------------------------------------------------------------+
//| Write a variable of long or ulong type |
//+------------------------------------------------------------------+
uint CFileBin::WriteLong(const long value)
{
//--- check handle
if(m_handle!=INVALID_HANDLE)
return(FileWriteLong(m_handle,value));
//--- failure
return(0);
}
//+------------------------------------------------------------------+
//| Write a variable of float type |
//+------------------------------------------------------------------+
uint CFileBin::WriteFloat(const float value)
{
//--- check handle
if(m_handle!=INVALID_HANDLE)
return(FileWriteFloat(m_handle,value));
//--- failure
return(0);
}
//+------------------------------------------------------------------+
//| Write a variable of double type |
//+------------------------------------------------------------------+
uint CFileBin::WriteDouble(const double value)
{
//--- check handle
if(m_handle!=INVALID_HANDLE)
return(FileWriteDouble(m_handle,value));
//--- failure
return(0);
}
//+------------------------------------------------------------------+
//| Write a variable of string type |
//+------------------------------------------------------------------+
uint CFileBin::WriteString(const string value)
{
//--- check handle
if(m_handle!=INVALID_HANDLE)
{
//--- size of string
int size=StringLen(value);
//--- write
if(FileWriteInteger(m_handle,size)==sizeof(int))
return(FileWriteString(m_handle,value,size));
}
//--- failure
return(0);
}
//+------------------------------------------------------------------+
//| Write a part of string |
//+------------------------------------------------------------------+
uint CFileBin::WriteString(const string value,const int size)
{
//--- check handle
if(m_handle!=INVALID_HANDLE)
return(FileWriteString(m_handle,value,size));
//--- failure
return(0);
}
//+------------------------------------------------------------------+
//| Write array variables of type char or uchar |
//+------------------------------------------------------------------+
uint CFileBin::WriteCharArray(const char &array[],const int start_item,const int items_count)
{
//--- check handle
if(m_handle!=INVALID_HANDLE)
return(FileWriteArray(m_handle,array,start_item,items_count));
//--- failure
return(0);
}
//+------------------------------------------------------------------+
//| Write an array of variables of short or ushort type |
//+------------------------------------------------------------------+
uint CFileBin::WriteShortArray(const short &array[],const int start_item,const int items_count)
{
//--- check handle
if(m_handle!=INVALID_HANDLE)
return(FileWriteArray(m_handle,array,start_item,items_count));
//--- failure
return(0);
}
//+------------------------------------------------------------------+
//| Write an array of variables of int or uint type |
//+------------------------------------------------------------------+
uint CFileBin::WriteIntegerArray(const int &array[],const int start_item,const int items_count)
{
//--- check handle
if(m_handle!=INVALID_HANDLE)
return(FileWriteArray(m_handle,array,start_item,items_count));
//--- failure
return(0);
}
//+------------------------------------------------------------------+
//| Write an array of variables of long or ulong type |
//+------------------------------------------------------------------+
uint CFileBin::WriteLongArray(const long &array[],const int start_item,const int items_count)
{
//--- check handle
if(m_handle!=INVALID_HANDLE)
return(FileWriteArray(m_handle,array,start_item,items_count));
//--- failure
return(0);
}
//+------------------------------------------------------------------+
//| Write an array of variables of float type |
//+------------------------------------------------------------------+
uint CFileBin::WriteFloatArray(const float &array[],const int start_item,const int items_count)
{
//--- check handle
if(m_handle!=INVALID_HANDLE)
return(FileWriteArray(m_handle,array,start_item,items_count));
//--- failure
return(0);
}
//+------------------------------------------------------------------+
//| Write an array of variables of double type |
//+------------------------------------------------------------------+
uint CFileBin::WriteDoubleArray(const double &array[],const int start_item,const int items_count)
{
//--- check handle
if(m_handle!=INVALID_HANDLE)
return(FileWriteArray(m_handle,array,start_item,items_count));
//--- failure
return(0);
}
//+------------------------------------------------------------------+
//| Write an array of variables of any type |
//+------------------------------------------------------------------+
template<typename T>
uint CFileBin::WriteArray(T &array[],const int start_item=0,const int items_count=WHOLE_ARRAY)
{
//--- check handle
if(m_handle!=INVALID_HANDLE)
return(FileWriteArray(m_handle,array,start_item,items_count));
//--- failure
return(0);
}
//+------------------------------------------------------------------+
//| Write an structure |
//+------------------------------------------------------------------+
template<typename T>
uint CFileBin::WriteStruct(T &data)
{
//--- check handle
if(m_handle!=INVALID_HANDLE)
return(FileWriteStruct(m_handle,data));
//--- failure
return(0);
}
//+------------------------------------------------------------------+
//| Write data of an instance of the CObject class |
//+------------------------------------------------------------------+
bool CFileBin::WriteObject(CObject *object)
{
//--- check handle & object
if(m_handle!=INVALID_HANDLE)
if(CheckPointer(object))
return(object.Save(m_handle));
//--- failure
return(false);
}
//+------------------------------------------------------------------+
//| Read a variable of char or uchar type |
//+------------------------------------------------------------------+
bool CFileBin::ReadChar(char &value)
{
//--- check handle
if(m_handle!=INVALID_HANDLE)
{
ResetLastError();
value=(char)FileReadInteger(m_handle,sizeof(char));
return(GetLastError()==0);
}
//--- failure
return(false);
}
//+------------------------------------------------------------------+
//| Read a variable of short or ushort type |
//+------------------------------------------------------------------+
bool CFileBin::ReadShort(short &value)
{
//--- check handle
if(m_handle!=INVALID_HANDLE)
{
ResetLastError();
value=(short)FileReadInteger(m_handle,sizeof(short));
return(GetLastError()==0);
}
//--- failure
return(false);
}
//+------------------------------------------------------------------+
//| Read a variable of int or uint type |
//+------------------------------------------------------------------+
bool CFileBin::ReadInteger(int &value)
{
//--- check handle
if(m_handle!=INVALID_HANDLE)
{
ResetLastError();
value=FileReadInteger(m_handle,sizeof(int));
return(GetLastError()==0);
}
//--- failure
return(false);
}
//+------------------------------------------------------------------+
//| Read a variable of long or ulong type |
//+------------------------------------------------------------------+
bool CFileBin::ReadLong(long &value)
{
//--- check handle
if(m_handle!=INVALID_HANDLE)
{
ResetLastError();
value=FileReadLong(m_handle);
return(GetLastError()==0);
}
//--- failure
return(false);
}
//+------------------------------------------------------------------+
//| Read a variable of float type |
//+------------------------------------------------------------------+
bool CFileBin::ReadFloat(float &value)
{
//--- check handle
if(m_handle!=INVALID_HANDLE)
{
ResetLastError();
value=FileReadFloat(m_handle);
return(GetLastError()==0);
}
//--- failure
return(false);
}
//+------------------------------------------------------------------+
//| Read a variable of double type |
//+------------------------------------------------------------------+
bool CFileBin::ReadDouble(double &value)
{
//--- check handle
if(m_handle!=INVALID_HANDLE)
{
ResetLastError();
value=FileReadDouble(m_handle);
return(GetLastError()==0);
}
//--- failure
return(false);
}
//+------------------------------------------------------------------+
//| Read a variable of string type |
//+------------------------------------------------------------------+
bool CFileBin::ReadString(string &value)
{
//--- check handle
if(m_handle!=INVALID_HANDLE)
{
ResetLastError();
int size=FileReadInteger(m_handle);
if(GetLastError()==0)
{
value=FileReadString(m_handle,size);
return(size==StringLen(value));
}
}
//--- failure
return(false);
}
//+------------------------------------------------------------------+
//| Read a part of string |
//+------------------------------------------------------------------+
bool CFileBin::ReadString(string &value,const int size)
{
//--- check handle
if(m_handle!=INVALID_HANDLE)
{
value=FileReadString(m_handle,size);
return(size==StringLen(value));
}
//--- failure
return(false);
}
//+------------------------------------------------------------------+
//| Read an array of variables of char or uchar type |
//+------------------------------------------------------------------+
uint CFileBin::ReadCharArray(char &array[],const int start_item,const int items_count)
{
//--- check handle
if(m_handle!=INVALID_HANDLE)
return(FileReadArray(m_handle,array,start_item,items_count));
//--- failure
return(0);
}
//+------------------------------------------------------------------+
//| Read an array of variables of short or ushort type |
//+------------------------------------------------------------------+
uint CFileBin::ReadShortArray(short &array[],const int start_item,const int items_count)
{
//--- check handle
if(m_handle!=INVALID_HANDLE)
return(FileReadArray(m_handle,array,start_item,items_count));
//--- failure
return(0);
}
//+------------------------------------------------------------------+
//| Read an array of variables of int or uint type |
//+------------------------------------------------------------------+
uint CFileBin::ReadIntegerArray(int &array[],const int start_item,const int items_count)
{
//--- check handle
if(m_handle!=INVALID_HANDLE)
return(FileReadArray(m_handle,array,start_item,items_count));
//--- failure
return(0);
}
//+------------------------------------------------------------------+
//| Read an array of variables of long or ulong type |
//+------------------------------------------------------------------+
uint CFileBin::ReadLongArray(long &array[],const int start_item,const int items_count)
{
//--- check handle
if(m_handle!=INVALID_HANDLE)
return(FileReadArray(m_handle,array,start_item,items_count));
//--- failure
return(0);
}
//+------------------------------------------------------------------+
//| Read an array of variables of float type |
//+------------------------------------------------------------------+
uint CFileBin::ReadFloatArray(float &array[],const int start_item,const int items_count)
{
//--- check handle
if(m_handle!=INVALID_HANDLE)
return(FileReadArray(m_handle,array,start_item,items_count));
//--- failure
return(0);
}
//+------------------------------------------------------------------+
//| Read an array of variables of double type |
//+------------------------------------------------------------------+
uint CFileBin::ReadDoubleArray(double &array[],const int start_item,const int items_count)
{
//--- check handle
if(m_handle!=INVALID_HANDLE)
return(FileReadArray(m_handle,array,start_item,items_count));
//--- failure
return(0);
}
//+------------------------------------------------------------------+
//| Read an array of variables of any type |
//+------------------------------------------------------------------+
template<typename T>
uint CFileBin::ReadArray(T &array[],const int start_item=0,const int items_count=WHOLE_ARRAY)
{
//--- check handle
if(m_handle!=INVALID_HANDLE)
return(FileReadArray(m_handle,array,start_item,items_count));
//--- failure
return(0);
}
//+------------------------------------------------------------------+
//| Read an structure |
//+------------------------------------------------------------------+
template<typename T>
uint CFileBin::ReadStruct(T &data)
{
//--- check handle
if(m_handle!=INVALID_HANDLE)
return(FileReadStruct(m_handle,data));
//--- failure
return(0);
}
//+------------------------------------------------------------------+
//| Read data of an instance of the CObject class |
//+------------------------------------------------------------------+
bool CFileBin::ReadObject(CObject *object)
{
//--- check handle & object
if(m_handle!=INVALID_HANDLE)
if(CheckPointer(object))
return(object.Load(m_handle));
//--- failure
return(false);
}
//+------------------------------------------------------------------+
//| Read a variable of an enumeration type |
//+------------------------------------------------------------------+
template<typename T>
bool CFileBin::ReadEnum(T &value)
{
int val;
if(!ReadInteger(val))
return(false);
//---
value=(T)val;
return(true);
}
//+------------------------------------------------------------------+
+347
View File
@@ -0,0 +1,347 @@
//+------------------------------------------------------------------+
//| FilePipe.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include "File.mqh"
//+------------------------------------------------------------------+
//| Class CFilePipe |
//| Purpose: Class of operations with binary files |
//| Derives from class CFile |
//+------------------------------------------------------------------+
class CFilePipe : public CFile
{
public:
CFilePipe(void);
~CFilePipe(void);
//--- methods for working with files
int Open(const string file_name,const int open_flags);
//--- wait for incoming data
bool WaitForRead(const ulong size);
//--- methods for writing data
template<typename T>
uint WriteInteger(const T value);
uint WriteLong(const long value);
uint WriteFloat(const float value);
uint WriteDouble(const double value);
uint WriteString(const string value);
uint WriteString(const string value,const int size);
template<typename T>
uint WriteArray(T &array[],const int start_item=0,const int items_count=WHOLE_ARRAY);
template<typename T>
uint WriteStruct(T &data);
bool WriteObject(CObject *object);
template<typename T>
uint WriteEnum(const T value) { return(WriteInteger((int)value)); }
//--- methods for reading data
template<typename T>
bool ReadInteger(T &value);
bool ReadLong(long &value);
bool ReadFloat(float &value);
bool ReadDouble(double &value);
bool ReadString(string &value);
bool ReadString(string &value,const int size);
template<typename T>
uint ReadArray(T &array[],const int start_item=0,const int items_count=WHOLE_ARRAY);
template<typename T>
uint ReadStruct(T &data);
bool ReadObject(CObject *object);
template<typename T>
bool ReadEnum(T &value);
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CFilePipe::CFilePipe(void)
{
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CFilePipe::~CFilePipe(void)
{
}
//+------------------------------------------------------------------+
//| Opening a binary file |
//+------------------------------------------------------------------+
int CFilePipe::Open(const string file_name,const int open_flags)
{
return(CFile::Open(file_name,open_flags|FILE_BIN));
}
//+------------------------------------------------------------------+
//| Wait for incoming data |
//+------------------------------------------------------------------+
bool CFilePipe::WaitForRead(const ulong size)
{
//--- check handle and stop flag
while(m_handle!=INVALID_HANDLE && !IsStopped())
{
//--- enought data?
if(FileSize(m_handle)>=size)
return(true);
//--- wait a little
Sleep(1);
}
//--- failure
return(false);
}
//+------------------------------------------------------------------+
//| Write a variable of integer types |
//+------------------------------------------------------------------+
template<typename T>
uint CFilePipe::WriteInteger(const T value)
{
//--- check handle
if(m_handle!=INVALID_HANDLE)
return(FileWriteInteger(m_handle,value,sizeof(T)));
//--- failure
return(0);
}
//+------------------------------------------------------------------+
//| Write a variable of long or ulong type |
//+------------------------------------------------------------------+
uint CFilePipe::WriteLong(const long value)
{
//--- check handle
if(m_handle!=INVALID_HANDLE)
return(FileWriteLong(m_handle,value));
//--- failure
return(0);
}
//+------------------------------------------------------------------+
//| Write a variable of float type |
//+------------------------------------------------------------------+
uint CFilePipe::WriteFloat(const float value)
{
//--- check handle
if(m_handle!=INVALID_HANDLE)
return(FileWriteFloat(m_handle,value));
//--- failure
return(0);
}
//+------------------------------------------------------------------+
//| Write a variable of double type |
//+------------------------------------------------------------------+
uint CFilePipe::WriteDouble(const double value)
{
//--- check handle
if(m_handle!=INVALID_HANDLE)
return(FileWriteDouble(m_handle,value));
//--- failure
return(0);
}
//+------------------------------------------------------------------+
//| Write a variable of string type |
//+------------------------------------------------------------------+
uint CFilePipe::WriteString(const string value)
{
//--- check handle
if(m_handle!=INVALID_HANDLE)
{
//--- size of string
int size=StringLen(value);
//--- write
if(FileWriteInteger(m_handle,size)==sizeof(int))
return(FileWriteString(m_handle,value,size));
}
//--- failure
return(0);
}
//+------------------------------------------------------------------+
//| Write a part of string |
//+------------------------------------------------------------------+
uint CFilePipe::WriteString(const string value,const int size)
{
//--- check handle
if(m_handle!=INVALID_HANDLE)
return(FileWriteString(m_handle,value,size));
//--- failure
return(0);
}
//+------------------------------------------------------------------+
//| Write an array of variables of any type |
//+------------------------------------------------------------------+
template<typename T>
uint CFilePipe::WriteArray(T &array[],const int start_item=0,const int items_count=WHOLE_ARRAY)
{
//--- check handle
if(m_handle!=INVALID_HANDLE)
return(FileWriteArray(m_handle,array,start_item,items_count));
//--- failure
return(0);
}
//+------------------------------------------------------------------+
//| Write an structure |
//+------------------------------------------------------------------+
template<typename T>
uint CFilePipe::WriteStruct(T &data)
{
//--- check handle
if(m_handle!=INVALID_HANDLE)
return(FileWriteStruct(m_handle,data));
//--- failure
return(0);
}
//+------------------------------------------------------------------+
//| Write data of an instance of the CObject class |
//+------------------------------------------------------------------+
bool CFilePipe::WriteObject(CObject *object)
{
//--- check handle & object
if(m_handle!=INVALID_HANDLE)
if(CheckPointer(object))
return(object.Save(m_handle));
//--- failure
return(false);
}
//+------------------------------------------------------------------+
//| Read a variable of integer types |
//+------------------------------------------------------------------+
template<typename T>
bool CFilePipe::ReadInteger(T &value)
{
//--- check for data
if(WaitForRead(sizeof(T)))
{
ResetLastError();
value=FileReadInteger(m_handle,sizeof(T));
return(GetLastError()==0);
}
//--- failure
return(false);
}
//+------------------------------------------------------------------+
//| Read a variable of long or ulong type |
//+------------------------------------------------------------------+
bool CFilePipe::ReadLong(long &value)
{
//--- check handle
if(WaitForRead(sizeof(long)))
{
ResetLastError();
value=FileReadLong(m_handle);
return(GetLastError()==0);
}
//--- failure
return(false);
}
//+------------------------------------------------------------------+
//| Read a variable of float type |
//+------------------------------------------------------------------+
bool CFilePipe::ReadFloat(float &value)
{
//--- check for data
if(WaitForRead(sizeof(float)))
{
ResetLastError();
value=FileReadFloat(m_handle);
return(GetLastError()==0);
}
//--- failure
return(false);
}
//+------------------------------------------------------------------+
//| Read a variable of double type |
//+------------------------------------------------------------------+
bool CFilePipe::ReadDouble(double &value)
{
//--- check for data
if(WaitForRead(sizeof(double)))
{
ResetLastError();
value=FileReadDouble(m_handle);
return(GetLastError()==0);
}
//--- failure
return(false);
}
//+------------------------------------------------------------------+
//| Read a variable of string type |
//+------------------------------------------------------------------+
bool CFilePipe::ReadString(string &value)
{
//--- check for data
if(WaitForRead(sizeof(int)))
{
ResetLastError();
int size=FileReadInteger(m_handle);
if(GetLastError()==0)
{
//--- check for data
if(WaitForRead(size))
{
value=FileReadString(m_handle,size);
return(size==StringLen(value));
}
}
}
//--- failure
return(false);
}
//+------------------------------------------------------------------+
//| Read a part of string |
//+------------------------------------------------------------------+
bool CFilePipe::ReadString(string &value,const int size)
{
//--- check for data
if(WaitForRead(size))
{
value=FileReadString(m_handle,size);
return(size==StringLen(value));
}
//--- failure
return(false);
}
//+------------------------------------------------------------------+
//| Read an array of variables of any type |
//+------------------------------------------------------------------+
template<typename T>
uint CFilePipe::ReadArray(T &array[],const int start_item=0,const int items_count=WHOLE_ARRAY)
{
//--- calculate size
uint size=ArraySize(array);
if(items_count!=WHOLE_ARRAY) size=items_count;
//--- check for data
if(WaitForRead(size*sizeof(T)))
return(FileReadArray(m_handle,array,start_item,items_count));
//--- failure
return(0);
}
//+------------------------------------------------------------------+
//| Read an structure |
//+------------------------------------------------------------------+
template<typename T>
uint CFilePipe::ReadStruct(T &data)
{
//--- check for data
if(WaitForRead(sizeof(T)))
return(FileReadStruct(m_handle,data));
//--- failure
return(0);
}
//+------------------------------------------------------------------+
//| Read data of an instance of the CObject class |
//+------------------------------------------------------------------+
bool CFilePipe::ReadObject(CObject *object)
{
//--- check for object & data
if(CheckPointer(object))
if(WaitForRead(sizeof(int))) // only 4 bytes!
return(object.Load(m_handle));
//--- failure
return(false);
}
//+------------------------------------------------------------------+
//| Read a variable of an enumeration type |
//+------------------------------------------------------------------+
template<typename T>
bool CFilePipe::ReadEnum(T &value)
{
int val;
if(!ReadInteger(val))
return(false);
//---
value=(T)val;
return(true);
}
//+------------------------------------------------------------------+
+64
View File
@@ -0,0 +1,64 @@
//+------------------------------------------------------------------+
//| FileTxt.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include "File.mqh"
//+------------------------------------------------------------------+
//| Class CFileTxt |
//| Purpose: Class of operations with text files. |
//| Derives from class CFile. |
//+------------------------------------------------------------------+
class CFileTxt : public CFile
{
public:
CFileTxt(void);
~CFileTxt(void);
//--- methods for working with files
int Open(const string file_name,const int open_flags);
//--- methods to access data
uint WriteString(const string value);
string ReadString(void);
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CFileTxt::CFileTxt(void)
{
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CFileTxt::~CFileTxt(void)
{
}
//+------------------------------------------------------------------+
//| Open the text file |
//+------------------------------------------------------------------+
int CFileTxt::Open(const string file_name,const int open_flags)
{
return(CFile::Open(file_name,open_flags|FILE_TXT));
}
//+------------------------------------------------------------------+
//| Writing string to file |
//+------------------------------------------------------------------+
uint CFileTxt::WriteString(const string value)
{
//--- check handle
if(m_handle!=INVALID_HANDLE)
return(FileWriteString(m_handle,value));
//--- failure
return(0);
}
//+------------------------------------------------------------------+
//| Reading string from file |
//+------------------------------------------------------------------+
string CFileTxt::ReadString(void)
{
//--- check handle
if(m_handle!=INVALID_HANDLE)
return(FileReadString(m_handle));
//--- failure
return("");
}
//+------------------------------------------------------------------+
Binary file not shown.
+622
View File
@@ -0,0 +1,622 @@
//+------------------------------------------------------------------+
//| HashMap.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Generic\Interfaces\IMap.mqh>
#include <Generic\Interfaces\IEqualityComparer.mqh>
#include <Generic\Internal\DefaultEqualityComparer.mqh>
#include <Generic\Interfaces\IComparable.mqh>
#include <Generic\Internal\CompareFunction.mqh>
#include "HashSet.mqh"
//+------------------------------------------------------------------+
//| Struct Entry<TKey, TValue>. |
//| Usage: Internal structure for organization CHashMap<T>. |
//+------------------------------------------------------------------+
template<typename TKey,typename TValue>
struct Entry: public Slot<TValue>
{
public:
TKey key;
Entry(void): key((TKey)NULL) {}
};
//+------------------------------------------------------------------+
//| Class CKeyValuePair<TKey, TValue>. |
//| Usage: Defines a key/value pair that can be set or retrieved. |
//+------------------------------------------------------------------+
template<typename TKey,typename TValue>
class CKeyValuePair: public IComparable<CKeyValuePair<TKey,TValue>*>
{
protected:
TKey m_key;
TValue m_value;
public:
CKeyValuePair(void) { }
CKeyValuePair(TKey key,TValue value): m_key(key), m_value(value) { }
~CKeyValuePair(void) { }
//--- methods to access protected data
TKey Key(void) { return(m_key); }
void Key(TKey key) { m_key=key; }
TValue Value(void) { return(m_value); }
void Value(TValue value) { m_value=value; }
//--- method to create clone of current instance
CKeyValuePair<TKey,TValue>*Clone(void) { return new CKeyValuePair<TKey,TValue>(m_key,m_value); }
//--- method to compare keys
int Compare(CKeyValuePair<TKey,TValue>*pair) { return ::Compare(m_key,pair.m_key); }
//--- method for determining equality
bool Equals(CKeyValuePair<TKey,TValue>*pair) { return ::Equals(m_key,pair.m_key); }
//--- method to calculate hash code
int HashCode(void) { return ::GetHashCode(m_key); }
};
//+------------------------------------------------------------------+
//| Class CKeyValuePairComparer<TKey, TValue>. |
//| Usage: Provides a comparer class for convertation IComparer<TKey>|
//| to the IComparer<CKeyValuePair<TKey, TValue>*> interface. |
//+------------------------------------------------------------------+
template<typename TKey,typename TValue>
class CKeyValuePairComparer: public IComparer<CKeyValuePair<TKey,TValue>*>
{
private:
IComparer<TKey>*m_comparer;
public:
CKeyValuePairComparer(IComparer<TKey>*comaprer) { m_comparer=comaprer; }
int Compare(CKeyValuePair<TKey,TValue>* x,CKeyValuePair<TKey,TValue>* y) { return(m_comparer.Compare(x.Key(), y.Key())); }
};
//+------------------------------------------------------------------+
//| Class CHashMap<TKey, TValue>. |
//| Usage: Represents a collection of keys and values. |
//+------------------------------------------------------------------+
template<typename TKey,typename TValue>
class CHashMap: public IMap<TKey,TValue>
{
protected:
int m_buckets[];
Entry<TKey,TValue>m_entries[];
int m_count;
int m_capacity;
int m_free_list;
int m_free_count;
IEqualityComparer<TKey>*m_comparer;
bool m_delete_comparer;
public:
CHashMap(void);
CHashMap(const int capacity);
CHashMap(IEqualityComparer<TKey>*comparer);
CHashMap(const int capacity,IEqualityComparer<TKey>*comparer);
CHashMap(IMap<TKey,TValue>*map);
CHashMap(IMap<TKey,TValue>*map,IEqualityComparer<TKey>*comparer);
~CHashMap(void);
//--- methods of filling data
bool Add(CKeyValuePair<TKey,TValue>*pair);
bool Add(TKey key,TValue value);
//--- methods of access to protected data
int Count(void) { return(m_count-m_free_count); }
IEqualityComparer<TKey>*Comparer(void) const { return(m_comparer); }
bool Contains(CKeyValuePair<TKey,TValue>*item);
bool Contains(TKey key,TValue value);
bool ContainsKey(TKey key);
bool ContainsValue(TValue value);
//--- methods of copy data from collection
int CopyTo(CKeyValuePair<TKey,TValue>*&dst_array[],const int dst_start=0);
int CopyTo(TKey &dst_keys[],TValue &dst_values[],const int dst_start=0);
//--- methods of cleaning and deleting
void Clear(void);
bool Remove(CKeyValuePair<TKey,TValue>*item);
bool Remove(TKey key);
//--- method of access to the data
bool TryGetValue(TKey key,TValue &value);
bool TrySetValue(TKey key,TValue value);
private:
void Initialize(const int capacity);
bool Resize(int new_size);
int FindEntry(TKey key);
bool Insert(TKey key,TValue value,const bool add);
static int m_collision_threshold;
};
//+------------------------------------------------------------------+
//| Initializes a new instance of the CHashMap<TKey,TValue> class |
//| that is empty, has the default initial capacity, and uses the |
//| default equality comparer for the key type. |
//+------------------------------------------------------------------+
template<typename TKey,typename TValue>
CHashMap::CHashMap(void): m_count(0),
m_free_list(0),
m_free_count(0),
m_capacity(0)
{
//--- use default equality comaprer
m_comparer=new CDefaultEqualityComparer<TKey>();
m_delete_comparer=true;
}
//+------------------------------------------------------------------+
//| Initializes a new instance of the CHashMap<TKey,TValue> class |
//| that is empty, has the specified initial capacity, and uses the |
//| default equality comparer for the key type. |
//+------------------------------------------------------------------+
template<typename TKey,typename TValue>
CHashMap::CHashMap(const int capacity): m_count(0),
m_free_list(0),
m_free_count(0),
m_capacity(0)
{
//--- set capacity
if(capacity>0)
Initialize(capacity);
//--- use default equality comaprer
m_comparer=new CDefaultEqualityComparer<TKey>();
m_delete_comparer=true;
}
//+------------------------------------------------------------------+
//| Initializes a new instance of the CHashMap<TKey,TValue> class |
//| that is empty, has the default initial capacity, and uses the |
//| specified IEqualityComparer<TKey>. |
//+------------------------------------------------------------------+
template<typename TKey,typename TValue>
CHashMap::CHashMap(IEqualityComparer<TKey>*comparer): m_count(0),
m_free_list(0),
m_free_count(0),
m_capacity(0)
{
//--- check equality comaprer
if(CheckPointer(comparer)==POINTER_INVALID)
{
//--- use default equality comaprer
m_comparer=new CDefaultEqualityComparer<TKey>();
m_delete_comparer=true;
}
else
{
//--- use specified equality comaprer
m_comparer=comparer;
m_delete_comparer=false;
}
}
//+------------------------------------------------------------------+
//| Initializes a new instance of the CHashMap<TKey,TValue> class |
//| that is empty, has the specified initial capacity, and uses the |
//| specified IEqualityComparer<TKey>. |
//+------------------------------------------------------------------+
template<typename TKey,typename TValue>
CHashMap::CHashMap(const int capacity,IEqualityComparer<TKey>*comparer): m_count(0),
m_free_list(0),
m_free_count(0),
m_capacity(0)
{
if(capacity>0)
Initialize(capacity);
//--- check equality comaprer
if(CheckPointer(comparer)==POINTER_INVALID)
{
//--- use default equality comaprer
m_comparer=new CDefaultEqualityComparer<TKey>();
m_delete_comparer=true;
}
else
{
//--- use specified equality comaprer
m_comparer=comparer;
m_delete_comparer=false;
}
}
//+------------------------------------------------------------------+
//| Initializes a new instance of the CHashMap<TKey,TValue> class |
//| that contains elements copied from the specified |
//| IMap<TKey,TValue> and uses the default equality comparer for the |
//| key type. |
//+------------------------------------------------------------------+
template<typename TKey,typename TValue>
CHashMap::CHashMap(IMap<TKey,TValue>*map): m_count(0),
m_free_list(0),
m_free_count(0),
m_capacity(0)
{
//--- use default equality comaprer
m_comparer=new CDefaultEqualityComparer<TKey>();
m_delete_comparer=true;
//--- check map
if(CheckPointer(map)!=POINTER_INVALID && map.Count()>0)
{
//--- set capacity
Initialize(map.Count());
TKey keys[];
TValue values[];
map.CopyTo(keys,values);
//--- copy all keys and values from specified map to current map
for(int i=0; i<map.Count(); i++)
Add(keys[i],values[i]);
}
}
//+------------------------------------------------------------------+
//| Initializes a new instance of the CHashMap<TKey,TValue> class |
//| that contains elements copied from the specified |
//| IMap<TKey,TValue> and uses the specified IEqualityComparer<TKey>.|
//+------------------------------------------------------------------+
template<typename TKey,typename TValue>
CHashMap::CHashMap(IMap<TKey,TValue>*map,IEqualityComparer<TKey>*comparer): m_count(0),
m_free_list(0),
m_free_count(0),
m_capacity(0)
{
//--- check equality comaprer
if(CheckPointer(comparer)==POINTER_INVALID)
{
//--- use default equality comaprer
m_comparer=new CDefaultEqualityComparer<TKey>();
m_delete_comparer=true;
}
else
{
//--- use specified equality comaprer
m_comparer=comparer;
m_delete_comparer=false;
}
//--- check map
if(CheckPointer(map)!=POINTER_INVALID && map.Count()>0)
{
//--- set capacity
Initialize(map.Count());
TKey keys[];
TValue values[];
map.CopyTo(keys,values);
//--- copy all keys and values from specified map to current map
for(int i=0; i<map.Count(); i++)
Add(keys[i],values[i]);
}
}
//+------------------------------------------------------------------+
//| Destructor. |
//+------------------------------------------------------------------+
template<typename TKey,typename TValue>
CHashMap::~CHashMap(void)
{
if(m_delete_comparer)
delete m_comparer;
}
//+------------------------------------------------------------------+
//| Adds the specified key-value pair to the map. |
//+------------------------------------------------------------------+
template<typename TKey,typename TValue>
bool CHashMap::Add(CKeyValuePair<TKey,TValue>*pair)
{
//--- check pair
if(CheckPointer(pair)==POINTER_INVALID)
return(false);
return(Add(pair.Key(),pair.Value()));
}
//+------------------------------------------------------------------+
//| Adds the specified key and value to the map. |
//+------------------------------------------------------------------+
template<typename TKey,typename TValue>
bool CHashMap::Add(TKey key,TValue value)
{
return(Insert(key,value,true));
}
//+------------------------------------------------------------------+
//| Determines whether the map contains the specified key-value pair.|
//+------------------------------------------------------------------+
template<typename TKey,typename TValue>
bool CHashMap::Contains(CKeyValuePair<TKey,TValue>*item)
{
//--- check pair
if(CheckPointer(item)==POINTER_INVALID)
return(false);
//--- find pair with specified key
int i=FindEntry(item.Key());
//--- create default equality value comparer
CDefaultEqualityComparer<TValue>comparer;
//--- check value is equal value from the found pair
if(i>=0 && comparer.Equals(m_entries[i].value,item.Value()))
return(true);
else
return(false);
}
//+------------------------------------------------------------------+
//| Determines whether the map contains the specified key with value.|
//+------------------------------------------------------------------+
template<typename TKey,typename TValue>
bool CHashMap::Contains(TKey key,TValue value)
{
//--- find pair with specified key
int i=FindEntry(key);
//--- create default equality value comparer
CDefaultEqualityComparer<TValue>comparer;
//--- check value is equal value from the found pair
if(i>=0 && comparer.Equals(m_entries[i].value,value))
return(true);
else
return(false);
}
//+------------------------------------------------------------------+
//| Determines whether the map contains the specified key. |
//+------------------------------------------------------------------+
template<typename TKey,typename TValue>
bool CHashMap::ContainsKey(TKey key)
{
return(FindEntry(key)>=0);
}
//+------------------------------------------------------------------+
//| Determines whether the map contains the specified value. |
//+------------------------------------------------------------------+
template<typename TKey,typename TValue>
bool CHashMap::ContainsValue(TValue value)
{
//--- create default equality value comparer
CDefaultEqualityComparer<TValue>comparer_value();
//--- try to find pair contains specified value
for(int i=0; i<m_count; i++)
if(m_entries[i].hash_code>=0 && comparer_value.Equals(m_entries[i].value,value))
return(true);
return(false);
}
//+------------------------------------------------------------------+
//| Copies a range of elements from the map to a compatible |
//| one-dimensional array. |
//+------------------------------------------------------------------+
template<typename TKey,typename TValue>
int CHashMap::CopyTo(CKeyValuePair<TKey,TValue>*&dst_array[],const int dst_start=0)
{
//--- resize array
if(dst_start+m_count>ArraySize(dst_array))
ArrayResize(dst_array,dst_start+m_count);
//--- start copy
int index=0;
for(int i=0; i<ArraySize(m_entries); i++)
if(m_entries[i].hash_code>=0)
{
//--- check indexes
if(dst_start+index>=ArraySize(dst_array) || index>=m_count)
return(index);
dst_array[dst_start+index++]=new CKeyValuePair<TKey,TValue>(m_entries[i].key,m_entries[i].value);
}
return(index);
}
//+------------------------------------------------------------------+
//| Copies a range of elements from the map to a compatible |
//| one-dimensionals keys and values arrays. |
//+------------------------------------------------------------------+
template<typename TKey,typename TValue>
int CHashMap::CopyTo(TKey &dst_keys[],TValue &dst_values[],const int dst_start=0)
{
int count=m_count-m_free_count;
//--- resize keys array
if(dst_start+count>ArraySize(dst_keys))
ArrayResize(dst_keys,dst_start+count);
//--- resize values array
if(dst_start+count>ArraySize(dst_values))
ArrayResize(dst_values,MathMin(ArraySize(dst_keys),dst_start+count));
//--- start copy
int index=0;
for(int i=0; i<ArraySize(m_entries); i++)
if(m_entries[i].hash_code>=0)
{
//--- check indexes
if(dst_start+index>=ArraySize(dst_keys) || dst_start+index>=ArraySize(dst_values) || index>=count)
return(index);
dst_keys[dst_start+index]=m_entries[i].key;
dst_values[dst_start+index]=m_entries[i].value;
index++;
}
return(index);
}
//+------------------------------------------------------------------+
//| Removes all keys and values from the map. |
//+------------------------------------------------------------------+
template<typename TKey,typename TValue>
void CHashMap::Clear(void)
{
//--- check count
if(m_count>0)
{
ArrayFill(m_buckets,0,m_capacity,-1);
ArrayFree(m_entries);
m_count=0;
m_free_list=-1;
m_free_count=0;
}
}
//+------------------------------------------------------------------+
//| Removes the specified key-value pair from map. |
//+------------------------------------------------------------------+
template<typename TKey,typename TValue>
bool CHashMap::Remove(CKeyValuePair<TKey,TValue>*item)
{
//--- check pair
if(CheckPointer(item)==POINTER_INVALID)
return(false);
//--- find pair with specified key
int i=FindEntry(item.Key());
//--- create default equality value comparer
CDefaultEqualityComparer<TValue>comparer_value();
//--- remove pair
if(i>=0 && comparer_value.Equals(m_entries[i].value,item.Value()))
return Remove(item.Key());
return(false);
}
//+------------------------------------------------------------------+
//| Removes the value with the specified key from the map. |
//+------------------------------------------------------------------+
template<typename TKey,typename TValue>
bool CHashMap::Remove(TKey key)
{
if(m_capacity!=0)
{
int hash_code=m_comparer.HashCode(key)&0x7FFFFFFF;
int bucket=hash_code%m_capacity;
int last=-1;
//--- search pair with specified key
for(int i=m_buckets[bucket]; i>=0; last=i,i=m_entries[i].next)
{
if(m_entries[i].hash_code==hash_code && m_comparer.Equals(m_entries[i].key,key))
{
if(last<0)
m_buckets[bucket]=m_entries[i].next;
else
m_entries[last].next=m_entries[i].next;
//--- remove pair
m_entries[i].hash_code=-1;
m_entries[i].next=m_free_list;
m_entries[i].key=(TKey)NULL;
m_entries[i].value=(TValue)NULL;
//--- incremet free count
m_free_list=i;
m_free_count++;
return(true);
}
}
}
return(false);
}
//+------------------------------------------------------------------+
//| Gets the value associated with the specified key. |
//+------------------------------------------------------------------+
template<typename TKey,typename TValue>
bool CHashMap::TryGetValue(TKey key,TValue &value)
{
//--- find pair with specified key
int i=FindEntry(key);
//--- check index
if(i>=0)
{
//--- get value
value=m_entries[i].value;
return(true);
}
return(false);
}
//+------------------------------------------------------------------+
//| Sets the value associated with the specified key. |
//+------------------------------------------------------------------+
template<typename TKey,typename TValue>
bool CHashMap::TrySetValue(TKey key,TValue value)
{
return(Insert(key, value, false));
}
//+------------------------------------------------------------------+
//| Initialize map with specified capacity. |
//+------------------------------------------------------------------+
template<typename TKey,typename TValue>
void CHashMap::Initialize(const int capacity)
{
m_capacity=CPrimeGenerator::GetPrime(capacity);
ArrayResize(m_buckets,m_capacity);
ArrayFill(m_buckets,0,m_capacity,-1);
ArrayResize(m_entries,m_capacity);
m_free_list=-1;
}
//+------------------------------------------------------------------+
//| Resize map. |
//+------------------------------------------------------------------+
template<typename TKey,typename TValue>
bool CHashMap::Resize(const int new_size)
{
//--- resize buckets
if(ArrayResize(m_buckets,new_size)!=new_size)
return(false);
ArrayFill(m_buckets,0,new_size,-1);
//--- resize entries
if(ArrayResize(m_entries,new_size)!=new_size)
return(false);
//--- restore buckets
for(int i=0; i<m_count; i++)
if(m_entries[i].hash_code>=0)
{
int bucket=m_entries[i].hash_code%new_size;
m_entries[i].next = m_buckets[bucket];
m_buckets[bucket] = i;
}
//--- restore capacity
m_capacity=new_size;
return(true);
}
//+------------------------------------------------------------------+
//| Find index of entry with specified key. |
//+------------------------------------------------------------------+
template<typename TKey,typename TValue>
int CHashMap::FindEntry(TKey key)
{
if(m_capacity!=NULL)
{
//--- get hash code from key
int hash_code=m_comparer.HashCode(key)&0x7FFFFFFF;
//--- search pair with specified key
for(int i=m_buckets[hash_code%m_capacity]; i>=0; i=m_entries[i].next)
if(m_entries[i].hash_code==hash_code && m_comparer.Equals(m_entries[i].key,key))
return(i);
}
return(-1);
}
//+------------------------------------------------------------------+
//| Insert the value with the specified key from the map. |
//+------------------------------------------------------------------+
template<typename TKey,typename TValue>
bool CHashMap::Insert(TKey key,TValue value,const bool add)
{
if(m_capacity==0)
Initialize(0);
//--- get hash code from key
int hash_code=m_comparer.HashCode(key)&0x7FFFFFFF;
int target_bucket=hash_code%m_capacity;
//--- collisions count in one bucket with different hashes
int collision_count=0;
//--- search pair with specified key
for(int i=m_buckets[target_bucket]; i>=0; i=m_entries[i].next)
{
//--- hash compare
if(m_entries[i].hash_code!=hash_code)
{
collision_count++;
continue;
}
//--- value compare
if(m_comparer.Equals(m_entries[i].key,key))
{
//--- adding duplicate
if(add)
return(false);
m_entries[i].value=value;
return(true);
}
}
//--- check collision
if(collision_count>=m_collision_threshold)
{
int new_size=CPrimeGenerator::ExpandPrime(m_count);
if(!Resize(new_size))
return(false);
target_bucket=hash_code%new_size;
}
//--- calculate index
int index;
if(m_free_count>0)
{
index=m_free_list;
m_free_list=m_entries[index].next;
m_free_count--;
}
else
{
if(m_count==ArraySize(m_entries))
{
int new_size=CPrimeGenerator::ExpandPrime(m_count);
if(!Resize(new_size))
return(false);
target_bucket=hash_code%new_size;
}
index=m_count;
m_count++;
}
//--- set pair
m_entries[index].hash_code=hash_code;
m_entries[index].next=m_buckets[target_bucket];
m_entries[index].key=key;
m_entries[index].value=value;
m_buckets[target_bucket]=index;
return(true);
}
template<typename TKey,typename TValue>
static int CHashMap::m_collision_threshold=8;
//+------------------------------------------------------------------+
+972
View File
@@ -0,0 +1,972 @@
//+------------------------------------------------------------------+
//| HashSet.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include<Generic\Interfaces\ISet.mqh>
#include <Generic\Internal\PrimeGenerator.mqh>
#include <Generic\Interfaces\IEqualityComparer.mqh>
#include <Generic\Internal\DefaultEqualityComparer.mqh>
//+------------------------------------------------------------------+
//| Struct Slot<T>. |
//| Usage: Internal structure for organization CHashSet<T>. |
//+------------------------------------------------------------------+
template<typename T>
struct Slot
{
public:
int hash_code;
T value;
int next;
Slot(void): hash_code(0),value((T)NULL),next(0) {}
};
//+------------------------------------------------------------------+
//| Class CHashSet<T>. |
//| Usage: Represents a set of unique values. |
//+------------------------------------------------------------------+
template<typename T>
class CHashSet: public ISet<T>
{
protected:
int m_buckets[];
Slot<T> m_slots[];
int m_count;
int m_last_index;
int m_free_list;
IEqualityComparer<T>*m_comparer;
bool m_delete_comparer;
public:
CHashSet(void);
CHashSet(IEqualityComparer<T>*comparer);
CHashSet(ICollection<T>*collection);
CHashSet(ICollection<T>*collection,IEqualityComparer<T>*comparer);
CHashSet(T &array[]);
CHashSet(T &array[],IEqualityComparer<T>*comparer);
~CHashSet(void);
//--- methods of filling data
bool Add(T value);
//--- methods of access to protected data
int Count(void) { return(m_count); }
IEqualityComparer<T>* Comparer(void) const { return(m_comparer); }
bool Contains(T item);
void TrimExcess(void);
//--- methods of copy data from collection
int CopyTo(T &ds_array[],const int dst_start=0);
//--- methods of cleaning and deleting
void Clear(void);
bool Remove(T item);
//--- methods of changing sets
void ExceptWith(ICollection<T>*collection);
void ExceptWith(T &array[]);
void IntersectWith(ICollection<T>*collection);
void IntersectWith(T &array[]);
void SymmetricExceptWith(ICollection<T>*collection);
void SymmetricExceptWith(T &array[]);
void UnionWith(ICollection<T>*collection);
void UnionWith(T &array[]);
//--- methods for determining the relationship between sets
bool IsProperSubsetOf(ICollection<T>*collection);
bool IsProperSubsetOf(T &array[]);
bool IsProperSupersetOf(ICollection<T>*collection);
bool IsProperSupersetOf(T &array[]);
bool IsSubsetOf(ICollection<T>*collection);
bool IsSubsetOf(T &array[]);
bool IsSupersetOf(ICollection<T>*collection);
bool IsSupersetOf(T &array[]);
bool Overlaps(ICollection<T>*collection);
bool Overlaps(T &array[]);
bool SetEquals(ICollection<T>*collection);
bool SetEquals(T &array[]);
private:
void SetCapacity(const int new_size,bool new_hash_codes);
bool AddIfNotPresent(T value);
void Initialize(const int capacity);
void InternalSymmetricExceptWith(CHashSet<T>*set);
bool InternalIsSubsetOf(CHashSet<T>*set);
bool InternalIsSupersetOf(CHashSet<T>*set);
bool InternalIsProperSubsetOf(CHashSet<T>*set);
bool InternalIsProperSupersetOf(CHashSet<T>*set);
};
//+------------------------------------------------------------------+
//| Initializes a new instance of the CHashSet<T> class that is empty|
//| and uses the default equality comparer for the set type. |
//+------------------------------------------------------------------+
template<typename T>
CHashSet::CHashSet(void): m_count(0),
m_last_index(0),
m_free_list(-1)
{
//--- use default equality comaprer
m_comparer=new CDefaultEqualityComparer<T>();
m_delete_comparer=true;
}
//+------------------------------------------------------------------+
//| Initializes a new instance of the CHashSet<T> class that is empty|
//| and uses the specified equality comparer for the set type. |
//+------------------------------------------------------------------+
template<typename T>
CHashSet::CHashSet(IEqualityComparer<T>*comparer): m_count(0),
m_last_index(0),
m_free_list(-1)
{
//--- check equality comaprer
if(CheckPointer(comparer)==POINTER_INVALID)
{
//--- use default equality comaprer
m_comparer=new CDefaultEqualityComparer<T>();
m_delete_comparer=true;
}
else
{
//--- use specified equality comaprer
m_comparer=comparer;
m_delete_comparer=false;
}
}
//+------------------------------------------------------------------+
//| Initializes a new instance of the CHashSet<T> class that uses the|
//| default equality comparer for the set type, contains elements |
//| copied from the specified collection, and has sufficient capacity|
//| to accommodate the number of elements copied. |
//+------------------------------------------------------------------+
template<typename T>
CHashSet::CHashSet(ICollection<T>*collection): m_count(0),
m_last_index(0),
m_free_list(-1)
{
//--- use default equality comaprer
m_comparer=new CDefaultEqualityComparer<T>();
m_delete_comparer=true;
//--- check collection
if(CheckPointer(collection)==POINTER_INVALID)
return;
//--- set capacity for elements of the collection
int count=collection.Count();
Initialize(count);
//--- add element from collection to the set
this.UnionWith(collection);
if((m_count==0 && ArraySize(m_slots)>3) ||
(m_count>0 && ArraySize(m_slots)/m_count>3))
TrimExcess();
}
//+------------------------------------------------------------------+
//| Initializes a new instance of the CHashSet<T> class that uses the|
//| specified equality comparer for the set type, contains elements |
//| copied from the specified collection, and has sufficient capacity|
//| to accommodate the number of elements copied. |
//+------------------------------------------------------------------+
template<typename T>
CHashSet::CHashSet(ICollection<T>*collection,IEqualityComparer<T>*comparer): m_count(0),
m_last_index(0),
m_free_list(-1)
{
//--- check equality comaprer
if(CheckPointer(comparer)==POINTER_INVALID)
{
//--- use default equality comaprer
m_comparer=new CDefaultEqualityComparer<T>();
m_delete_comparer=true;
}
else
{
//--- use specified comaprer
m_comparer=comparer;
m_delete_comparer=false;
}
//--- check collection
if(CheckPointer(collection)==POINTER_INVALID)
return;
//--- set capacity for elements of the collection
int count=collection.Count();
Initialize(count);
//--- add element from collection to the set
this.UnionWith(collection);
if((m_count==0 && ArraySize(m_slots)>3) ||
(m_count>0 && ArraySize(m_slots)/m_count>3))
TrimExcess();
}
//+------------------------------------------------------------------+
//| Initializes a new instance of the CHashSet<T> class that uses the|
//| default equality comparer for the set type, contains elements |
//| copied from the specified array, and has sufficient capacity to |
//| accommodate the number of elements copied. |
//+------------------------------------------------------------------+
template<typename T>
CHashSet::CHashSet(T &array[]): m_count(0),
m_last_index(0),
m_free_list(-1)
{
//--- use default equality comaprer
m_comparer=new CDefaultEqualityComparer<T>();
m_delete_comparer=true;
//--- set capacity for elements of the array
int count=ArraySize(array);
Initialize(count);
//--- add element from array to the set
this.UnionWith(array);
if((m_count==0 && ArraySize(m_slots)>3) ||
(m_count>0 && ArraySize(m_slots)/m_count>3))
TrimExcess();
}
//+------------------------------------------------------------------+
//| Initializes a new instance of the CHashSet<T> class that uses the|
//| specified equality comparer for the set type, contains elements |
//| copied from the specified array, and has sufficient capacity to |
//| accommodate the number of elements copied. |
//+------------------------------------------------------------------+
template<typename T>
CHashSet::CHashSet(T &array[],IEqualityComparer<T>*comparer): m_count(0),
m_last_index(0),
m_free_list(-1)
{
//--- check equality comaprer
if(CheckPointer(comparer)==POINTER_INVALID)
{
//--- use default equality comaprer
m_comparer=new CDefaultEqualityComparer<T>();
m_delete_comparer=true;
}
else
{
//--- use specified comaprer
m_comparer=comparer;
m_delete_comparer=false;
}
//--- set capacity for elements of the array
int count=ArraySize(array);
Initialize(count);
//--- add element from array to the set
this.UnionWith(array);
if((m_count==0 && ArraySize(m_slots)>3) ||
(m_count>0 && ArraySize(m_slots)/m_count>3))
TrimExcess();
}
//+------------------------------------------------------------------+
//| Destructor. |
//+------------------------------------------------------------------+
template<typename T> CHashSet::~CHashSet(void)
{
if(m_delete_comparer)
delete m_comparer;
}
//+------------------------------------------------------------------+
//| Adds the specified element to a set. |
//+------------------------------------------------------------------+
template<typename T>
bool CHashSet::Add(T value)
{
return AddIfNotPresent(value);
}
//+------------------------------------------------------------------+
//| Determines whether a set contains the specified element. |
//+------------------------------------------------------------------+
template<typename T>
bool CHashSet::Contains(T item)
{
//--- check buckets
if(ArraySize(m_buckets)!=0)
{
//--- get hash code for item
int hash_code=m_comparer.HashCode(item)&0x7FFFFFFF;
//--- search item in the slots
for(int i=m_buckets[hash_code%ArraySize(m_buckets)]-1; i>=0; i=m_slots[i].next)
if(m_slots[i].hash_code==hash_code && m_comparer.Equals(m_slots[i].value,item))
return(true);
}
return(false);
}
//+------------------------------------------------------------------+
//| Sets the capacity of a set to the actual number of elements it |
//| contains, rounded up to a nearby, implementation-specific value. |
//+------------------------------------------------------------------+
template<typename T>
void CHashSet::TrimExcess(void)
{
if(m_count==0)
{
ArrayFree(m_buckets);
ArrayFree(m_slots);
}
else
{
//--- calculate min prime size for current count
int new_size=CPrimeGenerator::GetPrime(m_count);
//--- resize buckets and slots
ArrayResize(m_slots,new_size);
ArrayResize(m_buckets,new_size);
//--- restore buckets and slots
int new_index=0;
for(int i=0; i<m_last_index; i++)
{
if(m_slots[i].hash_code>=0)
{
m_slots[new_index]=m_slots[i];
//--- rehash
int bucket=m_slots[new_index].hash_code%new_size;
m_slots[new_index].next=m_buckets[bucket]-1;
m_buckets[bucket]=new_index+1;
//--- increment index
new_index++;
}
}
m_last_index=new_index;
m_free_list=-1;
}
}
//+------------------------------------------------------------------+
//| Copies a range of elements from the set to a compatible |
//| one-dimensional array. |
//+------------------------------------------------------------------+
template<typename T>
int CHashSet::CopyTo(T &dst_array[],const int dst_start)
{
//--- resize array
if(dst_start+m_count>ArraySize(dst_array))
ArrayResize(dst_array,dst_start+m_count);
//--- start copy
int index=0;
for(int i=0; i<ArraySize(m_slots); i++)
if(m_slots[i].hash_code>=0)
{
if(dst_start+index>=ArraySize(dst_array) || index>=m_count)
return(index);
dst_array[dst_start+index++]=m_slots[i].value;
}
return(index);
}
//+------------------------------------------------------------------+
//| Removes all elements from a set. |
//+------------------------------------------------------------------+
template<typename T>
void CHashSet::Clear(void)
{
if(m_last_index>0)
{
ArrayFree(m_slots);
ArrayFree(m_buckets);
m_last_index=0;
m_count=0;
m_free_list=-1;
}
}
//+------------------------------------------------------------------+
//| Removes the specified element from a set. |
//+------------------------------------------------------------------+
template<typename T>
bool CHashSet::Remove(T item)
{
if(ArraySize(m_buckets)!=0)
{
//--- get hash code for item
int hash_code=m_comparer.HashCode(item)&0x7FFFFFFF;
int bucket=hash_code%ArraySize(m_buckets);
int last=-1;
//--- search item
for(int i=m_buckets[bucket]-1; i>=0; last=i,i=m_slots[i].next)
{
if(m_slots[i].hash_code==hash_code && m_comparer.Equals(m_slots[i].value,item))
{
if(last<0)
m_buckets[bucket]=m_slots[i].next+1;
else
m_slots[last].next=m_slots[i].next;
//--- remove item
m_slots[i].hash_code=-1;
m_slots[i].value=(T)NULL;
m_slots[i].next =m_free_list;
//--- decrement count
m_count--;
if(m_count==0)
{
m_last_index= 0;
m_free_list = -1;
}
else
{
m_free_list=i;
}
return(true);
}
}
}
return(false);
}
//+------------------------------------------------------------------+
//| Removes all elements in the specified collection from the current|
//| set. |
//+------------------------------------------------------------------+
template<typename T>
void CHashSet::ExceptWith(ICollection<T>*collection)
{
//--- check collection
if(CheckPointer(collection)==POINTER_INVALID)
return;
//--- this is already the enpty set
if(m_count==0)
return;
//--- special case if collecion is this
//--- a set minus itself is the empty set
if(collection==GetPointer(this))
{
Clear();
return;
}
//--- copy collection to array
T array[];
collection.CopyTo(array,0);
//--- remove every element in collection from this
for(int i=0; i<ArraySize(array); i++)
Remove(array[i]);
}
//+------------------------------------------------------------------+
//| Removes all elements in the specified array from the current set.|
//+------------------------------------------------------------------+
template<typename T>
void CHashSet::ExceptWith(T &array[])
{
//--- this is already the enpty set
if(m_count==0)
return;
//--- remove every element in collection from this
for(int i=0; i<ArraySize(array); i++)
Remove(array[i]);
}
//+------------------------------------------------------------------+
//| Modifies the current set to contain only elements that are |
//| present in that object and in the specified collection. |
//+------------------------------------------------------------------+
template<typename T>
void CHashSet::IntersectWith(ICollection<T>*collection)
{
//--- check collection
if(CheckPointer(collection)==POINTER_INVALID)
return;
//--- intersection of anything with empty set is empty set, so return if count is 0
if(m_count==0)
return;
//--- if collection is empty, intersection is empty set
if(collection.Count()==0)
{
Clear();
return;
}
//--- intersect
for(int i=0; i<m_last_index; i++)
{
if(m_slots[i].hash_code>=0)
{
T item=m_slots[i].value;
if(!collection.Contains(item))
Remove(item);
}
}
}
//+------------------------------------------------------------------+
//| Modifies the current set to contain only elements that are |
//| present in that object and in the specified array. |
//+------------------------------------------------------------------+
template<typename T>
void CHashSet::IntersectWith(T &array[])
{
//--- intersection of anything with empty set is empty set, so return if count is 0
if(m_count==0)
return;
//--- if collection is empty, intersection is empty set
if(ArraySize(array)==0)
{
Clear();
return;
}
//--- intersect
CHashSet<T>set(array);
for(int i=0; i<m_last_index; i++)
{
if(m_slots[i].hash_code>=0)
{
T item=m_slots[i].value;
if(!set.Contains(item))
Remove(item);
}
}
}
//+------------------------------------------------------------------+
//| Modifies the current set to contain only elements that are |
//| present either in that set or in the specified collection, but |
//| not both. |
//+------------------------------------------------------------------+
template<typename T>
void CHashSet::SymmetricExceptWith(ICollection<T>*collection)
{
//--- check collection
if(CheckPointer(collection)==POINTER_INVALID)
return;
//--- if set is empty, then symmetric difference is other
if(m_count==0)
{
UnionWith(collection);
return;
}
//--- special case this; the symmetric difference of a set with itself is the empty set
if(collection==GetPointer(this))
{
Clear();
return;
}
//--- check collection is set
CHashSet<T>*ptr_set=dynamic_cast<CHashSet<T>*>(collection);
if(CheckPointer(ptr_set)!=POINTER_INVALID)
{
InternalSymmetricExceptWith(ptr_set);
}
else
{
//--- create a set based on a specified collection
CHashSet<T>set(collection);
InternalSymmetricExceptWith(GetPointer(set));
}
}
//+------------------------------------------------------------------+
//| Modifies the current set to contain only elements that are |
//| present either in that set or in the specified array, but not |
//| both. |
//+------------------------------------------------------------------+
template<typename T>
void CHashSet::SymmetricExceptWith(T &array[])
{
//--- if set is empty, then symmetric difference is other
if(m_count==0)
{
UnionWith(array);
return;
}
//--- symmetric except
CHashSet<T>set(array);
InternalSymmetricExceptWith(GetPointer(set));
}
//+------------------------------------------------------------------+
//| Modifies the current set to contain all elements that are present|
//| in itself, the specified collection, or both. |
//+------------------------------------------------------------------+
template<typename T>
void CHashSet::UnionWith(ICollection<T>*collection)
{
//--- check collection
if(CheckPointer(collection)==POINTER_INVALID)
return;
//--- get array from collection
T array[];
collection.CopyTo(array);
//--- union array with the current set
UnionWith(array);
}
//+------------------------------------------------------------------+
//| Modifies the current set to contain all elements that are present|
//| in itself, the specified array, or both. |
//+------------------------------------------------------------------+
template<typename T>
void CHashSet::UnionWith(T &array[])
{
for(int i=0; i<ArraySize(array); i++)
AddIfNotPresent(array[i]);
}
//+------------------------------------------------------------------+
//| Determines whether a set is a proper subset of the specified |
//| collection. |
//+------------------------------------------------------------------+
template<typename T>
bool CHashSet::IsProperSubsetOf(ICollection<T>*collection)
{
//--- check collection
if(CheckPointer(collection)==POINTER_INVALID)
return(false);
//--- the empty set is a proper subset of anything but the empty set
if(m_count==0)
return(collection.Count()>0);
//--- check collection is set
CHashSet<T>*ptr_set=dynamic_cast<CHashSet<T>*>(collection);
if(CheckPointer(ptr_set)!=POINTER_INVALID)
{
return InternalIsProperSubsetOf(ptr_set);
}
else
{
//--- create a set based on a specified collection
CHashSet<T>set(collection);
return InternalIsProperSubsetOf(GetPointer(set));
}
}
//+------------------------------------------------------------------+
//| Determines whether a set is a proper subset of the specified |
//| array. |
//+------------------------------------------------------------------+
template<typename T>
bool CHashSet::IsProperSubsetOf(T &array[])
{
//--- the empty set is a proper subset of anything but the empty set
if(m_count==0)
return(ArraySize(array)>0);
//--- create a set based on a specified array
CHashSet<T>set(array);
return InternalIsProperSubsetOf(GetPointer(set));
}
//+------------------------------------------------------------------+
//| Determines whether a set is a proper superset of the specified |
//| collection. |
//+------------------------------------------------------------------+
template<typename T>
bool CHashSet::IsProperSupersetOf(ICollection<T>*collection)
{
//--- check collection
if(CheckPointer(collection)==POINTER_INVALID)
return(m_count>0);
//--- the empty set is a proper subset of anything but the empty set
if(m_count==0)
return(false);
//--- if other is the empty set then this is a superset
if(collection.Count()==0)
return(true);
//--- check collection is set
CHashSet<T>*ptr_set=dynamic_cast<CHashSet<T>*>(collection);
if(CheckPointer(ptr_set)!=POINTER_INVALID)
{
return InternalIsProperSupersetOf(ptr_set);
}
else
{
//--- create a set based on a specified collection
CHashSet<T>set(collection);
return InternalIsProperSupersetOf(GetPointer(set));
}
}
//+------------------------------------------------------------------+
//| Determines whether a set is a proper superset of the specified |
//| array. |
//+------------------------------------------------------------------+
template<typename T>
bool CHashSet::IsProperSupersetOf(T &array[])
{
//--- the empty set is a proper subset of anything but the empty set
if(m_count==0)
return(false);
//--- if other is the empty set then this is a superset
if(ArraySize(array)==0)
return(true);
//--- create a set based on a specified array
CHashSet<T>set(array);
return InternalIsProperSupersetOf(GetPointer(set));
}
//+------------------------------------------------------------------+
//| Determines whether a set is a subset of the specified collection.|
//+------------------------------------------------------------------+
template<typename T>
bool CHashSet::IsSubsetOf(ICollection<T>*collection)
{
if(CheckPointer(collection)==POINTER_INVALID)
return(m_count==0);
//--- The empty set is a subset of any set
if(m_count==0)
return(true);
//--- check collection is set
CHashSet<T>*ptr_set=dynamic_cast<CHashSet<T>*>(collection);
if(CheckPointer(ptr_set)!=POINTER_INVALID)
{
return InternalIsSubsetOf(ptr_set);
}
else
{
//--- create a set based on a specified collection
CHashSet<T>set(collection);
return InternalIsSubsetOf(GetPointer(set));
}
}
//+------------------------------------------------------------------+
//| Determines whether a set is a subset of the specified array. |
//+------------------------------------------------------------------+
template<typename T>
bool CHashSet::IsSubsetOf(T &array[])
{
//--- The empty set is a subset of any set
if(m_count==0)
return(true);
//--- create a set based on a specified array
CHashSet<T>set(array);
return InternalIsSubsetOf(GetPointer(set));
}
//+------------------------------------------------------------------+
//| Determines whether a set is a superset of the specified |
//| collection. |
//+------------------------------------------------------------------+
template<typename T>
bool CHashSet::IsSupersetOf(ICollection<T>*collection)
{
if(CheckPointer(collection)==POINTER_INVALID)
return(m_count>=0);
//--- if other is the empty set then this is a superset
if(collection.Count()==0)
return(true);
//--- check collection is set
CHashSet<T>*ptr_set=dynamic_cast<CHashSet<T>*>(collection);
if(CheckPointer(ptr_set)!=POINTER_INVALID)
{
return InternalIsSupersetOf(ptr_set);
}
else
{
//--- create a set based on a specified collection
CHashSet<T>set(collection);
return InternalIsSupersetOf(GetPointer(set));
}
}
//+------------------------------------------------------------------+
//| Determines whether a set is a superset of the specified array. |
//+------------------------------------------------------------------+
template<typename T>
bool CHashSet::IsSupersetOf(T &array[])
{
//--- if other is the empty set then this is a superset
if(ArraySize(array)==0)
return(true);
//--- create a set based on a specified array
CHashSet<T>set(array);
return InternalIsSupersetOf(GetPointer(set));
}
//+------------------------------------------------------------------+
//| Determines whether the current set and a specified collection |
//| share common elements. |
//+------------------------------------------------------------------+
template<typename T>
bool CHashSet::Overlaps(ICollection<T>*collection)
{
//--- check collection
if(CheckPointer(collection)==POINTER_INVALID)
return(false);
//--- check current count
if(m_count==0)
return(false);
//--- get array from collection
T array[];
collection.CopyTo(array);
//--- check overlaps between current set and array
return Overlaps(array);
}
//+------------------------------------------------------------------+
//| Determines whether the current set and a specified array share |
//| common elements. |
//+------------------------------------------------------------------+
template<typename T>
bool CHashSet::Overlaps(T &array[])
{
//--- check current count
if(m_count==0)
return(false);
//--- try to find any elements from specified array in current set
for(int i=0; i<ArraySize(array); i++)
if(Contains(array[i]))
return(true);
return(false);
}
//+------------------------------------------------------------------+
//| Determines whether a set and the specified collection contain the|
//| same elements. |
//+------------------------------------------------------------------+
template<typename T>
bool CHashSet::SetEquals(ICollection<T>*collection)
{
//--- check collection
if(CheckPointer(collection)==POINTER_INVALID)
return(false);
//--- check current set is equal specified collection
if(collection==GetPointer(this))
return(true);
//--- get array from collection
T array[];
collection.CopyTo(array);
//--- check current set is equal specified array
return SetEquals(array);
}
//+------------------------------------------------------------------+
//| Determines whether a set and the specified array contain the same|
//| elements. |
//+------------------------------------------------------------------+
template<typename T>
bool CHashSet::SetEquals(T &array[])
{
//--- check size
if(ArraySize(array)!=m_count)
return(false);
//--- check current set is equal specified array
for(int i=0; i<ArraySize(array); i++)
if(!Contains(array[i]))
return(false);
return(true);
}
//+------------------------------------------------------------------+
//| Set the underlying buckets array to size new_size and rehash. |
//+------------------------------------------------------------------+
template<typename T>
void CHashSet::SetCapacity(const int new_size,bool new_hash_codes)
{
//--- resize slots
ArrayResize(m_slots,new_size);
//--- restore slots
if(new_hash_codes)
for(int i=0; i<m_last_index; i++)
if(m_slots[i].hash_code!=-1)
m_slots[i].hash_code=m_comparer.HashCode(m_slots[i].value)&0x7FFFFFFF;
//--- resize buckets
ArrayResize(m_buckets,new_size);
ArrayFill(m_buckets,0,new_size,0);
//--- restore buckets
for(int i=0; i<m_last_index; i++)
{
int bucket=m_slots[i].hash_code%new_size;
m_slots[i].next=m_buckets[bucket]-1;
m_buckets[bucket]=i+1;
}
}
//+------------------------------------------------------------------+
//| Adds value to set if not contained already. Returns true if added|
//| and false if already present. |
//+------------------------------------------------------------------+
template<typename T>
bool CHashSet::AddIfNotPresent(T value)
{
//--- set minimum capacity
if(ArraySize(m_buckets)==0)
Initialize(0);
//--- get hash code and bucket for value
int hash_code=m_comparer.HashCode(value)&0x7FFFFFFF;
int bucket=hash_code%ArraySize(m_buckets);
//--- check value already in the set
for(int i=m_buckets[hash_code%ArraySize(m_buckets)]-1; i>=0; i=m_slots[i].next)
if(m_slots[i].hash_code==hash_code && m_comparer.Equals(m_slots[i].value,value))
return(false);
//--- calculate index for value
int index=0;
if(m_free_list>=0)
{
index=m_free_list;
m_free_list=m_slots[index].next;
}
else
{
if(m_last_index==ArraySize(m_slots))
{
int new_size=CPrimeGenerator::ExpandPrime(m_count);
SetCapacity(new_size,false);
bucket=hash_code%ArraySize(m_buckets);
}
index=m_last_index;
m_last_index++;
}
//--- set value
m_slots[index].hash_code=hash_code;
m_slots[index].value=value;
m_slots[index].next=m_buckets[bucket]-1;
m_buckets[bucket]=index+1;
//--- increase count
m_count++;
return(true);
}
//+------------------------------------------------------------------+
//| Initialize set with specified capacity. |
//+------------------------------------------------------------------+
template<typename T>
void CHashSet::Initialize(const int capacity)
{
int size=CPrimeGenerator::GetPrime(capacity);
ArrayResize(m_buckets,size);
ArrayResize(m_slots,size);
ZeroMemory(m_buckets);
ZeroMemory(m_slots);
}
//+------------------------------------------------------------------+
//| Modifies the current set to contain only elements that are |
//| present either in that set or in the specified set, but not both.|
//+------------------------------------------------------------------+
template<typename T>
void CHashSet::InternalSymmetricExceptWith(CHashSet<T>*set)
{
for(int i=0; i<ArraySize(set.m_slots); i++)
{
T item=set.m_slots[i].value;
if(!Remove(item))
AddIfNotPresent(item);
}
}
//+------------------------------------------------------------------+
//| Determines whether a set is a subset of the specified set. |
//+------------------------------------------------------------------+
template<typename T>
bool CHashSet::InternalIsSubsetOf(CHashSet<T>*set)
{
//--- if this has more elements then it can't be a subset
if(m_count>set.m_count)
return(false);
//--- try to find any elements from current set in specified set
for(int i=0; i<m_count; i++)
{
T item=m_slots[i].value;
if(!set.Contains(item))
return(false);
}
return(true);
}
//+------------------------------------------------------------------+
//| Determines whether a set is a superset of the specified set. |
//+------------------------------------------------------------------+
template<typename T>
bool CHashSet::InternalIsSupersetOf(CHashSet<T>*set)
{
//--- if this has less elements then it can't be a superset
if(set.m_count>m_count)
return(false);
//--- try to find any elements from specified set in current set
for(int i=0; i<set.m_count; i++)
{
T item=set.m_slots[i].value;
if(!Contains(item))
return(false);
}
return(true);
}
//+------------------------------------------------------------------+
//| Determines whether a set is a proper subset of the specified set.|
//+------------------------------------------------------------------+
template<typename T>
bool CHashSet::InternalIsProperSubsetOf(CHashSet<T>*set)
{
//--- if this has more or equal elements then it can't be a proper subset
if(m_count>=set.m_count)
return(false);
//--- try to find any elements from current set in specified set
for(int i=0; i<m_count; i++)
{
T item=m_slots[i].value;
if(!set.Contains(item))
return(false);
}
return(true);
}
//+------------------------------------------------------------------+
//| Determines whether a set is a proper superset of the specified |
//| set. |
//+------------------------------------------------------------------+
template<typename T>
bool CHashSet::InternalIsProperSupersetOf(CHashSet<T>*set)
{
//--- if this has less or equal elements then it can't be a proper superset
if(m_count<=set.m_count)
return(false);
//--- try to find any elements from specified set in current set
for(int i=0; i<set.m_count; i++)
{
T item=set.m_slots[i].value;
if(!Contains(item))
return(false);
}
return(true);
}
//+------------------------------------------------------------------+
+24
View File
@@ -0,0 +1,24 @@
//+------------------------------------------------------------------+
//| ICollection.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Interface ICollection<T>. |
//| Usage: Defines methods to manipulate generic collections. |
//+------------------------------------------------------------------+
template<typename T>
interface ICollection
{
//--- methods of filling data
bool Add(T value);
//--- methods of access to protected data
int Count(void);
bool Contains(T item);
//--- methods of copy data from collection
int CopyTo(T &dst_array[],const int dst_start=0);
//--- methods of cleaning and removing
void Clear(void);
bool Remove(T item);
};
//+------------------------------------------------------------------+
+19
View File
@@ -0,0 +1,19 @@
//+------------------------------------------------------------------+
//| IComparable.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include "IEqualityComparable.mqh"
//+------------------------------------------------------------------+
//| Interface IComparable<T>. |
//| Usage: Defines a generalized comparison method to create a |
//| type-specific comparison method for ordering or sorting |
//| instances. |
//+------------------------------------------------------------------+
template<typename T>
interface IComparable: public IEqualityComparable<T>
{
//--- method for determining compare
int Compare(T value);
};
//+------------------------------------------------------------------+
+17
View File
@@ -0,0 +1,17 @@
//+------------------------------------------------------------------+
//| IComparer.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Interface IComparer<T>. |
//| Usage: Defines a method that a type implements to compare two |
//| values. |
//+------------------------------------------------------------------+
template<typename T>
interface IComparer
{
//--- compares two values and returns a value indicating whether one is less than, equal to, or greater than the other
int Compare(T x,T y);
};
//+------------------------------------------------------------------+
@@ -0,0 +1,19 @@
//+------------------------------------------------------------------+
//| IEqualityComparable.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Interface IEqualityComparable<T>. |
//| Usage: Defines a generalized method to create a type-specific |
//| method for determining equality of instances. |
//+------------------------------------------------------------------+
template<typename T>
interface IEqualityComparable
{
//--- method for determining equality
bool Equals(T value);
//--- method to calculate hash code
int HashCode(void);
};
//+------------------------------------------------------------------+
+19
View File
@@ -0,0 +1,19 @@
//+------------------------------------------------------------------+
//| IEqualityComparer.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Interface IEqualityComparer<T>. |
//| Usage: Defines methods to support the comparison of values for |
//| equality. |
//+------------------------------------------------------------------+
template<typename T>
interface IEqualityComparer
{
//--- determines whether the specified values are equal
bool Equals(T x,T y);
//--- returns a hash code for the specified object
int HashCode(T value);
};
//+------------------------------------------------------------------+
+26
View File
@@ -0,0 +1,26 @@
//+------------------------------------------------------------------+
//| IList.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include "ICollection.mqh"
//+------------------------------------------------------------------+
//| Interface IList<T>. |
//| Usage: Represents a collection of objects that can be |
//| individually accessed by index. |
//+------------------------------------------------------------------+
template<typename T>
interface IList: public ICollection<T>
{
//--- method of access to the data
bool TryGetValue(const int index,T &value);
bool TrySetValue(const int index,T value);
//--- methods of filling the array
bool Insert(const int index,T item);
//--- methods for searching index
int IndexOf(T item);
int LastIndexOf(T item);
//--- methods of cleaning and deleting
bool RemoveAt(const int index);
};
//+------------------------------------------------------------------+
+27
View File
@@ -0,0 +1,27 @@
//+------------------------------------------------------------------+
//| IMap.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include "ICollection.mqh"
template<typename TKey,typename TValue>
class CKeyValuePair;
//+------------------------------------------------------------------+
//| Interface IMap<TKey,TValue>. |
//| Usage: Represents a generic collection of key/value pairs. |
//+------------------------------------------------------------------+
template<typename TKey,typename TValue>
interface IMap: public ICollection<CKeyValuePair<TKey,TValue>*>
{
//--- methods of filling data
bool Add(TKey key,TValue value);
//--- methods of access to protected data
bool Contains(TKey key,TValue value);
bool Remove(TKey key);
//--- method of access to the data
bool TryGetValue(TKey key,TValue &value);
bool TrySetValue(TKey key,TValue value);
//--- methods of copy data from collection
int CopyTo(TKey &dst_keys[],TValue &dst_values[],const int dst_start=0);
};
//+------------------------------------------------------------------+
+37
View File
@@ -0,0 +1,37 @@
//+------------------------------------------------------------------+
//| ISet.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include "ICollection.mqh"
//+------------------------------------------------------------------+
//| Interface ISet<T>. |
//| Usage: Provides the base interface for the abstraction of sets. |
//+------------------------------------------------------------------+
template<typename T>
interface ISet: public ICollection<T>
{
//--- methods of changing sets
void ExceptWith(ICollection<T>*collection);
void ExceptWith(T &array[]);
void IntersectWith(ICollection<T>*collection);
void IntersectWith(T &array[]);
void SymmetricExceptWith(ICollection<T>*collection);
void SymmetricExceptWith(T &array[]);
void UnionWith(ICollection<T>*collection);
void UnionWith(T &array[]);
//--- methods for determining the relationship between sets
bool IsProperSubsetOf(ICollection<T>*collection);
bool IsProperSubsetOf(T &array[]);
bool IsProperSupersetOf(ICollection<T>*collection);
bool IsProperSupersetOf(T &array[]);
bool IsSubsetOf(ICollection<T>*collection);
bool IsSubsetOf(T &array[]);
bool IsSupersetOf(ICollection<T>*collection);
bool IsSupersetOf(T &array[]);
bool Overlaps(ICollection<T>*collection);
bool Overlaps(T &array[]);
bool SetEquals(ICollection<T>*collection);
bool SetEquals(T &array[]);
};
//+------------------------------------------------------------------+
+135
View File
@@ -0,0 +1,135 @@
//+------------------------------------------------------------------+
//| ArrayFunction.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include "CompareFunction.mqh"
#include <Generic\Interfaces\IComparer.mqh>
//+------------------------------------------------------------------+
//| Searches an entire one-dimensional sorted array for a specific |
//| element, using the IComparable<T> generic interface implemented |
//| by each element of the array and by the specified object. |
//+------------------------------------------------------------------+
template<typename T>
int ArrayBinarySearch(T &array[],const int start_index,const int count, T value,IComparer<T>*comparer)
{
int lo=start_index;
int hi=start_index+count-1;
int size=ArraySize(array);
//--- check array size
if(size==0)
return(-1);
//--- check comaparer
if(CheckPointer(comparer)==POINTER_INVALID)
return(-1);
//--- check index
if(start_index<0 || count<0 || size-start_index<count)
return(-1);
//--- bianry search value
while(lo<=hi)
{
int i=lo+((hi-lo)>>1);
int order=comparer.Compare(array[i],value);
if(order==0)
{
return(i);
}
if(order<0)
{
lo=i+1;
}
else
{
hi=i-1;
}
}
//--- returns the index of an element nearest in value
if(lo>0)
return(lo-1);
return(lo);
}
//+------------------------------------------------------------------+
//| Searches for the specified object and returns the index of its |
//| first occurrence in a one-dimensional array. |
//+------------------------------------------------------------------+
template<typename T>
int ArrayIndexOf(T &array[],T value,const int start_index,const int count)
{
int size=ArraySize(array);
//--- check array size
if(size==0)
return(-1);
//--- check start index and count
if(start_index<0 || start_index>size ||
count<0 || count>size-start_index)
return(-1);
//--- search value
int end_index=start_index+count;
for(int i=start_index; i<end_index; i++)
{
//--- check the value in array is eqaul to specified value
if(::Equals(array[i],value))
{
//--- return fist index
return(i);
}
}
//--- return -1 if value not in array
return(-1);
}
//+------------------------------------------------------------------+
//| Returns the index of the last occurrence of a value in a |
//| one-dimensional array. |
//+------------------------------------------------------------------+
template<typename T>
int ArrayLastIndexOf(T &array[],T value,const int start_index,const int count)
{
int size=ArraySize(array);
//--- check array size
if(size==0)
return(-1);
//--- check start index and count
if(start_index<0 || start_index>=size ||
count<0 || count>start_index+1)
return(-1);
//--- search value
int end_index=start_index-count+1;
for(int i=start_index; i>=end_index; i--)
{
//--- check the value in array is eqaul to specified value
if(::Equals(array[i],value))
{
//--- return fist index from the end
return (i);
}
}
//--- return -1 if value not in array
return(-1);
}
//+------------------------------------------------------------------+
//| Reverses the elements in a range of this array. Following a call |
//| to this method, an element in the range given by index and count |
//| which was previously located at index i will now be located at |
//| index index + (index + count - i - 1). |
//+------------------------------------------------------------------+
template<typename T>
bool ArrayReverse(T &array[],const int start_index,const int count)
{
int size=ArraySize(array);
//--- check start index and count
if(count<0 || size-start_index<count)
return(false);
//--- reverse elements
int i = start_index;
int j = start_index + count - 1;
while(i<j)
{
T temp=array[i];
array[i] = array[j];
array[j] = temp;
i++;
j--;
}
return(true);
}
//+------------------------------------------------------------------+
+209
View File
@@ -0,0 +1,209 @@
//+------------------------------------------------------------------+
//| CompareFunction.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Generic\Interfaces\IComparable.mqh>
//+------------------------------------------------------------------+
//| Compares two objects and returns a value indicating whether one |
//| is less than, equal to, or greater than the other. |
//+------------------------------------------------------------------+
int Compare(const bool x,const bool y)
{
if(x>y)
return(1);
else if(x<y)
return(-1);
else
return(0);
}
//+------------------------------------------------------------------+
//| Compares two objects and returns a value indicating whether one |
//| is less than, equal to, or greater than the other. |
//+------------------------------------------------------------------+
int Compare(const char x,const char y)
{
if(x>y)
return(1);
else if(x<y)
return(-1);
else
return(0);
}
//+------------------------------------------------------------------+
//| Compares two objects and returns a value indicating whether one |
//| is less than, equal to, or greater than the other. |
//+------------------------------------------------------------------+
int Compare(const uchar x,const uchar y)
{
if(x>y)
return(1);
else if(x<y)
return(-1);
else
return(0);
}
//+------------------------------------------------------------------+
//| Compares two objects and returns a value indicating whether one |
//| is less than, equal to, or greater than the other. |
//+------------------------------------------------------------------+
int Compare(const short x,const short y)
{
if(x>y)
return(1);
else if(x<y)
return(-1);
else
return(0);
}
//+------------------------------------------------------------------+
//| Compares two objects and returns a value indicating whether one |
//| is less than, equal to, or greater than the other. |
//+------------------------------------------------------------------+
int Compare(const ushort x,const ushort y)
{
if(x>y)
return(1);
else if(x<y)
return(-1);
else
return(0);
}
//+------------------------------------------------------------------+
//| Compares two objects and returns a value indicating whether one |
//| is less than, equal to, or greater than the other. |
//+------------------------------------------------------------------+
int Compare(const color x,const color y)
{
if(x>y)
return(1);
else if(x<y)
return(-1);
else
return(0);
}
//+------------------------------------------------------------------+
//| Compares two objects and returns a value indicating whether one |
//| is less than, equal to, or greater than the other. |
//+------------------------------------------------------------------+
int Compare(const int x,const int y)
{
if(x>y)
return(1);
else if(x<y)
return(-1);
else
return(0);
}
//+------------------------------------------------------------------+
//| Compares two objects and returns a value indicating whether one |
//| is less than, equal to, or greater than the other. |
//+------------------------------------------------------------------+
int Compare(const uint x,const uint y)
{
if(x>y)
return(1);
else if(x<y)
return(-1);
else
return(0);
}
//+------------------------------------------------------------------+
//| Compares two objects and returns a value indicating whether one |
//| is less than, equal to, or greater than the other. |
//+------------------------------------------------------------------+
int Compare(const datetime x,const datetime y)
{
if(x>y)
return(1);
else if(x<y)
return(-1);
else
return(0);
}
//+------------------------------------------------------------------+
//| Compares two objects and returns a value indicating whether one |
//| is less than, equal to, or greater than the other. |
//+------------------------------------------------------------------+
int Compare(const long x,const long y)
{
if(x>y)
return(1);
else if(x<y)
return(-1);
else
return(0);
}
//+------------------------------------------------------------------+
//| Compares two objects and returns a value indicating whether one |
//| is less than, equal to, or greater than the other. |
//+------------------------------------------------------------------+
int Compare(const ulong x,const ulong y)
{
if(x>y)
return(1);
else if(x<y)
return(-1);
else
return(0);
}
//+------------------------------------------------------------------+
//| Compares two objects and returns a value indicating whether one |
//| is less than, equal to, or greater than the other. |
//+------------------------------------------------------------------+
int Compare(const float x,const float y)
{
if(x>y)
return(1);
else if(x<y)
return(-1);
else
return(0);
}
//+------------------------------------------------------------------+
//| Compares two objects and returns a value indicating whether one |
//| is less than, equal to, or greater than the other. |
//+------------------------------------------------------------------+
int Compare(const double x,const double y)
{
if(x>y)
return(1);
else if(x<y)
return(-1);
else
return(0);
}
//+------------------------------------------------------------------+
//| Compares two objects and returns a value indicating whether one |
//| is less than, equal to, or greater than the other. |
//+------------------------------------------------------------------+
int Compare(const string x,const string y)
{
if(x>y)
return(1);
else if(x<y)
return(-1);
else
return(0);
}
//+------------------------------------------------------------------+
//| Compares two objects and returns a value indicating whether one |
//| is less than, equal to, or greater than the other. |
//+------------------------------------------------------------------+
template<typename T>
int Compare(T x,T y)
{
//--- try to convert to comparable object
IComparable<T>*comparable=dynamic_cast<IComparable<T>*>(x);
if(comparable)
{
//--- use specied compare method
return comparable.Compare(y);
}
else
{
//--- unknown compare function
return(0);
}
}
//+------------------------------------------------------------------+
+22
View File
@@ -0,0 +1,22 @@
//+------------------------------------------------------------------+
//| DefaultComparer.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Generic\Interfaces\IComparer.mqh>
#include "CompareFunction.mqh"
//+------------------------------------------------------------------+
//| Class CDefaultComparer<T>. |
//| Usage: Provides a default class for implementations of the |
//| IComparer<T> generic interface. |
//+------------------------------------------------------------------+
template<typename T>
class CDefaultComparer: public IComparer<T>
{
public:
CDefaultComparer(void) { }
~CDefaultComparer(void) { }
//--- compares two values and returns a value describing relationship between them
int Compare(T x,T y) { return ::Compare(x,y); }
};
//+------------------------------------------------------------------+
@@ -0,0 +1,25 @@
//+------------------------------------------------------------------+
//| DefaultEqualityComparer.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Generic\Interfaces\IEqualityComparer.mqh>
#include "EqualFunction.mqh"
#include "HashFunction.mqh"
//+------------------------------------------------------------------+
//| Class CDefaultEqualityComparer<T>. |
//| Usage: Provides a default class for implementations of the |
//| IEqualityComparer<T> generic interface. |
//+------------------------------------------------------------------+
template<typename T>
class CDefaultEqualityComparer: public IEqualityComparer<T>
{
public:
CDefaultEqualityComparer(void) { }
~CDefaultEqualityComparer(void) { }
//--- determines whether the specified values are equal
bool Equals(T x,T y) { return ::Equals(x,y); }
//--- returns a hash code for the specified object
int HashCode(T value) { return ::GetHashCode(value); }
};
//+------------------------------------------------------------------+
+26
View File
@@ -0,0 +1,26 @@
//+------------------------------------------------------------------+
//| EqualFunction.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Generic\Interfaces\IEqualityComparable.mqh>
//+------------------------------------------------------------------+
//| Indicates whether x object is equal y object of the same type. |
//+------------------------------------------------------------------+
template<typename T>
bool Equals(T x,T y)
{
//--- try to convert to equality comparable object
IEqualityComparable<T>*equtable=dynamic_cast<IEqualityComparable<T>*>(x);
if(equtable)
{
//--- use specied equality compare method
return equtable.Equals(y);
}
else
{
//--- use default equality comparer operator
return(x==y);
}
}
//+------------------------------------------------------------------+
+176
View File
@@ -0,0 +1,176 @@
//+------------------------------------------------------------------+
//| HashFunction.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Unioun BitInterpreter. |
//| Usage: Provides the ability to interpret the same bit sequence in|
//| different types. |
//+------------------------------------------------------------------+
union BitInterpreter
{
bool bool_value;
char char_value;
uchar uchar_value;
short short_value;
ushort ushort_value;
color color_value;
int int_value;
uint uint_value;
datetime datetime_value;
long long_value;
ulong ulong_value;
float float_value;
double double_value;
};
//+------------------------------------------------------------------+
//| Returns a hashcode for boolean. |
//+------------------------------------------------------------------+
int GetHashCode(const bool value)
{
return((value)?true:false);
}
//+------------------------------------------------------------------+
//| Returns a hashcode for character. |
//+------------------------------------------------------------------+
int GetHashCode(const char value)
{
return((int)value | ((int)value << 16));
}
//+------------------------------------------------------------------+
//| Returns a hashcode for unsigned character. |
//+------------------------------------------------------------------+
int GetHashCode(const uchar value)
{
return((int)value | ((int)value << 16));
}
//+------------------------------------------------------------------+
//| Returns a hashcode for short. |
//+------------------------------------------------------------------+
int GetHashCode(const short value)
{
return(((int)((ushort)value) | (((int)value) << 16)));
}
//+------------------------------------------------------------------+
//| Returns a hashcode for unsigned short. |
//+------------------------------------------------------------------+
int GetHashCode(const ushort value)
{
return((int)value);
}
//+------------------------------------------------------------------+
//| Returns a hashcode for color. |
//+------------------------------------------------------------------+
int GetHashCode(const color value)
{
return((int)value);
}
//+------------------------------------------------------------------+
//| Returns a hashcode for integer. |
//+------------------------------------------------------------------+
int GetHashCode(const int value)
{
return(value);
}
//+------------------------------------------------------------------+
//| Returns a hashcode for unsigned integer. |
//+------------------------------------------------------------------+
int GetHashCode(const uint value)
{
return((int)value);
}
//+------------------------------------------------------------------+
//| Returns a hashcode for datetime. |
//+------------------------------------------------------------------+
int GetHashCode(const datetime value)
{
long ticks=(long)value;
return(((int)ticks) ^ (int)(ticks >> 32));
}
//+------------------------------------------------------------------+
//| Returns a hashcode for long. |
//+------------------------------------------------------------------+
int GetHashCode(const long value)
{
return(((int)((long)value)) ^ (int)(value >> 32));
}
//+------------------------------------------------------------------+
//| Returns a hashcode for unsigned long. |
//+------------------------------------------------------------------+
int GetHashCode(const ulong value)
{
return(((int)value) ^ (int)(value >> 32));
}
//+------------------------------------------------------------------+
//| Returns a hashcode for float. |
//+------------------------------------------------------------------+
int GetHashCode(const float value)
{
if(value==0)
{
//--- ensure that 0 and -0 have the same hash code
return(0);
}
BitInterpreter convert;
convert.float_value=value;
return(convert.int_value);
}
//+------------------------------------------------------------------+
//| Returns a hashcode for string. |
//+------------------------------------------------------------------+
int GetHashCode(const double value)
{
if(value==0)
{
//--- ensure that 0 and -0 have the same hash code
return(0);
}
BitInterpreter convert;
convert.double_value=value;
long lvalue=convert.long_value;
return(((int)lvalue) ^ ((int)(lvalue >> 32)));
}
//+------------------------------------------------------------------+
//| Returns a hashcode for string. |
//| The hashcode for a string is computed as: |
//| |
//| s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1] |
//| |
//| using int arithmetic, where s[i] is the ith character of the |
//| string, n is the length of the string, and ^ indicates |
//| exponentiation. (The hash value of the empty string is zero.) |
//+------------------------------------------------------------------+
int GetHashCode(const string value)
{
int len=StringLen(value);
int hash=0;
//--- check length of string
if(len>0)
{
//--- calculate a hash as a fucntion of each char
for(int i=0; i<len; i++)
hash=31*hash+value[i];
}
return(hash);
}
//+------------------------------------------------------------------+
//| Returns a hashcode for custom object. |
//+------------------------------------------------------------------+
template<typename T>
int GetHashCode(T value)
{
//--- try to convert to equality comparable object
IEqualityComparable<T>*equtable=dynamic_cast<IEqualityComparable<T>*>(value);
if(equtable)
{
//--- calculate hash by specied method
return equtable.HashCode();
}
else
{
//--- calculate hash from name of object
return GetHashCode(typename(value));
}
}
//+------------------------------------------------------------------+
+244
View File
@@ -0,0 +1,244 @@
//+------------------------------------------------------------------+
//| Introsort.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Struct Introsort<TKey,TItem>. |
//| Usage: Used by the sort methods for instances of array. |
//+------------------------------------------------------------------+
template<typename TKey,typename TItem>
struct Introsort
{
public:
IComparer<TKey>* comparer;
TKey keys[];
TItem items[];
Introsort(void) {}
~Introsort(void) {}
//--- method for sort array
void Sort(const int index,const int length);
private:
//--- methods for introspective sorting
void IntroSort(const int lo,const int hi,int depthLimit);
int PickPivotAndPartition(const int lo,const int hi);
void InsertionSort(const int lo,const int hi);
//--- methods for heap sorting
void Heapsort(const int lo,const int hi);
void DownHeap(const int i,const int n,const int lo);
//--- swap methods
void SwapIfGreaterWithItems(const int a,const int b);
void Swap(const int i,const int j);
//--- service methods
int FloorLog2(int n) const;
};
//+------------------------------------------------------------------+
//| IntrospectiveSort is a hybrid sorting algorithm that provides |
//| both fast average performance and (asymptotically) optimal |
//| worst-case performance. It begins with quicksort and switches to |
//| heapsort when the recursion depth exceeds a level based on the |
//| number of elements being sorted. |
//+------------------------------------------------------------------+
template<typename TKey,typename TItem>
void Introsort::Sort(const int index,const int length)
{
if(length<2)
return;
IntroSort(index,length+index-1,2*FloorLog2(ArraySize(keys)));
}
//+------------------------------------------------------------------+
//| Exchanges the values of a and b, if a greater b. |
//+------------------------------------------------------------------+
template<typename TKey,typename TItem>
void Introsort::SwapIfGreaterWithItems(const int a,const int b)
{
if(a!=b)
{
if(comparer.Compare(keys[a],keys[b])>0)
{
TKey key=keys[a];
keys[a]=keys[b];
keys[b]=key;
if(ArraySize(items)!=NULL)
{
TItem item=items[a];
items[a]=items[b];
items[b]=item;
}
}
}
}
//+------------------------------------------------------------------+
//| Exchanges the values of a and b. |
//+------------------------------------------------------------------+
template<typename TKey,typename TItem>
void Introsort::Swap(const int i,const int j)
{
TKey key=keys[i];
keys[i]=keys[j];
keys[j]=key;
if(ArraySize(items)!=NULL)
{
TItem item=items[i];
items[i]=items[j];
items[j]=item;
}
}
//+------------------------------------------------------------------+
//| Returns the closest integer value less than or equal to the base |
//| 2 log of the input value. |
//+------------------------------------------------------------------+
template<typename TKey,typename TItem>
int Introsort::FloorLog2(int n) const
{
int result=0;
while(n>=1)
{
result++;
n=n/2;
}
return(result);
}
//+------------------------------------------------------------------+
//| Introspective sort. |
//+------------------------------------------------------------------+
template<typename TKey,typename TItem>
void Introsort::IntroSort(const int lo,int hi,int depthLimit)
{
const int IntrosortSizeThreshold=16;
while(hi>lo)
{
int partitionSize = hi - lo + 1;
if(partitionSize <= IntrosortSizeThreshold)
{
if(partitionSize==1)
{
return;
}
if(partitionSize==2)
{
SwapIfGreaterWithItems(lo,hi);
return;
}
if(partitionSize==3)
{
SwapIfGreaterWithItems(lo,hi-1);
SwapIfGreaterWithItems(lo,hi);
SwapIfGreaterWithItems(hi-1,hi);
return;
}
InsertionSort(lo,hi);
return;
}
if(depthLimit==0)
{
Heapsort(lo,hi);
return;
}
depthLimit--;
int p=PickPivotAndPartition(lo,hi);
IntroSort(p+1,hi,depthLimit);
hi=p-1;
}
}
//+------------------------------------------------------------------+
//| Insertion sort. |
//+------------------------------------------------------------------+
template<typename TKey,typename TItem>
void Introsort::InsertionSort(const int lo,const int hi)
{
int i,j;
TKey t;
TItem dt;
for(i=lo; i<hi; i++)
{
j = i;
t = keys[i + 1];
dt=(ArraySize(items)!=NULL) ? (TItem)items[i+1] : (TItem)NULL;
while(j>=lo && comparer.Compare(t,keys[j])<0)
{
keys[j+1]=keys[j];
if(ArraySize(items)!=NULL)
{
items[j+1]=items[j];
}
j--;
}
keys[j+1]=t;
if(ArraySize(items)!=NULL)
{
items[j+1]=dt;
}
}
}
//+------------------------------------------------------------------+
//| Array partitioning by a quick sort algorithm. |
//+------------------------------------------------------------------+
template<typename TKey,typename TItem>
int Introsort::PickPivotAndPartition(const int lo,const int hi)
{
//--- Compute median-of-three. But also partition them, since we've done the comparison.
int mid=lo+(hi-lo)/2;
SwapIfGreaterWithItems(lo,mid);
SwapIfGreaterWithItems(lo,hi);
SwapIfGreaterWithItems(mid,hi);
TKey pivot=keys[mid];
Swap(mid,hi-1);
int left=lo,right=hi-1;
while(left<right)
{
while(comparer.Compare(keys[++left], pivot) < 0);
while(comparer.Compare(pivot, keys[--right]) < 0);
if(left>=right)
break;
Swap(left,right);
}
//--- Put pivot in the right location.
Swap(left,(hi-1));
return (left);
}
//+------------------------------------------------------------------+
//| Heap sorting algorithm. |
//+------------------------------------------------------------------+
template<typename TKey,typename TItem>
void Introsort::Heapsort(const int lo,const int hi)
{
int n=hi-lo+1;
for(int i=n/2; i>=1; i=i-1)
{
DownHeap(i,n,lo);
}
for(int i=n; i>1; i=i-1)
{
Swap(lo,lo+i-1);
DownHeap(1,i-1,lo);
}
}
//+------------------------------------------------------------------+
//| Downheap function for heapsort. |
//+------------------------------------------------------------------+
template<typename TKey,typename TItem>
void Introsort::DownHeap(int i,const int n,const int lo)
{
bool f=ArraySize(items)!=0;
TKey d=keys[lo+i-1];
TItem dt=f ? (TItem)items[lo+i-1] : (TItem)NULL;
while(i<=n/2)
{
int child=2*i;
if(child<n && comparer.Compare(keys[lo+child-1],keys[lo+child])<0)
child++;
if(!(comparer.Compare(d,keys[lo+child-1])<0))
break;
keys[lo+i-1]=keys[lo+child-1];
if(f)
items[lo+i-1]=items[lo+child-1];
i=child;
}
keys[lo+i-1]=d;
if(f)
items[lo+i-1]=dt;
}
//+------------------------------------------------------------------+
+81
View File
@@ -0,0 +1,81 @@
//+------------------------------------------------------------------+
//| PrimeGenerator.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Class CPrimeGenrator. |
//| Usage: Used to generate prime numbers. |
//+------------------------------------------------------------------+
class CPrimeGenerator
{
private:
const static int s_primes[]; // table of prime numbers
const static int s_hash_prime;
public:
static bool IsPrime(const int candidate);
static int GetPrime(const int min);
static int ExpandPrime(const int old_size);
};
const static int CPrimeGenerator::s_primes[]=
{
3,7,11,17,23,29,37,47,59,71,89,107,131,163,197,239,293,353,431,521,631,761,919,
1103,1327,1597,1931,2333,2801,3371,4049,4861,5839,7013,8419,10103,12143,14591,
17519,21023,25229,30293,36353,43627,52361,62851,75431,90523,108631,130363,156437,
187751,225307,270371,324449,389357,467237,560689,672827,807403,968897,1162687,1395263,
1674319,2009191,2411033,2893249,3471899,4166287,4999559,5999471,7199369,8332579,
9999161,11998949,14398753,16665163,19998337,23997907,28797523,33330329,39996683,
47995853,57595063,66660701,79993367,95991737,115190149,133321403,159986773,191983481,
230380307,266642809,319973567,383966977,460760623,533285671,639947149,767933981,
921521257,1066571383,1279894313,1535867969,1843042529,2133142771
};
const static int CPrimeGenerator::s_hash_prime=101;
//+------------------------------------------------------------------+
//| Determines whether a value is prime. |
//+------------------------------------------------------------------+
bool CPrimeGenerator::IsPrime(const int candidate)
{
if((candidate&1)!=0)
{
int limit=(int)MathSqrt(candidate);
//--- check value is prime
for(int divisor=3; divisor<=limit; divisor+=2)
if((candidate%divisor)==0)
return(false);
return(true);
}
return(candidate==2);
}
//+------------------------------------------------------------------+
//| Fast generator of prime value. |
//+------------------------------------------------------------------+
int CPrimeGenerator::GetPrime(const int min)
{
//--- a typical resize algorithm would pick the smallest prime number in this array
//--- that is larger than twice the previous capacity.
//--- get next prime value from table
for(int i=0; i<ArraySize(s_primes); i++)
{
int prime=s_primes[i];
if(prime>=min)
return(prime);
}
//--- outside of our predefined table
for(int i=(min|1); i<=INT_MAX;i+=2)
{
if(IsPrime(i) && ((i-1)%s_hash_prime!=0))
return(i);
}
return(min);
}
//+------------------------------------------------------------------+
//| Generate a new prime value greater than old_size. |
//+------------------------------------------------------------------+
int CPrimeGenerator::ExpandPrime(const int old_size)
{
if(old_size>=INT_MAX/2)
return(INT_MAX);
return(GetPrime(old_size*2));
}
//+------------------------------------------------------------------+
+563
View File
@@ -0,0 +1,563 @@
//+------------------------------------------------------------------+
//| LinkedList.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Generic\Interfaces\ICollection.mqh>
#include <Generic\Internal\EqualFunction.mqh>
//+------------------------------------------------------------------+
//| Class CLinkedListNode<T>. |
//| Usage: Represents a node of linked list. |
//+------------------------------------------------------------------+
template<typename T>
class CLinkedListNode
{
protected:
CLinkedList<T>*m_list;
CLinkedListNode<T>*m_next;
CLinkedListNode<T>*m_prev;
T m_item;
public:
CLinkedListNode(T value): m_item(value) { }
CLinkedListNode(CLinkedList<T>*list,T value): m_list(list),m_item(value) { }
~CLinkedListNode(void) { }
//--- methods of access to protected data
CLinkedList<T>* List(void) { return(m_list); }
void List(CLinkedList<T>*value) { m_list=value; }
CLinkedListNode<T>*Next(void) { return(m_next); }
void Next(CLinkedListNode<T>*value) { m_next=value; }
CLinkedListNode<T>*Previous(void) { return(m_prev); }
void Previous(CLinkedListNode<T>*value) { m_prev=value; }
T Value(void) { return(m_item); }
void Value(T value) { m_item=value; }
};
//+------------------------------------------------------------------+
//| Class CLinkedList<T>. |
//| Usage: Represents a doubly linked list. |
//+------------------------------------------------------------------+
template<typename T>
class CLinkedList: public ICollection<T>
{
protected:
CLinkedListNode<T>*m_head;
int m_count;
public:
CLinkedList(void);
CLinkedList(ICollection<T>*collection);
CLinkedList(T &array[]);
~CLinkedList(void);
//--- methods of filling data
bool Add(T value);
CLinkedListNode<T>*AddAfter(CLinkedListNode<T>*node,T value);
bool AddAfter(CLinkedListNode<T>*node,CLinkedListNode<T>*new_node);
CLinkedListNode<T>*AddBefore(CLinkedListNode<T>*node,T value);
bool AddBefore(CLinkedListNode<T>*node,CLinkedListNode<T>*new_node);
CLinkedListNode<T>*AddFirst(T value);
bool AddFirst(CLinkedListNode<T>*node);
CLinkedListNode<T>*AddLast(T value);
bool AddLast(CLinkedListNode<T>*node);
//--- methods of access to protected data
int Count(void);
CLinkedListNode<T>*Head(void) {return(m_head);}
CLinkedListNode<T>*First(void);
CLinkedListNode<T>*Last(void);
bool Contains(T item);
//--- methods of copy data from collection
int CopyTo(T &dst_array[],const int dst_start=0);
//--- methods of cleaning and deleting
void Clear(void);
bool Remove(T item);
bool Remove(CLinkedListNode<T>*node);
bool RemoveFirst(void);
bool RemoveLast(void);
//--- method for searching
CLinkedListNode<T>*Find(T value);
CLinkedListNode<T>*FindLast(T value);
private:
bool ValidateNode(CLinkedListNode<T>*node);
bool ValidateNewNode(CLinkedListNode<T>*node);
void InternalInsertNodeBefore(CLinkedListNode<T>*node,CLinkedListNode<T>*new_node);
void InternalInsertNodeToEmptyList(CLinkedListNode<T>*new_node);
void InternalRemoveNode(CLinkedListNode<T>*node);
};
//+------------------------------------------------------------------+
//| Initializes a new instance of the CLinkedList<T> class that is |
//| empty. |
//+------------------------------------------------------------------+
template<typename T>
CLinkedList::CLinkedList(void): m_count(0)
{
}
//+------------------------------------------------------------------+
//| Initializes a new instance of the CLinkedList<T> class that |
//| contains elements copied from the specified array and has |
//| sufficient capacity to accommodate the number of elements copied.|
//+------------------------------------------------------------------+
template<typename T>
CLinkedList::CLinkedList(T &array[]): m_count(0)
{
for(int i=0; i<ArraySize(array); i++)
AddLast(array[i]);
}
//+------------------------------------------------------------------+
//| Initializes a new instance of the CLinkedList<T> class that |
//| contains elements copied from the specified collection and has |
//| sufficient capacity to accommodate the number of elements copied.|
//+------------------------------------------------------------------+
template<typename T>
CLinkedList::CLinkedList(ICollection<T>*collection): m_count(0)
{
//--- check collection
if(CheckPointer(collection)!=POINTER_INVALID)
{
T array[];
int size=collection.CopyTo(array,0);
for(int i=0; i<size; i++)
AddLast(array[i]);
}
}
//+------------------------------------------------------------------+
//| Destructor. |
//+------------------------------------------------------------------+
template<typename T>
CLinkedList::~CLinkedList(void)
{
Clear();
}
//+------------------------------------------------------------------+
//| Adds an value to the end of the list. |
//+------------------------------------------------------------------+
template<typename T>
bool CLinkedList::Add(T value)
{
return(CheckPointer(AddLast(value))!=POINTER_INVALID);
}
//+------------------------------------------------------------------+
//| Adds a new node containing the specified value after the |
//| specified existing node in the CLinkedList<T>. |
//+------------------------------------------------------------------+
template<typename T>
CLinkedListNode<T>*CLinkedList::AddAfter(CLinkedListNode<T>*node,T value)
{
//--- check node
if(!ValidateNode(node))
return(NULL);
//--- create new node
CLinkedListNode<T>*result=new CLinkedListNode<T>(node.List(),value);
//--- insert node to the list
InternalInsertNodeBefore(node.Next(),result);
return(result);
}
//+------------------------------------------------------------------+
//| Adds the specified new node after the specified existing node in |
//| the LinkedList<T>. |
//+------------------------------------------------------------------+
template<typename T>
bool CLinkedList::AddAfter(CLinkedListNode<T>*node,CLinkedListNode<T>*new_node)
{
//--- check node
if(!ValidateNode(node))
return(false);
//--- check new node
if(!ValidateNewNode(new_node))
return(false);
//--- insert node to the list
InternalInsertNodeBefore(node.Next(),new_node);
//--- set the current list as list for new node
new_node.List(GetPointer(this));
return(true);
}
//+------------------------------------------------------------------+
//| Adds a new node containing the specified value before the |
//| specified existing node in the CLinkedList<T>. |
//+------------------------------------------------------------------+
template<typename T>
CLinkedListNode<T>*CLinkedList::AddBefore(CLinkedListNode<T>*node,T value)
{
//--- check node
if(!ValidateNode(node))
return(NULL);
//--- create new node
CLinkedListNode<T>*result=new CLinkedListNode<T>(node.List(),value);
//--- insert node to the list
InternalInsertNodeBefore(node,result);
if(node==m_head)
m_head=result;
return(result);
}
//+------------------------------------------------------------------+
//| Adds the specified new node before the specified existing node in|
//| the LinkedList<T>. |
//+------------------------------------------------------------------+
template<typename T>
bool CLinkedList::AddBefore(CLinkedListNode<T>*node,CLinkedListNode<T>*new_node)
{
//--- check node
if(!ValidateNode(node))
return(false);
//--- check new node
if(!ValidateNewNode(new_node))
return(false);
//--- insert node to the list
InternalInsertNodeBefore(node,new_node);
//--- set the current list as list for new node
new_node.List(GetPointer(this));
if(node==m_head)
m_head=new_node;
return(true);
}
//+------------------------------------------------------------------+
//| Adds a new node containing the specified value at the start of |
//| the CLinkedList<T>. |
//+------------------------------------------------------------------+
template<typename T>
CLinkedListNode<T>*CLinkedList::AddFirst(T value)
{
//--- create new node
CLinkedListNode<T>*node=new CLinkedListNode<T>(GetPointer(this),value);
//--- check head node
if(CheckPointer(m_head)==POINTER_INVALID)
{
//--- insert node to the empty list
InternalInsertNodeToEmptyList(node);
}
else
{
//--- insert node to the list
InternalInsertNodeBefore(m_head,node);
m_head=node;
}
return(node);
}
//+------------------------------------------------------------------+
//| Adds the specified new node at the start of the CLinkedList<T>. |
//+------------------------------------------------------------------+
template<typename T>
bool CLinkedList::AddFirst(CLinkedListNode<T>*node)
{
//--- check node
if(!ValidateNewNode(node))
return(false);
//--- check head node
if(CheckPointer(m_head)==POINTER_INVALID)
{
//--- insert node to the empty list
InternalInsertNodeToEmptyList(node);
}
else
{
//--- insert node to the list
InternalInsertNodeBefore(m_head,node);
m_head=node;
}
//--- set the current list as list for node
node.List(GetPointer(this));
return(true);
}
//+------------------------------------------------------------------+
//| Adds a new node containing the specified value at the end of the |
//| CLinkedList<T>. |
//+------------------------------------------------------------------+
template<typename T>
CLinkedListNode<T>*CLinkedList::AddLast(T value)
{
//--- create new node
CLinkedListNode<T>*node=new CLinkedListNode<T>(GetPointer(this),value);
//--- check head node
if(CheckPointer(m_head)==POINTER_INVALID)
{
//--- insert node to the empty list
InternalInsertNodeToEmptyList(node);
}
else
{
//--- insert node to the list
InternalInsertNodeBefore(m_head,node);
}
return(node);
}
//+------------------------------------------------------------------+
//| Adds the specified new node at the end of the CLinkedList<T>. |
//+------------------------------------------------------------------+
template<typename T>
bool CLinkedList::AddLast(CLinkedListNode<T>*node)
{
//--- check node
if(!ValidateNewNode(node))
return(false);
//--- check head node
if(CheckPointer(m_head)==POINTER_INVALID)
{
//--- insert node to the empty list
InternalInsertNodeToEmptyList(node);
}
else
{
//--- insert node to the list
InternalInsertNodeBefore(m_head,node);
}
//--- set the current list as list for node
node.List(GetPointer(this));
return(true);
}
//+------------------------------------------------------------------+
//| Determines whether an element is in the linked list. |
//+------------------------------------------------------------------+
template<typename T>
int CLinkedList::Count(void)
{
return(m_count);
}
//+------------------------------------------------------------------+
//| Gets the first node of the CLinkedList<T>. |
//+------------------------------------------------------------------+
template<typename T>
CLinkedListNode<T>*CLinkedList::First(void)
{
return(m_head);
}
//+------------------------------------------------------------------+
//| Gets the last node of the CLinkedList<T>. |
//+------------------------------------------------------------------+
template<typename T>
CLinkedListNode<T>*CLinkedList::Last(void)
{
return(CheckPointer(m_head)!=POINTER_INVALID ? m_head.Previous() : NULL);
}
//+------------------------------------------------------------------+
//| Determines whether a value is in the CLinkedList<T>. |
//+------------------------------------------------------------------+
template<typename T>
bool CLinkedList::Contains(T item)
{
return(CheckPointer(Find(item))!=POINTER_INVALID);
}
//+------------------------------------------------------------------+
//| Copies a range of elements from the linkedlist to a compatible |
//| one-dimensional array. |
//+------------------------------------------------------------------+
template<typename T>
int CLinkedList::CopyTo(T &dst_array[],const int dst_start=0)
{
//--- resize array
if(dst_start+m_count>ArraySize(dst_array))
ArrayResize(dst_array,dst_start+m_count);
//--- check start index
if(dst_start>ArraySize(dst_array))
return(0);
//--- start copy
CLinkedListNode<T>*node=m_head;
if(CheckPointer(node)!=POINTER_INVALID)
{
int dst_index=dst_start;
do
{
dst_array[dst_index++]=node.Value();
node=node.Next();
}
while(dst_index<ArraySize(dst_array) && node!=m_head);
return(dst_index-dst_start);
}
//--- list is empty
return(0);
}
//+------------------------------------------------------------------+
//| Removes all nodes from the CLinkedList<T>. |
//+------------------------------------------------------------------+
template<typename T>
void CLinkedList::Clear(void)
{
//--- check count
if(m_count>0)
{
//--- check head node
if(CheckPointer(m_head)!=POINTER_INVALID)
{
while(m_head.Next()!=m_head)
{
CLinkedListNode<T>*node=m_head.Next();
m_head.Next(node.Next());
delete node;
}
delete m_head;
}
//--- reset count
m_count=0;
}
}
//+------------------------------------------------------------------+
//| Removes the first occurrence of the specified value from the |
//| CLinkedList<T>. |
//+------------------------------------------------------------------+
template<typename T>
bool CLinkedList::Remove(T item)
{
//--- find node with specified value
CLinkedListNode<T>*node=Find(item);
if(CheckPointer(node)!=POINTER_INVALID)
{
//--- remove node
InternalRemoveNode(node);
return(true);
}
return(false);
}
//+------------------------------------------------------------------+
//| Removes the specified node from the LinkedList<T>. |
//+------------------------------------------------------------------+
template<typename T>
bool CLinkedList::Remove(CLinkedListNode<T>*node)
{
//--- check node
if(ValidateNode(node))
{
//--- remove node
InternalRemoveNode(node);
return(true);
}
return(false);
}
//+------------------------------------------------------------------+
//| Removes the node at the start of the CLinkedList<T>. |
//+------------------------------------------------------------------+
template<typename T>
bool CLinkedList::RemoveFirst(void)
{
//--- check head node
if(CheckPointer(m_head)==POINTER_INVALID)
return(false);
//--- remove head node
InternalRemoveNode(m_head);
return(true);
}
//+------------------------------------------------------------------+
//| Removes the node at the end of the CLinkedList<T>. |
//+------------------------------------------------------------------+
template<typename T>
bool CLinkedList::RemoveLast(void)
{
//--- check head node
if(CheckPointer(m_head)==POINTER_INVALID)
return(false);
//--- remove last node
InternalRemoveNode(m_head.Previous());
return(true);
}
//+------------------------------------------------------------------+
//| Finds the first node that contains the specified value. |
//+------------------------------------------------------------------+
template<typename T>
CLinkedListNode<T>*CLinkedList::Find(T value)
{
CLinkedListNode<T>*node=m_head;
//--- start search specified value in the list
if(CheckPointer(node)!=POINTER_INVALID)
{
do
{
//--- use default equals function
if(::Equals(node.Value(),value))
return(node);
node=node.Next();
}
while(node!=m_head);
}
return(NULL);
}
//+------------------------------------------------------------------+
//| Finds the last node that contains the specified value. |
//+------------------------------------------------------------------+
template<typename T>
CLinkedListNode<T>*CLinkedList::FindLast(T value)
{
//--- check head node
if(CheckPointer(m_head)==POINTER_INVALID)
return(NULL);
//--- get last node
CLinkedListNode<T> *last = m_head.Previous();
CLinkedListNode<T> *node = last;
//--- start search from the end of the list
if(node!=NULL)
{
do
{
//--- use default equals function
if(::Equals(node.Value(),value))
return(node);
node=node.Previous();
}
while(node!=last);
}
return(NULL);
}
//+------------------------------------------------------------------+
//| Validation of node on not null and belongs in the current list. |
//+------------------------------------------------------------------+
template<typename T>
bool CLinkedList::ValidateNode(CLinkedListNode<T>*node)
{
return(CheckPointer(node)!=POINTER_INVALID && node.List()==GetPointer(this));
}
//+------------------------------------------------------------------+
//| Validation of new node on not null. |
//+------------------------------------------------------------------+
template<typename T>
bool CLinkedList::ValidateNewNode(CLinkedListNode<T>*node)
{
return(CheckPointer(node)!=POINTER_INVALID && node.List()==NULL);
}
//+------------------------------------------------------------------+
//| Insert node before the specified node. |
//+------------------------------------------------------------------+
template<typename T>
void CLinkedList::InternalInsertNodeBefore(CLinkedListNode<T>*node,CLinkedListNode<T>*new_node)
{
//--- set node befor the specified node
new_node.Next(node);
new_node.Previous(node.Previous());
node.Previous().Next(new_node);
node.Previous(new_node);
//--- increment count
m_count++;
}
//+------------------------------------------------------------------+
//| Add first node to the list. |
//+------------------------------------------------------------------+
template<typename T>
void CLinkedList::InternalInsertNodeToEmptyList(CLinkedListNode<T>*new_node)
{
//--- set node as head of the list
new_node.Next(new_node);
new_node.Previous(new_node);
m_head=new_node;
//--- increment count
m_count++;
}
//+------------------------------------------------------------------+
//| Remove specified node from the list. |
//+------------------------------------------------------------------+
template<typename T>
void CLinkedList::InternalRemoveNode(CLinkedListNode<T>*node)
{
//--- check node
if(node.Next()==node)
{
//--- resets the head of the list
m_head=NULL;
}
else
{
//--- detach node from the list
node.Next().Previous(node.Previous());
node.Previous().Next(node.Next());
if(m_head==node)
m_head=node.Next();
}
//--- decrement count and delete node
m_count--;
delete node;
}
//+------------------------------------------------------------------+
BIN
View File
Binary file not shown.
Binary file not shown.
+341
View File
@@ -0,0 +1,341 @@
//+------------------------------------------------------------------+
//| SortedMap.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Generic\Interfaces\IMap.mqh>
#include <Generic\Interfaces\IComparer.mqh>
#include <Generic\Internal\DefaultComparer.mqh>
#include <Generic\Internal\CompareFunction.mqh>
#include "HashMap.mqh"
#include "SortedSet.mqh"
//+------------------------------------------------------------------+
//| Class CSortedMap<TKey, TValue>. |
//| Usage: Represents a collection of key/value pairs that are sorted|
//| on the key. |
//+------------------------------------------------------------------+
template<typename TKey,typename TValue>
class CSortedMap: public IMap<TKey,TValue>
{
protected:
CRedBlackTree<CKeyValuePair<TKey,TValue>*>*m_tree;
IComparer<TKey>*m_comparer;
bool m_delete_comparer;
public:
CSortedMap(void);
CSortedMap(IComparer<TKey>*comparer);
CSortedMap(IMap<TKey,TValue>*map);
CSortedMap(IMap<TKey,TValue>*map,IComparer<TKey>*comparer);
~CSortedMap(void);
//--- methods of filling data
bool Add(CKeyValuePair<TKey,TValue>*value) { return m_tree.Add(value); }
bool Add(TKey key,TValue value);
//--- methods of access to protected data
int Count(void) { return m_tree.Count(); }
bool Contains(CKeyValuePair<TKey,TValue>*item) { return m_tree.Contains(item); }
bool Contains(TKey key,TValue value);
bool ContainsKey(TKey key);
bool ContainsValue(TValue value);
IComparer<TKey> *Comparer(void) const { return(m_comparer); }
//--- methods of copy data from collection
int CopyTo(CKeyValuePair<TKey,TValue>*&dst_array[],const int dst_start=0);
int CopyTo(TKey &dst_keys[],TValue &dst_values[],const int dst_start=0);
//--- methods of cleaning and deleting
void Clear(void);
bool Remove(CKeyValuePair<TKey,TValue>*item) { return m_tree.Remove(item); }
bool Remove(TKey key);
//--- method of access to the data
bool TryGetValue(TKey key,TValue &value);
bool TrySetValue(TKey key,TValue value);
private:
static void ClearNodes(CRedBlackTreeNode<CKeyValuePair<TKey,TValue>*>*node);
};
//+------------------------------------------------------------------+
//| Initializes a new instance of the CSortedMap<TKey,TValue> class |
//| that is empty, has the default initial capacity, and uses the |
//| default comparer for the key type. |
//+------------------------------------------------------------------+
template<typename TKey,typename TValue>
CSortedMap::CSortedMap(void)
{
//--- use default comaprer
m_comparer=new CDefaultComparer<TKey>();
m_delete_comparer=true;
m_tree=new CRedBlackTree<CKeyValuePair<TKey,TValue>*>(new CKeyValuePairComparer<TKey,TValue>(m_comparer));
}
//+------------------------------------------------------------------+
//| Initializes a new instance of the CSortedMap<TKey,TValue> class |
//| that is empty, has the default initial capacity, and uses the |
//| specified IComparer<TKey>. |
//+------------------------------------------------------------------+
template<typename TKey,typename TValue>
CSortedMap::CSortedMap(IComparer<TKey>*comparer)
{
//--- check comaprer
if(CheckPointer(comparer)==POINTER_INVALID)
{
//--- use default comaprer
m_comparer=new CDefaultComparer<TKey>();
m_delete_comparer=true;
}
else
{
//--- use specified comaprer
m_comparer=comparer;
m_delete_comparer=false;
}
m_tree=new CRedBlackTree<CKeyValuePair<TKey,TValue>*>(new CKeyValuePairComparer<TKey,TValue>(m_comparer));
}
//+------------------------------------------------------------------+
//| Initializes a new instance of the CSortedMap<TKey,TValue> class |
//| that contains elements copied from the specified |
//| IMap<TKey,TValue> and uses the default comparer for the key type.|
//+------------------------------------------------------------------+
template<typename TKey,typename TValue>
CSortedMap::CSortedMap(IMap<TKey,TValue>*map)
{
//--- use default comaprer
m_comparer=new CDefaultComparer<TKey>();
m_delete_comparer=true;
m_tree=new CRedBlackTree<CKeyValuePair<TKey,TValue>*>(map,new CKeyValuePairComparer<TKey,TValue>(m_comparer));
}
//+------------------------------------------------------------------+
//| Initializes a new instance of the CSortedMap<TKey,TValue> class |
//| that contains elements copied from the specified |
//| IMap<TKey,TValue> and uses the specified IComparer<TKey>. |
//+------------------------------------------------------------------+
template<typename TKey,typename TValue>
CSortedMap::CSortedMap(IMap<TKey,TValue>*map,IComparer<TKey>*comparer)
{
//--- check comaprer
if(CheckPointer(comparer)==POINTER_INVALID)
{
//--- use default comaprer
m_comparer=new CDefaultComparer<TKey>();
m_delete_comparer=true;
}
else
{
//--- use specified comaprer
m_comparer=comparer;
m_delete_comparer=false;
}
m_tree=new CRedBlackTree<CKeyValuePair<TKey,TValue>*>(map,new CKeyValuePairComparer<TKey,TValue>(m_comparer));
}
//+------------------------------------------------------------------+
//| Destructor. |
//+------------------------------------------------------------------+
template<typename TKey,typename TValue>
CSortedMap::~CSortedMap(void)
{
//--- delete comparer
if(m_delete_comparer)
delete m_comparer;
//--- delete tree comparer
delete m_tree.Comparer();
//--- delete nodes values
ClearNodes(m_tree.Root());
//--- delete tree and nodes
delete m_tree;
}
//+------------------------------------------------------------------+
//| Walk all nodes of tree and delete their value. |
//+------------------------------------------------------------------+
template<typename TKey,typename TValue>
static void CSortedMap::ClearNodes(CRedBlackTreeNode<CKeyValuePair<TKey,TValue>*>*node)
{
//--- check node
if(CheckPointer(node)==POINTER_INVALID)
return;
//--- walk of a right subtree
if(!node.Right().IsLeaf())
ClearNodes(node.Right());
//--- delete value
delete node.Value();
//--- walk of a left subtree
if(!node.Left().IsLeaf())
ClearNodes(node.Left());
}
//+------------------------------------------------------------------+
//| Adds the specified key and value to the map. |
//+------------------------------------------------------------------+
template<typename TKey,typename TValue>
bool CSortedMap::Add(TKey key,TValue value)
{
//--- create pair
CKeyValuePair<TKey,TValue>*pair=new CKeyValuePair<TKey,TValue>(key,value);
//--- add pair to tree
bool success=m_tree.Add(pair);
//--- if addition was not successful delte pair
if(!success)
delete pair;
return(success);
}
//+------------------------------------------------------------------+
//| Determines whether the map contains the specified key with value.|
//+------------------------------------------------------------------+
template<typename TKey,typename TValue>
bool CSortedMap::Contains(TKey key,TValue value)
{
//--- find node with specified key
CKeyValuePair<TKey,TValue>pair(key,NULL);
CRedBlackTreeNode<CKeyValuePair<TKey,TValue>*>*node=m_tree.Find(GetPointer(pair));
//--- create value comparer
CDefaultEqualityComparer<TValue>comaprer;
//--- determine whether the finding node contains specified value
if(CheckPointer(node)!=POINTER_INVALID && comaprer.Equals(value,node.Value().Value()))
return(true);
return(false);
}
//+------------------------------------------------------------------+
//| Determines whether the map contains the specified key. |
//+------------------------------------------------------------------+
template<typename TKey,typename TValue>
bool CSortedMap::ContainsKey(TKey key)
{
//--- crete pair
CKeyValuePair<TKey,TValue>pair(key,NULL);
//--- determines whether the tree contains the pair.
return m_tree.Contains(GetPointer(pair));
}
//+------------------------------------------------------------------+
//| Determines whether the map contains the specified value. |
//+------------------------------------------------------------------+
template<typename TKey,typename TValue>
bool CSortedMap::ContainsValue(TValue value)
{
//--- copy all pairs in array
CKeyValuePair<TKey,TValue>*array[];
int count=m_tree.CopyTo(array);
//--- create value comparer
CDefaultEqualityComparer<TValue>comaprer;
//--- determines whether the array contains the specified value
for(int i=0; i<count; i++)
if(comaprer.Equals(value,array[i].Value()))
return(true);
return(false);
}
//+------------------------------------------------------------------+
//| Copies a range of elements from the map to a compatible |
//| one-dimensional array. |
//+------------------------------------------------------------------+
template<typename TKey,typename TValue>
int CSortedMap::CopyTo(CKeyValuePair<TKey,TValue>*&dst_array[],const int dst_start=0)
{
int result=m_tree.CopyTo(dst_array,dst_start);
if(result>0)
{
//--- create clones for each pair
for(int i=0; i<result; i++)
dst_array[dst_start+i]=dst_array[dst_start+i].Clone();
}
return(result);
}
//+------------------------------------------------------------------+
//| Copies a range of elements from the map to a compatible |
//| one-dimensionals keys and values arrays. |
//+------------------------------------------------------------------+
template<typename TKey,typename TValue>
int CSortedMap::CopyTo(TKey &dst_keys[],TValue &dst_values[],const int dst_start=0)
{
//--- create array and copy all values from tree to there
CKeyValuePair<TKey,TValue>*array[];
int count=m_tree.CopyTo(array);
//--- check real cout
if(count>0)
{
//--- resize keys array
if(dst_start+count>ArraySize(dst_keys))
ArrayResize(dst_keys,dst_start+count);
//--- resize values array
if(dst_start+count>ArraySize(dst_values))
ArrayResize(dst_values,MathMin(ArraySize(dst_keys),dst_start+count));
//--- start copy
int index=0;
while(index<count && dst_start+index<ArraySize(dst_keys) && dst_start+index<ArraySize(dst_values))
{
dst_keys[dst_start+index]=array[index].Key();
dst_values[dst_start+index]=array[index].Value();
index++;
}
return(index);
}
return(0);
}
//+------------------------------------------------------------------+
//| Clear and delete all values from map. |
//+------------------------------------------------------------------+
template<typename TKey,typename TValue>
void CSortedMap::Clear(void)
{
//--- check count
if(m_tree.Count()>0)
{
//--- delete nodes values
ClearNodes(m_tree.Root());
//--- claer th tree
m_tree.Clear();
}
}
//+------------------------------------------------------------------+
//| Removes the value with the specified key from the map. |
//+------------------------------------------------------------------+
template<typename TKey,typename TValue>
bool CSortedMap::Remove(TKey key)
{
//--- create pair with specified key
CKeyValuePair<TKey,TValue>pair(key,NULL);
//--- find node
CRedBlackTreeNode<CKeyValuePair<TKey,TValue>*>*node=m_tree.Find(GetPointer(pair));
//--- check node
if(CheckPointer(node)!=POINTER_INVALID)
{
CKeyValuePair<TKey,TValue>*real_pair=node.Value();
//--- remove node from tree
if(m_tree.Remove(node))
{
//--- check and delete node value
if(CheckPointer(real_pair)==POINTER_DYNAMIC)
delete real_pair;
return(true);
}
}
return(false);
}
//+------------------------------------------------------------------+
//| Gets the value associated with the specified key. |
//+------------------------------------------------------------------+
template<typename TKey,typename TValue>
bool CSortedMap::TryGetValue(TKey key,TValue &value)
{
//--- create pair with specified key
CKeyValuePair<TKey,TValue>pair(key,NULL);
//--- find node with specified pair in the tree
CRedBlackTreeNode<CKeyValuePair<TKey,TValue>*>*node=m_tree.Find(GetPointer(pair));
//--- check node
if(CheckPointer(node)==POINTER_INVALID)
return(false);
//--- get value
value=node.Value().Value();
return(true);
}
//+------------------------------------------------------------------+
//| Sets the value associated with the specified key. |
//+------------------------------------------------------------------+
template<typename TKey,typename TValue>
bool CSortedMap::TrySetValue(TKey key,TValue value)
{
//--- create pair with specified key
CKeyValuePair<TKey,TValue>pair(key,NULL);
//--- find node with specified pair in the tree
CRedBlackTreeNode<CKeyValuePair<TKey,TValue>*>*node=m_tree.Find(GetPointer(pair));
//--- check node
if(CheckPointer(node)==POINTER_INVALID)
return(false);
//--- set value
node.Value().Value(value);
return(true);
}
//+------------------------------------------------------------------+
+673
View File
@@ -0,0 +1,673 @@
//+------------------------------------------------------------------+
//| SortedList.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Generic\Interfaces\ISet.mqh>
#include <Generic\Internal\Introsort.mqh>
#include "RedBlackTree.mqh"
#include "HashSet.mqh"
//+------------------------------------------------------------------+
//| Class CSortedSet<T>. |
//| Usage: Represents a collection of objects that is maintained in |
//| sorted order. |
//+------------------------------------------------------------------+
template<typename T>
class CSortedSet: public ISet<T>
{
protected:
CRedBlackTree<T>*m_tree;
public:
CSortedSet(void);
CSortedSet(IComparer<T>*comparer);
CSortedSet(ICollection<T>*collection);
CSortedSet(ICollection<T>*collection,IComparer<T>*comparer);
CSortedSet(T &array[]);
CSortedSet(T &array[],IComparer<T>*comparer);
~CSortedSet(void);
//--- methods of filling data
bool Add(T value) { return(m_tree.Add(value)); }
//--- methods of access to protected data
int Count(void) { return(m_tree.Count()); }
bool Contains(T item) { return(m_tree.Contains(item)); }
IComparer<T> *Comparer(void) const { return(m_tree.Comparer()); }
bool TryGetMin(T &min) { return(m_tree.TryGetMin(min)); }
bool TryGetMax(T &max) { return(m_tree.TryGetMax(max)); }
//--- methods of copy data from collection
int CopyTo(T &dst_array[],const int dst_start=0);
//--- methods of cleaning and deleting
void Clear(void) { m_tree.Clear(); }
bool Remove(T item) { return(m_tree.Remove(item)); }
//--- methods of changing sets
void ExceptWith(ICollection<T>*collection);
void ExceptWith(T &array[]);
void IntersectWith(ICollection<T>*collection);
void IntersectWith(T &array[]);
void SymmetricExceptWith(ICollection<T>*collection);
void SymmetricExceptWith(T &array[]);
void UnionWith(ICollection<T>*collection);
void UnionWith(T &array[]);
//--- methods for determining the relationship between sets
bool IsProperSubsetOf(ICollection<T>*collection);
bool IsProperSubsetOf(T &array[]);
bool IsProperSupersetOf(ICollection<T>*collection);
bool IsProperSupersetOf(T &array[]);
bool IsSubsetOf(ICollection<T>*collection);
bool IsSubsetOf(T &array[]);
bool IsSupersetOf(ICollection<T>*collection);
bool IsSupersetOf(T &array[]);
bool Overlaps(ICollection<T>*collection);
bool Overlaps(T &array[]);
bool SetEquals(ICollection<T>*collection);
bool SetEquals(T &array[]);
//--- methods for working with an ordered set
bool GetViewBetween(T &array[],T lower_value,T upper_value);
bool GetReverse(T &array[]);
};
//+------------------------------------------------------------------+
//| Initializes a new instance of the CSortedSet<T> class that is |
//| empty and uses the default equality comparer for the set type. |
//+------------------------------------------------------------------+
template<typename T>
CSortedSet::CSortedSet(void)
{
m_tree=new CRedBlackTree<T>();
}
//+------------------------------------------------------------------+
//| Initializes a new instance of the CSortedSet<T> class that is |
//| empty and uses the specified equality comparer for the set type. |
//+------------------------------------------------------------------+
template<typename T>
CSortedSet::CSortedSet(IComparer<T>*comparer)
{
m_tree=new CRedBlackTree<T>(comparer);
}
//+------------------------------------------------------------------+
//| Initializes a new instance of the CSortedSet<T> class that uses |
//| the default equality comparer for the set type, contains elements|
//| copied from the specified collection, and has sufficient capacity|
//| to accommodate the number of elements copied. |
//+------------------------------------------------------------------+
template<typename T>
CSortedSet::CSortedSet(ICollection<T>*collection)
{
m_tree=new CRedBlackTree<T>(collection);
}
//+------------------------------------------------------------------+
//| Initializes a new instance of the CSortedSet<T> class that uses |
//| the specified equality comparer for the set type, contains |
//| elements copied from the specified collection, and has sufficient|
//| capacity to accommodate the number of elements copied. |
//+------------------------------------------------------------------+
template<typename T>
CSortedSet::CSortedSet(ICollection<T>*collection,IComparer<T>*comparer)
{
m_tree=new CRedBlackTree<T>(collection,comparer);
}
//+------------------------------------------------------------------+
//| Initializes a new instance of the CSortedSet<T> class that uses |
//| the default equality comparer for the set type, contains |
//| elements copied from the specified array, and has sufficient |
//| capacity to accommodate the number of elements copied. |
//+------------------------------------------------------------------+
template<typename T>
CSortedSet::CSortedSet(T &array[])
{
m_tree=new CRedBlackTree<T>(array);
}
//+------------------------------------------------------------------+
//| Initializes a new instance of the CSortedSet<T> class that uses |
//| the specified equality comparer for the set type, contains |
//| elements copied from the specified array, and has sufficient |
//| capacity to accommodate the number of elements copied. |
//+------------------------------------------------------------------+
template<typename T>
CSortedSet::CSortedSet(T &array[],IComparer<T>*comparer)
{
m_tree=new CRedBlackTree<T>(array,comparer);
}
//+------------------------------------------------------------------+
//| Destructor. |
//+------------------------------------------------------------------+
template<typename T>
CSortedSet::~CSortedSet(void)
{
delete m_tree;
}
//+------------------------------------------------------------------+
//| Copies a range of elements from the set to a compatible |
//| one-dimensional array. |
//+------------------------------------------------------------------+
template<typename T>
int CSortedSet::CopyTo(T &dst_array[],const int dst_start=0)
{
return(m_tree.CopyTo(dst_array, dst_start));
}
//+------------------------------------------------------------------+
//| Removes all elements in the specified collection from the current|
//| set. |
//+------------------------------------------------------------------+
template<typename T>
void CSortedSet::ExceptWith(ICollection<T>*collection)
{
//--- check collection
if(CheckPointer(collection)==POINTER_INVALID)
return;
//--- check tree count
if(m_tree.Count()==0)
return;
//--- special case if collection is this
//--- a set minus itself is the empty set
if(collection==GetPointer(this))
{
Clear();
return;
}
//--- copy collection to array
T array[];
int size=collection.CopyTo(array);
//--- find max and min value
T max;
T min;
//--- get comaprer
IComparer<T>*comparer=Comparer();
if(!m_tree.TryGetMax(max))
return;
if(!m_tree.TryGetMin(min))
return;
//--- remove elements
for(int i=0; i<size; i++)
{
T item=array[i];
if(!(comparer.Compare(item,min)<0 || comparer.Compare(item,max)>0) && Contains(item))
m_tree.Remove(item);
}
}
//+------------------------------------------------------------------+
//| Removes all elements in the specified array from the current set.|
//+------------------------------------------------------------------+
template<typename T>
void CSortedSet::ExceptWith(T &array[])
{
//--- check tree count
if(m_tree.Count()==0)
return;
//--- get array size
int size=ArraySize(array);
//--- find max and min value
T max;
T min;
//--- get comparer
IComparer<T>*comparer=Comparer();
if(!m_tree.TryGetMax(max))
return;
if(!m_tree.TryGetMin(min))
return;
//--- remove elements
for(int i=0; i<size; i++)
{
T item=array[i];
if(!(comparer.Compare(item,min)<0 || comparer.Compare(item,max)>0) && Contains(item))
m_tree.Remove(item);
}
}
//+------------------------------------------------------------------+
//| Modifies the current set to contain only elements that are |
//| present in that object and in the specified collection. |
//+------------------------------------------------------------------+
template<typename T>
void CSortedSet::IntersectWith(ICollection<T>*collection)
{
//--- check collection
if(CheckPointer(collection)==POINTER_INVALID)
return;
//--- check tree count
if(m_tree.Count()==0)
return;
//--- special case if collection is this
//--- a set minus itself is the empty set
if(collection==GetPointer(this))
return;
//--- copy collection to array
T array[];
int size=collection.CopyTo(array);
//--- create emty tree
CRedBlackTree<T>*tree=new CRedBlackTree<T>();
//--- store values conatin in tree and array
for(int i=0; i<size; i++)
if(m_tree.Contains(array[i]))
tree.Add(array[i]);
//--- overwrite tree
delete m_tree;
m_tree=tree;
}
//+------------------------------------------------------------------+
//| Modifies the current set to contain only elements that are |
//| present in that object and in the specified array. |
//+------------------------------------------------------------------+
template<typename T>
void CSortedSet::IntersectWith(T &array[])
{
//--- check tree count
if(m_tree.Count()==0)
return;
//--- get array size
int size=ArraySize(array);
//--- create emty tree
CRedBlackTree<T>*tree=new CRedBlackTree<T>();
//--- store values conatin in tree and array
for(int i=0; i<size; i++)
if(m_tree.Contains(array[i]))
tree.Add(array[i]);
//--- overwrite tree
delete m_tree;
m_tree=tree;
}
//+------------------------------------------------------------------+
//| Modifies the current set to contain only elements that are |
//| present either in that set or in the specified collection, but |
//| not both. |
//+------------------------------------------------------------------+
template<typename T>
void CSortedSet::SymmetricExceptWith(ICollection<T>*collection)
{
//--- check collection
if(CheckPointer(collection)==POINTER_INVALID)
return;
//--- check collection count
if(collection.Count()==0)
return;
//--- check tree count
if(m_tree.Count()==0)
{
UnionWith(collection);
return;
}
//--- special case if collection is this
//--- a set minus itself is the empty set
if(collection==GetPointer(this))
{
Clear();
return;
}
//--- copy colleaction to array
T array[];
int size=collection.CopyTo(array);
//--- get comparer
IComparer<T>*comparer=m_tree.Comparer();
//--- sort array
Introsort<T,T>sort;
ArrayCopy(sort.keys,array);
sort.comparer=comparer;
sort.Sort(0, size);
ArrayCopy(array,sort.keys);
//--- modify tree
T last=array[0];
for(int i=0; i<size; i++)
{
while(i<size && i!=0 && comparer.Compare(array[i],last)==0)
i++;
if(i>=size)
break;
if(m_tree.Contains(array[i]))
m_tree.Remove(array[i]);
else
m_tree.Add(array[i]);
last=array[i];
}
}
//+------------------------------------------------------------------+
//| Modifies the current set to contain only elements that are |
//| present either in that set or in the specified array, but not |
//| both. |
//+------------------------------------------------------------------+
template<typename T>
void CSortedSet::SymmetricExceptWith(T &array[])
{
//--- check array size
if(ArraySize(array)==0)
return;
//--- check tree count
if(m_tree.Count()==0)
{
UnionWith(array);
return;
}
//--- get size
int size=ArraySize(array);
//--- get comparer
IComparer<T>*comparer=m_tree.Comparer();
//--- sort array
Introsort<T,T>sort;
ArrayCopy(sort.keys,array);
sort.comparer=comparer;
sort.Sort(0, size);
ArrayReverse(sort.keys,0,ArraySize(sort.keys));
//--- modify tree
T last=sort.keys[0];
for(int i=0; i<size; i++)
{
while(i<size && i!=0 && comparer.Compare(sort.keys[i],last)==0)
i++;
if(i>=size)
break;
if(m_tree.Contains(sort.keys[i]))
m_tree.Remove(sort.keys[i]);
else
m_tree.Add(sort.keys[i]);
last=sort.keys[i];
}
}
//+------------------------------------------------------------------+
//| Modifies the current set to contain all elements that are present|
//| in itself, the specified collection, or both. |
//+------------------------------------------------------------------+
template<typename T>
void CSortedSet::UnionWith(ICollection<T>*collection)
{
//--- check collection
if(CheckPointer(collection)==POINTER_INVALID)
return;
//--- copy all elements from collecton to array
T array[];
int size=collection.CopyTo(array);
//--- add all elemets from array to set
for(int i=0; i<size; i++)
m_tree.Add(array[i]);
}
//+------------------------------------------------------------------+
//| Modifies the current set to contain all elements that are present|
//| in itself, the specified array, or both. |
//+------------------------------------------------------------------+
template<typename T>
void CSortedSet::UnionWith(T &array[])
{
//--- get array size
int size=ArraySize(array);
//--- add all elemets from array to set
for(int i=0; i<size; i++)
m_tree.Add(array[i]);
}
//+------------------------------------------------------------------+
//| Determines whether a set is a proper subset of the specified |
//| collection. |
//+------------------------------------------------------------------+
template<typename T>
bool CSortedSet::IsProperSubsetOf(ICollection<T>*collection)
{
//--- check collection
if(CheckPointer(collection)==POINTER_INVALID)
return(false);
//--- check tree count
if(m_tree.Count()==0)
return(collection.Count() > 0);
//--- check collection is set
CHashSet<T>*ptr_set=dynamic_cast<CHashSet<T>*>(collection);
if(CheckPointer(ptr_set)!=POINTER_INVALID)
{
return(ptr_set.IsProperSupersetOf(m_tree));
}
else
{
//--- create a set based on a specified collection
CHashSet<T>set(collection);
return(set.IsProperSupersetOf(m_tree));
}
}
//+------------------------------------------------------------------+
//| Determines whether a set is a proper subset of the specified |
//| array. |
//+------------------------------------------------------------------+
template<typename T>
bool CSortedSet::IsProperSubsetOf(T &array[])
{
if(m_tree.Count()==0)
return(ArraySize(array) > 0);
//--- create a set based on a specified array
CHashSet<T>set(array);
if(m_tree.Count()>=set.Count())
return(false);
return(set.IsProperSupersetOf(m_tree));
}
//+------------------------------------------------------------------+
//| Determines whether a set is a proper superset of the specified |
//| collection. |
//+------------------------------------------------------------------+
template<typename T>
bool CSortedSet::IsProperSupersetOf(ICollection<T>*collection)
{
//--- check collection
if(CheckPointer(collection)==POINTER_INVALID)
return(m_tree.Count()>0);
//--- check tree count
if(m_tree.Count()==0)
return(false);
//--- check collection count
if(collection.Count()==0)
return(true);
//--- check collection is set
CHashSet<T>*ptr_set=dynamic_cast<CHashSet<T>*>(collection);
if(CheckPointer(ptr_set)!=POINTER_INVALID)
{
return(ptr_set.IsProperSubsetOf(m_tree));
}
else
{
//--- create a set based on a specified collection
CHashSet<T>set(collection);
return(set.IsProperSubsetOf(m_tree));
}
}
//+------------------------------------------------------------------+
//| Determines whether a set is a proper superset of the specified |
//| array. |
//+------------------------------------------------------------------+
template<typename T>
bool CSortedSet::IsProperSupersetOf(T &array[])
{
if(m_tree.Count()==0)
return(false);
if(ArraySize(array)==0)
return(true);
//--- create a set based on a specified array
CHashSet<T>set(array);
return(set.IsProperSubsetOf(m_tree));
}
//+------------------------------------------------------------------+
//| Determines whether a set is a subset of the specified collection.|
//+------------------------------------------------------------------+
template<typename T>
bool CSortedSet::IsSubsetOf(ICollection<T>*collection)
{
//--- cehck collection
if(CheckPointer(collection)==POINTER_INVALID)
return(m_tree.Count()==0);
//--- check tree count
if(m_tree.Count()==0)
return(true);
//--- check collection is set
CHashSet<T>*ptr_set=dynamic_cast<CHashSet<T>*>(collection);
if(CheckPointer(ptr_set)==POINTER_DYNAMIC)
{
return(ptr_set.IsProperSupersetOf(m_tree));
}
else
{
//--- create a set based on a specified collection
CHashSet<T>set(collection);
return(set.IsProperSupersetOf(m_tree));
}
}
//+------------------------------------------------------------------+
//| Determines whether a set is a subset of the specified array. |
//+------------------------------------------------------------------+
template<typename T>
bool CSortedSet::IsSubsetOf(T &array[])
{
//--- check tree count
if(m_tree.Count()==0)
return(true);
//--- create a set based on a specified array
CHashSet<T>set(array);
if(m_tree.Count()>set.Count())
return(false);
return(set.IsProperSupersetOf(m_tree));
}
//+------------------------------------------------------------------+
//| Determines whether a set is a superset of the specified |
//| collection. |
//+------------------------------------------------------------------+
template<typename T>
bool CSortedSet::IsSupersetOf(ICollection<T>*collection)
{
//--- check collection
if(CheckPointer(collection)==POINTER_INVALID)
return(m_tree.Count()>=0);
//--- check collection count
if(collection.Count()==0)
return(true);
//--- check collection is set
CHashSet<T>*ptr_set=dynamic_cast<CHashSet<T>*>(collection);
if(CheckPointer(ptr_set)!=POINTER_INVALID)
{
return(ptr_set.IsSupersetOf(m_tree));
}
else
{
//--- create a set based on a specified collection
CHashSet<T>set(collection);
return(set.IsSupersetOf(m_tree));
}
}
//+------------------------------------------------------------------+
//| Determines whether a set is a superset of the specified array. |
//+------------------------------------------------------------------+
template<typename T>
bool CSortedSet::IsSupersetOf(T &array[])
{
//--- check array size
if(ArraySize(array)==0)
return(true);
//--- create a set based on a specified array
CHashSet<T>set(array);
return(set.IsSupersetOf(m_tree));
}
//+------------------------------------------------------------------+
//| Determines whether the current set and a specified collection |
//| share common elements. |
//+------------------------------------------------------------------+
template<typename T>
bool CSortedSet::Overlaps(ICollection<T>*collection)
{
//--- check collection
if(CheckPointer(collection)==POINTER_INVALID)
return(false);
//--- check tree count
if(m_tree.Count()==0)
return(false);
//--- check collection count
if(collection.Count()==0)
return(false);
//--- check collection is set
CHashSet<T>*ptr_set=dynamic_cast<CHashSet<T>*>(collection);
if(CheckPointer(ptr_set)!=POINTER_INVALID)
{
return(ptr_set.Overlaps(m_tree));
}
else
{
//--- create a set based on a specified collection
CHashSet<T>set(collection);
return(set.Overlaps(m_tree));
}
}
//+------------------------------------------------------------------+
//| Determines whether the current set and a specified array share |
//| common elements. |
//+------------------------------------------------------------------+
template<typename T>
bool CSortedSet::Overlaps(T &array[])
{
//--- check tree count
if(m_tree.Count()==0)
return(false);
//--- check array size
if(ArraySize(array)==0)
return(false);
//--- convert array to set
CHashSet<T>set(array);
return(set.Overlaps(m_tree));
}
//+------------------------------------------------------------------+
//| Determines whether a set and the specified collection contain the|
//| same elements. |
//+------------------------------------------------------------------+
template<typename T>
bool CSortedSet::SetEquals(ICollection<T>*collection)
{
if(CheckPointer(collection)==POINTER_INVALID)
return(false);
//--- get array from collection
T array[];
collection.CopyTo(array);
//--- check current set is equal specified array
return SetEquals(array);
}
//+------------------------------------------------------------------+
//| Determines whether a set and the specified array contain the same|
//| elements. |
//+------------------------------------------------------------------+
template<typename T>
bool CSortedSet::SetEquals(T &array[])
{
//--- try find all elements in the tree
for(int i=0; i<ArraySize(array); i++)
if(!m_tree.Contains(array[i]))
return(false);
return(true);
}
//+------------------------------------------------------------------+
//| Copy a view of a subset in a CSortedSet<T> to array. |
//+------------------------------------------------------------------+
template<typename T>
bool CSortedSet::GetViewBetween(T &array[],T lower_value,T upper_value)
{
//--- get comparer
IComparer<T>*comparer=m_tree.Comparer();
if(comparer.Compare(lower_value,upper_value)>0)
return(false);
//--- copy all element from tree to array
T buff[];
int size=m_tree.CopyTo(buff);
//--- check range
if(size==0 || comparer.Compare(buff[0],upper_value)>0 || comparer.Compare(buff[size-1],lower_value)<0)
return(false);
//--- find first element greater than lower_value
int index_lower=0;
while(index_lower<size && comparer.Compare(buff[index_lower],lower_value)<0)
index_lower++;
//--- find first element less than upper_value
int index_upper=size-1;
while(index_upper>0 && comparer.Compare(buff[index_upper],upper_value)>0)
index_upper--;
//--- check indices
if(index_lower>index_upper)
return(false);
//--- copy view between lower_value and upper_value to array
return(ArrayCopy(array,buff,0,index_lower,index_upper-index_lower+1)>=0);
}
//+------------------------------------------------------------------+
//| Copy the CSortedSet<T> in reverse order to array. |
//+------------------------------------------------------------------+
template<typename T>
bool CSortedSet::GetReverse(T &array[])
{
int size=m_tree.CopyTo(array);
return ArrayReverse(array,0,size);
}
//+------------------------------------------------------------------+
+227
View File
@@ -0,0 +1,227 @@
//+------------------------------------------------------------------+
//| Stack.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Generic\Interfaces\ICollection.mqh>
#include <Generic\Internal\ArrayFunction.mqh>
#include <Generic\Internal\EqualFunction.mqh>
//+------------------------------------------------------------------+
//| Class CStack<T>. |
//| Usage: Represents a variable size last-in-first-out (LIFO) |
//| collection of instances of the same specified type. |
//+------------------------------------------------------------------+
template<typename T>
class CStack: public ICollection<T>
{
protected:
T m_array[];
int m_size;
const int m_default_capacity;
public:
CStack(void);
CStack(const int capacity);
CStack(ICollection<T>&collection[]);
CStack(T &array[]);
~CStack(void);
//--- methods of filling data
bool Add(T value);
bool Push(T value);
//--- methods of access to protected data
int Count(void);
bool Contains(T item);
void TrimExcess(void);
//--- methods of copy data from collection
int CopyTo(T &dst_array[],const int dst_start=0);
//--- methods of cleaning and removing
void Clear(void);
bool Remove(T item);
//--- methods of access to protected data
T Peek(void);
T Pop(void);
};
//+------------------------------------------------------------------+
//| Initializes a new instance of the CStack<T> class that is empty |
//| and has the default initial capacity. |
//+------------------------------------------------------------------+
template<typename T>
CStack::CStack(void): m_default_capacity(4),
m_size(0)
{
}
//+------------------------------------------------------------------+
//| Initializes a new instance of the CStack<T> class that is empty |
//| and has the specified initial capacity or the default initial |
//| capacity, whichever is greater. |
//+------------------------------------------------------------------+
template<typename T>
CStack::CStack(const int capacity): m_default_capacity(4),
m_size(0)
{
ArrayResize(m_array,capacity);
}
//+------------------------------------------------------------------+
//| Initializes a new instance of the CStack<T> class that contains |
//| elements copied from the specified array and has sufficient |
//| capacity to accommodate the number of elements copied. |
//+------------------------------------------------------------------+
template<typename T>
CStack::CStack(T &array[]): m_default_capacity(4),
m_size(0)
{
m_size=ArrayCopy(m_array,array);
}
//+------------------------------------------------------------------+
//| Initializes a new instance of the CStack<T> class that contains |
//| elements copied from the specified collection and has sufficient |
//| capacity to accommodate the number of elements copied. |
//+------------------------------------------------------------------+
template<typename T>
CStack::CStack(ICollection<T>*collection): m_default_capacity(4),
m_size(0)
{
//--- check collection
if(CheckPointer(collection)!=POINTER_INVALID)
m_size=collection.CopyTo(m_array,0);
}
//+------------------------------------------------------------------+
//| Destructor. |
//+------------------------------------------------------------------+
template<typename T>
CStack::~CStack(void)
{
}
//+------------------------------------------------------------------+
//| Inserts an value at the top of the CStack<T>. |
//+------------------------------------------------------------------+
template<typename T>
bool CStack::Add(T value)
{
return Push(value);
}
//+------------------------------------------------------------------+
//| Gets the number of elements. |
//+------------------------------------------------------------------+
template<typename T>
int CStack::Count(void)
{
return(m_size);
}
//+------------------------------------------------------------------+
//| Removes all values from the CStack<T>. |
//+------------------------------------------------------------------+
template<typename T>
bool CStack::Contains(T item)
{
int count=m_size;
//--- try to find item in array
while(count-->0)
{
//--- use default equality function
if(::Equals(m_array[count],item))
return(true);
}
return(false);
}
//+------------------------------------------------------------------+
//| Copies a range of elements from the stack to a compatible |
//| one-dimensional array. |
//+------------------------------------------------------------------+
template<typename T>
int CStack::CopyTo(T &dst_array[],const int dst_start=0)
{
//--- resize array
if(dst_start+m_size>ArraySize(dst_array))
ArrayResize(dst_array,dst_start+m_size);
//--- start copy
int src_index = m_size-1;
int dst_index = dst_start;
while(src_index>=0 && dst_index<ArraySize(dst_array))
dst_array[dst_index++]=m_array[src_index--];
return(dst_index-dst_start);
}
//+------------------------------------------------------------------+
//| Removes all values from the CStack<T>. |
//+------------------------------------------------------------------+
template<typename T>
void CStack::Clear(void)
{
//--- check current size
if(m_size>0)
{
ZeroMemory(m_array);
m_size=0;
}
}
//+------------------------------------------------------------------+
//| Removes the first occurrence of a specific value from the stack. |
//+------------------------------------------------------------------+
template<typename T>
bool CStack::Remove(T item)
{
//--- find index of item
int index=ArrayIndexOf(m_array,item,0,m_size);
//--- check index
if(index==-1)
return(false);
//--- shift the values to the left
ArrayCopy(m_array,m_array,index,index+1);
//--- decrement size
m_size--;
return(true);
}
//+------------------------------------------------------------------+
//| Inserts an values at the top of the CStack<T>. |
//+------------------------------------------------------------------+
template<typename T>
bool CStack::Push(T value)
{
int size=ArraySize(m_array);
//--- check array size
if(m_size==size)
{
//--- increase capacity
if(size==0)
ArrayResize(m_array,m_default_capacity);
else
ArrayResize(m_array,2*size);
}
//--- add value to the end
m_array[m_size++]=value;
return(true);
}
//+------------------------------------------------------------------+
//| Returns the value at the top of the CStack<T> without removing. |
//+------------------------------------------------------------------+
template<typename T>
T CStack::Peek(void)
{
//--- return last value
return(m_array[m_size-1]);
}
//+------------------------------------------------------------------+
//| Removes and returns the value at the top of the CStack<T>. |
//+------------------------------------------------------------------+
template<typename T>
T CStack::Pop(void)
{
//--- return last value and decrement size
T item=m_array[--m_size];
return(item);
}
//+------------------------------------------------------------------+
//| Sets the capacity to the actual number of elements in the |
//| CStack<T>, if that number is less than 90 percent of current |
//| capacity. |
//+------------------------------------------------------------------+
template<typename T>
void CStack::TrimExcess(void)
{
//--- calculate threshold value
int threshold=(int)(((double)ArraySize(m_array)*0.9));
//--- calculate resize array
if(m_size<threshold)
ArrayResize(m_array,m_size);
}
//+------------------------------------------------------------------+
Binary file not shown.
@@ -0,0 +1,201 @@
#include "String.mqh"
//+------------------------------------------------------------------+
//| Структура для статистики торговли |
//+------------------------------------------------------------------+
struct ExpTradeSummarySingle
{
public:
int Offset1[10];
int bars;
int ticks;
STRING32 symbol;
double initial_deposit; // начальный депозит
double withdrawal; // снято средств
double profit; // общая прибыль (+)
double grossprofit; // общий плюс
double grossloss; // общий минус
double maxprofit; // максимально прибыльная сделка
double minprofit; // максимально убыточная сделка
double conprofitmax; // прибыль максимальной последовательности прибыльных сделок
double maxconprofit; // максимальная прибыль среди последовательностей
double conlossmax; // убыток максимальной последовательности убыточных сделок
double maxconloss; // максимальный убыток среди последовательностей
double balance_min; // минимальное значение баланса (для расчёта абсолютной просадки)
double maxdrawdown; // максимальная просадка по балансу
double drawdownpercent; // отношение максимальной просадки по балансу к её пику
double reldrawdown; // максимальная относительная просадка по балансу в деньгах
double reldrawdownpercent; // максимальная относительная просадка по балансу в процентах
double equity_min; // минимальное значение equity (для расчёта абсолютной просадки по equity)
double maxdrawdown_e; // максимальная просадка по equity
double drawdownpercent_e; // отношение максимальной просадки по equity к её пику (+)
double reldrawdown_e; // максимальная относительная просадка по equity в деньгах
double reldrawdownpercnt_e; // максимальная относительная просадка по equity в процентах
double expected_payoff; // матожидание выигрыша (+)
double profit_factor; // показатель прибыльности (+)
double recovery_factor; // фактор восстановления (+)
double sharpe_ratio; // коэффициент Шарпа (+)
double margin_level; // минимальный уровень маржи
double custom_fitness; // пользовательский фитнесс - результат OnTester (+)
int deals; // общее количество сделок
int trades; // количество сделок out/inout
int profittrades; // количество прибыльных
int losstrades; // количество убыточных
int shorttrades; // количество шортов
int longtrades; // количество лонгов
int winshorttrades; // количество прибыльных шортов
int winlongtrades; // количество прибыльных лонгов
int conprofitmax_trades; // максимальная последовательность прибыльных сделок
int maxconprofit_trades; // последовательность максимальной прибыли
int conlossmax_trades; // максимальная последовательность убыточных сделок
int maxconloss_trades; // последовательность максимального убытка
int avgconwinners; // среднее количество последовательных прибыльных сделок
int avgconloosers; // среднее количество последовательных убыточных сделок
#define TOSTRING(A) #A + " = " + (string)(A) + "\n"
#define TOSTRING3(A) #A + " = " + this.A[] + "\n"
string ToString( void ) const
{
return(
TOSTRING(bars) +
TOSTRING(ticks) +
TOSTRING3(symbol) +
TOSTRING(initial_deposit) + // начальный депозит
TOSTRING(withdrawal) + // снято средств
TOSTRING(profit) + // общая прибыль (+)
TOSTRING(grossprofit) + // общий плюс
TOSTRING(grossloss) + // общий минус
TOSTRING(maxprofit) + // максимально прибыльная сделка
TOSTRING(minprofit) + // максимально убыточная сделка
TOSTRING(conprofitmax) + // прибыль максимальной последовательности прибыльных сделок
TOSTRING(maxconprofit) + // максимальная прибыль среди последовательностей
TOSTRING(conlossmax) + // убыток максимальной последовательности убыточных сделок
TOSTRING(maxconloss) + // максимальный убыток среди последовательностей
TOSTRING(balance_min) + // минимальное значение баланса (для расчёта абсолютной просадки)
TOSTRING(maxdrawdown) + // максимальная просадка по балансу
TOSTRING(drawdownpercent) + // отношение максимальной просадки по балансу к её пику
TOSTRING(reldrawdown) + // максимальная относительная просадка по балансу в деньгах
TOSTRING(reldrawdownpercent) + // максимальная относительная просадка по балансу в процентах
TOSTRING(equity_min) + // минимальное значение equity (для расчёта абсолютной просадки по equity)
TOSTRING(maxdrawdown_e) + // максимальная просадка по equity
TOSTRING(drawdownpercent_e) + // отношение максимальной просадки по equity к её пику (+)
TOSTRING(reldrawdown_e) + // максимальная относительная просадка по equity в деньгах
TOSTRING(reldrawdownpercnt_e) + // максимальная относительная просадка по equity в процентах
TOSTRING(expected_payoff) + // матожидание выигрыша (+)
TOSTRING(profit_factor) + // показатель прибыльности (+)
TOSTRING(recovery_factor) + // фактор восстановления (+)
TOSTRING(sharpe_ratio) + // коэффициент Шарпа (+)
TOSTRING(margin_level) + // минимальный уровень маржи
TOSTRING(custom_fitness) + // пользовательский фитнесс - результат OnTester (+)
TOSTRING(deals) + // общее количество сделок
TOSTRING(trades) + // количество сделок out/inout
TOSTRING(profittrades) + // количество прибыльных
TOSTRING(losstrades) + // количество убыточных
TOSTRING(shorttrades) + // количество шортов
TOSTRING(longtrades) + // количество лонгов
TOSTRING(winshorttrades) + // количество прибыльных шортов
TOSTRING(winlongtrades) + // количество прибыльных лонгов
TOSTRING(conprofitmax_trades) + // максимальная последовательность прибыльных сделок
TOSTRING(maxconprofit_trades) + // последовательность максимальной прибыли
TOSTRING(conlossmax_trades) + // максимальная последовательность убыточных сделок
TOSTRING(maxconloss_trades) + // последовательность максимального убытка
TOSTRING(avgconwinners) + // среднее количество последовательных прибыльных сделок
TOSTRING(avgconloosers) // среднее количество последовательных убыточных сделок
);
}
#undef TOSTRING3
#undef TOSTRING
double TesterStatistics( const ENUM_STATISTICS Statistic_ID ) const
{
switch (Statistic_ID)
{
case STAT_INITIAL_DEPOSIT:
return(this.initial_deposit);
case STAT_WITHDRAWAL:
return(this.withdrawal);
case STAT_PROFIT:
return(this.profit);
case STAT_GROSS_PROFIT:
return(this.grossprofit);
case STAT_GROSS_LOSS:
return(-this.grossloss);
case STAT_MAX_PROFITTRADE:
return(this.maxprofit);
case STAT_MAX_LOSSTRADE:
return(-this.minprofit);
case STAT_CONPROFITMAX:
return(this.maxconprofit);
case STAT_CONPROFITMAX_TRADES:
return(this.maxconprofit_trades);
case STAT_MAX_CONWINS:
return(this.conprofitmax);
case STAT_MAX_CONPROFIT_TRADES:
return(this.conprofitmax_trades);
case STAT_CONLOSSMAX:
return(-this.conlossmax);
case STAT_CONLOSSMAX_TRADES:
return(this.conlossmax_trades);
case STAT_MAX_CONLOSSES:
return(-this.maxconloss);
case STAT_MAX_CONLOSS_TRADES:
return(this.maxconloss_trades);
case STAT_BALANCEMIN:
return(this.balance_min);
case STAT_BALANCE_DD:
return(this.maxdrawdown);
case STAT_BALANCEDD_PERCENT:
return(this.drawdownpercent);
case STAT_BALANCE_DDREL_PERCENT:
return(this.reldrawdownpercent);
case STAT_BALANCE_DD_RELATIVE:
return(this.reldrawdown);
case STAT_EQUITYMIN:
return(this.equity_min);
case STAT_EQUITY_DD:
return(this.maxdrawdown_e);
case STAT_EQUITYDD_PERCENT:
return(this.drawdownpercent_e);
case STAT_EQUITY_DDREL_PERCENT:
return(this.reldrawdownpercnt_e);
case STAT_EQUITY_DD_RELATIVE:
return(this.reldrawdown_e);
case STAT_EXPECTED_PAYOFF:
return(this.expected_payoff);
case STAT_PROFIT_FACTOR:
return(this.profit_factor);
case STAT_RECOVERY_FACTOR:
return(this.recovery_factor);
case STAT_SHARPE_RATIO:
return(this.sharpe_ratio);
case STAT_MIN_MARGINLEVEL:
return(this.margin_level);
case STAT_CUSTOM_ONTESTER:
return(this.custom_fitness);
case STAT_DEALS:
return(this.deals);
case STAT_TRADES:
return(this.trades);
case STAT_PROFIT_TRADES:
return(this.profittrades);
case STAT_LOSS_TRADES:
return(this.losstrades);
case STAT_SHORT_TRADES:
return(this.shorttrades);
case STAT_LONG_TRADES:
return(this.longtrades);
case STAT_PROFIT_SHORTTRADES:
return(this.winshorttrades);
case STAT_PROFIT_LONGTRADES:
return(this.winlongtrades);
case STAT_PROFITTRADES_AVGCON:
return(this.avgconwinners);
case STAT_LOSSTRADES_AVGCON:
return(this.avgconloosers);
}
return(0);
}
};
Binary file not shown.
Binary file not shown.
+50
View File
@@ -0,0 +1,50 @@
#ifndef __STRING__
#define __STRING__
#define NULL_CHAR (short)0xFFFF
#define DEFINE_STRING(A) \
struct STRING##A \
{ \
public : \
short Array[A]; \
\
public: \
void operator =( const string &Str ) \
{ \
::ArrayInitialize(Array, 0); \
this.Array[0] = NULL_CHAR; \
::StringToShortArray(Str, this.Array); \
\
return; \
} \
\
template <typename T> \
void operator =( const T &Str ) \
{ \
const string StrTmp = Str[]; \
this = StrTmp; \
\
return; \
} \
\
string operator []( const int = 0 ) const \
{ \
return((this.Array[0] == NULL_CHAR) \
? NULL : \
::ShortArrayToString(this.Array)); \
} \
};
DEFINE_STRING(16)
DEFINE_STRING(32)
DEFINE_STRING(64)
DEFINE_STRING(128)
DEFINE_STRING(80)
#undef DEFINE_STRING
#undef NULL_CHAR
#endif // __STRING__
@@ -0,0 +1,44 @@
#define UINT64 ulong
#define INT64 datetime
//+------------------------------------------------------------------+
//| Ñòðóêòóðà ðåçóëüòàòîâ äëÿ ïîçèöèè |
//+------------------------------------------------------------------+
struct TesterPositionProfit
{
private:
string LengthToString( const datetime Length ) const
{
const int Days = (int)(Length / (24 * 3600));
return(((Days) ? (string)Days + "d ": "") + ::TimeToString(Length, TIME_SECONDS));
}
public:
UINT64 id; // id ïîçèöèè
double mfe; // MFE
double mae; // MAE
double profit; // ïðèáûëü
INT64 lifetime; // âðåìÿ æèçíè ïîçèöèè â ñåêóíäàõ
UINT64 reserve[3];
#define TOSTRING(A) #A + " = " + (string)(this.A) + "\n"
#define TOSTRING2(A) #A + " = " + this.LengthToString(A) + "\n"
string ToString( void ) const
{
return(
TOSTRING(id) + // id ïîçèöèè
TOSTRING(mfe) + // MFE
TOSTRING(mae) + // MAE
TOSTRING(profit) + // ïðèáûëü
TOSTRING2(lifetime) // âðåìÿ æèçíè ïîçèöèè â ñåêóíäàõ
);
}
#undef TOSTRING2
#undef TOSTRING
};
#undef INT64
#undef UINT64
@@ -0,0 +1,29 @@
#define __int64 datetime
//+------------------------------------------------------------------+
//| Ñòðóêòóðà äëÿ ãðàôèêà òåñòèðîâàíèÿ |
//+------------------------------------------------------------------+
struct TesterTradeState
{
// __int64 datetime; // òåêóùåå òåñòîâîå âðåìÿ
__int64 time; // òåêóùåå òåñòîâîå âðåìÿ
double balance; // òåêóùèé áàëàíñ
double equity; // òåêóùèé equity
double value; // òåêóùåå ðàññ÷èòàííîå çíà÷åíèå íàãðóçêè íà äåïîçèò
#define TOSTRING(A) #A + " = " + (string)(this.A) + "\n"
string ToString( void ) const
{
return(
TOSTRING(time) + // òåêóùåå òåñòîâîå âðåìÿ
TOSTRING(balance) + // òåêóùèé áàëàíñ
TOSTRING(equity) + // òåêóùèé equity
TOSTRING(value) // òåêóùåå ðàññ÷èòàííîå çíà÷åíèå íàãðóçêè íà äåïîçèò
);
}
#undef TOSTRING
};
#undef __int64
Binary file not shown.
+237
View File
@@ -0,0 +1,237 @@
#include "String.mqh"
#define UINT64 ulong
#define INT64 datetime
#define UINT uint
//+------------------------------------------------------------------+
//| Ñòðóêòóðà òîðãîâîãî îðäåðà |
//+------------------------------------------------------------------+
struct TradeOrder
{
private:
ENUM_ORDER_REASON ReasonToInteger( const ENUM_ORDER_REASON Reason ) const
{
int Res = 1;
switch (Reason)
{
case ORDER_REASON_SL:
Res = 3;
break;
case ORDER_REASON_TP:
Res = 4;
break;
}
return((ENUM_ORDER_REASON)Res);
}
ENUM_ORDER_REASON IntegerToReason( const int Reason ) const
{
ENUM_ORDER_REASON Res = ORDER_REASON_CLIENT;
switch (Reason)
{
case 3:
Res = ORDER_REASON_SL;
break;
case 4:
Res = ORDER_REASON_TP;
break;
}
return((ENUM_ORDER_REASON)Res);
}
public:
UINT64 order; // óíèêàëüíûé èäåíòèôèêàòîð îðäåðà
// wchar_t symbol[32]; // ñèìâîë ïî êîòîðîìó âûñòàâëåí îðäåð
STRING32 symbol; // ñèìâîë ïî êîòîðîìó âûñòàâëåí îðäåð
INT64 time_setup; // âðåìÿ ïðè¸ìà îðäåðà îò êëèåíòà â ñèñòåìó
INT64 time_done; // âðåìÿ ñíÿòèÿ çàâêè
ENUM_ORDER_TYPE type; // òèï îðäåðà
ENUM_ORDER_REASON type_reason; // ïðè÷èíà ôîðìèðîâàíèÿ îðäåðà
double price_order; // öåíà îðäåðà
double price_trigger; // öåíà èñïîëíåíèÿ îðäåðà
double price_sl; // öåíà SL â îðäåðå
double price_tp; // öåíà TP â îðäåðå
UINT64 volume_initial; // íà÷àëüíûé îáú¸ì çàÿâêè
UINT64 volume_current; // òåêóùèé îáú¸ì çàÿâêè
// wchar_t comment[32]; // êîììåíòàðèé ê îðäåðó
STRING32 comment; // êîììåíòàðèé ê îðäåðó
ENUM_ORDER_STATE state; // òåêóùåå ñîñòîÿíèå îðäåðà
UINT digits; // êîëè÷åñòâî çíàêîâ ó òîðãîâîãî ñèìâîëà
double contract_size; // ðàçìåð êîíòðàêòà
bool Set( const ulong Ticket )
{
const bool Res = (::HistoryOrderGetInteger(Ticket, ORDER_TICKET) == Ticket);
if (Res)
{
this.order = Ticket; // óíèêàëüíûé èäåíòèôèêàòîð îðäåðà
string Str = ::HistoryOrderGetString(Ticket, ORDER_SYMBOL);
this.symbol = Str; // ñèìâîë ïî êîòîðîìó âûñòàâëåí îðäåð
this.contract_size = ::SymbolInfoDouble(Str, SYMBOL_TRADE_CONTRACT_SIZE); // ðàçìåð êîíòðàêòà
this.digits = (UINT)::SymbolInfoInteger(Str, SYMBOL_DIGITS); // êîëè÷åñòâî çíàêîâ ó òîðãîâîãî ñèìâîëà
Str = ::HistoryOrderGetString(Ticket, ORDER_COMMENT);
this.comment = Str; // êîììåíòàðèé ê îðäåðó
this.time_setup = (INT64)::HistoryOrderGetInteger(Ticket, ORDER_TIME_SETUP); // âðåìÿ ïðè¸ìà îðäåðà îò êëèåíòà â ñèñòåìó
this.time_done = (INT64)::HistoryOrderGetInteger(Ticket, ORDER_TIME_DONE); // âðåìÿ ñíÿòèÿ çàâêè
this.type = (ENUM_ORDER_TYPE)::HistoryOrderGetInteger(Ticket, ORDER_TYPE); // òèï îðäåðà
this.type_reason = this.ReasonToInteger((ENUM_ORDER_REASON)::HistoryOrderGetInteger(Ticket, ORDER_REASON)); // ïðè÷èíà ôîðìèðîâàíèÿ îðäåðà
this.state = (ENUM_ORDER_STATE)::HistoryOrderGetInteger(Ticket, ORDER_STATE); // òåêóùåå ñîñòîÿíèå îðäåðà
this.price_order = ::HistoryOrderGetDouble(Ticket, ORDER_PRICE_OPEN); // öåíà îðäåðà
this.price_trigger = 0; // öåíà èñïîëíåíèÿ îðäåðà
this.price_sl = ::HistoryOrderGetDouble(Ticket, ORDER_SL); // öåíà SL â îðäåðå
this.price_tp = ::HistoryOrderGetDouble(Ticket, ORDER_TP); // öåíà TP â îðäåðå
this.volume_initial = (UINT64)(::HistoryOrderGetDouble(Ticket, ORDER_VOLUME_INITIAL) * this.contract_size * 1000 + 0.1); // íà÷àëüíûé îáú¸ì çàÿâêè
this.volume_current = (UINT64)(::HistoryOrderGetDouble(Ticket, ORDER_VOLUME_CURRENT) * this.contract_size * 1000 + 0.1); // òåêóùèé îáú¸ì çàÿâêè
}
return(Res);
}
long GetProperty( const ENUM_ORDER_PROPERTY_INTEGER Property ) const
{
long Res = 0;
switch (Property)
{
case ORDER_TICKET:
Res = (long)this.order;
break;
case ORDER_TIME_SETUP:
Res = this.time_setup;
break;
case ORDER_TYPE:
Res = this.type;
break;
case ORDER_STATE:
Res = this.state;
break;
case ORDER_TIME_DONE:
Res = this.time_done;
break;
case ORDER_TIME_SETUP_MSC:
Res = (long)this.time_setup * 1000;
break;
case ORDER_TIME_DONE_MSC:
Res = (long)this.time_done * 1000;
break;
case ORDER_REASON:
Res = this.IntegerToReason(this.type_reason);
break;
case ORDER_POSITION_ID:
Res = (long)this.order;
break;
}
return(Res);
}
double GetProperty( const ENUM_ORDER_PROPERTY_DOUBLE Property ) const
{
double Res = 0;
switch (Property)
{
case ORDER_VOLUME_INITIAL:
Res = (double)this.volume_initial / (this.contract_size ? this.contract_size * 1000 : 1e8);
break;
case ORDER_VOLUME_CURRENT:
Res = (double)this.volume_current / (this.contract_size ? this.contract_size * 1000 : 1e8);
break;
case ORDER_PRICE_OPEN:
Res = this.price_order;
break;
case ORDER_SL:
Res = this.price_sl;
break;
case ORDER_TP:
Res = this.price_tp;
break;
}
return(Res);
}
string GetProperty( const ENUM_ORDER_PROPERTY_STRING Property ) const
{
string Res = NULL;
switch (Property)
{
case ORDER_SYMBOL:
Res = this.symbol[];
break;
case ORDER_COMMENT:
Res = this.comment[];
break;
}
return(Res);
}
#define TOSTRING(A) #A + " = " + (string)(this.A) + "\n"
#define TOSTRING2(A) #A + " = " + ::EnumToString(this.A) + " (" + (string)(this.A) + ")\n"
#define TOSTRING3(A) #A + " = " + this.A[] + "\n"
string ToString( void ) const
{
return(
TOSTRING(order) + // óíèêàëüíûé èäåíòèôèêàòîð îðäåðà
TOSTRING3(symbol) + // ñèìâîë ïî êîòîðîìó âûñòàâëåí îðäåð
TOSTRING(time_setup) + // âðåìÿ ïðè¸ìà îðäåðà îò êëèåíòà â ñèñòåìó
TOSTRING(time_done) + // âðåìÿ ñíÿòèÿ çàâêè
TOSTRING2(type) + // òèï îðäåðà
TOSTRING2(type_reason) + // ïðè÷èíà ôîðìèðîâàíèÿ îðäåðà
TOSTRING(price_order) + // öåíà îðäåðà
TOSTRING(price_trigger) + // öåíà èñïîëíåíèÿ îðäåðà
TOSTRING(price_sl) + // öåíà SL â îðäåðå
TOSTRING(price_tp) + // öåíà TP â îðäåðå
TOSTRING(volume_initial) + // íà÷àëüíûé îáú¸ì çàÿâêè
TOSTRING(volume_current) + // òåêóùèé îáú¸ì çàÿâêè
TOSTRING3(comment) + // êîììåíòàðèé ê îðäåðó
TOSTRING2(state) + // òåêóùåå ñîñòîÿíèå îðäåðà
TOSTRING(digits) + // êîëè÷åñòâî çíàêîâ ó òîðãîâîãî ñèìâîëà
TOSTRING(contract_size) // ðàçìåð êîíòðàêòà
);
}
#undef TOSTRING3
#undef TOSTRING2
#undef TOSTRING
};
#undef UINT
#undef INT64
#undef UINT64
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.