463 lines
38 KiB
MQL5
463 lines
38 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| 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âmetro escolhido para o [Período da Média Rápida do MACD] de [MACD Strategy] é inválido.");
|
|
return(false);
|
|
}
|
|
if(m_macd_slow_ema_period<=0)
|
|
{
|
|
printf("Erro: parâmetro escolhido para o [Período da Média Longa do MACD] de [MACD Strategy] é inválido.");
|
|
return(false);
|
|
}
|
|
if(m_macd_signal_period<=0)
|
|
{
|
|
printf("Erro: parâmetro escolhido para o [Período do Sinal do MACD] de [MACD Strategy] é inválido.");
|
|
return(false);
|
|
}
|
|
if(m_atr_period<=0)
|
|
{
|
|
printf("Erro: parâmetro escolhido para o [Período do ATR] de [MACD Strategy] é inválido.");
|
|
return(false);
|
|
}
|
|
if(m_atr_multiplier<=0)
|
|
{
|
|
printf("Erro: parâmetro escolhido para o [Multiplicador do ATR] de [MACD Strategy] é invá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é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édia Mó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ã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ã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á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);
|
|
}
|
|
|
|
|