//+------------------------------------------------------------------+ //| TrendTrader.mq5 | //| Sergey Lebedev | //| https://www.mql5.com | //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ #property copyright "Copyright 2019, Sergey Lebedev" #property link "https://www.mql5.com/ru/users/c-4" #property version "1.0" #include "Strategy\Strategy.mqh" #include "Strategy\Indicators.mqh" #include "Strategy\Trailings\TrailingClassic.mqh" //+------------------------------------------------------------------+ //| TrendTrader based on Unified Expert Engine (aka UXE) //| Latest verion is https://www.mql5.com/ru/articles/2653 //| Should be copied to MQL5\Insclude\UXE | //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| Expert Enums //+------------------------------------------------------------------+ enum ENUM_TREND_DIR // Trend Direction { DIR_DN = 0, // Dir DN DIR_UP = 1 // Dir UP }; enum ENUM_TREND_STATE // Trend State { STATE_DEAD = 0, STATE_JUNG = 1, STATE_OLDA = 2, STATE_BEAT = 3, STATE_FLAT = 4 }; enum ENUM_EXEC_TYPE // Executiuon Type { ByTimerEvent = 1, // By Timer ByTickEvent = 2 // By Ticks }; //+------------------------------------------------------------------+ //| Expert Inputs //+------------------------------------------------------------------+ sinput string Parameters = "========= Main Parameters ========="; input ENUM_TREND_DIR TrendDir = DIR_UP; // TrendDir: UP/DN input ENUM_TIMEFRAMES MainTF = PERIOD_M1; // Timeframe input ENUM_TREND_STATE InitState = STATE_DEAD; // Trend Initial State //+-------------------------------------------------+ sinput string MM_Parameters = "========= Money Managment Parameters ========="; input ENUM_MM_TYPE AmountMode=MM_PERCENT_DEPO; // MM Type input double MMVal=25; // MM Value //+-------------------------------------------------+ sinput string Ind_Params = "========= Indicators Values ========="; input int PeriiodRSI =14; // Rsi Periiod input int PeriiodATR =7; // ATR Periiod //+-------------------------------------------------+ sinput string Open_Events = "========= Open Events ========="; input bool Open_RSIH1_AT = true; // Open position on RSIH1 в OVX-zone of Corrention input bool Open_RSIH4_AT = true; // Open position on RSIH4 в OVX-zone of Corrention //+-------------------------------------------------+ sinput string Close_Events = "========= Close Events ========="; input bool Close_RSIH4_TRN = true; // Close позицию при RSIH4 в OVX-zone Trend input bool Close_RSID1_TRN = true; // Close position при RSID1 в OVX-zone Trend //+-------------------------------------------------+ sinput string Technicals = "========= Technical Parameters ========="; input ENUM_EXEC_TYPE ExecMode = ByTimerEvent; // Способ активации input int TimerSec = 2; // Секунды для таймера input double SLonATR = 2.62; // SL on ATR coef input bool UseTLS = true; // Use trailing Stop sinput bool DebugLog = true; // Extended(Debug) logging //+------------------------------------------------------------------+ //| Стратегия CImpulse | //+------------------------------------------------------------------+ class CTrendTrader : public CStrategy { private: double m_percent; // Deposit persent to open new position double m_Amount, m_Taget; // m_Amount - amount to open new position, m_Taget - target for SL/TP int h_RSIH1, h_RSIH4, h_RSID1, h_SLATR; // Handles CLog* m_log; // Логирование bool m_Signal; // Signal to Open/Close string m_SgnTag; // Signal Tag (for Comments and Debuggin) double m_InitATR4SL; // Initial ATR value for SL bool m_ResBool; protected: virtual void InitBuy(const MarketEvent &event); virtual void InitSell(const MarketEvent &event); virtual void SupportBuy(const MarketEvent &event,CPosition *pos); virtual void SupportSell(const MarketEvent &event,CPosition *pos); virtual void SupportPendingBuy(const MarketEvent &event,CPendingOrder *order); virtual void SupportPendingSell(const MarketEvent &event,CPendingOrder* order); virtual bool OnInit(void); public: double GetPercent(void); void SetPercent(double percent); CUnIndicator RSIH1, RSIH4, RSID1, SLATR; }; bool CTrendTrader::OnInit(void) { // Configure Log Manager m_log=CLog::GetLog(); if (DebugLog) m_log.TerminalPriority(MESSAGE_INFO); m_ResBool = false; //Configure Signals if (ExecMode == ByTimerEvent) { EventSetTimer(TimerSec); // 1 = 1 sec CMessage *msg=new CMessage(MESSAGE_INFO,__FUNCTION__,"Timer is set for "+ TimerSec + " sec!"); m_log.AddMessage(msg); } if (Open_RSIH1_AT) { RSIH1.SetParameter(PeriiodRSI); RSIH1.SetParameter(PRICE_CLOSE); h_RSIH1 = RSIH1.Create(Symbol(), PERIOD_H1, IND_RSI); if(h_RSIH1 == INVALID_HANDLE) { CMessage *msg=new CMessage(MESSAGE_ERROR,__FUNCTION__,"Error-1: RSI-H1 is not created!"); m_log.AddMessage(msg); return false; } } if (Open_RSIH4_AT || Close_RSIH4_TRN) { RSIH4.SetParameter(PeriiodRSI); RSIH4.SetParameter(PRICE_CLOSE); h_RSIH4 = RSIH4.Create(Symbol(), PERIOD_H4, IND_RSI); if(h_RSIH4 == INVALID_HANDLE) { CMessage *msg=new CMessage(MESSAGE_ERROR,__FUNCTION__,"Error-2: RSI-H4 is not created!"); m_log.AddMessage(msg); return false; } } if (Close_RSID1_TRN) { RSID1.SetParameter(PeriiodRSI); RSID1.SetParameter(PRICE_CLOSE); h_RSID1 = RSID1.Create(Symbol(), PERIOD_H4, IND_RSI); if(h_RSID1 == INVALID_HANDLE) { CMessage *msg=new CMessage(MESSAGE_ERROR,__FUNCTION__,"Error-3: RSI-D1 is not created!"); m_log.AddMessage(msg); return false; } } // Configure MM MM.SetMMType(AmountMode); if (AmountMode==MM_FIX_LOT) MM.SetLotFixed(MMVal); if (AmountMode==MM_PERCENT_DEPO) { m_percent = MMVal/100; MM.SetPercent(m_percent); } // Configure SL SLATR.SetParameter(PeriiodATR); SLATR.SetParameter(PRICE_CLOSE); h_SLATR = SLATR.Create(Symbol(), PERIOD_H4, IND_ATR); if(h_SLATR == INVALID_HANDLE) { CMessage *msg=new CMessage(MESSAGE_ERROR,__FUNCTION__,"Error-4: ATR-H4 is not created!"); m_log.AddMessage(msg); return false; } // COnfigure Trade States for Just2Trade broker TradeState(TRADE_BUY_AND_SELL); return true; } //+------------------------------------------------------------------+ //| Set Buy orders | //+------------------------------------------------------------------+ void CTrendTrader::InitBuy(const MarketEvent &event) { if(!IsTrackEvents(event))return; if(PositionsTotal(POSITION_TYPE_BUY, ExpertSymbol(), ExpertMagic()) > 0) return; m_Signal = false; if(TrendDir == DIR_UP) { if (Open_RSIH1_AT & RSIH1[0]<30) {m_Signal= true;m_SgnTag="RSIH1_AT";} if (Open_RSIH4_AT & RSIH4[0]<30) {m_Signal= true;m_SgnTag="RSIH4_AT";} if (m_Signal) { if (AmountMode==MM_FIX_LOT) m_Amount = MM.GetLotFixed(); if (AmountMode==MM_PERCENT_DEPO) m_Amount = MM.GetLotByPercentDepo(); Trade.Buy(m_Amount, ExpertSymbol(), m_SgnTag); CMessage *msg=new CMessage(MESSAGE_INFO,__FUNCTION__,"Open BUY(" + DoubleToString(WS.Bid(),WS.Digits()) + ") Signal based on " + m_SgnTag); m_log.AddMessage(msg); m_InitATR4SL= SLATR[0]; } } } //+------------------------------------------------------------------+ //| Set Sell orders | //+------------------------------------------------------------------+ void CTrendTrader::InitSell(const MarketEvent &event) { if(!IsTrackEvents(event))return; if(PositionsTotal(POSITION_TYPE_SELL, ExpertSymbol(), ExpertMagic()) > 0) return; m_Signal = false; if(TrendDir == DIR_DN ) { if (Open_RSIH1_AT & RSIH1[0]>70) {m_Signal= true;m_SgnTag="RSIH1_AT";} if (Open_RSIH4_AT & RSIH4[0]>70) {m_Signal= true;m_SgnTag="RSIH4_AT";} if (m_Signal) { CMessage *msg=new CMessage(MESSAGE_INFO,__FUNCTION__,"Open SELL(" + DoubleToString(WS.Bid(),WS.Digits()) + ") Signal based on " + m_SgnTag); m_log.AddMessage(msg); if (AmountMode==MM_FIX_LOT) m_Amount = MM.GetLotFixed(); if (AmountMode==MM_PERCENT_DEPO) m_Amount = MM.GetLotByPercentDepo(); Trade.Sell(m_Amount, ExpertSymbol(), m_SgnTag); m_InitATR4SL= SLATR[0]; } } } //+------------------------------------------------------------------+ //| Support BUY | //+------------------------------------------------------------------+ void CTrendTrader::SupportBuy(const MarketEvent &event,CPosition *pos) { if(!IsTrackEvents(event))return; m_Signal = false; if (Close_RSIH4_TRN & RSIH4[0]>70) {m_Signal= true;m_SgnTag="RSIH4_TRN";} if (Close_RSID1_TRN & RSID1[0]>70) {m_Signal= true;m_SgnTag="RSID1_TRN";} if(m_Signal) { CMessage *msg=new CMessage(MESSAGE_INFO,__FUNCTION__,"Close BUY(" + DoubleToString(WS.Bid(),WS.Digits()) + ") Signal based on " + m_SgnTag); m_log.AddMessage(msg); pos.CloseAtMarket(m_SgnTag); } // SL if (pos.StopLossValue()==0) { m_Taget = WS.Bid() - m_InitATR4SL*SLonATR; CPosition *pos=ActivePositions.At(0); if (CheckPointer(pos)) pos.StopLossValue(m_Taget); CMessage *msg2=new CMessage(MESSAGE_INFO,__FUNCTION__,"SL for BUY is set on "+ DoubleToString(m_Taget,WS.Digits()) + " based on ATR "+ DoubleToString(m_InitATR4SL,4)+ " and Price "+ DoubleToString(WS.Bid(),WS.Digits())); m_log.AddMessage(msg2); } // Activate/change TLS if UseTLS is True and profit is reached if (UseTLS) { m_Taget = m_InitATR4SL*SLonATR*WS.ContractSize(); if (pos.Profit() < m_Taget) return; // Not enougth profit for TLS, still using initial SL CMessage *msg3=new CMessage(MESSAGE_INFO,__FUNCTION__,"Position Profit "+ DoubleToString(pos.Profit(),2) + " on Price "+ DoubleToString(WS.Bid(),WS.Digits())+ " reached Level1 "+ DoubleToString(m_Taget,2)); m_log.AddMessage(msg3); if(pos.Trailing == NULL) { CTrailingClassic* trailing = new CTrailingClassic(); trailing.SetPosition(pos); trailing.SetDiffExtremum(m_InitATR4SL*SLonATR); trailing.SetStepModify(m_InitATR4SL*SLonATR/4); pos.Trailing = trailing; } m_ResBool= pos.Trailing.Modify(); if (m_ResBool) { CMessage *msg4=new CMessage(MESSAGE_INFO,__FUNCTION__,"TLS for BUY position is set on "+ DoubleToString(pos.StopLossValue(),WS.Digits())); m_log.AddMessage(msg4); } } } //+------------------------------------------------------------------+ //| Support SELL | //+------------------------------------------------------------------+ void CTrendTrader::SupportSell(const MarketEvent &event,CPosition *pos) { if(!IsTrackEvents(event))return; m_Signal = false; if (Close_RSIH4_TRN & RSIH4[0]<30) {m_Signal= true;m_SgnTag="RSIH4_TRN";} if (Close_RSID1_TRN & RSID1[0]<30) {m_Signal= true;m_SgnTag="RSID1_TRN";} if(m_Signal) { CMessage *msg=new CMessage(MESSAGE_INFO,__FUNCTION__,"Close SELL(" + DoubleToString(WS.Ask(),WS.Digits()) + ") Signal based on " + m_SgnTag); m_log.AddMessage(msg); pos.CloseAtMarket(m_SgnTag); } // Set SL if (pos.StopLossValue()==0) { m_Taget = WS.Ask() + m_InitATR4SL*SLonATR; CPosition *pos=ActivePositions.At(0); if (CheckPointer(pos)) pos.StopLossValue(m_Taget); CMessage *msg2=new CMessage(MESSAGE_INFO,__FUNCTION__,"SL for SELL is set on "+ DoubleToString(m_Taget,WS.Digits()) + " based on ATR "+ DoubleToString(m_InitATR4SL,4)+ " and Price "+ DoubleToString(WS.Ask(),WS.Digits())); m_log.AddMessage(msg2); } // Activate/change TLS if UseTLS is True and profit is reached if (UseTLS) { m_Taget = m_InitATR4SL*SLonATR*WS.ContractSize(); if (pos.Profit() < m_Taget) return; // Not enougth profit for TLS, still using initial SL CMessage *msg3=new CMessage(MESSAGE_INFO,__FUNCTION__,"Position Profit "+ DoubleToString(pos.Profit(),2) + " at Price "+ DoubleToString(WS.Ask(),WS.Digits()) +" reached Level1 "+ DoubleToString(m_Taget,2)); m_log.AddMessage(msg3); if(pos.Trailing == NULL) { CTrailingClassic* trailing = new CTrailingClassic(); trailing.SetPosition(pos); trailing.SetDiffExtremum(m_InitATR4SL*SLonATR); trailing.SetStepModify(m_InitATR4SL*SLonATR/4); pos.Trailing = trailing; } m_ResBool=pos.Trailing.Modify(); if (m_ResBool) { CMessage *msg4=new CMessage(MESSAGE_INFO,__FUNCTION__,"TLS for SELL position is set on "+ DoubleToString(pos.StopLossValue(),WS.Digits())); m_log.AddMessage(msg4); } } } //+------------------------------------------------------------------+ //| Работа с отложенными ордерами BuyStop для открытия длинной | //| позиции | //+------------------------------------------------------------------+ void CTrendTrader::SupportPendingBuy(const MarketEvent &event,CPendingOrder *order) { } //+------------------------------------------------------------------+ //| Работа с отложенными ордерами SellStop для открытия короткой | //| позиции | //+------------------------------------------------------------------+ void CTrendTrader::SupportPendingSell(const MarketEvent &event,CPendingOrder* order) { } //+------------------------------------------------------------------+ //| Возвращает процент средств для открытия позиции | //+------------------------------------------------------------------+ double CTrendTrader::GetPercent(void) { return m_percent; } //+------------------------------------------------------------------+ //| Устанавливает процент средств для открытия позиции | //+------------------------------------------------------------------+ void CTrendTrader::SetPercent(double percent) { m_percent = percent; MM.SetPercent(m_percent); } //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { CTrendTrader* TrnTrader = new CTrendTrader(); TrnTrader.ExpertMagic(140578); TrnTrader.ExpertName("TrendTrader 1.0"); TrnTrader.Timeframe(PERIOD_H1); TrnTrader.ExpertSymbol(Symbol()); Manager.AddStrategy(TrnTrader); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { if (ExecMode == ByTickEvent) Manager.OnTick(); } void OnTimer() { if (ExecMode == ByTimerEvent) Manager.OnTimer(); } //+------------------------------------------------------------------+ //| ChartEvent function | //+------------------------------------------------------------------+ void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { Manager.OnChartEvent(id, lparam, dparam, sparam); ChartRedraw(0); }