DevSolve_DS_SDK_UnitTest/Strategies/MACDStrategy.mqh

464 lines
38 KiB
MQL5
Raw Permalink Normal View History

2025-05-30 14:49:27 +02:00
<EFBFBD><EFBFBD>//+------------------------------------------------------------------+
//| MACDStrategy.mqh |
//| Copyrigth - Dev Solve LTDA |
//+------------------------------------------------------------------+
#include "..\ExpertStrategy.mqh"
#include <Math\Stat\Normal.mqh>
#resource "\\Indicators\\Examples\\Custom_MACD.ex5"
//+------------------------------------------------------------------+
//| Class CMACDStrategy. |
//| Purpose: Class of strategy based on MACD signals strategy. |
//| The ATR indicator is filter usage in strategy. |
//| Derives from class CExpertStrategy. |
//+------------------------------------------------------------------+
class CMACDStrategy : public CExpertStrategy
{
private:
//--- fields of the strategy
MqlRates m_rates[];
int m_macd_handle;
double m_MACD_MAIN[];
double m_MACD_SIGNAL[];
double m_MACD_EMA_FAST[];
double m_MACD_EMA_SLOW[];
double m_MACD_STDDEV_UP[];
double m_MACD_STDDEV_DOWN[];
ENUM_TIMEFRAMES m_macd_timeframe;
int m_macd_fast_ema_period;
int m_macd_slow_ema_period;
int m_macd_signal_period;
ENUM_APPLIED_PRICE m_macd_applied_price;
ENUM_TIMEFRAMES m_atr_timeframe;
int m_atr_period;
double m_atr_multiplier;
int m_atr_candle_counter;
int m_atr_counter;
int m_atr_handle;
double m_ATR[];
ENUM_MACD_TYPE_ENTRY M_MACD_TYPE_ENTRY;
int m_macd_stddev_period;
double m_macd_stddev_multiplier;
int m_ema_fast_handle;
int m_ema_slow_handle;
double m_MACD_EMA_FAST_PLOT[];
double m_MACD_EMA_SLOW_PLOT[];
public:
CMACDStrategy();
~CMACDStrategy();
//--- setter of the direction strategy
void SetDirection(ENUM_TYPE_DIRECTION value) { m_direction=value; }
//--- setters of the fields
void Set_m_macd_timeframe(ENUM_TIMEFRAMES value) {m_macd_timeframe = value;};
void Set_m_macd_fast_ema_period(int value) {m_macd_fast_ema_period = value;};
void Set_m_macd_slow_ema_period(int value) {m_macd_slow_ema_period = value;};
void Set_m_macd_signal_period(int value) {m_macd_signal_period = value;};
void Set_m_macd_applied_price(ENUM_APPLIED_PRICE value) {m_macd_applied_price = value;};
//---
void Set_m_atr_timeframe(ENUM_TIMEFRAMES value) {m_atr_timeframe = value;};
void Set_m_atr_period(int value) {m_atr_period = value;};
void Set_m_atr_multiplier(double value) {m_atr_multiplier = value;};
void Set_m_atr_candle_counter(int value) {m_atr_candle_counter = value;};
//---
void Set_m_macd_stddev_period(int value) {m_macd_stddev_period = value;};
void Set_m_macd_stddev_multiplier(double value) {m_macd_stddev_multiplier = value;};
void Set_m_macd_stddev_timeframe(ENUM_TIMEFRAMES value) {m_macd_stddev_period = value;};
//---
void Set_M_MACD_TYPE_ENTRY(ENUM_MACD_TYPE_ENTRY value) {M_MACD_TYPE_ENTRY = value;};
//--- validation input data
virtual bool ValidationSettings(void);
virtual bool InitIndicators(CIndicators *indicators);
//--- methods of the current strategy
virtual bool CheckOpenLong(double &price, double &sl, double &tp, datetime &expiration);
virtual bool CheckOpenShort(double &price, double &sl, double &tp, datetime &expiration);
virtual bool CheckTralilingOrder(COrderInfo *order, double &price, datetime &expiration);
protected:
bool CheckPriceWithDirection(ENUM_TYPE_DIRECTION direction,ENUM_POSITION_TYPE type,double &price,double &sl,double &tp,datetime &expiration);
bool CheckPriceTrendDirection(ENUM_POSITION_TYPE type,double &price,double &sl,double &tp,datetime &expiration);
bool CheckPriceCounterTrendDirection(ENUM_POSITION_TYPE type,double &price,double &sl,double &tp,datetime &expiration);
bool CheckPriceMax(double &price,double &sl,double &tp,datetime &expiration);
bool CheckPriceMin(double &price,double &sl,double &tp,datetime &expiration);
bool Refresh(void);
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CMACDStrategy::CMACDStrategy(): m_macd_handle(-1),
m_macd_fast_ema_period(-1),
m_macd_slow_ema_period(-1),
m_macd_signal_period(-1),
m_atr_period(-1),
m_macd_stddev_period(-1),
m_macd_stddev_multiplier(-1),
m_atr_counter(0)
{
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CMACDStrategy::~CMACDStrategy()
{
IndicatorRelease(m_atr_handle);
IndicatorRelease(m_macd_handle);
}
//+------------------------------------------------------------------+
//| Validation Settings |
//+------------------------------------------------------------------+
bool CMACDStrategy::ValidationSettings(void)
{
if(!CEngineBase::ValidationSettings())
return(false);
//--- chek all inputs param
if(m_macd_fast_ema_period <=0)
{
printf("Erro: par<00>metro escolhido para o [Per<00>odo da M<00>dia R<00>pida do MACD] de [MACD Strategy] <00> inv<00>lido.");
return(false);
}
if(m_macd_slow_ema_period<=0)
{
printf("Erro: par<00>metro escolhido para o [Per<00>odo da M<00>dia Longa do MACD] de [MACD Strategy] <00> inv<00>lido.");
return(false);
}
if(m_macd_signal_period<=0)
{
printf("Erro: par<00>metro escolhido para o [Per<00>odo do Sinal do MACD] de [MACD Strategy] <00> inv<00>lido.");
return(false);
}
if(m_atr_period<=0)
{
printf("Erro: par<00>metro escolhido para o [Per<00>odo do ATR] de [MACD Strategy] <00> inv<00>lido.");
return(false);
}
if(m_atr_multiplier<=0)
{
printf("Erro: par<00>metro escolhido para o [Multiplicador do ATR] de [MACD Strategy] <00> inv<00>lido.");
return(false);
}
//---
if(m_macd_timeframe==PERIOD_CURRENT)
m_macd_timeframe=m_period;
//---
if(m_atr_timeframe==PERIOD_CURRENT)
m_atr_timeframe=m_period;
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Init Indicators |
//+------------------------------------------------------------------+
bool CMACDStrategy::InitIndicators(CIndicators *indicators)
{
//---
ArrayResize(m_MACD_MAIN, m_macd_stddev_period+2);
ArrayResize(m_MACD_SIGNAL, m_macd_stddev_period+2);
ArraySetAsSeries(m_MACD_MAIN, true);
ArraySetAsSeries(m_MACD_SIGNAL, true);
if (m_macd_stddev_period < 2) {
ArrayResize(m_MACD_MAIN, 3);
ArrayResize(m_MACD_SIGNAL, 3);
}
ArrayResize(m_ATR,m_atr_period+3);
ArraySetAsSeries(m_ATR, true);
//--- init MACD
//m_macd_handle=iCustom(m_other_ticker,m_macd_timeframe,"::Indicators\\Examples\\MACD.ex5",m_macd_fast_ema_period,m_macd_slow_ema_period,m_macd_signal_period,m_macd_applied_price);
m_macd_handle=iCustom(m_other_ticker,m_macd_timeframe,"::Indicators\\Examples\\Custom_MACD.ex5",m_macd_fast_ema_period,m_macd_slow_ema_period,m_macd_signal_period,m_macd_applied_price,m_macd_stddev_period,m_macd_stddev_multiplier);
//--- check
ResetLastError();
if(m_macd_handle==INVALID_HANDLE)
{
SetUserError(ERR_INVALID_HANDLE);
printf("Erro ao carregar MACD - error: %d",GetLastError());
return(false);
}
//--- add to chart
ChartIndicatorAdd(0,0,m_macd_handle);
//--- init atr
m_atr_handle=iATR(m_other_ticker,m_atr_timeframe,m_atr_period);
//--- check
ResetLastError();
if(m_atr_handle==INVALID_HANDLE)
{
SetUserError(ERR_INVALID_HANDLE);
printf("Erro ao carregar M<00>dia Lenta - error: %d",GetLastError());
return(false);
}
//--- add to chart
ChartIndicatorAdd(0,0,m_atr_handle);
//--- init moving averages
m_ema_fast_handle=iMA(m_other_ticker,m_macd_timeframe,m_macd_fast_ema_period,0,MODE_EMA,PRICE_CLOSE);
m_ema_slow_handle=iMA(m_other_ticker,m_macd_timeframe,m_macd_slow_ema_period,0,MODE_EMA,PRICE_CLOSE);
//--- check
ResetLastError();
if(m_ema_fast_handle==INVALID_HANDLE || m_ema_slow_handle==INVALID_HANDLE )
{
SetUserError(ERR_INVALID_HANDLE);
printf("Erro ao carregar M<00>dia M<00>veis - error: %d",GetLastError());
return(false);
}
//--- add to chart
ChartIndicatorAdd(0,0,m_ema_fast_handle);
ChartIndicatorAdd(0,0,m_ema_slow_handle);
//--- ok
return(true);
}
//+------------------------------------------------------------------+
//| Checking if there is a possibility of opening a buy position. |
//+------------------------------------------------------------------+
bool CMACDStrategy::CheckOpenLong(double &price, double &sl, double &tp, datetime &expiration)
{
return(CheckPriceWithDirection(m_direction,POSITION_TYPE_BUY,price,sl,tp,expiration));
}
//+------------------------------------------------------------------+
//| Checking if there is a possibility of opening a sell position. |
//+------------------------------------------------------------------+
bool CMACDStrategy::CheckOpenShort(double &price, double &sl, double &tp, datetime &expiration)
{
return(CheckPriceWithDirection(m_direction,POSITION_TYPE_SELL,price,sl,tp,expiration));
}
//+------------------------------------------------------------------+
//| Checking price by direction |
//+------------------------------------------------------------------+
bool CMACDStrategy::CheckPriceWithDirection(ENUM_TYPE_DIRECTION direction,ENUM_POSITION_TYPE type,double &price,double &sl,double &tp,datetime &expiration)
{
//--- if trend direction
if(direction==TREND_DIRECTION)
return(CheckPriceTrendDirection(type,price,sl,tp,expiration));
//--- counter trend direction
else
return(CheckPriceCounterTrendDirection(type,price,sl,tp,expiration));
}
//+------------------------------------------------------------------+
//| Checking price by trend direction |
//+------------------------------------------------------------------+
bool CMACDStrategy::CheckPriceTrendDirection(ENUM_POSITION_TYPE type,double &price,double &sl,double &tp,datetime &expiration)
{
//--- check positon type
if(type==POSITION_TYPE_BUY)
return(CheckPriceMax(price,sl,tp,expiration));
else
return(CheckPriceMin(price,sl,tp,expiration));
return(false);
}
//+------------------------------------------------------------------+
//| Checking price by counter trend direction |
//+------------------------------------------------------------------+
bool CMACDStrategy::CheckPriceCounterTrendDirection(ENUM_POSITION_TYPE type,double &price,double &sl,double &tp,datetime &expiration)
{
//--- check positon type
if(type==POSITION_TYPE_BUY)
return(CheckPriceMin(price,sl,tp,expiration));
else
return(CheckPriceMax(price,sl,tp,expiration));
return(false);
}
//+------------------------------------------------------------------+
//| Obtain price max |
//+------------------------------------------------------------------+
bool CMACDStrategy::CheckPriceMax(double &price,double &sl,double &tp,datetime &expiration)
{
//---
if(!Refresh())
return false;
// check strategy trigger
bool authorizeATR = false;
if(M_MACD_TYPE_ENTRY == MACD_TYPE_ENTRY_1)
{
if(m_MACD_SIGNAL[1] < 0 && m_MACD_SIGNAL[0] > 0)
{
m_atr_counter = m_atr_candle_counter;
//price = m_symbol.Last();
//return true;
}
}
else
if(M_MACD_TYPE_ENTRY == MACD_TYPE_ENTRY_2)
{
if(m_MACD_MAIN[1] < m_MACD_SIGNAL[1] && m_MACD_MAIN[0] > m_MACD_SIGNAL[0])
{
m_atr_counter = m_atr_candle_counter;
//price = m_symbol.Last();
//return true;
}
}
else
if(M_MACD_TYPE_ENTRY == MACD_TYPE_ENTRY_3)
{
if(m_MACD_MAIN[1] < m_MACD_STDDEV_UP[1] && m_MACD_MAIN[0] > m_MACD_STDDEV_UP[0])
{
m_atr_counter = m_atr_candle_counter;
//price = m_symbol.Last();
//return true;
}
}
else
if(M_MACD_TYPE_ENTRY == MACD_TYPE_ENTRY_4)
{
if(m_MACD_MAIN[1] < 0 && m_MACD_MAIN[0] > 0)
{
m_atr_counter = m_atr_candle_counter;
//price = m_symbol.Last();
//return true;
}
}
else
{
Print("Tipo de Entrada MACD n<00>o selecionada.");
}
if (m_atr_counter > 0) {
m_atr_counter -= 1;
int maxAtrArray = ArrayMaximum(m_ATR,0,m_atr_candle_counter);
if (maxAtrArray == 0) {
price = m_symbol.Last();
return true;
}
}
//---
return(false);
}
//+------------------------------------------------------------------+
//| Obtain price min |
//+------------------------------------------------------------------+
bool CMACDStrategy::CheckPriceMin(double &price,double &sl,double &tp,datetime &expiration)
{
//---
if(!Refresh())
return false;
// check strategy trigger
if(M_MACD_TYPE_ENTRY == MACD_TYPE_ENTRY_1)
{
if(m_MACD_SIGNAL[1] > 0 && m_MACD_SIGNAL[0] < 0)
{
m_atr_counter = m_atr_candle_counter;
//price = m_symbol.Last();
//return true;
}
}
else
if(M_MACD_TYPE_ENTRY == MACD_TYPE_ENTRY_2)
{
if(m_MACD_MAIN[1] > m_MACD_SIGNAL[1] && m_MACD_MAIN[0] < m_MACD_SIGNAL[0])
{
m_atr_counter = m_atr_candle_counter;
//price = m_symbol.Last();
//return true;
}
}
else
if(M_MACD_TYPE_ENTRY == MACD_TYPE_ENTRY_3)
{
if(m_MACD_MAIN[1] > m_MACD_STDDEV_DOWN[1] && m_MACD_MAIN[0] < m_MACD_STDDEV_DOWN[0])
{
m_atr_counter = m_atr_candle_counter;
//price = m_symbol.Last();
//return true;
}
}
else
if(M_MACD_TYPE_ENTRY == MACD_TYPE_ENTRY_4)
{
if(m_MACD_MAIN[1] > 0 && m_MACD_MAIN[0] < 0)
{
m_atr_counter = m_atr_candle_counter;
//price = m_symbol.Last();
//return true;
}
}
else
{
Print("Tipo de Entrada MACD n<00>o selecionada.");
}
if (m_atr_counter > 0) {
m_atr_counter -= 1;
int maxAtrArray = ArrayMaximum(m_ATR,0,m_atr_candle_counter);
if (maxAtrArray == 0) {
price = m_symbol.Last();
return true;
}
}
//---
return(false);
}
//+------------------------------------------------------------------+
//| Check Trailing Order |
//+------------------------------------------------------------------+
bool CMACDStrategy::CheckTralilingOrder(COrderInfo *order,double &price,datetime &expiration)
{
//---
return(false);
}
//+------------------------------------------------------------------+
//| Refresh Indicators Data. |
//+------------------------------------------------------------------+
bool CMACDStrategy::Refresh(void)
{
//--- check n bars in chart
if(Bars(m_other_ticker,m_macd_timeframe)<m_macd_fast_ema_period) //--- checar no tf do indicador
return(false);
if(Bars(m_other_ticker,m_macd_timeframe)<m_macd_slow_ema_period) //--- checar no tf do indicador
return(false);
if(Bars(m_other_ticker,m_macd_timeframe)<m_macd_signal_period) //--- checar no tf do indicador
return(false);
//--- check n bars calculated
if(BarsCalculated(m_macd_handle)<1)
return(false);
//--- check n bars copied
if(CopyBuffer(m_macd_handle,0,1,m_macd_stddev_period+2,m_MACD_MAIN)<1) //--- compiar sempre da barra 1 pra tr<EFBFBD>s
return(false);
if(CopyBuffer(m_macd_handle,1,1,3,m_MACD_SIGNAL)<1)
return(false);
if(CopyBuffer(m_macd_handle,2,1,3,m_MACD_STDDEV_UP)<1)
return(false);
if(CopyBuffer(m_macd_handle,3,1,3,m_MACD_STDDEV_DOWN)<1)
return(false);
if(CopyBuffer(m_macd_handle,4,1,3,m_MACD_EMA_FAST)<1)
return(false);
if(CopyBuffer(m_macd_handle,5,1,3,m_MACD_EMA_SLOW)<1)
return(false);
//--- check n bars in chart
if(Bars(m_other_ticker,m_atr_timeframe)<m_atr_period) //--- checar no tf do indicador
return(false);
//--- check n bars calculated
if(BarsCalculated(m_atr_handle)<1)
return(false);
//--- check n bars copied
if(CopyBuffer(m_atr_handle,0,1,m_atr_period+2,m_ATR)<1)
return(false);
//---
if(CopyRates(m_symbol.Name(),m_period,1,1,m_rates)<1)
return(false);
//---
return(true);
}