Download data_engine.py from MrBro123/bott: direct link, hf CLI and curl.
- Browser
- Download file 3.74 kB
-
https://huggingface.co/spaces/MrBro123/bott/resolve/main/data_engine.py
- Command line
-
hf download hf://spaces/MrBro123/bott/data_engine.py
-
curl -L -o data_engine.py https://huggingface.co/spaces/MrBro123/bott/resolve/main/data_engine.py
3.74 kB
| import yfinance as yf | |
| import pandas as pd | |
| import numpy as np | |
| def fetch_data(symbol, period='2y', interval='1d'): | |
| """ | |
| Fetch historical data for a given symbol. | |
| Symbols: BTC-USD, ETH-USD, GC=F (Gold), CL=F (Oil), SI=F (Silver) | |
| """ | |
| ticker = yf.Ticker(symbol) | |
| df = ticker.history(period=period, interval=interval) | |
| return df | |
| def add_indicators(df): | |
| """ | |
| Add technical indicators manually to avoid dependency issues with pandas_ta on Python 3.14. | |
| """ | |
| # EMA for trend | |
| df['EMA_20'] = df['Close'].ewm(span=20, adjust=False).mean() | |
| df['EMA_50'] = df['Close'].ewm(span=50, adjust=False).mean() | |
| # RSI for momentum | |
| delta = df['Close'].diff() | |
| gain = (delta.where(delta > 0, 0)).rolling(window=14).mean() | |
| loss = (-delta.where(delta < 0, 0)).rolling(window=14).mean() | |
| # Handle division by zero safely | |
| rs = gain / loss.replace(0, np.finfo(float).eps) | |
| df['RSI'] = 100 - (100 / (1 + rs)) | |
| # MACD | |
| exp1 = df['Close'].ewm(span=12, adjust=False).mean() | |
| exp2 = df['Close'].ewm(span=26, adjust=False).mean() | |
| df['MACD'] = exp1 - exp2 | |
| df['MACD_Signal'] = df['MACD'].ewm(span=9, adjust=False).mean() | |
| # Bollinger Bands | |
| df['BB_Mid'] = df['Close'].rolling(window=20).mean() | |
| df['BB_Std'] = df['Close'].rolling(window=20).std() | |
| df['BB_Upper'] = df['BB_Mid'] + (df['BB_Std'] * 2) | |
| df['BB_Lower'] = df['BB_Mid'] - (df['BB_Std'] * 2) | |
| # ATR for volatility | |
| high_low = df['High'] - df['Low'] | |
| high_close = np.abs(df['High'] - df['Close'].shift()) | |
| low_close = np.abs(df['Low'] - df['Close'].shift()) | |
| ranges = pd.concat([high_low, high_close, low_close], axis=1) | |
| true_range = np.max(ranges, axis=1) | |
| df['ATR'] = true_range.rolling(window=14).mean() | |
| # Simple Candlestick Patterns | |
| # Hammer: Small body, long lower shadow, little/no upper shadow | |
| body = (df['Close'] - df['Open']).abs() | |
| range_ = df['High'] - df['Low'] | |
| # Hammer definition: lower shadow > 2 * body, upper shadow < body, body in upper 1/3 of range | |
| df['CDL_Hammer'] = (range_ > 3 * body) & \ | |
| ((df[['Open', 'Close']].min(axis=1) - df['Low']) > 2 * body) & \ | |
| ((df['High'] - df[['Open', 'Close']].max(axis=1)) < body) | |
| # Engulfing: Current body completely covers previous body with opposite direction | |
| prev_open = df['Open'].shift(1) | |
| prev_close = df['Close'].shift(1) | |
| # Bullish Engulfing | |
| bull_eng = (df['Close'] > df['Open']) & (prev_close < prev_open) & \ | |
| (df['Close'] > prev_open) & (df['Open'] < prev_close) | |
| # Bearish Engulfing | |
| bear_eng = (df['Close'] < df['Open']) & (prev_close > prev_open) & \ | |
| (df['Close'] < prev_open) & (df['Open'] > prev_close) | |
| df['CDL_Bull_Engulfing'] = bull_eng | |
| df['CDL_Bear_Engulfing'] = bear_eng | |
| df.dropna(inplace=True) | |
| return df | |
| def prepare_ml_data(df, window_size=10): | |
| """ | |
| Prepare sequences for the model. | |
| """ | |
| # Select numeric features only | |
| features = ['Open', 'High', 'Low', 'Close', 'Volume', 'EMA_20', 'EMA_50', 'RSI', 'MACD', 'ATR'] | |
| data = df[features].values | |
| # Target: Close price of the next day > current Close price | |
| target = (df['Close'].shift(-1) > df['Close']).astype(int).values | |
| X = [] | |
| y = [] | |
| for i in range(window_size, len(data) - 1): | |
| X.append(data[i-window_size:i]) | |
| y.append(target[i]) | |
| # Also return the latest window for prediction (we don't have target for this one) | |
| latest_window = data[len(data)-window_size:] | |
| return np.array(X), np.array(y), latest_window | |