mirror of
https://github.com/Xe138/AI-Trader.git
synced 2026-04-04 10:07:23 -04:00
feat: implement date range API and on-demand downloads (WIP phase 2)
Phase 2 progress - API integration complete. API Changes: - Replace date_range (List[str]) with start_date/end_date (str) - Add automatic end_date defaulting to start_date for single day - Add date format validation - Integrate PriceDataManager for on-demand downloads - Add rate limit handling (trusts provider, no pre-config) - Validate date ranges with configurable max days (MAX_SIMULATION_DAYS) New Modules: - api/date_utils.py - Date validation and expansion utilities - scripts/migrate_price_data.py - Migration script for merged.jsonl API Flow: 1. Validate date range (start <= end, max 30 days, not future) 2. Check missing price data coverage 3. Download missing data if AUTO_DOWNLOAD_PRICE_DATA=true 4. Priority-based download (maximize date completion) 5. Create job with available trading dates 6. Graceful handling of partial data (rate limits) Configuration: - AUTO_DOWNLOAD_PRICE_DATA (default: true) - MAX_SIMULATION_DAYS (default: 30) - No rate limit configuration needed Still TODO: - Update tools/price_tools.py to read from database - Implement simulation run tracking - Update .env.example - Comprehensive testing - Documentation updates Breaking Changes: - API request format changed (date_range -> start_date/end_date) - This completes v0.3.0 preparation
This commit is contained in:
93
api/date_utils.py
Normal file
93
api/date_utils.py
Normal file
@@ -0,0 +1,93 @@
|
||||
"""
|
||||
Date range utilities for simulation date management.
|
||||
|
||||
This module provides:
|
||||
- Date range expansion
|
||||
- Date range validation
|
||||
- Trading day detection
|
||||
"""
|
||||
|
||||
import os
|
||||
from datetime import datetime, timedelta
|
||||
from typing import List
|
||||
|
||||
|
||||
def expand_date_range(start_date: str, end_date: str) -> List[str]:
|
||||
"""
|
||||
Expand date range into list of all dates (inclusive).
|
||||
|
||||
Args:
|
||||
start_date: Start date (YYYY-MM-DD)
|
||||
end_date: End date (YYYY-MM-DD)
|
||||
|
||||
Returns:
|
||||
Sorted list of dates in range
|
||||
|
||||
Raises:
|
||||
ValueError: If dates are invalid or start > end
|
||||
"""
|
||||
start = datetime.strptime(start_date, "%Y-%m-%d")
|
||||
end = datetime.strptime(end_date, "%Y-%m-%d")
|
||||
|
||||
if start > end:
|
||||
raise ValueError(f"start_date ({start_date}) must be <= end_date ({end_date})")
|
||||
|
||||
dates = []
|
||||
current = start
|
||||
|
||||
while current <= end:
|
||||
dates.append(current.strftime("%Y-%m-%d"))
|
||||
current += timedelta(days=1)
|
||||
|
||||
return dates
|
||||
|
||||
|
||||
def validate_date_range(
|
||||
start_date: str,
|
||||
end_date: str,
|
||||
max_days: int = 30
|
||||
) -> None:
|
||||
"""
|
||||
Validate date range for simulation.
|
||||
|
||||
Args:
|
||||
start_date: Start date (YYYY-MM-DD)
|
||||
end_date: End date (YYYY-MM-DD)
|
||||
max_days: Maximum allowed days in range
|
||||
|
||||
Raises:
|
||||
ValueError: If validation fails
|
||||
"""
|
||||
# Parse dates
|
||||
try:
|
||||
start = datetime.strptime(start_date, "%Y-%m-%d")
|
||||
end = datetime.strptime(end_date, "%Y-%m-%d")
|
||||
except ValueError as e:
|
||||
raise ValueError(f"Invalid date format: {e}")
|
||||
|
||||
# Check order
|
||||
if start > end:
|
||||
raise ValueError(f"start_date ({start_date}) must be <= end_date ({end_date})")
|
||||
|
||||
# Check range size
|
||||
days = (end - start).days + 1
|
||||
if days > max_days:
|
||||
raise ValueError(
|
||||
f"Date range too large: {days} days (max: {max_days}). "
|
||||
f"Reduce range or increase MAX_SIMULATION_DAYS."
|
||||
)
|
||||
|
||||
# Check not in future
|
||||
today = datetime.now().date()
|
||||
if end.date() > today:
|
||||
raise ValueError(f"end_date ({end_date}) cannot be in the future")
|
||||
|
||||
|
||||
def get_max_simulation_days() -> int:
|
||||
"""
|
||||
Get maximum simulation days from environment.
|
||||
|
||||
Returns:
|
||||
Maximum days allowed in simulation range
|
||||
"""
|
||||
return int(os.getenv("MAX_SIMULATION_DAYS", "30"))
|
||||
Reference in New Issue
Block a user