Files
All-MQL5-code/Include/Strategy/Strategy.mqh
T
Pierre8rTeam d2a192666b Commit
2018-06-23 11:25:42 +02:00

685 lines
62 KiB
Plaintext
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//+------------------------------------------------------------------+
//| Strategy.mqh |
//| Copyright 2015, Vasiliy Sokolov. |
//| http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2015, Vasiliy Sokolov."
#property link "http://www.mql5.com"
#property strict
#define SOURCE ("ID " + (string)ExpertMagic() + " " + __FUNCTION__)
#include <Object.mqh>
#include <XML\XMLBase.mqh> // Work with XML
#include "Logs.mqh" // Logging
#include "PositionMT5.mqh" // A class of common positions
#include "TradeEnvironment.mqh" // A class for detecting changes in trading environment
#include "NewBarDetector.mqh" // New bar detector
#include "NewTickDetector.mqh" // New tick detector
#include "Series.mqh" // Provides easy access to OHLCV of the data series
#include "TradeControl.mqh" // Trading module with additional methods of control of open positions
#include "TradeState.mqh" // Trading module with additional methods of control of open positions
#include "MoneyManagment.mqh"
//+------------------------------------------------------------------+
//| Defiles the type of market event. |
//+------------------------------------------------------------------+
enum ENUM_MARKET_EVENT_TYPE
{
MARKET_EVENT_TICK, // Arrival of a new tick for the current symbol
MARKET_EVENT_BAR_OPEN, // Opening of a new bar of the current instrument
MARKET_EVENT_TIMER, // Timer
MARKET_EVENT_BOOK_EVENT // Depth of Market change (including tick arrival).
};
//+------------------------------------------------------------------+
//| Parameters of the event that caused method call. |
//+------------------------------------------------------------------+
struct MarketEvent
{
ENUM_MARKET_EVENT_TYPE type; // Event type.
ENUM_TIMEFRAMES period; // Timeframe of the chart the event belongs to (only for MARKET_EVENT_BAR_OPEN).
string symbol; // Name of the symbol on which the event occurred. For all events except
// MARKET_EVENT_BOOK_EVENT, symbol name corresponds to the current instrument.
};
//+------------------------------------------------------------------+
//| Main statistics of open positions of the strategy (instance) |
//+------------------------------------------------------------------+
struct PositionsStat
{
int open_buy; // Total number of open positions of a Buy strategy
int open_sell; // Total number of open positions of a Sell strategy
int open_total; // Total number of open positions of the strategy
int open_complex; // The total number of complex positions belonging to this strategy
};
//+------------------------------------------------------------------+
//| Basic class of the layer strategy. |
//+------------------------------------------------------------------+
class CStrategy : public CObject
{
private:
MarketEvent m_event; // Last or current market event.
ulong m_last_changed; // Time of the last change of trading environment in micro seconds since launch.
uint m_expert_magic; // A unique ID of the Expert Advisor.
string m_expert_name; // Expert Advisor name.
string m_expert_symbol; // The symbol the EA is running on
ENUM_TIMEFRAMES m_timeframe; // The timeframe of the strategy
ENUM_TRADE_STATE m_trade_state; // EA's trading state.
CTradeState m_state; // Returns the trading state.
CTradeEnvironment m_environment; // The trading environment of the portfolio.
CArrayObj m_bars_detecors; // Contain new bar detectors.
CArrayObj m_ticks_detectors; // Contain new tick detectors.
void RebuildPositions(void);
void CallInit(const MarketEvent &event);
void CallSupport(const MarketEvent &event);
void SpyEnvironment(void);
virtual void ExitByStopRegim(CPosition *pos);
void NewBarsDetect(void);
void NewTickDetect(void);
void InitSeries(string symbol,ENUM_TIMEFRAMES period);
void RecalcStatistic(PositionsStat &positions);
int LastWorkExpDay(MqlDateTime &dt);
protected:
CArrayObj ActivePositions; // The list of COMMON active classical positions.
CArrayObj ComplexPositions; // The list of COMMON complex positions consisting of many classical positions
PositionsStat positions; // Statistics of the strategy's positions
CTradeControl Trade; // Trading class (CStrategy has no trading logic).
CArrayObj Modules; // Additional support modules
static CLog* Log; // EA logs
/* MQL4-type access to quotes */
CTime Time;
COpen Open;
CHigh High;
CLow Low;
CClose Close;
CVolume Volume;
string GetCurrentContract(string symbol);
bool CheckCurrentSL(double sl,ENUM_POSITION_TYPE type);
/* Subscription to events "opening of a new bar" and "formation of a new tick" */
bool AddBarOpenEvent(string symbol,ENUM_TIMEFRAMES timeframe);
bool AddTickEvent(string symbol);
void CheckVolumes(void);
/* The EA must redraw its indicators when the symbol and timeframe change,
for this it should monitor appropriate events
*/
virtual void OnSymbolChanged(string symbol);
virtual void OnTimeframeChanged(ENUM_TIMEFRAMES tf);
/* Trading functions to override */
virtual void InitBuy(const MarketEvent &event);
virtual void InitSell(const MarketEvent &event);
virtual void InitComplexPos(const MarketEvent &event);
virtual void SupportBuy(const MarketEvent &event,CPosition *pos);
virtual void SupportSell(const MarketEvent &event,CPosition *pos);
public:
CMoneyManagment MM; // Money management module
CStrategy(void);
CStrategy(string symbol,string exp_name,uint magic,ENUM_TIMEFRAMES tf);
/*Common properties*/
static CStrategy *GetStrategy(string name);
virtual bool ParseXmlParams(CXmlElement *params);
uint ExpertMagic(void);
void ExpertMagic(uint ExpertMagic);
string ExpertName(void);
void ExpertName(string name);
virtual string ExpertNameFull(void);
string ExpertSymbol();
void ExpertSymbol(string symbol);
void Timeframe(ENUM_TIMEFRAMES period);
ENUM_TIMEFRAMES Timeframe(void);
ENUM_TRADE_STATE TradeState(void);
void TradeState(ENUM_TRADE_STATE state);
/*External management*/
void Buy(double vol);
void Sell(double vol);
/*Passing events*/
void OnTick(void);
void OnTimer(void);
void OnBookEvent(string symbol);
virtual void OnTradeTransaction(const MqlTradeTransaction &trans,
const MqlTradeRequest &request,
const MqlTradeResult &result){;}
virtual int Compare(const CObject *node,const int mode=0) const;
};
/*Placing static variables*/
CLog *CStrategy::Log;
//+------------------------------------------------------------------+
//| Basic class of the layer strategy. |
//+------------------------------------------------------------------+
CStrategy::CStrategy(void)
{
m_last_changed = 0;
m_expert_magic = 0;
m_timeframe=PERIOD_CURRENT;
Log=CLog::GetLog();
}
//+------------------------------------------------------------------+
//| Basic class with the required parameters. |
//+------------------------------------------------------------------+
CStrategy::CStrategy(string symbol,string exp_name,uint magic,ENUM_TIMEFRAMES tf)
{
m_last_changed=0;
Log=CLog::GetLog();
ExpertSymbol(symbol);
ExpertName(exp_name);
Timeframe(tf);
ExpertMagic(magic);
}
//+------------------------------------------------------------------+
//| If the basic symbol has changed, the Expert Advisor needs to |
//| redraw its indicators and other internal data to work with |
//| this symbol, for this it needs to override this handler |
//| of symbol change |
//+------------------------------------------------------------------+
void CStrategy::OnSymbolChanged(string symbol)
{
}
//+------------------------------------------------------------------+
//| If the working timeframe has changed, the Expert Advisor needs |
//| to redraw its indicators and other internal data to work |
//| with this timeframe, for which it needs to override this |
//| handler of timeframe change |
//+------------------------------------------------------------------+
void CStrategy::OnTimeframeChanged(ENUM_TIMEFRAMES tf)
{
}
//+------------------------------------------------------------------+
//| Override the method using the strategy rule, which being met |
//| a LONG position should be opened. The position opening should |
//| also be performed straight in this method |
//| IN: |
//| event - the structure described the event, upon receipt |
//| of which the method was called. |
//+------------------------------------------------------------------+
void CStrategy::InitBuy(const MarketEvent &event)
{
}
//+------------------------------------------------------------------+
//| Override the method using the strategy rule, which being met |
//| a SHORT position should be opened. The position opening should |
//| also be performed straight in this method |
//| IN: |
//| event - the structure described the event, upon receipt |
//| of which the method was called. |
//+------------------------------------------------------------------+
void CStrategy::InitSell(const MarketEvent &event)
{
}
//+------------------------------------------------------------------+
//| Override the method using the strategy rule, which being met |
//| a COMPLEX (or arbitrage) position should be opened. |
//| The opening of the position should be performed |
//| right in this method |
//| IN: |
//| event - the structure described the event, upon receipt |
//| of which the method was called. |
//+------------------------------------------------------------------+
void CStrategy::InitComplexPos(const MarketEvent &event)
{
}
//+------------------------------------------------------------------+
//| Override the method using the strategy rule, which being met |
//| you should close the LONG position passed as the second |
//| parameter. The closing of position should also be performed |
//| right in this method |
//| IN: |
//| event - the structure described the event, upon receipt |
//| of which the method was called. |
//| pos - the position that you need to manage. |
//+------------------------------------------------------------------+
void CStrategy::SupportBuy(const MarketEvent &event,CPosition *pos)
{
}
//+------------------------------------------------------------------+
//| Override the method using the strategy rule, which being met |
//| you should close the SHORT position passed as the second |
//| parameter. The closing of position should also be performed |
//| right in this method |
//| IN: |
//| event - the structure described the event, upon receipt |
//| of which the method was called. |
//| pos - the position that you need to manage. |
//+------------------------------------------------------------------+
void CStrategy::SupportSell(const MarketEvent &event,CPosition *pos)
{
}
//+------------------------------------------------------------------+
//| Delegates the child strategy to parse its specific |
//| parameters found in the <Params> section |
//+------------------------------------------------------------------+
bool CStrategy::ParseXmlParams(CXmlElement *xmlParams)
{
string text="Found specific xml-settings, but "+ExpertName()+" strategy does not handle them. Override the method ParseXmlParams";
CMessage *msg=new CMessage(MESSAGE_WARNING,SOURCE,text);
Log.AddMessage(msg);
return false;
}
//+------------------------------------------------------------------+
//| Sets a unique identifier of the Expert Advisor. |
//+------------------------------------------------------------------+
void CStrategy::ExpertMagic(uint ExpertMagic)
{
m_expert_magic=ExpertMagic;
Trade.SetExpertMagicNumber(m_expert_magic);
}
//+------------------------------------------------------------------+
//| Returns the unique identifier of the EA. |
//+------------------------------------------------------------------+
uint CStrategy::ExpertMagic(void)
{
return m_expert_magic;
}
//+------------------------------------------------------------------+
//| Returns the name of the Expert Advisor (the name must be |
//| previously set by the EA using the appropriate method). |
//+------------------------------------------------------------------+
string CStrategy::ExpertName(void)
{
return m_expert_name;
}
//+------------------------------------------------------------------+
//| Using this method, the EA sets its name. |
//+------------------------------------------------------------------+
void CStrategy::ExpertName(string name)
{
m_expert_name=name;
}
//+------------------------------------------------------------------+
//| Returns the full (unique) name of the EA. |
//| (This method must be overridden in the derived class) |
//+------------------------------------------------------------------+
string CStrategy::ExpertNameFull(void)
{
return ExpertName();
}
//+------------------------------------------------------------------+
//| Returns the working symbol of the EA. |
//+------------------------------------------------------------------+
string CStrategy::ExpertSymbol(void)
{
if(m_expert_symbol==NULL || m_expert_symbol=="")
return _Symbol;
return m_expert_symbol;
}
//+------------------------------------------------------------------+
//| Sets the working symbol of the EA. |
//+------------------------------------------------------------------+
void CStrategy::ExpertSymbol(string symbol)
{
m_expert_symbol=GetCurrentContract(symbol);
InitSeries(symbol,Timeframe());
OnSymbolChanged(m_expert_symbol);
}
//+------------------------------------------------------------------+
//| Called by the strategy manager upon the system event |
//| 'new tick'. |
//+------------------------------------------------------------------+
void CStrategy::OnTick(void)
{
NewTickDetect();
NewBarsDetect();
}
//+------------------------------------------------------------------+
//| Called by the strategy manager upon the system event |
//| 'OnTimer'. |
//+------------------------------------------------------------------+
void CStrategy::OnTimer(void)
{
m_event.symbol=Symbol();
m_event.type=MARKET_EVENT_TIMER;
m_event.period=(ENUM_TIMEFRAMES)Period();
CallSupport(m_event);
CallInit(m_event);
NewTickDetect();
NewBarsDetect();
}
//+------------------------------------------------------------------+
//| Called by the strategy manager upon the system event |
//| 'OnBookEvent'. |
//+------------------------------------------------------------------+
void CStrategy::OnBookEvent(string symbol)
{
m_event.symbol=symbol;
m_event.type=MARKET_EVENT_BOOK_EVENT;
m_event.period=PERIOD_CURRENT;
CallSupport(m_event);
CallInit(m_event);
NewTickDetect();
NewBarsDetect();
}
//+------------------------------------------------------------------+
//| On behalf of the EA, buy the volume of vol |
//+------------------------------------------------------------------+
void CStrategy::Buy(double vol)
{
Trade.Buy(vol,ExpertSymbol(),"hand buy");
}
//+------------------------------------------------------------------+
//| On behalf of the EA, sell the volume of vol |
//+------------------------------------------------------------------+
void CStrategy::Sell(double vol)
{
Trade.Sell(vol,ExpertSymbol(),"hand sell");
}
//+------------------------------------------------------------------+
//| Returns the current trading state of the EA.   |
//+------------------------------------------------------------------+
ENUM_TRADE_STATE CStrategy::TradeState(void)
{
return m_trade_state;
}
//+------------------------------------------------------------------+
//| Sets the current trading state of the EA.   |
//+------------------------------------------------------------------+
void CStrategy::TradeState(ENUM_TRADE_STATE state)
{
if(state!=m_trade_state)
{
m_trade_state=state;
string text="The mode of the current strategy has been changed to "+EnumToString(m_trade_state)+
". The changes will come into force at receipt of new events";
CMessage *msg=new CMessage(MESSAGE_INFO,SOURCE,text);
Log.AddMessage(msg);
}
}
//+------------------------------------------------------------------+
//| Calls position opening logic provided that the trading |
//| state does not explicitly restrict this. |
//+------------------------------------------------------------------+
void CStrategy::CallInit(const MarketEvent &event)
{
m_trade_state=m_state.GetTradeState();
if(m_trade_state == TRADE_STOP)return;
if(m_trade_state == TRADE_WAIT)return;
if(m_trade_state == TRADE_NO_NEW_ENTRY)return;
SpyEnvironment();
InitComplexPos(event);
if(m_trade_state==TRADE_BUY_AND_SELL || m_trade_state==TRADE_BUY_ONLY)
InitBuy(event);
if(m_trade_state==TRADE_BUY_AND_SELL || m_trade_state==TRADE_SELL_ONLY)
InitSell(event);
}
//+------------------------------------------------------------------+
//| Calls position maintenance logic provided that the trading |
//| state isn't equal to TRADE_WAIT |
//+------------------------------------------------------------------+
void CStrategy::CallSupport(const MarketEvent &event)
{
m_trade_state=m_state.GetTradeState();
if(m_trade_state == TRADE_WAIT)return;
SpyEnvironment();
for(int i=ActivePositions.Total()-1; i>=0; i--)
{
CPosition *pos=ActivePositions.At(i);
if(pos.ExpertMagic()!=m_expert_magic)continue;
if(pos.Symbol()!=ExpertSymbol())continue;
if(pos.Direction()==POSITION_TYPE_BUY)
SupportBuy(event,pos);
else
SupportSell(event,pos);
if(m_trade_state==TRADE_STOP && pos.IsActive())
ExitByStopRegim(pos);
}
}
//+------------------------------------------------------------------+
//| Tracks changes in the trading environment. |
//+------------------------------------------------------------------+
void CStrategy::SpyEnvironment(void)
{
if(m_environment.ChangeEnvironment())
{
printf(ExpertNameFull()+". Trading environment has changed. Rebuild the environment");
RebuildPositions();
RecalcStatistic(positions);
m_environment.RememberEnvironment();
}
}
//+------------------------------------------------------------------+
//| Recalculates statistics of positions and fills in appropriate |
//| structure. |
//+------------------------------------------------------------------+
void CStrategy::RecalcStatistic(PositionsStat &pos)
{
pos.open_buy=0;
pos.open_sell=0;
pos.open_total=0;
pos.open_complex=0;
for(int i=0; i<ActivePositions.Total(); i++)
{
CPosition *cpos=ActivePositions.At(i);
if(cpos.ExpertMagic()!=ExpertMagic())continue;
pos.open_total+=1;
if(cpos.Direction()==POSITION_TYPE_BUY)
pos.open_buy++;
else
pos.open_sell++;
}
}
//+------------------------------------------------------------------+
//| Rearranges lists of positions |
//+------------------------------------------------------------------+
void CStrategy::RebuildPositions(void)
{
ActivePositions.Clear();
for(int i=0; i<PositionsTotal(); i++)
{
string symbol=PositionGetSymbol(i);
PositionSelect(symbol);
CPosition *pos=new CPosition();
ActivePositions.Add(pos);
}
}
//+------------------------------------------------------------------+
//| Sets working timeframe of the strategy. |
//+------------------------------------------------------------------+
void CStrategy::Timeframe(ENUM_TIMEFRAMES period)
{
m_timeframe=period;
InitSeries(ExpertSymbol(),m_timeframe);
OnTimeframeChanged(m_timeframe);
}
//+------------------------------------------------------------------+
//| Returns working timeframe of strategy. |
//+------------------------------------------------------------------+
ENUM_TIMEFRAMES CStrategy::Timeframe(void)
{
return m_timeframe;
}
//+------------------------------------------------------------------+
//| Sets OHLCV series for the current instrument and timeframe. |
//+------------------------------------------------------------------+
void CStrategy::InitSeries(string symbol,ENUM_TIMEFRAMES period)
{
Time.Symbol(symbol);
Time.Timeframe(period);
Open.Symbol(symbol);
Open.Timeframe(period);
High.Symbol(symbol);
High.Timeframe(period);
Low.Symbol(symbol);
Low.Timeframe(period);
Close.Symbol(symbol);
Close.Timeframe(period);
Volume.Symbol(symbol);
Volume.Timeframe(period);
}
//+------------------------------------------------------------------+
//| Closes position by the Stop mode. |
//+------------------------------------------------------------------+
void CStrategy::ExitByStopRegim(CPosition *pos)
{
ResetLastError();
CMessage *msg_info=new CMessage(MESSAGE_INFO,ExpertName(),"Try close position #"+(string)pos.ID()+" by stop regim...");
Log.AddMessage(msg_info);
bool res=pos.CloseAtMarket("Exit by StopRegim");
if(res)
CMessage *msg=new CMessage(MESSAGE_INFO,ExpertName(),"Out of position #"+(string)pos.ID()+" successfully completed.");
// If position closure failed, the pos.CloseAtMarket method will notify if this.
}
//+------------------------------------------------------------------+
//| Detects emergence of a new bar and generates an appropriate |
//| event for the EA. |
//+------------------------------------------------------------------+
void CStrategy::NewBarsDetect(void)
{
if(m_bars_detecors.Total()==0)
AddBarOpenEvent(ExpertSymbol(),Timeframe());
for(int i=0; i<m_bars_detecors.Total(); i++)
{
CBarDetector *bar=m_bars_detecors.At(i);
if(bar.IsNewBar())
{
m_event.period = bar.Timeframe();
m_event.symbol = bar.Symbol();
m_event.type=MARKET_EVENT_BAR_OPEN;
CallSupport(m_event);
CallInit(m_event);
}
}
}
//+------------------------------------------------------------------+
//| Detects the arrival of new ticks of multi-instruments. |
//+------------------------------------------------------------------+
void CStrategy::NewTickDetect(void)
{
if(m_ticks_detectors.Total()==0)
AddTickEvent(ExpertSymbol());
for(int i=0; i<m_ticks_detectors.Total(); i++)
{
CTickDetector *tick=m_ticks_detectors.At(i);
if(tick.IsNewTick())
{
m_event.period=PERIOD_CURRENT;
m_event.type=MARKET_EVENT_TICK;
m_event.symbol=tick.Symbol();
CallSupport(m_event);
CallInit(m_event);
}
}
}
//+------------------------------------------------------------------+
//| Subscribes the EA to receive an event of new bar opening |
//| for the specified 'symbol' and 'timeframe'. If the EA is already |
//| subscribed to the event, method returns false. If subscription |
//| successful, returns true. |
//+------------------------------------------------------------------+
bool CStrategy::AddBarOpenEvent(string symbol,ENUM_TIMEFRAMES timeframe)
{
for(int i=0; i<m_bars_detecors.Total(); i++)
{
CBarDetector *d=m_bars_detecors.At(i);
if(d.Symbol()==symbol && d.Timeframe()==timeframe)
{
string text="You are already subscribed to the opening bars of said symbol and timeframe.";
CMessage *message=new CMessage(MESSAGE_INFO,__FUNCTION__,text);
return false;
}
}
datetime time[];
if(CopyTime(symbol,timeframe,0,3,time)==0)
{
string text="A symbol "+symbol+" that you want to monitor is not available in the terminal."+
" Make sure that the name of the instrument and its timeframe"+EnumToString(timeframe)+" are correct.";
CMessage *message=new CMessage(MESSAGE_WARNING,__FUNCTION__,text);
return false;
}
CBarDetector *bar=new CBarDetector(symbol,timeframe);
return m_bars_detecors.Add(bar);
}
//+------------------------------------------------------------------+
//| Subscribes the EA to receive the 'new tick' event |
//| for a selected symbol. If the EA is already subscribed to the |
//| event, method returns false. If subscription |
//| successful, returns true. |
//+------------------------------------------------------------------+
bool CStrategy::AddTickEvent(string symbol)
{
for(int i=0; i<m_bars_detecors.Total(); i++)
{
CTickDetector *d=m_ticks_detectors.At(i);
if(d.Symbol()==symbol)
{
string text="You are already subscribed to new tick event of said symbol.";
CMessage *message=new CMessage(MESSAGE_WARNING,__FUNCTION__,text);
return false;
}
}
datetime time[];
if(CopyTime(symbol,PERIOD_D1,0,3,time)==0)
{
string text="A symbol "+symbol+" that you want to monitor is not available in the terminal."+
" Make sure that the name of the instrument are correct.";
CMessage *message=new CMessage(MESSAGE_WARNING,__FUNCTION__,text);
return false;
}
CTickDetector *tick=new CTickDetector(symbol);
return m_ticks_detectors.Add(tick);
}
//+------------------------------------------------------------------+
//| Returns the full name of the current contract for FORTS that |
//| corresponds to the passed symbol. E.g., if the current date is |
//| is 02.10.2015, and the passed symbol is "Si", the method returns |
//| the name of nearest contract: Si-12.15. |
//| Before returning symbol name, it checks its actual availability |
//| for trading; and if it is unavailable, the method returns
//| NULL. Otherwise returns the full name of the contract. |
//+------------------------------------------------------------------+
string CStrategy::GetCurrentContract(string symbol)
{
datetime time[];
if(SymbolInfoInteger(symbol,SYMBOL_SELECT))
return symbol;
MqlDateTime dt={0};
TimeCurrent(dt);
int mon=0;
int year=0;
if((dt.mon==12 && dt.day>=14) || dt.mon==1 || dt.mon==2 || (dt.mon==3 && dt.day<14))
{
mon=3;
year=dt.year+1;
}
if((dt.mon==3 && dt.day>=14) || dt.mon==4 || dt.mon==5 || (dt.mon==6 && dt.day<14))
{
mon=6;
year=dt.year;
}
if((dt.mon==6 && dt.day>=14) || dt.mon==7 || dt.mon==8 || (dt.mon==9 && dt.day<14))
{
mon=9;
year=dt.year;
}
if((dt.mon==9 && dt.day>=14) || dt.mon==10 || dt.mon==11 || (dt.mon==12 && dt.day<14))
{
mon=12;
year=dt.year;
}
if(mon==0 || year==0)
{
string text="The current date is outside the execution of futures";
CMessage *msg=new CMessage(MESSAGE_ERROR,__FUNCTION__,text);
return NULL;
}
//Let's try to generate a symbol and receive its details
string full_symbol=symbol+"-"+(string)mon+"."+StringSubstr((string)year,2);
if(!SymbolInfoInteger(full_symbol,SYMBOL_SELECT))
{
string text="Symbol "+symbol+" is not not selected in market watch. Check the name of the instrument";
CMessage *msg=new CMessage(MESSAGE_ERROR,__FUNCTION__,text);
Log.AddMessage(msg);
return NULL;
}
return full_symbol;
}
//+------------------------------------------------------------------+
//| Overrides magic based comparison |
//+------------------------------------------------------------------+
int CStrategy::Compare(const CObject *obj,const int mode=0)const
{
const CStrategy *str=obj;
if(m_expert_magic > str.m_expert_magic)return 1;
if(m_expert_magic < str.m_expert_magic)return -1;
return 0;
}
#include <Strategy\StrategyFactory.mqh>
//+------------------------------------------------------------------+