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)