MobinMQL/Include/Expert/Expert.mqh
2025-07-22 14:47:41 +03:00

1606 lines
120 KiB
MQL5

//+------------------------------------------------------------------+
//| 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);
}
//+------------------------------------------------------------------+