Files
MT5-indicator-collection/macd-mme.mq5
T
Coding for Dummies 9003b29674 Indicator Collection
Indicator Collection
2024-08-27 23:35:50 +07:00

579 lines
20 KiB
Plaintext

//+------------------------------------------------------------------+
//| MACD Sample.mq5 |
//| Copyright 2009-2013, MetaQuotes Software Corp. |
//| http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2014 Semet Gaetan"
#property link "http://www.xeberon.net/gaetan"
#property version "1.0"
#property description "Gaetan Semet Expert Advisor"
#property description "This expert advisor triggers position on MACD and"
#property description "crossing Moving Averages. After a bid is placed"
#property description "it is qualified as 'gaining' or loosing'. If loosing,"
#property description "the stop will triggered to stop losses. If gaining,"
#property description "a trailing stop will be placed that allow a retracement"
#property description "of N percents. Only a small number of retracement is"
#property description "allowed, after a stop loss will be placed."
//---
#include <Trade\Trade.mqh>
#include <Trade\SymbolInfo.mqh>
#include <Trade\PositionInfo.mqh>
#include <Trade\AccountInfo.mqh>
//---
input double InpLots = 0.1; // Size of lots for each position
input int InpAllowedRetracementPercent = 50; // Allowed retracement for gaining position (in percent)
input int IntMaxNumberOfRetracement = 2; // Maximum number of allowed retracement before placing a close stop loss.
input int InpMACDOpenLevel = 3; // MACD open level (in pips)
input int InpMACDCloseLevel = 2; // MACD close level (in pips)
input int InpMA20TrendPeriod = 20; // Long MA trend period
input int InpMA6TrendPeriod = 6; // Short MA trend period
//---
int ExtTimeOut=10; // time out in seconds between trade operations
//+------------------------------------------------------------------+
//| CMacdExpert class |
//+------------------------------------------------------------------+
class CMacdExpert
{
protected:
double m_adjusted_point; // point value adjusted for 3 or 5 points
CTrade m_trade; // trading object
CSymbolInfo m_symbol; // symbol info object
CPositionInfo m_position; // trade position object
CAccountInfo m_account; // account info wrapper
//--- indicators
int m_handle_macd; // MACD indicator handle
int m_handle_ema20; // long moving average indicator handle
int m_handle_ema6; // short moving average indicator handle
//--- indicator buffers
double m_buff_MACD_main[]; // MACD indicator main buffer
double m_buff_MACD_signal[]; // MACD indicator signal buffer
double m_buff_EMA[]; // EMA indicator buffer
//--- indicator data for processing
double m_macd_current;
double m_macd_previous;
double m_signal_current;
double m_signal_previous;
double m_ema_current;
double m_ema_previous;
//---
double m_macd_open_level;
double m_macd_close_level;
double m_traling_stop;
double m_take_profit;
public:
CMacdExpert(void);
~CMacdExpert(void);
bool Init(void);
void Deinit(void);
bool Processing(void);
protected:
bool InitCheckParameters(const int digits_adjust);
bool InitIndicators(void);
bool LongClosed(void);
bool ShortClosed(void);
bool LongModified(void);
bool ShortModified(void);
bool LongOpened(void);
bool ShortOpened(void);
};
//--- global expert
CMacdExpert ExtExpert;
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CMacdExpert::CMacdExpert(void) : m_adjusted_point(0),
m_handle_macd(INVALID_HANDLE),
m_handle_ema20(INVALID_HANDLE),
m_handle_ema6(INVALID_HANDLE),
m_macd_current(0),
m_macd_previous(0),
m_signal_current(0),
m_signal_previous(0),
m_ema_current(0),
m_ema_previous(0),
m_macd_open_level(0),
m_macd_close_level(0),
m_traling_stop(0),
m_take_profit(0)
{
ArraySetAsSeries(m_buff_MACD_main, true);
ArraySetAsSeries(m_buff_MACD_signal, true);
ArraySetAsSeries(m_buff_EMA, true);
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CMacdExpert::~CMacdExpert(void)
{
}
//+------------------------------------------------------------------+
//| Initialization and checking for input parameters |
//+------------------------------------------------------------------+
bool CMacdExpert::Init(void)
{
//--- initialize common information
m_symbol.Name(Symbol()); // symbol
m_trade.SetExpertMagicNumber(0xcafebabe); // magic
//--- tuning for 3 or 5 digits
int digits_adjust=1;
if (m_symbol.Digits() == 3 || m_symbol.Digits() == 5)
{
digits_adjust = 10;
}
m_adjusted_point = m_symbol.Point() * digits_adjust;
//--- set default deviation for trading in adjusted points
m_macd_open_level = InpMACDOpenLevel * m_adjusted_point;
m_macd_close_level= InpMACDCloseLevel * m_adjusted_point;
m_traling_stop = InpTrailingStop * m_adjusted_point;
m_take_profit = InpTakeProfit * m_adjusted_point;
//--- set default deviation for trading in adjusted points
m_trade.SetDeviationInPoints(3 * digits_adjust);
if (!InitCheckParameters(digits_adjust))
{
return(false);
}
if (!InitIndicators())
{
return(false);
}
return(true);
}
//+------------------------------------------------------------------+
//| Checking for input parameters |
//+------------------------------------------------------------------+
bool CMacdExpert::InitCheckParameters(const int digits_adjust)
{
//--- initial data checks
if (InpTakeProfit * digits_adjust < m_symbol.StopsLevel())
{
printf("Take Profit must be greater than %d", m_symbol.StopsLevel());
return(false);
}
if (InpTrailingStop * digits_adjust < m_symbol.StopsLevel())
{
printf("Trailing Stop must be greater than %d", m_symbol.StopsLevel());
return(false);
}
//--- check for right lots amount
if (InpLots < m_symbol.LotsMin() || InpLots > m_symbol.LotsMax())
{
printf("Lots amount must be in the range from %f to %f", m_symbol.LotsMin(), m_symbol.LotsMax());
return(false);
}
if (MathAbs(InpLots / m_symbol.LotsStep() - MathRound(InpLots / m_symbol.LotsStep())) > 1.0E - 10)
{
printf("Lots amount is not corresponding with lot step %f", m_symbol.LotsStep());
return(false);
}
//--- warning
if (InpTakeProfit <= InpTrailingStop)
{
printf("Warning: Trailing Stop must be less than Take Profit");
}
return(true);
}
//+------------------------------------------------------------------+
//| Initialization of the indicators |
//+------------------------------------------------------------------+
bool CMacdExpert::InitIndicators(void)
{
//--- create MACD indicator
if (m_handle_macd == INVALID_HANDLE)
{
if ((m_handle_macd = iMACD(NULL, 0, 12, 26, 9, PRICE_CLOSE)) == INVALID_HANDLE)
{
printf("Error creating MACD indicator");
return(false);
}
}
//--- create EMA 20 indicator and add it to collection
if (m_handle_ema20 == INVALID_HANDLE)
{
if ((m_handle_ema20 = iMA(NULL, 0, InpMA20TrendPeriod, 0, MODE_EMA, PRICE_CLOSE)) == INVALID_HANDLE)
{
printf("Error creating EMA indicator");
return(false);
}
}
//--- create EMA 6 indicator and add it to collection
if (m_handle_ema6== INVALID_HANDLE)
{
if ((m_handle_ema6 = iMA(NULL, 0, InpMA6TrendPeriod, 0, MODE_EMA, PRICE_CLOSE)) == INVALID_HANDLE)
{
printf("Error creating EMA indicator");
return(false);
}
}
return(true);
}
//+------------------------------------------------------------------+
//| Check for long position closing |
//+------------------------------------------------------------------+
bool CMacdExpert::LongClosed(void)
{
bool res = false;
//--- should it be closed?
if (m_macd_current > 0)
{
if ((m_macd_current < m_signal_current) && (m_macd_previous > m_signal_previous))
{
if (m_macd_current > m_macd_close_level)
{
//--- close position
if (m_trade.PositionClose(Symbol()))
{
printf("Long position by %s to be closed",Symbol());
}
else
{
printf("Error closing position by %s : '%s'", Symbol(), m_trade.ResultComment());
}
//--- processed and cannot be modified
res = true;
}
}
}
return(res);
}
//+------------------------------------------------------------------+
//| Check for short position closing |
//+------------------------------------------------------------------+
bool CMacdExpert::ShortClosed(void)
{
bool res=false;
//--- should it be closed?
if (m_macd_current < 0)
{
if ((m_macd_current > m_signal_current) && (m_macd_previous < m_signal_previous))
{
if (MathAbs(m_macd_current) > m_macd_close_level)
{
//--- close position
if (m_trade.PositionClose(Symbol()))
{
printf("Short position by %s to be closed",Symbol());
}
else
{
printf("Error closing position by %s : '%s'", Symbol(), m_trade.ResultComment());
}
//--- processed and cannot be modified
res = true;
}
}
}
return(res);
}
//+------------------------------------------------------------------+
//| Check for long position modifying |
//+------------------------------------------------------------------+
bool CMacdExpert::LongModified(void)
{
bool res = false;
//--- check for trailing stop
if (InpTrailingStop > 0)
{
if ((m_symbol.Bid() - m_position.PriceOpen()) > (m_adjusted_point * InpTrailingStop))
{
double sl = NormalizeDouble(m_symbol.Bid() - m_traling_stop, m_symbol.Digits());
double tp = m_position.TakeProfit();
if ((m_position.StopLoss() < sl) || (m_position.StopLoss() == 0.0))
{
//--- modify position
if (m_trade.PositionModify(Symbol(), sl, tp))
{
printf("Long position by %s to be modified",Symbol());
}
else
{
printf("Error modifying position by %s : '%s'", Symbol(), m_trade.ResultComment());
printf("Modify parameters : SL=%f,TP=%f", sl, tp);
}
//--- modified and must exit from expert
res = true;
}
}
}
return(res);
}
//+------------------------------------------------------------------+
//| Check for short position modifying |
//+------------------------------------------------------------------+
bool CMacdExpert::ShortModified(void)
{
bool res = false;
//--- check for trailing stop
if (InpTrailingStop > 0)
{
if ((m_position.PriceOpen() - m_symbol.Ask()) > (m_adjusted_point * InpTrailingStop))
{
double sl = NormalizeDouble(m_symbol.Ask() + m_traling_stop, m_symbol.Digits());
double tp = m_position.TakeProfit();
if ((m_position.StopLoss() > sl) || (m_position.StopLoss() == 0.0))
{
//--- modify position
if (m_trade.PositionModify(Symbol(), sl, tp))
{
printf("Short position by %s to be modified",Symbol());
}
else
{
printf("Error modifying position by %s : '%s'",Symbol(), m_trade.ResultComment());
printf("Modify parameters : SL=%f,TP=%f", sl, tp);
}
//--- modified and must exit from expert
res=true;
}
}
}
//--- result
return(res);
}
//+------------------------------------------------------------------+
//| Check for long position opening |
//+------------------------------------------------------------------+
bool CMacdExpert::LongOpened(void)
{
bool res = false;
//--- check for long position (BUY) possibility
if (m_macd_current < 0)
{
if (m_macd_current > m_signal_current && m_macd_previous<m_signal_previous)
{
if ((MathAbs(m_macd_current) > m_macd_open_level) && (m_ema_current > m_ema_previous))
{
double price=m_symbol.Ask();
double tp =m_symbol.Bid() + m_take_profit;
//--- check for free money
if (m_account.FreeMarginCheck(Symbol(), ORDER_TYPE_BUY, InpLots, price) < 0.0)
{
printf("We have no money. Free Margin = %f",m_account.FreeMargin());
}
else
{
//--- open position
if (m_trade.PositionOpen(Symbol(), ORDER_TYPE_BUY, InpLots, price, 0.0, tp))
printf("Position by %s to be opened", Symbol());
else
{
printf("Error opening BUY position by %s : '%s'", Symbol(), m_trade.ResultComment());
printf("Open parameters : price=%f,TP=%f", price, tp);
}
}
//--- in any case we must exit from expert
res = true;
}
}
}
return(res);
}
//+------------------------------------------------------------------+
//| Check for short position opening |
//+------------------------------------------------------------------+
bool CMacdExpert::ShortOpened(void)
{
bool res = false;
//--- check for short position (SELL) possibility
if (m_macd_current > 0)
{
if (m_macd_current < m_signal_current && m_macd_previous > m_signal_previous)
{
if (m_macd_current > (m_macd_open_level) && m_ema_current < m_ema_previous)
{
double price = m_symbol.Bid();
double tp = m_symbol.Ask() - m_take_profit;
//--- check for free money
if (m_account.FreeMarginCheck(Symbol(), ORDER_TYPE_SELL, InpLots, price) < 0.0)
{
printf("We have no money. Free Margin = %f",m_account.FreeMargin());
}
else
{
//--- open position
if (m_trade.PositionOpen(Symbol(), ORDER_TYPE_SELL, InpLots, price, 0.0, tp))
{
printf("Position by %s to be opened",Symbol());
}
else
{
printf("Error opening SELL position by %s : '%s'", Symbol(), m_trade.ResultComment());
printf("Open parameters : price=%f,TP=%f", price, tp);
}
}
//--- in any case we must exit from expert
res = true;
}
}
}
//--- result
return(res);
}
//+------------------------------------------------------------------+
//| main function returns true if any position processed |
//+------------------------------------------------------------------+
bool CMacdExpert::Processing(void)
{
//--- refresh rates
if (!m_symbol.RefreshRates())
{
return(false);
}
//--- refresh indicators
if (BarsCalculated(m_handle_macd) < 2 || BarsCalculated(m_handle_ema20) < 2 || BarsCalculated(m_handle_ema6) < 2)
{
return(false);
}
if (CopyBuffer(m_handle_macd, 0, 0, 2, m_buff_MACD_main) != 2 ||
CopyBuffer(m_handle_macd, 1, 0, 2, m_buff_MACD_signal)!= 2 ||
CopyBuffer(m_handle_ema6, 0, 0, 2, m_buff_EMA) != 2 ||
CopyBuffer(m_handle_ema20, 0, 0, 2, m_buff_EMA) != 2)
{
return(false);
}
// m_indicators.Refresh();
//--- to simplify the coding and speed up access
//--- data are put into internal variables
m_macd_current = m_buff_MACD_main[0];
m_macd_previous = m_buff_MACD_main[1];
m_signal_current = m_buff_MACD_signal[0];
m_signal_previous= m_buff_MACD_signal[1];
m_ema_current = m_buff_EMA[0];
m_ema_previous = m_buff_EMA[1];
//--- it is important to enter the market correctly,
//--- but it is more important to exit it correctly...
//--- first check if position exists - try to select it
if (m_position.Select(Symbol()))
{
if (m_position.PositionType() == POSITION_TYPE_BUY)
{
//--- try to close or modify long position
if (LongClosed())
{
return(true);
}
if (LongModified())
{
return(true);
}
}
else
{
//--- try to close or modify short position
if (ShortClosed())
{
return(true);
}
if (ShortModified())
{
return(true);
}
}
}
//--- no opened position identified
else
{
//--- check for long position (BUY) possibility
if (LongOpened())
{
return(true);
}
//--- check for short position (SELL) possibility
if (ShortOpened())
{
return(true);
}
}
//--- exit without position processing
return(false);
}
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit(void)
{
//--- create all necessary objects
if (!ExtExpert.Init())
{
return(INIT_FAILED);
}
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert new tick handling function |
//+------------------------------------------------------------------+
void OnTick(void)
{
static datetime limit_time = 0; // last trade processing time + timeout
//--- don't process if timeout
if (TimeCurrent() >= limit_time)
{
//--- check for data
if (Bars(Symbol(), Period()) > 2 * InpMA20TrendPeriod)
{
//--- change limit time by timeout in seconds if processed
if (ExtExpert.Processing())
{
limit_time = TimeCurrent() + ExtTimeOut;
}
}
}
}
//+------------------------------------------------------------------+