Compare commits

...

2 Commits

Author SHA1 Message Date
rob ab217e247f Allow omitting limit to return all candles in range
Change default limit from 100 to None. When limit is omitted,
EDM returns all candles in the requested range without truncation.

Also increased max limit from 1000 to 10000 for large requests.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-08 01:26:31 -04:00
rob e14a607bfc Fix SINCE mode requests returning wrong data
When requesting candles with start date but no end date (SINCE mode),
EDM was skipping gap processing entirely because gap_end was None.
This caused requests to return cached data clipped to the most recent
N candles, ignoring the requested start date.

Fix: Normalize gaps with end=None to use current time, so SINCE mode
requests properly fetch data from the requested start time to now.

Bug symptoms:
- Request start=2026-03-01, limit=100
- Got 100 candles starting from 2026-03-04 (most recent 100)
- Expected 100 candles starting from 2026-03-01

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-08 01:15:47 -04:00
2 changed files with 15 additions and 1 deletions

View File

@ -283,7 +283,7 @@ async def get_candles(
timeframe: str = Query(..., description="Candle timeframe (e.g., 5m, 1h)"), timeframe: str = Query(..., description="Candle timeframe (e.g., 5m, 1h)"),
start: Optional[int] = Query(None, description="Start timestamp (Unix seconds)"), start: Optional[int] = Query(None, description="Start timestamp (Unix seconds)"),
end: Optional[int] = Query(None, description="End timestamp (Unix seconds)"), end: Optional[int] = Query(None, description="End timestamp (Unix seconds)"),
limit: Optional[int] = Query(100, description="Maximum candles to return", le=1000), limit: Optional[int] = Query(None, description="Maximum candles to return (omit for all)", le=10000),
session_id: Optional[str] = Query( session_id: Optional[str] = Query(
None, None,
description="Optional session ID for per-session exchange credentials", description="Optional session ID for per-session exchange credentials",

View File

@ -189,6 +189,20 @@ class CacheManager:
source = "exchange" if exchange_candles else "memory" source = "exchange" if exchange_candles else "memory"
return result, source return result, source
# Step 2b: Handle SINCE mode (start provided, no end)
# Gaps with end=None need to be fetched from exchange directly
import time as time_module
now = int(time_module.time())
normalized_gaps = []
for gap_start, gap_end in gaps_to_fill:
if gap_start is not None and gap_end is None:
# SINCE mode: fetch from start to now
normalized_gaps.append((gap_start, now))
elif gap_start is not None and gap_end is not None:
normalized_gaps.append((gap_start, gap_end))
# Skip gaps where start is None (shouldn't happen with proper request)
gaps_to_fill = normalized_gaps if normalized_gaps else gaps_to_fill
db_hit = False db_hit = False
exchange_hit = False exchange_hit = False