4

I'm having trouble figuring out which tradings session any particular time is in.

There are four possible sessions, show in this picture taken from ForexFactory.com

enter image description here

I have this method that I need to check is currentTime is during the specified trading session.

public bool IsTradingSession(TradingSession tradingSession, DateTime currentTime)
{
    //currentTime is in local time.


    //Regular session is 5PM - next day 5PM, this is the session in the picture.
    //Irregular sessions also occur for example late open (3AM - same day 5PM)  or early close (5PM - next day 11AM)
    DateTime sessionStart = Exchange.ToLocalTime(Exchange.CurrentSessionOpen);
    DateTime sessionEnd = Exchange.ToLocalTime(Exchange.CurrentSessionClose);

    if(tradingSession == TradingSession.Sydney)
        return ....... ? true : false;
    if(tradingSession == TradingSession.Tokyo)
        return ....... ? true : false;        
    if(tradingSession == TradingSession.London)
        return ....... ? true : false;
    if (tradingSession == TradingSession.NewYork)
        return ....... ? true : false;

    return false;
}

Use:

    bool isSydneySession = IsTradingSession(TradingSession.Sydney, CurrentTime);
    bool isTokyoSession = IsTradingSession(TradingSession.Tokyo, CurrentTime);
    bool isLondonSession = IsTradingSession(TradingSession.London, CurrentTime);
    bool isNewYorkSession = IsTradingSession(TradingSession.NewYork, CurrentTime);

Thank you

parliament
  • 21,544
  • 38
  • 148
  • 238
  • 1
    .NET DateTime is notoriously difficult to use correctly, especially with varying timezones. Consider looking at http://code.google.com/p/noda-time/ if you can influence the decision to use standard DateTime or not. – Eric J. Jul 11 '12 at 03:06
  • 1
    If `currentTime` is always in a consistent timezone then UTC isn't a necessity; it won't hurt to stick to local time for simplicity. – Kirk Broadhurst Jul 11 '12 at 03:58
  • @Kirk Broadhurst yes, this was my issue with dthorpe's answer as I mentioned in my comment – parliament Jul 11 '12 at 03:59
  • @user1267778 Depending on whether the trading session covers one or two days, you need to customise the function. Check my updated answer – Kirk Broadhurst Jul 11 '12 at 04:08
  • You have good answers below. But if you want some more about the fundamentals of programming for time, this can help - http://blogs.windwardreports.com/davidt/2009/11/what-every-developer-should-know-about-time.html – David Thielen Jul 11 '12 at 05:18

3 Answers3

3

I'd suggest writing a simple function for each trading session, which takes a DateTime and returns a bool indicating if it's open at that time.

var sydneyOpen = new TimeSpan(17, 0, 0);
var sydneyClose = new TimeSpan(2, 0, 0);
Func<DateTime, bool> isOpenInSydney = d => 
    (d.TimeOfDay > sydneyOpen || d.TimeOfDay < sydneyClose);

// same for other markets, write a function to check against two times

Then place these into a Dictionary<TradingSession, Func> like this for generic retrieval...

var marketHours = new Dictionary<TradingSession, Func<DateTime, bool>>();
marketHours.Add(TradingSession.Sydney, isOpenInSydney);
// add other markets...

And then your existing method simply selects the appropriate function for the given TradingSession and applies it

public bool IsTradingSession(TradingSession tradingSession, DateTime currentTime)
{
    var functionForSession = marketHours[tradingSession];
    return functionForSession(currentTime);
}

I don't believe you need UTC time here as long as your application only runs in a single timezone, but daylight savings might cause problems.


A nice way to account for the problem of trading sessions which cover two days, as opposed to just one day, is to write a helper that precisely considers whether it's a 'cross-day' trading session and applies a different rule for you:

private bool IsBetween(DateTime now, TimeSpan open, TimeSpan close)
{
    var nowTime = now.TimeOfDay;
    return (open < close
        // if open is before close, then now must be between them
        ? (nowTime > open && nowTime < close)
        // otherwise now must be *either* after open or before close
        : (nowTime > open || nowTime < close));
}

and then

var sydneyOpen = new TimeSpan(17, 0, 0);
var sydneyClose = new TimeSpan(2, 0, 0);
Func<DateTime, bool> isOpenInSydney = d => IsBetween(d, sydneyOpen, sydneyClose);
Kirk Broadhurst
  • 27,836
  • 16
  • 104
  • 169
  • using timespan objects for sydneyStart, sydneyEnd, tokyoStart... etc was how I originally started. The problem with this is d.TimeOfDay (lets say 8AM) is both before AND after sydneyClose = new TimeSpan(2,0,0) – parliament Jul 11 '12 at 04:06
  • why not? if currentTime = new DateTime(2012, 7, 10, 8, 00, 00) then currentTime.TimeOfDay (8AM) is after 7/10/2012 2AM sydneyClose and before 7/11/2012 2AM sydneyClose, no? – parliament Jul 11 '12 at 04:17
  • @user1267778 for any given time, it's after the previous close and before the next close. But you should only consider the open and close times for the current day, otherwise you will confuse yourself. This is what `TimeOfDay` does - limits you to the current 24 hour day. Makes things simpler! – Kirk Broadhurst Jul 11 '12 at 04:22
2

You can compare with > & < or compare ticks.

See related questions: Check if datetime instance falls in between other two datetime objects

To avoid the multiple if statements, you could also create a TradingSession object with start and end time and define a property/function to check if in session. When I have big switch or if blocks, it usually indicates a missed OO opportunity :)

TradingSession sydneySession = new TradingSession 
{
    StartTimeUtc = ...;
    EndTimeUtc = ...;
}

The trading session object could then have a property IsInSession.

public bool IsInSession
{
    get {
        return DateTime.UTCNow >= StartTimeUtc && DateTime.UTCNow <= EndTimeUtc;
    }
}

This uses UTC time to eliminate time zone issues.

Community
  • 1
  • 1
bryanmac
  • 38,941
  • 11
  • 91
  • 99
0

You need to normalize your local times to UTC. You can then compare times across regions.

For each trading session, you need to know the session start and end time in UTC.

You need the current time in UTC. DateTime.UtcNow, for example.

You can then perform range comparisons for each trading session window:

if(tradingSession == TradingSession.Sydney)
        return currentTimeUtc >= sydneyStartTimeUtc && currentTimeUtc <= sydneyEndTimeUtc;

etc...

If you're trying to validate that a transaction time is valid for a transaction on a particular trading session, this will work fine.

If however you're trying to figure out what trading session a trade belongs to based on its time, you will have multiple answers sometimes because the trading sessions overlap. Multiple trading sessions may be valid for a given time.

dthorpe
  • 35,318
  • 5
  • 75
  • 119
  • 1
    I'm still not wrapping my head around this. Please disregard the times in the picture inside the blue boxes for the sessions, that may have caused some confusion. All the times inside the method are in local time ei CurrentTime, sessionStart, sessionEnd, etc are all in local time (I edited my method to reflect this). Not seeing how it matters what time zone the comparisons are being made in as long as it's consistent for all times being compared. I think I'm still missing something. – parliament Jul 11 '12 at 03:56
  • Perhaps I'm confused as how to define the actual times for each individual session (sydneyStartTime, sydneyEndTime, tokyoStartTime, tokyoEndTime, etc) based on the OVERALL session start and end time (5pm - next day 5pm) which may or may not be IRREGULAR(for ex a late open 3AM - same day 5PM will skip the entire Sydney session and part of the Tokyo session only to open at the beginning of the London session. – parliament Jul 11 '12 at 03:57
  • You need to define your question better. – dthorpe Jul 11 '12 at 07:15