Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import yfinance as yf | |
| import requests | |
| import numpy as np | |
| import pandas as pd | |
| import matplotlib.pyplot as plt | |
| from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas | |
| # Polymarket GraphQL API endpoint | |
| POLYMARKET_API = "https://api.polymarket.com/graphql" | |
| # Function to fetch Polymarket data | |
| def fetch_polymarket_data(search_term="S&P"): | |
| query = """ | |
| query { | |
| markets(first: 5, searchTerm: "%s") { | |
| edges { | |
| node { | |
| id | |
| question | |
| outcomes { | |
| name | |
| price | |
| } | |
| } | |
| } | |
| } | |
| } | |
| """ % search_term | |
| response = requests.post(POLYMARKET_API, json={"query": query}) | |
| if response.status_code != 200: | |
| return None | |
| data = response.json() | |
| markets = data["data"]["markets"]["edges"] | |
| if not markets: | |
| return None | |
| # Parse the first relevant market | |
| for market in markets: | |
| node = market["node"] | |
| outcomes = node["outcomes"] | |
| if len(outcomes) >= 2: # Ensure there's at least Yes/No or similar | |
| return { | |
| "question": node["question"], | |
| "outcomes": {outcome["name"]: float(outcome["price"]) for outcome in outcomes} | |
| } | |
| return None | |
| # Function to fetch Yahoo Finance data and calculate drift/volatility | |
| def fetch_yahoo_data(ticker): | |
| try: | |
| stock = yf.download(ticker, period="1y", progress=False) | |
| if stock.empty: | |
| return None, None, None | |
| daily_returns = stock["Adj Close"].pct_change().dropna() | |
| mu = daily_returns.mean() * 252 # Annualized drift | |
| sigma = daily_returns.std() * np.sqrt(252) # Annualized volatility | |
| last_price = stock["Adj Close"][-1] | |
| return mu, sigma, last_price | |
| except Exception: | |
| return None, None, None | |
| # Monte Carlo Simulation with GBM | |
| def monte_carlo_simulation(S0, mu, sigma, T, N, sims, risk_factor, pm_data): | |
| dt = 1 / 252 # Daily time step | |
| steps = int(T * 252) | |
| sim_paths = np.zeros((sims, steps + 1)) | |
| sim_paths[:, 0] = S0 | |
| # Adjust drift based on Polymarket probabilities | |
| if pm_data and "outcomes" in pm_data: | |
| outcomes = pm_data["outcomes"] | |
| bullish_prob = outcomes.get("Yes", 0.5) if "Yes" in outcomes else 0.5 | |
| bearish_prob = 1 - bullish_prob | |
| mu_bull = mu * 1.2 * risk_factor | |
| mu_bear = mu * -0.5 * risk_factor | |
| mu_adjusted = bullish_prob * mu_bull + bearish_prob * mu_bear | |
| else: | |
| mu_adjusted = mu * risk_factor | |
| for t in range(1, steps + 1): | |
| Z = np.random.standard_normal(sims) | |
| sim_paths[:, t] = sim_paths[:, t-1] * np.exp( | |
| (mu_adjusted - 0.5 * sigma**2) * dt + sigma * np.sqrt(dt) * Z | |
| ) | |
| return sim_paths | |
| # Main simulation function | |
| def run_simulation(investment, ticker, horizon, num_sims, risk_factor): | |
| # Fetch data | |
| mu, sigma, S0 = fetch_yahoo_data(ticker) | |
| if mu is None: | |
| return None, "Invalid ticker or no data available from Yahoo Finance." | |
| pm_data = fetch_polymarket_data("S&P") # Search for S&P-related markets | |
| # Run Monte Carlo simulation | |
| sim_paths = monte_carlo_simulation(S0, mu, sigma, horizon, num_sims, num_sims, risk_factor, pm_data) | |
| final_values = sim_paths[:, -1] * (investment / S0) # Scale to investment amount | |
| # Create histogram | |
| fig, ax = plt.subplots(figsize=(8, 6)) | |
| ax.hist(final_values, bins=50, color="skyblue", edgecolor="black") | |
| ax.set_title(f"Distribution of Final Investment Value ({ticker})") | |
| ax.set_xlabel("Final Value ($)") | |
| ax.set_ylabel("Frequency") | |
| plt.tight_layout() | |
| # Calculate stats | |
| mean_val = np.mean(final_values) | |
| min_val = np.min(final_values) | |
| max_val = np.max(final_values) | |
| std_val = np.std(final_values) | |
| # Prepare summary text | |
| summary = f"Market Data (Yahoo Finance):\n" | |
| summary += f"- Drift (μ): {mu:.4f}\n" | |
| summary += f"- Volatility (σ): {sigma:.4f}\n\n" | |
| if pm_data: | |
| summary += f"Polymarket Data:\n- Question: {pm_data['question']}\n" | |
| for outcome, prob in pm_data["outcomes"].items(): | |
| summary += f"- {outcome}: {prob*100:.1f}%\n" | |
| else: | |
| summary += "Polymarket Data: No relevant market found.\n" | |
| summary += f"\nSimulation Results:\n" | |
| summary += f"- Mean Final Value: ${mean_val:.2f}\n" | |
| summary += f"- Min Final Value: ${min_val:.2f}\n" | |
| summary += f"- Max Final Value: ${max_val:.2f}\n" | |
| summary += f"- Std Dev: ${std_val:.2f}" | |
| return fig, summary | |
| # Gradio UI | |
| with gr.Blocks(title="Investment Simulation Platform") as demo: | |
| gr.Markdown("# Investment Decision Simulation Platform") | |
| gr.Markdown("Simulate investment outcomes using Yahoo Finance data and Polymarket probabilities.") | |
| with gr.Row(): | |
| with gr.Column(): | |
| investment = gr.Number(label="Investment Amount ($)", value=10000) | |
| ticker = gr.Textbox(label="Ticker Symbol (e.g., AAPL, ^GSPC)", value="AAPL") | |
| horizon = gr.Number(label="Investment Horizon (Years)", value=1) | |
| num_sims = gr.Number(label="Number of Simulations", value=1000) | |
| risk_factor = gr.Slider(0.5, 2.0, value=1.0, label="Risk Factor") | |
| submit_btn = gr.Button("Run Simulation") | |
| with gr.Column(): | |
| plot_output = gr.Plot(label="Final Value Distribution") | |
| text_output = gr.Textbox(label="Simulation Summary", lines=10) | |
| submit_btn.click( | |
| fn=run_simulation, | |
| inputs=[investment, ticker, horizon, num_sims, risk_factor], | |
| outputs=[plot_output, text_output] | |
| ) | |
| if __name__ == "__main__": | |
| demo.launch() |