Skip to content

Commit 7214262

Browse files
committed
fix: source shifts midnight-UTC to market close before API call (v0.1.6)
1 parent 95af061 commit 7214262

6 files changed

Lines changed: 46 additions & 5 deletions

File tree

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and
88

99
_No changes yet._
1010

11+
## [0.1.6] — 2026-06-02
12+
13+
### Fixed
14+
15+
- **`FlashAlphaSource.For` shifts midnight-UTC dates to 20:00 UTC (16:00 ET, NYSE close) before calling the API.** v0.1.5 still passed LEAN's daily-resolution timestamp (midnight UTC) straight through to FlashAlpha. The API only has market-hours data, so every daily-res request returned NoDataError → empty file → LEAN skipped the bar. Algorithms got 0 trades despite the bridge working. Now midnight-UTC dates are silently shifted to the session close; non-midnight times pass through unchanged so intraday subscriptions still get exactly what they asked for. Same fix in C# and Python.
16+
1117
## [0.1.5] — 2026-06-02
1218

1319
### Fixed

src/csharp/FlashAlpha.QuantConnect/Data/FlashAlphaSource.cs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@ public static SubscriptionDataSource For(string endpoint, Symbol symbol, DateTim
4747
// (NoDataException / NoCoverageException / InvalidAtException), write
4848
// an empty file so Parse returns null and LEAN skips the bar cleanly.
4949
//
50+
// Date shift: LEAN daily-res ticks midnight UTC but FlashAlpha has
51+
// market-hours data only. Shift midnight to 20:00 UTC (16:00 ET, NYSE
52+
// close) so the API returns the session's closing snapshot.
53+
var apiAt = ShiftToMarketHours(date);
54+
//
5055
// Transport: LocalFile — LEAN's RestSubscriptionStreamReader would try
5156
// to HTTP-fetch a URL, so a custom in-memory sentinel scheme isn't
5257
// workable. Writing JSON as a single-line file under the OS tempdir
@@ -56,7 +61,7 @@ public static SubscriptionDataSource For(string endpoint, Symbol symbol, DateTim
5661
try
5762
{
5863
payload = _http.Value
59-
.FetchJsonAsync(endpoint, symbol.Value, date)
64+
.FetchJsonAsync(endpoint, symbol.Value, apiAt)
6065
.GetAwaiter().GetResult();
6166
}
6267
catch (FlashAlpha.Historical.NoDataException)
@@ -87,6 +92,21 @@ public static SubscriptionDataSource For(string endpoint, Symbol symbol, DateTim
8792
FileFormat.Csv);
8893
}
8994

95+
/// <summary>
96+
/// LEAN daily-res ticks at midnight UTC but FlashAlpha has market-hours
97+
/// data only. Shift any midnight-UTC date to 20:00 UTC (16:00 ET, NYSE
98+
/// close) so the API returns the session's closing snapshot. Non-midnight
99+
/// dates pass through unchanged.
100+
/// </summary>
101+
private static DateTime ShiftToMarketHours(DateTime date)
102+
{
103+
if (date.Hour == 0 && date.Minute == 0 && date.Second == 0)
104+
{
105+
return date.AddHours(20);
106+
}
107+
return date;
108+
}
109+
90110
/// <summary>
91111
/// Parses <paramref name="line"/> (either the sentinel URL or raw JSON)
92112
/// into a new bar of type <typeparamref name="T"/>, populating its

src/csharp/FlashAlpha.QuantConnect/FlashAlpha.QuantConnect.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<PropertyGroup>
33
<PackageId>FlashAlpha.QuantConnect</PackageId>
44
<RootNamespace>FlashAlpha.QuantConnect</RootNamespace>
5-
<Version>0.1.5</Version>
5+
<Version>0.1.6</Version>
66
<Authors>FlashAlpha</Authors>
77
<Company>FlashAlpha</Company>
88
<Copyright>Copyright (c) 2026 FlashAlpha</Copyright>

src/python/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
44

55
[project]
66
name = "flashalpha-quantconnect"
7-
version = "0.1.5"
7+
version = "0.1.6"
88
description = "FlashAlpha options-flow and dealer-positioning data as QuantConnect LEAN custom-data bars. GEX, DEX, VEX, vol surface, 0DTE, VRP, max-pain."
99
readme = "README.md"
1010
license = "MIT"

src/python/src/flashalpha_quantconnect/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"""FlashAlpha options-flow data as QuantConnect LEAN custom-data bars."""
22

3-
__version__ = "0.1.5"
3+
__version__ = "0.1.6"
44

55
from . import config
66
from .data.exposure import (

src/python/src/flashalpha_quantconnect/data/source.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,20 @@ def _to_pascal_case(snake: str) -> str:
4646
return "".join(p.title() for p in snake.split("_"))
4747

4848

49+
def _shift_to_market_hours(date: datetime) -> datetime:
50+
"""LEAN daily-res ticks at midnight UTC, but FlashAlpha's historical API
51+
only has market-hours data. Shift any midnight-UTC date to 20:00 UTC
52+
(16:00 ET, NYSE close) so the API returns the session's closing snapshot.
53+
54+
Dates with non-midnight times pass through unchanged — callers that
55+
want a specific timestamp (intraday hourly subscriptions, etc.) get
56+
exactly what they asked for.
57+
"""
58+
if date.hour == 0 and date.minute == 0 and date.second == 0:
59+
return date.replace(hour=20, minute=0, second=0)
60+
return date
61+
62+
4963
def source_for(endpoint: str, symbol: Any, date: datetime) -> Any:
5064
"""Eagerly fetch the JSON for (endpoint, ticker, date), persist it to a
5165
temp file, return a ``SubscriptionDataSource`` pointing LEAN at the file.
@@ -80,8 +94,9 @@ def source_for(endpoint: str, symbol: Any, date: datetime) -> Any:
8094
ticker = symbol.Value
8195
key = _make_key(endpoint, ticker, date)
8296

97+
api_at = _shift_to_market_hours(date)
8398
try:
84-
payload = _get_client().fetch_json(endpoint=endpoint, ticker=ticker, at=date)
99+
payload = _get_client().fetch_json(endpoint=endpoint, ticker=ticker, at=api_at)
85100
line = json.dumps(payload)
86101
except (NoDataError, NoCoverageError, InvalidAtError):
87102
line = ""

0 commit comments

Comments
 (0)