Download core/data_loader.py from SurgeSoftwareSolutions/intraday-btc-model-11yr: direct link, hf CLI and curl.
- Browser
- Download file 6.21 kB
-
https://huggingface.co/SurgeSoftwareSolutions/intraday-btc-model-11yr/resolve/main/core/data_loader.py
- Command line
-
hf download hf://SurgeSoftwareSolutions/intraday-btc-model-11yr/core/data_loader.py
-
curl -L -o data_loader.py https://huggingface.co/SurgeSoftwareSolutions/intraday-btc-model-11yr/resolve/main/core/data_loader.py
6.21 kB
| """ | |
| Data loader module for BTC 1-minute OHLCV data. | |
| This module handles loading, validation, and preprocessing of historical | |
| Bitcoin price data from CSV files. | |
| """ | |
| import pandas as pd | |
| import os | |
| from typing import Optional | |
| def load_data( | |
| filepath: str, | |
| start_date: Optional[str] = None, | |
| end_date: Optional[str] = None, | |
| validate: bool = True | |
| ) -> pd.DataFrame: | |
| """ | |
| Load BTC 1-minute OHLCV data from CSV file. | |
| Parameters | |
| ---------- | |
| filepath : str | |
| Path to the CSV file containing OHLCV data | |
| start_date : str, optional | |
| Start date for filtering (format: 'YYYY-MM-DD') | |
| end_date : str, optional | |
| End date for filtering (format: 'YYYY-MM-DD') | |
| validate : bool, default True | |
| Whether to validate the data integrity | |
| Returns | |
| ------- | |
| pd.DataFrame | |
| DataFrame with columns: timestamp, open, high, low, close, volume | |
| Indexed by timestamp | |
| Raises | |
| ------ | |
| FileNotFoundError | |
| If the file doesn't exist | |
| ValueError | |
| If required columns are missing or data is invalid | |
| """ | |
| if not os.path.exists(filepath): | |
| raise FileNotFoundError(f"Data file not found: {filepath}") | |
| # Load CSV | |
| print(f"Loading data from {filepath}...") | |
| df = pd.read_csv(filepath) | |
| # Validate required columns | |
| required_cols = ['timestamp', 'open', 'high', 'low', 'close', 'volume'] | |
| missing_cols = [col for col in required_cols if col not in df.columns] | |
| if missing_cols: | |
| raise ValueError(f"Missing required columns: {missing_cols}") | |
| # Convert timestamp to datetime | |
| df['timestamp'] = pd.to_datetime(df['timestamp']) | |
| # Sort by timestamp | |
| df = df.sort_values('timestamp').reset_index(drop=True) | |
| # Filter by date range if specified | |
| if start_date: | |
| df = df[df['timestamp'] >= pd.to_datetime(start_date)] | |
| if end_date: | |
| df = df[df['timestamp'] <= pd.to_datetime(end_date)] | |
| # Set timestamp as index | |
| df = df.set_index('timestamp') | |
| if validate: | |
| _validate_data(df) | |
| print(f"✓ Loaded {len(df)} bars from {df.index[0]} to {df.index[-1]}") | |
| return df | |
| def _validate_data(df: pd.DataFrame) -> None: | |
| """ | |
| Validate data integrity. | |
| Parameters | |
| ---------- | |
| df : pd.DataFrame | |
| DataFrame to validate | |
| Raises | |
| ------ | |
| ValueError | |
| If data validation fails | |
| """ | |
| # Check for missing values | |
| if df.isnull().any().any(): | |
| null_counts = df.isnull().sum() | |
| print(f"⚠ Warning: Found missing values:\n{null_counts[null_counts > 0]}") | |
| # Fill forward missing values | |
| df.fillna(method='ffill', inplace=True) | |
| print(" → Filled missing values using forward fill") | |
| # Validate OHLC relationships (with small tolerance for rounding) | |
| tolerance = 0.01 # Allow 1 cent of tolerance | |
| invalid_high = (df['high'] < df['low'] - tolerance).sum() | |
| invalid_open = ((df['open'] > df['high'] + tolerance) | (df['open'] < df['low'] - tolerance)).sum() | |
| invalid_close = ((df['close'] > df['high'] + tolerance) | (df['close'] < df['low'] - tolerance)).sum() | |
| if invalid_high > 0: | |
| print(f"⚠ Warning: Found {invalid_high} bars where high < low (fixing automatically)") | |
| # Fix by swapping | |
| mask = df['high'] < df['low'] | |
| df.loc[mask, ['high', 'low']] = df.loc[mask, ['low', 'high']].values | |
| if invalid_open > 0: | |
| print(f"⚠ Warning: Found {invalid_open} bars where open is outside [low, high] (fixing automatically)") | |
| # Clamp to range | |
| df['open'] = df['open'].clip(lower=df['low'], upper=df['high']) | |
| if invalid_close > 0: | |
| print(f"⚠ Warning: Found {invalid_close} bars where close is outside [low, high] (fixing automatically)") | |
| # Clamp to range | |
| df['close'] = df['close'].clip(lower=df['low'], upper=df['high']) | |
| # Check for negative prices or volume | |
| if (df[['open', 'high', 'low', 'close', 'volume']] < 0).any().any(): | |
| raise ValueError("Found negative prices or volume") | |
| # Check for zero prices (volume can be zero) | |
| if (df[['open', 'high', 'low', 'close']] == 0).any().any(): | |
| raise ValueError("Found zero prices") | |
| print("✓ Data validation passed") | |
| def get_data_summary(df: pd.DataFrame) -> dict: | |
| """ | |
| Get summary statistics for the dataset. | |
| Parameters | |
| ---------- | |
| df : pd.DataFrame | |
| OHLCV DataFrame | |
| Returns | |
| ------- | |
| dict | |
| Dictionary containing summary statistics | |
| """ | |
| summary = { | |
| 'num_bars': len(df), | |
| 'start_date': df.index[0], | |
| 'end_date': df.index[-1], | |
| 'duration_days': (df.index[-1] - df.index[0]).days, | |
| 'price_range': { | |
| 'min': df['low'].min(), | |
| 'max': df['high'].max(), | |
| 'mean': df['close'].mean(), | |
| 'std': df['close'].std() | |
| }, | |
| 'volume': { | |
| 'total': df['volume'].sum(), | |
| 'mean': df['volume'].mean(), | |
| 'median': df['volume'].median() | |
| } | |
| } | |
| return summary | |
| if __name__ == "__main__": | |
| # Test the data loader | |
| import sys | |
| sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) | |
| import config | |
| try: | |
| df = load_data(config.BTC_DATA_FILE) | |
| summary = get_data_summary(df) | |
| print("\nData Summary:") | |
| print(f" Bars: {summary['num_bars']:,}") | |
| print(f" Period: {summary['start_date']} to {summary['end_date']}") | |
| print(f" Duration: {summary['duration_days']} days") | |
| print(f" Price range: ${summary['price_range']['min']:.2f} - ${summary['price_range']['max']:.2f}") | |
| print(f" Mean price: ${summary['price_range']['mean']:.2f}") | |
| except FileNotFoundError: | |
| print("⚠ Data file not found. Please add btc_1m.csv to the data/ directory.") | |
| except Exception as e: | |
| print(f"✗ Error: {e}") | |