How to check 'Market is closed' befor opening a position? - page 3

 
Zsolt Haromszeki:

Dear Coders!

I started a backtest. My expert advisor is trying to open a position immediately at time 00:00. I get 'Market is closed' (TRADE_RETCODE_MARKET_CLOSED, error code: 10018) message, because the trading is start only at time 00:01:


How can I check in advance if it is possible to open a position?

I tried unsuccessfully with this code:

Please help me, how can I check the allowed trading periods.

Thank you in advance.

Zsolt

Try the below code, currently in script, but easy enough to incorporate in an EA.

Also I assume you use some sort of version of the IsNewBar function, this market open I beliwve needs to be incorporated to the IsNewBar function

ENUM_DAY_OF_WEEK day_of_week;
//+------------------------------------------------------------------+
//| Script                                                           |
//+------------------------------------------------------------------+
void OnStart()
  {
   Print("Trade Session Open: ", trade_session());
  }
//+------------------------------------------------------------------+
//| Function: Check if trade session is open and excl. Sat and Sun   |
//+------------------------------------------------------------------+
bool trade_session()
  {
   datetime time_now = TimeCurrent();
   MqlDateTime time;
   TimeToStruct(time_now, time);
   uint week_day_now = time.day_of_week;
   uint seconds_now = (time.hour * 3600) + (time.min * 60) + time.sec;
   if(week_day_now == 0)
      day_of_week = SUNDAY;
   if(week_day_now == 1)
      day_of_week = MONDAY;
   if(week_day_now == 2)
      day_of_week = TUESDAY;
   if(week_day_now == 3)
      day_of_week = WEDNESDAY;
   if(week_day_now == 4)
      day_of_week = THURSDAY;
   if(week_day_now == 5)
      day_of_week = FRIDAY;
   if(week_day_now == 6)
      day_of_week = SATURDAY;
   datetime from, to;
   uint session = 0;
   while(SymbolInfoSessionTrade(_Symbol, day_of_week, session, from, to))
     {
      session++;
     }
   uint trade_session_open_seconds = uint(from);
   uint trade_session_close_seconds = uint(to);
   if(trade_session_open_seconds < seconds_now && trade_session_close_seconds > seconds_now && week_day_now >= 1 && week_day_now <= 5)
      return(true);
   return(false);
  }
 
Centaur #:

Thank you.

 
Dominik Egert #:

Here is my function to solve the issue:


There is a bug in the implementation of this function.

Here is the corrected version:

//+------------------------------------------------------------------+
//| SymbolInfoQuerySessionTimes()                                    |
//+------------------------------------------------------------------+
const bool SymbolInfoQuerySessionTimes(const string symbol, datetime& session_begin, datetime& session_end, datetime& next_session, const bool quote_sessions = false, const datetime reference_time = NULL)
{
    // Local cache

        static  datetime    c_begin     = NULL;
        static  datetime    c_end       = NULL;
        static  datetime    c_next      = NULL;
        static  bool        c_quotes    = false;
        static  string      c_symbol    = NULL;


    // Cache update

        if( (c_symbol == symbol)
         && (c_quotes == quote_sessions)
         && (c_begin < reference_time)
         && (c_end > reference_time) )
        {
            session_begin   = c_begin;
            session_end     = c_end;
            next_session    = c_next;
            return(true);
        }
        c_symbol    = symbol;
        c_quotes    = quote_sessions;


    // Pre init

        MqlDateTime     mql_time        = {};
        const datetime  time_current    = (reference_time == NULL) ? ::TimeTradeServer(mql_time) : reference_time;
        if( (time_current > NULL)
         && (!::TimeToStruct(time_current, mql_time)) )
        {
            session_begin   = 0xFFFFFFFFFFFFFFFF;
            session_end     = 0xFFFFFFFFFFFFFFFF;
            next_session    = 0xFFFFFFFFFFFFFFFF;
            return(false);
        }


    // Local init

        datetime    start           = NULL;
        datetime    finish          = NULL;
        datetime    day_start       = time_current - (time_current % 0x0000000000015180) - 0x0000000000015180;
        int         session_index   = NULL;
                    session_begin   = NULL;
                    session_end     = NULL;
                    next_session    = NULL;


    // Loop search

        for(ulong cnt = NULL; (cnt < 0x08) && !_StopFlag; cnt++)
        {
            // Current time offset
            day_start      += 0x0000000000015180;
            session_index   = NULL;

            // Switch type of evaluation
            switch((uint)cnt)
            {
                // Find current session if any
                case 0x00:
                    if(quote_sessions)
                    {
                        while( ((day_start + finish) <= time_current)
                            && (mqlplus::SymbolInfoSessionQuote(symbol, mqlplus::DayOfWeekToEnum(mql_time.day_of_week + cnt), (int)(session_index++), start, finish))
                            && !_StopFlag);
                    }
                    else
                    {
                        while( ((day_start + finish) <= time_current)
                            && (mqlplus::SymbolInfoSessionTrade(symbol, mqlplus::DayOfWeekToEnum(mql_time.day_of_week + cnt), (int)(session_index++), start, finish))
                            && !_StopFlag);
                    }

                    // Check results
                    if( ((day_start + start) <= time_current)
                     && ((day_start + finish) > time_current))
                    {
                        session_begin           = (day_start + start);
                        session_end             = (day_start + finish);
                    }

                    // Search for beginning of session
                    if(session_begin > NULL)
                    {
                        // Init loop
                        int         session_index1  = NULL;
                        int         max_count       = NULL;
                        datetime    local_begin     = NULL;
                        datetime    local_end       = NULL;

                        // Loop search
                        for(int cnt1 = (day_start == session_begin); (cnt1 < 0x08) && !_StopFlag; cnt1++)
                        {
                            // Init search loop
                            day_start      -= 0x0000000000015180 * ((cnt1 > NULL) && (session_index1 == NULL));
                            session_index1  = NULL;
                            local_end       = NULL;

                            // Loop backwards
                            if(quote_sessions)
                            {
                                while( ((session_index1 < max_count) || (max_count == NULL))
                                    && (mqlplus::SymbolInfoSessionQuote(symbol, mqlplus::DayOfWeekToEnum(mql_time.day_of_week - cnt1), session_index1++, start, finish))
                                    && ((day_start + finish) <= session_begin)
                                    && !_StopFlag)
                                {
                                    local_begin = (day_start + start);
                                    local_end   = (day_start + finish);
                                }
                                session_index1--;
                            }
                            else
                            {
                                while( ((session_index1 < max_count) || (max_count == NULL))
                                    && (mqlplus::SymbolInfoSessionTrade(symbol, mqlplus::DayOfWeekToEnum(mql_time.day_of_week - cnt1), session_index1++, start, finish))
                                    && ((day_start + finish) <= session_begin)
                                    && !_StopFlag)
                                {
                                    local_begin = (day_start + start);
                                    local_end   = (day_start + finish);
                                }
                                session_index1--;
                            }

                            // Repeat search on same day if more than one session
                            if(session_begin == local_end)
                            {
                                session_begin   = local_begin;
                                cnt1           -= 1 * (session_index1 > 0x01);
                                session_index1 -= (session_index1 == 0x01);
                                max_count       = session_index1;
                            }

                            cnt1 |= 0xFF * (session_begin > local_end);
                        }

                        // Reset day_start variable
                        day_start = time_current - (time_current % 0x0000000000015180);
                    }

                    // Check for multiple sessions
                    if( ((day_start + start) > session_end)
                     && (finish > NULL))
                    {
                        next_session            = (day_start + start);
                        c_begin                 = session_begin;
                        c_end                   = session_end;
                        c_next                  = next_session;
                        return(true);
                    }


                // Find next session
                default:
                    if(quote_sessions)
                    {
                        if(!mqlplus::SymbolInfoSessionQuote(symbol, mqlplus::DayOfWeekToEnum(mql_time.day_of_week + cnt), (int)(session_index++), start, finish))
                        { continue; }
                    }
                    else
                    {
                        if(!mqlplus::SymbolInfoSessionTrade(symbol, mqlplus::DayOfWeekToEnum(mql_time.day_of_week + cnt), (int)(session_index++), start, finish))
                        { continue; }
                    }

                    // Next found session
                    next_session                = (day_start + start) * (session_end < (long)(day_start + start));
                    session_end                 = ((session_end * (next_session > NULL)) + (((finish > NULL) ? day_start + finish : session_end) * (next_session == NULL)));
            }

            if(next_session > NULL)
            {
                c_begin = session_begin;
                c_end   = session_end;
                c_next  = next_session;
                return(true);
            }
        }


    // Clear to zero as 24/7 sessions

        session_begin   = NULL;
        session_end     = NULL;
        next_session    = NULL;
        c_begin         = session_begin;
        c_end           = session_end;
        c_next          = next_session;

    // Return
    return(!_StopFlag);
}



namespace mqlplus
{
    //+------------------------------------------------------------------+
    //| SymbolInfoSessionQuote()                                         |
    //+------------------------------------------------------------------+
    bool SymbolInfoSessionQuote(const string symbol, const ENUM_DAY_OF_WEEK day, const int session_index, datetime& start, datetime& finish)
    {
        start   = NULL;
        finish  = NULL;
        return(::SymbolInfoSessionQuote(symbol, day, session_index, start, finish));
    }


    //+------------------------------------------------------------------+
    //| SymbolInfoSessionTrade()                                         |
    //+------------------------------------------------------------------+
    bool SymbolInfoSessionTrade(const string symbol, const ENUM_DAY_OF_WEEK day, const int session_index, datetime& start, datetime& finish)
    {
        start   = NULL;
        finish  = NULL;
        return(::SymbolInfoSessionTrade(symbol, day, session_index, start, finish));
    }


    //+------------------------------------------------------------------+
    //| DayOfWeekToEnum()                                                |
    //+------------------------------------------------------------------+
    template <typename T>
    const ENUM_DAY_OF_WEEK DayOfWeekToEnum(const T day_of_week, const bool first_day_monday = false)
    {
        switch((((uchar)day_of_week) + ((uchar)(first_day_monday))) % 7)
        {
            case 0x01:  return(MONDAY);
            case 0x02:  return(TUESDAY);
            case 0x03:  return(WEDNESDAY);
            case 0x04:  return(THURSDAY);
            case 0x05:  return(FRIDAY);
            case 0x06:  return(SATURDAY);
            default:    return(SUNDAY);
        }
    }

}; // END namespace mqlplus
 
Control_Trade_Sessions
Control_Trade_Sessions
  • www.mql5.com
Библиотека для контроля торговой сессии. При запуске считает время торговых сессий за все 7 дней недели (в сб и вс может быть торговля по криптовалютам), до 10 сессий в день. Затем в OnTick() можно делать проверки, и если тик пришел вне торговой сессии, то можно выйти из дальнейшей его обработки.
 
Dominik Egert #:

There is a bug in the implementation of this function.

Here is the corrected version:

Many thanks, Dominik! As always, very much appreciated.

Thanks.

 
Fernando Carreiro #:

Your code should verify the trade session times using SymbolInfoSessionTrade(), as trading will not be disabled, just temporarily closed:

Is it showing GMT, Server time or Local time ?   I can probably find out by letting the EA print those alternative timestamps to the log in the moment of a TRADE_RETCODE_MARKET_CLOSED situation.
 
You also might sometimes want to avoid leaving a trade open after the market closes (especially if it's in a loss and not a "smart" trade). I made a function which will close any trade that's in a certain loss just before the market would close.
 
Conor Mcnamara #:
You also might sometimes want to avoid leaving a trade open after the market closes (especially if it's in a loss and not a "smart" trade). I made a function which will close any trade that's in a certain loss just before the market would close.
That is one of the things I try to implement. For now I will try to base my calculations on SymbolInfoSessionTrade responses. I have not concluded fully if market open hours are expressed in some particular time zone format. What I have seen looks GMT to me. I assume if I do historical backtesting that such queries will reflect settings in effect at that time.  
Reason: