Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -1,78 +1,63 @@
|
|
| 1 |
-
|
| 2 |
-
from chronos import
|
| 3 |
import torch
|
| 4 |
import numpy as np
|
| 5 |
|
| 6 |
-
|
| 7 |
-
pipeline = ChronosBoltPipeline.from_pretrained("amazon/chronos-bolt-tiny")
|
| 8 |
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
# Chronos-Bolt expects [Batch, Sequence] shape
|
| 16 |
-
context = torch.tensor(prices).unsqueeze(0)
|
| 17 |
-
|
| 18 |
-
# 2. Run AI Prediction
|
| 19 |
-
# length 20 = roughly 2 business weeks
|
| 20 |
-
forecast = pipeline.predict(context, prediction_length=20)
|
| 21 |
-
|
| 22 |
-
# 3. Calculate Quantiles (Bolt-Tiny outputs raw samples)
|
| 23 |
-
# forecast[0] is the matrix of possible futures
|
| 24 |
-
p10 = np.quantile(forecast[0].numpy(), 0.1)
|
| 25 |
-
p50 = np.quantile(forecast[0].numpy(), 0.5)
|
| 26 |
-
p90 = np.quantile(forecast[0].numpy(), 0.9)
|
| 27 |
-
|
| 28 |
-
# 4. CERTAINTY (Confidence)
|
| 29 |
-
# Narrow gap = AI is certain. Wide gap = High Market Noise.
|
| 30 |
-
volatility = (p90 - p10) / p50
|
| 31 |
-
certainty = max(0, min(100, 100 * (1 - volatility)))
|
| 32 |
-
|
| 33 |
-
# 5. DYNAMIC TRADING LOGIC
|
| 34 |
-
# Floor (Stop Loss) is the P10
|
| 35 |
-
risk_amount = current_price - p10
|
| 36 |
-
|
| 37 |
-
if risk_amount <= 0:
|
| 38 |
-
return "Wait for Dip (Price < Floor)", "N/A", "0%", "0%", "Low Probability"
|
| 39 |
-
|
| 40 |
-
# TP = Current Price + (Risk * RR Ratio)
|
| 41 |
-
target_tp = current_price + (risk_amount * rr_ratio)
|
| 42 |
-
|
| 43 |
-
# Potential Gain/Loss Percentages
|
| 44 |
-
gain_pct = ((target_tp - current_price) / current_price) * 100
|
| 45 |
-
loss_pct = ((current_price - p10) / current_price) * 100
|
| 46 |
-
|
| 47 |
-
# Confidence Label
|
| 48 |
-
status = " HIGH" if certainty > 75 else " MED" if certainty > 50 else " LOW"
|
| 49 |
-
|
| 50 |
-
return (
|
| 51 |
-
f"${p10:.2f}",
|
| 52 |
-
f"${target_tp:.2f}",
|
| 53 |
-
f"+{gain_pct:.2f}%",
|
| 54 |
-
f"-{loss_pct:.2f}%",
|
| 55 |
-
f"{certainty:.1f}% ({status})"
|
| 56 |
-
)
|
| 57 |
-
|
| 58 |
-
except Exception as e:
|
| 59 |
-
return f"Error: {str(e)}", "", "", "", ""
|
| 60 |
-
|
| 61 |
-
# 6. INTERFACE SETUP
|
| 62 |
-
demo = gr.Interface(
|
| 63 |
-
fn=analyze_trade,
|
| 64 |
-
inputs=[
|
| 65 |
-
gr.Textbox(label="Stock History (Comma Separated)", placeholder="150, 152, 151, 155..."),
|
| 66 |
-
gr.Slider(minimum=1.0, maximum=5.0, value=2.0, label="Risk/Reward Ratio")
|
| 67 |
-
],
|
| 68 |
-
outputs=[
|
| 69 |
-
gr.Text(label="Suggested Stop Loss"),
|
| 70 |
-
gr.Text(label="Suggested Take Profit"),
|
| 71 |
-
gr.Text(label="Potential Gain if Win"),
|
| 72 |
-
gr.Text(label="Potential Loss if Stopped"),
|
| 73 |
-
gr.Text(label="AI Confidence Level")
|
| 74 |
-
],
|
| 75 |
-
title="Chronos-Bolt Live Analytics"
|
| 76 |
)
|
| 77 |
|
| 78 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from fastapi import FastAPI, Request
|
| 2 |
+
from chronos import ChronosPipeline
|
| 3 |
import torch
|
| 4 |
import numpy as np
|
| 5 |
|
| 6 |
+
app = FastAPI()
|
|
|
|
| 7 |
|
| 8 |
+
# Load the model once on startup
|
| 9 |
+
pipeline = ChronosPipeline.from_pretrained(
|
| 10 |
+
"amazon/chronos-t5-small", # or base/large depending on your Space hardware
|
| 11 |
+
device_map="auto",
|
| 12 |
+
torch_dtype=torch.bfloat16,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 13 |
)
|
| 14 |
|
| 15 |
+
@app.post("/predict")
|
| 16 |
+
async def predict(info: Request):
|
| 17 |
+
data = await info.json()
|
| 18 |
+
# Accept the full history array from your backend
|
| 19 |
+
history_array = data.get("history", [])
|
| 20 |
+
prediction_length = data.get("forecast_horizon", 12) # e.g., next 12 periods
|
| 21 |
+
|
| 22 |
+
# Convert to tensor
|
| 23 |
+
context = torch.tensor(history_array)
|
| 24 |
+
|
| 25 |
+
# Chronos Prediction (Probabilistic)
|
| 26 |
+
# returns shape: (num_samples, prediction_length)
|
| 27 |
+
forecast = pipeline.predict(context, prediction_length)
|
| 28 |
+
|
| 29 |
+
# Extract Quantiles (P10, P50, P90)
|
| 30 |
+
low_bound = np.percentile(forecast.numpy(), 10, axis=0)
|
| 31 |
+
median_pred = np.percentile(forecast.numpy(), 50, axis=0)
|
| 32 |
+
high_bound = np.percentile(forecast.numpy(), 90, axis=0)
|
| 33 |
+
|
| 34 |
+
# Trading Logic Calculations (Based on the first predicted step)
|
| 35 |
+
entry_price = history_array[-1]
|
| 36 |
+
predicted_next = median_pred[0]
|
| 37 |
+
p10_support = low_bound[0]
|
| 38 |
+
|
| 39 |
+
# Stop Loss (SL) set at the Lower Bound (P10)
|
| 40 |
+
sl = p10_support
|
| 41 |
+
risk = entry_price - sl
|
| 42 |
+
|
| 43 |
+
# Take Profit (TP) based on 2:1 RR Ratio
|
| 44 |
+
# Formula: Entry + (Risk * 2)
|
| 45 |
+
tp = entry_price + (risk * 2) if risk > 0 else entry_price * 1.05
|
| 46 |
+
|
| 47 |
+
# Verdict Logic
|
| 48 |
+
if predicted_next > entry_price and entry_price > p10_support:
|
| 49 |
+
verdict = "Strong Entry - Trend is Up"
|
| 50 |
+
elif predicted_next < entry_price:
|
| 51 |
+
verdict = "Wait - Potential Pullback Detected"
|
| 52 |
+
else:
|
| 53 |
+
verdict = "Neutral - High Volatility"
|
| 54 |
+
|
| 55 |
+
return {
|
| 56 |
+
"prediction": median_pred.tolist(),
|
| 57 |
+
"upper_bound": high_bound.tolist(),
|
| 58 |
+
"lower_bound": low_bound.tolist(),
|
| 59 |
+
"suggested_tp": round(tp, 2),
|
| 60 |
+
"suggested_sl": round(sl, 2),
|
| 61 |
+
"verdict": verdict,
|
| 62 |
+
"rr_ratio": "2:1"
|
| 63 |
+
}
|