Skip to content

Parse yield curve date without time zone conversion - #9

Merged
AlexCatarino merged 1 commit into
QuantConnect:masterfrom
AlexCatarino:fix-yieldcurve-date-timezone-shift
Aug 10, 2026
Merged

Parse yield curve date without time zone conversion#9
AlexCatarino merged 1 commit into
QuantConnect:masterfrom
AlexCatarino:fix-yieldcurve-date-timezone-shift

Conversation

@AlexCatarino

Copy link
Copy Markdown
Member

Description

USTreasuryYieldCurveRate.Reader parses the CSV date with DateTimeStyles.AssumeUniversal. Without AdjustToUniversal, that style treats the string as UTC and then converts the result to the machine local time, returning a DateTime with Kind = Local. The Reader truncates that value with .Date before stamping it at 16:30, so the truncation happens after the shift:

Machine time zone 20190724 parses to Resulting Time
Eastern 2019-07-23 20:00 2019-07-23 16:30
Pacific 2019-07-23 17:00 2019-07-23 16:30
UTC 2019-07-24 00:00 2019-07-24 16:30
W. Europe / Tokyo 2019-07-24 02:00 / 09:00 2019-07-24 16:30

Every data point is dated one day earlier than the Treasury published it on any machine west of UTC. The bug is latent on QC cloud servers and on the LEAN Docker image (both UTC), so it only surfaces on native or IDE runs of LEAN on a machine behind UTC, where it silently misdates the whole series rather than failing.

DateTimeStyles.None leaves the date unshifted with Kind = Unspecified, which is also the correct semantics here: the value is a US Treasury business date in ET, not a UTC instant. AssumeUniversal | AdjustToUniversal would produce the same instant but stamp Kind = Utc, mislabeling it.

This is the only parse affected. USTreasuryYieldCurveConverter uses AdjustToUniversal alone at line 99, which performs no conversion on a time-zone-less string and is sort-only regardless, and Parse.DateTime elsewhere, which defaults to DateTimeStyles.None.

Related Issue

None filed; found while debugging a local backtest whose yields were consistently stamped a day early.

Motivation and Context

Yields silently attributed to the wrong date on any local run behind UTC. Because it fails quietly and never reproduces in the cloud, it is expensive to track down from the algorithm side.

Requires Documentation Change

No.

How Has This Been Tested?

Added ReaderParsesDateWithoutTimeZoneShift, which asserts the resulting timestamp and that Time.Kind is Unspecified.

The kind assertion is the part that matters for CI: a value-only assertion passes on a UTC runner and would not guard anything. Kind propagates through .Date and .AddHours, so before this change Time.Kind is Local on every machine including UTC. Verified locally (UTC+1) that the test fails against the old parse:

Failed ReaderParsesDateWithoutTimeZoneShift
  Expected: Unspecified
  But was:  Local

and that the full fixture passes with the fix (4/4, net10.0).

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist:

  • My code follows the code style of this project.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have added tests to cover my changes.
  • All new and existing tests passed.

🤖 Generated with Claude Code

DateTimeStyles.AssumeUniversal treats the CSV date as UTC and then converts
it to the machine's local time, returning a DateTime with Kind Local. The
Reader truncates that value with .Date before stamping it at 16:30, so on
any machine west of UTC every data point was dated one day earlier than the
Treasury published it. The bug is latent on UTC servers and only corrupts
runs on local machines behind UTC.

Parse with DateTimeStyles.None instead, which keeps the date unshifted and
Kind Unspecified, matching the exchange-local business date the value
represents.

Add a Reader test asserting both the resulting timestamp and that its Kind
is Unspecified. The kind assertion fails regardless of the machine's time
zone, so it guards the regression even when the tests run on UTC.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@AlexCatarino
AlexCatarino merged commit e0df528 into QuantConnect:master Aug 10, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant