codelion commited on
Commit
b02bd01
·
verified ·
1 Parent(s): 18ee127

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +148 -84
app.py CHANGED
@@ -1,95 +1,159 @@
1
  import gradio as gr
 
 
 
 
 
 
2
 
3
- # Define stocks with their events and impacts
4
- stocks = {
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
- def calculate_portfolio(selected_stocks, total_investment,
26
- aapl_event1_prob, aapl_event2_prob,
27
- tsla_event1_prob, tsla_event2_prob,
28
- goog_event1_prob, goog_event2_prob):
29
- # Check if any stocks are selected
30
- if not selected_stocks:
31
- return "Please select at least one stock."
32
-
33
- # Map user-input probabilities to stocks (convert from percentage to decimal)
34
- probs = {
35
- "AAPL": [aapl_event1_prob / 100, aapl_event2_prob / 100],
36
- "TSLA": [tsla_event1_prob / 100, tsla_event2_prob / 100],
37
- "GOOG": [goog_event1_prob / 100, goog_event2_prob / 100],
 
 
 
38
  }
 
 
 
 
 
 
 
 
39
 
40
- # Calculate expected return for each selected stock
41
- expected_returns = {}
42
- for stock in selected_stocks:
43
- events = stocks[stock]["events"]
44
- exp_return = 0
45
- for i, event in enumerate(events):
46
- p = probs[stock][i]
47
- impact_happens = event["impact_if_happens"]
48
- impact_not = event["impact_if_not"]
49
- exp_return += p * impact_happens + (1 - p) * impact_not
50
- expected_returns[stock] = exp_return
51
-
52
- # Calculate portfolio metrics assuming equal investment
53
- num_stocks = len(selected_stocks)
54
- investment_per_stock = total_investment / num_stocks
55
- portfolio_expected_return = sum(expected_returns[stock] for stock in selected_stocks) / num_stocks
56
- expected_future_value = sum(investment_per_stock * (1 + expected_returns[stock]) for stock in selected_stocks)
57
-
58
- # Format the output
59
- output = "Expected Returns:\n"
60
- for stock in selected_stocks:
61
- output += f"{stock}: {expected_returns[stock]*100:.2f}%\n"
62
- output += f"\nPortfolio Expected Return: {portfolio_expected_return*100:.2f}%\n"
63
- output += f"Expected Future Value: ${expected_future_value:.2f}"
64
- return output
65
 
66
- # Define Gradio inputs
67
- selected_stocks = gr.CheckboxGroup(choices=["AAPL", "TSLA", "GOOG"], label="Select Stocks")
68
- total_investment = gr.Number(label="Total Investment ($)", value=10000)
 
 
 
69
 
70
- # Probability sliders for each event
71
- aapl_event1_prob = gr.Slider(0, 100, label="AAPL: Probability of New iPhone release (%)", value=50)
72
- aapl_event2_prob = gr.Slider(0, 100, label="AAPL: Probability of Positive earnings report (%)", value=50)
73
- tsla_event1_prob = gr.Slider(0, 100, label="TSLA: Probability of Achieving production target (%)", value=50)
74
- tsla_event2_prob = gr.Slider(0, 100, label="TSLA: Probability of New model announcement (%)", value=50)
75
- goog_event1_prob = gr.Slider(0, 100, label="GOOG: Probability of AI breakthrough (%)", value=50)
76
- goog_event2_prob = gr.Slider(0, 100, label="GOOG: Probability of Regulatory approval (%)", value=50)
 
 
 
77
 
78
- # Define output
79
- output = gr.Textbox(label="Results")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
80
 
81
- # Create Gradio interface
82
- iface = gr.Interface(
83
- fn=calculate_portfolio,
84
- inputs=[selected_stocks, total_investment,
85
- aapl_event1_prob, aapl_event2_prob,
86
- tsla_event1_prob, tsla_event2_prob,
87
- goog_event1_prob, goog_event2_prob],
88
- outputs=output,
89
- title="Investment Decision Analysis POC",
90
- description="Select stocks and adjust event probabilities to analyze expected returns based on simulated prediction market data. Event impacts are predefined. Click 'Submit' to see results."
91
- )
 
 
 
 
 
 
 
 
 
 
 
 
92
 
93
- # Launch the app
94
  if __name__ == "__main__":
95
- iface.launch()
 
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()