simple_volatility_checker.py•5.72 kB
# simple_volatility_check.py - Simple volatility analysis for ARIMA suitability
import yfinance as yf
import pandas as pd
import numpy as np
import json
from pathlib import Path
import warnings
warnings.filterwarnings('ignore')
def load_portfolio_config(config_path: str = "config/trading_config.json"):
"""Load portfolio configuration."""
try:
with open(config_path, 'r') as f:
return json.load(f)
except Exception as e:
print(f"❌ Error loading config: {e}")
return {"tickers": {"default": ["AAPL", "MSFT", "GOOGL"]}}
def analyze_stock_volatility(ticker: str):
"""Analyze single stock volatility."""
try:
# Download 1 year of data
data = yf.download(ticker, period="1y", progress=False)
if data.empty:
return {"ticker": ticker, "error": "No data"}
close = data['Close'].dropna()
returns = close.pct_change().dropna()
# Calculate volatility
daily_vol = float(returns.std())
max_change = float(returns.abs().max())
# Classify
crypto_keywords = ['COIN', 'BTC', 'ETH', 'GBTC', 'MSTR', 'HOOD']
is_crypto = any(keyword in ticker.upper() for keyword in crypto_keywords)
if daily_vol > 0.05:
vol_class = "EXTREME"
arima_suitable = "NO"
elif daily_vol > 0.03:
vol_class = "HIGH"
arima_suitable = "MAYBE"
else:
vol_class = "MODERATE"
arima_suitable = "YES"
if is_crypto and arima_suitable == "YES":
arima_suitable = "MAYBE"
return {
"ticker": ticker,
"daily_volatility": daily_vol,
"vol_class": vol_class,
"max_1day_change": max_change,
"is_crypto": is_crypto,
"arima_suitable": arima_suitable
}
except Exception as e:
return {"ticker": ticker, "error": str(e)}
def main():
"""Main function."""
import argparse
parser = argparse.ArgumentParser(description="Simple volatility check for ARIMA suitability")
parser.add_argument('--portfolio', type=str, help='Portfolio name from config')
parser.add_argument('--tickers', nargs='+', help='Specific tickers')
args = parser.parse_args()
config = load_portfolio_config()
if args.tickers:
tickers = args.tickers
desc = f"specified tickers: {', '.join(tickers)}"
elif args.portfolio:
tickers = config.get("tickers", {}).get(args.portfolio, [])
if not tickers:
print(f"❌ Portfolio '{args.portfolio}' not found")
print("Available portfolios:")
for name in config.get("tickers", {}).keys():
print(f" - {name}")
return
desc = f"'{args.portfolio}' portfolio"
else:
print("🔍 SIMPLE VOLATILITY CHECKER")
print("Available portfolios:")
for name, stocks in config.get("tickers", {}).items():
print(f" • {name:<20} ({len(stocks):2d} stocks)")
print("\nUsage:")
print(" python simple_volatility_check.py --portfolio PORTFOLIO_NAME")
print(" python simple_volatility_check.py --tickers AAPL MSFT COIN")
return
print(f"🔍 Analyzing {desc}")
print("=" * 60)
print(f"{'Ticker':<8} {'Daily Vol':<10} {'Class':<10} {'ARIMA OK':<10} {'Crypto':<8}")
print("-" * 60)
suitable_stocks = []
problematic_stocks = []
for ticker in tickers:
result = analyze_stock_volatility(ticker)
if "error" in result:
print(f"{ticker:<8} {'ERROR':<10} {'N/A':<10} {'N/A':<10} {'N/A':<8}")
continue
vol = result["daily_volatility"]
vol_class = result["vol_class"]
arima_ok = result["arima_suitable"]
is_crypto = "YES" if result["is_crypto"] else "NO"
# Icons
if vol_class == "EXTREME":
class_icon = "🔴"
elif vol_class == "HIGH":
class_icon = "🟡"
else:
class_icon = "🟢"
if arima_ok == "YES":
arima_icon = "✅"
elif arima_ok == "MAYBE":
arima_icon = "⚠️ "
else:
arima_icon = "❌"
print(f"{ticker:<8} {vol:<10.1%} {class_icon}{vol_class:<9} {arima_icon}{arima_ok:<8} {is_crypto:<8}")
if arima_ok == "YES":
suitable_stocks.append(ticker)
else:
problematic_stocks.append(ticker)
print("-" * 60)
print(f"\n📊 SUMMARY:")
print(f" Total stocks: {len(tickers)}")
print(f" ✅ Suitable for ARIMA: {len(suitable_stocks)}")
print(f" ⚠️ Problematic: {len(problematic_stocks)}")
if suitable_stocks:
print(f"\n✅ OPTIMIZE THESE STOCKS:")
print(f" {', '.join(suitable_stocks)}")
print(f"\n Command: python preprocess_arima_params.py --tickers {' '.join(suitable_stocks)}")
if problematic_stocks:
print(f"\n⚠️ SKIP THESE STOCKS (use manual parameters):")
print(f" {', '.join(problematic_stocks)}")
print(f"\n💡 RECOMMENDATION:")
suitable_pct = len(suitable_stocks) / len(tickers) * 100
if suitable_pct >= 70:
print(f" Portfolio is {suitable_pct:.0f}% suitable - proceed with optimization")
elif suitable_pct >= 30:
print(f" Portfolio is {suitable_pct:.0f}% suitable - optimize suitable stocks only")
else:
print(f" Portfolio is {suitable_pct:.0f}% suitable - consider alternative approaches")
if __name__ == "__main__":
main()