Why do the clocks disagree?
The clocks disagree because London and New York each move their clocks for daylight saving on different dates, Tokyo does not move at all, and most broker feeds are stamped in a server time that follows one of those conventions or none of them.
For most of the year the offset between any two of these is constant, and a rule written against one of them is correct. For a few weeks each spring and autumn, when one centre has changed and another has not, the offsets shift by an hour. A fixed offset from the feed's timestamp to the London open is then wrong by an hour for those weeks, and so is every rule that uses it.
Broker server time adds a further layer. Many brokers stamp bars in a time that tracks New York with a fixed offset, so that the daily bar closes at the New York close, and that time changes with New York's clock rather than London's. A trader who assumes the feed is in UTC, or in their own local time, has an error that varies through the year.
The disagreement is small in hours and large in effect, because the hours it moves are precisely the ones session rules care about.
Which rules does it corrupt?
It corrupts every rule that references a clock: session filters, opening-range definitions, daily and weekly bar boundaries, time-of-day exits, and any rule that avoids or targets a scheduled event by its hour.
Session filters are the obvious victims. A rule that trades only between two fixed hours of the feed's time is trading a window that slides against the actual London or New York open by an hour for several weeks a year. The trades taken in those weeks are from the wrong hours, and over a decade they are a meaningful share of the sample.
Daily bars are the less obvious victims. The daily open, high, low and close depend on where the day is cut, and a feed that cuts it at the New York close produces different daily bars from one that cuts it at midnight UTC. Any rule built on the daily bar, such as a daily range breakout or a rule that reads yesterday's close, is a different rule on each feed, and the difference is not visible on a chart.
Weekly bars and event times inherit the same problem. A weekly bar that starts on Sunday evening in one convention starts on Monday morning in another, and a scheduled release at half past eight in one city is a different hour of the feed depending on the season.
How do you detect it in your data?
Detect it by profiling activity by hour of the feed's clock across the year and looking for the step change at the daylight-saving dates, and by checking the timestamps of bars around a known transition against what the exchange clock says they should be.
The activity profile is the quickest check. Average the bar range or the tick count by hour of the day, separately for the weeks before and after each daylight-saving transition. If the feed's clock follows one centre, the profile for the other centre's hours will jump by an hour at that centre's transition date. The jump tells you which centre the feed follows, and that the other one is drifting relative to it.
The timestamp check is the precise one. Take a date on which London and New York had different daylight-saving states and look at the bar that contains a known event, such as the New York equity open. Its timestamp in the feed, compared with the known local time of the event, gives the feed's offset on that date. Repeat for a date in the other state and the two offsets show whether the feed moved with London, with New York, or with neither.
Once the convention is known, it should be written down next to the data, because it is not recoverable from the bars themselves and every rule depends on it.
How do you define time so it stays put?
Define every clock reference in a named local timezone, London time for the London session and New York time for the New York session, convert it to the feed's time per date using the actual daylight-saving rules of that zone, and state the daily-bar boundary as a convention rather than inheriting one.
Naming the zone is the fix for sessions. A rule that says the first three hours after the London open, in London time, is the same rule in every week of the year, and the conversion to the data's clock is done for each date by a timezone library that knows when London changed. The offset is then a function of the date, which is what it always was.
The daily boundary is a choice and the honest thing is to make it explicit. Cutting the day at the New York close produces daily bars that match most retail charts; cutting at midnight UTC produces bars that match most institutional data. A rule that reads daily values should say which, and a backtest of it on the other convention is a backtest of a different rule.
The result should carry the convention with it. A session result that does not state its zone and its daily boundary cannot be reproduced on another feed, and a comparison between two such results is a comparison between two unknown rules.
How does QuantParadox handle time?
QuantParadox stores its archive in a single reference time and defines each session in the local time of its market centre, so the London, New York and Tokyo sessions are converted per date with the actual daylight-saving rules of each zone, and a rule stated in a session's local hours means the same thing across the whole decade.
Clock windows stated in hours and minutes are resolved the same way, against a named zone, so a kill-zone or opening-range rule written in London time is graded on the London hours in every week of the year rather than on a fixed offset that drifts.
The daily-bar boundary on the platform is a stated convention rather than a broker's, and a rule that depends on a specific broker's daily close has to say so; a daily-range rule ported from a feed with a different boundary will produce different daily bars and should be checked for agreement on a sample of days before its results are compared.
The reason to be explicit about all of this is that the error it prevents is invisible in a result. A session rule graded on drifting hours does not fail; it produces a number that is quietly wrong for a tenth of the history, and the only defence is a definition that does not drift.