Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -1,95 +1,159 @@
|
|
1 |
import gradio as gr
|
|
|
|
|
|
|
|
|
|
|
|
|
2 |
|
3 |
-
#
|
4 |
-
|
5 |
-
"AAPL": {
|
6 |
-
"events": [
|
7 |
-
{"name": "New iPhone release", "impact_if_happens": 0.10, "impact_if_not": -0.05},
|
8 |
-
{"name": "Positive earnings report", "impact_if_happens": 0.08, "impact_if_not": -0.03},
|
9 |
-
]
|
10 |
-
},
|
11 |
-
"TSLA": {
|
12 |
-
"events": [
|
13 |
-
{"name": "Achieves production target", "impact_if_happens": 0.15, "impact_if_not": -0.10},
|
14 |
-
{"name": "New model announcement", "impact_if_happens": 0.12, "impact_if_not": -0.02},
|
15 |
-
]
|
16 |
-
},
|
17 |
-
"GOOG": {
|
18 |
-
"events": [
|
19 |
-
{"name": "AI breakthrough", "impact_if_happens": 0.20, "impact_if_not": -0.05},
|
20 |
-
{"name": "Regulatory approval", "impact_if_happens": 0.05, "impact_if_not": -0.15},
|
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 |
-
return output
|
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 |
-
# Launch the app
|
94 |
if __name__ == "__main__":
|
95 |
-
|
|
|
1 |
import gradio as gr
|
2 |
+
import yfinance as yf
|
3 |
+
import requests
|
4 |
+
import numpy as np
|
5 |
+
import pandas as pd
|
6 |
+
import matplotlib.pyplot as plt
|
7 |
+
from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
|
8 |
|
9 |
+
# Polymarket GraphQL API endpoint
|
10 |
+
POLYMARKET_API = "https://api.polymarket.com/graphql"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11 |
|
12 |
+
# Function to fetch Polymarket data
|
13 |
+
def fetch_polymarket_data(search_term="S&P"):
|
14 |
+
query = """
|
15 |
+
query {
|
16 |
+
markets(first: 5, searchTerm: "%s") {
|
17 |
+
edges {
|
18 |
+
node {
|
19 |
+
id
|
20 |
+
question
|
21 |
+
outcomes {
|
22 |
+
name
|
23 |
+
price
|
24 |
+
}
|
25 |
+
}
|
26 |
+
}
|
27 |
+
}
|
28 |
}
|
29 |
+
""" % search_term
|
30 |
+
response = requests.post(POLYMARKET_API, json={"query": query})
|
31 |
+
if response.status_code != 200:
|
32 |
+
return None
|
33 |
+
data = response.json()
|
34 |
+
markets = data["data"]["markets"]["edges"]
|
35 |
+
if not markets:
|
36 |
+
return None
|
37 |
|
38 |
+
# Parse the first relevant market
|
39 |
+
for market in markets:
|
40 |
+
node = market["node"]
|
41 |
+
outcomes = node["outcomes"]
|
42 |
+
if len(outcomes) >= 2: # Ensure there's at least Yes/No or similar
|
43 |
+
return {
|
44 |
+
"question": node["question"],
|
45 |
+
"outcomes": {outcome["name"]: float(outcome["price"]) for outcome in outcomes}
|
46 |
+
}
|
47 |
+
return None
|
48 |
+
|
49 |
+
# Function to fetch Yahoo Finance data and calculate drift/volatility
|
50 |
+
def fetch_yahoo_data(ticker):
|
51 |
+
try:
|
52 |
+
stock = yf.download(ticker, period="1y", progress=False)
|
53 |
+
if stock.empty:
|
54 |
+
return None, None, None
|
55 |
+
daily_returns = stock["Adj Close"].pct_change().dropna()
|
56 |
+
mu = daily_returns.mean() * 252 # Annualized drift
|
57 |
+
sigma = daily_returns.std() * np.sqrt(252) # Annualized volatility
|
58 |
+
last_price = stock["Adj Close"][-1]
|
59 |
+
return mu, sigma, last_price
|
60 |
+
except Exception:
|
61 |
+
return None, None, None
|
|
|
62 |
|
63 |
+
# Monte Carlo Simulation with GBM
|
64 |
+
def monte_carlo_simulation(S0, mu, sigma, T, N, sims, risk_factor, pm_data):
|
65 |
+
dt = 1 / 252 # Daily time step
|
66 |
+
steps = int(T * 252)
|
67 |
+
sim_paths = np.zeros((sims, steps + 1))
|
68 |
+
sim_paths[:, 0] = S0
|
69 |
|
70 |
+
# Adjust drift based on Polymarket probabilities
|
71 |
+
if pm_data and "outcomes" in pm_data:
|
72 |
+
outcomes = pm_data["outcomes"]
|
73 |
+
bullish_prob = outcomes.get("Yes", 0.5) if "Yes" in outcomes else 0.5
|
74 |
+
bearish_prob = 1 - bullish_prob
|
75 |
+
mu_bull = mu * 1.2 * risk_factor
|
76 |
+
mu_bear = mu * -0.5 * risk_factor
|
77 |
+
mu_adjusted = bullish_prob * mu_bull + bearish_prob * mu_bear
|
78 |
+
else:
|
79 |
+
mu_adjusted = mu * risk_factor
|
80 |
|
81 |
+
for t in range(1, steps + 1):
|
82 |
+
Z = np.random.standard_normal(sims)
|
83 |
+
sim_paths[:, t] = sim_paths[:, t-1] * np.exp(
|
84 |
+
(mu_adjusted - 0.5 * sigma**2) * dt + sigma * np.sqrt(dt) * Z
|
85 |
+
)
|
86 |
+
|
87 |
+
return sim_paths
|
88 |
+
|
89 |
+
# Main simulation function
|
90 |
+
def run_simulation(investment, ticker, horizon, num_sims, risk_factor):
|
91 |
+
# Fetch data
|
92 |
+
mu, sigma, S0 = fetch_yahoo_data(ticker)
|
93 |
+
if mu is None:
|
94 |
+
return None, "Invalid ticker or no data available from Yahoo Finance."
|
95 |
+
|
96 |
+
pm_data = fetch_polymarket_data("S&P") # Search for S&P-related markets
|
97 |
+
|
98 |
+
# Run Monte Carlo simulation
|
99 |
+
sim_paths = monte_carlo_simulation(S0, mu, sigma, horizon, num_sims, num_sims, risk_factor, pm_data)
|
100 |
+
final_values = sim_paths[:, -1] * (investment / S0) # Scale to investment amount
|
101 |
+
|
102 |
+
# Create histogram
|
103 |
+
fig, ax = plt.subplots(figsize=(8, 6))
|
104 |
+
ax.hist(final_values, bins=50, color="skyblue", edgecolor="black")
|
105 |
+
ax.set_title(f"Distribution of Final Investment Value ({ticker})")
|
106 |
+
ax.set_xlabel("Final Value ($)")
|
107 |
+
ax.set_ylabel("Frequency")
|
108 |
+
plt.tight_layout()
|
109 |
+
|
110 |
+
# Calculate stats
|
111 |
+
mean_val = np.mean(final_values)
|
112 |
+
min_val = np.min(final_values)
|
113 |
+
max_val = np.max(final_values)
|
114 |
+
std_val = np.std(final_values)
|
115 |
+
|
116 |
+
# Prepare summary text
|
117 |
+
summary = f"Market Data (Yahoo Finance):\n"
|
118 |
+
summary += f"- Drift (μ): {mu:.4f}\n"
|
119 |
+
summary += f"- Volatility (σ): {sigma:.4f}\n\n"
|
120 |
+
if pm_data:
|
121 |
+
summary += f"Polymarket Data:\n- Question: {pm_data['question']}\n"
|
122 |
+
for outcome, prob in pm_data["outcomes"].items():
|
123 |
+
summary += f"- {outcome}: {prob*100:.1f}%\n"
|
124 |
+
else:
|
125 |
+
summary += "Polymarket Data: No relevant market found.\n"
|
126 |
+
summary += f"\nSimulation Results:\n"
|
127 |
+
summary += f"- Mean Final Value: ${mean_val:.2f}\n"
|
128 |
+
summary += f"- Min Final Value: ${min_val:.2f}\n"
|
129 |
+
summary += f"- Max Final Value: ${max_val:.2f}\n"
|
130 |
+
summary += f"- Std Dev: ${std_val:.2f}"
|
131 |
+
|
132 |
+
return fig, summary
|
133 |
|
134 |
+
# Gradio UI
|
135 |
+
with gr.Blocks(title="Investment Simulation Platform") as demo:
|
136 |
+
gr.Markdown("# Investment Decision Simulation Platform")
|
137 |
+
gr.Markdown("Simulate investment outcomes using Yahoo Finance data and Polymarket probabilities.")
|
138 |
+
|
139 |
+
with gr.Row():
|
140 |
+
with gr.Column():
|
141 |
+
investment = gr.Number(label="Investment Amount ($)", value=10000)
|
142 |
+
ticker = gr.Textbox(label="Ticker Symbol (e.g., AAPL, ^GSPC)", value="AAPL")
|
143 |
+
horizon = gr.Number(label="Investment Horizon (Years)", value=1)
|
144 |
+
num_sims = gr.Number(label="Number of Simulations", value=1000)
|
145 |
+
risk_factor = gr.Slider(0.5, 2.0, value=1.0, label="Risk Factor")
|
146 |
+
submit_btn = gr.Button("Run Simulation")
|
147 |
+
|
148 |
+
with gr.Column():
|
149 |
+
plot_output = gr.Plot(label="Final Value Distribution")
|
150 |
+
text_output = gr.Textbox(label="Simulation Summary", lines=10)
|
151 |
+
|
152 |
+
submit_btn.click(
|
153 |
+
fn=run_simulation,
|
154 |
+
inputs=[investment, ticker, horizon, num_sims, risk_factor],
|
155 |
+
outputs=[plot_output, text_output]
|
156 |
+
)
|
157 |
|
|
|
158 |
if __name__ == "__main__":
|
159 |
+
demo.launch()
|