Spaces:
Sleeping
Sleeping
File size: 16,643 Bytes
09f44d7 70205dc 09f44d7 70205dc 09f44d7 70205dc 09f44d7 70205dc 09f44d7 70205dc 09f44d7 70205dc 09f44d7 70205dc 09f44d7 70205dc 09f44d7 70205dc 09f44d7 70205dc 09f44d7 70205dc 09f44d7 70205dc 09f44d7 70205dc 09f44d7 70205dc 09f44d7 70205dc 09f44d7 70205dc 09f44d7 70205dc 09f44d7 70205dc 09f44d7 70205dc 09f44d7 70205dc 09f44d7 70205dc 09f44d7 70205dc 09f44d7 70205dc 09f44d7 70205dc 09f44d7 70205dc 09f44d7 70205dc 09f44d7 70205dc 09f44d7 70205dc 09f44d7 70205dc 09f44d7 70205dc 09f44d7 70205dc 09f44d7 70205dc 09f44d7 70205dc d54b594 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 |
from fastapi import FastAPI, HTTPException, Query
from pydantic import BaseModel
import talib
import numpy as np
from typing import List, Optional, Dict, Any
import yfinance as yf
from datetime import datetime, timedelta
from enum import Enum
import pandas as pd
app = FastAPI(
title="Elite US Stock Tracker API",
version="2.0.0",
description="Advanced technical analysis for top 5 US companies with actionable trading signals"
)
# Top 5 US Companies by Market Cap (2024)
class EliteStock(str, Enum):
APPLE = "AAPL"
MICROSOFT = "MSFT"
NVIDIA = "NVDA"
ALPHABET = "GOOGL"
AMAZON = "AMZN"
class TimeFrame(str, Enum):
ONE_WEEK = "7d"
ONE_MONTH = "1mo"
THREE_MONTHS = "3mo"
SIX_MONTHS = "6mo"
ONE_YEAR = "1y"
class TradingSignal(str, Enum):
STRONG_BUY = "STRONG_BUY"
BUY = "BUY"
HOLD = "HOLD"
SELL = "SELL"
STRONG_SELL = "STRONG_SELL"
class PositionRecommendation(BaseModel):
signal: TradingSignal
confidence: float # 0-100%
entry_price: Optional[float] = None
stop_loss: Optional[float] = None
take_profit: Optional[float] = None
position_size: str # Small, Medium, Large
reason: str
class TechnicalIndicators(BaseModel):
sma_20: float
sma_50: float
ema_12: float
ema_26: float
rsi: float
macd: float
macd_signal: float
macd_histogram: float
bollinger_upper: float
bollinger_middle: float
bollinger_lower: float
atr: float
stoch_k: float
stoch_d: float
williams_r: float
adx: float
class MarketMetrics(BaseModel):
current_price: float
price_change_24h: float
price_change_pct_24h: float
volume: int
avg_volume_20d: float
market_cap: Optional[float] = None
pe_ratio: Optional[float] = None
support_level: float
resistance_level: float
class ComprehensiveAnalysis(BaseModel):
symbol: str
company_name: str
last_updated: datetime
market_metrics: MarketMetrics
technical_indicators: TechnicalIndicators
position_recommendation: PositionRecommendation
key_levels: Dict[str, float]
trend_analysis: Dict[str, Any]
@app.get("/")
async def root():
return {
"message": "Elite US Stock Tracker API - Top 5 Companies",
"version": "2.0.0",
"supported_stocks": [stock.value for stock in EliteStock],
"features": [
"Advanced technical analysis",
"Position recommendations",
"Support/Resistance levels",
"Multi-timeframe analysis",
"Risk management signals"
]
}
@app.get("/stocks")
async def list_elite_stocks():
"""Get information about all supported elite stocks"""
stock_info = {
"AAPL": {"name": "Apple Inc.", "sector": "Technology"},
"MSFT": {"name": "Microsoft Corporation", "sector": "Technology"},
"NVDA": {"name": "NVIDIA Corporation", "sector": "Technology"},
"GOOGL": {"name": "Alphabet Inc.", "sector": "Technology"},
"AMZN": {"name": "Amazon.com Inc.", "sector": "Consumer Discretionary"}
}
return {
"elite_stocks": stock_info,
"total_count": len(stock_info),
"last_updated": datetime.now()
}
def calculate_support_resistance(prices: np.ndarray, window: int = 20) -> tuple:
"""Calculate dynamic support and resistance levels"""
recent_prices = prices[-window:]
support = np.min(recent_prices)
resistance = np.max(recent_prices)
return support, resistance
def generate_trading_signal(indicators: dict, market_data: dict) -> PositionRecommendation:
"""Generate intelligent trading signals based on multiple indicators"""
score = 0
reasons = []
# RSI Analysis
rsi = indicators['rsi']
if rsi < 30:
score += 2
reasons.append("RSI oversold (bullish)")
elif rsi > 70:
score -= 2
reasons.append("RSI overbought (bearish)")
elif 40 <= rsi <= 60:
score += 1
reasons.append("RSI neutral zone")
# MACD Analysis
if indicators['macd'] > indicators['macd_signal']:
score += 1
reasons.append("MACD bullish crossover")
else:
score -= 1
reasons.append("MACD bearish signal")
# Moving Average Analysis
current_price = market_data['current_price']
if current_price > indicators['sma_50']:
score += 1
reasons.append("Price above 50-day SMA")
else:
score -= 1
reasons.append("Price below 50-day SMA")
# Bollinger Bands Analysis
bb_position = (current_price - indicators['bollinger_lower']) / (indicators['bollinger_upper'] - indicators['bollinger_lower'])
if bb_position < 0.2:
score += 1
reasons.append("Near lower Bollinger Band (potential bounce)")
elif bb_position > 0.8:
score -= 1
reasons.append("Near upper Bollinger Band (potential reversal)")
# ADX Trend Strength
if indicators['adx'] > 25:
if score > 0:
score += 1
reasons.append("Strong trend confirms bullish bias")
else:
score -= 1
reasons.append("Strong trend confirms bearish bias")
# Determine signal and confidence
if score >= 4:
signal = TradingSignal.STRONG_BUY
confidence = min(95, 70 + score * 5)
position_size = "Large"
elif score >= 2:
signal = TradingSignal.BUY
confidence = min(85, 60 + score * 5)
position_size = "Medium"
elif score <= -4:
signal = TradingSignal.STRONG_SELL
confidence = min(95, 70 + abs(score) * 5)
position_size = "Large"
elif score <= -2:
signal = TradingSignal.SELL
confidence = min(85, 60 + abs(score) * 5)
position_size = "Medium"
else:
signal = TradingSignal.HOLD
confidence = 50 + abs(score) * 10
position_size = "Small"
# Calculate risk management levels
atr = indicators['atr']
if signal in [TradingSignal.STRONG_BUY, TradingSignal.BUY]:
entry_price = current_price
stop_loss = current_price - (2 * atr)
take_profit = current_price + (3 * atr)
elif signal in [TradingSignal.STRONG_SELL, TradingSignal.SELL]:
entry_price = current_price
stop_loss = current_price + (2 * atr)
take_profit = current_price - (3 * atr)
else:
entry_price = None
stop_loss = None
take_profit = None
return PositionRecommendation(
signal=signal,
confidence=confidence,
entry_price=entry_price,
stop_loss=stop_loss,
take_profit=take_profit,
position_size=position_size,
reason="; ".join(reasons)
)
@app.get("/analysis/{symbol}", response_model=ComprehensiveAnalysis)
async def get_comprehensive_analysis(
symbol: EliteStock,
timeframe: TimeFrame = TimeFrame.THREE_MONTHS
):
"""Get comprehensive technical analysis for an elite stock"""
try:
# Fetch stock data
ticker = yf.Ticker(symbol.value)
hist = ticker.history(period=timeframe.value)
info = ticker.info
if hist.empty:
raise HTTPException(status_code=404, detail=f"No data found for {symbol.value}")
# Extract price data
closes = hist['Close'].values
highs = hist['High'].values
lows = hist['Low'].values
volumes = hist['Volume'].values
# Calculate technical indicators
sma_20 = talib.SMA(closes, timeperiod=20)
sma_50 = talib.SMA(closes, timeperiod=50)
ema_12 = talib.EMA(closes, timeperiod=12)
ema_26 = talib.EMA(closes, timeperiod=26)
rsi = talib.RSI(closes, timeperiod=14)
macd, macd_signal, macd_hist = talib.MACD(closes)
bb_upper, bb_middle, bb_lower = talib.BBANDS(closes)
atr = talib.ATR(highs, lows, closes, timeperiod=14)
stoch_k, stoch_d = talib.STOCH(highs, lows, closes)
williams_r = talib.WILLR(highs, lows, closes)
adx = talib.ADX(highs, lows, closes)
# Get latest values
current_price = float(closes[-1])
latest_indicators = {
'sma_20': float(sma_20[-1]) if not np.isnan(sma_20[-1]) else current_price,
'sma_50': float(sma_50[-1]) if not np.isnan(sma_50[-1]) else current_price,
'ema_12': float(ema_12[-1]) if not np.isnan(ema_12[-1]) else current_price,
'ema_26': float(ema_26[-1]) if not np.isnan(ema_26[-1]) else current_price,
'rsi': float(rsi[-1]) if not np.isnan(rsi[-1]) else 50.0,
'macd': float(macd[-1]) if not np.isnan(macd[-1]) else 0.0,
'macd_signal': float(macd_signal[-1]) if not np.isnan(macd_signal[-1]) else 0.0,
'macd_histogram': float(macd_hist[-1]) if not np.isnan(macd_hist[-1]) else 0.0,
'bollinger_upper': float(bb_upper[-1]) if not np.isnan(bb_upper[-1]) else current_price * 1.02,
'bollinger_middle': float(bb_middle[-1]) if not np.isnan(bb_middle[-1]) else current_price,
'bollinger_lower': float(bb_lower[-1]) if not np.isnan(bb_lower[-1]) else current_price * 0.98,
'atr': float(atr[-1]) if not np.isnan(atr[-1]) else current_price * 0.02,
'stoch_k': float(stoch_k[-1]) if not np.isnan(stoch_k[-1]) else 50.0,
'stoch_d': float(stoch_d[-1]) if not np.isnan(stoch_d[-1]) else 50.0,
'williams_r': float(williams_r[-1]) if not np.isnan(williams_r[-1]) else -50.0,
'adx': float(adx[-1]) if not np.isnan(adx[-1]) else 25.0
}
# Calculate support and resistance
support, resistance = calculate_support_resistance(closes)
# Market metrics
price_change_24h = float(closes[-1] - closes[-2]) if len(closes) > 1 else 0.0
price_change_pct_24h = (price_change_24h / closes[-2] * 100) if len(closes) > 1 else 0.0
avg_volume_20d = float(np.mean(volumes[-20:])) if len(volumes) >= 20 else float(volumes[-1])
market_metrics = MarketMetrics(
current_price=current_price,
price_change_24h=price_change_24h,
price_change_pct_24h=price_change_pct_24h,
volume=int(volumes[-1]),
avg_volume_20d=avg_volume_20d,
market_cap=info.get('marketCap'),
pe_ratio=info.get('trailingPE'),
support_level=float(support),
resistance_level=float(resistance)
)
# Generate trading recommendation
position_rec = generate_trading_signal(latest_indicators, {'current_price': current_price})
# Key levels analysis
key_levels = {
"pivot_point": float((highs[-1] + lows[-1] + closes[-1]) / 3),
"fibonacci_618": float(support + (resistance - support) * 0.618),
"fibonacci_382": float(support + (resistance - support) * 0.382),
"vwap": float(np.average(closes[-20:], weights=volumes[-20:])) if len(closes) >= 20 else current_price
}
# Trend analysis
trend_analysis = {
"short_term_trend": "bullish" if latest_indicators['ema_12'] > latest_indicators['ema_26'] else "bearish",
"medium_term_trend": "bullish" if current_price > latest_indicators['sma_50'] else "bearish",
"trend_strength": "strong" if latest_indicators['adx'] > 25 else "weak",
"volatility": "high" if latest_indicators['atr'] / current_price > 0.03 else "normal"
}
return ComprehensiveAnalysis(
symbol=symbol.value,
company_name=info.get('longName', symbol.value),
last_updated=datetime.now(),
market_metrics=market_metrics,
technical_indicators=TechnicalIndicators(**latest_indicators),
position_recommendation=position_rec,
key_levels=key_levels,
trend_analysis=trend_analysis
)
except Exception as e:
raise HTTPException(status_code=500, detail=f"Analysis failed: {str(e)}")
@app.get("/portfolio/overview")
async def portfolio_overview():
"""Get overview of all elite stocks with quick signals"""
try:
results = {}
for stock in EliteStock:
ticker = yf.Ticker(stock.value)
hist = ticker.history(period="1mo")
if not hist.empty:
closes = hist['Close'].values
current_price = float(closes[-1])
rsi = talib.RSI(closes, timeperiod=14)
macd, macd_signal, _ = talib.MACD(closes)
# Quick signal
latest_rsi = float(rsi[-1]) if not np.isnan(rsi[-1]) else 50.0
latest_macd = float(macd[-1]) if not np.isnan(macd[-1]) else 0.0
latest_macd_signal = float(macd_signal[-1]) if not np.isnan(macd_signal[-1]) else 0.0
if latest_rsi < 30 and latest_macd > latest_macd_signal:
quick_signal = "BUY"
elif latest_rsi > 70 and latest_macd < latest_macd_signal:
quick_signal = "SELL"
else:
quick_signal = "HOLD"
results[stock.value] = {
"current_price": current_price,
"rsi": latest_rsi,
"quick_signal": quick_signal,
"price_change_24h": float(closes[-1] - closes[-2]) if len(closes) > 1 else 0.0
}
return {
"portfolio_overview": results,
"market_sentiment": "mixed", # Could be enhanced with market-wide analysis
"last_updated": datetime.now()
}
except Exception as e:
raise HTTPException(status_code=500, detail=f"Portfolio overview failed: {str(e)}")
@app.get("/alerts/{symbol}")
async def get_trading_alerts(symbol: EliteStock):
"""Get real-time trading alerts for a specific stock"""
try:
ticker = yf.Ticker(symbol.value)
hist = ticker.history(period="5d") # Last 5 days for recent alerts
if hist.empty:
raise HTTPException(status_code=404, detail=f"No data found for {symbol.value}")
closes = hist['Close'].values
highs = hist['High'].values
lows = hist['Low'].values
# Calculate indicators for alerts
rsi = talib.RSI(closes, timeperiod=14)
bb_upper, bb_middle, bb_lower = talib.BBANDS(closes)
alerts = []
current_price = float(closes[-1])
latest_rsi = float(rsi[-1]) if not np.isnan(rsi[-1]) else 50.0
# RSI alerts
if latest_rsi <= 30:
alerts.append({
"type": "RSI_OVERSOLD",
"message": f"RSI at {latest_rsi:.1f} - Potential buying opportunity",
"urgency": "HIGH"
})
elif latest_rsi >= 70:
alerts.append({
"type": "RSI_OVERBOUGHT",
"message": f"RSI at {latest_rsi:.1f} - Consider taking profits",
"urgency": "HIGH"
})
# Bollinger Band alerts
if current_price <= bb_lower[-1]:
alerts.append({
"type": "BOLLINGER_LOWER",
"message": f"Price touching lower Bollinger Band - Potential reversal",
"urgency": "MEDIUM"
})
elif current_price >= bb_upper[-1]:
alerts.append({
"type": "BOLLINGER_UPPER",
"message": f"Price touching upper Bollinger Band - Overbought condition",
"urgency": "MEDIUM"
})
# Volume alerts
volumes = hist['Volume'].values
avg_volume = np.mean(volumes[:-1]) # Average excluding today
volume_ratio = volumes[-1] / avg_volume
if volume_ratio > 2:
alerts.append({
"type": "HIGH_VOLUME",
"message": f"Volume spike: {volume_ratio:.1f}x average - Significant interest",
"urgency": "HIGH"
})
return {
"symbol": symbol.value,
"alerts": alerts,
"alert_count": len(alerts),
"last_updated": datetime.now()
}
except Exception as e:
raise HTTPException(status_code=500, detail=f"Alerts failed: {str(e)}")
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=7860) |