Spaces:
Sleeping
Sleeping
File size: 6,882 Bytes
18ee127 b02bd01 fb027d3 18ee127 b02bd01 18ee127 b02bd01 48663c9 b02bd01 48663c9 fb027d3 48663c9 b02bd01 48663c9 b02bd01 fb027d3 18ee127 b02bd01 18ee127 b02bd01 18ee127 b02bd01 48663c9 b02bd01 48663c9 b02bd01 48663c9 b02bd01 fb027d3 b02bd01 8901955 48663c9 b02bd01 48663c9 b02bd01 18ee127 b02bd01 8901955 b02bd01 48663c9 b02bd01 18ee127 b02bd01 |
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 |
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
import time
# Polymarket GraphQL API endpoint
POLYMARKET_API = "https://api.polymarket.com/graphql"
# Function to fetch Polymarket data
def fetch_polymarket_data(search_term="S&P"):
try:
query = """
query {
markets(first: 5, searchTerm: "%s") {
edges {
node {
id
question
outcomes {
name
price
}
}
}
}
}
""" % search_term
response = requests.post(POLYMARKET_API, json={"query": query}, timeout=10)
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:
return {
"question": node["question"],
"outcomes": {outcome["name"]: float(outcome["price"]) for outcome in outcomes}
}
return None
except Exception as e:
return None
# Function to fetch Yahoo Finance data with retry
def fetch_yahoo_data(ticker, retries=3, delay=2):
for attempt in range(retries):
try:
stock = yf.download(ticker, period="1y", auto_adjust=False, progress=False)
if stock.empty or len(stock) < 2:
return None, None, None, f"No data returned for ticker '{ticker}'. It may be invalid or lack sufficient history."
daily_returns = stock["Close"].pct_change().dropna()
if daily_returns.empty:
return None, None, None, f"No valid returns calculated for ticker '{ticker}'. Insufficient price data."
mu = daily_returns.mean() * 252 # Annualized drift
sigma = daily_returns.std() * np.sqrt(252) # Annualized volatility
last_price = stock["Close"][-1] # Use most recent unadjusted Close
return mu, sigma, last_price, None
except Exception as e:
error_msg = f"Attempt {attempt + 1}/{retries} failed for ticker '{ticker}': {str(e)}"
if attempt < retries - 1:
time.sleep(delay) # Wait before retrying
else:
return None, None, None, error_msg
return None, None, None, f"Failed to fetch data for '{ticker}' after {retries} attempts."
# 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):
# Validate inputs
if not ticker or investment <= 0 or horizon <= 0 or num_sims <= 0:
return None, "Please provide valid inputs: positive investment, horizon, and simulations, and a ticker."
# Fetch data
mu, sigma, S0, error_msg = fetch_yahoo_data(ticker)
if mu is None:
return None, error_msg
pm_data = fetch_polymarket_data("S&P")
# 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} (based on unadjusted Close)\n"
summary += f"- Volatility (σ): {sigma:.4f}\n"
summary += f"- Last Close Price: ${S0:.2f}\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 or API unavailable.\n"
summary += f"\nSimulation Results ({num_sims} runs):\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 (unadjusted) 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=12)
submit_btn.click(
fn=run_simulation,
inputs=[investment, ticker, horizon, num_sims, risk_factor],
outputs=[plot_output, text_output]
)
if __name__ == "__main__":
demo.launch() |