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

 

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:

Trading hours

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

I tried unsuccessfully with this code:
if ( SymbolInfoInteger(_Symbol,SYMBOL_TRADE_MODE) != SYMBOL_TRADE_MODE_FULL ) break;

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

Thank you in advance.

Zsolt

 
Zsolt Haromszeki: 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.

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

Forum on trading, automated trading systems and testing trading strategies

Forex time and Backtest operations during Weekends

Fernando Carreiro, 2021.06.12 02:34

No, not every candle is tradable! Just as I wrote, there times on any symbol, not just Forex, that no trading is allowed. When you pull up the contract specifications for a symbol, you can see at which times the sessions close for trading.


You should use the MQL function SymbolInfoSessionTrade() to obtain data about these sessions and prevent your EA logic from trying to place orders or manage existing positions during those periods.

Also, the only reasons to close positions on a Friday night and open them again on a Monday morning, is if you wish to manage opening weekend gaps or reduce swap costs. If you are trying to reduce swap costs, then you would also need to close positions a few minutes before midnight and reopen them again a few minutes after midnight every day of the week. This is especially important on Wednesday night where triple-swaps are applied.

Documentation on MQL5: Market Info / SymbolInfoSessionTrade
Documentation on MQL5: Market Info / SymbolInfoSessionTrade
  • www.mql5.com
SymbolInfoSessionTrade - Market Info - MQL5 Reference - Reference on algorithmic/automated trading language for MetaTrader 5
 
Fernando Carreiro:

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

Thank you very much Fernando!
 

Sometimes the candle doesn't close when they said it would with SymbolInfoSessionTrade() .

During my backtesting I had a friday candle close at 18:47 but SymbolInfoSessionTrade() said 23:58 was the end of the session.

I only use server time TimeCurrent() in my code to get Datetime informations.

Documentation on MQL5: Market Info / SymbolInfoSessionTrade
Documentation on MQL5: Market Info / SymbolInfoSessionTrade
  • www.mql5.com
SymbolInfoSessionTrade - Market Info - MQL5 Reference - Reference on algorithmic/automated trading language for MetaTrader 5
 

@Fernando Carreiro I saw in other topics that you already spoke about SymoblInfoSessionTrade() 

I tried the other approach you mentionned far before too (enabling hours only during open trading session with 2 inputs). I still have [market closed] error during backtesting.

Sorry for that but I didn't find in the MQL5 forums an example of the use of SymbolInfoSessionTrade().


May someone write down here the code that could be implement in an EA in order to backtest correctly whatever the Symbol ?

Thanks.

 
turfu22 #: Sometimes the candle doesn't close when they said it would with SymbolInfoSessionTrade() .
You can't know when a candle closes. Only when a new tick arrives that starts a new bar is the old bar closed.
 
Search for function IsNewBar()
 

Here is my function to solve the issue:


//+------------------------------------------------------------------+
//| SymbolInfoSessionTimes()                                         |
//+------------------------------------------------------------------+
bool SymbolInfoSessionTimes(const string symbol, long& session_begin, long& session_end, long& next_session, const bool quote_sessions = false, const long reference_time = NULL)
{
    // Local cache
    
        static  string  c_symbol    = NULL;
        static  bool    c_quotes    = false;
        static  long    c_ref_time  = NULL;
        static  ulong   c_timestamp = NULL;
        static  long    c_begin     = NULL;
        static  long    c_end       = NULL;
        static  long    c_next      = NULL;


    // Cache update
    
        if( (c_symbol == symbol)
         && (c_quotes == quote_sessions)
         && (c_ref_time == reference_time) 
         && (c_timestamp > GetTickCount64() - 1000) )
        {
            session_begin   = c_begin;
            session_end     = c_end;
            next_session    = c_next;
            return(true);
        }
        c_symbol    = symbol;
        c_quotes    = quote_sessions;
        c_timestamp = GetTickCount64();


    // Pre init

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

    // Local init

                ulong           start           = NULL;
                ulong           finish          = NULL;
                ulong           day_start       = time_current - (time_current % 0x0000000000015180) - 0x0000000000015180;
                ulong           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, DayOfWeekToEnum(mql_time.day_of_week + cnt), (int)(session_index++), start, finish)) 
                                                        && !_StopFlag);
                                        }
                                        else
                                        {
                                                while( ((day_start + finish) <= time_current)
                                                        && (mqlplus::SymbolInfoSessionTrade(symbol, 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           = (long)(day_start + start);
                                                session_end             = (long)(day_start + finish);
                                        }

                                        // Search for beginning of session
                                        if(session_begin > NULL)
                                        {
                                                // Init loop
                                                int             session_index1  = NULL;
                                                int             max_count               = NULL;
                                                ulong       local_begin     = NULL;
                                                ulong       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_begin     = NULL;
                                                        local_end       = NULL;
                
                                                        // Loop backwards
                                                        if(quote_sessions)
                                                        {
                                                                while( ((session_index1 < max_count) || (max_count == NULL))
                                                                        && (mqlplus::SymbolInfoSessionQuote(symbol, DayOfWeekToEnum(mql_time.day_of_week - cnt1), (int)(session_index1++), start, finish)) 
                                                                        && ((long)(day_start + finish) <= session_begin) 
                                                                        && !_StopFlag)
                                                                {
                                                                        local_begin = (day_start + start);
                                                                        local_end   = (day_start + finish);
                                                                }
                                                        }
                                                        else
                                                        {
                                                                while( ((session_index1 < max_count) || (max_count == NULL))
                                                                        && (mqlplus::SymbolInfoSessionTrade(symbol, DayOfWeekToEnum(mql_time.day_of_week - cnt1), (int)(session_index1++), start, finish)) 
                                                                        && ((long)(day_start + finish) <= session_begin) 
                                                                        && !_StopFlag)
                                                                {
                                                                        local_begin = (day_start + start);
                                                                        local_end   = (day_start + finish);
                                                                }
                                                        }
                                                                
                                                        // Repeat search on same day if more than one session
                                                        if(session_begin == local_end)
                                                        {
                                                                session_begin   = (long)(local_begin);
                                                                cnt1           -= 1 * (session_index1 > 0x01);
                                                                max_count       = session_index1;
                                                        }

                                                        cnt1 |= 0xFF * (session_begin > (long)local_end);
                                                }
                                                
                                                // Reset day_start variable
                                                day_start = time_current - (time_current % 0x0000000000015180);
                                        }
                                        
                                        // Check for multiple sessions
                                        if( ((long)(day_start + start) > session_end) 
                                         && (finish > NULL))
                                        {
                                                next_session            = (long)(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, DayOfWeekToEnum(mql_time.day_of_week + cnt), (int)(session_index++), start, finish))
                                                { continue; }
                                        }
                                        else 
                                        {
                                                if(!mqlplus::SymbolInfoSessionTrade(symbol, DayOfWeekToEnum(mql_time.day_of_week + cnt), (int)(session_index++), start, finish))
                                                { continue; }
                                        }
                                        
                                        // Next found session                 
                                        next_session                = (long)(day_start + start) * (session_end < (long)(day_start + start));
                                        session_end                 = (long)((session_end * (next_session > NULL)) + ((day_start + finish) * (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(false);
}

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


}


EDIT:


Please see this post with bug-fixed version of this code:

https://www.mql5.com/en/forum/373227/page3#comment_52249679

How to check 'Market is closed' befor opening a position?
How to check 'Market is closed' befor opening a position?
  • 2022.07.17
  • www.mql5.com
Dear Coders! I started a backtest. My expert advisor is trying to open a position immediately at time 00:00...
 

And you need this:

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

 
Dominik Egert #:

And you need this:

Thank you @Dominik Egert

I will try to implement it.

 

Welcome.


here some Instructions on how to use the function:

SymbolInfoSessionTimes(
        const string symbol,                    // Input: The symbol to which you want the session times
        long& session_begin,                    // Result, when the current running session has begun
        long& session_end,                      // Result, when the current running session will end
        long& next_session,                     // Result, when the next session will start
        const bool quote_sessions = false,      // Input: Wether you want trading session or quote session times
        const long reference_time = NULL)       // Input: The time now. Here you input the time to which you want to know the session details.

// The function returns -1 in all result fields if an error has occured.
// The result NULL in all result fields will indicate 24/7 session details.
// All inputs are in long, and can be given as datetime, wich is the native MQL type for times.

Reason: