Spaces:
Running
Running
| import os | |
| import torch | |
| import numpy as np | |
| from chronos import BaseChronosPipeline | |
| # Fix: Point HF cache to a writable path for the non-root HF Spaces user | |
| os.environ.setdefault("HF_HOME", "/home/user/.cache/huggingface") | |
| os.environ.setdefault("TRANSFORMERS_CACHE", "/home/user/.cache/huggingface") | |
| class SMCPredictionEngine: | |
| def __init__(self, model_name="amazon/chronos-bolt-base"): | |
| """ | |
| Initializes the Hugging Face Time-Series Transformer. | |
| Runs on CPU for compatibility with standard HF Spaces containers. | |
| """ | |
| print(f"Loading pre-trained AI weights: {model_name}...") | |
| self.pipeline = BaseChronosPipeline.from_pretrained( | |
| model_name, | |
| device_map="cpu", | |
| torch_dtype=torch.float32, | |
| ) | |
| print("Model loaded successfully.") | |
| def calculate_forecast(self, history_array: list | np.ndarray, prediction_length: int = 12) -> dict: | |
| """ | |
| Takes an array of historical prices and generates probabilistic forecasts. | |
| BaseChronosPipeline.predict() returns a tensor of shape: | |
| [batch_size, num_samples, prediction_length] | |
| We derive low / median / high by taking quantiles across the sample axis (axis=1). | |
| """ | |
| context_tensor = torch.tensor( | |
| np.array(history_array, dtype=np.float32).reshape(1, -1), # [1, seq_len] | |
| dtype=torch.float32, | |
| ) | |
| # forecast shape: [1, num_samples, prediction_length] | |
| forecast = self.pipeline.predict( | |
| context=context_tensor, | |
| prediction_length=prediction_length, | |
| ) | |
| # Convert to numpy: shape [num_samples, prediction_length] | |
| samples = forecast[0].numpy() # drop batch dimension | |
| # Derive quantile bands across the sample axis | |
| low_bounds = np.quantile(samples, 0.10, axis=0) # 10th percentile | |
| median_predictions = np.quantile(samples, 0.50, axis=0) # median | |
| high_bounds = np.quantile(samples, 0.90, axis=0) # 90th percentile | |
| # Projected momentum: % change from last known price to median forecast end | |
| last_price = float(history_array[-1]) | |
| projected_change = ((median_predictions[-1] - last_price) / last_price) * 100.0 | |
| return { | |
| "low": low_bounds, | |
| "median": median_predictions, | |
| "high": high_bounds, | |
| "projected_change_pct": float(projected_change), | |
| } |