cryptogold-prime / data_processor.py
omniverse1's picture
Update Gradio app with multiple files
a469221 verified
import yfinance as yf
import pandas as pd
import numpy as np
from datetime import datetime, timedelta
class DataProcessor:
def __init__(self):
self.fundamentals_cache = {}
def get_market_data(self, ticker="GC=F", interval="1d"):
"""Fetch market data from Yahoo Finance for a given ticker"""
try:
interval_map = {
"5m": "5m",
"15m": "15m",
"30m": "30m",
"1h": "60m",
"4h": "240m",
"1d": "1d",
"1wk": "1wk",
"1mo": "1mo",
"3mo": "3mo"
}
yf_interval = interval_map.get(interval, "1d")
if interval in ["5m", "15m", "30m", "1h", "4h"]:
period = "60d"
elif interval in ["1d"]:
period = "1y"
elif interval in ["1wk"]:
period = "2y"
else:
period = "max"
ticker_obj = yf.Ticker(ticker)
df = ticker_obj.history(interval=yf_interval, period=period)
if df.empty:
raise ValueError(f"No data retrieved from Yahoo Finance for {ticker}")
df.columns = [col.capitalize() for col in df.columns]
return df
except Exception as e:
print(f"Error fetching data for {ticker}: {e}")
return pd.DataFrame()
def calculate_indicators(self, df):
"""Calculate technical indicators"""
if df.empty:
return df
# Simple Moving Averages (5, 20 as requested)
df['SMA_5'] = df['Close'].rolling(window=5).mean()
df['SMA_20'] = df['Close'].rolling(window=20).mean()
# Exponential Moving Averages
df['EMA_12'] = df['Close'].ewm(span=12, adjust=False).mean()
df['EMA_26'] = df['Close'].ewm(span=26, adjust=False).mean()
# MACD (12, 26, 9)
df['MACD'] = df['EMA_12'] - df['EMA_26']
df['MACD_signal'] = df['MACD'].ewm(span=9, adjust=False).mean()
df['MACD_histogram'] = df['MACD'] - df['MACD_signal']
# Split histogram into positive and negative for plotting
df['MACD_bar_positive'] = df['MACD_histogram'].where(df['MACD_histogram'] > 0, 0)
df['MACD_bar_negative'] = df['MACD_histogram'].where(df['MACD_histogram'] < 0, 0)
# 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))
# Bollinger Bands
df['BB_middle'] = df['Close'].rolling(window=20).mean()
bb_std = df['Close'].rolling(window=20).std()
df['BB_upper'] = df['BB_middle'] + (bb_std * 2)
df['BB_lower'] = df['BB_middle'] - (bb_std * 2)
# Average True Range (ATR)
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 = ranges.max(axis=1)
df['ATR'] = true_range.rolling(window=14).mean()
# Volume indicators
df['Volume_SMA'] = df['Volume'].rolling(window=20).mean()
df['Volume_ratio'] = df['Volume'] / df['Volume_SMA']
# Stochastic Oscillator (14, 3)
low_14 = df['Low'].rolling(window=14).min()
high_14 = df['High'].rolling(window=14).max()
df['%K'] = 100 * (df['Close'] - low_14) / (high_14 - low_14)
df['%D'] = df['%K'].rolling(window=3).mean()
df['%SD'] = df['%D'].rolling(window=3).mean()
df['UL'] = 70 # Upper limit
df['DL'] = 30 # Lower limit
return df
def get_fundamental_data(self, ticker="GC=F"):
"""Get fundamental gold market data (now generalized/mocked)"""
try:
if ticker == "BTC-USD":
fundamentals = {
"Crypto Volatility Index": round(np.random.uniform(50, 150), 1),
"Dominance Index": f"{np.random.uniform(40, 60):.2f}%",
"Fear & Greed Index": np.random.choice(["Extreme Fear", "Fear", "Neutral", "Greed", "Extreme Greed"]),
"Hash Rate Trend": np.random.choice(["Increasing", "Stable", "Decreasing"]),
"Institutional Flow (Net)": f"{np.random.uniform(-100, 100):,.0f}M USD",
"Market Sentiment": np.random.choice(["Bullish", "Neutral", "Bearish"]),
}
else:
fundamentals = {
"Gold Strength Index": round(np.random.uniform(30, 80), 1),
"Dollar Index (DXY)": round(np.random.uniform(90, 110), 1),
"Real Interest Rate": f"{np.random.uniform(-2, 5):.2f}%",
"Gold Volatility": f"{np.random.uniform(10, 40):.1f}%",
"Commercial Hedgers (Net)": f"{np.random.uniform(-50000, 50000):,.0f}",
"Managed Money (Net)": f"{np.random.uniform(-100000, 100000):,.0f}",
"Market Sentiment": np.random.choice(["Bullish", "Neutral", "Bearish"]),
}
return fundamentals
except Exception as e:
print(f"Error fetching fundamentals: {e}")
return {"Error": str(e)}
def prepare_for_chronos(self, df, lookback=100):
"""Prepare data for Chronos model"""
if df.empty or len(df) < lookback:
return None
prices = df['Close'].iloc[-lookback:].values
prices = prices.astype(np.float32)
mean = np.mean(prices)
std = np.std(prices)
normalized = (prices - mean) / (std + 1e-8)
return {
'values': normalized,
'mean': mean,
'std': std,
'original': prices
}