- Added FastAPI backend with core API endpoints for strategies, backtests, and data management. - Introduced Vue 3 frontend with a dark theme, enabling users to run backtests, adjust parameters, and compare results. - Implemented Pydantic schemas for request/response validation and SQLAlchemy models for database interactions. - Enhanced project structure with dedicated modules for services, routers, and components. - Updated dependencies in `pyproject.toml` and `frontend/package.json` to include FastAPI, SQLAlchemy, and Vue-related packages. - Improved `.gitignore` to exclude unnecessary files and directories.
98 lines
3.0 KiB
Python
98 lines
3.0 KiB
Python
"""
|
|
Data status and symbol information endpoints.
|
|
"""
|
|
from pathlib import Path
|
|
|
|
import pandas as pd
|
|
from fastapi import APIRouter
|
|
|
|
from api.models.schemas import DataStatusResponse, SymbolInfo
|
|
|
|
router = APIRouter()
|
|
|
|
# Base path for CCXT data
|
|
DATA_BASE = Path(__file__).parent.parent.parent / "data" / "ccxt"
|
|
|
|
|
|
def _scan_available_data() -> list[SymbolInfo]:
|
|
"""
|
|
Scan the data directory for available symbols and timeframes.
|
|
|
|
Returns list of SymbolInfo with date ranges and row counts.
|
|
"""
|
|
symbols = []
|
|
|
|
if not DATA_BASE.exists():
|
|
return symbols
|
|
|
|
# Structure: data/ccxt/{exchange}/{market_type}/{symbol}/{timeframe}.csv
|
|
for exchange_dir in DATA_BASE.iterdir():
|
|
if not exchange_dir.is_dir():
|
|
continue
|
|
exchange = exchange_dir.name
|
|
|
|
for market_dir in exchange_dir.iterdir():
|
|
if not market_dir.is_dir():
|
|
continue
|
|
market_type = market_dir.name
|
|
|
|
for symbol_dir in market_dir.iterdir():
|
|
if not symbol_dir.is_dir():
|
|
continue
|
|
symbol = symbol_dir.name
|
|
|
|
# Find all timeframes
|
|
timeframes = []
|
|
start_date = None
|
|
end_date = None
|
|
row_count = 0
|
|
|
|
for csv_file in symbol_dir.glob("*.csv"):
|
|
tf = csv_file.stem
|
|
timeframes.append(tf)
|
|
|
|
# Read first and last rows for date range
|
|
try:
|
|
df = pd.read_csv(csv_file, parse_dates=['timestamp'])
|
|
if not df.empty:
|
|
row_count = len(df)
|
|
start_date = df['timestamp'].min().strftime("%Y-%m-%d")
|
|
end_date = df['timestamp'].max().strftime("%Y-%m-%d")
|
|
except Exception:
|
|
pass
|
|
|
|
if timeframes:
|
|
symbols.append(SymbolInfo(
|
|
symbol=symbol,
|
|
exchange=exchange,
|
|
market_type=market_type,
|
|
timeframes=sorted(timeframes),
|
|
start_date=start_date,
|
|
end_date=end_date,
|
|
row_count=row_count,
|
|
))
|
|
|
|
return symbols
|
|
|
|
|
|
@router.get("/symbols", response_model=DataStatusResponse)
|
|
async def get_symbols():
|
|
"""
|
|
Get list of available symbols with their data ranges.
|
|
|
|
Scans the local data directory for downloaded OHLCV data.
|
|
"""
|
|
symbols = _scan_available_data()
|
|
return DataStatusResponse(symbols=symbols)
|
|
|
|
|
|
@router.get("/data/status", response_model=DataStatusResponse)
|
|
async def get_data_status():
|
|
"""
|
|
Get detailed data inventory status.
|
|
|
|
Alias for /symbols with additional metadata.
|
|
"""
|
|
symbols = _scan_available_data()
|
|
return DataStatusResponse(symbols=symbols)
|