Parse yield curve date without time zone conversion - #9
Merged
AlexCatarino merged 1 commit intoAug 10, 2026
Merged
Conversation
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
USTreasuryYieldCurveRate.Readerparses the CSV date withDateTimeStyles.AssumeUniversal. WithoutAdjustToUniversal, that style treats the string as UTC and then converts the result to the machine local time, returning aDateTimewithKind = Local. The Reader truncates that value with.Datebefore stamping it at 16:30, so the truncation happens after the shift:20190724parses toTimeEvery 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.Noneleaves the date unshifted withKind = Unspecified, which is also the correct semantics here: the value is a US Treasury business date in ET, not a UTC instant.AssumeUniversal | AdjustToUniversalwould produce the same instant but stampKind = Utc, mislabeling it.This is the only parse affected.
USTreasuryYieldCurveConverterusesAdjustToUniversalalone at line 99, which performs no conversion on a time-zone-less string and is sort-only regardless, andParse.DateTimeelsewhere, which defaults toDateTimeStyles.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 thatTime.KindisUnspecified.The kind assertion is the part that matters for CI: a value-only assertion passes on a UTC runner and would not guard anything.
Kindpropagates through.Dateand.AddHours, so before this changeTime.KindisLocalon every machine including UTC. Verified locally (UTC+1) that the test fails against the old parse:and that the full fixture passes with the fix (4/4, net10.0).
Types of changes
Checklist:
🤖 Generated with Claude Code