UTE/Examples/TrendTrader.mq5

413 lines
33 KiB
MQL5
Raw Permalink Normal View History

2025-05-30 16:34:43 +02:00
<EFBFBD><EFBFBD>//+------------------------------------------------------------------+
//| 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 2 OVX-zone of Corrention
input bool Open_RSIH4_AT = true; // Open position on RSIH4 2 OVX-zone of Corrention
//+-------------------------------------------------+
sinput string Close_Events = "========= Close Events =========";
input bool Close_RSIH4_TRN = true; // Close ?>78F8N ?@8 RSIH4 2 OVX-zone Trend
input bool Close_RSID1_TRN = true; // Close position ?@8 RSID1 2 OVX-zone Trend
//+-------------------------------------------------+
sinput string Technicals = "========= Technical Parameters =========";
input ENUM_EXEC_TYPE ExecMode = ByTimerEvent; // !?>A>1 0:B820F88
input int TimerSec = 2; // !5:C=4K 4;O B09<5@0
input double SLonATR = 2.62; // SL on ATR coef
input bool UseTLS = true; // Use trailing Stop
sinput bool DebugLog = true; // Extended(Debug) logging
//+------------------------------------------------------------------+
//| !B@0B538O 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; // >38@>20=85
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);
}
}
}
//+------------------------------------------------------------------+
//| 01>B0 A >B;>65==K<8 >@45@0<8 BuyStop 4;O >B:@KB8O 4;8==>9 |
//| ?>78F88 |
//+------------------------------------------------------------------+
void CTrendTrader::SupportPendingBuy(const MarketEvent &event,CPendingOrder *order)
{
}
//+------------------------------------------------------------------+
//| 01>B0 A >B;>65==K<8 >@45@0<8 SellStop 4;O >B:@KB8O :>@>B:>9 |
//| ?>78F88 |
//+------------------------------------------------------------------+
void CTrendTrader::SupportPendingSell(const MarketEvent &event,CPendingOrder* order)
{
}
//+------------------------------------------------------------------+
//| >72@0I05B ?@>F5=B A@54AB2 4;O >B:@KB8O ?>78F88 |
//+------------------------------------------------------------------+
double CTrendTrader::GetPercent(void)
{
return m_percent;
}
//+------------------------------------------------------------------+
//| #AB0=02;8205B ?@>F5=B A@54AB2 4;O >B:@KB8O ?>78F88 |
//+------------------------------------------------------------------+
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);
}