MythMan commited on
Commit
20f34b4
·
verified ·
1 Parent(s): f348578

Upload app.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. app.py +230 -0
app.py ADDED
@@ -0,0 +1,230 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Arvanu Chronos Forecaster - Time Series Prediction API
3
+ Part of the Arvanu AI Prediction Ensemble for Premium Tiers
4
+
5
+ Uses amazon/chronos-bolt-base for fast, accurate probabilistic forecasting
6
+ of market odds trajectories.
7
+ """
8
+
9
+ import gradio as gr
10
+ import numpy as np
11
+ import torch
12
+ from chronos import ChronosBoltPipeline
13
+ import json
14
+
15
+ # Load model on startup (cached)
16
+ print("Loading Chronos-Bolt model...")
17
+ pipeline = ChronosBoltPipeline.from_pretrained(
18
+ "amazon/chronos-bolt-base",
19
+ device_map="cpu", # HF free tier is CPU only
20
+ torch_dtype=torch.float32,
21
+ )
22
+ print("Model loaded successfully!")
23
+
24
+
25
+ def forecast_odds(
26
+ historical_prices: str,
27
+ prediction_horizon: int = 24,
28
+ num_samples: int = 20,
29
+ ) -> dict:
30
+ """
31
+ Forecast market odds trajectory.
32
+
33
+ Args:
34
+ historical_prices: JSON array of historical YES prices (0-1 range)
35
+ e.g., "[0.52, 0.54, 0.55, 0.58, 0.56, ...]"
36
+ prediction_horizon: Number of time steps to forecast (default: 24)
37
+ num_samples: Number of sample trajectories for uncertainty (default: 20)
38
+
39
+ Returns:
40
+ JSON with forecast, trend analysis, and confidence metrics
41
+ """
42
+ try:
43
+ # Parse input
44
+ if isinstance(historical_prices, str):
45
+ prices = json.loads(historical_prices)
46
+ else:
47
+ prices = list(historical_prices)
48
+
49
+ if len(prices) < 10:
50
+ return {"error": "Need at least 10 historical data points"}
51
+
52
+ # Ensure values are in valid range
53
+ prices = [max(0.01, min(0.99, float(p))) for p in prices]
54
+
55
+ # Convert to tensor
56
+ context = torch.tensor(prices, dtype=torch.float32).unsqueeze(0)
57
+
58
+ # Generate forecasts
59
+ with torch.no_grad():
60
+ forecasts = pipeline.predict(
61
+ context=context,
62
+ prediction_length=prediction_horizon,
63
+ num_samples=num_samples,
64
+ )
65
+
66
+ # forecasts shape: (1, num_samples, prediction_horizon)
67
+ forecast_np = forecasts[0].numpy()
68
+
69
+ # Calculate quantiles
70
+ q10 = np.percentile(forecast_np, 10, axis=0).tolist()
71
+ q50 = np.percentile(forecast_np, 50, axis=0).tolist() # Median
72
+ q90 = np.percentile(forecast_np, 90, axis=0).tolist()
73
+
74
+ # Trend analysis
75
+ current_price = prices[-1]
76
+ forecast_end = q50[-1]
77
+ price_change = forecast_end - current_price
78
+
79
+ # Determine trend
80
+ if price_change > 0.03:
81
+ trend = "strongly_bullish"
82
+ trend_strength = min(1.0, price_change * 10)
83
+ elif price_change > 0.01:
84
+ trend = "bullish"
85
+ trend_strength = min(0.7, price_change * 10)
86
+ elif price_change < -0.03:
87
+ trend = "strongly_bearish"
88
+ trend_strength = min(1.0, abs(price_change) * 10)
89
+ elif price_change < -0.01:
90
+ trend = "bearish"
91
+ trend_strength = min(0.7, abs(price_change) * 10)
92
+ else:
93
+ trend = "neutral"
94
+ trend_strength = 0.3
95
+
96
+ # Calculate momentum (rate of change)
97
+ if len(prices) >= 5:
98
+ recent_momentum = (prices[-1] - prices[-5]) / 5
99
+ else:
100
+ recent_momentum = 0
101
+
102
+ # Volatility from forecast spread
103
+ avg_spread = np.mean(np.array(q90) - np.array(q10))
104
+ volatility = float(avg_spread)
105
+
106
+ # Confidence based on forecast tightness and trend clarity
107
+ # Tighter forecasts = higher confidence
108
+ confidence = max(0.3, min(0.95, 1.0 - (volatility * 2)))
109
+
110
+ # Adjust confidence based on trend strength
111
+ if trend in ["strongly_bullish", "strongly_bearish"]:
112
+ confidence = min(0.95, confidence * 1.15)
113
+
114
+ # Direction for ensemble (matches NLP output format)
115
+ if trend in ["bullish", "strongly_bullish"]:
116
+ direction = "YES"
117
+ direction_confidence = 0.5 + (trend_strength * 0.4)
118
+ elif trend in ["bearish", "strongly_bearish"]:
119
+ direction = "NO"
120
+ direction_confidence = 0.5 + (trend_strength * 0.4)
121
+ else:
122
+ # Neutral - slight lean based on momentum
123
+ direction = "YES" if recent_momentum > 0 else "NO"
124
+ direction_confidence = 0.5
125
+
126
+ return {
127
+ "success": True,
128
+ "forecast": {
129
+ "median": q50,
130
+ "lower_bound": q10,
131
+ "upper_bound": q90,
132
+ },
133
+ "analysis": {
134
+ "trend": trend,
135
+ "trend_strength": round(trend_strength, 3),
136
+ "price_change_predicted": round(price_change, 4),
137
+ "current_price": round(current_price, 4),
138
+ "forecast_end_price": round(forecast_end, 4),
139
+ "momentum": round(recent_momentum, 4),
140
+ "volatility": round(volatility, 4),
141
+ },
142
+ "ensemble_output": {
143
+ "direction": direction,
144
+ "confidence": round(direction_confidence, 3),
145
+ "model_confidence": round(confidence, 3),
146
+ },
147
+ "meta": {
148
+ "model": "chronos-bolt-base",
149
+ "input_length": len(prices),
150
+ "horizon": prediction_horizon,
151
+ }
152
+ }
153
+
154
+ except Exception as e:
155
+ return {
156
+ "success": False,
157
+ "error": str(e),
158
+ }
159
+
160
+
161
+ def forecast_api(historical_prices: str, prediction_horizon: int = 24) -> str:
162
+ """API endpoint wrapper that returns JSON string"""
163
+ result = forecast_odds(historical_prices, prediction_horizon)
164
+ return json.dumps(result, indent=2)
165
+
166
+
167
+ # Create Gradio interface
168
+ with gr.Blocks(title="Arvanu Chronos Forecaster") as demo:
169
+ gr.Markdown("""
170
+ # 🔮 Arvanu Chronos Forecaster
171
+
172
+ **Time-Series Prediction API for Market Odds**
173
+
174
+ Part of the Arvanu AI Prediction Ensemble. Uses Amazon's Chronos-Bolt
175
+ for probabilistic forecasting of market price trajectories.
176
+
177
+ ## API Usage
178
+
179
+ ```python
180
+ import requests
181
+
182
+ response = requests.post(
183
+ "https://mythman-arvanu-chronos.hf.space/api/predict",
184
+ json={
185
+ "data": [
186
+ "[0.52, 0.54, 0.55, 0.58, 0.56, 0.59, 0.61, 0.60, 0.62, 0.64]",
187
+ 24 # prediction horizon
188
+ ]
189
+ }
190
+ )
191
+ result = response.json()
192
+ ```
193
+ """)
194
+
195
+ with gr.Row():
196
+ with gr.Column():
197
+ prices_input = gr.Textbox(
198
+ label="Historical Prices (JSON array)",
199
+ placeholder='[0.52, 0.54, 0.55, 0.58, 0.56, 0.59, 0.61, 0.60, 0.62, 0.64]',
200
+ lines=3,
201
+ )
202
+ horizon_input = gr.Slider(
203
+ minimum=1,
204
+ maximum=48,
205
+ value=24,
206
+ step=1,
207
+ label="Prediction Horizon (time steps)",
208
+ )
209
+ submit_btn = gr.Button("Generate Forecast", variant="primary")
210
+
211
+ with gr.Column():
212
+ output = gr.JSON(label="Forecast Result")
213
+
214
+ submit_btn.click(
215
+ fn=forecast_odds,
216
+ inputs=[prices_input, horizon_input],
217
+ outputs=output,
218
+ )
219
+
220
+ gr.Examples(
221
+ examples=[
222
+ ['[0.52, 0.54, 0.55, 0.58, 0.56, 0.59, 0.61, 0.60, 0.62, 0.64, 0.63, 0.65]', 24],
223
+ ['[0.72, 0.71, 0.69, 0.68, 0.70, 0.67, 0.65, 0.64, 0.63, 0.62, 0.60, 0.58]', 12],
224
+ ['[0.50, 0.51, 0.50, 0.49, 0.50, 0.51, 0.50, 0.50, 0.49, 0.50, 0.51, 0.50]', 24],
225
+ ],
226
+ inputs=[prices_input, horizon_input],
227
+ )
228
+
229
+ # Launch with API enabled
230
+ demo.launch()