dibend commited on
Commit
c3b67d5
·
verified ·
1 Parent(s): 58ddaed

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +31 -24
app.py CHANGED
@@ -3,32 +3,44 @@ import pandas as pd
3
  import numpy as np
4
  import plotly.graph_objects as go
5
 
6
- # Live CSV URL for Median Sales Price
7
  CSV_URL = "https://gardenstatemls.stats.showingtime.com/infoserv/s-v1/kpou-Asg"
8
 
9
  def monte_carlo_live(T=1.0, steps=12, n_paths=100):
10
  try:
11
- # Load and clean CSV
12
  df = pd.read_csv(CSV_URL, skiprows=9)
13
- df = df.dropna(axis=1, how='all') # Drop empty unnamed columns
 
 
 
 
 
14
  df.columns = ['Date', 'Median Sales Price']
15
 
16
- # Parse full month + year format like "January 2009"
17
- df['Date'] = pd.to_datetime(df['Date'], format="%B %Y")
 
18
 
19
- # Convert price to float
 
 
 
 
20
  df['Median Sales Price'] = df['Median Sales Price'].replace('[\$,]', '', regex=True).astype(float)
21
 
22
- # Historical prices and returns
 
 
23
  prices = df['Median Sales Price'].values
24
- returns = np.diff(np.log(prices))
 
25
 
26
- # Calculate annualized drift (mu) and volatility (sigma)
27
- mu = np.mean(returns) * 12
28
- sigma = np.std(returns) * np.sqrt(12)
29
  S0 = prices[-1]
30
 
31
- # Monte Carlo simulation (Geometric Brownian Motion)
32
  dt = T / steps
33
  paths = np.zeros((steps + 1, n_paths))
34
  paths[0] = S0
@@ -36,31 +48,26 @@ def monte_carlo_live(T=1.0, steps=12, n_paths=100):
36
  rand = np.random.normal(0, 1, n_paths)
37
  paths[t] = paths[t - 1] * np.exp((mu - 0.5 * sigma**2) * dt + sigma * np.sqrt(dt) * rand)
38
 
39
- # Time axis
40
  time = np.linspace(0, T, steps + 1)
41
-
42
- # Create Plotly chart
43
  fig = go.Figure()
44
 
45
  for i in range(n_paths):
46
  fig.add_trace(go.Scatter(x=time, y=paths[:, i], mode='lines', line=dict(width=1), showlegend=False))
47
 
48
- # Mean and median paths
49
  mean_path = paths.mean(axis=1)
50
  median_path = np.median(paths, axis=1)
51
  fig.add_trace(go.Scatter(x=time, y=mean_path, name='Mean Path', line=dict(width=3, dash='dash')))
52
  fig.add_trace(go.Scatter(x=time, y=median_path, name='Median Path', line=dict(width=3, dash='dot')))
53
 
54
  fig.update_layout(
55
- title="Monte Carlo Simulation — Median Sales Price Forecast",
56
- xaxis_title="Time (Years)",
57
  yaxis_title="Simulated Price ($)",
58
  height=600
59
  )
60
 
61
- # Text summary
62
- summary = f"Simulated {n_paths} paths from latest value ${S0:.2f}.\n" \
63
- f"Annualized drift (μ): {mu*100:.2f}%, Volatility (σ): {sigma*100:.2f}%"
64
 
65
  return fig, summary
66
 
@@ -75,14 +82,14 @@ def monte_carlo_live(T=1.0, steps=12, n_paths=100):
75
  }])
76
  return fig, f"Error: {e}"
77
 
78
- # Gradio UI
79
  with gr.Blocks() as demo:
80
- gr.Markdown("## 📈 Monte Carlo Simulation: Live MLS Median Sales Price Forecast")
81
 
82
  with gr.Row():
83
  years = gr.Slider(0.1, 5.0, value=1.0, step=0.1, label="Forecast Horizon (Years)")
84
  steps = gr.Slider(12, 120, value=12, step=12, label="Time Steps")
85
- paths = gr.Slider(10, 300, value=100, step=10, label="Number of Paths")
86
 
87
  run_button = gr.Button("Run Simulation")
88
  plot = gr.Plot()
 
3
  import numpy as np
4
  import plotly.graph_objects as go
5
 
 
6
  CSV_URL = "https://gardenstatemls.stats.showingtime.com/infoserv/s-v1/kpou-Asg"
7
 
8
  def monte_carlo_live(T=1.0, steps=12, n_paths=100):
9
  try:
10
+ # Load CSV with metadata skipped
11
  df = pd.read_csv(CSV_URL, skiprows=9)
12
+
13
+ # Drop completely empty columns
14
+ df = df.dropna(axis=1, how='all')
15
+
16
+ # Expect first two useful columns: Date and Median Sales Price
17
+ df = df.iloc[:, :2]
18
  df.columns = ['Date', 'Median Sales Price']
19
 
20
+ # Filter out rows where either value is NaN or clearly non-numeric
21
+ df = df.dropna(subset=['Date', 'Median Sales Price'])
22
+ df = df[df['Median Sales Price'].str.contains(r'\d', na=False)]
23
 
24
+ # Parse date with full month names
25
+ df['Date'] = pd.to_datetime(df['Date'], errors='coerce')
26
+ df = df.dropna(subset=['Date'])
27
+
28
+ # Clean price data
29
  df['Median Sales Price'] = df['Median Sales Price'].replace('[\$,]', '', regex=True).astype(float)
30
 
31
+ # Ensure sorted time series
32
+ df = df.sort_values(by='Date')
33
+
34
  prices = df['Median Sales Price'].values
35
+ if len(prices) < 2:
36
+ raise ValueError("Not enough valid price data after cleaning.")
37
 
38
+ returns = np.diff(np.log(prices))
39
+ mu = returns.mean() * 12
40
+ sigma = returns.std() * np.sqrt(12)
41
  S0 = prices[-1]
42
 
43
+ # Monte Carlo simulation
44
  dt = T / steps
45
  paths = np.zeros((steps + 1, n_paths))
46
  paths[0] = S0
 
48
  rand = np.random.normal(0, 1, n_paths)
49
  paths[t] = paths[t - 1] * np.exp((mu - 0.5 * sigma**2) * dt + sigma * np.sqrt(dt) * rand)
50
 
 
51
  time = np.linspace(0, T, steps + 1)
 
 
52
  fig = go.Figure()
53
 
54
  for i in range(n_paths):
55
  fig.add_trace(go.Scatter(x=time, y=paths[:, i], mode='lines', line=dict(width=1), showlegend=False))
56
 
 
57
  mean_path = paths.mean(axis=1)
58
  median_path = np.median(paths, axis=1)
59
  fig.add_trace(go.Scatter(x=time, y=mean_path, name='Mean Path', line=dict(width=3, dash='dash')))
60
  fig.add_trace(go.Scatter(x=time, y=median_path, name='Median Path', line=dict(width=3, dash='dot')))
61
 
62
  fig.update_layout(
63
+ title="Monte Carlo Simulation — MLS Median Sales Price Forecast",
64
+ xaxis_title="Years Ahead",
65
  yaxis_title="Simulated Price ($)",
66
  height=600
67
  )
68
 
69
+ summary = f"Simulated {n_paths} paths from latest price ${S0:.2f}.\n" \
70
+ f"μ = {mu*100:.2f}% / year, σ = {sigma*100:.2f}% / year."
 
71
 
72
  return fig, summary
73
 
 
82
  }])
83
  return fig, f"Error: {e}"
84
 
85
+ # Gradio app
86
  with gr.Blocks() as demo:
87
+ gr.Markdown("## 📊 Monte Carlo Simulation Based on Live MLS Data")
88
 
89
  with gr.Row():
90
  years = gr.Slider(0.1, 5.0, value=1.0, step=0.1, label="Forecast Horizon (Years)")
91
  steps = gr.Slider(12, 120, value=12, step=12, label="Time Steps")
92
+ paths = gr.Slider(10, 300, value=100, step=10, label="Number of Simulated Paths")
93
 
94
  run_button = gr.Button("Run Simulation")
95
  plot = gr.Plot()