UTE/Strategy/Strategy.mqh

880 lines
79 KiB
MQL5
Raw Permalink Normal View History

2025-05-30 16:34:43 +02:00
<EFBFBD><EFBFBD>//+------------------------------------------------------------------+
//| Strategy.mqh |
//| Copyright 2016, Vasiliy Sokolov, St-Petersburg, Russia |
//| https://www.mql5.com/ru/users/c-4 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2016, Vasiliy Sokolov."
#property link "https://www.mql5.com/ru/users/c-4"
#property strict
#define SOURCE ("ID " + (string)ExpertMagic() + " " + __FUNCTION__)
#include <Object.mqh>
#include "XML\XMLBase.mqh" // 01>B0 A XML
#include "Logs.mqh" // >38@>20=85
#ifdef __HT__
#include "Position.mqh"
#else
#include "PositionMT5.mqh" // ;0AA >1K:=>25==KE ?>78F89
#endif
#include "TradeEnvironment.mqh" // ;0AA 4;O 45B5:B8@>20=8O 87<5=5=89 B>@3>2>3> >:@C65=8O
#include "NewBarDetector.mqh" // ?@545;8B5;L =>2>3> 10@0
#include "NewTickDetector.mqh" // ?@545;8B5;L =>2>3> B8:0
#include "Series.mqh" // @54>AB02;O5B C4>1=K9 4>ABC? : OHLCV A5@88 40==KE
#include "TradeControl.mqh" // ">@3>2K9 <>4C;L A 4>?>;=8B5;L=K<8 <5B>40<8 :>=B@>;O 70 >B:@KBK<8 ?>78F8O<8
#include "TradeState.mqh" // ">@3>2K9 <>4C;L A 4>?>;=8B5;L=K<8 <5B>40<8 :>=B@>;O 70 >B:@KBK<8 ?>78F8O<8
#include "MoneyManagment.mqh"
#include "PendingOrders.mqh"
#include "Symbol.mqh"
//+------------------------------------------------------------------+
//| ?@545;O5B B8? @K=>G=>3> A>1KB8O. |
//+------------------------------------------------------------------+
enum ENUM_MARKET_EVENT_TYPE
{
MARKET_EVENT_TICK, // @8E>4 =>2>3> B8:0 ?> B5:CI5<C 8=AB@C<5=BC
MARKET_EVENT_BAR_OPEN, // B:@KB85 =>2>3> 10@0 ?> B5:CI5<C 8=AB@C<5=BC
MARKET_EVENT_TIMER, // !@010BK20=85 B09<5@0
MARKET_EVENT_BOOK_EVENT // 7<5=5=85 AB0:0=0 (2 B.G. ?@8E>4 B8:0).
};
//+------------------------------------------------------------------+
//| 0@0<5B@K A>1KB8O, :>B>@>5 ?>2;5:;> 2K7>2 <5B>40. |
//+------------------------------------------------------------------+
struct MarketEvent
{
ENUM_MARKET_EVENT_TYPE type; // "8? A>1KB8O.
ENUM_TIMEFRAMES period; // 5@8>4 3@0D8:0, : :>B>@><C >B=>A8BAO A>1KB85 (B>;L:> 4;O MARKET_EVENT_BAR_OPEN).
string symbol; // 0720=85 8=AB@C<5=B0, ?> :>B>@><C ?@>87>H;> A>1KB85. ;O 2A5E A>1KB89, :@><5
// MARKET_EVENT_BOOK_EVENT, =0720=85 8=AB@C<5=B0 A>>B25BAB2C5B B5:CI5<C 8=AB@C<5=BC.
};
//+------------------------------------------------------------------+
//| A=>2=0O AB0B8AB8:0 ?> >B:@KBK< ?>78F8O< AB@0B5388 (M:75<?;O@0) |
//+------------------------------------------------------------------+
struct PositionsStat
{
int open_buy; // A53> >B:@KBKE ?>78F89 AB@0B5388 =0 ?>:C?:C
int open_sell; // A53> >B:@KBKE ?>78F89 AB@0B5388 =0 ?@>406C
int open_total; // 1I55 :>;8G5AB2> >B:@KBKE ?>78F89 AB@0B5388
int open_complex; // A53> :><?;5:A=KE ?>78F89, :>B>@K5 ?@8=04;560B 40==>9 AB@0B5388
};
//+------------------------------------------------------------------+
//| 07>2K9 :;0AA AB@0B5388-?@>A;>9:8. |
//+------------------------------------------------------------------+
class CStrategy : public CObject
{
private:
MarketEvent m_event; // >A;54=55 8;8 B5:CI55 @K=>G=>5 A>1KB85.
ulong m_last_changed; // >A;54=55 2@5<O 87<5=5=8O B>@3>2>3> >:@C65=8O 2 <8:@>A5:C=40E A <><5=B0 70?CA:0.
uint m_expert_magic; // #=8:0;L=K9 845=B8D8:0B>@ M:A?5@B0.
string m_expert_name; // <O M:A?5@B0.
string m_expert_symbol; // 01>G89 8=AB@C<5=B M:A?5@B0
ENUM_TIMEFRAMES m_timeframe; // "09<D@59< AB@0B5388
ENUM_TRADE_STATE m_trade_state; // ">@3>2>5 A>AB>O=85 M:A?5@B0.
CTradeEnvironment m_environment; // ">@3>2>5 >:@C65=85 ?>@BD5;O.
CArrayObj m_bars_detectors; // !>45@60B >?@545;8B5;8 =>2KE 10@>2.
CArrayObj m_ticks_detectors; // !>45@68B >?@545;8B5;8 =>2KE B8:>2.
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 RecalcStatistic(PositionsStat &positions);
int LastWorkExpDay(MqlDateTime &dt);
protected:
bool m_multi_symbols;
CTradeState m_state; // >72@0I05B B>@3>2>5 A>AB>O=85.
CArrayObj ActivePositions; // !?8A>: )% 0:B82=KE :;0AA8G5A:8E ?>78F89.
CArrayObj ComplexPositions; // !?8A>: )% :><?;5:A=KE ?>78F89 A>AB>OI89 87 <=>65AB20 :;0AA8G5A:8E ?>78F89
PositionsStat positions; // !B0B8AB8:0 ?> ?>78F8O< AB@0B5388
CTradeControl Trade; // ">@3>2K9 :;0AA (A0< CStrategy =5 >1;0405B B>@3>2>9 ;>38:>9).
CArrayObj Modules; // >?>;=8B5;L=K5 <>4C;8 A>?@>2>645=8O
static CLog* Log; // >38@>20=85 M:A?5@B0
string GetCurrentContract(string symbol);
bool CheckCurrentSL(double sl,ENUM_POSITION_TYPE type);
COrdersEnvironment PendingOrders;
/* >4?8A:0 =0 A>1KB8O ">B:@KB85 =>2>3> 10@0" 8 ">1@07>20=85 =>2>3> B8:0" */
bool AddBarOpenEvent(string symbol,ENUM_TIMEFRAMES timeframe);
bool AddTickEvent(string symbol);
void CheckVolumes(void);
/* -:A?5@B 4>;65= A0<>AB>OB5;L=> ?5@5AB>8BL A2>8 8=48:0B>@K ?@8 A<5=5 8=AB@C<5=B0 8 B09<D@59<0,
4;O G53> >= 4>;65= >BA;56820BL A>>B25BAB2CNI85 A>1KB8O
*/
virtual void OnSymbolChanged(string symbol);
virtual void OnTimeframeChanged(ENUM_TIMEFRAMES tf);
/* ">@3>2K5 DC=:F88, :>B>@K5 =5>1E>48<> ?5@5>?@545;8BL */
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);
virtual void SupportPendingBuy(const MarketEvent &event, CPendingOrder* order);
virtual void SupportPendingSell(const MarketEvent &event, CPendingOrder* order);
virtual void OnEvent(const MarketEvent& event);
virtual bool IsTrackEvents(const MarketEvent &event);
int PositionsTotal(ENUM_POSITION_TYPE pos_type, string symbol="", int magic = 0);
int OrdersTotal(ENUM_POSITION_TYPE pos_type, string symbol="", int magic = 0);
int OrdersTotal(ENUM_ORDER_TYPE order_type, string symbol="", int magic = 0);
public:
CMoneyManagment MM; // >4C;L C?@02;5=8O :0?8B0;><
CTrailing* Trailing; // >4C;L C?@02;5=8O B@59;8=3-AB>?>< 4;O 2A5E ?>78F89
CStrategy(void);
CStrategy(string symbol,string exp_name,uint magic,ENUM_TIMEFRAMES tf);
~CStrategy(void);
/*1I85 A2>9AB20*/
static CStrategy *GetStrategy(string name);
CSymbol WS;
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);
/*#?@02;5=85 87 2=5*/
void Buy(double vol);
void Sell(double vol);
/*5@540G0 A>1KB89*/
virtual bool OnInit(void);
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;
};
/* 07<5I5=85 AB0B8G5A:8E ?5@5<5==KE*/
CLog *CStrategy::Log;
//+------------------------------------------------------------------+
//| 07>2K9 :;0AA AB@0B5388-?@>A;>9:8. |
//+------------------------------------------------------------------+
CStrategy::CStrategy(void)
{
m_multi_symbols = false;
m_last_changed = 0;
m_expert_magic = 0;
m_timeframe=PERIOD_CURRENT;
Log=CLog::GetLog();
WS.Name(Symbol());
WS.Period(Period());
}
//+------------------------------------------------------------------+
//| 07>2K9 :;0AA A >1O70B5;L=K<8 ?0@0<5B@0<8. |
//+------------------------------------------------------------------+
CStrategy::CStrategy(string symbol,string exp_name,uint magic,ENUM_TIMEFRAMES tf) : WS(symbol, tf)
{
m_multi_symbols = false;
m_last_changed=0;
Log=CLog::GetLog();
ExpertSymbol(symbol);
ExpertName(exp_name);
Timeframe(tf);
ExpertMagic(magic);
}
//+------------------------------------------------------------------+
//| 8AB@C:B>@. #40;O5B <>4C;L B@59;8=3-AB>?0 2 A;CG05 8A?>;L7>20=8O |
//+------------------------------------------------------------------+
CStrategy::~CStrategy(void)
{
if(CheckPointer(Trailing)!=POINTER_INVALID)
delete Trailing;
}
//+------------------------------------------------------------------+
//| A;8 @01>G89 A8<2>; 87<5=8;AO, M:A?5@BC =5>1E>48<> A0<>AB>OB5;L=>|
//| ?5@5AB@>8BL A2>8 8=48:0B>@K 8 4@C385 2=CB@5==85 40==K5 =0 @01>BC |
//| A MB8< A8<2>;><, 4;O G53> ?5@5>?@545;8BL 40==K9 >1@01>BG8: |
//| 87<5=5=8O A8<2>;0 |
//+------------------------------------------------------------------+
void CStrategy::OnSymbolChanged(string symbol)
{
}
//+------------------------------------------------------------------+
//| A;8 @01>G89 B09<D@59< 87<5=8;AO, M:A?5@BC =5>1E>48<> |
//| A0<>AB>OB5;L=> ?5@5AB@>8BL A2>8 8=48:0B>@K 8 4@C385 2=CB@5==85 |
//| 40==K5 =0 @01>BC A MB8< B09<D@59<><, 4;O G53> ?5@5>?@545;8BL |
//| 40==K9 >1@01>BG8: 87<5=5=8O B09<D@59<0 |
//+------------------------------------------------------------------+
void CStrategy::OnTimeframeChanged(ENUM_TIMEFRAMES tf)
{
}
//+------------------------------------------------------------------+
//| 5@5>?@545;8B5 <5B>4 ?@028;0<8 AB@0B5388, ?@8 2K?>;=5=88 :>B>@KE |
//| =5>1E>48<> >B:@KBL #. ?>78F8N. !0<> >B:@KB85 ?>78F88 B0:65 |
//| =5>1E>48<> 2K?>;=8BL ?@O<> 2 MB>< <5B>45. |
//| IN: |
//| event - AB@C:BC@0, >?8AK20NI0O A>1KB85, ?@8 ?>;CG5=88 |
//| :>B>@>3> ?@>87>H5; 2K7>2 MB>3> <5B>40. |
//+------------------------------------------------------------------+
void CStrategy::InitBuy(const MarketEvent &event)
{
}
//+------------------------------------------------------------------+
//| 5@5>?@545;8B5 <5B>4 ?@028;0<8 AB@0B5388, ?@8 2K?>;=5=88 :>B>@KE |
//| =5>1E>48<> >B:@KBL  "#. ?>78F8N. !0<> >B:@KB85 ?>78F88 B0:65 |
//| =5>1E>48<> 2K?>;=8BL ?@O<> 2 MB>< <5B>45. |
//| IN: |
//| event - AB@C:BC@0, >?8AK20NI0O A>1KB85, ?@8 ?>;CG5=88 |
//| :>B>@>3> ?@>87>H5; 2K7>2 MB>3> <5B>40. |
//+------------------------------------------------------------------+
void CStrategy::InitSell(const MarketEvent &event)
{
}
//+------------------------------------------------------------------+
//| 5@5>?@545;8B5 <5B>4 ?@028;0<8 AB@0B5388, ?@8 2K?>;=5=88 :>B>@KE |
//| =5>1E>48<> >B:@KBL !#. (8;8 0@18B@06=CN) ?>78F8N. |
//| !0<> >B:@KB85 ?>78F88 B0:65 =5>1E>48<> 2K?>;=8BL |
//| ?@O<> 2 MB>< <5B>45. |
//| IN: |
//| event - AB@C:BC@0, >?8AK20NI0O A>1KB85, ?@8 ?>;CG5=88 |
//| :>B>@>3> ?@>87>H5; 2K7>2 MB>3> <5B>40. |
//+------------------------------------------------------------------+
void CStrategy::InitComplexPos(const MarketEvent &event)
{
}
//+------------------------------------------------------------------+
//| 5@5>?@545;8B5 <5B>4 ?@028;0<8 AB@0B5388, ?@8 2K?>;=5=88 :>B>@KE |
//| =5>1E>48<> 70:@KBL #. ?>78F8N, ?5@540==CN 2 :0G5AB25 2B>@>3>|
//| ?0@0<5B@0. !0<> 70:@KB85 ?>78F88 B0:65 =5>1E>48<> 2K?>;=8BL |
//| ?@O<> 2 MB>< <5B>45. |
//| IN: |
//| event - AB@C:BC@0, >?8AK20NI0O A>1KB85, ?@8 ?>;CG5=88 |
//| :>B>@>3> ?@>87>H5; 2K7>2 MB>3> <5B>40. |
//| pos - ?>78F8O, C?@02;5=85 :>B>@>9 B@51C5BAO ?@>8725AB8. |
//+------------------------------------------------------------------+
void CStrategy::SupportBuy(const MarketEvent &event,CPosition *pos)
{
}
//+------------------------------------------------------------------+
//| 5@5>?@545;8B5 <5B>4 ?@028;0<8 AB@0B5388, ?@8 2K?>;=5=88 :>B>@KE |
//| =5>1E>48<> 70:@KBL  "#. ?>78F8N,?5@540==CN 2 :0G5AB25 2B>@>3>|
//| ?0@0<5B@0. !0<> 70:@KB85 ?>78F88 B0:65 =5>1E>48<> 2K?>;=8BL |
//| ?@O<> 2 MB>< <5B>45. |
//| IN: |
//| event - AB@C:BC@0, >?8AK20NI0O A>1KB85, ?@8 ?>;CG5=88 |
//| :>B>@>3> ?@>87>H5; 2K7>2 MB>3> <5B>40. |
//| pos - ?>78F8O, C?@02;5=85 :>B>@>9 B@51C5BAO ?@>8725AB8. |
//+------------------------------------------------------------------+
void CStrategy::SupportSell(const MarketEvent &event,CPosition *pos)
{
}
//+------------------------------------------------------------------+
//| 5@5>?@545;8B5 40==K9 <5B>4 4;O ?>A;54>20B5;L=>3> A>?@>2>645=8O |
//| >B;>65==>3> >@45@0 =0 ?>:C?:C |
//| IN: |
//| event - AB@C:BC@0, >?8AK20NI0O A>1KB85, ?@8 ?>;CG5=88 |
//| :>B>@>3> ?@>87>H5; 2K7>2 MB>3> <5B>40. |
//| order - ?>78F8O, C?@02;5=85 :>B>@>9 B@51C5BAO ?@>8725AB8. |
//+------------------------------------------------------------------+
void CStrategy::SupportPendingBuy(const MarketEvent &event, CPendingOrder *order)
{
}
//+------------------------------------------------------------------+
//| 5@5>?@545;8B5 40==K9 <5B>4 4;O ?>A;54>20B5;L=>3> A>?@>2>645=8O |
//| >B;>65==>3> >@45@0 =0 ?@>406C |
//| IN: |
//| event - AB@C:BC@0, >?8AK20NI0O A>1KB85, ?@8 ?>;CG5=88 |
//| :>B>@>3> ?@>87>H5; 2K7>2 MB>3> <5B>40. |
//| order - ?>78F8O, C?@02;5=85 :>B>@>9 B@51C5BAO ?@>8725AB8. |
//+------------------------------------------------------------------+
void CStrategy::SupportPendingSell(const MarketEvent &event, CPendingOrder *order)
{
}
//+------------------------------------------------------------------+
//| 1I55 A>1KB85 OnEvent. K7K205BAO ?@8 ?>;CG5=88 ;N1>3> A>1KB8O |
//| =57028A8<> >B B>@3>2>3> @568<0 8 =0AB@>5: M:A?5@B0. |
//+------------------------------------------------------------------+
void CStrategy::OnEvent(const MarketEvent &event)
{
}
//+------------------------------------------------------------------+
//| BD8;LB@>2K205B ?>ABC?0NI85 A>1KB8O. A;8 ?5@540==>5 A>1KB85 |
//| =5 >1@010BK205BAO AB@0B53859, 2>72@0I05B ;>6L, 5A;8 >1@010BK20- |
//| 5BAO - 2>72@0I05B 8AB8=C. |
//+------------------------------------------------------------------+
bool CStrategy::IsTrackEvents(const MarketEvent &event)
{
//1@010BK205< B>;L:> >B:@KB85 =>2>3> 10@0 =0 @01>G5< 8=AB@C<5=B5 8 B09<D@59<5
if(event.type != MARKET_EVENT_BAR_OPEN)return false;
if(event.period != Timeframe())return false;
if(event.symbol != ExpertSymbol())return false;
return true;
}
//+------------------------------------------------------------------+
//| 5;538@C5B 4>G5@=59 AB@0B5388 ?0@A8=3 55 A?5F8D8G5A:8E |
//| ?0@0<5B@>2, >1=0@C65==KE 2 A5:F88 <Params> |
//+------------------------------------------------------------------+
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;
}
//+------------------------------------------------------------------+
//| #AB0=02;8205B C=8:0;L=K9 845=BD8:0B>@ M:A?5@B0. |
//+------------------------------------------------------------------+
void CStrategy::ExpertMagic(uint ExpertMagic)
{
m_expert_magic=ExpertMagic;
Trade.SetExpertMagicNumber(m_expert_magic);
}
//+------------------------------------------------------------------+
//| >72@0I05B C=8:0;L=K9 845=B8D8:0B>@ M:A?5@B0. |
//+------------------------------------------------------------------+
uint CStrategy::ExpertMagic(void)
{
return m_expert_magic;
}
//+------------------------------------------------------------------+
//| >72@0I05B <O M:A?5@B0 (8<O M:A?5@B0 4>;6=> 1KBL ?@5420@8B5;L=> |
//| CAB0=>2;5==> A0<8< M:A?5@B>< A ?><>ILN >4=>8<5==>3> <5B>40). |
//+------------------------------------------------------------------+
string CStrategy::ExpertName(void)
{
return m_expert_name;
}
//+------------------------------------------------------------------+
//| ! ?><>ILN MB>3> <5B>40 M:A?5@B CAB0=02;8205B A2>5 8<O. |
//+------------------------------------------------------------------+
void CStrategy::ExpertName(string name)
{
m_expert_name=name;
}
//+------------------------------------------------------------------+
//| >72@0I05B ?>;=>5 (C=8:0;L=>5 8<O M:A?5@B0). |
//| (-B>B <5B>4 =5>1E>48<> ?5@5>?@545;8BL 2 ?@>872>4=>< :;0AA5) |
//+------------------------------------------------------------------+
string CStrategy::ExpertNameFull(void)
{
return ExpertName();
}
//+------------------------------------------------------------------+
//| >72@0I05B @01>G89 8=AB@C<5=B M:A?5@B0. |
//+------------------------------------------------------------------+
string CStrategy::ExpertSymbol(void)
{
if(m_expert_symbol==NULL || m_expert_symbol=="")
return _Symbol;
return m_expert_symbol;
}
//+------------------------------------------------------------------+
//| #AB0=02;8205B @01>G89 8=AB@C<5=B M:A?5@B0. |
//+------------------------------------------------------------------+
void CStrategy::ExpertSymbol(string symbol)
{
m_expert_symbol=GetCurrentContract(symbol);
OnSymbolChanged(m_expert_symbol);
WS.Name(symbol);
}
//+------------------------------------------------------------------+
//| K7K205BAO <5=5465@>< AB@0B5389 ?@8 =0ABC?;5=88 A8AB5<=>3> |
//| A>1KB8O '=>2K9 B8:'. |
//+------------------------------------------------------------------+
void CStrategy::OnTick(void)
{
NewTickDetect();
NewBarsDetect();
}
//+------------------------------------------------------------------+
//| -B> A>1KB85 2K7K205BAO ?@8 4>102;5=88 AB@0B5388 2 A?8A>: |
//| AB@0B5389. >4@07C<5205BAO, GB> 2 <><5=B 2K7>20 MB>9 DC=:F88, |
//| 2A5 107>2K5 ?0@0<5B@K M:A?5@B0, B0:85 :0: =0720=85 A8<>2>;0, |
//| <038G5A:89 =><5@ 8 B09D@5< 1C4CB CAB0=>2;5=K.  M:A?5@B A<>65B |
//| A:>=D83C@8@>20BL 2 MB>< <5B>45 A2>8 2=CB@5==85 40==K5. |
//|  A;CG05, 5A;8 OnInit AB@0B5388 25@=5B false, AB@0B538O =5 1C45B |
//| 4>102;5=0 2 A?8A>:. |
//+------------------------------------------------------------------+
bool CStrategy::OnInit(void)
{
return true;
}
//+------------------------------------------------------------------+
//| K7K205BAO <5=5465@>< AB@0B5389 ?@8 =0ABC?;5=88 A8AB5<=>3> |
//| A>1KB8O 'OnTimer'. |
//+------------------------------------------------------------------+
void CStrategy::OnTimer(void)
{
m_event.symbol=Symbol();
m_event.type=MARKET_EVENT_TIMER;
m_event.period=(ENUM_TIMEFRAMES)Period();
OnEvent(m_event);
CallSupport(m_event);
CallInit(m_event);
NewTickDetect();
NewBarsDetect();
}
//+------------------------------------------------------------------+
//| K7K205BAO <5=5465@>< AB@0B5389 ?@8 =0ABC?;5=88 A8AB5<=>3> |
//| A>1KB8O 'OnBookEvent'. |
//+------------------------------------------------------------------+
void CStrategy::OnBookEvent(string symbol)
{
m_event.symbol=symbol;
m_event.type=MARKET_EVENT_BOOK_EVENT;
m_event.period=PERIOD_CURRENT;
OnEvent(m_event);
CallSupport(m_event);
CallInit(m_event);
NewTickDetect();
NewBarsDetect();
}
//+------------------------------------------------------------------+
//| >:C?05B >B 8<5=8 M:A?5@B0 >1J5< vol |
//+------------------------------------------------------------------+
void CStrategy::Buy(double vol)
{
Trade.Buy(vol,ExpertSymbol(),"hand buy");
}
//+------------------------------------------------------------------+
//| @>405< >B 8<5=8 M:A?5@B0 >1J5< vol |
//+------------------------------------------------------------------+
void CStrategy::Sell(double vol)
{
Trade.Sell(vol,ExpertSymbol(),"hand sell");
}
//+------------------------------------------------------------------+
//| >72@0I05B B5:CI55 B>@3>2>5 A>AB>O=85 M:A?5@B0. |
//+------------------------------------------------------------------+
ENUM_TRADE_STATE CStrategy::TradeState(void)
{
return m_trade_state;
}
//+------------------------------------------------------------------+
//| #AB0=02;8205B B5:CI55 B>@3>2>5 A>AB>O=85 M:A?5@B0. |
//+------------------------------------------------------------------+
void CStrategy::TradeState(ENUM_TRADE_STATE state)
{
if(state!=m_state.GetTradeState())
{
m_state.SetTradeState(D'00:00', D'23:59', ALL_DAYS_OF_WEEK, state);
string text="The mode of the current strategy has been changed to "+EnumToString(m_state.GetTradeState())+
". The changes will come into force at receipt of new events";
CMessage *msg=new CMessage(MESSAGE_INFO,SOURCE,text);
Log.AddMessage(msg);
}
}
//+------------------------------------------------------------------+
//| K7K205B ;>38:C >B:@KB8O ?>78F88 ?@8 CA;>288, GB> B>@3>2>5 |
//| A>AB>O=85 O2=> =5 70?@5I05B MB>3> 45;0BL. |
//+------------------------------------------------------------------+
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);
}
//+------------------------------------------------------------------+
//| K7K205B ;>38:C A>?@>2>645=8O ?>78F89 ?@8 CA;>288, GB> B>@3>2>5 |
//| A>AB>O=85 =5 @02=> TRADE_WAIT. |
//+------------------------------------------------------------------+
void CStrategy::CallSupport(const MarketEvent &event)
{
m_trade_state=m_state.GetTradeState();
if(m_trade_state == TRADE_WAIT)return;
SpyEnvironment();
// #?@02;5=85 0:B82=K<8 ?>78F8O<8
for(int i=ActivePositions.Total()-1; i>=0; i--)
{
CPosition *pos=ActivePositions.At(i);
if(pos.ExpertMagic()!=m_expert_magic)continue;
if(!m_multi_symbols && pos.Symbol()!=ExpertSymbol())continue;
if(CheckPointer(Trailing)!=POINTER_INVALID)
{
if(CheckPointer(pos.Trailing)==POINTER_INVALID)
{
pos.Trailing = Trailing.Copy();
pos.Trailing.SetPosition(pos);
}
pos.Trailing.Modify();
if(!pos.IsActive())
continue;
}
if(pos.Direction()==POSITION_TYPE_BUY)
SupportBuy(event,pos);
else
SupportSell(event,pos);
if(m_trade_state==TRADE_STOP && pos.IsActive())
ExitByStopRegim(pos);
}
// #40;5=85 >B;>65==KE >@45@>2 ?@8 A<5=5 @568<0
if(PendingOrders.Total() > 0 && (m_trade_state == TRADE_STOP ||
m_trade_state == TRADE_BUY_ONLY || m_trade_state == TRADE_SELL_ONLY))
{
for(int p = PendingOrders.Total()-1; p >= 0; p--)
{
CPendingOrder* pend = PendingOrders.GetOrder(p);
if(!pend.IsMain(ExpertSymbol(), ExpertMagic()))continue;
bool needDelete = m_trade_state == TRADE_STOP;
// SELL_ONLY - C40;O5< >B;>65==K5 >@45@0 =0 ?>:C?:C
if(!needDelete)
{
needDelete = m_trade_state == TRADE_SELL_ONLY &&
(pend.Type() == ORDER_TYPE_BUY_STOP ||
pend.Type() == ORDER_TYPE_BUY_LIMIT);
}
// BUY_ONLY - C40;O5< >B;>65==K5 >@45@0 =0 ?@>406C
if(!needDelete)
{
needDelete = m_trade_state == TRADE_BUY_ONLY &&
(pend.Type() == ORDER_TYPE_SELL_STOP ||
pend.Type() == ORDER_TYPE_SELL_LIMIT);
}
if(needDelete)
pend.Delete();
}
}
for(int i = PendingOrders.Total()-1; i >= 0; i--)
{
CPendingOrder* order = PendingOrders.GetOrder(i);
if(order.ExpertMagic()!=m_expert_magic)continue;
if(order.Direction() == POSITION_TYPE_BUY)
SupportPendingBuy(event, order);
else
SupportPendingSell(event, order);
}
}
//+------------------------------------------------------------------+
//| BA;568205B 87<5=5=85 B>@3>2>3> >:@C65=8O. |
//+------------------------------------------------------------------+
void CStrategy::SpyEnvironment(void)
{
if(m_environment.ChangeEnvironment())
{
//printf(ExpertNameFull()+". Trading environment has changed. Rebuild the environment");
RebuildPositions();
RecalcStatistic(positions);
m_environment.RememberEnvironment();
}
}
//+------------------------------------------------------------------+
//| 5@5AG8BK205B AB0B8AB8:C ?>78F89 8 70?>;=O5B A>>B25BAB2CNICN |
//| AB@C:BC@C. |
//+------------------------------------------------------------------+
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;
if(cpos.Symbol() != ExpertSymbol())continue;
pos.open_total+=1;
if(cpos.Direction()==POSITION_TYPE_BUY)
pos.open_buy++;
else
pos.open_sell++;
}
}
//+------------------------------------------------------------------+
//| 5@5AB@08205B A?8A:8 ?>78F89. |
//+------------------------------------------------------------------+
#ifdef __HT__
void CStrategy::RebuildPositions(void)
{
ActivePositions.Clear();
for(int i = 0; i < TransactionsTotal(); i++)
{
if(!TransactionSelect(i))continue;
if(TransactionType() != TRANS_HEDGE_POSITION)continue;
CPosition* pos = new CPosition();
ActivePositions.Add(pos);
}
}
#else
void CStrategy::RebuildPositions(void)
{
ActivePositions.Clear();
ENUM_ACCOUNT_MARGIN_MODE mode=(ENUM_ACCOUNT_MARGIN_MODE)AccountInfoInteger(ACCOUNT_MARGIN_MODE);
if(mode!=ACCOUNT_MARGIN_MODE_RETAIL_HEDGING)
{
for(int i=0; i<PositionsTotal(); i++)
{
string symbol=PositionGetSymbol(i);
PositionSelect(symbol);
CPosition *pos=new CPosition();
ActivePositions.Add(pos);
}
}
else
{
for(int i=0; i<PositionsTotal(); i++)
{
ulong ticket=PositionGetTicket(i);
PositionSelectByTicket(ticket);
CPosition *pos=new CPosition();
ActivePositions.Add(pos);
}
}
}
#endif
//+------------------------------------------------------------------+
//| #AB0=02;8205B @01>G89 B09<D@5< AB@0B5388. |
//+------------------------------------------------------------------+
void CStrategy::Timeframe(ENUM_TIMEFRAMES period)
{
m_timeframe=period;
OnTimeframeChanged(m_timeframe);
WS.Period(period);
}
//+------------------------------------------------------------------+
//| >72@0I05B @01>G89 B09<D@59< AB@0B5388. |
//+------------------------------------------------------------------+
ENUM_TIMEFRAMES CStrategy::Timeframe(void)
{
return m_timeframe;
}
//+------------------------------------------------------------------+
//| 0:@K205B ?>78F8N ?> @568<C Stop. |
//+------------------------------------------------------------------+
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.");
//A;8 70:@KB85 ?>78F88 =5 C40;>AL, B> >1 MB>< =0?8H5B A0< <5B>4 pos.CloseAtMarket.
}
//+------------------------------------------------------------------+
//| ?@545;O5B =0ABC?;5=85 =>2KE 10@>2 8 35=5@8@C5B A>>B25BAB2CNI55 |
//| A>1KB85 4;O M:A?5@B0. |
//+------------------------------------------------------------------+
void CStrategy::NewBarsDetect(void)
{
if(m_bars_detectors.Total()==0)
AddBarOpenEvent(ExpertSymbol(),Timeframe());
for(int i=0; i<m_bars_detectors.Total(); i++)
{
CBarDetector *bar=m_bars_detectors.At(i);
if(bar.IsNewBar())
{
m_event.period = bar.Timeframe();
m_event.symbol = bar.Symbol();
m_event.type=MARKET_EVENT_BAR_OPEN;
SpyEnvironment();
OnEvent(m_event);
CallSupport(m_event);
CallInit(m_event);
}
}
}
//+------------------------------------------------------------------+
//| 5B5:B8@C5B ?>O2;5=85 =>2KE B8:>2 =0 <C;LB88=AB@C<5=B0E. |
//+------------------------------------------------------------------+
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();
SpyEnvironment();
OnEvent(m_event);
CallSupport(m_event);
CallInit(m_event);
}
}
}
//+------------------------------------------------------------------+
//| >4?8AK205B M:A?5@B0 =0 ?>;CG5=85 A>1KB8O >B:@KB8O =>2>3> 10@0 |
//| ?> 8=AB@C<5=BC symbol 8 B09<D@59<C timframe. A;8 M:A?5@B C65 |
//| ?>4?8A0= =0 40==>5 A>1KB85, <5B>4 25@=5B ;>6L. A;8 ?>4?8A:0 |
//| ?@>H;0 CA?5H=>, 2>72@0I05BAO 8AB8=0. |
//+------------------------------------------------------------------+
bool CStrategy::AddBarOpenEvent(string symbol,ENUM_TIMEFRAMES timeframe)
{
for(int i=0; i<m_bars_detectors.Total(); i++)
{
CBarDetector *d=m_bars_detectors.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_detectors.Add(bar);
}
//+------------------------------------------------------------------+
//| >4?8AK205B M:A?5@B0 =0 ?>;CG5=85 A>1KB8O "=>2K9 B8:", |
//| ?> 8=AB@C<5=BC symbol. A;8 M:A?5@B C65 ?>4?8A0= =0 40==>5 |
//| A>1KB85, <5B>4 25@=5B ;>6L. A;8 ?>4?8A:0 |
//| ?@>H;0 CA?5H=>, 2>72@0I05BAO 8AB8=0. |
//+------------------------------------------------------------------+
bool CStrategy::AddTickEvent(string symbol)
{
for(int i=0; i<m_ticks_detectors.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);
}
//+------------------------------------------------------------------+
//| >72@0I05B ?>;=>5 8<O B5:CI53> :>=B@0:B0 4;O FORTS, :>B>@>5 |
//| A>>B25BAB2C5B ?5@540==><C A8<2>;C. 0?@8<5@, 5A;8 B5:CI0O 40B0 |
//| @02=0 02.10.2015, 0 ?5@540==K9 A8<2>; @025= "Si", <5B>4 25@=5B |
//| =0720=85 1;8609H53> :>=B@0:B0: Si-12.15. |
//| 5@54 2>7@0B>< 8<5=8 8=AB@C<5=B0 ?@>25@O5BAO 53> D0:B8G5A:0O |
//| 4>ABC?=>ABL 4;O B>@3>2;8, 8 5A;8 >= =54>ABC?5=, 2>72@0I05BAO |
//| NULL.  ?@>B82=>< A;CG05 2>72@0I05BAO ?>;=>5 =0720=85 :>=B@0:B0. |
//+------------------------------------------------------------------+
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;
}
//@>1C5< A35=5@8@>20BL 8=AB@C<5=B 8 ?>;CG8BL ?> =5<C 40==K5
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;
}
//+------------------------------------------------------------------+
//| 5@5>?@545;O5B A@02=5=85 ?> <0468:C |
//+------------------------------------------------------------------+
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;
}
//+------------------------------------------------------------------+
//| >72@0I05B >1I55 :>;8G5AB2> ?>78F89 ?> 7040==><C :@8B5@8N |
//+------------------------------------------------------------------+
int CStrategy::PositionsTotal(ENUM_POSITION_TYPE pos_type, string symbol="", int magic = 0)
{
int total = 0;
for(int i = 0; i < ActivePositions.Total(); i++)
{
CPosition* pos = ActivePositions.At(i);
if(magic != 0 && magic != pos.ExpertMagic())continue;
if(symbol != "" && symbol != pos.Symbol())continue;
if(pos.Direction() != pos_type)continue;
total++;
}
return total;
}
//+------------------------------------------------------------------+
//| >72@0I05B >1I55 :>;8G5AB2> >B;>65==KE >@45@>2, GL5 =0?@02;5=85 |
//| @02=> 7040==><C |
//+------------------------------------------------------------------+
int CStrategy::OrdersTotal(ENUM_POSITION_TYPE pos_type, string symbol="", int magic = 0)
{
int total = 0;
for(int i = 0; i < PendingOrders.Total(); i++)
{
CPendingOrder* order = PendingOrders.GetOrder(i);
if(magic != 0 && magic != order.ExpertMagic())continue;
if(symbol != "" && symbol != order.Symbol())continue;
if(order.Direction() != pos_type)continue;
total++;
}
return total;
}
//+------------------------------------------------------------------+
//| >72@0I05B >1I55 :>;8G5AB2> >B;>65==KE >@45@>2, G59 B8? |
//| @025= 7040==><C |
//+------------------------------------------------------------------+
int CStrategy::OrdersTotal(ENUM_ORDER_TYPE order_type, string symbol="", int magic = 0)
{
int total = 0;
for(int i = 0; i < PendingOrders.Total(); i++)
{
CPendingOrder* order = PendingOrders.GetOrder(i);
if(magic != 0 && magic != order.ExpertMagic())continue;
if(symbol != "" && symbol != order.Symbol())continue;
if(order.Type() != order_type)continue;
total++;
}
return total;
}
#include "StrategiesList.mqh"
//+------------------------------------------------------------------+