Spaces:
Sleeping
Sleeping
| import numpy as np | |
| import pandas as pd | |
| def add_technical_indicators(df: pd.DataFrame) -> pd.DataFrame: | |
| df = df.copy() | |
| # RSI | |
| delta = df["Close"].diff() | |
| gain = delta.where(delta > 0, 0).rolling(window=14).mean() | |
| loss = -delta.where(delta < 0, 0).rolling(window=14).mean() | |
| rs = gain / loss | |
| 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 | |
| # Simple 50-day MA | |
| df["MA50"] = df["Close"].rolling(window=50).mean() | |
| # Log Volume | |
| df["Log_Volume"] = np.log(df["Volume"] + 1) | |
| df = df.dropna() | |
| return df | |
| def classify_signal(predicted_change: float, asset_type: str = "stock") -> str: | |
| """ | |
| predicted_change: percentage change predicted by model | |
| asset_type: 'stock' or 'crypto' | |
| """ | |
| # Crypto → larger natural volatility | |
| if asset_type == "crypto": | |
| if predicted_change > 3.0: | |
| return "STRONG BUY" | |
| if predicted_change > 0.8: | |
| return "BUY" | |
| if predicted_change < -3.0: | |
| return "STRONG SELL" | |
| if predicted_change < -0.8: | |
| return "SELL" | |
| return "HOLD" | |
| # Stock → tighter thresholds | |
| if predicted_change > 1.5: | |
| return "STRONG BUY" | |
| if predicted_change > 0.3: | |
| return "BUY" | |
| if predicted_change < -1.5: | |
| return "STRONG SELL" | |
| if predicted_change < -0.3: | |
| return "SELL" | |
| return "HOLD" | |
| def classify_volatility(df: pd.DataFrame, asset_type: str = "stock") -> str: | |
| returns = df["Close"].pct_change().dropna() | |
| vol = returns.std() | |
| # Crypto volatility bands | |
| if asset_type == "crypto": | |
| if vol < 0.02: | |
| return "Low" | |
| if vol < 0.05: | |
| return "Medium" | |
| return "High" | |
| # Stock volatility bands | |
| if vol < 0.008: | |
| return "Low" | |
| if vol < 0.02: | |
| return "Medium" | |
| return "High" | |