# ============================================================ # PORTFOLIO INTELLIGENCE ENGINE - FULL APP.PY # Live + Historical Data Enabled # ============================================================ import yfinance as yf import numpy as np import pandas as pd from datetime import datetime, timedelta from scipy.optimize import minimize from scipy import stats from dataclasses import dataclass from typing import Dict, List import warnings warnings.filterwarnings("ignore") # ============================================================ # DATA ENGINE # ============================================================ class MarketDataLoader: def __init__(self, lookback_days=365, interval="1d"): self.lookback_days = lookback_days self.interval = interval def fetch(self, symbols: List[str]) -> Dict[str, pd.DataFrame]: end = datetime.now() start = end - timedelta(days=self.lookback_days) data = {} for s in symbols: df = yf.download( s, start=start.strftime("%Y-%m-%d"), end=end.strftime("%Y-%m-%d"), interval=self.interval, auto_adjust=True, progress=False ) if not df.empty: data[s] = df[["Open", "High", "Low", "Close", "Volume"]].dropna() return data # ============================================================ # AI FORECAST ENGINE (PROXY) # ============================================================ class SimpleAIForecaster: def forecast(self, prices: pd.Series, horizon=30) -> Dict: returns = np.log(prices / prices.shift(1)).dropna() mu = returns.mean() * horizon sigma = returns.std() * np.sqrt(horizon) samples = np.random.normal(mu, sigma, 1000) return { "samples": samples, "expected_return": mu, "confidence": float(np.clip(1 / (1 + sigma * 10), 0.3, 0.9)) } # ============================================================ # REGIME DETECTOR # ============================================================ class RegimeDetector: def detect(self, returns: pd.Series) -> Dict: vol = returns.std() * np.sqrt(252) momentum = returns.rolling(20).mean().iloc[-1] if momentum > 0 and vol < 0.25: return {"regime": "bull", "confidence": 0.7} elif momentum < 0: return {"regime": "bear", "confidence": 0.7} else: return {"regime": "sideways", "confidence": 0.6} # ============================================================ # FEATURE ENGINE # ============================================================ @dataclass class AssetFeature: symbol: str expected_return: float confidence: float volatility: float returns: pd.Series regime: str class FeatureBuilder: def build(self, symbol, df, forecast, regime) -> AssetFeature: returns = np.log(df["Close"] / df["Close"].shift(1)).dropna() vol = returns.std() * np.sqrt(252) return AssetFeature( symbol=symbol, expected_return=forecast["expected_return"] * forecast["confidence"], confidence=forecast["confidence"], volatility=vol, returns=returns, regime=regime["regime"] ) # ============================================================ # OPTIMIZATION ENGINE # ============================================================ class Optimizer: def optimize(self, features: List[AssetFeature]) -> np.ndarray: returns = np.array([f.expected_return for f in features]) returns = np.clip(returns, -0.5, 0.5) returns_df = pd.concat( [f.returns for f in features], axis=1 ) returns_df.columns = [f.symbol for f in features] cov = returns_df.cov().values n = len(features) def objective(w): port_ret = w @ returns port_vol = np.sqrt(w @ cov @ w) return -(port_ret / (port_vol + 1e-8)) bounds = [(0.05, 0.5) for _ in range(n)] cons = [{"type": "eq", "fun": lambda w: np.sum(w) - 1}] w0 = np.ones(n) / n res = minimize(objective, w0, bounds=bounds, constraints=cons) return res.x if res.success else w0 # ============================================================ # RISK ANALYTICS # ============================================================ class RiskEngine: def analyze(self, weights, features): returns = np.array([f.expected_return for f in features]) returns_df = pd.concat([f.returns for f in features], axis=1) cov = returns_df.cov().values port_ret = weights @ returns port_vol = np.sqrt(weights @ cov @ weights) sharpe = (port_ret - 0.04) / port_vol if port_vol > 0 else 0 return { "expected_return": port_ret, "volatility": port_vol, "sharpe": sharpe } # ============================================================ # MAIN ORCHESTRATOR # ============================================================ class PortfolioApp: def __init__(self, symbols): self.symbols = symbols self.data_loader = MarketDataLoader() self.forecaster = SimpleAIForecaster() self.regime_detector = RegimeDetector() self.feature_builder = FeatureBuilder() self.optimizer = Optimizer() self.risk_engine = RiskEngine() def run(self): market_data = self.data_loader.fetch(self.symbols) features = [] for s, df in market_data.items(): forecast = self.forecaster.forecast(df["Close"]) returns = np.log(df["Close"] / df["Close"].shift(1)).dropna() regime = self.regime_detector.detect(returns) feature = self.feature_builder.build(s, df, forecast, regime) features.append(feature) weights = self.optimizer.optimize(features) risk = self.risk_engine.analyze(weights, features) print("\n📊 PORTFÖY SONUCU\n") for i, f in enumerate(features): print(f"{f.symbol:5s} | Weight: {weights[i]:.2%} | Regime: {f.regime}") print("\n--- RISK METRICS ---") print(f"Expected Return : {risk['expected_return']:.2%}") print(f"Volatility : {risk['volatility']:.2%}") print(f"Sharpe Ratio : {risk['sharpe']:.2f}") # ============================================================ # RUN # ============================================================ if __name__ == "__main__": symbols = ["XOM", "GOOGL", "WMT", "JNJ"] app = PortfolioApp(symbols) app.run()