Untitled

mail@pastecode.io avatar
unknown
c_cpp
a year ago
11 kB
3
Indexable
Never
//+------------------------------------------------------------------+
//| Impulse MACD strategy                                            |
//| Copyright 2023, YourCompany                                      |
//| https://www.yourcompany.com                                      |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, YourCompany"
#property link      "https://www.yourcompany.com"

#define MAGIC_NUMBER 1234518

#include <Trade/Trade.mqh>
#include <Trade\SymbolInfo.mqh>
#include <Trade\PositionInfo.mqh>
#include <Trade\AccountInfo.mqh>

input int MasterMA = 34;
input int SignalMA = 9;
input double longLine = -0.002;
input double shortLine = 0.002;
input int takeProfitSize = 20;
input int stopLossSize = 50;

int ExtTimeOut = 10;


//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class CImpulseMACDExpert
  {
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;                     // ImpulseMACD indicator handle
   //--- indicator buffers
   double            m_buff_impulse_MACD[];        // MACD indicator main buffer
   double            m_buff_signal[];              // MACD indicator signal buffer
   //--- indicator data for processing
   double            m_impulse_macd_current;
   double            m_impulse_macd_previous;
   double            m_signal_current;
   double            m_signal_previous;
   //---
   double            m_stop_loss;
   double            m_take_profit;

public:
                     CImpulseMACDExpert(void);
                    ~CImpulseMACDExpert(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
CImpulseMACDExpert ExtExpert;
//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CImpulseMACDExpert::CImpulseMACDExpert(void) : m_adjusted_point(0),
   m_handle(INVALID_HANDLE),
   m_impulse_macd_current(0),
   m_impulse_macd_previous(0),
   m_signal_current(0),
   m_signal_previous(0),
   m_stop_loss(0),
   m_take_profit(0)
  {
   ArraySetAsSeries(m_buff_impulse_MACD,true);
   ArraySetAsSeries(m_buff_signal,true);
  }
//+------------------------------------------------------------------+
//| Destructor                                                       |
//+------------------------------------------------------------------+
CImpulseMACDExpert::~CImpulseMACDExpert(void)
  {
  }
//+------------------------------------------------------------------+
//| Initialization and checking for input parameters                 |
//+------------------------------------------------------------------+
bool CImpulseMACDExpert::Init(void)
  {
//--- initialize common information
   m_symbol.Name(Symbol());
   m_trade.SetExpertMagicNumber(MAGIC_NUMBER);
   m_trade.SetMarginMode();
   m_trade.SetTypeFillingBySymbol(Symbol());
//--- 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_stop_loss = stopLossSize*m_adjusted_point;
   m_take_profit = takeProfitSize*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);
//--- succeed
   return(true);
  }
//+------------------------------------------------------------------+
//| Checking for input parameters                                    |
//+------------------------------------------------------------------+
bool CImpulseMACDExpert::InitCheckParameters(const int digits_adjust)
  {
//--- initial data checks
   if(takeProfitSize*digits_adjust<m_symbol.StopsLevel())
     {
      printf("Take Profit must be greater than %d",m_symbol.StopsLevel());
      return(false);
     }
   if(stopLossSize*digits_adjust<m_symbol.StopsLevel())
     {
      printf("Stop loss must be greater than %d",m_symbol.StopsLevel());
      return(false);
     }
//--- succeed
   return(true);
  }
//+------------------------------------------------------------------+
//| Initialization of the indicators                                 |
//+------------------------------------------------------------------+
bool CImpulseMACDExpert::InitIndicators(void)
  {
//--- create MACD indicator
   if(m_handle==INVALID_HANDLE)
      if((m_handle=iCustom(NULL, 0, "impulse", MasterMA, SignalMA))==INVALID_HANDLE)
        {
         printf("ErroMT5|Expert!11r creating ImpulseMACD indicator");
         return(false);
        }
//--- succeed
   return(true);
  }
//+------------------------------------------------------------------+
//| Check for long position opening                                  |
//+------------------------------------------------------------------+
bool CImpulseMACDExpert::LongOpened(void)
  {
   bool res=false;
//--- check for long position (BUY) possibility
   if(m_impulse_macd_current <= longLine && m_signal_current <= longLine)
      if(m_impulse_macd_current>m_signal_current && m_impulse_macd_previous<m_signal_previous)
        {
         double price=m_symbol.Ask();
         double tp   =m_symbol.Bid()+m_take_profit;
         double sl = m_symbol.Bid()-m_stop_loss;
         double lotSize = m_account.MaxLotCheck(Symbol(), ORDER_TYPE_BUY, price) * 0.95;
         lotSize = NormalizeDouble(lotSize, 2);
         //--- open position
         if(m_trade.PositionOpen(Symbol(),ORDER_TYPE_BUY,lotSize,price,sl,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);
           }

         res=true;
        }
//--- result
   return(res);
  }
//+------------------------------------------------------------------+
//| Check for short position opening                                 |
//+------------------------------------------------------------------+
bool CImpulseMACDExpert::ShortOpened(void)
  {
   bool res=false;
//--- check for short position (SELL) possibility
   if(m_impulse_macd_current >= shortLine && m_signal_current >= shortLine)
      if(m_impulse_macd_current<m_signal_current && m_impulse_macd_previous>m_signal_previous)
        {
         double price=m_symbol.Bid();
         double tp   =m_symbol.Ask()-m_take_profit;
         double sl = m_symbol.Ask()+m_stop_loss;
         double lotSize = m_account.MaxLotCheck(Symbol(), ORDER_TYPE_SELL, price) * 0.95;
         lotSize = NormalizeDouble(lotSize, 2);
         //--- open position
         if(m_trade.PositionOpen(Symbol(),ORDER_TYPE_SELL,lotSize,price,sl,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 CImpulseMACDExpert::Processing(void)
  {
   if(!m_symbol.RefreshRates())
      return(false);
   if(BarsCalculated(m_handle)<2)
      return(false);
   if(CopyBuffer(m_handle,0,1,2,m_buff_impulse_MACD) !=2 ||
      CopyBuffer(m_handle,1,1,2,m_buff_signal)!=2)
      return(false);

   m_impulse_macd_current = m_buff_impulse_MACD[0];
   m_impulse_macd_previous = m_buff_impulse_MACD[1];
   m_signal_current =m_buff_signal[0];
   m_signal_previous =m_buff_signal[1];

   if(m_position.Select(Symbol()))
     {
      // TODO
     }
//--- no opened position identified
   else
     {
      if(LongOpened())
         return(true);
      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);
//--- secceed
   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*SignalMA)
        {
         //--- change limit time by timeout in seconds if processed
         if(ExtExpert.Processing())
            limit_time=TimeCurrent()+ExtTimeOut;
        }
     }
  }
//+------------------------------------------------------------------+



//crossover = ta.crossover(md[1], sb[1])
//crossunder = ta.crossunder(md[1], sb[1])
//
//longCondition = (sb[1] <= longLine and md[1] <= longLine) and crossover
//if (longCondition)
//    strategy.entry("Long", strategy.long)
// alert("Long signal")
//
//shortCondition = (sb[1] >= shortLine and md[1] >= shortLine) and crossunder
//if (shortCondition)
//    strategy.entry("Short", strategy.short)
// alert("Short signal")
//
//inLong = strategy.position_size > 0
//inShort = strategy.position_size < 0
//
//if inLong
// tpPrice = strategy.position_avg_price + tpPips
// slPrice = strategy.position_avg_price - slPips
// strategy.exit("TP/SL", from_entry="Long", limit=tpPrice, stop=slPrice)
//
//if inShort
// tpPrice = strategy.position_avg_price - tpPips
// slPrice = strategy.position_avg_price + slPips
// strategy.exit("TP/SL", from_entry="Short", limit=tpPrice, stop=slPrice)