"""AlphaForge x K2 Think V2 - Institutional-Grade Quantitative Analysis Platform Multi-market support: US, EU, Asia, Crypto, Forex, Commodities Finance-themed UI with dark mode, professional color scheme Enhanced features: Options pricing, Pairs Trading, Macro Analysis Powered by MBZUAI K2 Think V2 reasoning model API Key: set via K2_API_KEY environment variable """ import os, json, traceback, warnings, math, random warnings.filterwarnings('ignore') # Core imports try: import gradio as gr import requests import yfinance as yf import pandas as pd import numpy as np import plotly.graph_objects as go from plotly.subplots import make_subplots PLOTLY_OK = True except ImportError as e: raise ImportError(f"Missing required package: {e}") # CONFIG K2_API_KEY = os.environ.get("K2_API_KEY", "") K2_BASE_URL = "https://api.k2think.ai/v1/chat/completions" K2_MODEL = "MBZUAI-IFM/K2-Think-v2" # K2 THINK V2 CLIENT class K2ThinkClient: def __init__(self): self.api_key = K2_API_KEY self.available = bool(self.api_key) and len(self.api_key) > 10 self.base_url = K2_BASE_URL def chat(self, messages, temperature=0.7, max_tokens=4096): if not self.available: return "⚠️ K2 Think V2 API Not Configured. Add K2_API_KEY in Space Settings > Repository Secrets. All other features work perfectly!" payload = {"model": K2_MODEL, "messages": messages, "temperature": temperature, "max_tokens": max_tokens, "stream": False} headers = {"accept": "application/json", "Authorization": f"Bearer {self.api_key}", "Content-Type": "application/json"} try: r = requests.post(self.base_url, headers=headers, json=payload, timeout=120) r.raise_for_status() j = r.json() if 'choices' in j and len(j['choices']) > 0: return j['choices'][0]['message']['content'] return f"⚠️ Unexpected format: {json.dumps(j, indent=2)[:400]}" except requests.exceptions.Timeout: return "⏱️ Timeout after 120s. API may be under high load." except requests.exceptions.HTTPError as e: if e.response.status_code == 401: return "🔐 Auth failed. Check K2_API_KEY secret." elif e.response.status_code == 429: return "🚦 Rate limited. Wait a moment." return f"🔴 HTTP {e.response.status_code}: {str(e)[:200]}" except Exception as e: return f"🔴 Error: {str(e)[:300]}" def analyze_market(self, ticker, market, data_summary, tech_summary, timeframe): prompt = f"""You are an elite quantitative analyst at a top hedge fund (Two Sigma / Jane Street level). Analyze with deep chain-of-thought reasoning. ## Asset Information - **Ticker**: {ticker} - **Market**: {market} - **Timeframe**: {timeframe} ## Market Data Summary {data_summary} ## Technical Indicators {tech_summary} ## Deliverables Provide exactly these sections: ### 1. Executive Summary (3 bullets) ### 2. Technical Analysis - Interpret RSI, MACD, Bollinger Bands, ADX, Ichimoku - Identify support/resistance levels from SMAs and VWAP ### 3. Risk Assessment - Volatility regime (low/normal/high) - Tail risk estimate - Correlation risk ### 4. Alpha Signal - Direction: BULLISH / NEUTRAL / BEARISH - Confidence: X% - Time horizon - Key conviction drivers ### 5. Trade Recommendation - Entry price / zone - Stop-loss - Target 1 (conservative) and Target 2 (aggressive) - Position sizing suggestion ### 6. Catalyst Calendar - Next 7 days - Next 30 days ### 7. Contrarian View - What would make this signal wrong? - Alternative scenario with probability Think step-by-step. Reference specific numbers.""" return self.chat([{"role": "user", "content": prompt}], temperature=0.2, max_tokens=4096) def portfolio_advice(self, portfolio_data, corr_data, risk_metrics, market_context): prompt = f"""You are a CIO managing $2B AUM at a systematic macro fund. ## Portfolio Holdings {portfolio_data} ## Correlation Analysis {corr_data} ## Risk Metrics {risk_metrics} ## Market Context {market_context} ## Deliverables ### 1. Portfolio Health Score (0-100) with letter grade (A+ to F) ### 2. Concentration Risk ### 3. Correlation Risk Matrix ### 4. Rebalancing Roadmap - Specific weight adjustments with % - Timeline: immediate / 1 week / 1 month ### 5. Hedging Strategy ### 6. Expected Return & Risk (Forward 12M) ### 7. Scenario Analysis - Bull case (20% probability) - Base case (50% probability) - Bear case (20% probability) - Tail case (10% probability) Use quantitative reasoning throughout.""" return self.chat([{"role": "user", "content": prompt}], temperature=0.2, max_tokens=4096) def macro_analysis(self, macro_text): prompt = f"""You are a global macro strategist at Bridgewater / Millennium. ## Input {macro_text} ## Deliverables ### 1. Macro Regime Classification ### 2. Cross-Asset Implications - Equities, Fixed Income, FX, Commodities, Crypto ### 3. Trade Ideas (3 concrete setups) Each with: instrument, direction, entry, stop, target, conviction %, time horizon ### 4. Risk Factors Think like a macro PM.""" return self.chat([{"role": "user", "content": prompt}], temperature=0.3, max_tokens=4096) # MARKET DATA MARKET_PRESETS = { "🇺🇸 US Equities": {"suffix": "", "examples": "AAPL, TSLA, NVDA, SPY, QQQ, META, AMZN, GOOGL"}, "🇪🇺 European Equities": {"suffix": ".PA", "examples": "AIR.PA, SAN.PA, TTE.PA, OR.PA, MC.PA"}, "🇬🇧 UK Equities": {"suffix": ".L", "examples": "AZN.L, SHEL.L, BP.L, ULVR.L, RIO.L"}, "🇩🇪 German Equities": {"suffix": ".DE", "examples": "SAP.DE, SIE.DE, ALV.DE, BAS.DE, BMW.DE"}, "🇯🇵 Japanese Equities": {"suffix": ".T", "examples": "7203.T, 9984.T, 6861.T, 6758.T"}, "🇨🇳 Chinese Equities": {"suffix": ".HK", "examples": "0700.HK, 9988.HK, 3690.HK, 1810.HK"}, "🇮🇳 Indian Equities": {"suffix": ".NS", "examples": "RELIANCE.NS, TCS.NS, INFY.NS"}, "🪙 Crypto": {"suffix": "", "examples": "BTC-USD, ETH-USD, SOL-USD, XRP-USD"}, "💱 Forex Majors": {"suffix": "=X", "examples": "EURUSD=X, GBPUSD=X, USDJPY=X"}, "🥇 Commodities": {"suffix": "", "examples": "GC=F, SI=F, CL=F, NG=F, ZC=F"}, "📊 Indices": {"suffix": "", "examples": "^GSPC, ^DJI, ^IXIC, ^FTSE, ^N225"}, } def fetch_data(ticker, period="6mo", interval="1d"): try: stock = yf.Ticker(ticker.upper().strip()) df = stock.history(period=period, interval=interval) if df.empty: return None, None, f"No data for '{ticker}'. Try examples from the selected market." info = stock.info return df, info, None except Exception as e: return None, None, f"Error fetching '{ticker}': {str(e)[:200]}" def calc_indicators(df): df = df.copy() df['Ret'] = df['Close'].pct_change() df['LogRet'] = np.log(df['Close']/df['Close'].shift(1)) df['SMA5'] = df['Close'].rolling(5).mean() df['SMA20'] = df['Close'].rolling(20).mean() df['SMA50'] = df['Close'].rolling(50).mean() df['SMA200'] = df['Close'].rolling(200).mean() df['EMA12'] = df['Close'].ewm(span=12, adjust=False).mean() df['EMA26'] = df['Close'].ewm(span=26, adjust=False).mean() df['MACD'] = df['EMA12'] - df['EMA26'] df['MACDS'] = df['MACD'].ewm(span=9, adjust=False).mean() df['MACDH'] = df['MACD'] - df['MACDS'] d = df['Close'].diff() g = d.where(d>0,0).rolling(14).mean() l = (-d.where(d<0,0)).rolling(14).mean() df['RSI'] = 100 - (100/(1+g/(l+1e-10))) m = df['Close'].rolling(20).mean() s = df['Close'].rolling(20).std() df['BBU'] = m + 2*s df['BBL'] = m - 2*s df['BBP'] = (df['Close']-df['BBL'])/(df['BBU']-df['BBL']+1e-10) df['BBW'] = (df['BBU']-df['BBL'])/m tp = (df['High']+df['Low']+df['Close'])/3 df['VWAP'] = (tp*df['Volume']).cumsum()/(df['Volume'].cumsum()+1e-10) hl = df['High']-df['Low'] hc = np.abs(df['High']-df['Close'].shift()) lc = np.abs(df['Low']-df['Close'].shift()) tr = pd.concat([hl,hc,lc],axis=1).max(axis=1) df['ATR'] = tr.rolling(14).mean() df['ATR_pct'] = df['ATR']/df['Close']*100 lo = df['Low'].rolling(14).min() hi = df['High'].rolling(14).max() df['Stoch_K'] = 100*(df['Close']-lo)/(hi-lo+1e-10) df['Stoch_D'] = df['Stoch_K'].rolling(3).mean() df['VM'] = df['Volume'].rolling(20).mean() df['VR'] = df['Volume']/(df['VM']+1e-10) plus_dm = df['High'].diff() minus_dm = df['Low'].diff() plus_dm[plus_dm<0] = 0 minus_dm[minus_dm>0] = 0 minus_dm = np.abs(minus_dm) atr_smooth = tr.ewm(alpha=1/14, adjust=False).mean() df['plus_DI'] = 100 * (plus_dm.ewm(alpha=1/14, adjust=False).mean() / atr_smooth) df['minus_DI'] = 100 * (minus_dm.ewm(alpha=1/14, adjust=False).mean() / atr_smooth) dx = 100 * np.abs(df['plus_DI']-df['minus_DI'])/(df['plus_DI']+df['minus_DI']+1e-10) df['ADX'] = dx.ewm(alpha=1/14, adjust=False).mean() df['OBV'] = (np.sign(df['Close'].diff())*df['Volume']).cumsum() tp_r = (df['High']+df['Low']+df['Close'])/3 tp_diff = tp_r.diff() pos_flow = tp_r.where(tp_diff>0,0)*df['Volume'] neg_flow = tp_r.where(tp_diff<0,0)*df['Volume'] mfi_pos = pos_flow.rolling(14).sum() mfi_neg = neg_flow.rolling(14).sum() df['MFI'] = 100 - (100/(1+mfi_pos/(mfi_neg+1e-10))) df['ICH_tenkan'] = (df['High'].rolling(9).max()+df['Low'].rolling(9).min())/2 df['ICH_kijun'] = (df['High'].rolling(26).max()+df['Low'].rolling(26).min())/2 df['ICH_senkou_A'] = ((df['ICH_tenkan']+df['ICH_kijun'])/2).shift(26) df['ICH_senkou_B'] = ((df['High'].rolling(52).max()+df['Low'].rolling(52).min())/2).shift(26) return df def calc_risk(df): r = df['Ret'].dropna() if len(r) < 30: return {} ar = r.mean()*252 av = r.std()*np.sqrt(252) sh = ar/(av+1e-10) dn = r[r<0] sd = dn.std()*np.sqrt(252) if len(dn)>0 else 1e-10 so = ar/(sd+1e-10) c = (1+r).cumprod() rm = c.expanding().max() md = ((c-rm)/rm).min() v95 = np.percentile(r,5) v99 = np.percentile(r,1) cv95 = r[r<=v95].mean() if len(r[r<=v95])>0 else v95 cv99 = r[r<=v99].mean() if len(r[r<=v99])>0 else v99 ca = ar/(abs(md)+1e-10) roll_sharpe = (r.rolling(63).mean()*252)/(r.rolling(63).std()*np.sqrt(252)+1e-10) return {'ar':ar,'av':av,'sh':sh,'so':so,'md':md,'v95':v95,'v99':v99, 'cv95':cv95,'cv99':cv99,'ca':ca,'sk':r.skew(),'ku':r.kurtosis(), 'wr':(r>0).mean(),'pf':abs(r[r>0].sum()/(r[r<0].sum()+1e-10)), 'avg_win':r[r>0].mean() if len(r[r>0])>0 else 0, 'avg_loss':r[r<0].mean() if len(r[r<0])>0 else 0, 'roll_sharpe':roll_sharpe.iloc[-1] if len(roll_sharpe.dropna())>0 else 0, 'vol_regime':'low' if av<0.15 else 'normal' if av<0.30 else 'high'} def calc_signals(df): l = df.iloc[-1] p = df.iloc[-2] if len(df)>1 else l s = {'trend':'neutral','mom':'neutral','vol':'normal','volume':'normal', 'adx_trend':'weak','score':50,'ichimoku':'neutral'} if l['Close']>l['SMA20']>l['SMA50']>l['SMA200']: s['trend'] = 'strongly bullish' elif l['Close']>l['SMA20']>l['SMA50']: s['trend'] = 'bullish' elif l['Close']70: s['mom'] = 'deeply overbought' elif l['RSI']>60: s['mom'] = 'overbought' elif l['MACD']>l['MACDS'] and p['MACD']<=p['MACDS']: s['mom'] = 'bullish MACD crossover' elif l['MACD']=p['MACDS']: s['mom'] = 'bearish MACD crossover' if l['BBW'] > df['BBW'].quantile(0.9): s['vol'] = 'expanding (high vol)' elif l['BBW'] < df['BBW'].quantile(0.1): s['vol'] = 'contracting (low vol / squeeze)' if l['VR'] > 2.5: s['volume'] = 'very heavy (institutional)' elif l['VR'] > 1.5: s['volume'] = 'above average' if l['ADX'] > 25: s['adx_trend'] = 'strong trend' elif l['ADX'] > 20: s['adx_trend'] = 'trending' if l['Close'] > l['ICH_senkou_A'] and l['Close'] > l['ICH_senkou_B']: s['ichimoku'] = 'bullish cloud' elif l['Close'] < l['ICH_senkou_A'] and l['Close'] < l['ICH_senkou_B']: s['ichimoku'] = 'bearish cloud' sc = 50 if 'bullish' in s['trend']: sc += 20 if 'bearish' in s['trend']: sc -= 20 if 'oversold' in s['mom']: sc += 10 if 'overbought' in s['mom']: sc -= 10 if 'crossover' in s['mom'] and 'bullish' in s['mom']: sc += 10 if 'crossover' in s['mom'] and 'bearish' in s['mom']: sc -= 10 if l['Close'] > l['VWAP']: sc += 5 if l['Close'] < l['VWAP']: sc -= 5 if l['Stoch_K'] < 20: sc += 5 if l['Stoch_K'] > 80: sc -= 5 if s['ichimoku'] == 'bullish cloud': sc += 5 if s['ichimoku'] == 'bearish cloud': sc -= 5 s['score'] = max(0, min(100, sc)) s['dir'] = 'BULLISH' if sc>60 else 'BEARISH' if sc<40 else 'NEUTRAL' s['strength'] = 'STRONG' if abs(sc-50)>25 else 'MODERATE' if abs(sc-50)>15 else 'WEAK' return s def make_candlestick(df, ticker, market): fig = make_subplots(rows=3, cols=1, shared_xaxes=True, vertical_spacing=0.03, row_heights=[0.55, 0.25, 0.20], subplot_titles=(f'{ticker} ({market})', 'Volume + VWAP', 'RSI')) fig.add_trace(go.Candlestick(x=df.index, open=df['Open'], high=df['High'], low=df['Low'], close=df['Close'], name='Price', increasing_line_color='#00C853', decreasing_line_color='#FF5252'), row=1, col=1) fig.add_trace(go.Scatter(x=df.index, y=df['SMA20'], line=dict(color='#FF9800', width=1), name='SMA20'), row=1, col=1) fig.add_trace(go.Scatter(x=df.index, y=df['SMA50'], line=dict(color='#2196F3', width=1), name='SMA50'), row=1, col=1) fig.add_trace(go.Scatter(x=df.index, y=df['SMA200'], line=dict(color='#9C27B0', width=1.5, dash='dash'), name='SMA200'), row=1, col=1) fig.add_trace(go.Scatter(x=df.index, y=df['BBU'], line=dict(color='gray', width=0.8, dash='dash'), name='BB+', opacity=0.4), row=1, col=1) fig.add_trace(go.Scatter(x=df.index, y=df['BBL'], line=dict(color='gray', width=0.8, dash='dash'), name='BB-', opacity=0.4), row=1, col=1) colors = ['#00C853' if df['Close'].iloc[i]>=df['Open'].iloc[i] else '#FF5252' for i in range(len(df))] fig.add_trace(go.Bar(x=df.index, y=df['Volume'], marker_color=colors, name='Volume', opacity=0.7), row=2, col=1) fig.add_trace(go.Scatter(x=df.index, y=df['VM'], line=dict(color='#FF9800', width=1), name='Vol MA20'), row=2, col=1) fig.add_trace(go.Scatter(x=df.index, y=df['RSI'], line=dict(color='#9C27B0', width=1.5), fill='tozeroy', fillcolor='rgba(156,39,176,0.1)'), row=3, col=1) fig.add_hline(y=70, line_dash="dash", line_color="#FF5252", row=3, col=1) fig.add_hline(y=30, line_dash="dash", line_color="#00C853", row=3, col=1) fig.add_hline(y=50, line_dash="dot", line_color="gray", row=3, col=1) fig.update_layout(title=f'{ticker} Technical Analysis', template='plotly_dark', xaxis_rangeslider_visible=False, height=850, paper_bgcolor='#0d1117', plot_bgcolor='#161b22', font=dict(color='#e6edf3')) fig.update_yaxes(title_text="Price", row=1, col=1) fig.update_yaxes(title_text="Volume", row=2, col=1) fig.update_yaxes(title_text="RSI", range=[0,100], row=3, col=1) return fig def make_macd(df, ticker): fig = make_subplots(rows=2, cols=1, shared_xaxes=True, vertical_spacing=0.05, row_heights=[0.6, 0.4], subplot_titles=('MACD', 'Histogram')) fig.add_trace(go.Scatter(x=df.index, y=df['MACD'], line=dict(color='#2196F3', width=1.5), name='MACD'), row=1, col=1) fig.add_trace(go.Scatter(x=df.index, y=df['MACDS'], line=dict(color='#FF9800', width=1.5), name='Signal'), row=1, col=1) colors = ['#00C853' if v>=0 else '#FF5252' for v in df['MACDH']] fig.add_trace(go.Bar(x=df.index, y=df['MACDH'], marker_color=colors, name='Histogram', opacity=0.7), row=2, col=1) fig.update_layout(title=f'{ticker} MACD', template='plotly_dark', height=500, paper_bgcolor='#0d1117', plot_bgcolor='#161b22', font=dict(color='#e6edf3')) return fig def make_stoch(df, ticker): fig = go.Figure() fig.add_trace(go.Scatter(x=df.index, y=df['Stoch_K'], line=dict(color='#2196F3', width=1.5), name='%K')) fig.add_trace(go.Scatter(x=df.index, y=df['Stoch_D'], line=dict(color='#FF9800', width=1.5), name='%D')) fig.add_hline(y=80, line_dash="dash", line_color="#FF5252") fig.add_hline(y=20, line_dash="dash", line_color="#00C853") fig.update_layout(title=f'{ticker} Stochastic', template='plotly_dark', height=400, paper_bgcolor='#0d1117', plot_bgcolor='#161b22', font=dict(color='#e6edf3')) return fig def make_vol(df, ticker): fig = make_subplots(rows=2, cols=1, shared_xaxes=True, vertical_spacing=0.05, row_heights=[0.6, 0.4], subplot_titles=('ATR %', 'Volume Ratio')) fig.add_trace(go.Scatter(x=df.index, y=df['ATR_pct'], line=dict(color='#FF9800', width=1.5), fill='tozeroy'), row=1, col=1) fig.add_trace(go.Scatter(x=df.index, y=df['VR'], line=dict(color='#9C27B0', width=1.5)), row=2, col=1) fig.add_hline(y=1.0, line_dash="dash", line_color="gray", row=2, col=1) fig.update_layout(title=f'{ticker} Volatility', template='plotly_dark', height=500, paper_bgcolor='#0d1117', plot_bgcolor='#161b22', font=dict(color='#e6edf3')) return fig def make_adx(df, ticker): fig = go.Figure() fig.add_trace(go.Scatter(x=df.index, y=df['plus_DI'], line=dict(color='#00C853', width=1), name='+DI')) fig.add_trace(go.Scatter(x=df.index, y=df['minus_DI'], line=dict(color='#FF5252', width=1), name='-DI')) fig.add_trace(go.Scatter(x=df.index, y=df['ADX'], line=dict(color='#2196F3', width=2), name='ADX')) fig.add_hline(y=25, line_dash="dash", line_color="gray") fig.update_layout(title=f'{ticker} ADX', template='plotly_dark', height=400, paper_bgcolor='#0d1117', plot_bgcolor='#161b22', font=dict(color='#e6edf3')) return fig def make_dist(r, ticker): fig = go.Figure() fig.add_trace(go.Histogram(x=r, nbinsx=50, marker_color='#2196F3', opacity=0.7, name='Returns')) mu, sig = r.mean(), r.std() fig.add_vline(x=mu, line_color='#00C853', line_dash='dash', annotation_text=f'Mean: {mu*100:.2f}%') fig.add_vline(x=np.percentile(r,5), line_color='#FF5252', line_dash='dot', annotation_text='VaR95') fig.update_layout(title=f'{ticker} Returns', xaxis_title='Daily Return', yaxis_title='Count', height=400, template='plotly_dark', paper_bgcolor='#0d1117', plot_bgcolor='#161b22', font=dict(color='#e6edf3')) return fig # PORTFOLIO def optimize_portfolio(tickers, period="1y"): ts = [t.strip().upper() for t in tickers.split(',') if t.strip()] if len(ts) < 2: return None, None, None, "Enter at least 2 tickers." data = {} errs = [] for t in ts: df, info, err = fetch_data(t, period) if err: errs.append(err) elif df is not None and len(df) > 30: data[t] = df['Close'] if len(data) < 2: return None, None, None, f"Could not fetch data: {'; '.join(errs[:3])}" prices = pd.DataFrame(data).dropna() returns = prices.pct_change().dropna() if len(returns) < 30: return None, None, None, "Need more data." mu = returns.mean() * 252 sigma = returns.cov() * 252 n = len(mu) best_sh = -999 best_w = np.ones(n)/n np.random.seed(42) for _ in range(5000): w = np.random.dirichlet(np.ones(n)*0.5) w = np.clip(w, 0, 0.4) w = w/w.sum() pr = np.dot(w, mu) pv = np.sqrt(np.dot(w.T, np.dot(sigma, w))) sh = pr/(pv+1e-10) if sh > best_sh: best_sh = sh best_w = w pr = np.dot(best_w, mu) pv = np.sqrt(np.dot(best_w.T, np.dot(sigma, best_w))) eq_w = np.ones(n)/n eq_r = np.dot(eq_w, mu) eq_v = np.sqrt(np.dot(eq_w.T, np.dot(sigma, eq_w))) ws = np.random.dirichlet(np.ones(n)*0.5, 3000) ws = np.clip(ws, 0, 0.4) ws = ws/ws.sum(axis=1, keepdims=True) prets = np.dot(ws, mu) pvols = np.array([np.sqrt(np.dot(w.T, np.dot(sigma, w))) for w in ws]) psh = prets/(pvols+1e-10) fig = go.Figure() fig.add_trace(go.Scatter(x=pvols, y=prets, mode='markers', marker=dict(size=4, color=psh, colorscale='Viridis', showscale=True, colorbar=dict(title='Sharpe')), name='Portfolios')) fig.add_trace(go.Scatter(x=[pv], y=[pr], mode='markers+text', marker=dict(size=18, color='#FF5252', symbol='star'), text=['Optimal'], textposition='top center', name='Optimal')) fig.add_trace(go.Scatter(x=[eq_v], y=[eq_r], mode='markers+text', marker=dict(size=14, color='#FF9800', symbol='diamond'), text=['Equal'], textposition='bottom center', name='Equal Weight')) fig.update_layout(title='Efficient Frontier', xaxis_title='Volatility', yaxis_title='Return', template='plotly_dark', height=550, paper_bgcolor='#0d1117', plot_bgcolor='#161b22', font=dict(color='#e6edf3')) corr = returns.corr() corr_fig = go.Figure(data=go.Heatmap(z=corr.values, x=corr.columns, y=corr.columns, colorscale='RdBu', zmid=0, text=np.round(corr.values,2), texttemplate='%{text:.2f}', colorbar=dict(title='Correlation'))) corr_fig.update_layout(title='Correlation Matrix', template='plotly_dark', height=450, paper_bgcolor='#0d1117', plot_bgcolor='#161b22', font=dict(color='#e6edf3')) wdf = pd.DataFrame({'Ticker': list(data.keys()), 'Optimal (%)': np.round(best_w*100, 2), 'Equal (%)': np.round(eq_w*100, 2)}) md = f"""## Portfolio Results **Tickers:** {', '.join(list(data.keys()))} | | Optimal | Equal | |-|---------|-------| | Return | {pr*100:.1f}% | {eq_r*100:.1f}% | | Volatility | {pv*100:.1f}% | {eq_v*100:.1f}% | | Sharpe | {best_sh:.2f} | {eq_r/(eq_v+1e-10):.2f} | Improvements: Sharpe {((best_sh/(eq_r/(eq_v+1e-10))-1)*100):+.1f}% {wdf.to_markdown(index=False)} """ return fig, corr_fig, wdf, md # PAIRS TRADING def analyze_pair(ticker_a, ticker_b, period="1y"): df_a, _, _ = fetch_data(ticker_a, period) df_b, _, _ = fetch_data(ticker_b, period) if df_a is None or df_b is None: return None, None, "Could not fetch data for one or both tickers." prices = pd.DataFrame({ticker_a: df_a['Close'], ticker_b: df_b['Close']}).dropna() if len(prices) < 30: return None, None, "Insufficient aligned data." spread = prices[ticker_a] - prices[ticker_b] spread_norm = (spread - spread.mean()) / spread.std() beta = np.polyfit(prices[ticker_b], prices[ticker_a], 1)[0] hedge_ratio = beta spread_hedged = prices[ticker_a] - hedge_ratio * prices[ticker_b] spread_hedged_norm = (spread_hedged - spread_hedged.mean()) / spread_hedged.std() lag_spread = spread_hedged.shift(1) delta_spread = spread_hedged.diff() valid = delta_spread.dropna().index y = delta_spread.loc[valid] x = lag_spread.loc[valid] - spread_hedged.mean() theta = -np.polyfit(x, y, 1)[0] half_life = np.log(2)/theta if theta > 0 else float('inf') z = spread_hedged_norm.iloc[-1] signal = 'SHORT SPREAD' if z > 2 else 'LONG SPREAD' if z < -2 else 'NO SIGNAL' fig = make_subplots(rows=3, cols=1, shared_xaxes=True, vertical_spacing=0.05, subplot_titles=(f'{ticker_a} vs {ticker_b}', 'Normalized Spread', 'Z-Score')) fig.add_trace(go.Scatter(x=prices.index, y=prices[ticker_a], line=dict(color='#2196F3', width=1.5), name=ticker_a), row=1, col=1) fig.add_trace(go.Scatter(x=prices.index, y=prices[ticker_b], line=dict(color='#FF9800', width=1.5), name=ticker_b), row=1, col=1) fig.add_trace(go.Scatter(x=prices.index, y=spread_norm, line=dict(color='#00C853', width=1.5), fill='tozeroy'), row=2, col=1) fig.add_trace(go.Scatter(x=prices.index, y=spread_hedged_norm, line=dict(color='#9C27B0', width=1.5)), row=3, col=1) fig.add_hline(y=2, line_dash="dash", line_color="#FF5252", row=3, col=1) fig.add_hline(y=-2, line_dash="dash", line_color="#00C853", row=3, col=1) fig.add_hline(y=0, line_dash="dot", line_color="gray", row=3, col=1) fig.update_layout(title=f'Pairs: {ticker_a} / {ticker_b}', template='plotly_dark', height=750, paper_bgcolor='#0d1117', plot_bgcolor='#161b22', font=dict(color='#e6edf3')) scat = go.Figure() scat.add_trace(go.Scatter(x=prices[ticker_b], y=prices[ticker_a], mode='markers', marker=dict(size=4, color=np.arange(len(prices)), colorscale='Viridis', showscale=True), name='Price Path')) x_range = np.linspace(prices[ticker_b].min(), prices[ticker_b].max(), 100) intercept = np.polyfit(prices[ticker_b], prices[ticker_a], 1)[1] y_range = hedge_ratio * x_range + intercept scat.add_trace(go.Scatter(x=x_range, y=y_range, mode='lines', line=dict(color='#FF5252', dash='dash'), name=f'OLS (β={hedge_ratio:.2f})')) scat.update_layout(title=f'Price Relationship (β={hedge_ratio:.2f})', template='plotly_dark', xaxis_title=ticker_b, yaxis_title=ticker_a, height=450, paper_bgcolor='#0d1117', plot_bgcolor='#161b22', font=dict(color='#e6edf3')) md = f"""## Pairs Trading: {ticker_a} vs {ticker_b} | Metric | Value | |--------|-------| | Hedge Ratio (β) | {hedge_ratio:.3f} | | Spread Mean | ${spread_hedged.mean():.2f} | | Spread Std | ${spread_hedged.std():.2f} | | Current Z-Score | {z:.2f} | | Half-Life | {half_life:.1f} days | ### Signal | Z-Score | Action | |---------|--------| | {z:.2f} | **{signal}** | ### Rules - **Long Spread** when Z < -2 (buy {ticker_a}, short {ticker_b}) - **Short Spread** when Z > +2 (short {ticker_a}, buy {ticker_b}) - **Exit** when Z crosses 0 - **Stop Loss** when |Z| > 3.5 """ return fig, scat, md # OPTIONS def black_scholes(S, K, T, r, sigma, option_type='call'): try: d1 = (np.log(S/K) + (r + 0.5*sigma**2)*T) / (sigma*np.sqrt(T)) d2 = d1 - sigma*np.sqrt(T) try: from scipy.stats import norm nd1 = norm.cdf(d1) nd2 = norm.cdf(d2) npdf_d1 = norm.pdf(d1) except: def approx_cdf(x): return 0.5 * (1 + math.erf(x / math.sqrt(2))) nd1 = approx_cdf(d1) nd2 = approx_cdf(d2) npdf_d1 = (1/math.sqrt(2*math.pi)) * math.exp(-0.5*d1**2) if option_type == 'call': price = S*nd1 - K*math.exp(-r*T)*nd2 delta = nd1 else: price = K*math.exp(-r*T)*(1-nd2) - S*(1-nd1) delta = nd1 - 1 gamma = npdf_d1 / (S*sigma*np.sqrt(T)) theta = -(S*npdf_d1*sigma)/(2*np.sqrt(T)) - r*K*math.exp(-r*T)*nd2 if option_type=='call' else -(S*npdf_d1*sigma)/(2*np.sqrt(T)) + r*K*math.exp(-r*T)*(1-nd2) vega = S*npdf_d1*np.sqrt(T) rho = K*T*math.exp(-r*T)*nd2 if option_type=='call' else -K*T*math.exp(-r*T)*(1-nd2) return {'price': price, 'delta': delta, 'gamma': gamma, 'theta': theta/252, 'vega': vega/100, 'rho': rho/100, 'd1': d1, 'd2': d2} except Exception as e: return {'error': str(e)} def analyze_options(ticker, strike_pct, days, rfr, vol_override, option_type): df, info, err = fetch_data(ticker, "6mo") if df is None: return None, None, f"Error: {err}" df = calc_indicators(df) S = df['Close'].iloc[-1] K = S * (strike_pct/100) T = days / 365 if vol_override and vol_override > 0: sigma = vol_override / 100 else: sigma = df['Ret'].dropna().std() * np.sqrt(252) r = rfr / 100 bs = black_scholes(S, K, T, r, sigma, option_type.lower()) if 'error' in bs: return None, None, f"BS Error: {bs['error']}" pct_changes = np.arange(-30, 31, 5) pl_data = [] for pct in pct_changes: new_S = S * (1 + pct/100) new_bs = black_scholes(new_S, K, max(T - 1/365, 0.001), r, sigma, option_type.lower()) pl = (new_bs['price'] - bs['price']) * 100 pl_data.append({'Price Change %': f'{pct:+d}%', 'Stock Price': f'${new_S:.2f}', 'Option Price': f'${new_bs["price"]:.2f}', 'P/L (per 100)': f'${pl:+.2f}'}) pl_df = pd.DataFrame(pl_data) strikes = np.linspace(S*0.7, S*1.3, 50) greeks_data = {'price': [], 'delta': [], 'gamma': [], 'theta': [], 'vega': []} for st in strikes: res = black_scholes(S, st, T, r, sigma, option_type.lower()) for k in greeks_data: greeks_data[k].append(res.get(k, 0)) fig = make_subplots(rows=2, cols=3, subplot_titles=('Price', 'Delta', 'Gamma', 'Theta (daily)', 'Vega', 'P/L at Expiry'), vertical_spacing=0.12, horizontal_spacing=0.08) colors = ['#2196F3', '#00C853', '#FF9800', '#FF5252', '#9C27B0', '#673AB7'] for i, (k, v) in enumerate(greeks_data.items()): row, col = (i//3)+1, (i%3)+1 fig.add_trace(go.Scatter(x=strikes, y=v, line=dict(color=colors[i], width=2), name=k), row=row, col=col) fig.add_vline(x=S, line_dash='dash', line_color='gray', row=row, col=col) expiry_payoff = [max(s-K,0) if option_type.lower()=='call' else max(K-s,0) for s in strikes] pl_expiry = [p - bs['price'] for p in expiry_payoff] fig.add_trace(go.Scatter(x=strikes, y=pl_expiry, line=dict(color='#673AB7', width=2), name='P/L Expiry'), row=2, col=3) fig.add_hline(y=0, line_dash='dot', line_color='gray', row=2, col=3) fig.update_layout( title=f'{ticker} {option_type.title()} Greeks (S=${S:.2f}, K=${K:.2f}, T={days}d, σ={sigma*100:.1f}%)', template='plotly_dark', height=650, paper_bgcolor='#0d1117', plot_bgcolor='#161b22', font=dict(color='#e6edf3')) md = f"""## {ticker} {option_type.title()} Analysis | Parameter | Value | |-----------|-------| | Spot (S) | ${S:.2f} | | Strike (K) | ${K:.2f} ({strike_pct:.0f}% of spot) | | Time to Expiry | {days} days | | Risk-Free Rate | {r*100:.2f}% | | Volatility | {sigma*100:.1f}% | ### Greeks | Greek | Value | |-------|-------| | **Price** | ${bs['price']:.3f} | | **Delta** | {bs['delta']:.4f} | | **Gamma** | {bs['gamma']:.6f} | | **Theta** | ${bs['theta']:.4f}/day | | **Vega** | ${bs['vega']:.4f} | | **Rho** | ${bs['rho']:.4f} | | **d1** | {bs['d1']:.4f} | | **d2** | {bs['d2']:.4f} | ### P/L Scenarios (per 100 contracts) {pl_df.to_markdown(index=False)} """ return fig, pl_df, md # MACRO def get_macro_data(): macros = {} for t, name in [('^GSPC','S&P 500'),('^IXIC','Nasdaq'),('^TNX','10Y Treasury'), ('GC=F','Gold'),('CL=F','Oil'),('EURUSD=X','EUR/USD'), ('DX-Y.NYB','DXY Dollar'),('BTC-USD','Bitcoin')]: try: df = yf.Ticker(t).history(period='1mo') if not df.empty: macros[name] = {'price': df['Close'].iloc[-1], 'change_1m': (df['Close'].iloc[-1]/df['Close'].iloc[0]-1)*100} except: pass return macros def ai_macro(): macros = get_macro_data() macro_text = "Global Macro Snapshot:\n" for name, data in macros.items(): macro_text += f"- {name}: ${data['price']:.2f} (1M change: {data['change_1m']:+.1f}%)\n" client = K2ThinkClient() return client.macro_analysis(macro_text) # UI FUNCTIONS def analyze_stock(ticker, market_preset, period, interval): ticker = ticker.strip().upper() if not ticker: return [None]*6 + ["Enter a ticker."] suffix = MARKET_PRESETS.get(market_preset, {}).get('suffix', '') if suffix and not any(ticker.endswith(s) for s in suffix.split('|')): ticker = ticker + suffix df, info, err = fetch_data(ticker, period) if df is None: return [None]*6 + [f"Error: {err}"] df = calc_indicators(df) sg = calc_signals(df) rk = calc_risk(df) if not rk: return [None]*6 + ["Need more data."] l = df.iloc[-1] p = df.iloc[-2] if len(df)>1 else l ch = ((l['Close']/p['Close']-1)*100) if p['Close']>0 else 0 c1 = make_candlestick(df, ticker, market_preset) c2 = make_macd(df, ticker) c3 = make_stoch(df, ticker) c4 = make_vol(df, ticker) c5 = make_adx(df, ticker) c6 = make_dist(df['Ret'].dropna(), ticker) info_lines = [] if info: info_lines.append(f"| Name | {info.get('longName', ticker)} |") info_lines.append(f"| Sector | {info.get('sector', 'N/A')} |") info_lines.append(f"| Industry | {info.get('industry', 'N/A')} |") if info.get('marketCap'): info_lines.append(f"| Market Cap | {info.get('marketCap'):,} |") if info.get('fiftyTwoWeekHigh'): info_lines.append(f"| 52W High | ${info.get('fiftyTwoWeekHigh'):.2f} |") if info.get('fiftyTwoWeekLow'): info_lines.append(f"| 52W Low | ${info.get('fiftyTwoWeekLow'):.2f} |") if info.get('trailingPE'): info_lines.append(f"| P/E | {info.get('trailingPE'):.2f} |") mkt_info = "\n".join(info_lines) md = f"""# {ticker} - {sg['dir']} {sg['strength']} (Score: {sg['score']}/100) **Price:** ${l['Close']:.2f} | **Change:** {ch:+.2f}% | **Period:** {period} {mkt_info} ## Signal Dashboard | Indicator | Value | Signal | |-----------|-------|--------| | RSI (14) | {l['RSI']:.1f} | {'🟢 Deeply Oversold' if l['RSI']<30 else '🔴 Deeply Overbought' if l['RSI']>70 else '⚪ Neutral'} | | MACD | {l['MACD']:.3f} | {'🟢 Bullish' if l['MACD']>l['MACDS'] else '🔴 Bearish'} | | Bollinger | {l['BBP']:.1%} | {'🔴 Upper' if l['BBP']>0.8 else '🟢 Lower' if l['BBP']<0.2 else '⚪ Mid'} | | VWAP | {'🟢 Above' if l['Close']>l['VWAP'] else '🔴 Below'} | {'🟢 Bullish' if l['Close']>l['VWAP'] else '🔴 Bearish'} | | Stoch %K | {l['Stoch_K']:.1f} | {'🟢 Oversold' if l['Stoch_K']<20 else '🔴 Overbought' if l['Stoch_K']>80 else '⚪ Neutral'} | | ADX | {l['ADX']:.1f} | {sg['adx_trend']} | | Volume | {l['VR']:.1f}x avg | {'🔥 Heavy' if l['VR']>2 else '⬆️ Above Avg' if l['VR']>1.5 else '⚪ Normal'} | | Trend | {sg['trend'].upper()} | — | | Momentum | {sg['mom']} | — | | Volatility | {sg['vol']} | — | | Ichimoku | {sg['ichimoku']} | — | ## Risk Metrics | Metric | Value | |--------|-------| | Ann. Return | {rk['ar']*100:.1f}% | | Ann. Volatility | {rk['av']*100:.1f}% | | Vol Regime | {rk['vol_regime'].upper()} | | Sharpe | {rk['sh']:.2f} | | Sortino | {rk['so']:.2f} | | Max Drawdown | {rk['md']*100:.1f}% | | VaR (95%) | {rk['v95']*100:.2f}% | | VaR (99%) | {rk['v99']*100:.2f}% | | CVaR (95%) | {rk['cv95']*100:.2f}% | | CVaR (99%) | {rk['cv99']*100:.2f}% | | Calmar | {rk['ca']:.2f} | | Win Rate | {rk['wr']*100:.1f}% | | Avg Win | {rk['avg_win']*100:.2f}% | | Avg Loss | {rk['avg_loss']*100:.2f}% | | Profit Factor | {rk['pf']:.2f} | | Skewness | {rk['sk']:.2f} | | Kurtosis | {rk['ku']:.2f} | | 63D Rolling Sharpe | {rk['roll_sharpe']:.2f} | """ return [c1, c2, c3, c4, c5, c6, md] def ai_analyze_stock(ticker, market_preset, period, interval): ticker = ticker.strip().upper() if not ticker: return "Enter a ticker." suffix = MARKET_PRESETS.get(market_preset, {}).get('suffix', '') if suffix and not any(ticker.endswith(s) for s in suffix.split('|')): ticker = ticker + suffix df, info, err = fetch_data(ticker, period) if df is None: return f"Error: {err}" df = calc_indicators(df) sg = calc_signals(df) rk = calc_risk(df) l = df.iloc[-1] p = df.iloc[-2] if len(df)>1 else l ch = ((l['Close']/p['Close']-1)*100) if p['Close']>0 else 0 data_sum = f"""Ticker: {ticker} Price: ${l['Close']:.2f} (Change: {ch:+.2f}%) Period: {period} | Data Points: {len(df)} SMA20: ${l['SMA20']:.2f} | SMA50: ${l['SMA50']:.2f} | SMA200: ${l['SMA200']:.2f} 52W Range: ${df['Low'].min():.2f} - ${df['High'].max():.2f} ATR: ${l['ATR']:.2f} ({l['ATR_pct']:.1f}% of price) Volume: {l['Volume']:,.0f} ({l['VR']:.1f}x avg) """ tech_sum = f"""RSI: {l['RSI']:.1f} | MACD: {l['MACD']:.3f} vs Signal: {l['MACDS']:.3f} | MACD Hist: {l['MACDH']:.3f} BB Position: {l['BBP']:.1%} | BB Width: {l['BBW']:.2f} | Stoch %K: {l['Stoch_K']:.1f} VWAP: ${l['VWAP']:.2f} | ADX: {l['ADX']:.1f} | MFI: {l['MFI']:.1f} Ichimoku: {sg['ichimoku']} | Cloud: Senkou A={l['ICH_senkou_A']:.2f}, B={l['ICH_senkou_B']:.2f} Score: {sg['score']}/100 | Direction: {sg['dir']} | Strength: {sg['strength']} Risk: Sharpe={rk.get('sh',0):.2f}, Vol={rk.get('av',0)*100:.1f}%, MaxDD={rk.get('md',0)*100:.1f}%, VaR95={rk.get('v95',0)*100:.2f}%""" client = K2ThinkClient() return client.analyze_market(ticker, market_preset, data_sum, tech_sum, period) def ai_portfolio(tickers, period): fig, corr_fig, wdf, md = optimize_portfolio(tickers, period) if fig is None: return f"Error: {md}" pd_str = f"Tickers: {', '.join(wdf['Ticker'].tolist())}\nWeights: {', '.join([f'{t}: {w:.1f}%' for t,w in zip(wdf['Ticker'], wdf['Optimal (%)'])])}" corr_str = f"Correlations:\n{wdf['Ticker'].tolist()}" client = K2ThinkClient() return client.portfolio_advice(pd_str, corr_str, md, "Current macro: mixed signals, rates elevated, geopolitical uncertainty") def ai_chat(question, temp): if not question.strip(): return "Enter a question." client = K2ThinkClient() return client.chat([{"role":"user","content":question}], temperature=temp, max_tokens=4096) # GRADIO APP def build_app(): with gr.Blocks( title="AlphaForge x K2 Think V2 - Institutional Quant Platform", theme=gr.themes.Soft( primary_hue="blue", secondary_hue="indigo", neutral_hue="slate", font=[gr.themes.GoogleFont("Inter"), "system-ui", "sans-serif"] ), css=""" body { background: #0d1117 !important; } .gradio-container { background: #0d1117 !important; color: #e6edf3 !important; } .tabitem { background: #161b22 !important; border: 1px solid #30363d !important; border-radius: 12px !important; } .tab-nav { background: #0d1117 !important; border-bottom: 1px solid #30363d !important; } .tab-nav button { color: #8b949e !important; background: transparent !important; border: none !important; } .tab-nav button.selected { color: #58a6ff !important; border-bottom: 2px solid #58a6ff !important; } input, textarea, select { background: #21262d !important; color: #e6edf3 !important; border: 1px solid #30363d !important; } button.primary { background: linear-gradient(135deg, #1f6feb, #58a6ff) !important; color: white !important; border: none !important; border-radius: 8px !important; font-weight: 600 !important; } button.secondary { background: #21262d !important; color: #58a6ff !important; border: 1px solid #30363d !important; border-radius: 8px !important; } .title-bar { text-align: center; padding: 24px 0; } .title-bar h1 { font-size: 2.8em; font-weight: 800; margin: 0; background: linear-gradient(90deg, #58a6ff, #a371f7); -webkit-background-clip: text; -webkit-text-fill-color: transparent; } .title-bar p { color: #8b949e; font-size: 1.1em; margin-top: 8px; } .badge-row { text-align: center; margin: 16px 0 24px; } .badge { display: inline-block; padding: 6px 14px; margin: 4px; border-radius: 20px; font-size: 0.85em; font-weight: 600; } .badge-api { background: linear-gradient(135deg, #1f6feb, #a371f7); color: white; } .badge-data { background: #238636; color: white; } .badge-alpha { background: #8957e5; color: white; } .k2-active { text-align: center; padding: 8px; margin: 8px 0; border-radius: 8px; font-size: 0.9em; background: rgba(35,134,54,0.2); color: #3fb950; border: 1px solid #238636; } .k2-inactive { text-align: center; padding: 8px; margin: 8px 0; border-radius: 8px; font-size: 0.9em; background: rgba(209,36,47,0.2); color: #f85149; border: 1px solid #da3633; } """ ) as demo: gr.HTML("""

🔥 AlphaForge x K2 Think V2

Institutional-Grade Quantitative Analysis Platform - Powered by MBZUAI's State-of-the-Art Reasoning Model

🤖 K2 Think V2 📊 Multi-Market 🎯 AI Alpha 📐 Options 🔗 Pairs 🌍 Macro
""") k2_cls = "k2-active" if K2_API_KEY else "k2-inactive" k2_txt = "✅ K2 Think V2 API Connected" if K2_API_KEY else "⚠️ K2 Think V2 Not Configured — Add K2_API_KEY in Space Settings > Repository Secrets" gr.HTML(f'
{k2_txt}
') with gr.Tab("📈 Technical Analysis"): with gr.Row(): with gr.Column(scale=1): mkt_select = gr.Dropdown(label="🌍 Market", choices=list(MARKET_PRESETS.keys()), value="🇺🇸 US Equities") ticker_in = gr.Textbox(label="Ticker", value="AAPL", placeholder="e.g., AAPL, BTC-USD, EURUSD=X") period_in = gr.Dropdown(label="Period", choices=["1mo","3mo","6mo","1y","2y","5y"], value="6mo") interval_in = gr.Dropdown(label="Interval", choices=["1d","1wk","1mo"], value="1d") analyze_btn = gr.Button("🔍 Analyze", variant="primary") ai_btn = gr.Button("🤖 AI Deep Analysis (K2 Think V2)", variant="secondary") with gr.Column(scale=2): summary_out = gr.Markdown() with gr.Row(): chart1 = gr.Plot(label="Price & Technicals") chart2 = gr.Plot(label="MACD") with gr.Row(): chart3 = gr.Plot(label="Stochastic") chart4 = gr.Plot(label="Volatility & Volume") with gr.Row(): chart5 = gr.Plot(label="ADX Trend Strength") chart6 = gr.Plot(label="Return Distribution") with gr.Row(): ai_out = gr.Textbox(label="🤖 K2 Think V2 Analysis", lines=30, max_lines=50) analyze_btn.click(fn=analyze_stock, inputs=[ticker_in, mkt_select, period_in, interval_in], outputs=[chart1, chart2, chart3, chart4, chart5, chart6, summary_out]) ai_btn.click(fn=ai_analyze_stock, inputs=[ticker_in, mkt_select, period_in, interval_in], outputs=[ai_out]) with gr.Tab("💼 Portfolio Optimizer"): with gr.Row(): with gr.Column(scale=1): port_in = gr.Textbox(label="Tickers (comma-separated)", value="AAPL, MSFT, GOOGL, AMZN, NVDA") port_period = gr.Dropdown(label="Lookback", choices=["6mo","1y","2y","3y"], value="1y") opt_btn = gr.Button("🎯 Optimize", variant="primary") ai_port_btn = gr.Button("🤖 AI Portfolio Advice", variant="secondary") with gr.Column(scale=2): port_md = gr.Markdown() with gr.Row(): frontier_plot = gr.Plot(label="Efficient Frontier") corr_plot = gr.Plot(label="Correlation Matrix") with gr.Row(): weights_df = gr.DataFrame(label="Optimal Weights", interactive=False) with gr.Row(): ai_port_out = gr.Textbox(label="🤖 AI Portfolio Advice", lines=25, max_lines=40) opt_btn.click(fn=optimize_portfolio, inputs=[port_in, port_period], outputs=[frontier_plot, corr_plot, weights_df, port_md]) ai_port_btn.click(fn=ai_portfolio, inputs=[port_in, port_period], outputs=[ai_port_out]) with gr.Tab("🔗 Pairs Trading"): with gr.Row(): with gr.Column(scale=1): pair_a = gr.Textbox(label="Ticker A (Long)", value="AAPL") pair_b = gr.Textbox(label="Ticker B (Short)", value="MSFT") pair_period = gr.Dropdown(label="Lookback", choices=["6mo","1y","2y"], value="1y") pair_btn = gr.Button("Analyze Pair", variant="primary") with gr.Column(scale=2): pair_md = gr.Markdown() with gr.Row(): pair_chart = gr.Plot(label="Spread Analysis") pair_scatter = gr.Plot(label="Price Relationship") pair_btn.click(fn=analyze_pair, inputs=[pair_a, pair_b, pair_period], outputs=[pair_chart, pair_scatter, pair_md]) with gr.Tab("📐 Options Pricing"): with gr.Row(): with gr.Column(scale=1): opt_ticker = gr.Textbox(label="Underlying Ticker", value="AAPL") opt_type = gr.Dropdown(label="Option Type", choices=["Call","Put"], value="Call") opt_strike = gr.Slider(label="Strike (% of spot)", minimum=70, maximum=130, value=100, step=1) opt_days = gr.Slider(label="Days to Expiry", minimum=7, maximum=365, value=30, step=7) opt_rfr = gr.Slider(label="Risk-Free Rate (%)", minimum=0, maximum=10, value=4.5, step=0.25) opt_vol = gr.Number(label="Vol Override (%)", value=0, info="0 = use historical vol") opt_calc_btn = gr.Button("📐 Calculate Greeks", variant="primary") with gr.Column(scale=2): opt_md = gr.Markdown() with gr.Row(): greeks_plot = gr.Plot(label="Greeks Analysis") opt_pl = gr.DataFrame(label="P/L Scenarios", interactive=False) opt_calc_btn.click(fn=analyze_options, inputs=[opt_ticker, opt_strike, opt_days, opt_rfr, opt_vol, opt_type], outputs=[greeks_plot, opt_pl, opt_md]) with gr.Tab("🌍 Macro Analysis"): with gr.Row(): macro_btn = gr.Button("🌍 Analyze Global Macro (K2 Think V2)", variant="primary") with gr.Row(): macro_out = gr.Textbox(label="🤖 K2 Think V2 Macro Analysis", lines=40, max_lines=60) macro_btn.click(fn=ai_macro, outputs=[macro_out]) with gr.Tab("💬 K2 Think V2 Chat"): gr.Markdown("## Direct Chat with K2 Think V2") gr.Markdown("Ask any financial question - strategy, market analysis, quant interview prep, portfolio advice.") with gr.Row(): chat_in = gr.Textbox(label="Your Question", placeholder="e.g., 'Explain gamma scalping with a real trade example'", lines=4) chat_temp = gr.Slider(label="Temp", minimum=0, maximum=1, value=0.4, step=0.1) chat_btn = gr.Button("🚀 Ask K2 Think V2", variant="primary") chat_out = gr.Textbox(label="🤖 Response", lines=30, max_lines=50) chat_btn.click(fn=ai_chat, inputs=[chat_in, chat_temp], outputs=[chat_out]) with gr.Tab("ℹ️ About & Setup"): gr.Markdown(f""" ## AlphaForge x K2 Think V2 Built for the **Build with K2 Think V2 Challenge** by MBZUAI. ### Features | Feature | Description | |---------|-------------| | **📈 Technical Analysis** | 18+ indicators: RSI, MACD, Bollinger, VWAP, Stochastic, ADX, Ichimoku, ATR, MFI, OBV | | **🌍 Multi-Market** | US, EU, UK, DE, JP, CN, IN equities + Crypto + Forex + Commodities + Indices | | **💼 Portfolio** | Mean-variance optimization, efficient frontier, correlation matrix | | **🔗 Pairs Trading** | Cointegration analysis, hedge ratio, half-life, Z-score signals | | **📐 Options Pricing** | Black-Scholes + full Greeks (Delta, Gamma, Theta, Vega, Rho), P/L scenarios | | **🌍 Macro Analysis** | Global cross-asset regime analysis via K2 Think V2 | | **🤖 AI Analysis** | K2 Think V2 chain-of-thought: entry/stop/target, catalyst calendar, contrarian view | | **💬 AI Chat** | Ask any financial question with adjustable temperature | ### Setup > **K2 Think V2 API Key** > 1. Space Settings → Repository secrets > 2. New secret: `K2_API_KEY` = `IFM-4SpQ0qEg0Wlsw04O` > 3. Save → Factory Rebuild **Without API key:** All technical analysis, charts, portfolio optimization, pairs trading, and options pricing work perfectly! ### Links - [Full AlphaForge](https://huggingface.co/Premchan369/alphaforge-quant-system) (25 quant modules) - [Q-TensorFormer](https://huggingface.co/Premchan369/Q-TensorFormer) (Quantum AI) - [Challenge](https://build.k2think.ai/) - [MBZUAI](https://mbzuai.ac.ae/) *Built by Premchan | Build with K2 Think V2* """) return demo if __name__ == "__main__": demo = build_app() demo.queue().launch(server_name="0.0.0.0", server_port=7860)