mirror of
https://github.com/rithsila/MT5-EA-Sniper-Strategy.git
synced 2026-08-20 22:28:19 +00:00
Organize project in different folders
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
CommonBase.mqh
|
||||
For framework version 1.0
|
||||
|
||||
Copyright 2013-2020, Orchard Forex
|
||||
https://www.orchardforex.com
|
||||
|
||||
*/
|
||||
|
||||
class CCommonBase {
|
||||
|
||||
private:
|
||||
|
||||
protected: // Members
|
||||
|
||||
int mDigits;
|
||||
string mSymbol;
|
||||
ENUM_TIMEFRAMES mTimeframe;
|
||||
|
||||
string mInitMessage;
|
||||
int mInitResult;
|
||||
|
||||
protected: // Constructors
|
||||
|
||||
//
|
||||
// Constructors
|
||||
//
|
||||
CCommonBase() { Init(_Symbol, (ENUM_TIMEFRAMES)_Period); }
|
||||
CCommonBase(string symbol) { Init(symbol, (ENUM_TIMEFRAMES)_Period); }
|
||||
CCommonBase(int timeframe) { Init(_Symbol, (ENUM_TIMEFRAMES)timeframe); }
|
||||
CCommonBase(ENUM_TIMEFRAMES timeframe) { Init(_Symbol, timeframe); }
|
||||
CCommonBase(string symbol, int timeframe) { Init(symbol, (ENUM_TIMEFRAMES)timeframe); }
|
||||
CCommonBase(string symbol, ENUM_TIMEFRAMES timeframe) { Init(symbol, timeframe); }
|
||||
|
||||
//
|
||||
// Destructors
|
||||
//
|
||||
~CCommonBase() {};
|
||||
|
||||
int Init(string symbol, ENUM_TIMEFRAMES timeframe);
|
||||
|
||||
protected: // Functions
|
||||
|
||||
int InitError(string initMessage, int initResult)
|
||||
{ mInitMessage = initMessage;
|
||||
mInitResult = initResult;
|
||||
return(initResult); }
|
||||
|
||||
public: // Properties
|
||||
|
||||
int InitResult() { return(mInitResult); }
|
||||
string InitMessage() { return(mInitMessage); }
|
||||
|
||||
public: // Functions
|
||||
|
||||
bool TradeAllowed() { return(SymbolInfoInteger(mSymbol, SYMBOL_TRADE_MODE)!=SYMBOL_TRADE_MODE_DISABLED); }
|
||||
|
||||
};
|
||||
|
||||
int CCommonBase::Init(string symbol, ENUM_TIMEFRAMES timeframe) {
|
||||
|
||||
InitError("", INIT_SUCCEEDED);
|
||||
|
||||
mSymbol = symbol;
|
||||
mTimeframe = timeframe;
|
||||
mDigits = (int)SymbolInfoInteger(symbol, SYMBOL_DIGITS);
|
||||
|
||||
return(INIT_SUCCEEDED);
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,193 @@
|
||||
/*
|
||||
ExpertBase.mqh
|
||||
For framework version 1.0
|
||||
|
||||
Copyright 2013-2020, Orchard Forex
|
||||
https://www.orchardforex.com
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include "CommonBase.mqh"
|
||||
#include "Signals/SignalBase.mqh"
|
||||
#include "Trade/Trade.mqh"
|
||||
|
||||
class CExpertBase : public CCommonBase {
|
||||
|
||||
protected:
|
||||
|
||||
int mMagicNumber;
|
||||
string mTradeComment;
|
||||
|
||||
double mVolume;
|
||||
|
||||
datetime mLastBarTime;
|
||||
datetime mBarTime;
|
||||
|
||||
CSignalBase *mEntrySignal;
|
||||
CSignalBase *mExitSignal;
|
||||
|
||||
CTradeCustom Trade;
|
||||
|
||||
private:
|
||||
|
||||
protected:
|
||||
|
||||
virtual bool LoopMain(bool newBar, bool firstTime);
|
||||
|
||||
protected:
|
||||
|
||||
int Init(int magicNumber, string tradeComment);
|
||||
|
||||
public:
|
||||
|
||||
//
|
||||
// Constructors
|
||||
//
|
||||
CExpertBase() : CCommonBase()
|
||||
{ Init(0, ""); }
|
||||
CExpertBase(string symbol, int timeframe, int magicNumber, string tradeComment)
|
||||
: CCommonBase(symbol, timeframe)
|
||||
{ Init(magicNumber, tradeComment); }
|
||||
CExpertBase(string symbol, ENUM_TIMEFRAMES timeframe, int magicNumber, string tradeComment)
|
||||
: CCommonBase(symbol, timeframe)
|
||||
{ Init(magicNumber, tradeComment); }
|
||||
CExpertBase(int magicNumber, string tradeComment)
|
||||
: CCommonBase()
|
||||
{ Init(magicNumber, tradeComment); }
|
||||
|
||||
//
|
||||
// Destructors
|
||||
//
|
||||
~CExpertBase();
|
||||
|
||||
public: // Default properties
|
||||
|
||||
//
|
||||
// Assign the default values to the expert
|
||||
//
|
||||
virtual void SetVolume(double volume) { mVolume = volume; }
|
||||
virtual void SetTradeComment(string comment) { mTradeComment = comment; }
|
||||
virtual void SetMagic(int magicNumber) { mMagicNumber = magicNumber;
|
||||
Trade.SetExpertMagicNumber(magicNumber); }
|
||||
|
||||
public: // Setup
|
||||
|
||||
virtual void AddEntrySignal(CSignalBase *signal) { mEntrySignal=signal; }
|
||||
virtual void AddExitSignal(CSignalBase *signal) { mExitSignal=signal; }
|
||||
|
||||
public: // Event handlers
|
||||
|
||||
virtual int OnInit() { return(InitResult()); }
|
||||
virtual void OnTick();
|
||||
virtual void OnTimer() { return; }
|
||||
virtual double OnTester() { return(0.0); }
|
||||
virtual void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) {};
|
||||
|
||||
#ifdef __MQL5__
|
||||
virtual void OnTrade() { return; }
|
||||
virtual void OnTradeTransaction(const MqlTradeTransaction& trans,
|
||||
const MqlTradeRequest& request,
|
||||
const MqlTradeResult& result)
|
||||
{ return; }
|
||||
virtual void OnTesterInit() { return; }
|
||||
virtual void OnTesterPass() { return; }
|
||||
virtual void OnTesterDeinit() { return; }
|
||||
virtual void OnBookEvent() { return; }
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
CExpertBase::~CExpertBase() {
|
||||
|
||||
}
|
||||
|
||||
int CExpertBase::Init(int magicNumber, string tradeComment) {
|
||||
|
||||
if (mInitResult!=INIT_SUCCEEDED) return(mInitResult);
|
||||
|
||||
mTradeComment = tradeComment;
|
||||
SetMagic(magicNumber);
|
||||
|
||||
mLastBarTime = 0;
|
||||
|
||||
return(INIT_SUCCEEDED);
|
||||
|
||||
}
|
||||
|
||||
void CExpertBase::OnTick(void) {
|
||||
|
||||
if (!TradeAllowed()) return;
|
||||
|
||||
mBarTime = iTime(mSymbol, mTimeframe, 0);
|
||||
|
||||
bool firstTime = (mLastBarTime==0);
|
||||
bool newBar = (mBarTime!=mLastBarTime);
|
||||
|
||||
if (LoopMain(newBar, firstTime)) {
|
||||
mLastBarTime = mBarTime;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
bool CExpertBase::LoopMain(bool newBar,bool firstTime) {
|
||||
|
||||
//
|
||||
// To start I will only trade on a new bar
|
||||
// and not on the first bar after start
|
||||
//
|
||||
if (!newBar) return(true);
|
||||
if (firstTime) return(true);
|
||||
|
||||
//
|
||||
// Update the signals
|
||||
//
|
||||
if (mEntrySignal!=NULL) mEntrySignal.UpdateSignal();
|
||||
if (mEntrySignal!=mExitSignal) {
|
||||
if (mExitSignal!=NULL) mExitSignal.UpdateSignal();
|
||||
}
|
||||
|
||||
//
|
||||
// Should any trades be closed
|
||||
//
|
||||
if (mExitSignal!=NULL) {
|
||||
if (mExitSignal.ExitSignal()==OFX_SIGNAL_BOTH) {
|
||||
Trade.PositionCloseByType(mSymbol, POSITION_TYPE_BUY);
|
||||
Trade.PositionCloseByType(mSymbol, POSITION_TYPE_SELL);
|
||||
} else
|
||||
if (mExitSignal.ExitSignal()==OFX_SIGNAL_BUY) {
|
||||
Trade.PositionCloseByType(mSymbol, POSITION_TYPE_BUY);
|
||||
} else
|
||||
if (mExitSignal.ExitSignal()==OFX_SIGNAL_SELL) {
|
||||
Trade.PositionCloseByType(mSymbol, POSITION_TYPE_SELL);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Should a trade be opened
|
||||
//
|
||||
if (mEntrySignal!=NULL) {
|
||||
if (mEntrySignal.EntrySignal()==OFX_SIGNAL_BOTH) {
|
||||
Trade.Buy(mVolume, mSymbol);
|
||||
Trade.Sell(mVolume, mSymbol);
|
||||
} else
|
||||
if (mEntrySignal.EntrySignal()==OFX_SIGNAL_BUY) {
|
||||
Trade.Buy(mVolume, mSymbol);
|
||||
} else
|
||||
if (mEntrySignal.EntrySignal()==OFX_SIGNAL_SELL) {
|
||||
Trade.Sell(mVolume, mSymbol);
|
||||
}
|
||||
}
|
||||
|
||||
return(true);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
Framework_1.00.mqh
|
||||
|
||||
Copyright 2013-2020, Orchard Forex
|
||||
https://www.orchardforex.com
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _FRAMEWORK_VERSION_
|
||||
|
||||
#define _FRAMEWORK_VERSION_ "1.00"
|
||||
|
||||
#include "CommonBase.mqh"
|
||||
#include "Indicators/AllIndicators.mqh"
|
||||
#include "Signals/AllSignals.mqh"
|
||||
#include "ExpertBase.mqh"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
AllSignals.mqh
|
||||
|
||||
Copyright 2013-2020, Orchard Forex
|
||||
https://www.orchardforex.com
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#include "SignalBase.mqh"
|
||||
|
||||
//
|
||||
// Other signals go here
|
||||
//
|
||||
#include "Crossover/SignalCrossover.mqh"
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
SignalCrossover.mqh
|
||||
For framework version 1.0
|
||||
|
||||
Copyright 2013-2020, Orchard Forex
|
||||
https://www.orchardforex.com
|
||||
|
||||
*/
|
||||
|
||||
#include "../SignalBase.mqh"
|
||||
|
||||
class CSignalCrossover : public CSignalBase {
|
||||
|
||||
private:
|
||||
|
||||
protected: // member variables
|
||||
|
||||
int mIndex1;
|
||||
int mIndex2;
|
||||
|
||||
public: // constructors
|
||||
|
||||
CSignalCrossover(string symbol, ENUM_TIMEFRAMES timeframe,
|
||||
int index1=1, int index2=2)
|
||||
: CSignalBase(symbol, timeframe)
|
||||
{ Init(index1, index2); }
|
||||
CSignalCrossover(int index1=1, int index2=2)
|
||||
: CSignalBase()
|
||||
{ Init(index1, index2); }
|
||||
~CSignalCrossover() { }
|
||||
|
||||
int Init(int index1, int index2);
|
||||
|
||||
public:
|
||||
|
||||
virtual void UpdateSignal();
|
||||
|
||||
};
|
||||
|
||||
int CSignalCrossover::Init(int index1, int index2) {
|
||||
|
||||
if (InitResult()!=INIT_SUCCEEDED) return(InitResult());
|
||||
|
||||
mIndex1 = index1;
|
||||
mIndex2 = index2;
|
||||
|
||||
return(INIT_SUCCEEDED);
|
||||
|
||||
}
|
||||
|
||||
void CSignalCrossover::UpdateSignal() {
|
||||
|
||||
double fast1 = GetIndicatorData(0, mIndex1);
|
||||
double fast2 = GetIndicatorData(0, mIndex2);
|
||||
double slow1 = GetIndicatorData(1, mIndex1);
|
||||
double slow2 = GetIndicatorData(1, mIndex2);
|
||||
|
||||
// There is a less common condition where the fast
|
||||
// indicator touches the slow indicator and then
|
||||
// reverses. With the conditions below this would
|
||||
// appear like a cross.
|
||||
if ( (fast1>slow1) && !(fast2>slow2) ) { // Crossed up
|
||||
mEntrySignal = OFX_SIGNAL_BUY;
|
||||
mExitSignal = OFX_SIGNAL_SELL;
|
||||
} else
|
||||
if ( (fast1<slow1) && !(fast2<slow2) ) { // Crossed down
|
||||
mEntrySignal = OFX_SIGNAL_SELL;
|
||||
mExitSignal = OFX_SIGNAL_BUY;
|
||||
} else {
|
||||
mEntrySignal = OFX_SIGNAL_NONE;
|
||||
mExitSignal = OFX_SIGNAL_NONE;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
SignalBase.mqh
|
||||
|
||||
Copyright 2013-2020, Orchard Forex
|
||||
https://www.orchardforex.com
|
||||
|
||||
*/
|
||||
|
||||
#include "../CommonBase.mqh"
|
||||
#include "../Indicators/IndicatorBase.mqh"
|
||||
|
||||
struct SIndicatorItem {
|
||||
CIndicatorBase *indicator;
|
||||
int bufferNum;
|
||||
};
|
||||
|
||||
enum ENUM_OFX_SIGNAL_DIRECTION {
|
||||
OFX_SIGNAL_NONE = 0,
|
||||
OFX_SIGNAL_BUY = 1,
|
||||
OFX_SIGNAL_SELL = 2,
|
||||
OFX_SIGNAL_BOTH = 3
|
||||
};
|
||||
|
||||
class CSignalBase : public CCommonBase {
|
||||
|
||||
private:
|
||||
|
||||
protected: // member variables
|
||||
|
||||
ENUM_OFX_SIGNAL_DIRECTION mEntrySignal;
|
||||
ENUM_OFX_SIGNAL_DIRECTION mExitSignal;
|
||||
SIndicatorItem mIndicatorList[];
|
||||
|
||||
public: // constructors
|
||||
|
||||
CSignalBase() : CCommonBase()
|
||||
{ Init(); }
|
||||
CSignalBase(string symbol, ENUM_TIMEFRAMES timeframe) : CCommonBase(symbol, timeframe)
|
||||
{ Init(); }
|
||||
~CSignalBase() { }
|
||||
|
||||
int Init();
|
||||
|
||||
public:
|
||||
|
||||
virtual void UpdateSignal() { return; }
|
||||
virtual ENUM_OFX_SIGNAL_DIRECTION EntrySignal() { return(mEntrySignal); }
|
||||
virtual ENUM_OFX_SIGNAL_DIRECTION ExitSignal() { return(mExitSignal); }
|
||||
|
||||
virtual void AddIndicator(CIndicatorBase *indicator, int bufferNum);
|
||||
virtual double GetIndicatorData(int indicatorNum, int index);
|
||||
|
||||
};
|
||||
|
||||
int CSignalBase::Init() {
|
||||
|
||||
if (InitResult()!=INIT_SUCCEEDED) return(InitResult());
|
||||
|
||||
mEntrySignal = OFX_SIGNAL_NONE;
|
||||
mExitSignal = OFX_SIGNAL_NONE;
|
||||
|
||||
return(INIT_SUCCEEDED);
|
||||
|
||||
}
|
||||
|
||||
void CSignalBase::AddIndicator(CIndicatorBase *indicator, int bufferNum) {
|
||||
|
||||
SIndicatorItem indicatorItem = {NULL, 0};
|
||||
indicatorItem.indicator = indicator;
|
||||
indicatorItem.bufferNum = bufferNum;
|
||||
int cnt = ArraySize(mIndicatorList);
|
||||
ArrayResize(mIndicatorList, cnt+1);
|
||||
mIndicatorList[cnt] = indicatorItem;
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
double CSignalBase::GetIndicatorData(int indicatorNum,int index) {
|
||||
|
||||
return(mIndicatorList[indicatorNum].indicator.GetData(mIndicatorList[indicatorNum].bufferNum, index));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
Trade.mqh
|
||||
|
||||
Copyright 2013-2020, Orchard Forex
|
||||
https://www.orchardforex.com
|
||||
|
||||
*/
|
||||
|
||||
#ifdef __MQL4__
|
||||
#include "Trade_mql4.mqh"
|
||||
#endif
|
||||
#ifdef __MQL5__
|
||||
#include "Trade_mql5.mqh"
|
||||
#endif
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
Trade.mqh
|
||||
(For MQL4)
|
||||
|
||||
Copyright 2013-2020, Orchard Forex
|
||||
https://www.orchardforex.com
|
||||
|
||||
*/
|
||||
|
||||
#include "../CommonBase.mqh"
|
||||
|
||||
enum ENUM_POSITION_TYPE {
|
||||
POSITION_TYPE_BUY = ORDER_TYPE_BUY,
|
||||
POSITION_TYPE_SELL = ORDER_TYPE_SELL
|
||||
};
|
||||
|
||||
class CTradeCustom : public CCommonBase {
|
||||
|
||||
private:
|
||||
|
||||
protected: // member variables
|
||||
|
||||
int mMagic; // expert magic number
|
||||
|
||||
public: // constructors
|
||||
|
||||
CTradeCustom();
|
||||
~CTradeCustom();
|
||||
|
||||
public:
|
||||
|
||||
ulong RequestMagic() { return(mMagic); }
|
||||
void SetExpertMagicNumber(const int magic) { mMagic=magic; }
|
||||
|
||||
double BuyPrice(string symbol) { return(SymbolInfoDouble(symbol, SYMBOL_ASK)); }
|
||||
double SellPrice(string symbol) { return(SymbolInfoDouble(symbol, SYMBOL_BID)); }
|
||||
|
||||
bool Buy(const double volume,const string symbol=NULL,double price=0.0,const double sl=0.0,const double tp=0.0,const string comment="");
|
||||
bool Sell(const double volume,const string symbol=NULL,double price=0.0,const double sl=0.0,const double tp=0.0,const string comment="");
|
||||
|
||||
bool PositionCloseByType(const string symbol, ENUM_POSITION_TYPE positionType,const int deviation=ULONG_MAX);
|
||||
|
||||
};
|
||||
|
||||
CTradeCustom::CTradeCustom() {
|
||||
|
||||
mMagic = 0;
|
||||
|
||||
}
|
||||
|
||||
CTradeCustom::~CTradeCustom() {
|
||||
|
||||
}
|
||||
|
||||
bool CTradeCustom::Buy(const double volume,const string symbol=NULL,double price=0.0,const double sl=0.0,const double tp=0.0,const string comment="") {
|
||||
if (price==0.0) price = BuyPrice(symbol);
|
||||
int ticket = OrderSend(symbol, ORDER_TYPE_BUY, volume, price, 0, sl, tp, comment, mMagic);
|
||||
return(ticket>0);
|
||||
}
|
||||
|
||||
bool CTradeCustom::Sell(const double volume,const string symbol=NULL,double price=0.0,const double sl=0.0,const double tp=0.0,const string comment="") {
|
||||
if (price==0.0) price = SellPrice(symbol);
|
||||
int ticket = OrderSend(symbol, ORDER_TYPE_SELL, volume, price, 0, sl, tp, comment, mMagic);
|
||||
return(ticket>0);
|
||||
}
|
||||
|
||||
bool CTradeCustom::PositionCloseByType(const string symbol, ENUM_POSITION_TYPE positionType, const int deviation=ULONG_MAX) {
|
||||
|
||||
int slippage = (deviation==ULONG_MAX) ? 0 : deviation;
|
||||
|
||||
bool result = true;
|
||||
int cnt = OrdersTotal();
|
||||
for (int i = cnt-1; i>=0; i--) {
|
||||
if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {
|
||||
if (OrderSymbol()==symbol && OrderMagicNumber()==mMagic && OrderType()==positionType) {
|
||||
result &= OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), slippage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return(result);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
Trade.mqh
|
||||
(For MQL5)
|
||||
|
||||
Copyright 2013-2020, Orchard Forex
|
||||
https://www.orchardforex.com
|
||||
|
||||
*/
|
||||
|
||||
#include <Trade/Trade.mqh>
|
||||
|
||||
class CTradeCustom : public CTrade {
|
||||
|
||||
private:
|
||||
|
||||
protected: // member variables
|
||||
|
||||
public: // constructors
|
||||
|
||||
public:
|
||||
|
||||
bool PositionCloseByType(const string symbol, ENUM_POSITION_TYPE positionType,const ulong deviation=ULONG_MAX);
|
||||
|
||||
};
|
||||
|
||||
bool CTradeCustom::PositionCloseByType(const string symbol, ENUM_POSITION_TYPE positionType, const ulong deviation=ULONG_MAX) {
|
||||
|
||||
bool result = true;
|
||||
int cnt = PositionsTotal();
|
||||
for (int i = cnt-1; i>=0; i--) {
|
||||
ulong ticket = PositionGetTicket(i);
|
||||
if (PositionSelectByTicket(ticket)) {
|
||||
if (PositionGetString(POSITION_SYMBOL)==symbol && PositionGetInteger(POSITION_TYPE)==positionType && PositionGetInteger(POSITION_MAGIC)==m_magic) {
|
||||
result &= PositionClose(ticket, deviation);
|
||||
}
|
||||
} else {
|
||||
m_result.retcode=TRADE_RETCODE_REJECT;
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
|
||||
return(result);
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user