| //+------------------------------------------------------------------+
|
| //| Expert.mqh |
|
| //| Copyright 2000-2025, MetaQuotes Ltd. |
|
| //| https://www.mql5.com |
|
| //+------------------------------------------------------------------+
|
| #include "ExpertBase.mqh"
|
| #include "ExpertTrade.mqh"
|
| #include "ExpertSignal.mqh"
|
| #include "ExpertMoney.mqh"
|
| #include "ExpertTrailing.mqh"
|
| //+------------------------------------------------------------------+
|
| //| enumerations |
|
| //+------------------------------------------------------------------+
|
| //--- flags of expected events
|
| enum ENUM_TRADE_EVENTS
|
| {
|
| TRADE_EVENT_NO_EVENT =0, // no expected events
|
| TRADE_EVENT_POSITION_OPEN =0x1, // flag of expecting the "opening of position" event
|
| TRADE_EVENT_POSITION_VOLUME_CHANGE=0x2, // flag of expecting of the "modification of position volume" event
|
| TRADE_EVENT_POSITION_MODIFY =0x4, // flag of expecting of the "modification of stop order of position" event
|
| TRADE_EVENT_POSITION_CLOSE =0x8, // flag of expecting of the "closing of position" event
|
| TRADE_EVENT_POSITION_STOP_TAKE =0x10, // flag of expecting of the "triggering of stop order of position"
|
| TRADE_EVENT_ORDER_PLACE =0x20, // flag of expecting of the "placing of pending order" event
|
| TRADE_EVENT_ORDER_MODIFY =0x40, // flag of expecting of the "modification of pending order" event
|
| TRADE_EVENT_ORDER_DELETE =0x80, // flag of expecting of the "deletion of pending order" event
|
| TRADE_EVENT_ORDER_TRIGGER =0x100 // flag of expecting of the "triggering of pending order" event
|
| };
|
| //+------------------------------------------------------------------+
|
| //| Macro definitions. |
|
| //+------------------------------------------------------------------+
|
| //--- check the expectation of event
|
| #define IS_WAITING_POSITION_OPENED ((m_waiting_event&TRADE_EVENT_POSITION_OPEN)!=0)
|
| #define IS_WAITING_POSITION_VOLUME_CHANGED ((m_waiting_event&TRADE_EVENT_POSITION_VOLUME_CHANGE)!=0)
|
| #define IS_WAITING_POSITION_MODIFIED ((m_waiting_event&TRADE_EVENT_POSITION_MODIFY)!=0)
|
| #define IS_WAITING_POSITION_CLOSED ((m_waiting_event&TRADE_EVENT_POSITION_CLOSE)!=0)
|
| #define IS_WAITING_POSITION_STOP_TAKE ((m_waiting_event&TRADE_EVENT_POSITION_STOP_TAKE)!=0)
|
| #define IS_WAITING_ORDER_PLACED ((m_waiting_event&TRADE_EVENT_ORDER_PLACE)!=0)
|
| #define IS_WAITING_ORDER_MODIFIED ((m_waiting_event&TRADE_EVENT_ORDER_MODIFY)!=0)
|
| #define IS_WAITING_ORDER_DELETED ((m_waiting_event&TRADE_EVENT_ORDER_DELETE)!=0)
|
| #define IS_WAITING_ORDER_TRIGGERED ((m_waiting_event&TRADE_EVENT_ORDER_TRIGGER)!=0)
|
| //+------------------------------------------------------------------+
|
| //| Class CExpert. |
|
| //| Purpose: Base class expert advisor. |
|
| //| Derives from class CExpertBase. |
|
| //+------------------------------------------------------------------+
|
| class CExpert : public CExpertBase
|
| {
|
| protected:
|
| int m_period_flags; // timeframe flags (as visible flags)
|
| int m_max_orders; // max number of orders (include position)
|
| MqlDateTime m_last_tick_time; // time of last tick
|
| datetime m_expiration; // time expiration order
|
| //--- history info
|
| int m_pos_tot; // number of open positions
|
| int m_deal_tot; // number of deals in history
|
| int m_ord_tot; // number of pending orders
|
| int m_hist_ord_tot; // number of orders in history
|
| datetime m_beg_date; // start date of history
|
| //---
|
| int m_waiting_event; // flags of expected trade events
|
| //--- trading objects
|
| CExpertTrade *m_trade; // trading object
|
| CExpertSignal *m_signal; // trading signals object
|
| CExpertMoney *m_money; // money manager object
|
| CExpertTrailing *m_trailing; // trailing stops object
|
| bool m_check_volume; // check and decrease trading volume before OrderSend
|
| //--- indicators
|
| CIndicators m_indicators; // indicator collection to fast recalculations
|
| //--- market objects
|
| CPositionInfo m_position; // position info object
|
| COrderInfo m_order; // order info object
|
| //--- flags of handlers
|
| bool m_on_tick_process; // OnTick will be processed (default true)
|
| bool m_on_trade_process; // OnTrade will be processed (default false)
|
| bool m_on_timer_process; // OnTimer will be processed (default false)
|
| bool m_on_chart_event_process; // OnChartEvent will be processed (default false)
|
| bool m_on_book_event_process; // OnBookEvent will be processed (default false)
|
|
|
| public:
|
| CExpert(void);
|
| ~CExpert(void);
|
| //--- initialization
|
| bool Init(string symbol,ENUM_TIMEFRAMES period,bool every_tick,ulong magic=0);
|
| void Magic(ulong value);
|
| void CheckVolumeBeforeTrade(const bool flag) { m_check_volume=flag; }
|
| //--- initialization trading objects
|
| virtual bool InitSignal(CExpertSignal *signal=NULL);
|
| virtual bool InitTrailing(CExpertTrailing *trailing=NULL);
|
| virtual bool InitMoney(CExpertMoney *money=NULL);
|
| virtual bool InitTrade(ulong magic,CExpertTrade *trade=NULL);
|
| //--- deinitialization
|
| virtual void Deinit(void);
|
| //--- methods of setting adjustable parameters
|
| void OnTickProcess(bool value) { m_on_tick_process=value; }
|
| void OnTradeProcess(bool value) { m_on_trade_process=value; }
|
| void OnTimerProcess(bool value) { m_on_timer_process=value; }
|
| void OnChartEventProcess(bool value) { m_on_chart_event_process=value; }
|
| void OnBookEventProcess(bool value) { m_on_book_event_process=value; }
|
| int MaxOrders(void) const { return(m_max_orders); }
|
| void MaxOrders(int value) { m_max_orders=value; }
|
| //--- methods of access to protected data
|
| CExpertSignal *Signal(void) const { return(m_signal); }
|
| //--- method of verification of settings
|
| virtual bool ValidationSettings();
|
| //--- method of creating the indicator and timeseries
|
| virtual bool InitIndicators(CIndicators *indicators=NULL);
|
| //--- event handlers
|
| virtual void OnTick(void);
|
| virtual void OnTrade(void);
|
| virtual void OnTimer(void);
|
| virtual void OnChartEvent(const int id,const long &lparam,const double &dparam,const string &sparam);
|
| virtual void OnBookEvent(const string &symbol);
|
|
|
| protected:
|
| //--- initialization
|
| virtual bool InitParameters(void) { return(true); }
|
| //--- deinitialization
|
| virtual void DeinitTrade(void);
|
| virtual void DeinitSignal(void);
|
| virtual void DeinitTrailing(void);
|
| virtual void DeinitMoney(void);
|
| virtual void DeinitIndicators(void);
|
| //--- refreshing
|
| virtual bool Refresh(void);
|
| //--- position select depending on netting or hedging
|
| virtual bool SelectPosition(void);
|
| //--- processing (main method)
|
| virtual bool Processing(void);
|
| //--- trade open positions check
|
| virtual bool CheckOpen(void);
|
| virtual bool CheckOpenLong(void);
|
| virtual bool CheckOpenShort(void);
|
| //--- trade open positions processing
|
| virtual bool OpenLong(double price,double sl,double tp);
|
| virtual bool OpenShort(double price,double sl,double tp);
|
| //--- trade reverse positions check
|
| virtual bool CheckReverse(void);
|
| virtual bool CheckReverseLong(void);
|
| virtual bool CheckReverseShort(void);
|
| //--- trade reverse positions processing
|
| virtual bool ReverseLong(double price,double sl,double tp);
|
| virtual bool ReverseShort(double price,double sl,double tp);
|
| //--- trade close positions check
|
| virtual bool CheckClose(void);
|
| virtual bool CheckCloseLong(void);
|
| virtual bool CheckCloseShort(void);
|
| //--- trade close positions processing
|
| virtual bool CloseAll(double lot);
|
| virtual bool Close(void);
|
| virtual bool CloseLong(double price);
|
| virtual bool CloseShort(double price);
|
| //--- trailing stop check
|
| virtual bool CheckTrailingStop(void);
|
| virtual bool CheckTrailingStopLong(void);
|
| virtual bool CheckTrailingStopShort(void);
|
| //--- trailing stop processing
|
| virtual bool TrailingStopLong(double sl,double tp);
|
| virtual bool TrailingStopShort(double sl,double tp);
|
| //--- trailing order check
|
| virtual bool CheckTrailingOrderLong(void);
|
| virtual bool CheckTrailingOrderShort(void);
|
| //--- trailing order processing
|
| virtual bool TrailingOrderLong(double delta);
|
| virtual bool TrailingOrderShort(double delta);
|
| //--- delete order check
|
| virtual bool CheckDeleteOrderLong(void);
|
| virtual bool CheckDeleteOrderShort(void);
|
| //--- delete order processing
|
| virtual bool DeleteOrders(void);
|
| virtual bool DeleteOrdersLong(void);
|
| virtual bool DeleteOrdersShort(void);
|
| virtual bool DeleteOrder(void);
|
| virtual bool DeleteOrderLong(void);
|
| virtual bool DeleteOrderShort(void);
|
| //--- lot for trade
|
| double LotOpenLong(double price,double sl);
|
| double LotOpenShort(double price,double sl);
|
| double LotReverse(double sl);
|
| double LotCheck(double volume,double price,ENUM_ORDER_TYPE order_type);
|
| //--- methods of working with trade history
|
| void PrepareHistoryDate(void);
|
| void HistoryPoint(bool from_check_trade=false);
|
| bool CheckTradeState(void);
|
| //--- set/reset waiting events
|
| void WaitEvent(ENUM_TRADE_EVENTS event) { m_waiting_event|=event; }
|
| void NoWaitEvent(ENUM_TRADE_EVENTS event) { m_waiting_event&=~event; }
|
| //--- trade events
|
| virtual bool TradeEventPositionStopTake(void) { return(true); }
|
| virtual bool TradeEventOrderTriggered(void) { return(true); }
|
| virtual bool TradeEventPositionOpened(void) { return(true); }
|
| virtual bool TradeEventPositionVolumeChanged(void) { return(true); }
|
| virtual bool TradeEventPositionModified(void) { return(true); }
|
| virtual bool TradeEventPositionClosed(void) { return(true); }
|
| virtual bool TradeEventOrderPlaced(void) { return(true); }
|
| virtual bool TradeEventOrderModified(void) { return(true); }
|
| virtual bool TradeEventOrderDeleted(void) { return(true); }
|
| virtual bool TradeEventNotIdentified(void) { return(true); }
|
| //--- timeframe functions
|
| void TimeframeAdd(ENUM_TIMEFRAMES period);
|
| int TimeframesFlags(MqlDateTime &time);
|
| };
|
| //+------------------------------------------------------------------+
|
| //| Constructor |
|
| //+------------------------------------------------------------------+
|
| CExpert::CExpert(void) : m_period_flags(0),
|
| m_expiration(0),
|
| m_pos_tot(0),
|
| m_deal_tot(0),
|
| m_ord_tot(0),
|
| m_hist_ord_tot(0),
|
| m_beg_date(0),
|
| m_trade(NULL),
|
| m_signal(NULL),
|
| m_money(NULL),
|
| m_trailing(NULL),
|
| m_check_volume(false),
|
| m_on_tick_process(true),
|
| m_on_trade_process(false),
|
| m_on_timer_process(false),
|
| m_on_chart_event_process(false),
|
| m_on_book_event_process(false),
|
| m_max_orders(1)
|
| {
|
| m_other_symbol =true;
|
| m_other_period =true;
|
| m_adjusted_point =10;
|
| m_period =WRONG_VALUE;
|
| m_last_tick_time.min=-1;
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Destructor |
|
| //+------------------------------------------------------------------+
|
| CExpert::~CExpert(void)
|
| {
|
| Deinit();
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Initialization and checking for input parameters |
|
| //+------------------------------------------------------------------+
|
| bool CExpert::Init(string symbol,ENUM_TIMEFRAMES period,bool every_tick,ulong magic)
|
| {
|
| //--- returns false if the EA is initialized on a symbol/timeframe different from the current one
|
| if(symbol!=::Symbol() || period!=::Period())
|
| {
|
| PrintFormat(__FUNCTION__+": wrong symbol or timeframe (must be %s:%s)",symbol,EnumToString(period));
|
| return(false);
|
| }
|
| //--- initialize common information
|
| if(m_symbol==NULL)
|
| {
|
| if((m_symbol=new CSymbolInfo)==NULL)
|
| return(false);
|
| }
|
| if(!m_symbol.Name(symbol))
|
| return(false);
|
| m_period =period;
|
| m_every_tick=every_tick;
|
| m_magic =magic;
|
| SetMarginMode();
|
| if(every_tick)
|
| TimeframeAdd(WRONG_VALUE); // add all periods
|
| else
|
| TimeframeAdd(period); // add specified period
|
| //--- tuning for 3 or 5 digits
|
| int digits_adjust=(m_symbol.Digits()==3 || m_symbol.Digits()==5) ? 10 : 1;
|
| m_adjusted_point=m_symbol.Point()*digits_adjust;
|
| //--- initializing objects expert
|
| if(!InitTrade(magic))
|
| {
|
| Print(__FUNCTION__+": error initialization trade object");
|
| return(false);
|
| }
|
| if(!InitSignal())
|
| {
|
| Print(__FUNCTION__+": error initialization signal object");
|
| return(false);
|
| }
|
| if(!InitTrailing())
|
| {
|
| Print(__FUNCTION__+": error initialization trailing object");
|
| return(false);
|
| }
|
| if(!InitMoney())
|
| {
|
| Print(__FUNCTION__+": error initialization money object");
|
| return(false);
|
| }
|
| if(!InitParameters())
|
| {
|
| Print(__FUNCTION__+": error initialization parameters");
|
| return(false);
|
| }
|
| //--- initialization for working with trade history
|
| PrepareHistoryDate();
|
| HistoryPoint();
|
| //--- primary initialization is successful, pass to the phase of tuning
|
| m_init_phase=INIT_PHASE_TUNING;
|
| //--- ok
|
| return(true);
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Sets magic number for object and its dependent objects |
|
| //+------------------------------------------------------------------+
|
| void CExpert::Magic(ulong value)
|
| {
|
| if(m_trade!=NULL)
|
| m_trade.SetExpertMagicNumber(value);
|
| if(m_signal!=NULL)
|
| m_signal.Magic(value);
|
| if(m_money!=NULL)
|
| m_money.Magic(value);
|
| if(m_trailing!=NULL)
|
| m_trailing.Magic(value);
|
| //---
|
| CExpertBase::Magic(value);
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Initialization trade object |
|
| //+------------------------------------------------------------------+
|
| bool CExpert::InitTrade(ulong magic,CExpertTrade *trade=NULL)
|
| {
|
| //--- удаляем существующий объект
|
| if(m_trade!=NULL)
|
| delete m_trade;
|
| //---
|
| if(trade==NULL)
|
| {
|
| if((m_trade=new CExpertTrade)==NULL)
|
| return(false);
|
| }
|
| else
|
| m_trade=trade;
|
| //--- tune trade object
|
| m_trade.SetSymbol(GetPointer(m_symbol));
|
| m_trade.SetExpertMagicNumber(magic);
|
| m_trade.SetMarginMode();
|
| //--- set default deviation for trading in adjusted points
|
| m_trade.SetDeviationInPoints((ulong)(3*m_adjusted_point/m_symbol.Point()));
|
| //--- ok
|
| return(true);
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Initialization signal object |
|
| //+------------------------------------------------------------------+
|
| bool CExpert::InitSignal(CExpertSignal *signal)
|
| {
|
| if(m_signal!=NULL)
|
| delete m_signal;
|
| //---
|
| if(signal==NULL)
|
| {
|
| if((m_signal=new CExpertSignal)==NULL)
|
| return(false);
|
| }
|
| else
|
| m_signal=signal;
|
| //--- initializing signal object
|
| if(!m_signal.Init(GetPointer(m_symbol),m_period,m_adjusted_point))
|
| return(false);
|
| m_signal.EveryTick(m_every_tick);
|
| m_signal.Magic(m_magic);
|
| //--- ok
|
| return(true);
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Initialization trailing object |
|
| //+------------------------------------------------------------------+
|
| bool CExpert::InitTrailing(CExpertTrailing *trailing)
|
| {
|
| if(m_trailing!=NULL)
|
| delete m_trailing;
|
| //---
|
| if(trailing==NULL)
|
| {
|
| if((m_trailing=new CExpertTrailing)==NULL)
|
| return(false);
|
| }
|
| else
|
| m_trailing=trailing;
|
| //--- initializing trailing object
|
| if(!m_trailing.Init(GetPointer(m_symbol),m_period,m_adjusted_point))
|
| return(false);
|
| m_trailing.EveryTick(m_every_tick);
|
| m_trailing.Magic(m_magic);
|
| //--- ok
|
| return(true);
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Initialization money object |
|
| //+------------------------------------------------------------------+
|
| bool CExpert::InitMoney(CExpertMoney *money)
|
| {
|
| if(m_money!=NULL)
|
| delete m_money;
|
| //---
|
| if(money==NULL)
|
| {
|
| if((m_money=new CExpertMoney)==NULL)
|
| return(false);
|
| }
|
| else
|
| m_money=money;
|
| //--- initializing money object
|
| if(!m_money.Init(GetPointer(m_symbol),m_period,m_adjusted_point))
|
| return(false);
|
| m_money.EveryTick(m_every_tick);
|
| m_money.Magic(m_magic);
|
| //--- ok
|
| return(true);
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Validation settings |
|
| //+------------------------------------------------------------------+
|
| bool CExpert::ValidationSettings(void)
|
| {
|
| if(!CExpertBase::ValidationSettings())
|
| return(false);
|
| //--- Check signal parameters
|
| if(!m_signal.ValidationSettings())
|
| {
|
| Print(__FUNCTION__+": error signal parameters");
|
| return(false);
|
| }
|
| //--- Check trailing parameters
|
| if(!m_trailing.ValidationSettings())
|
| {
|
| Print(__FUNCTION__+": error trailing parameters");
|
| return(false);
|
| }
|
| //--- Check money parameters
|
| if(!m_money.ValidationSettings())
|
| {
|
| Print(__FUNCTION__+": error money parameters");
|
| return(false);
|
| }
|
| //--- ok
|
| return(true);
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Initialization indicators |
|
| //+------------------------------------------------------------------+
|
| bool CExpert::InitIndicators(CIndicators *indicators)
|
| {
|
| //--- NULL always comes as the parameter, but here it's not significant for us
|
| CIndicators *indicators_ptr=GetPointer(m_indicators);
|
| //--- gather information about using of timeseries
|
| m_used_series|=m_signal.UsedSeries();
|
| m_used_series|=m_trailing.UsedSeries();
|
| m_used_series|=m_money.UsedSeries();
|
| //--- create required timeseries
|
| if(!CExpertBase::InitIndicators(indicators_ptr))
|
| return(false);
|
| m_signal.SetPriceSeries(m_open,m_high,m_low,m_close);
|
| m_signal.SetOtherSeries(m_spread,m_time,m_tick_volume,m_real_volume);
|
| if(!m_signal.InitIndicators(indicators_ptr))
|
| {
|
| Print(__FUNCTION__+": error initialization indicators of signal object");
|
| return(false);
|
| }
|
| m_trailing.SetPriceSeries(m_open,m_high,m_low,m_close);
|
| m_trailing.SetOtherSeries(m_spread,m_time,m_tick_volume,m_real_volume);
|
| if(!m_trailing.InitIndicators(indicators_ptr))
|
| {
|
| Print(__FUNCTION__+": error initialization indicators of trailing object");
|
| return(false);
|
| }
|
| m_money.SetPriceSeries(m_open,m_high,m_low,m_close);
|
| m_money.SetOtherSeries(m_spread,m_time,m_tick_volume,m_real_volume);
|
| if(!m_money.InitIndicators(indicators_ptr))
|
| {
|
| Print(__FUNCTION__+": error initialization indicators of money object");
|
| return(false);
|
| }
|
| //--- ok
|
| return(true);
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Deinitialization expert |
|
| //+------------------------------------------------------------------+
|
| void CExpert::Deinit(void)
|
| {
|
| //--- delete trade class
|
| DeinitTrade();
|
| //--- delete signal class
|
| DeinitSignal();
|
| //--- delete trailing class
|
| DeinitTrailing();
|
| //--- delete money class
|
| DeinitMoney();
|
| //--- delete indicators collection
|
| DeinitIndicators();
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Deinitialization trade object |
|
| //+------------------------------------------------------------------+
|
| void CExpert::DeinitTrade(void)
|
| {
|
| if(m_trade!=NULL)
|
| {
|
| delete m_trade;
|
| m_trade=NULL;
|
| }
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Deinitialization signal object |
|
| //+------------------------------------------------------------------+
|
| void CExpert::DeinitSignal(void)
|
| {
|
| if(m_signal!=NULL)
|
| {
|
| delete m_signal;
|
| m_signal=NULL;
|
| }
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Deinitialization trailing object |
|
| //+------------------------------------------------------------------+
|
| void CExpert::DeinitTrailing(void)
|
| {
|
| if(m_trailing!=NULL)
|
| {
|
| delete m_trailing;
|
| m_trailing=NULL;
|
| }
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Deinitialization money object |
|
| //+------------------------------------------------------------------+
|
| void CExpert::DeinitMoney(void)
|
| {
|
| if(m_money!=NULL)
|
| {
|
| delete m_money;
|
| m_money=NULL;
|
| }
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Deinitialization indicators |
|
| //+------------------------------------------------------------------+
|
| void CExpert::DeinitIndicators(void)
|
| {
|
| m_indicators.Clear();
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Refreshing data for processing |
|
| //+------------------------------------------------------------------+
|
| bool CExpert::Refresh(void)
|
| {
|
| MqlDateTime time;
|
| //--- refresh rates
|
| if(!m_symbol.RefreshRates())
|
| return(false);
|
| //--- check need processing
|
| TimeToStruct(m_symbol.Time(),time);
|
| if(m_period_flags!=WRONG_VALUE && m_period_flags!=0)
|
| if((m_period_flags&TimeframesFlags(time))==0)
|
| return(false);
|
| m_last_tick_time=time;
|
| //--- refresh indicators
|
| m_indicators.Refresh();
|
| //--- ok
|
| return(true);
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Position select depending on netting or hedging |
|
| //+------------------------------------------------------------------+
|
| bool CExpert::SelectPosition(void)
|
| {
|
| bool res=false;
|
| //---
|
| if(IsHedging())
|
| res=m_position.SelectByMagic(m_symbol.Name(),m_magic);
|
| else
|
| res=m_position.Select(m_symbol.Name());
|
| //---
|
| return(res);
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Main function |
|
| //+------------------------------------------------------------------+
|
| bool CExpert::Processing(void)
|
| {
|
| //--- calculate signal direction once
|
| m_signal.SetDirection();
|
| //--- check if open positions
|
| if(SelectPosition())
|
| {
|
| //--- open position is available
|
| //--- check the possibility of reverse the position
|
| if(CheckReverse())
|
| return(true);
|
| //--- check the possibility of closing the position/delete pending orders
|
| if(!CheckClose())
|
| {
|
| //--- check the possibility of modifying the position
|
| if(CheckTrailingStop())
|
| return(true);
|
| //--- return without operations
|
| return(false);
|
| }
|
| }
|
| //--- check if plased pending orders
|
| int total=OrdersTotal();
|
| if(total!=0)
|
| {
|
| for(int i=total-1; i>=0; i--)
|
| {
|
| m_order.SelectByIndex(i);
|
| if(m_order.Symbol()!=m_symbol.Name())
|
| continue;
|
| if(m_order.OrderType()==ORDER_TYPE_BUY_LIMIT || m_order.OrderType()==ORDER_TYPE_BUY_STOP)
|
| {
|
| //--- check the ability to delete a pending order to buy
|
| if(CheckDeleteOrderLong())
|
| return(true);
|
| //--- check the possibility of modifying a pending order to buy
|
| if(CheckTrailingOrderLong())
|
| return(true);
|
| }
|
| else
|
| {
|
| //--- check the ability to delete a pending order to sell
|
| if(CheckDeleteOrderShort())
|
| return(true);
|
| //--- check the possibility of modifying a pending order to sell
|
| if(CheckTrailingOrderShort())
|
| return(true);
|
| }
|
| //--- return without operations
|
| return(false);
|
| }
|
| }
|
| //--- check the possibility of opening a position/setting pending order
|
| if(CheckOpen())
|
| return(true);
|
| //--- return without operations
|
| return(false);
|
| }
|
| //+------------------------------------------------------------------+
|
| //| OnTick handler |
|
| //+------------------------------------------------------------------+
|
| void CExpert::OnTick(void)
|
| {
|
| //--- check process flag
|
| if(!m_on_tick_process)
|
| return;
|
| //--- updated quotes and indicators
|
| if(!Refresh())
|
| return;
|
| //--- expert processing
|
| Processing();
|
| }
|
| //+------------------------------------------------------------------+
|
| //| OnTrade handler |
|
| //+------------------------------------------------------------------+
|
| void CExpert::OnTrade(void)
|
| {
|
| //--- check process flag
|
| if(!m_on_trade_process)
|
| return;
|
| CheckTradeState();
|
| }
|
| //+------------------------------------------------------------------+
|
| //| OnTimer handler |
|
| //+------------------------------------------------------------------+
|
| void CExpert::OnTimer(void)
|
| {
|
| //--- check process flag
|
| if(!m_on_timer_process)
|
| return;
|
| }
|
| //+------------------------------------------------------------------+
|
| //| OnChartEvent handler |
|
| //+------------------------------------------------------------------+
|
| void CExpert::OnChartEvent(const int id,const long &lparam,const double &dparam,const string &sparam)
|
| {
|
| //--- check process flag
|
| if(!m_on_chart_event_process)
|
| return;
|
| }
|
| //+------------------------------------------------------------------+
|
| //| OnBookEvent handler |
|
| //+------------------------------------------------------------------+
|
| void CExpert::OnBookEvent(const string &symbol)
|
| {
|
| //--- check process flag
|
| if(!m_on_book_event_process)
|
| return;
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Check for position open or limit/stop order set |
|
| //+------------------------------------------------------------------+
|
| bool CExpert::CheckOpen(void)
|
| {
|
| if(CheckOpenLong())
|
| return(true);
|
| if(CheckOpenShort())
|
| return(true);
|
| //--- return without operations
|
| return(false);
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Check for long position open or limit/stop order set |
|
| //+------------------------------------------------------------------+
|
| bool CExpert::CheckOpenLong(void)
|
| {
|
| double price=EMPTY_VALUE;
|
| double sl=0.0;
|
| double tp=0.0;
|
| datetime expiration=TimeCurrent();
|
| //--- check signal for long enter operations
|
| if(m_signal.CheckOpenLong(price,sl,tp,expiration))
|
| {
|
| if(!m_trade.SetOrderExpiration(expiration))
|
| m_expiration=expiration;
|
| return(OpenLong(price,sl,tp));
|
| }
|
| //--- return without operations
|
| return(false);
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Check for short position open or limit/stop order set |
|
| //+------------------------------------------------------------------+
|
| bool CExpert::CheckOpenShort(void)
|
| {
|
| double price=EMPTY_VALUE;
|
| double sl=0.0;
|
| double tp=0.0;
|
| datetime expiration=TimeCurrent();
|
| //--- check signal for short enter operations
|
| if(m_signal.CheckOpenShort(price,sl,tp,expiration))
|
| {
|
| if(!m_trade.SetOrderExpiration(expiration))
|
| m_expiration=expiration;
|
| return(OpenShort(price,sl,tp));
|
| }
|
| //--- return without operations
|
| return(false);
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Long position open or limit/stop order set |
|
| //+------------------------------------------------------------------+
|
| bool CExpert::OpenLong(double price,double sl,double tp)
|
| {
|
| if(price==EMPTY_VALUE)
|
| return(false);
|
| //--- get lot for open
|
| double lot=LotOpenLong(price,sl);
|
| //--- check lot for open
|
| lot=LotCheck(lot,price,ORDER_TYPE_BUY);
|
| if(lot==0.0)
|
| return(false);
|
| //---
|
| return(m_trade.Buy(lot,price,sl,tp));
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Short position open or limit/stop order set |
|
| //+------------------------------------------------------------------+
|
| bool CExpert::OpenShort(double price,double sl,double tp)
|
| {
|
| if(price==EMPTY_VALUE)
|
| return(false);
|
| //--- get lot for open
|
| double lot=LotOpenShort(price,sl);
|
| //--- check lot for open
|
| lot=LotCheck(lot,price,ORDER_TYPE_SELL);
|
| if(lot==0.0)
|
| return(false);
|
| //---
|
| return(m_trade.Sell(lot,price,sl,tp));
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Check for position reverse |
|
| //+------------------------------------------------------------------+
|
| bool CExpert::CheckReverse(void)
|
| {
|
| if(m_position.PositionType()==POSITION_TYPE_BUY)
|
| {
|
| //--- check the possibility of reverse the long position
|
| if(CheckReverseLong())
|
| return(true);
|
| }
|
| else
|
| {
|
| //--- check the possibility of reverse the short position
|
| if(CheckReverseShort())
|
| return(true);
|
| }
|
| //--- return without operations
|
| return(false);
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Check for long position reverse |
|
| //+------------------------------------------------------------------+
|
| bool CExpert::CheckReverseLong(void)
|
| {
|
| double price=EMPTY_VALUE;
|
| double sl=0.0;
|
| double tp=0.0;
|
| datetime expiration=TimeCurrent();
|
| //--- check signal for long reverse operations
|
| if(m_signal.CheckReverseLong(price,sl,tp,expiration))
|
| return(ReverseLong(price,sl,tp));
|
| //--- return without operations
|
| return(false);
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Check for short position reverse |
|
| //+------------------------------------------------------------------+
|
| bool CExpert::CheckReverseShort(void)
|
| {
|
| double price=EMPTY_VALUE;
|
| double sl=0.0;
|
| double tp=0.0;
|
| datetime expiration=TimeCurrent();
|
| //--- check signal for short reverse operations
|
| if(m_signal.CheckReverseShort(price,sl,tp,expiration))
|
| return(ReverseShort(price,sl,tp));
|
| //--- return without operations
|
| return(false);
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Long position reverse |
|
| //+------------------------------------------------------------------+
|
| bool CExpert::ReverseLong(double price,double sl,double tp)
|
| {
|
| if(price==EMPTY_VALUE)
|
| return(false);
|
| //--- get lot for reverse
|
| double lot=LotReverse(sl);
|
| //--- check lot
|
| if(lot==0.0)
|
| return(false);
|
| //---
|
| bool result=true;
|
| if(IsHedging())
|
| {
|
| //--- first close existing position
|
| lot-=m_position.Volume();
|
| result=m_trade.PositionClose(m_position.Ticket());
|
| }
|
| if(result)
|
| {
|
| lot=LotCheck(lot,price,ORDER_TYPE_SELL);
|
| if(lot==0.0)
|
| result=false;
|
| else
|
| result=m_trade.Sell(lot,price,sl,tp);
|
| }
|
| //---
|
| return(result);
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Short position reverse |
|
| //+------------------------------------------------------------------+
|
| bool CExpert::ReverseShort(double price,double sl,double tp)
|
| {
|
| if(price==EMPTY_VALUE)
|
| return(false);
|
| //--- get lot for reverse
|
| double lot=LotReverse(sl);
|
| //--- check lot
|
| if(lot==0.0)
|
| return(false);
|
| //---
|
| bool result=true;
|
| if(IsHedging())
|
| {
|
| //--- first close existing position
|
| lot-=m_position.Volume();
|
| result=m_trade.PositionClose(m_position.Ticket());
|
| }
|
| if(result)
|
| {
|
| lot=LotCheck(lot,price,ORDER_TYPE_BUY);
|
| if(lot==0.0)
|
| result=false;
|
| else
|
| result=m_trade.Buy(lot,price,sl,tp);
|
| }
|
| //---
|
| return(result);
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Check for position close or limit/stop order delete |
|
| //+------------------------------------------------------------------+
|
| bool CExpert::CheckClose(void)
|
| {
|
| double lot;
|
| //--- position must be selected before call
|
| if((lot=m_money.CheckClose(GetPointer(m_position)))!=0.0)
|
| return(CloseAll(lot));
|
| //--- check for position type
|
| if(m_position.PositionType()==POSITION_TYPE_BUY)
|
| {
|
| //--- check the possibility of closing the long position / delete pending orders to buy
|
| if(CheckCloseLong())
|
| {
|
| DeleteOrdersLong();
|
| return(true);
|
| }
|
| }
|
| else
|
| {
|
| //--- check the possibility of closing the short position / delete pending orders to sell
|
| if(CheckCloseShort())
|
| {
|
| DeleteOrdersShort();
|
| return(true);
|
| }
|
| }
|
| //--- return without operations
|
| return(false);
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Check for long position close or limit/stop order delete |
|
| //+------------------------------------------------------------------+
|
| bool CExpert::CheckCloseLong(void)
|
| {
|
| double price=EMPTY_VALUE;
|
| //--- check for long close operations
|
| if(m_signal.CheckCloseLong(price))
|
| return(CloseLong(price));
|
| //--- return without operations
|
| return(false);
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Check for short position close or limit/stop order delete |
|
| //+------------------------------------------------------------------+
|
| bool CExpert::CheckCloseShort(void)
|
| {
|
| double price=EMPTY_VALUE;
|
| //--- check for short close operations
|
| if(m_signal.CheckCloseShort(price))
|
| return(CloseShort(price));
|
| //--- return without operations
|
| return(false);
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Position close and orders delete |
|
| //+------------------------------------------------------------------+
|
| bool CExpert::CloseAll(double lot)
|
| {
|
| bool result=false;
|
| //--- check for close operations
|
| if(IsHedging())
|
| result=m_trade.PositionClose(m_position.Ticket());
|
| else
|
| {
|
| if(m_position.PositionType()==POSITION_TYPE_BUY)
|
| result=m_trade.Sell(lot,0,0,0);
|
| else
|
| result=m_trade.Buy(lot,0,0,0);
|
| }
|
| result|=DeleteOrders();
|
| //---
|
| return(result);
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Position close |
|
| //+------------------------------------------------------------------+
|
| bool CExpert::Close(void)
|
| {
|
| return(m_trade.PositionClose(m_symbol.Name()));
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Long position close |
|
| //+------------------------------------------------------------------+
|
| bool CExpert::CloseLong(double price)
|
| {
|
| bool result=false;
|
| //---
|
| if(price==EMPTY_VALUE)
|
| return(false);
|
| if(IsHedging())
|
| result=m_trade.PositionClose(m_position.Ticket());
|
| else
|
| result=m_trade.Sell(m_position.Volume(),price,0,0);
|
| //---
|
| return(result);
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Short position close |
|
| //+------------------------------------------------------------------+
|
| bool CExpert::CloseShort(double price)
|
| {
|
| bool result=false;
|
| //---
|
| if(price==EMPTY_VALUE)
|
| return(false);
|
| if(IsHedging())
|
| result=m_trade.PositionClose(m_position.Ticket());
|
| else
|
| result=m_trade.Buy(m_position.Volume(),price,0,0);
|
| //---
|
| return(result);
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Check for trailing stop/profit position |
|
| //+------------------------------------------------------------------+
|
| bool CExpert::CheckTrailingStop(void)
|
| {
|
| //--- position must be selected before call
|
| if(m_position.PositionType()==POSITION_TYPE_BUY)
|
| {
|
| //--- check the possibility of modifying the long position
|
| if(CheckTrailingStopLong())
|
| return(true);
|
| }
|
| else
|
| {
|
| //--- check the possibility of modifying the short position
|
| if(CheckTrailingStopShort())
|
| return(true);
|
| }
|
| //--- return without operations
|
| return(false);
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Check for trailing stop/profit long position |
|
| //+------------------------------------------------------------------+
|
| bool CExpert::CheckTrailingStopLong(void)
|
| {
|
| double sl=EMPTY_VALUE;
|
| double tp=EMPTY_VALUE;
|
| //--- check for long trailing stop operations
|
| if(m_trailing.CheckTrailingStopLong(GetPointer(m_position),sl,tp))
|
| {
|
| double position_sl=m_position.StopLoss();
|
| double position_tp=m_position.TakeProfit();
|
| if(sl==EMPTY_VALUE)
|
| sl=position_sl;
|
| else
|
| sl=m_symbol.NormalizePrice(sl);
|
| if(tp==EMPTY_VALUE)
|
| tp=position_tp;
|
| else
|
| tp=m_symbol.NormalizePrice(tp);
|
| if(sl==position_sl && tp==position_tp)
|
| return(false);
|
| //--- long trailing stop operations
|
| return(TrailingStopLong(sl,tp));
|
| }
|
| //--- return without operations
|
| return(false);
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Check for trailing stop/profit short position |
|
| //+------------------------------------------------------------------+
|
| bool CExpert::CheckTrailingStopShort(void)
|
| {
|
| double sl=EMPTY_VALUE;
|
| double tp=EMPTY_VALUE;
|
| //--- check for short trailing stop operations
|
| if(m_trailing.CheckTrailingStopShort(GetPointer(m_position),sl,tp))
|
| {
|
| double position_sl=m_position.StopLoss();
|
| double position_tp=m_position.TakeProfit();
|
| if(sl==EMPTY_VALUE)
|
| sl=position_sl;
|
| else
|
| sl=m_symbol.NormalizePrice(sl);
|
| if(tp==EMPTY_VALUE)
|
| tp=position_tp;
|
| else
|
| tp=m_symbol.NormalizePrice(tp);
|
| if(sl==position_sl && tp==position_tp)
|
| return(false);
|
| //--- short trailing stop operations
|
| return(TrailingStopShort(sl,tp));
|
| }
|
| //--- return without operations
|
| return(false);
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Trailing stop/profit long position |
|
| //+------------------------------------------------------------------+
|
| bool CExpert::TrailingStopLong(double sl,double tp)
|
| {
|
| bool result;
|
| //---
|
| if(IsHedging())
|
| result=m_trade.PositionModify(m_position.Ticket(),sl,tp);
|
| else
|
| result=m_trade.PositionModify(m_symbol.Name(),sl,tp);
|
| //---
|
| return(result);
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Trailing stop/profit short position |
|
| //+------------------------------------------------------------------+
|
| bool CExpert::TrailingStopShort(double sl,double tp)
|
| {
|
| bool result;
|
| //---
|
| if(IsHedging())
|
| result=m_trade.PositionModify(m_position.Ticket(),sl,tp);
|
| else
|
| result=m_trade.PositionModify(m_symbol.Name(),sl,tp);
|
| //---
|
| return(result);
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Check for trailing long limit/stop order |
|
| //+------------------------------------------------------------------+
|
| bool CExpert::CheckTrailingOrderLong(void)
|
| {
|
| double price;
|
| //--- check the possibility of modifying the long order
|
| if(m_signal.CheckTrailingOrderLong(GetPointer(m_order),price))
|
| return(TrailingOrderLong(m_order.PriceOpen()-price));
|
| //--- return without operations
|
| return(false);
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Check for trailing short limit/stop order |
|
| //+------------------------------------------------------------------+
|
| bool CExpert::CheckTrailingOrderShort(void)
|
| {
|
| double price;
|
| //--- check the possibility of modifying the short order
|
| if(m_signal.CheckTrailingOrderShort(GetPointer(m_order),price))
|
| return(TrailingOrderShort(m_order.PriceOpen()-price));
|
| //--- return without operations
|
| return(false);
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Trailing long limit/stop order |
|
| //+------------------------------------------------------------------+
|
| bool CExpert::TrailingOrderLong(double delta)
|
| {
|
| ulong ticket=m_order.Ticket();
|
| double price =m_symbol.NormalizePrice(m_order.PriceOpen()-delta);
|
| double sl =m_symbol.NormalizePrice(m_order.StopLoss()-delta);
|
| double tp =m_symbol.NormalizePrice(m_order.TakeProfit()-delta);
|
| //--- modifying the long order
|
| return(m_trade.OrderModify(ticket,price,sl,tp,m_order.TypeTime(),m_order.TimeExpiration()));
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Trailing short limit/stop order |
|
| //+------------------------------------------------------------------+
|
| bool CExpert::TrailingOrderShort(double delta)
|
| {
|
| ulong ticket=m_order.Ticket();
|
| double price =m_symbol.NormalizePrice(m_order.PriceOpen()-delta);
|
| double sl =m_symbol.NormalizePrice(m_order.StopLoss()-delta);
|
| double tp =m_symbol.NormalizePrice(m_order.TakeProfit()-delta);
|
| //--- modifying the short order
|
| return(m_trade.OrderModify(ticket,price,sl,tp,m_order.TypeTime(),m_order.TimeExpiration()));
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Check for delete long limit/stop order |
|
| //+------------------------------------------------------------------+
|
| bool CExpert::CheckDeleteOrderLong(void)
|
| {
|
| double price;
|
| //--- check the possibility of deleting the long order
|
| if(m_expiration!=0 && TimeCurrent()>m_expiration)
|
| {
|
| m_expiration=0;
|
| return(DeleteOrderLong());
|
| }
|
| if(m_signal.CheckCloseLong(price))
|
| return(DeleteOrderLong());
|
| //--- return without operations
|
| return(false);
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Check for delete short limit/stop order |
|
| //+------------------------------------------------------------------+
|
| bool CExpert::CheckDeleteOrderShort(void)
|
| {
|
| double price;
|
| //--- check the possibility of deleting the short order
|
| if(m_expiration!=0 && TimeCurrent()>m_expiration)
|
| {
|
| m_expiration=0;
|
| return(DeleteOrderShort());
|
| }
|
| if(m_signal.CheckCloseShort(price))
|
| return(DeleteOrderShort());
|
| //--- return without operations
|
| return(false);
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Delete all limit/stop orders |
|
| //+------------------------------------------------------------------+
|
| bool CExpert::DeleteOrders(void)
|
| {
|
| bool result=true;
|
| int total=OrdersTotal();
|
| //---
|
| for(int i=total-1;i>=0;i--)
|
| if(m_order.Select(OrderGetTicket(i)))
|
| {
|
| if(m_order.Symbol()!=m_symbol.Name())
|
| continue;
|
| result&=DeleteOrder();
|
| }
|
| //---
|
| return(result);
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Delete all limit/stop long orders |
|
| //+------------------------------------------------------------------+
|
| bool CExpert::DeleteOrdersLong(void)
|
| {
|
| bool result=true;
|
| int total=OrdersTotal();
|
| //---
|
| for(int i=total-1;i>=0;i--)
|
| if(m_order.Select(OrderGetTicket(i)))
|
| {
|
| if(m_order.Symbol()!=m_symbol.Name())
|
| continue;
|
| if(m_order.OrderType()!=ORDER_TYPE_BUY_STOP &&
|
| m_order.OrderType()!=ORDER_TYPE_BUY_LIMIT)
|
| continue;
|
| result&=DeleteOrder();
|
| }
|
| //---
|
| return(result);
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Delete all limit/stop orders |
|
| //+------------------------------------------------------------------+
|
| bool CExpert::DeleteOrdersShort(void)
|
| {
|
| bool result=true;
|
| int total=OrdersTotal();
|
| //---
|
| for(int i=total-1;i>=0;i--)
|
| if(m_order.Select(OrderGetTicket(i)))
|
| {
|
| if(m_order.Symbol()!=m_symbol.Name())
|
| continue;
|
| if(m_order.OrderType()!=ORDER_TYPE_SELL_STOP &&
|
| m_order.OrderType()!=ORDER_TYPE_SELL_LIMIT)
|
| continue;
|
| result&=DeleteOrder();
|
| }
|
| //---
|
| return(result);
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Delete limit/stop order |
|
| //+------------------------------------------------------------------+
|
| bool CExpert::DeleteOrder(void)
|
| {
|
| return(m_trade.OrderDelete(m_order.Ticket()));
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Delete long limit/stop order |
|
| //+------------------------------------------------------------------+
|
| bool CExpert::DeleteOrderLong(void)
|
| {
|
| return(m_trade.OrderDelete(m_order.Ticket()));
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Delete short limit/stop order |
|
| //+------------------------------------------------------------------+
|
| bool CExpert::DeleteOrderShort(void)
|
| {
|
| return(m_trade.OrderDelete(m_order.Ticket()));
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Method of getting the lot for open long position. |
|
| //+------------------------------------------------------------------+
|
| double CExpert::LotOpenLong(double price,double sl)
|
| {
|
| return(m_money.CheckOpenLong(price,sl));
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Method of getting the lot for open short position. |
|
| //+------------------------------------------------------------------+
|
| double CExpert::LotOpenShort(double price,double sl)
|
| {
|
| return(m_money.CheckOpenShort(price,sl));
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Method of getting the lot for reverse position. |
|
| //+------------------------------------------------------------------+
|
| double CExpert::LotReverse(double sl)
|
| {
|
| return(m_money.CheckReverse(GetPointer(m_position),sl));
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Check volume before OrderSend to avoid "not enough money" error |
|
| //+------------------------------------------------------------------+
|
| double CExpert::LotCheck(double volume,double price,ENUM_ORDER_TYPE order_type)
|
| {
|
| if(m_check_volume)
|
| return(m_trade.CheckVolume(m_symbol.Name(),volume,price,order_type));
|
| return(volume);
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Method of setting the start date for the history. |
|
| //+------------------------------------------------------------------+
|
| void CExpert::PrepareHistoryDate(void)
|
| {
|
| MqlDateTime dts;
|
| //---
|
| TimeCurrent(dts);
|
| //--- set up a date at the beginning of the month (but not less than one day)
|
| if(dts.day==1)
|
| {
|
| if(dts.mon==1)
|
| {
|
| dts.mon=12;
|
| dts.year--;
|
| }
|
| else
|
| dts.mon--;
|
| }
|
| dts.day =1;
|
| dts.hour=0;
|
| dts.min =0;
|
| dts.sec =0;
|
| //---
|
| m_beg_date=StructToTime(dts);
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Method of establishing the checkpoint history. |
|
| //+------------------------------------------------------------------+
|
| void CExpert::HistoryPoint(bool from_check_trade)
|
| {
|
| //--- check possible recursion
|
| if(!from_check_trade)
|
| CheckTradeState();
|
| //--- select history point
|
| if(HistorySelect(m_beg_date,TimeCurrent()))
|
| {
|
| m_hist_ord_tot=HistoryOrdersTotal();
|
| m_deal_tot =HistoryDealsTotal();
|
| }
|
| else
|
| {
|
| m_hist_ord_tot=0;
|
| m_deal_tot =0;
|
| }
|
| m_ord_tot=OrdersTotal();
|
| m_pos_tot=PositionsTotal();
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Method of verification of trade events. |
|
| //+------------------------------------------------------------------+
|
| bool CExpert::CheckTradeState(void)
|
| {
|
| bool res=false;
|
| //--- select current history point
|
| HistorySelect(m_beg_date,INT_MAX);
|
| int hist_ord_tot=HistoryOrdersTotal();
|
| int ord_tot =OrdersTotal();
|
| int deal_tot =HistoryDealsTotal();
|
| int pos_tot =PositionsTotal();
|
| //--- check for quantitative changes
|
| if(hist_ord_tot==m_hist_ord_tot && ord_tot==m_ord_tot && deal_tot==m_deal_tot && pos_tot==m_pos_tot)
|
| {
|
| //--- no quantitative changes
|
| if(IS_WAITING_POSITION_MODIFIED)
|
| {
|
| res=TradeEventPositionModified();
|
| NoWaitEvent(TRADE_EVENT_POSITION_MODIFY);
|
| }
|
| if(IS_WAITING_ORDER_MODIFIED)
|
| {
|
| res=TradeEventOrderModified();
|
| NoWaitEvent(TRADE_EVENT_ORDER_MODIFY);
|
| }
|
| return(true);
|
| }
|
| //--- check added a pending order
|
| if(hist_ord_tot==m_hist_ord_tot && ord_tot==m_ord_tot+1 && deal_tot==m_deal_tot && pos_tot==m_pos_tot)
|
| {
|
| //--- was added a pending order
|
| res=TradeEventOrderPlaced();
|
| //--- establishment of the checkpoint history of the trade
|
| HistoryPoint(true);
|
| return(true);
|
| }
|
| //--- check make a deal "with the market"
|
| if(hist_ord_tot==m_hist_ord_tot+1 && ord_tot==m_ord_tot)
|
| {
|
| //--- was an attempt to make a deal "with the market"
|
| if(deal_tot==m_deal_tot+1)
|
| {
|
| //--- operation successfull
|
| //--- check position update/subtracting
|
| if(pos_tot==m_pos_tot)
|
| {
|
| //--- position update/subtracting
|
| if(IS_WAITING_POSITION_VOLUME_CHANGED)
|
| {
|
| res=TradeEventPositionVolumeChanged();
|
| NoWaitEvent(TRADE_EVENT_POSITION_VOLUME_CHANGE);
|
| }
|
| //--- establishment of the checkpoint history of the trade
|
| HistoryPoint(true);
|
| return(res);
|
| }
|
| //--- check position open
|
| if(pos_tot==m_pos_tot+1)
|
| {
|
| //--- position open
|
| if(IS_WAITING_POSITION_OPENED)
|
| {
|
| res=TradeEventPositionOpened();
|
| NoWaitEvent(TRADE_EVENT_POSITION_OPEN);
|
| }
|
| //--- establishment of the checkpoint history of the trade
|
| HistoryPoint(true);
|
| return(res);
|
| }
|
| //--- check position is closed (including the stoploss/takeprofit)
|
| if(pos_tot==m_pos_tot-1)
|
| {
|
| //--- position is closed (including the stoploss/takeprofit)
|
| if(IS_WAITING_POSITION_CLOSED)
|
| {
|
| res=TradeEventPositionClosed();
|
| NoWaitEvent(TRADE_EVENT_POSITION_CLOSE);
|
| }
|
| else
|
| res=TradeEventPositionStopTake();
|
| //--- establishment of the checkpoint history of the trade
|
| HistoryPoint(true);
|
| return(res);
|
| }
|
| }
|
| else
|
| {
|
| //--- operation failed
|
| //--- establishment of the checkpoint history of the trade
|
| HistoryPoint(true);
|
| return(false);
|
| }
|
| }
|
| //--- check delete pending order
|
| if(hist_ord_tot==m_hist_ord_tot+1 && ord_tot==m_ord_tot-1 && deal_tot==m_deal_tot && pos_tot==m_pos_tot)
|
| {
|
| //--- delete pending order
|
| res=TradeEventOrderDeleted();
|
| //--- establishment of the checkpoint history of the trade
|
| HistoryPoint(true);
|
| return(res);
|
| }
|
| //--- check triggering of a pending order
|
| if(hist_ord_tot==m_hist_ord_tot+1 && ord_tot==m_ord_tot-1)
|
| {
|
| //--- triggering of a pending order
|
| if(deal_tot==m_deal_tot+1)
|
| {
|
| //--- operation successfull
|
| //--- check position update/subtracting
|
| if(pos_tot==m_pos_tot)
|
| {
|
| //--- position update/subtracting
|
| res=TradeEventOrderTriggered();
|
| //--- establishment of the checkpoint history of the trade
|
| HistoryPoint(true);
|
| return(res);
|
| }
|
| //--- check position open
|
| if(pos_tot==m_pos_tot+1)
|
| {
|
| //--- position open
|
| res=TradeEventOrderTriggered();
|
| //--- establishment of the checkpoint history of the trade
|
| HistoryPoint(true);
|
| return(res);
|
| }
|
| //--- check position is closed
|
| if(pos_tot==m_pos_tot-1)
|
| {
|
| //--- position is closed
|
| res=TradeEventOrderTriggered();
|
| //--- establishment of the checkpoint history of the trade
|
| HistoryPoint(true);
|
| return(res);
|
| }
|
| }
|
| else
|
| {
|
| //--- operation failed
|
| //--- establishment of the checkpoint history of the trade
|
| HistoryPoint(true);
|
| return(false);
|
| }
|
| }
|
| //--- trade event non identifical
|
| res=TradeEventNotIdentified();
|
| //--- establishment of the checkpoint history of the trade
|
| HistoryPoint(true);
|
| //---
|
| return(res);
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Add timeframe for checked |
|
| //+------------------------------------------------------------------+
|
| void CExpert::TimeframeAdd(ENUM_TIMEFRAMES period)
|
| {
|
| switch(period)
|
| {
|
| case PERIOD_M1: m_period_flags|=OBJ_PERIOD_M1; break;
|
| case PERIOD_M2: m_period_flags|=OBJ_PERIOD_M2; break;
|
| case PERIOD_M3: m_period_flags|=OBJ_PERIOD_M3; break;
|
| case PERIOD_M4: m_period_flags|=OBJ_PERIOD_M4; break;
|
| case PERIOD_M5: m_period_flags|=OBJ_PERIOD_M5; break;
|
| case PERIOD_M6: m_period_flags|=OBJ_PERIOD_M6; break;
|
| case PERIOD_M10: m_period_flags|=OBJ_PERIOD_M10; break;
|
| case PERIOD_M12: m_period_flags|=OBJ_PERIOD_M12; break;
|
| case PERIOD_M15: m_period_flags|=OBJ_PERIOD_M15; break;
|
| case PERIOD_M20: m_period_flags|=OBJ_PERIOD_M20; break;
|
| case PERIOD_M30: m_period_flags|=OBJ_PERIOD_M30; break;
|
| case PERIOD_H1: m_period_flags|=OBJ_PERIOD_H1; break;
|
| case PERIOD_H2: m_period_flags|=OBJ_PERIOD_H2; break;
|
| case PERIOD_H3: m_period_flags|=OBJ_PERIOD_H3; break;
|
| case PERIOD_H4: m_period_flags|=OBJ_PERIOD_H4; break;
|
| case PERIOD_H6: m_period_flags|=OBJ_PERIOD_H6; break;
|
| case PERIOD_H8: m_period_flags|=OBJ_PERIOD_H8; break;
|
| case PERIOD_H12: m_period_flags|=OBJ_PERIOD_H12; break;
|
| case PERIOD_D1: m_period_flags|=OBJ_PERIOD_D1; break;
|
| case PERIOD_W1: m_period_flags|=OBJ_PERIOD_W1; break;
|
| case PERIOD_MN1: m_period_flags|=OBJ_PERIOD_MN1; break;
|
| default: m_period_flags=WRONG_VALUE; break;
|
| }
|
| }
|
| //+------------------------------------------------------------------+
|
| //| Forms timeframes flags |
|
| //+------------------------------------------------------------------+
|
| int CExpert::TimeframesFlags(MqlDateTime &time)
|
| {
|
| //--- set flags for all timeframes
|
| int result=OBJ_ALL_PERIODS;
|
| //--- if first check, then setting flags all timeframes
|
| if(m_last_tick_time.min==-1)
|
| return(result);
|
| //--- check change time
|
| if(time.min==m_last_tick_time.min &&
|
| time.hour==m_last_tick_time.hour &&
|
| time.day==m_last_tick_time.day &&
|
| time.mon==m_last_tick_time.mon)
|
| return(OBJ_NO_PERIODS);
|
| //--- new month?
|
| if(time.mon!=m_last_tick_time.mon)
|
| return(result);
|
| //--- reset the "new month" flag
|
| result^=OBJ_PERIOD_MN1;
|
| //--- new day?
|
| if(time.day!=m_last_tick_time.day)
|
| return(result);
|
| //--- reset the "new day" and "new week" flags
|
| result^=OBJ_PERIOD_D1+OBJ_PERIOD_W1;
|
| //--- temporary variables to speed up working with structures
|
| int curr,delta;
|
| //--- new hour?
|
| curr=time.hour;
|
| delta=curr-m_last_tick_time.hour;
|
| if(delta!=0)
|
| {
|
| if(curr%2>=delta)
|
| result^=OBJ_PERIOD_H2;
|
| if(curr%3>=delta)
|
| result^=OBJ_PERIOD_H3;
|
| if(curr%4>=delta)
|
| result^=OBJ_PERIOD_H4;
|
| if(curr%6>=delta)
|
| result^=OBJ_PERIOD_H6;
|
| if(curr%8>=delta)
|
| result^=OBJ_PERIOD_H8;
|
| if(curr%12>=delta)
|
| result^=OBJ_PERIOD_H12;
|
| return(result);
|
| }
|
| //--- reset all flags for hour timeframes
|
| result^=OBJ_PERIOD_H1+OBJ_PERIOD_H2+OBJ_PERIOD_H3+OBJ_PERIOD_H4+OBJ_PERIOD_H6+OBJ_PERIOD_H8+OBJ_PERIOD_H12;
|
| //--- new minute?
|
| curr=time.min;
|
| delta=curr-m_last_tick_time.min;
|
| if(delta!=0)
|
| {
|
| if(curr%2>=delta)
|
| result^=OBJ_PERIOD_M2;
|
| if(curr%3>=delta)
|
| result^=OBJ_PERIOD_M3;
|
| if(curr%4>=delta)
|
| result^=OBJ_PERIOD_M4;
|
| if(curr%5>=delta)
|
| result^=OBJ_PERIOD_M5;
|
| if(curr%6>=delta)
|
| result^=OBJ_PERIOD_M6;
|
| if(curr%10>=delta)
|
| result^=OBJ_PERIOD_M10;
|
| if(curr%12>=delta)
|
| result^=OBJ_PERIOD_M12;
|
| if(curr%15>=delta)
|
| result^=OBJ_PERIOD_M15;
|
| if(curr%20>=delta)
|
| result^=OBJ_PERIOD_M20;
|
| if(curr%30>=delta)
|
| result^=OBJ_PERIOD_M30;
|
| }
|
| //--- result
|
| return(result);
|
| }
|
| //+------------------------------------------------------------------+
|