Spaces:
Paused
Paused
Upload 20 files
Browse filesUpload backend files
- .gitattributes +6 -0
- Dockerfile +23 -0
- api.py +798 -0
- data/nifty_5m.csv +3 -0
- data/nifty_5m_indicators.csv +3 -0
- data/nifty_ml_features.csv +3 -0
- data/nifty_ml_features_chronos.csv +3 -0
- data/nifty_with_indicators.csv +249 -0
- data/training_dataset.csv +3 -0
- data/training_dataset_chronos.csv +0 -0
- data/training_dataset_v2.csv +3 -0
- models/chronos-2/README.md +180 -0
- models/chronos-2/config.json +58 -0
- models/chronos-2/gitattributes +35 -0
- models/chronos-2/model.safetensors +3 -0
- models/feature_importance_v2.csv +24 -0
- models/nifty_stage1_tradeable.json +0 -0
- models/nifty_stage2_direction.json +0 -0
- models/nifty_xgboost.json +0 -0
- models/nifty_xgboost_v2.json +0 -0
- requirements.txt +10 -0
.gitattributes
CHANGED
|
@@ -33,3 +33,9 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
| 36 |
+
data/nifty_5m_indicators.csv filter=lfs diff=lfs merge=lfs -text
|
| 37 |
+
data/nifty_5m.csv filter=lfs diff=lfs merge=lfs -text
|
| 38 |
+
data/nifty_ml_features_chronos.csv filter=lfs diff=lfs merge=lfs -text
|
| 39 |
+
data/nifty_ml_features.csv filter=lfs diff=lfs merge=lfs -text
|
| 40 |
+
data/training_dataset_v2.csv filter=lfs diff=lfs merge=lfs -text
|
| 41 |
+
data/training_dataset.csv filter=lfs diff=lfs merge=lfs -text
|
Dockerfile
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Use official Python lightweight image
|
| 2 |
+
FROM python:3.11-slim
|
| 3 |
+
|
| 4 |
+
# Set working directory
|
| 5 |
+
WORKDIR /app
|
| 6 |
+
|
| 7 |
+
# Install git (required to install packages from github if needed)
|
| 8 |
+
RUN apt-get update && apt-get install -y git && rm -rf /var/lib/apt/lists/*
|
| 9 |
+
|
| 10 |
+
# Copy requirements file and install dependencies
|
| 11 |
+
COPY requirements.txt .
|
| 12 |
+
RUN pip install --no-cache-dir -r requirements.txt
|
| 13 |
+
RUN pip install git+https://github.com/amazon-science/chronos-forecasting.git
|
| 14 |
+
|
| 15 |
+
# Copy the rest of the application
|
| 16 |
+
COPY . .
|
| 17 |
+
|
| 18 |
+
# Expose the port Uvicorn will run on (Hugging Face Spaces defaults to 7860, Render also uses PORT)
|
| 19 |
+
EXPOSE 7860
|
| 20 |
+
|
| 21 |
+
# Command to run the application
|
| 22 |
+
# We use the $PORT environment variable which Hugging Face sets to 7860, or default to 7860
|
| 23 |
+
CMD ["sh", "-c", "uvicorn api:app --host 0.0.0.0 --port ${PORT:-7860}"]
|
api.py
ADDED
|
@@ -0,0 +1,798 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
STEP 6 — FASTAPI BACKEND (v7 — three-model system, multi-instrument)
|
| 3 |
+
======================================================================
|
| 4 |
+
Complete rewrite of api.py to use the v7 model system.
|
| 5 |
+
|
| 6 |
+
Key changes from original api.py:
|
| 7 |
+
- Three models loaded: Stage1, Stage2, 3-class (was single XGBRegressor)
|
| 8 |
+
- All v7 asymmetric gates applied (strict BUY, loose SELL)
|
| 9 |
+
- New /signal endpoint returns full decision trail + gate results
|
| 10 |
+
- New /analyse endpoint accepts uploaded CSV for any instrument
|
| 11 |
+
- CSV upload runs full pipeline: indicators → Chronos → models → signal
|
| 12 |
+
- Auto-detects column names (handles any OHLCV CSV format)
|
| 13 |
+
- Backtest results returned alongside live signal
|
| 14 |
+
- CORS enabled for frontend integration
|
| 15 |
+
- Live data via Twelve Data API (free tier: 800 calls/day)
|
| 16 |
+
|
| 17 |
+
Usage:
|
| 18 |
+
pip install fastapi uvicorn python-multipart python-dotenv requests
|
| 19 |
+
uvicorn api:app --reload --port 8080
|
| 20 |
+
|
| 21 |
+
Endpoints:
|
| 22 |
+
GET / → status
|
| 23 |
+
GET /signal → live signal from data/nifty_5m.csv
|
| 24 |
+
POST /analyse → upload any OHLCV CSV, get signal + backtest
|
| 25 |
+
GET /instruments → list of supported instruments
|
| 26 |
+
GET /live-analyse/{symbol} → fetch live data + full analysis
|
| 27 |
+
GET /price/{symbol} → quick current price lookup
|
| 28 |
+
"""
|
| 29 |
+
|
| 30 |
+
import io
|
| 31 |
+
import os
|
| 32 |
+
import time
|
| 33 |
+
import traceback
|
| 34 |
+
import numpy as np
|
| 35 |
+
import pandas as pd
|
| 36 |
+
import torch
|
| 37 |
+
import requests as http_requests
|
| 38 |
+
import xgboost as xgb
|
| 39 |
+
from fastapi import FastAPI, File, UploadFile, Form, Query
|
| 40 |
+
from fastapi.middleware.cors import CORSMiddleware
|
| 41 |
+
from fastapi.staticfiles import StaticFiles
|
| 42 |
+
from ta.momentum import RSIIndicator
|
| 43 |
+
from ta.trend import ADXIndicator, MACD
|
| 44 |
+
from ta.volatility import AverageTrueRange
|
| 45 |
+
from chronos import Chronos2Pipeline
|
| 46 |
+
from dotenv import load_dotenv
|
| 47 |
+
|
| 48 |
+
load_dotenv()
|
| 49 |
+
|
| 50 |
+
# ─── APP ──────────────────────────────────────────────────────────────────────
|
| 51 |
+
app = FastAPI(title="MPC Quant AI Engine", version="7.0")
|
| 52 |
+
|
| 53 |
+
app.add_middleware(
|
| 54 |
+
CORSMiddleware,
|
| 55 |
+
allow_origins=["*"],
|
| 56 |
+
allow_methods=["*"],
|
| 57 |
+
allow_headers=["*"],
|
| 58 |
+
)
|
| 59 |
+
|
| 60 |
+
# Serve frontend
|
| 61 |
+
if os.path.exists("frontend"):
|
| 62 |
+
app.mount("/quant", StaticFiles(directory="frontend", html=True), name="quant")
|
| 63 |
+
|
| 64 |
+
# ─── CONFIG ───────────────────────────────────────────────────────────────────
|
| 65 |
+
DEFAULT_DATA_FILE = "data/nifty_5m.csv"
|
| 66 |
+
DEFAULT_DATE_FMT = "%d-%m-%Y %H:%M"
|
| 67 |
+
CONTEXT_LENGTH = 512
|
| 68 |
+
PREDICTION_LENGTH = 6
|
| 69 |
+
|
| 70 |
+
STAGE1_CONF = 0.70
|
| 71 |
+
STAGE2_CONF = 0.60
|
| 72 |
+
MODEL3_CONF = 0.45
|
| 73 |
+
ADX_MIN = 20
|
| 74 |
+
|
| 75 |
+
# BUY gates — strict
|
| 76 |
+
BUY_ADX_MIN = 28
|
| 77 |
+
BUY_EMA50_SIDE = True
|
| 78 |
+
BUY_EMA_CROSS = True
|
| 79 |
+
BUY_MACD_CROSS = True
|
| 80 |
+
BUY_CHRONOS = True
|
| 81 |
+
|
| 82 |
+
# SELL gates — loose
|
| 83 |
+
SELL_EMA200_MAX = -0.5
|
| 84 |
+
SELL_ADX_MIN = 20
|
| 85 |
+
SELL_EMA50_SIDE = True
|
| 86 |
+
|
| 87 |
+
LABEL_MAP = {0:"SELL", 1:"NO TRADE", 2:"BUY"}
|
| 88 |
+
STAGE1_COLS = [
|
| 89 |
+
"RSI","ATR","ADX","EMA20","EMA50","EMA200","EMA200_DISTANCE",
|
| 90 |
+
"MACD","MACD_SIGNAL",
|
| 91 |
+
"CHRONOS_RETURN","CHRONOS_SPREAD","CHRONOS_Q25","CHRONOS_Q75","CHRONOS_AGREE",
|
| 92 |
+
"EMA_CROSS","EMA200_SIDE","MACD_CROSS","RSI_ZONE","ADX_TREND","ATR_NORM",
|
| 93 |
+
"HOUR","IS_OPEN_NOISE","IS_CLOSE_NOISE",
|
| 94 |
+
]
|
| 95 |
+
REGIME_COLS = ["REGIME","REGIME_STRONG","EMA_ALIGN","TREND_BARS","EMA50_SIDE"]
|
| 96 |
+
STAGE2_COLS = STAGE1_COLS + REGIME_COLS
|
| 97 |
+
|
| 98 |
+
# ─── LOAD MODELS ON STARTUP ───────────────────────────────────────────────────
|
| 99 |
+
print("Loading Chronos-2...")
|
| 100 |
+
torch.set_num_threads(1) # Reduce memory overhead on small instances
|
| 101 |
+
chronos_pipeline = Chronos2Pipeline.from_pretrained(
|
| 102 |
+
"autogluon/chronos-2", device_map="cpu", dtype=torch.bfloat16)
|
| 103 |
+
print("Chronos-2 loaded.")
|
| 104 |
+
|
| 105 |
+
print("Loading XGBoost models...")
|
| 106 |
+
stage1 = xgb.XGBClassifier(); stage1.load_model("models/nifty_stage1_tradeable.json")
|
| 107 |
+
stage2 = xgb.XGBClassifier(); stage2.load_model("models/nifty_stage2_direction.json")
|
| 108 |
+
model3 = xgb.XGBClassifier(); model3.load_model("models/nifty_xgboost_v2.json")
|
| 109 |
+
print("All models loaded. System ready.")
|
| 110 |
+
|
| 111 |
+
|
| 112 |
+
# ══════════════════════════════════════════════════════════════════════════════
|
| 113 |
+
# SHARED UTILITIES
|
| 114 |
+
# ══════════════════════════════════════════════════════════════════════════════
|
| 115 |
+
|
| 116 |
+
def detect_columns(df):
|
| 117 |
+
"""Auto-detect OHLCV column names regardless of case/spacing."""
|
| 118 |
+
mapping = {}
|
| 119 |
+
cols_lower = {c.strip().lower(): c for c in df.columns}
|
| 120 |
+
for standard, candidates in {
|
| 121 |
+
"date": ["date","datetime","time","timestamp","Date","DateTime"],
|
| 122 |
+
"open": ["open","Open","OPEN","o"],
|
| 123 |
+
"high": ["high","High","HIGH","h"],
|
| 124 |
+
"low": ["low","Low","LOW","l"],
|
| 125 |
+
"close": ["close","Close","CLOSE","c","ltp","LTP"],
|
| 126 |
+
"volume": ["volume","Volume","VOLUME","vol","Vol"],
|
| 127 |
+
}.items():
|
| 128 |
+
for cand in candidates:
|
| 129 |
+
if cand.lower() in cols_lower:
|
| 130 |
+
mapping[standard] = cols_lower[cand.lower()]
|
| 131 |
+
break
|
| 132 |
+
return mapping
|
| 133 |
+
|
| 134 |
+
|
| 135 |
+
def clean_and_parse(df, col_map):
|
| 136 |
+
"""Rename columns to standard names and clean flat candles."""
|
| 137 |
+
df = df.rename(columns={v: k for k, v in col_map.items()})
|
| 138 |
+
for col in ["open","high","low","close"]:
|
| 139 |
+
if col in df.columns:
|
| 140 |
+
df[col] = pd.to_numeric(df[col].astype(str).str.replace(",",""), errors="coerce")
|
| 141 |
+
df = df.dropna(subset=["open","high","low","close"]).reset_index(drop=True)
|
| 142 |
+
flat = ((df["open"]==df["high"]) & (df["high"]==df["low"]) & (df["low"]==df["close"]))
|
| 143 |
+
df = df[~flat].copy().reset_index(drop=True)
|
| 144 |
+
# Parse date — try multiple formats
|
| 145 |
+
if "date" in df.columns:
|
| 146 |
+
for fmt in ["%d-%m-%Y %H:%M", "%Y-%m-%d %H:%M:%S", "%Y-%m-%d %H:%M",
|
| 147 |
+
"%d/%m/%Y %H:%M", "%m/%d/%Y %H:%M", None]:
|
| 148 |
+
try:
|
| 149 |
+
df["date"] = pd.to_datetime(df["date"], format=fmt)
|
| 150 |
+
break
|
| 151 |
+
except Exception:
|
| 152 |
+
continue
|
| 153 |
+
return df
|
| 154 |
+
|
| 155 |
+
|
| 156 |
+
def add_indicators(df):
|
| 157 |
+
df["RSI"] = RSIIndicator(close=df["close"], window=14).rsi()
|
| 158 |
+
df["ATR"] = AverageTrueRange(
|
| 159 |
+
high=df["high"], low=df["low"], close=df["close"], window=14
|
| 160 |
+
).average_true_range()
|
| 161 |
+
df["ADX"] = ADXIndicator(
|
| 162 |
+
high=df["high"], low=df["low"], close=df["close"], window=14
|
| 163 |
+
).adx()
|
| 164 |
+
df["EMA20"] = df["close"].ewm(span=20, adjust=False).mean()
|
| 165 |
+
df["EMA50"] = df["close"].ewm(span=50, adjust=False).mean()
|
| 166 |
+
df["EMA200"] = df["close"].ewm(span=200, adjust=False).mean()
|
| 167 |
+
m = MACD(close=df["close"])
|
| 168 |
+
df["MACD"] = m.macd()
|
| 169 |
+
df["MACD_SIGNAL"] = m.macd_signal()
|
| 170 |
+
df["EMA200_DISTANCE"] = (df["close"] - df["EMA200"]) / df["EMA200"] * 100
|
| 171 |
+
return df.dropna().reset_index(drop=True)
|
| 172 |
+
|
| 173 |
+
|
| 174 |
+
def run_chronos(close_series):
|
| 175 |
+
history = close_series.tail(CONTEXT_LENGTH).values.astype("float32")
|
| 176 |
+
cp = float(history[-1])
|
| 177 |
+
inputs = torch.tensor(history).reshape(1,1,-1)
|
| 178 |
+
fc = chronos_pipeline.predict(inputs=inputs, prediction_length=PREDICTION_LENGTH)
|
| 179 |
+
qt = fc[0]
|
| 180 |
+
q25,q50,q75 = qt[0,5,:].numpy(), qt[0,10,:].numpy(), qt[0,15,:].numpy()
|
| 181 |
+
r50 = (float(q50[-1])-cp)/cp*100
|
| 182 |
+
r25 = (float(q25[-1])-cp)/cp*100
|
| 183 |
+
r75 = (float(q75[-1])-cp)/cp*100
|
| 184 |
+
diffs = np.diff(q50)
|
| 185 |
+
agree = (float((diffs>0).sum()) if r50>0 else float((diffs<0).sum()))/len(diffs) if r50!=0 else 0.0
|
| 186 |
+
return {
|
| 187 |
+
"CHRONOS_RETURN":r50, "CHRONOS_SPREAD":r75-r25,
|
| 188 |
+
"CHRONOS_Q25":r25, "CHRONOS_Q75":r75,
|
| 189 |
+
"CHRONOS_AGREE":agree,
|
| 190 |
+
"predicted_price":float(q50[-1]),
|
| 191 |
+
"current_price":cp,
|
| 192 |
+
}
|
| 193 |
+
|
| 194 |
+
|
| 195 |
+
def get_regime(df, idx):
|
| 196 |
+
row = df.iloc[idx]
|
| 197 |
+
count = 0
|
| 198 |
+
for j in range(max(0,idx-50), idx+1):
|
| 199 |
+
r = df.iloc[j]
|
| 200 |
+
count = max(count+1,1) if r["close"]>r["EMA50"] else min(count-1,-1)
|
| 201 |
+
bs = int(row["EMA20"]>row["EMA50"] and row["EMA50"]>row["EMA200"])
|
| 202 |
+
bb = int(row["EMA20"]<row["EMA50"] and row["EMA50"]<row["EMA200"])
|
| 203 |
+
return {
|
| 204 |
+
"REGIME": float(np.sign(row["close"]-row["EMA200"])),
|
| 205 |
+
"REGIME_STRONG": int(abs(row["EMA200_DISTANCE"])>1.0),
|
| 206 |
+
"EMA_ALIGN": bs-bb,
|
| 207 |
+
"TREND_BARS": int(np.clip(count,-50,50)),
|
| 208 |
+
"EMA50_SIDE": float(np.sign(row["close"]-row["EMA50"])),
|
| 209 |
+
}
|
| 210 |
+
|
| 211 |
+
|
| 212 |
+
def build_features(df, idx, cf):
|
| 213 |
+
row = df.iloc[idx]
|
| 214 |
+
h = row["date"].hour if "date" in df.columns else 12
|
| 215 |
+
m = row["date"].minute if "date" in df.columns else 0
|
| 216 |
+
reg = get_regime(df, idx)
|
| 217 |
+
feat = {
|
| 218 |
+
"RSI":float(row["RSI"]), "ATR":float(row["ATR"]), "ADX":float(row["ADX"]),
|
| 219 |
+
"EMA20":float(row["EMA20"]), "EMA50":float(row["EMA50"]), "EMA200":float(row["EMA200"]),
|
| 220 |
+
"EMA200_DISTANCE":float(row["EMA200_DISTANCE"]),
|
| 221 |
+
"MACD":float(row["MACD"]), "MACD_SIGNAL":float(row["MACD_SIGNAL"]),
|
| 222 |
+
"CHRONOS_RETURN":cf["CHRONOS_RETURN"], "CHRONOS_SPREAD":cf["CHRONOS_SPREAD"],
|
| 223 |
+
"CHRONOS_Q25":cf["CHRONOS_Q25"], "CHRONOS_Q75":cf["CHRONOS_Q75"],
|
| 224 |
+
"CHRONOS_AGREE":cf["CHRONOS_AGREE"],
|
| 225 |
+
"EMA_CROSS": float(np.sign(row["EMA20"]-row["EMA50"])),
|
| 226 |
+
"EMA200_SIDE": float(np.sign(row["close"]-row["EMA200"])),
|
| 227 |
+
"MACD_CROSS": float(np.sign(row["MACD"]-row["MACD_SIGNAL"])),
|
| 228 |
+
"RSI_ZONE": 0 if row["RSI"]<30 else (2 if row["RSI"]>70 else 1),
|
| 229 |
+
"ADX_TREND": int(row["ADX"]>20),
|
| 230 |
+
"ATR_NORM": float(row["ATR"]/row["close"])*100,
|
| 231 |
+
"HOUR":h, "IS_OPEN_NOISE":int(h==9 and m<=30), "IS_CLOSE_NOISE":int(h==15),
|
| 232 |
+
}
|
| 233 |
+
feat.update(reg)
|
| 234 |
+
return feat, reg
|
| 235 |
+
|
| 236 |
+
|
| 237 |
+
def predict_and_gate(feat, ema200_dist, chronos_ret):
|
| 238 |
+
"""Full three-model prediction + v7 asymmetric gates."""
|
| 239 |
+
X1 = pd.DataFrame([{c:feat[c] for c in STAGE1_COLS}])
|
| 240 |
+
s1_p = float(stage1.predict_proba(X1)[0][1])
|
| 241 |
+
m3p = model3.predict_proba(X1)[0]
|
| 242 |
+
m3sig = LABEL_MAP[int(np.argmax(m3p))]
|
| 243 |
+
|
| 244 |
+
if s1_p < STAGE1_CONF:
|
| 245 |
+
return "NO TRADE", s1_p, None, m3sig, m3p, "Stage 1 below threshold"
|
| 246 |
+
|
| 247 |
+
X2 = pd.DataFrame([{c:feat[c] for c in STAGE2_COLS}])
|
| 248 |
+
s2_p = float(stage2.predict_proba(X2)[0][1])
|
| 249 |
+
|
| 250 |
+
if s2_p >= STAGE2_CONF: raw,dc = "BUY", s2_p
|
| 251 |
+
elif s2_p <= (1-STAGE2_CONF): raw,dc = "SELL", 1-s2_p
|
| 252 |
+
else: return "NO TRADE", s1_p, None, m3sig, m3p, "Stage 2 uncertain"
|
| 253 |
+
|
| 254 |
+
# 3-class confirmation
|
| 255 |
+
if m3sig != raw and float(m3p.max()) >= MODEL3_CONF:
|
| 256 |
+
return "NO TRADE", s1_p, dc, m3sig, m3p, f"3-class disagreement ({m3sig} vs {raw})"
|
| 257 |
+
|
| 258 |
+
ema50_side = feat.get("EMA50_SIDE", 0)
|
| 259 |
+
ema_cross = feat.get("EMA_CROSS", 0)
|
| 260 |
+
macd_cross = feat.get("MACD_CROSS", 0)
|
| 261 |
+
adx = feat.get("ADX", 0)
|
| 262 |
+
|
| 263 |
+
if raw == "BUY":
|
| 264 |
+
if BUY_EMA50_SIDE and ema50_side <= 0: return "NO TRADE",s1_p,dc,m3sig,m3p,"BUY GATE: price below EMA50"
|
| 265 |
+
if adx < BUY_ADX_MIN: return "NO TRADE",s1_p,dc,m3sig,m3p,f"BUY GATE: ADX={adx:.1f}<{BUY_ADX_MIN}"
|
| 266 |
+
if BUY_EMA_CROSS and ema_cross <= 0: return "NO TRADE",s1_p,dc,m3sig,m3p,"BUY GATE: EMA20 not > EMA50"
|
| 267 |
+
if BUY_MACD_CROSS and macd_cross <= 0: return "NO TRADE",s1_p,dc,m3sig,m3p,"BUY GATE: MACD not > Signal"
|
| 268 |
+
if BUY_CHRONOS and chronos_ret <= 0: return "NO TRADE",s1_p,dc,m3sig,m3p,f"BUY GATE: Chronos={chronos_ret:+.4f}%"
|
| 269 |
+
|
| 270 |
+
if raw == "SELL":
|
| 271 |
+
if SELL_EMA50_SIDE and ema50_side >= 0: return "NO TRADE",s1_p,dc,m3sig,m3p,"SELL GATE: price above EMA50"
|
| 272 |
+
if ema200_dist > SELL_EMA200_MAX: return "NO TRADE",s1_p,dc,m3sig,m3p,f"SELL GATE: EMA200 dist={ema200_dist:+.2f}%"
|
| 273 |
+
if adx < SELL_ADX_MIN: return "NO TRADE",s1_p,dc,m3sig,m3p,f"SELL GATE: ADX={adx:.1f}<{SELL_ADX_MIN}"
|
| 274 |
+
|
| 275 |
+
return raw, s1_p, dc, m3sig, m3p, "PASSED ALL GATES"
|
| 276 |
+
|
| 277 |
+
|
| 278 |
+
def build_signal_response(df, cf, instrument_name="unknown"):
|
| 279 |
+
"""Run full pipeline on prepared df and return signal dict."""
|
| 280 |
+
latest_idx = len(df) - 1
|
| 281 |
+
latest = df.iloc[latest_idx]
|
| 282 |
+
feat, regime = build_features(df, latest_idx, cf)
|
| 283 |
+
ema200_dist = float(latest["EMA200_DISTANCE"])
|
| 284 |
+
chronos_ret = cf["CHRONOS_RETURN"]
|
| 285 |
+
|
| 286 |
+
signal, s1_p, dir_conf, m3sig, m3p, gate_note = predict_and_gate(
|
| 287 |
+
feat, ema200_dist, chronos_ret)
|
| 288 |
+
|
| 289 |
+
# Time filter
|
| 290 |
+
if "date" in df.columns:
|
| 291 |
+
h = latest["date"].hour
|
| 292 |
+
m_min = latest["date"].minute
|
| 293 |
+
if h==9 and m_min<=30: signal="NO TRADE"; gate_note="TIME: open noise"
|
| 294 |
+
if h==15: signal="NO TRADE"; gate_note="TIME: close noise"
|
| 295 |
+
|
| 296 |
+
# Trend description
|
| 297 |
+
if regime["EMA_ALIGN"]>0: trend = "FULL BULL"
|
| 298 |
+
elif regime["EMA_ALIGN"]<0: trend = "FULL BEAR"
|
| 299 |
+
elif regime["EMA50_SIDE"]>0: trend = "MIXED — above EMA50"
|
| 300 |
+
else: trend = "MIXED — below EMA50"
|
| 301 |
+
|
| 302 |
+
return {
|
| 303 |
+
"signal": signal,
|
| 304 |
+
"instrument": instrument_name,
|
| 305 |
+
"stage1_tradeable": s1_p >= STAGE1_CONF,
|
| 306 |
+
"stage1_conf": round(s1_p*100, 1),
|
| 307 |
+
"stage2_direction": LABEL_MAP.get(2 if (dir_conf or 0)>0.5 else 0, "NO TRADE") if dir_conf else "N/A",
|
| 308 |
+
"stage2_conf": round((dir_conf or 0)*100, 1),
|
| 309 |
+
"model3_signal": m3sig,
|
| 310 |
+
"model3_conf": round(float(m3p.max())*100, 1),
|
| 311 |
+
"prob_sell": round(float(m3p[0])*100, 1),
|
| 312 |
+
"prob_no_trade": round(float(m3p[1])*100, 1),
|
| 313 |
+
"prob_buy": round(float(m3p[2])*100, 1),
|
| 314 |
+
"gate_result": gate_note,
|
| 315 |
+
"regime": trend,
|
| 316 |
+
"trend_bars": regime["TREND_BARS"],
|
| 317 |
+
"ema50_side": "ABOVE" if regime["EMA50_SIDE"]>0 else "BELOW",
|
| 318 |
+
"ema200_side": "ABOVE" if regime["REGIME"]>0 else "BELOW",
|
| 319 |
+
"current_price": round(cf["current_price"], 2),
|
| 320 |
+
"predicted_price": round(cf["predicted_price"], 2),
|
| 321 |
+
"chronos_return": round(chronos_ret, 4),
|
| 322 |
+
"chronos_spread": round(cf["CHRONOS_SPREAD"], 4),
|
| 323 |
+
"chronos_agree": round(cf["CHRONOS_AGREE"], 2),
|
| 324 |
+
"adx": round(float(latest["ADX"]), 2),
|
| 325 |
+
"rsi": round(float(latest["RSI"]), 2),
|
| 326 |
+
"ema200_distance": round(ema200_dist, 4),
|
| 327 |
+
"data_rows": len(df),
|
| 328 |
+
"timestamp": str(latest.get("date", "N/A")),
|
| 329 |
+
}
|
| 330 |
+
|
| 331 |
+
|
| 332 |
+
def quick_backtest(df, instrument_name):
|
| 333 |
+
"""
|
| 334 |
+
Run a quick backtest on the uploaded data.
|
| 335 |
+
Uses simplified signal generation (no Chronos per-bar — too slow).
|
| 336 |
+
Uses rule-based signals from indicators for backtest only.
|
| 337 |
+
Returns summary stats.
|
| 338 |
+
"""
|
| 339 |
+
ATR_TRAIL = 4.5
|
| 340 |
+
ATR_TGT = 4.0
|
| 341 |
+
MAX_BARS = 12
|
| 342 |
+
SLIP = 0.5
|
| 343 |
+
|
| 344 |
+
# Simple rule-based signals for backtest (no per-bar Chronos)
|
| 345 |
+
df2 = df.copy().reset_index(drop=True)
|
| 346 |
+
df2["EMA_CROSS"] = np.sign(df2["EMA20"] - df2["EMA50"])
|
| 347 |
+
df2["MACD_CROSS"] = np.sign(df2["MACD"] - df2["MACD_SIGNAL"])
|
| 348 |
+
df2["EMA50_SIDE"] = np.sign(df2["close"] - df2["EMA50"])
|
| 349 |
+
df2["EMA200_SIDE"]= np.sign(df2["close"] - df2["EMA200"])
|
| 350 |
+
|
| 351 |
+
signals = []
|
| 352 |
+
for i in range(len(df2)):
|
| 353 |
+
row = df2.iloc[i]
|
| 354 |
+
adx = float(row.get("ADX", 0))
|
| 355 |
+
ema50 = float(row.get("EMA50_SIDE", 0))
|
| 356 |
+
ema_x = float(row.get("EMA_CROSS", 0))
|
| 357 |
+
macd_x= float(row.get("MACD_CROSS", 0))
|
| 358 |
+
e200 = float(row.get("EMA200_DISTANCE", 0))
|
| 359 |
+
|
| 360 |
+
if "date" in df2.columns:
|
| 361 |
+
h = row["date"].hour
|
| 362 |
+
mn= row["date"].minute
|
| 363 |
+
if (h==9 and mn<=30) or h==15:
|
| 364 |
+
signals.append("NO TRADE"); continue
|
| 365 |
+
|
| 366 |
+
# BUY: strict
|
| 367 |
+
if (ema50>0 and adx>=BUY_ADX_MIN and ema_x>0 and macd_x>0):
|
| 368 |
+
signals.append("BUY")
|
| 369 |
+
# SELL: loose
|
| 370 |
+
elif (ema50<0 and e200<SELL_EMA200_MAX and adx>=SELL_ADX_MIN):
|
| 371 |
+
signals.append("SELL")
|
| 372 |
+
else:
|
| 373 |
+
signals.append("NO TRADE")
|
| 374 |
+
|
| 375 |
+
df2["SIGNAL"] = signals
|
| 376 |
+
trades = []
|
| 377 |
+
equity = [100.0]
|
| 378 |
+
in_trade= False
|
| 379 |
+
entry_bar=entry_price=trade_dir=None
|
| 380 |
+
trail_stop=target_price=peak_high=trough_low=None
|
| 381 |
+
|
| 382 |
+
for i in range(len(df2)-1):
|
| 383 |
+
row = df2.iloc[i]
|
| 384 |
+
next_row = df2.iloc[i+1]
|
| 385 |
+
|
| 386 |
+
if in_trade:
|
| 387 |
+
bars_held = i - entry_bar
|
| 388 |
+
close = float(next_row["close"])
|
| 389 |
+
high = float(next_row.get("high", close))
|
| 390 |
+
low = float(next_row.get("low", close))
|
| 391 |
+
atr = float(row.get("ATR", 1)) or 1.0
|
| 392 |
+
ep=er=None
|
| 393 |
+
|
| 394 |
+
if trade_dir=="BUY":
|
| 395 |
+
peak_high = max(peak_high, high)
|
| 396 |
+
trail_stop = peak_high - ATR_TRAIL * atr
|
| 397 |
+
if low <= trail_stop: ep=max(trail_stop-SLIP,low); er="CHANDELIER"
|
| 398 |
+
elif high >= target_price: ep=target_price-SLIP; er="TARGET"
|
| 399 |
+
elif bars_held>=MAX_BARS: ep=close-SLIP; er="TIME"
|
| 400 |
+
else:
|
| 401 |
+
trough_low = min(trough_low, low)
|
| 402 |
+
trail_stop = trough_low + ATR_TRAIL * atr
|
| 403 |
+
if high >= trail_stop: ep=min(trail_stop+SLIP,high); er="CHANDELIER"
|
| 404 |
+
elif low <= target_price: ep=target_price+SLIP; er="TARGET"
|
| 405 |
+
elif bars_held>=MAX_BARS: ep=close+SLIP; er="TIME"
|
| 406 |
+
|
| 407 |
+
if ep is not None:
|
| 408 |
+
pnl = ((ep-entry_price)/entry_price*100 if trade_dir=="BUY"
|
| 409 |
+
else (entry_price-ep)/entry_price*100)
|
| 410 |
+
equity.append(equity[-1]*(1+pnl/100))
|
| 411 |
+
trades.append({"direction":trade_dir,"pnl_pct":round(pnl,4),
|
| 412 |
+
"exit_reason":er,"win":pnl>0,"bars_held":bars_held})
|
| 413 |
+
in_trade=False; entry_bar=entry_price=trade_dir=None
|
| 414 |
+
trail_stop=target_price=peak_high=trough_low=None
|
| 415 |
+
else:
|
| 416 |
+
equity.append(equity[-1])
|
| 417 |
+
|
| 418 |
+
if not in_trade:
|
| 419 |
+
sig = row["SIGNAL"]
|
| 420 |
+
if sig in ("BUY","SELL"):
|
| 421 |
+
atr = float(row.get("ATR",0))
|
| 422 |
+
if atr<=0: equity.append(equity[-1]); continue
|
| 423 |
+
ep = float(next_row.get("open", next_row["close"]))
|
| 424 |
+
ep += SLIP if sig=="BUY" else -SLIP
|
| 425 |
+
if sig=="BUY":
|
| 426 |
+
peak_high=ep; trail_stop=ep-ATR_TRAIL*atr; target_price=ep+ATR_TGT*atr; trough_low=None
|
| 427 |
+
else:
|
| 428 |
+
trough_low=ep; trail_stop=ep+ATR_TRAIL*atr; target_price=ep-ATR_TGT*atr; peak_high=None
|
| 429 |
+
entry_bar=i; entry_price=ep; trade_dir=sig; in_trade=True
|
| 430 |
+
equity.append(equity[-1])
|
| 431 |
+
else:
|
| 432 |
+
equity.append(equity[-1])
|
| 433 |
+
|
| 434 |
+
if not trades:
|
| 435 |
+
return {"total_trades":0,"message":"No trades generated — check data length and format"}
|
| 436 |
+
|
| 437 |
+
tr = pd.DataFrame(trades)
|
| 438 |
+
wins = tr[tr["win"]==True]; losses = tr[tr["win"]==False]
|
| 439 |
+
pf = (wins["pnl_pct"].sum()/abs(losses["pnl_pct"].sum())
|
| 440 |
+
if abs(losses["pnl_pct"].sum())>0 else 0)
|
| 441 |
+
eq = np.array(equity)
|
| 442 |
+
peak = np.maximum.accumulate(eq)
|
| 443 |
+
dd = float(((eq-peak)/peak).min())*100
|
| 444 |
+
wr = float(tr["win"].mean())*100
|
| 445 |
+
avg_w= float(wins["pnl_pct"].mean()) if len(wins)>0 else 0
|
| 446 |
+
avg_l= float(losses["pnl_pct"].mean()) if len(losses)>0 else 0
|
| 447 |
+
rr = abs(avg_w/avg_l) if avg_l!=0 else 0
|
| 448 |
+
ret = float(eq[-1]-100)
|
| 449 |
+
|
| 450 |
+
by_exit = {}
|
| 451 |
+
for reason in tr["exit_reason"].unique():
|
| 452 |
+
rr_df = tr[tr["exit_reason"]==reason]
|
| 453 |
+
by_exit[reason] = {
|
| 454 |
+
"count": int(len(rr_df)),
|
| 455 |
+
"win_rate": round(rr_df["win"].mean()*100, 1),
|
| 456 |
+
"avg_pnl": round(rr_df["pnl_pct"].mean(), 4),
|
| 457 |
+
}
|
| 458 |
+
|
| 459 |
+
return {
|
| 460 |
+
"total_trades": int(len(tr)),
|
| 461 |
+
"buy_trades": int((tr["direction"]=="BUY").sum()),
|
| 462 |
+
"sell_trades": int((tr["direction"]=="SELL").sum()),
|
| 463 |
+
"win_rate": round(wr, 1),
|
| 464 |
+
"avg_win": round(avg_w, 4),
|
| 465 |
+
"avg_loss": round(avg_l, 4),
|
| 466 |
+
"reward_risk": round(rr, 2),
|
| 467 |
+
"profit_factor": round(pf, 2),
|
| 468 |
+
"total_return": round(ret, 2),
|
| 469 |
+
"max_drawdown": round(dd, 2),
|
| 470 |
+
"exit_breakdown": by_exit,
|
| 471 |
+
"equity_curve": [round(e,4) for e in equity[::10]], # every 10th point
|
| 472 |
+
}
|
| 473 |
+
|
| 474 |
+
|
| 475 |
+
# ══════════════════════════════════════════════════════════════════════════════
|
| 476 |
+
# ENDPOINTS
|
| 477 |
+
# ══════════════════════════════════════════════════════════════════════════════
|
| 478 |
+
|
| 479 |
+
@app.get("/")
|
| 480 |
+
def home():
|
| 481 |
+
return {
|
| 482 |
+
"status": "running",
|
| 483 |
+
"system": "MPC Quant AI Engine v7",
|
| 484 |
+
"models": ["Stage1","Stage2","3-Class"],
|
| 485 |
+
"endpoints": ["/signal", "/analyse", "/instruments", "/live-analyse/{symbol}", "/price/{symbol}", "/quant"],
|
| 486 |
+
"live_data": "Twelve Data API",
|
| 487 |
+
"api_key_set": bool(os.getenv("TWELVEDATA_API_KEY", "").strip() and os.getenv("TWELVEDATA_API_KEY") != "your_api_key_here"),
|
| 488 |
+
}
|
| 489 |
+
|
| 490 |
+
|
| 491 |
+
@app.get("/signal")
|
| 492 |
+
def get_signal():
|
| 493 |
+
"""Live signal from the default NIFTY data file."""
|
| 494 |
+
try:
|
| 495 |
+
df = pd.read_csv(DEFAULT_DATA_FILE)
|
| 496 |
+
col_map = detect_columns(df)
|
| 497 |
+
df = clean_and_parse(df, col_map)
|
| 498 |
+
df = add_indicators(df)
|
| 499 |
+
cf = run_chronos(df["close"])
|
| 500 |
+
return build_signal_response(df, cf, instrument_name="NIFTY 50")
|
| 501 |
+
except Exception as e:
|
| 502 |
+
return {"error": str(e), "signal": "ERROR"}
|
| 503 |
+
|
| 504 |
+
|
| 505 |
+
@app.post("/analyse")
|
| 506 |
+
async def analyse_csv(
|
| 507 |
+
file: UploadFile = File(...),
|
| 508 |
+
instrument_name: str = Form(default=""),
|
| 509 |
+
):
|
| 510 |
+
"""
|
| 511 |
+
Upload any OHLCV CSV and receive:
|
| 512 |
+
1. Live signal (from latest bar)
|
| 513 |
+
2. Quick backtest summary
|
| 514 |
+
3. Full indicator values
|
| 515 |
+
|
| 516 |
+
Accepts any column naming convention.
|
| 517 |
+
Auto-detects date format.
|
| 518 |
+
Works for NIFTY, Stocks, Gold, Crypto, Forex — any instrument.
|
| 519 |
+
"""
|
| 520 |
+
try:
|
| 521 |
+
# Read uploaded file
|
| 522 |
+
contents = await file.read()
|
| 523 |
+
df_raw = pd.read_csv(io.StringIO(contents.decode("utf-8", errors="replace")))
|
| 524 |
+
|
| 525 |
+
if len(df_raw) < 250:
|
| 526 |
+
return {"error": f"Need at least 250 bars for indicators. Got {len(df_raw)}."}
|
| 527 |
+
|
| 528 |
+
# Detect and standardise columns
|
| 529 |
+
col_map = detect_columns(df_raw)
|
| 530 |
+
required = ["open","high","low","close"]
|
| 531 |
+
missing = [r for r in required if r not in col_map]
|
| 532 |
+
if missing:
|
| 533 |
+
return {
|
| 534 |
+
"error": f"Could not find columns: {missing}. "
|
| 535 |
+
f"Found: {list(df_raw.columns)}. "
|
| 536 |
+
f"CSV must have open, high, low, close columns."
|
| 537 |
+
}
|
| 538 |
+
|
| 539 |
+
df = clean_and_parse(df_raw, col_map)
|
| 540 |
+
df = df.sort_values("date").reset_index(drop=True) if "date" in df.columns else df
|
| 541 |
+
|
| 542 |
+
if len(df) < 250:
|
| 543 |
+
return {"error": f"After cleaning, only {len(df)} valid rows. Need 250+."}
|
| 544 |
+
|
| 545 |
+
# Auto-detect instrument name from filename if not provided
|
| 546 |
+
name = instrument_name.strip() or file.filename.replace(".csv","").replace("_"," ")
|
| 547 |
+
|
| 548 |
+
# Run indicators
|
| 549 |
+
df = add_indicators(df)
|
| 550 |
+
|
| 551 |
+
# Run Chronos on latest bars
|
| 552 |
+
cf = run_chronos(df["close"])
|
| 553 |
+
|
| 554 |
+
# Get live signal
|
| 555 |
+
signal_data = build_signal_response(df, cf, instrument_name=name)
|
| 556 |
+
|
| 557 |
+
# Run quick backtest
|
| 558 |
+
backtest_data = quick_backtest(df, name)
|
| 559 |
+
|
| 560 |
+
# Data summary
|
| 561 |
+
data_summary = {
|
| 562 |
+
"instrument": name,
|
| 563 |
+
"filename": file.filename,
|
| 564 |
+
"total_rows": len(df),
|
| 565 |
+
"date_start": str(df["date"].iloc[0]) if "date" in df.columns else "N/A",
|
| 566 |
+
"date_end": str(df["date"].iloc[-1]) if "date" in df.columns else "N/A",
|
| 567 |
+
"price_range": {
|
| 568 |
+
"low": round(float(df["close"].min()), 4),
|
| 569 |
+
"high": round(float(df["close"].max()), 4),
|
| 570 |
+
"current": round(float(df["close"].iloc[-1]), 4),
|
| 571 |
+
},
|
| 572 |
+
"avg_atr_pct": round(float((df["ATR"]/df["close"]*100).median()), 4),
|
| 573 |
+
"columns_detected": col_map,
|
| 574 |
+
}
|
| 575 |
+
|
| 576 |
+
return {
|
| 577 |
+
"status": "success",
|
| 578 |
+
"data_summary": data_summary,
|
| 579 |
+
"signal": signal_data,
|
| 580 |
+
"backtest": backtest_data,
|
| 581 |
+
}
|
| 582 |
+
|
| 583 |
+
except Exception as e:
|
| 584 |
+
return {"error": str(e), "detail": traceback.format_exc()}
|
| 585 |
+
|
| 586 |
+
|
| 587 |
+
# ══════════════════════════════════════════════════════════════════════════════
|
| 588 |
+
# TWELVE DATA — LIVE DATA INTEGRATION
|
| 589 |
+
# ══════════════════════════════════════════════════════════════════════════════
|
| 590 |
+
|
| 591 |
+
TWELVEDATA_BASE = "https://api.twelvedata.com"
|
| 592 |
+
|
| 593 |
+
INSTRUMENT_CATALOG = [
|
| 594 |
+
# ── Indian Indices ──
|
| 595 |
+
{"symbol": "NIFTY 50", "exchange": "NSE", "name": "NIFTY 50", "category": "Indices", "currency": "INR", "flag": "🇮🇳"},
|
| 596 |
+
{"symbol": "SENSEX", "exchange": "BSE", "name": "SENSEX", "category": "Indices", "currency": "INR", "flag": "🇮🇳"},
|
| 597 |
+
# ── Indian Stocks ──
|
| 598 |
+
{"symbol": "RELIANCE", "exchange": "NSE", "name": "Reliance Industries","category": "Indian Stocks","currency": "INR", "flag": "🇮🇳"},
|
| 599 |
+
{"symbol": "TCS", "exchange": "NSE", "name": "TCS", "category": "Indian Stocks","currency": "INR", "flag": "🇮🇳"},
|
| 600 |
+
{"symbol": "HDFCBANK", "exchange": "NSE", "name": "HDFC Bank", "category": "Indian Stocks","currency": "INR", "flag": "🇮🇳"},
|
| 601 |
+
{"symbol": "INFY", "exchange": "NSE", "name": "Infosys", "category": "Indian Stocks","currency": "INR", "flag": "🇮🇳"},
|
| 602 |
+
{"symbol": "ICICIBANK", "exchange": "NSE", "name": "ICICI Bank", "category": "Indian Stocks","currency": "INR", "flag": "🇮🇳"},
|
| 603 |
+
{"symbol": "SBIN", "exchange": "NSE", "name": "SBI", "category": "Indian Stocks","currency": "INR", "flag": "🇮🇳"},
|
| 604 |
+
# ── US Stocks ──
|
| 605 |
+
{"symbol": "AAPL", "exchange": "", "name": "Apple", "category": "US Stocks", "currency": "USD", "flag": "🇺🇸"},
|
| 606 |
+
{"symbol": "TSLA", "exchange": "", "name": "Tesla", "category": "US Stocks", "currency": "USD", "flag": "🇺🇸"},
|
| 607 |
+
{"symbol": "MSFT", "exchange": "", "name": "Microsoft", "category": "US Stocks", "currency": "USD", "flag": "🇺🇸"},
|
| 608 |
+
{"symbol": "GOOGL", "exchange": "", "name": "Alphabet (Google)", "category": "US Stocks", "currency": "USD", "flag": "🇺🇸"},
|
| 609 |
+
{"symbol": "AMZN", "exchange": "", "name": "Amazon", "category": "US Stocks", "currency": "USD", "flag": "🇺🇸"},
|
| 610 |
+
{"symbol": "NVDA", "exchange": "", "name": "NVIDIA", "category": "US Stocks", "currency": "USD", "flag": "🇺🇸"},
|
| 611 |
+
{"symbol": "META", "exchange": "", "name": "Meta (Facebook)", "category": "US Stocks", "currency": "USD", "flag": "🇺🇸"},
|
| 612 |
+
# ── Crypto ──
|
| 613 |
+
{"symbol": "BTC/USD", "exchange": "", "name": "Bitcoin", "category": "Crypto", "currency": "USD", "flag": "₿"},
|
| 614 |
+
{"symbol": "ETH/USD", "exchange": "", "name": "Ethereum", "category": "Crypto", "currency": "USD", "flag": "Ξ"},
|
| 615 |
+
{"symbol": "SOL/USD", "exchange": "", "name": "Solana", "category": "Crypto", "currency": "USD", "flag": "◎"},
|
| 616 |
+
{"symbol": "XRP/USD", "exchange": "", "name": "XRP", "category": "Crypto", "currency": "USD", "flag": "✕"},
|
| 617 |
+
# ── Forex ──
|
| 618 |
+
{"symbol": "EUR/USD", "exchange": "", "name": "Euro / Dollar", "category": "Forex", "currency": "USD", "flag": "🇪🇺"},
|
| 619 |
+
{"symbol": "GBP/USD", "exchange": "", "name": "Pound / Dollar", "category": "Forex", "currency": "USD", "flag": "🇬🇧"},
|
| 620 |
+
{"symbol": "USD/JPY", "exchange": "", "name": "Dollar / Yen", "category": "Forex", "currency": "JPY", "flag": "🇯🇵"},
|
| 621 |
+
{"symbol": "USD/INR", "exchange": "", "name": "Dollar / Rupee", "category": "Forex", "currency": "INR", "flag": "🇮🇳"},
|
| 622 |
+
# ── Commodities ──
|
| 623 |
+
{"symbol": "XAU/USD", "exchange": "", "name": "Gold", "category": "Commodities", "currency": "USD", "flag": "🥇"},
|
| 624 |
+
{"symbol": "XAG/USD", "exchange": "", "name": "Silver", "category": "Commodities", "currency": "USD", "flag": "🥈"},
|
| 625 |
+
]
|
| 626 |
+
|
| 627 |
+
|
| 628 |
+
def _get_api_key():
|
| 629 |
+
key = os.getenv("TWELVEDATA_API_KEY", "").strip()
|
| 630 |
+
if not key or key == "your_api_key_here":
|
| 631 |
+
return None
|
| 632 |
+
return key
|
| 633 |
+
|
| 634 |
+
|
| 635 |
+
def fetch_live_data(symbol: str, exchange: str = "", interval: str = "5min",
|
| 636 |
+
outputsize: int = 5000) -> pd.DataFrame:
|
| 637 |
+
"""
|
| 638 |
+
Fetch OHLCV time-series from Twelve Data.
|
| 639 |
+
Returns a pandas DataFrame with columns: date, open, high, low, close, volume.
|
| 640 |
+
Raises ValueError on API errors.
|
| 641 |
+
"""
|
| 642 |
+
api_key = _get_api_key()
|
| 643 |
+
if not api_key:
|
| 644 |
+
raise ValueError(
|
| 645 |
+
"TWELVEDATA_API_KEY not set. Add your free API key to .env file. "
|
| 646 |
+
"Sign up at https://twelvedata.com (free, 30 seconds)."
|
| 647 |
+
)
|
| 648 |
+
|
| 649 |
+
params = {
|
| 650 |
+
"symbol": symbol,
|
| 651 |
+
"interval": interval,
|
| 652 |
+
"outputsize": outputsize,
|
| 653 |
+
"apikey": api_key,
|
| 654 |
+
"format": "JSON",
|
| 655 |
+
"order": "ASC",
|
| 656 |
+
}
|
| 657 |
+
if exchange:
|
| 658 |
+
params["exchange"] = exchange
|
| 659 |
+
|
| 660 |
+
resp = http_requests.get(f"{TWELVEDATA_BASE}/time_series", params=params, timeout=30)
|
| 661 |
+
data = resp.json()
|
| 662 |
+
|
| 663 |
+
if data.get("status") == "error" or "code" in data:
|
| 664 |
+
msg = data.get("message", str(data))
|
| 665 |
+
raise ValueError(f"Twelve Data API error: {msg}")
|
| 666 |
+
|
| 667 |
+
values = data.get("values", [])
|
| 668 |
+
if not values:
|
| 669 |
+
raise ValueError(f"No data returned for symbol '{symbol}'. Check the symbol is valid.")
|
| 670 |
+
|
| 671 |
+
df = pd.DataFrame(values)
|
| 672 |
+
df = df.rename(columns={"datetime": "date"})
|
| 673 |
+
|
| 674 |
+
for col in ["open", "high", "low", "close", "volume"]:
|
| 675 |
+
if col in df.columns:
|
| 676 |
+
df[col] = pd.to_numeric(df[col], errors="coerce")
|
| 677 |
+
|
| 678 |
+
if "date" in df.columns:
|
| 679 |
+
df["date"] = pd.to_datetime(df["date"])
|
| 680 |
+
df = df.sort_values("date").reset_index(drop=True)
|
| 681 |
+
|
| 682 |
+
df = df.dropna(subset=["open", "high", "low", "close"]).reset_index(drop=True)
|
| 683 |
+
|
| 684 |
+
# Remove flat candles
|
| 685 |
+
flat = ((df["open"]==df["high"]) & (df["high"]==df["low"]) & (df["low"]==df["close"]))
|
| 686 |
+
df = df[~flat].copy().reset_index(drop=True)
|
| 687 |
+
|
| 688 |
+
return df
|
| 689 |
+
|
| 690 |
+
|
| 691 |
+
def fetch_current_price(symbol: str, exchange: str = ""):
|
| 692 |
+
"""Quick price lookup — 1 API credit."""
|
| 693 |
+
api_key = _get_api_key()
|
| 694 |
+
if not api_key:
|
| 695 |
+
return None
|
| 696 |
+
|
| 697 |
+
params = {"symbol": symbol, "apikey": api_key}
|
| 698 |
+
if exchange:
|
| 699 |
+
params["exchange"] = exchange
|
| 700 |
+
|
| 701 |
+
try:
|
| 702 |
+
resp = http_requests.get(f"{TWELVEDATA_BASE}/price", params=params, timeout=10)
|
| 703 |
+
data = resp.json()
|
| 704 |
+
if "price" in data:
|
| 705 |
+
return float(data["price"])
|
| 706 |
+
except Exception:
|
| 707 |
+
pass
|
| 708 |
+
return None
|
| 709 |
+
|
| 710 |
+
|
| 711 |
+
# ── Live data endpoints ───────────────────────────────────────────────────────
|
| 712 |
+
|
| 713 |
+
@app.get("/instruments")
|
| 714 |
+
def list_instruments():
|
| 715 |
+
"""Return the catalog of supported instruments with categories."""
|
| 716 |
+
api_ready = _get_api_key() is not None
|
| 717 |
+
return {
|
| 718 |
+
"api_ready": api_ready,
|
| 719 |
+
"instruments": INSTRUMENT_CATALOG,
|
| 720 |
+
"categories": sorted(set(i["category"] for i in INSTRUMENT_CATALOG)),
|
| 721 |
+
"timeframes": ["1min","5min","15min","1h","4h","1day"],
|
| 722 |
+
}
|
| 723 |
+
|
| 724 |
+
|
| 725 |
+
@app.get("/price/{symbol:path}")
|
| 726 |
+
def get_price(symbol: str, exchange: str = Query(default="")):
|
| 727 |
+
"""Quick current-price lookup for a symbol."""
|
| 728 |
+
price = fetch_current_price(symbol, exchange)
|
| 729 |
+
if price is None:
|
| 730 |
+
return {"error": "Could not fetch price. Check API key and symbol."}
|
| 731 |
+
return {"symbol": symbol, "price": price}
|
| 732 |
+
|
| 733 |
+
|
| 734 |
+
@app.get("/live-analyse/{symbol:path}")
|
| 735 |
+
def live_analyse(symbol: str, exchange: str = Query(default=""),
|
| 736 |
+
name: str = Query(default=""),
|
| 737 |
+
interval: str = Query(default="5min")):
|
| 738 |
+
"""
|
| 739 |
+
Fetch live OHLCV data from Twelve Data and run the full analysis pipeline:
|
| 740 |
+
indicators → Chronos forecast → 3 XGBoost models → signal + backtest.
|
| 741 |
+
Returns the same JSON structure as POST /analyse.
|
| 742 |
+
Supports intervals: 1min, 5min, 15min, 1h, 4h, 1day.
|
| 743 |
+
"""
|
| 744 |
+
valid_intervals = ["1min","5min","15min","1h","4h","1day"]
|
| 745 |
+
if interval not in valid_intervals:
|
| 746 |
+
return {"error": f"Invalid interval '{interval}'. Use one of: {valid_intervals}"}
|
| 747 |
+
|
| 748 |
+
try:
|
| 749 |
+
# Resolve from catalog if no exchange provided
|
| 750 |
+
if not exchange and not name:
|
| 751 |
+
for inst in INSTRUMENT_CATALOG:
|
| 752 |
+
if inst["symbol"].upper() == symbol.upper():
|
| 753 |
+
exchange = inst.get("exchange", "")
|
| 754 |
+
name = inst.get("name", symbol)
|
| 755 |
+
break
|
| 756 |
+
|
| 757 |
+
display_name = name.strip() or symbol
|
| 758 |
+
|
| 759 |
+
# Fetch live data
|
| 760 |
+
df = fetch_live_data(symbol, exchange=exchange, interval=interval, outputsize=5000)
|
| 761 |
+
|
| 762 |
+
if len(df) < 250:
|
| 763 |
+
return {"error": f"Only {len(df)} bars returned for {interval} timeframe. "
|
| 764 |
+
f"Need 250+ for indicators. Try a shorter timeframe."}
|
| 765 |
+
|
| 766 |
+
# Run full pipeline (same as /analyse)
|
| 767 |
+
df = add_indicators(df)
|
| 768 |
+
cf = run_chronos(df["close"])
|
| 769 |
+
signal_data = build_signal_response(df, cf, instrument_name=display_name)
|
| 770 |
+
backtest_data = quick_backtest(df, display_name)
|
| 771 |
+
|
| 772 |
+
data_summary = {
|
| 773 |
+
"instrument": display_name,
|
| 774 |
+
"filename": f"live:{symbol}",
|
| 775 |
+
"interval": interval,
|
| 776 |
+
"total_rows": len(df),
|
| 777 |
+
"date_start": str(df["date"].iloc[0]) if "date" in df.columns else "N/A",
|
| 778 |
+
"date_end": str(df["date"].iloc[-1]) if "date" in df.columns else "N/A",
|
| 779 |
+
"price_range": {
|
| 780 |
+
"low": round(float(df["close"].min()), 4),
|
| 781 |
+
"high": round(float(df["close"].max()), 4),
|
| 782 |
+
"current": round(float(df["close"].iloc[-1]), 4),
|
| 783 |
+
},
|
| 784 |
+
"avg_atr_pct": round(float((df["ATR"]/df["close"]*100).median()), 4),
|
| 785 |
+
"source": "Twelve Data API (live)",
|
| 786 |
+
}
|
| 787 |
+
|
| 788 |
+
return {
|
| 789 |
+
"status": "success",
|
| 790 |
+
"data_summary": data_summary,
|
| 791 |
+
"signal": signal_data,
|
| 792 |
+
"backtest": backtest_data,
|
| 793 |
+
}
|
| 794 |
+
|
| 795 |
+
except ValueError as e:
|
| 796 |
+
return {"error": str(e)}
|
| 797 |
+
except Exception as e:
|
| 798 |
+
return {"error": str(e), "detail": traceback.format_exc()}
|
data/nifty_5m.csv
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:ba583f06bb79a7adc7ce2ee56b38b0d78b5f0d1ed0d220996493d936ef73ee9b
|
| 3 |
+
size 10933851
|
data/nifty_5m_indicators.csv
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:b5c1e45e447f1f51f548e065d61f04c43f90234270310d8c19f5810df5afba66
|
| 3 |
+
size 30793012
|
data/nifty_ml_features.csv
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:14637c1912f1476407bab323ede1d39c3b3aaab8a30ae03ed835fedc34c44419
|
| 3 |
+
size 46596433
|
data/nifty_ml_features_chronos.csv
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:24c49553d0be6fe19d67c91e8ed56c81eab05cfbf195f71a64d0ae5b8304003b
|
| 3 |
+
size 54722343
|
data/nifty_with_indicators.csv
ADDED
|
@@ -0,0 +1,249 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Date,Open,High,Low,Close,Shares Traded,Turnover (₹ Cr),RSI,ATR,ADX
|
| 2 |
+
16-JUN-2025,24732.35,24967.1,24703.6,24946.5,305813047,23857.15,,0.0,0.0
|
| 3 |
+
17-JUN-2025,24977.85,24982.05,24813.7,24853.4,242415740,21818.05,,0.0,0.0
|
| 4 |
+
18-JUN-2025,24788.35,24947.55,24750.45,24812.05,237599011,22044.05,,0.0,0.0
|
| 5 |
+
19-JUN-2025,24803.25,24863.1,24733.4,24793.25,274619935,23620.79,,0.0,0.0
|
| 6 |
+
20-JUN-2025,24787.65,25136.2,24783.65,25112.4,574654035,55782.03,,0.0,0.0
|
| 7 |
+
23-JUN-2025,24939.75,25057.0,24824.85,24971.9,248534153,20797.88,,0.0,0.0
|
| 8 |
+
24-JUN-2025,25179.9,25317.7,24999.7,25044.35,450185468,35508.9,,0.0,0.0
|
| 9 |
+
25-JUN-2025,25150.35,25266.8,25125.05,25244.75,260582584,22985.17,,0.0,0.0
|
| 10 |
+
26-JUN-2025,25268.95,25565.3,25259.9,25549.0,428891818,38689.39,,0.0,0.0
|
| 11 |
+
27-JUN-2025,25576.65,25654.2,25523.55,25637.8,563957748,47108.6,,0.0,0.0
|
| 12 |
+
30-JUN-2025,25661.65,25669.35,25473.3,25517.05,270981274,24673.48,,0.0,0.0
|
| 13 |
+
01-JUL-2025,25551.35,25593.4,25501.8,25541.8,260669106,23921.02,,0.0,0.0
|
| 14 |
+
02-JUL-2025,25588.3,25608.1,25378.75,25453.4,309828013,26681.66,,0.0,0.0
|
| 15 |
+
03-JUL-2025,25505.1,25587.5,25384.35,25405.3,293428797,24531.7,63.100656695060266,224.16785714285703,0.0
|
| 16 |
+
04-JUL-2025,25428.85,25470.25,25331.65,25461.0,193511595,19101.33,65.18320015163106,218.05586734693858,0.0
|
| 17 |
+
07-JUL-2025,25450.45,25489.8,25407.25,25461.3,196051345,16923.26,65.19459406417769,208.3768768221572,0.0
|
| 18 |
+
08-JUL-2025,25427.85,25548.05,25424.15,25522.5,210410530,21947.32,67.52909110025904,202.34281419200292,0.0
|
| 19 |
+
09-JUL-2025,25514.6,25548.7,25424.35,25476.1,239081546,20549.5,64.02291818239064,196.77189889257428,0.0
|
| 20 |
+
10-JUL-2025,25511.65,25524.05,25340.45,25355.25,219609322,21435.36,55.88438301376682,195.831048971676,0.0
|
| 21 |
+
11-JUL-2025,25255.5,25322.45,25129.0,25149.85,249987681,26251.65,45.335870824031076,198.00383118798487,0.0
|
| 22 |
+
14-JUL-2025,25149.5,25151.1,25001.95,25082.3,259533624,23316.33,42.49502027629286,194.51427181741437,0.0
|
| 23 |
+
15-JUL-2025,25089.5,25245.2,25088.45,25195.8,241340130,23282.7,48.35129029226029,192.256109544742,0.0
|
| 24 |
+
16-JUL-2025,25196.6,25255.3,25121.05,25212.05,228815928,22254.54,49.14974622066617,188.11281600583183,0.0
|
| 25 |
+
17-JUL-2025,25230.75,25238.35,25101.0,25111.45,243412540,24715.35,44.557342570142026,184.48690057684374,0.0
|
| 26 |
+
18-JUL-2025,25108.55,25144.6,24918.65,24968.4,316979826,26330.8,38.97991177371459,187.4485505356404,0.0
|
| 27 |
+
21-JUL-2025,24999.0,25111.4,24882.3,25090.7,305216414,26062.25,45.28569548682767,190.4236540688091,0.0
|
| 28 |
+
22-JUL-2025,25166.65,25182.0,25035.55,25060.9,483725120,31248.06,44.09010657602441,187.28267877817993,0.0
|
| 29 |
+
23-JUL-2025,25139.35,25233.5,25085.5,25219.9,271539651,23042.49,51.45447610286116,186.23391600830982,23.565058769757503
|
| 30 |
+
24-JUL-2025,25243.3,25246.25,25018.7,25062.1,338728860,27433.34,45.104637809649034,189.18506486485904,22.127060667322876
|
| 31 |
+
25-JUL-2025,25010.35,25010.35,24806.35,24837.0,278136104,25273.64,37.91643695347334,193.93970308879767,21.972579701974933
|
| 32 |
+
28-JUL-2025,24782.45,24889.2,24646.6,24680.9,262142969,24976.54,33.883683166574386,197.41543858245515,22.525438590565848
|
| 33 |
+
29-JUL-2025,24609.65,24847.15,24598.6,24821.1,284657235,25954.42,40.050866929583954,201.06790725513716,23.22917425502695
|
| 34 |
+
30-JUL-2025,24890.4,24902.3,24771.95,24855.05,243886726,23525.25,41.47450560097145,196.0166281654844,23.45889751341621
|
| 35 |
+
31-JUL-2025,24642.25,24956.5,24635.0,24768.35,346303628,30477.71,38.93185893878757,204.9797261536641,24.23448076727495
|
| 36 |
+
01-AUG-2025,24734.9,24784.15,24535.05,24565.35,263357194,24972.45,33.71936246986505,208.13117428554537,25.318678062060155
|
| 37 |
+
04-AUG-2025,24596.05,24736.25,24554.0,24722.75,259329477,20372.68,40.38428027102401,206.282518979435,26.325432692932132
|
| 38 |
+
05-AUG-2025,24720.25,24733.1,24590.3,24649.55,251849778,23815.36,38.44798009246112,201.74805333804673,27.260276278741827
|
| 39 |
+
06-AUG-2025,24641.35,24671.4,24539.2,24574.2,225091071,20559.22,36.50754200386468,196.78033524247203,28.332629002499832
|
| 40 |
+
07-AUG-2025,24464.2,24634.2,24344.15,24596.15,616739190,35574.59,37.497147394357064,203.442454153724,29.99846069753881
|
| 41 |
+
08-AUG-2025,24544.25,24585.5,24337.5,24363.3,312630157,38135.74,31.82957415201612,207.38585028560095,31.56578683535193
|
| 42 |
+
11-AUG-2025,24371.5,24600.85,24347.45,24585.05,241145497,21081.61,40.97870274526137,210.67257526520072,32.86346786977862
|
| 43 |
+
12-AUG-2025,24563.35,24702.6,24465.65,24487.4,237002462,22258.29,38.526605055434786,212.54953417482903,33.06336280755051
|
| 44 |
+
13-AUG-2025,24586.2,24664.55,24535.25,24619.35,236006791,22843.14,43.45072302594758,210.02099601948393,33.24897953548156
|
| 45 |
+
14-AUG-2025,24607.25,24673.65,24596.9,24631.3,270162203,22375.44,43.88908392007861,200.50163916094934,33.3277951520185
|
| 46 |
+
18-AUG-2025,24938.2,25022.0,24852.85,24876.95,363071305,37637.67,52.10778552505962,214.0872363637387,31.225377338765906
|
| 47 |
+
19-AUG-2025,24891.35,25012.65,24873.95,24980.65,252340828,24781.97,55.09777969392301,208.70243376632882,29.27313222645992
|
| 48 |
+
20-AUG-2025,24965.8,25088.7,24929.7,25050.55,287054119,25330.45,57.044516058900825,205.15225992587676,27.921856850974837
|
| 49 |
+
21-AUG-2025,25142.0,25153.65,25054.9,25083.75,226542052,21865.07,57.97643430734785,197.8628127883143,27.03998660266659
|
| 50 |
+
22-AUG-2025,25064.15,25084.85,24859.15,24870.1,210165384,19655.78,50.398872046520594,199.8511833034345,25.308327841449827
|
| 51 |
+
25-AUG-2025,24949.15,25021.55,24894.35,24967.75,213032133,19871.25,53.3969724768671,196.3939559246178,23.700358991748544
|
| 52 |
+
26-AUG-2025,24899.5,24919.65,24689.6,24712.05,750473927,47068.2,45.620879550493825,202.23367335857378,23.32968521442798
|
| 53 |
+
28-AUG-2025,24695.8,24702.65,24481.6,24500.9,326601486,29371.67,40.39011748492477,204.24912526153284,23.860231000725587
|
| 54 |
+
29-AUG-2025,24466.7,24572.45,24404.7,24426.85,325543583,26796.69,38.71369085983561,201.64204488570905,24.63211202797527
|
| 55 |
+
01-SEP-2025,24432.7,24635.6,24432.7,24625.05,229327424,20704.88,45.26243708761956,202.14975596530127,24.89143142069513
|
| 56 |
+
02-SEP-2025,24653.0,24756.1,24522.35,24579.6,271558516,22051.8,44.09875083920981,204.40691625349405,24.316644201062754
|
| 57 |
+
03-SEP-2025,24616.5,24737.05,24533.2,24715.05,340283328,23533.08,48.35979224147172,204.36713652110151,23.782913211404118
|
| 58 |
+
04-SEP-2025,24980.75,24980.75,24708.2,24734.3,314094160,30252.19,48.9552917062556,209.2373410553085,22.32260959946156
|
| 59 |
+
05-SEP-2025,24818.85,24832.35,24621.6,24741.0,210071924,18530.24,49.174976368161616,209.34538812278646,20.947341342467837
|
| 60 |
+
08-SEP-2025,24802.6,24885.5,24751.55,24773.15,213228202,20122.88,50.28074553406894,204.71357468544457,19.52173527192056
|
| 61 |
+
09-SEP-2025,24864.1,24891.8,24814.0,24868.6,226919775,22356.88,53.51433981685825,198.56617649362695,18.23332164920341
|
| 62 |
+
10-SEP-2025,24991.0,25035.7,24915.05,24973.1,244146466,22458.98,56.82502621202437,196.31859245836804,17.807668580547507
|
| 63 |
+
11-SEP-2025,24945.5,25037.3,24940.15,25005.5,224570983,21316.72,57.82788058308388,189.23512156848446,17.4206265575615
|
| 64 |
+
12-SEP-2025,25074.45,25139.45,25038.05,25114.0,225739766,21335.67,61.08748225770283,185.28618431359274,17.57822248783852
|
| 65 |
+
15-SEP-2025,25118.9,25138.45,25048.75,25069.2,185375759,17115.6,59.05770388060118,178.45859971976475,17.724561565952893
|
| 66 |
+
16-SEP-2025,25073.6,25261.4,25070.45,25239.1,240122320,22642.86,63.9498906667505,179.44012831121017,18.454049580462684
|
| 67 |
+
17-SEP-2025,25276.6,25346.5,25275.35,25330.25,268936695,23484.12,66.27794366228426,174.29440486040954,19.49976005387826
|
| 68 |
+
18-SEP-2025,25441.05,25448.55,25329.75,25423.6,272193683,24198.11,68.52008101968661,170.3305187989517,20.875048271778066
|
| 69 |
+
19-SEP-2025,25410.2,25431.4,25286.3,25327.05,380362832,38805.58,63.79552482511782,168.528338884741,21.782028723241726
|
| 70 |
+
22-SEP-2025,25238.1,25331.7,25151.05,25202.35,254509892,25277.82,58.212632530275506,169.3941718215453,21.562836982282988
|
| 71 |
+
23-SEP-2025,25209.0,25261.9,25084.65,25169.5,299204338,31435.17,56.80240444840752,169.95530240572066,20.888269727382376
|
| 72 |
+
24-SEP-2025,25108.75,25149.85,25027.45,25056.9,244382281,22310.05,52.139794026972055,167.9620665195977,19.869404368311763
|
| 73 |
+
25-SEP-2025,25034.5,25092.7,24878.3,24890.85,342534768,32715.91,46.12667582754492,171.27906176819798,18.898327937813058
|
| 74 |
+
26-SEP-2025,24818.55,24868.6,24629.45,24654.7,291537949,29987.93,39.2023664081673,177.71627164189798,19.191959193492128
|
| 75 |
+
29-SEP-2025,24728.55,24791.3,24606.2,24634.9,394388242,40004.93,38.67810079476936,178.24368081033373,19.561670208096537
|
| 76 |
+
30-SEP-2025,24691.95,24731.8,24587.7,24611.1,304924720,29285.11,38.01991771646372,175.80484646673835,19.98545418028764
|
| 77 |
+
01-OCT-2025,24620.55,24867.95,24605.95,24836.3,308135228,29041.17,47.17922183424384,181.9616431476856,19.432353985954876
|
| 78 |
+
03-OCT-2025,24759.55,24904.8,24747.55,24894.25,366929642,31409.06,49.25726212858114,180.19652577999378,18.67935140000224
|
| 79 |
+
06-OCT-2025,24916.55,25095.95,24881.65,25077.65,271953070,25160.76,55.256665839376765,182.6324882242799,17.822063190161337
|
| 80 |
+
07-OCT-2025,25085.3,25220.9,25076.3,25108.3,286833765,26176.23,56.188919266346005,179.9158819225458,17.63553696731559
|
| 81 |
+
08-OCT-2025,25079.75,25192.5,25008.5,25046.15,225967495,21701.19,53.7436421841388,180.20760464236395,17.04491747362978
|
| 82 |
+
09-OCT-2025,25074.3,25199.25,25024.3,25181.8,286253252,22617.86,58.03619464005307,179.8320614536237,16.531501142698076
|
| 83 |
+
10-OCT-2025,25167.65,25330.75,25156.85,25285.35,232943306,21749.23,61.010635397424245,179.40834277836498,16.71095781022523
|
| 84 |
+
13-OCT-2025,25177.3,25267.3,25152.3,25227.35,234285202,20806.83,58.50904587572733,176.0970325799103,16.84542724244308
|
| 85 |
+
14-OCT-2025,25277.55,25310.35,25060.55,25145.5,292129083,24151.97,55.076977185371696,181.36153025277378,16.32718979693375
|
| 86 |
+
15-OCT-2025,25181.95,25365.15,25159.35,25323.55,289930172,25202.02,60.50435597314488,184.09642094900434,16.14663782739653
|
| 87 |
+
16-OCT-2025,25394.9,25625.4,25376.85,25585.3,372777021,32008.64,66.84581160079668,192.50739088121847,17.16315301466889
|
| 88 |
+
17-OCT-2025,25546.85,25781.5,25508.6,25709.85,422055809,35106.96,69.36627981026413,198.2497201039887,18.65659212074458
|
| 89 |
+
20-OCT-2025,25824.6,25926.2,25788.5,25843.15,301133193,29637.12,71.83422562340411,199.54259723941823,20.48284072022335
|
| 90 |
+
21-OCT-2025,25901.2,25934.35,25825.8,25868.6,42477128,3831.1,72.29317518381517,193.04312600803115,22.202508024401507
|
| 91 |
+
23-OCT-2025,26057.2,26104.2,25862.45,25891.4,448404894,41777.68,72.72200740843272,196.52218843602893,24.268655307528483
|
| 92 |
+
24-OCT-2025,25935.1,25944.15,25718.2,25795.15,284913477,23527.98,67.94137284674038,198.62417497631262,25.13158398330705
|
| 93 |
+
27-OCT-2025,25843.2,26005.95,25827.0,25966.05,266337274,23989.06,71.52123898475186,199.49387676371882,26.129147869803678
|
| 94 |
+
28-OCT-2025,25939.95,26041.7,25810.05,25936.2,395231207,37023.32,70.04988805358391,201.79074270916757,27.169388096789827
|
| 95 |
+
29-OCT-2025,25982.0,26097.85,25960.3,26053.9,321880610,26309.32,72.45604703010113,198.92354680136972,28.31502599458842
|
| 96 |
+
30-OCT-2025,25984.4,26032.05,25845.25,25877.85,257373001,24180.46,64.15385327698235,199.61829345841485,28.503304728745196
|
| 97 |
+
31-OCT-2025,25863.8,25953.75,25711.2,25722.1,334384400,28788.4,57.839623335479196,202.6848439256709,27.77100063361481
|
| 98 |
+
03-NOV-2025,25696.85,25803.1,25645.5,25763.35,275858501,23949.88,58.990845243558105,199.46449793098003,26.6796927434581
|
| 99 |
+
04-NOV-2025,25744.75,25787.4,25578.4,25597.65,305143084,29307.41,52.75877287198876,200.1456052216243,25.2578536319756
|
| 100 |
+
06-NOV-2025,25593.35,25679.15,25491.55,25509.7,371852417,36129.62,49.754246363159865,199.24949056293698,23.47454381472313
|
| 101 |
+
07-NOV-2025,25433.8,25551.25,25318.45,25492.3,305606393,35487.0,49.15779934075203,201.64595552272712,22.70436671280556
|
| 102 |
+
10-NOV-2025,25503.5,25653.45,25503.5,25574.35,243592948,25023.65,52.075326488941684,198.75338727110383,21.399326759719262
|
| 103 |
+
11-NOV-2025,25617.0,25715.8,25449.25,25694.95,297714069,28285.51,56.06598752257347,203.5960024660249,19.896757335422908
|
| 104 |
+
12-NOV-2025,25834.3,25934.55,25781.15,25875.8,343864299,30633.19,61.27370605883247,206.16771657559448,19.55402574613625
|
| 105 |
+
13-NOV-2025,25906.1,26010.7,25808.4,25879.15,385170023,30145.74,61.36506221729995,205.8914511059091,19.55433773768908
|
| 106 |
+
14-NOV-2025,25767.9,25940.2,25740.8,25910.05,518943416,33121.81,62.24967048542835,205.42777602691572,19.1462692012789
|
| 107 |
+
17-NOV-2025,25948.2,26024.2,25906.35,26013.45,264610565,23384.35,65.12710544861164,199.1722205964219,19.13746629168512
|
| 108 |
+
18-NOV-2025,26021.8,26029.85,25876.5,25910.05,280000989,26059.6,60.18662228148841,195.89920483953455,18.93802524278393
|
| 109 |
+
19-NOV-2025,25918.1,26074.65,25856.2,26052.65,250110008,24496.86,64.21802033759161,197.50997592242499,18.962485296146717
|
| 110 |
+
20-NOV-2025,26132.1,26246.65,26063.2,26192.15,240425729,25000.17,67.66715351509887,197.2592633565375,19.715659279465136
|
| 111 |
+
21-NOV-2025,26109.55,26179.2,26052.2,26068.15,235581427,24720.07,61.950732516022924,193.16574454535632,20.33501719531918
|
| 112 |
+
24-NOV-2025,26122.8,26142.8,25912.15,25959.5,464655063,44895.45,57.376940484296036,195.843191363545,19.937806372821672
|
| 113 |
+
25-NOV-2025,25998.5,26032.6,25857.5,25884.8,260454909,25320.15,54.4030253331595,194.3615348375774,19.219266862594875
|
| 114 |
+
26-NOV-2025,25842.95,26215.15,25842.95,26205.3,275265169,31666.03,63.21304934472638,207.06428234917908,19.408421555186855
|
| 115 |
+
27-NOV-2025,26261.25,26310.45,26141.9,26215.55,240287057,25306.47,63.456233283547206,204.3132621813805,19.972425835633082
|
| 116 |
+
28-NOV-2025,26237.45,26280.75,26172.4,26202.95,202511545,20525.36,62.90572653865619,197.45874345413895,20.49614409604743
|
| 117 |
+
01-DEC-2025,26325.8,26325.8,26124.2,26175.75,213828573,21734.75,61.66210076467754,197.75454749312894,20.625842365823093
|
| 118 |
+
02-DEC-2025,26087.95,26154.6,25997.85,26032.2,254803113,26298.82,55.43349596214558,196.33636552933413,19.875449001744332
|
| 119 |
+
03-DEC-2025,26004.9,26066.45,25891.0,25986.0,265660108,25320.85,53.55839992651379,194.8444822772389,18.524050801009963
|
| 120 |
+
04-DEC-2025,25981.85,26098.25,25938.95,26033.75,248099545,26377.76,55.24349158717939,192.3055906860075,17.452980872765163
|
| 121 |
+
05-DEC-2025,25999.8,26202.6,25985.35,26186.45,249254405,27491.07,60.21497846094057,194.08733420843552,17.037865200628495
|
| 122 |
+
08-DEC-2025,26159.8,26178.7,25892.25,25960.55,320729920,31677.57,51.16114978966641,201.23823890783302,16.056268786349392
|
| 123 |
+
09-DEC-2025,25867.1,25923.65,25728.0,25839.65,275978160,29894.41,47.08106863318138,203.4747932715592,15.591614231124094
|
| 124 |
+
10-DEC-2025,25864.05,25947.65,25734.55,25758.0,207944446,21975.7,44.49998014254869,204.16230803787656,15.009949432006161
|
| 125 |
+
11-DEC-2025,25771.4,25922.8,25693.25,25898.55,206099631,20145.19,49.62002616067503,205.9757146065996,14.696912936317386
|
| 126 |
+
12-DEC-2025,25971.2,26057.6,25938.45,26046.95,216344338,19484.07,54.4030670273083,202.6238778489853,13.739323300623782
|
| 127 |
+
15-DEC-2025,25930.05,26047.15,25904.75,26027.3,181557703,17444.03,53.676387755077684,198.3221722883436,12.869688653619566
|
| 128 |
+
16-DEC-2025,25951.5,25980.75,25834.35,25860.1,264351195,23554.69,47.822912196350984,197.93844569631912,12.481447536259974
|
| 129 |
+
17-DEC-2025,25902.4,25929.15,25770.35,25818.55,206521258,19787.57,46.466808769826365,195.14284243229653,12.485648974232593
|
| 130 |
+
18-DEC-2025,25764.7,25902.35,25726.3,25815.55,197553755,20046.07,46.36457884924669,193.77906797284672,12.734938904119291
|
| 131 |
+
19-DEC-2025,25911.5,25993.35,25880.45,25966.4,382927284,36600.58,52.074270459677656,192.6377059747862,12.300676238874738
|
| 132 |
+
22-DEC-2025,26055.85,26180.7,26047.8,26172.4,252990050,25333.26,58.56165895730966,194.18501269087284,12.098828243914271
|
| 133 |
+
23-DEC-2025,26205.2,26233.55,26119.05,26177.15,216553840,19670.5,58.70048062077157,188.4932260700962,12.195427033329477
|
| 134 |
+
24-DEC-2025,26170.65,26236.4,26123.0,26142.1,188846828,17474.44,57.17830331089755,183.12942420794658,12.300856042518976
|
| 135 |
+
26-DEC-2025,26121.25,26144.2,26008.6,26042.3,142243763,12263.06,52.96664388558337,179.73446533595055,11.594176084281864
|
| 136 |
+
29-DEC-2025,26063.35,26106.8,25920.3,25942.1,234312888,18184.45,49.05943702740574,180.2177178119541,11.150730623143426
|
| 137 |
+
30-DEC-2025,25940.9,25976.75,25878.0,25938.85,396893959,39492.31,48.93335034331525,174.3985951111002,10.994263276761862
|
| 138 |
+
31-DEC-2025,25971.05,26187.95,25969.0,26129.6,246314941,20703.99,56.0697082064446,179.73440974602178,10.882946212903873
|
| 139 |
+
01-JAN-2026,26173.3,26197.55,26113.4,26146.55,425631910,23454.66,56.649435636078,172.90695190702007,10.832604279558455
|
| 140 |
+
02-JAN-2026,26155.1,26340.0,26118.4,26328.55,357547806,23770.13,62.38879453531093,176.38502677080425,11.528905740377018
|
| 141 |
+
05-JAN-2026,26333.7,26373.2,26210.05,26250.3,338777649,25742.83,58.785212903212575,175.4396677157469,12.33571326617542
|
| 142 |
+
06-JAN-2026,26189.7,26273.95,26124.75,26178.7,383040203,34567.52,55.61952287160706,173.56540573605074,12.448905313466302
|
| 143 |
+
07-JAN-2026,26143.1,26187.15,26067.9,26140.75,338216740,30232.63,53.96084342278448,169.6857338977614,12.151570375991668
|
| 144 |
+
08-JAN-2026,26106.5,26133.2,25858.45,25876.85,328520950,27556.32,44.10979344835144,177.72961004792123,11.96053346303383
|
| 145 |
+
09-JAN-2026,25840.4,25940.6,25623.0,25683.3,348757262,27486.64,38.55102938848346,187.7203521873553,12.854447974733517
|
| 146 |
+
12-JAN-2026,25669.05,25813.15,25473.4,25790.25,275757268,23874.45,42.83774677972843,198.57961274540136,14.233826451019192
|
| 147 |
+
13-JAN-2026,25897.35,25899.8,25603.3,25732.3,339536336,31434.03,41.16216442295997,205.57392612072982,14.950872467952331
|
| 148 |
+
14-JAN-2026,25648.55,25791.75,25603.95,25665.6,393126596,28944.88,39.25875272486165,204.30435996924908,15.61670091224739
|
| 149 |
+
16-JAN-2026,25696.05,25873.5,25662.4,25694.35,434041776,37156.05,40.53516636816675,204.78976282858835,15.690489262764233
|
| 150 |
+
19-JAN-2026,25653.1,25653.3,25494.35,25585.5,443087953,33632.38,37.336176662094715,204.4476369122606,16.470796704907322
|
| 151 |
+
20-JAN-2026,25580.3,25585.0,25171.35,25232.5,409772324,31020.36,29.269026863869385,219.4263771328135,18.235221123398293
|
| 152 |
+
21-JAN-2026,25141.0,25300.95,24919.8,25157.5,395624981,30984.61,27.89018967668804,230.97806448046978,20.47300455997047
|
| 153 |
+
22-JAN-2026,25344.15,25435.75,25168.5,25289.9,486395433,34583.24,33.81752020111129,234.3546313032934,21.73839216141437
|
| 154 |
+
23-JAN-2026,25344.6,25347.95,25025.3,25048.65,393944908,31844.65,29.120451459761824,240.66144335305825,23.26681973689778
|
| 155 |
+
27-JAN-2026,25063.35,25246.65,24932.55,25175.4,618696080,50989.25,34.28480855914806,245.90705454212568,24.900867383533406
|
| 156 |
+
28-JAN-2026,25258.85,25372.1,25187.65,25342.75,574903942,42364.52,40.45376960103045,242.39226493197364,25.671611193386575
|
| 157 |
+
29-JAN-2026,25345.0,25458.15,25159.8,25418.9,582389331,44306.95,43.0725371641871,246.38924600826138,25.900941253288106
|
| 158 |
+
30-JAN-2026,25247.55,25370.7,25213.65,25320.65,508388604,40772.08,40.59208221449045,243.4507284362427,26.113890594625246
|
| 159 |
+
01-FEB-2026,25333.75,25440.9,24571.75,24825.45,379370206,25572.6,30.925373992976716,288.14353354793974,27.849365175647215
|
| 160 |
+
02-FEB-2026,24796.5,25108.1,24679.4,25088.4,449215604,34038.26,39.20452424776383,298.18328115165815,29.460877286596183
|
| 161 |
+
03-FEB-2026,26308.05,26341.2,25641.3,25727.55,637263148,52338.39,53.7236539223383,366.37018964082534,28.083078037381135
|
| 162 |
+
04-FEB-2026,25675.05,25818.55,25563.95,25776.0,429788986,36899.12,54.608603524435054,358.3866046664806,26.595245480728178
|
| 163 |
+
05-FEB-2026,25755.9,25757.65,25579.5,25642.8,343812628,28582.32,51.682446239067765,346.82327576173196,25.21368667812186
|
| 164 |
+
06-FEB-2026,25605.8,25703.95,25491.9,25693.7,375476124,29777.45,52.724924641819854,337.1966132073225,23.673238792108663
|
| 165 |
+
09-FEB-2026,25888.7,25922.25,25780.9,25867.3,359386006,28449.55,56.19621089963604,329.43614083537085,22.812418869757426
|
| 166 |
+
10-FEB-2026,25922.65,25989.45,25870.45,25935.15,460878237,32795.1,57.509425248427796,314.6299879185587,22.181661423689444
|
| 167 |
+
11-FEB-2026,25997.45,26009.4,25899.8,25953.85,331389240,31456.05,57.88417870920234,299.98498878151895,21.647970277059567
|
| 168 |
+
12-FEB-2026,25906.7,25906.7,25752.4,25807.2,419388014,38977.68,53.87147530992135,292.94677529712453,20.635334218226113
|
| 169 |
+
13-FEB-2026,25571.15,25630.35,25444.3,25471.1,453523192,40137.15,46.000773684312755,297.9434342044729,19.582569784615377
|
| 170 |
+
16-FEB-2026,25423.6,25697.0,25372.7,25682.75,325487729,22205.92,50.86873348253021,299.8260460470105,18.8079275593665
|
| 171 |
+
17-FEB-2026,25637.95,25764.4,25570.3,25725.4,378436265,27818.81,51.811466252431664,292.2741856150813,17.857969338510575
|
| 172 |
+
18-FEB-2026,25752.65,25828.05,25645.15,25819.35,400807585,22228.22,53.909463156424444,284.4617437854325,16.75493359234772
|
| 173 |
+
19-FEB-2026,25873.35,25885.3,25388.75,25454.35,333658812,24756.87,45.60268991920163,299.6109049436158,16.51712378399399
|
| 174 |
+
20-FEB-2026,25406.55,25663.55,25379.75,25571.25,309373691,24024.7,48.34781642948546,298.4815545905003,16.322562746013894
|
| 175 |
+
23-FEB-2026,25678.4,25771.45,25609.35,25713.0,399135843,25494.64,51.54119826063681,291.46144354832177,15.719385051786706
|
| 176 |
+
24-FEB-2026,25641.8,25641.8,25327.6,25424.65,439068188,36735.38,45.393190034973806,298.17134043772745,15.998486322148356
|
| 177 |
+
25-FEB-2026,25512.6,25652.6,25428.2,25482.5,414215742,31084.17,46.76515805633626,293.15553040646097,16.212901854787017
|
| 178 |
+
26-FEB-2026,25556.3,25572.95,25400.95,25496.55,405219244,33155.5,47.11269920247926,284.50156394885664,16.49317993851439
|
| 179 |
+
27-FEB-2026,25459.85,25476.4,25141.3,25178.65,438924282,38634.68,40.64671551028954,289.5550236667954,17.471383047134182
|
| 180 |
+
02-MAR-2026,24659.25,24989.35,24603.5,24865.7,519228821,41306.37,35.4837913417888,309.954664833453,19.472748619949687
|
| 181 |
+
04-MAR-2026,24388.8,24602.45,24305.4,24480.5,598993881,47700.19,30.37032165249248,327.83647448820636,21.781663547658237
|
| 182 |
+
05-MAR-2026,24615.95,24854.2,24529.4,24765.9,504339053,40011.88,37.5509712016357,331.1124405961917,22.893298465213718
|
| 183 |
+
06-MAR-2026,24656.4,24700.8,24415.75,24450.45,433408256,35453.32,33.445455613297455,332.4722662678924,24.12352722379867
|
| 184 |
+
09-MAR-2026,23868.05,24078.15,23697.8,24028.05,526901605,40569.31,28.890540754456808,362.4849615344716,26.255448424171654
|
| 185 |
+
10-MAR-2026,24280.8,24303.8,24079.95,24261.6,444283436,36657.53,34.224480203179425,356.2896071391522,27.436435057967305
|
| 186 |
+
11-MAR-2026,24231.85,24299.0,23834.3,23866.85,407400643,32549.4,30.112971043262874,364.0332066292129,28.853678354332725
|
| 187 |
+
12-MAR-2026,23674.85,23833.15,23556.3,23639.15,501004098,40147.62,28.0218159104367,360.2129775842691,30.498352156263376
|
| 188 |
+
13-MAR-2026,23462.5,23492.4,23112.0,23151.1,519776752,40786.7,24.150606557349093,372.1370506139643,32.47442793977147
|
| 189 |
+
16-MAR-2026,23116.1,23502.0,22955.25,23408.8,540293230,44710.21,29.675121564588537,384.6094041415382,34.45062099425677
|
| 190 |
+
17-MAR-2026,23493.2,23656.8,23346.6,23581.15,458788167,34495.73,33.18043794997378,379.294446702857,35.73810239993337
|
| 191 |
+
18-MAR-2026,23632.9,23862.25,23618.45,23777.8,382876401,28805.6,37.03675457538159,372.2805576526528,36.23618694890165
|
| 192 |
+
19-MAR-2026,23197.75,23378.7,22930.35,23002.15,550147401,42000.27,29.744898600522177,406.2212321060348,37.466504391115926
|
| 193 |
+
20-MAR-2026,23110.15,23345.15,23067.6,23114.5,663289390,50308.33,31.838229969117606,401.70542981274656,38.60894201602919
|
| 194 |
+
23-MAR-2026,22824.35,22851.7,22471.25,22512.65,550275334,41002.59,27.168189117267588,418.9586133975504,40.19723780849616
|
| 195 |
+
24-MAR-2026,22878.45,23057.3,22624.2,22912.4,538098322,43385.04,34.084063292341696,427.93656958343945,41.03290239316662
|
| 196 |
+
25-MAR-2026,23064.4,23465.35,23063.2,23306.45,505418973,40733.98,40.120134239774124,436.8661003274793,40.65583766645875
|
| 197 |
+
27-MAR-2026,23173.55,23186.1,22804.55,22819.6,612556883,47239.2,35.76277251896089,441.5113788755166,40.616098088184096
|
| 198 |
+
30-MAR-2026,22549.65,22714.1,22283.85,22331.4,698599891,53093.7,32.00859246839198,448.24270895583686,41.1263737958402
|
| 199 |
+
01-APR-2026,22899.0,22941.3,22618.6,22679.4,517954448,41192.2,37.079030455922954,459.7896583161341,41.0019068733043
|
| 200 |
+
02-APR-2026,22383.4,22782.3,22182.55,22713.1,495121035,38669.56,37.564606926659984,469.7868255792674,41.34042032632165
|
| 201 |
+
06-APR-2026,22780.3,22998.35,22542.95,22968.25,426416812,35893.16,41.260687599313385,468.7591951807481,41.10307040008071
|
| 202 |
+
07-APR-2026,22838.7,23153.85,22719.3,23123.65,476981883,38940.47,43.45619909480266,466.3156812392661,40.49370012168241
|
| 203 |
+
08-APR-2026,23855.15,24025.15,23828.5,23997.35,639257993,56557.11,53.89108616757308,497.4002754364614,38.10686270328049
|
| 204 |
+
09-APR-2026,23909.05,23990.75,23682.8,23775.1,466587329,40443.59,51.2977137817701,484.33954147671415,36.11267414488197
|
| 205 |
+
10-APR-2026,23880.55,24074.05,23856.35,24050.6,481302436,40109.22,54.23754105453634,471.0974313712346,34.102001878355374
|
| 206 |
+
13-APR-2026,23589.6,23907.4,23555.6,23842.65,488844789,41931.51,51.700713159574505,472.8047577018607,32.713514022665386
|
| 207 |
+
15-APR-2026,24163.8,24280.9,24145.8,24231.3,460334041,38376.84,55.85640330763691,470.33656072315637,30.697555262191734
|
| 208 |
+
16-APR-2026,24385.2,24400.95,24102.8,24196.75,508017772,44634.35,55.40006515599299,458.0375206715025,28.60321382106539
|
| 209 |
+
17-APR-2026,24165.9,24371.9,24096.05,24353.55,498625189,35373.29,57.11254996180931,445.0241263378239,26.671154724541772
|
| 210 |
+
20-APR-2026,24391.5,24480.65,24241.25,24364.85,415942883,35042.31,57.23997287888664,430.33668874226515,24.874835649309716
|
| 211 |
+
21-APR-2026,24374.55,24601.7,24354.9,24576.6,425826834,37315.7,59.65875250021234,417.22692526067476,23.45335706805335
|
| 212 |
+
22-APR-2026,24470.85,24515.95,24352.9,24378.1,440524292,38980.03,56.43593418732543,403.40357345634067,22.128739641522856
|
| 213 |
+
23-APR-2026,24202.35,24310.2,24134.8,24173.05,467549860,39616.97,53.23662567560352,391.96760392374483,20.708540589705297
|
| 214 |
+
24-APR-2026,24100.55,24206.0,23813.65,23897.95,438433486,36898.39,49.206330261259446,391.99491792919156,20.07121873541172
|
| 215 |
+
27-APR-2026,23945.45,24130.7,23936.2,24092.7,430297937,36685.28,51.97797998238496,380.6202809342493,19.479419870710537
|
| 216 |
+
28-APR-2026,24049.9,24181.8,23957.05,23995.7,554134344,43390.29,50.499899051661906,369.48668943894575,18.788636189683324
|
| 217 |
+
29-APR-2026,24096.9,24334.7,24059.95,24177.65,531122966,38035.47,53.18891005210662,367.30906876473534,17.724185301445303
|
| 218 |
+
30-APR-2026,23996.95,24087.45,23796.85,23997.55,505520648,44420.83,50.27748017792355,368.27270671011155,17.359541589452444
|
| 219 |
+
04-MAY-2026,24063.55,24290.2,24004.75,24119.3,419069793,35790.21,52.182974843958,362.8710848022465,16.456906247198926
|
| 220 |
+
05-MAY-2026,24052.6,24081.7,23882.05,24032.8,363297728,33650.36,50.696477247580276,353.89815017351464,15.916149497062193
|
| 221 |
+
06-MAY-2026,24171.0,24356.5,23997.9,24330.95,429190144,38826.87,55.41128239668968,354.2339965896921,14.88614305246873
|
| 222 |
+
07-MAY-2026,24398.5,24482.1,24284.0,24326.65,440621691,39529.1,55.329103981673676,343.08156826185683,14.245127182640564
|
| 223 |
+
08-MAY-2026,24233.65,24253.8,24126.65,24176.15,335887188,31217.1,52.39994388576248,332.86145624315276,13.236794807899622
|
| 224 |
+
11-MAY-2026,23970.1,23997.45,23799.1,23815.85,390108343,37404.28,46.10680972292998,336.0177807972135,13.109165973084606
|
| 225 |
+
12-MAY-2026,23722.6,23757.55,23348.4,23379.55,447518189,36200.59,39.86347079753725,345.4057964545552,13.900321129065365
|
| 226 |
+
13-MAY-2026,23362.45,23582.95,23262.55,23412.6,415359044,33693.48,40.52050809395995,343.61966813637275,14.79015291735624
|
| 227 |
+
14-MAY-2026,23530.25,23777.2,23426.55,23689.6,428735424,38828.33,45.85958562812082,345.11826326948915,15.02731353096364
|
| 228 |
+
15-MAY-2026,23731.4,23839.3,23610.3,23643.5,408864566,35052.32,45.13347368910804,336.82410160738283,15.062118138902386
|
| 229 |
+
18-MAY-2026,23482.2,23695.65,23317.1,23649.95,391968426,30029.02,45.26405755577249,339.8045229211414,15.701020786699006
|
| 230 |
+
19-MAY-2026,23675.3,23782.3,23587.2,23618.0,441953184,39325.73,44.696575490822426,329.46848556963124,16.01970810662859
|
| 231 |
+
20-MAY-2026,23457.25,23690.9,23397.3,23659.0,344050591,26163.78,45.63843960422801,326.90645088608636,16.704412273566554
|
| 232 |
+
21-MAY-2026,23830.05,23859.9,23596.6,23654.7,348183907,29930.79,45.55081991546277,322.36313296565186,16.789952092400515
|
| 233 |
+
22-MAY-2026,23671.2,23835.65,23671.0,23719.3,336108649,24993.16,47.19113214051073,312.26219489667676,16.869381924174906
|
| 234 |
+
25-MAY-2026,23940.25,24054.45,23922.85,24031.7,351224048,27301.94,54.35277627104842,313.8970381183428,16.23298990790084
|
| 235 |
+
26-MAY-2026,24004.1,24089.8,23885.45,23913.7,387932940,29835.11,51.51117584763934,306.07224968131817,15.742544838255323
|
| 236 |
+
27-MAY-2026,23880.35,23983.2,23858.25,23907.15,531572650,34903.35,51.35069191709423,293.13494613265266,15.363717395974874
|
| 237 |
+
29-MAY-2026,23902.15,24002.8,23484.75,23547.75,1198023438,101439.0,43.36688891213874,309.2003071231774,15.964459708647382
|
| 238 |
+
01-JUN-2026,23654.5,23733.7,23357.95,23382.6,421691204,33843.74,40.26864425430988,313.95385661437905,16.803382262697742
|
| 239 |
+
02-JUN-2026,23229.15,23556.95,23229.15,23483.55,511852817,43063.5,42.95159899684816,314.94286685620904,17.858406349056732
|
| 240 |
+
03-JUN-2026,23415.95,23459.65,23151.5,23405.6,450089851,36726.56,41.405066875586485,316.16480493790834,19.002010477401907
|
| 241 |
+
04-JUN-2026,23282.45,23465.3,23247.3,23416.55,412505524,32848.46,41.72250796800722,309.1530331566292,20.038862288221225
|
| 242 |
+
05-JUN-2026,23478.95,23516.35,23282.65,23366.7,366208223,28432.83,40.64300311407537,303.76353078829834,20.764437529076215
|
| 243 |
+
08-JUN-2026,23080.7,23267.3,23070.15,23123.0,375730763,26550.42,35.77047898250383,303.24827858913415,21.93835453131042
|
| 244 |
+
09-JUN-2026,23259.05,23279.4,23104.45,23242.1,402552937,32911.17,39.5826369632425,294.08411583276745,22.96850452233958
|
| 245 |
+
10-JUN-2026,23233.95,23425.35,23184.6,23214.95,380030627,31906.68,39.01417502630117,290.27453613042695,23.20844800916083
|
| 246 |
+
11-JUN-2026,23104.4,23327.45,23072.05,23161.6,362996956,28529.75,37.863463975502945,287.7834978353966,23.73427604532795
|
| 247 |
+
12-JUN-2026,23412.55,23645.35,23313.9,23622.9,351944432,29593.12,51.252030983246506,301.7811051328682,22.83243546804758
|
| 248 |
+
15-JUN-2026,23984.85,24011.4,23817.8,23853.9,398913735,34783.09,56.326789545383484,307.97531190909194,21.646114704048966
|
| 249 |
+
16-JUN-2026,23923.9,24002.6,23888.2,23989.15,327307262,27953.23,59.01692051456147,296.5985039155852,20.544531137478824
|
data/training_dataset.csv
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:2f91d176b9592cd66a1c268fbd300be835f287a08fa476309491a6ed6a2b47a2
|
| 3 |
+
size 39170718
|
data/training_dataset_chronos.csv
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
data/training_dataset_v2.csv
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:196ba571320163c2f0a78cebed41d15a06f6a0c58f66f440f67c36d86b911d10
|
| 3 |
+
size 57089936
|
models/chronos-2/README.md
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
license: apache-2.0
|
| 3 |
+
model_id: chronos-2
|
| 4 |
+
tags:
|
| 5 |
+
- time series
|
| 6 |
+
- forecasting
|
| 7 |
+
- foundation models
|
| 8 |
+
- pretrained models
|
| 9 |
+
- safetensors
|
| 10 |
+
paper:
|
| 11 |
+
- https://arxiv.org/abs/2510.15821
|
| 12 |
+
datasets:
|
| 13 |
+
- autogluon/chronos_datasets
|
| 14 |
+
- Salesforce/GiftEvalPretrain
|
| 15 |
+
leaderboards:
|
| 16 |
+
- Salesforce/GIFT-Eval
|
| 17 |
+
- autogluon/fev-leaderboard
|
| 18 |
+
pipeline_tag: time-series-forecasting
|
| 19 |
+
library_name: chronos-forecasting
|
| 20 |
+
|
| 21 |
+
---
|
| 22 |
+
|
| 23 |
+
# Chronos-2
|
| 24 |
+
|
| 25 |
+
**Update Jun 5, 2026:** ☁️ Deploy Chronos-2 on AWS with AutoGluon-Cloud. Real-time, serverless, or batch inference in 3 lines of code — pandas DataFrames in, forecasts out. Check out the [new deployment guide](https://auto.gluon.ai/cloud/stable/tutorials/foundation-model-timeseries.html).
|
| 26 |
+
|
| 27 |
+
**Chronos-2** is a 120M-parameter, encoder-only time series foundation model for zero-shot forecasting.
|
| 28 |
+
It supports **univariate**, **multivariate**, and **covariate-informed** tasks within a single architecture.
|
| 29 |
+
Inspired by the T5 encoder, Chronos-2 produces multi-step-ahead quantile forecasts and uses a group attention mechanism for efficient in-context learning across related series and covariates.
|
| 30 |
+
Trained on a combination of real-world and large-scale synthetic datasets, it achieves **state-of-the-art zero-shot accuracy** among public models on [**fev-bench**](https://huggingface.co/spaces/autogluon/fev-leaderboard), [**GIFT-Eval**](https://huggingface.co/spaces/Salesforce/GIFT-Eval), and [**Chronos Benchmark II**](https://arxiv.org/abs/2403.07815).
|
| 31 |
+
Chronos-2 is also **highly efficient**, delivering over 300 time series forecasts per second on a single A10G GPU and supporting both **GPU and CPU inference**.
|
| 32 |
+
|
| 33 |
+
## Links
|
| 34 |
+
- ☁️ [Deploy on SageMaker with AutoGluon-Cloud](https://auto.gluon.ai/cloud/stable/tutorials/foundation-model-timeseries.html) (recommended)
|
| 35 |
+
- 🚀 [Deploy on SageMaker with JumpStart](https://github.com/amazon-science/chronos-forecasting/blob/main/notebooks/deploy-chronos-to-amazon-sagemaker.ipynb)
|
| 36 |
+
- 📄 [Technical report](https://arxiv.org/abs/2510.15821v1)
|
| 37 |
+
- 💻 [GitHub](https://github.com/amazon-science/chronos-forecasting)
|
| 38 |
+
- 📘 [Example notebook](https://github.com/amazon-science/chronos-forecasting/blob/main/notebooks/chronos-2-quickstart.ipynb)
|
| 39 |
+
- 📰 [Amazon Science Blog](https://www.amazon.science/blog/introducing-chronos-2-from-univariate-to-universal-forecasting)
|
| 40 |
+
|
| 41 |
+
|
| 42 |
+
## Overview
|
| 43 |
+
|
| 44 |
+
| Capability | Chronos-2 | Chronos-Bolt | Chronos |
|
| 45 |
+
|------------|-----------|--------------|----------|
|
| 46 |
+
| Univariate Forecasting | ✅ | ✅ | ✅ |
|
| 47 |
+
| Cross-learning across items | ✅ | ❌ | ❌ |
|
| 48 |
+
| Multivariate Forecasting | ✅ | ❌ | ❌ |
|
| 49 |
+
| Past-only (real/categorical) covariates | ✅ | ❌ | ❌ |
|
| 50 |
+
| Known future (real/categorical) covariates | ✅ | 🧩 | 🧩 |
|
| 51 |
+
| Max. Context Length | 8192 | 2048 | 512 |
|
| 52 |
+
| Max. Prediction Length | 1024 | 64 | 64 |
|
| 53 |
+
|
| 54 |
+
🧩 Chronos & Chronos-Bolt do not natively support future covariates, but they can be combined with external covariate regressors (see [AutoGluon tutorial](https://auto.gluon.ai/stable/tutorials/timeseries/forecasting-chronos.html#incorporating-the-covariates)). This only models per-timestep effects, not effects across time. In contrast, Chronos-2 supports all covariate types natively.
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
## Running the model locally
|
| 58 |
+
|
| 59 |
+
For experimentation and local inference, you can use the [inference package](https://github.com/amazon-science/chronos-forecasting).
|
| 60 |
+
|
| 61 |
+
Install the package
|
| 62 |
+
```
|
| 63 |
+
pip install "chronos-forecasting>=2.0"
|
| 64 |
+
```
|
| 65 |
+
|
| 66 |
+
Make zero-shot predictions using the `pandas` API
|
| 67 |
+
|
| 68 |
+
```python
|
| 69 |
+
import pandas as pd # requires: pip install 'pandas[pyarrow]'
|
| 70 |
+
from chronos import Chronos2Pipeline
|
| 71 |
+
|
| 72 |
+
pipeline = Chronos2Pipeline.from_pretrained("amazon/chronos-2", device_map="cuda")
|
| 73 |
+
|
| 74 |
+
# Load historical target values and past values of covariates
|
| 75 |
+
context_df = pd.read_parquet("https://autogluon.s3.amazonaws.com/datasets/timeseries/electricity_price/train.parquet")
|
| 76 |
+
|
| 77 |
+
# (Optional) Load future values of covariates
|
| 78 |
+
future_df = pd.read_parquet("https://autogluon.s3.amazonaws.com/datasets/timeseries/electricity_price/test.parquet").drop(columns="target")
|
| 79 |
+
|
| 80 |
+
# Generate predictions with covariates
|
| 81 |
+
pred_df = pipeline.predict_df(
|
| 82 |
+
context_df,
|
| 83 |
+
future_df=future_df,
|
| 84 |
+
prediction_length=24, # Number of steps to forecast
|
| 85 |
+
quantile_levels=[0.1, 0.5, 0.9], # Quantiles for probabilistic forecast
|
| 86 |
+
id_column="id", # Column identifying different time series
|
| 87 |
+
timestamp_column="timestamp", # Column with datetime information
|
| 88 |
+
target="target", # Column(s) with time series values to predict
|
| 89 |
+
)
|
| 90 |
+
```
|
| 91 |
+
|
| 92 |
+
## Production use on Amazon SageMaker
|
| 93 |
+
|
| 94 |
+
For production use, we recommend deploying Chronos-2 to Amazon SageMaker. There are two options:
|
| 95 |
+
|
| 96 |
+
- **AutoGluon-Cloud** (recommended) — minimal setup with a high-level Python API: pass a pandas DataFrame in, get forecasts back. Supports real-time, serverless, and batch inference out of the box.
|
| 97 |
+
- **SageMaker JumpStart** — fine-grained control over the deployment configuration. JSON request/response payloads only; serverless inference and batch prediction require additional setup.
|
| 98 |
+
|
| 99 |
+
### ☁️ AutoGluon-Cloud
|
| 100 |
+
|
| 101 |
+
Install AutoGluon-Cloud:
|
| 102 |
+
|
| 103 |
+
```
|
| 104 |
+
pip install autogluon.cloud>=0.5.0
|
| 105 |
+
```
|
| 106 |
+
|
| 107 |
+
Make predictions from a pandas DataFrame
|
| 108 |
+
|
| 109 |
+
```python
|
| 110 |
+
from autogluon.cloud import TimeSeriesFoundationModel
|
| 111 |
+
|
| 112 |
+
model = TimeSeriesFoundationModel(model_name="chronos-2")
|
| 113 |
+
|
| 114 |
+
# Batch prediction
|
| 115 |
+
forecast_df = model.predict(df, prediction_length=24)
|
| 116 |
+
|
| 117 |
+
# Deploy & invoke a real-time endpoint
|
| 118 |
+
endpoint = model.deploy(instance_type="ml.g5.xlarge")
|
| 119 |
+
forecast_df = endpoint.predict(df, prediction_length=24)
|
| 120 |
+
```
|
| 121 |
+
|
| 122 |
+
For more details (e.g. serverless endpoints, covariate-aware forecasting), see the [full deployment guide](https://auto.gluon.ai/cloud/stable/tutorials/foundation-model-timeseries.html).
|
| 123 |
+
|
| 124 |
+
### 🚀 SageMaker JumpStart
|
| 125 |
+
|
| 126 |
+
First, update the SageMaker SDK to make sure that all the latest models are available.
|
| 127 |
+
|
| 128 |
+
```
|
| 129 |
+
pip install -U 'sagemaker<3'
|
| 130 |
+
```
|
| 131 |
+
|
| 132 |
+
Deploy an inference endpoint to SageMaker.
|
| 133 |
+
|
| 134 |
+
```python
|
| 135 |
+
from sagemaker.jumpstart.model import JumpStartModel
|
| 136 |
+
|
| 137 |
+
model = JumpStartModel(
|
| 138 |
+
model_id="pytorch-forecasting-chronos-2",
|
| 139 |
+
instance_type="ml.g5.2xlarge",
|
| 140 |
+
)
|
| 141 |
+
predictor = model.deploy()
|
| 142 |
+
```
|
| 143 |
+
|
| 144 |
+
Now you can send time series data to the endpoint in JSON format.
|
| 145 |
+
|
| 146 |
+
```python
|
| 147 |
+
payload = {
|
| 148 |
+
"inputs": [
|
| 149 |
+
{"target": [1.0, 2.5, ..., 12.3]}
|
| 150 |
+
],
|
| 151 |
+
"parameters": {
|
| 152 |
+
"prediction_length": 24,
|
| 153 |
+
}
|
| 154 |
+
}
|
| 155 |
+
forecast = predictor.predict(payload)["predictions"]
|
| 156 |
+
```
|
| 157 |
+
|
| 158 |
+
For more details about the endpoint API, check out the [example notebook](https://github.com/amazon-science/chronos-forecasting/blob/2.2.2/notebooks/deploy-chronos-to-amazon-sagemaker.ipynb).
|
| 159 |
+
|
| 160 |
+
|
| 161 |
+
## Training data
|
| 162 |
+
More details about the training data are available in the [technical report](https://arxiv.org/abs/2510.15821).
|
| 163 |
+
|
| 164 |
+
- Subset of [Chronos Datasets](https://huggingface.co/datasets/autogluon/chronos_datasets) (excluding test portion of datasets that overlap with GIFT-Eval)
|
| 165 |
+
- Subset of [GIFT-Eval Pretrain](https://huggingface.co/datasets/Salesforce/GiftEvalPretrain)
|
| 166 |
+
- Synthetic univariate and multivariate data
|
| 167 |
+
|
| 168 |
+
|
| 169 |
+
## Citation
|
| 170 |
+
|
| 171 |
+
If you find Chronos-2 useful for your research, please consider citing the associated paper:
|
| 172 |
+
|
| 173 |
+
```
|
| 174 |
+
@article{ansari2025chronos2,
|
| 175 |
+
title = {Chronos-2: From Univariate to Universal Forecasting},
|
| 176 |
+
author = {Abdul Fatir Ansari and Oleksandr Shchur and Jaris Küken and Andreas Auer and Boran Han and Pedro Mercado and Syama Sundar Rangapuram and Huibin Shen and Lorenzo Stella and Xiyuan Zhang and Mononito Goswami and Shubham Kapoor and Danielle C. Maddix and Pablo Guerron and Tony Hu and Junming Yin and Nick Erickson and Prateek Mutalik Desai and Hao Wang and Huzefa Rangwala and George Karypis and Yuyang Wang and Michael Bohlke-Schneider},
|
| 177 |
+
year = {2025},
|
| 178 |
+
url = {https://arxiv.org/abs/2510.15821}
|
| 179 |
+
}
|
| 180 |
+
```
|
models/chronos-2/config.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"architectures": [
|
| 3 |
+
"Chronos2Model"
|
| 4 |
+
],
|
| 5 |
+
"chronos_config": {
|
| 6 |
+
"context_length": 8192,
|
| 7 |
+
"input_patch_size": 16,
|
| 8 |
+
"input_patch_stride": 16,
|
| 9 |
+
"max_output_patches": 64,
|
| 10 |
+
"output_patch_size": 16,
|
| 11 |
+
"quantiles": [
|
| 12 |
+
0.01,
|
| 13 |
+
0.05,
|
| 14 |
+
0.1,
|
| 15 |
+
0.15,
|
| 16 |
+
0.2,
|
| 17 |
+
0.25,
|
| 18 |
+
0.3,
|
| 19 |
+
0.35,
|
| 20 |
+
0.4,
|
| 21 |
+
0.45,
|
| 22 |
+
0.5,
|
| 23 |
+
0.55,
|
| 24 |
+
0.6,
|
| 25 |
+
0.65,
|
| 26 |
+
0.7,
|
| 27 |
+
0.75,
|
| 28 |
+
0.8,
|
| 29 |
+
0.85,
|
| 30 |
+
0.9,
|
| 31 |
+
0.95,
|
| 32 |
+
0.99
|
| 33 |
+
],
|
| 34 |
+
"time_encoding_scale": 8192,
|
| 35 |
+
"use_arcsinh": true,
|
| 36 |
+
"use_reg_token": true
|
| 37 |
+
},
|
| 38 |
+
"chronos_pipeline_class": "Chronos2Pipeline",
|
| 39 |
+
"d_ff": 3072,
|
| 40 |
+
"d_kv": 64,
|
| 41 |
+
"d_model": 768,
|
| 42 |
+
"dense_act_fn": "relu",
|
| 43 |
+
"dropout_rate": 0.1,
|
| 44 |
+
"feed_forward_proj": "relu",
|
| 45 |
+
"initializer_factor": 0.05,
|
| 46 |
+
"is_gated_act": false,
|
| 47 |
+
"layer_norm_epsilon": 1e-06,
|
| 48 |
+
"model_type": "t5",
|
| 49 |
+
"num_heads": 12,
|
| 50 |
+
"num_layers": 12,
|
| 51 |
+
"pad_token_id": 0,
|
| 52 |
+
"reg_token_id": 1,
|
| 53 |
+
"rope_theta": 10000.0,
|
| 54 |
+
"torch_dtype": "float32",
|
| 55 |
+
"transformers_version": "4.49.0",
|
| 56 |
+
"use_cache": true,
|
| 57 |
+
"vocab_size": 2
|
| 58 |
+
}
|
models/chronos-2/gitattributes
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
*.7z filter=lfs diff=lfs merge=lfs -text
|
| 2 |
+
*.arrow filter=lfs diff=lfs merge=lfs -text
|
| 3 |
+
*.bin filter=lfs diff=lfs merge=lfs -text
|
| 4 |
+
*.bz2 filter=lfs diff=lfs merge=lfs -text
|
| 5 |
+
*.ckpt filter=lfs diff=lfs merge=lfs -text
|
| 6 |
+
*.ftz filter=lfs diff=lfs merge=lfs -text
|
| 7 |
+
*.gz filter=lfs diff=lfs merge=lfs -text
|
| 8 |
+
*.h5 filter=lfs diff=lfs merge=lfs -text
|
| 9 |
+
*.joblib filter=lfs diff=lfs merge=lfs -text
|
| 10 |
+
*.lfs.* filter=lfs diff=lfs merge=lfs -text
|
| 11 |
+
*.mlmodel filter=lfs diff=lfs merge=lfs -text
|
| 12 |
+
*.model filter=lfs diff=lfs merge=lfs -text
|
| 13 |
+
*.msgpack filter=lfs diff=lfs merge=lfs -text
|
| 14 |
+
*.npy filter=lfs diff=lfs merge=lfs -text
|
| 15 |
+
*.npz filter=lfs diff=lfs merge=lfs -text
|
| 16 |
+
*.onnx filter=lfs diff=lfs merge=lfs -text
|
| 17 |
+
*.ot filter=lfs diff=lfs merge=lfs -text
|
| 18 |
+
*.parquet filter=lfs diff=lfs merge=lfs -text
|
| 19 |
+
*.pb filter=lfs diff=lfs merge=lfs -text
|
| 20 |
+
*.pickle filter=lfs diff=lfs merge=lfs -text
|
| 21 |
+
*.pkl filter=lfs diff=lfs merge=lfs -text
|
| 22 |
+
*.pt filter=lfs diff=lfs merge=lfs -text
|
| 23 |
+
*.pth filter=lfs diff=lfs merge=lfs -text
|
| 24 |
+
*.rar filter=lfs diff=lfs merge=lfs -text
|
| 25 |
+
*.safetensors filter=lfs diff=lfs merge=lfs -text
|
| 26 |
+
saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
| 27 |
+
*.tar.* filter=lfs diff=lfs merge=lfs -text
|
| 28 |
+
*.tar filter=lfs diff=lfs merge=lfs -text
|
| 29 |
+
*.tflite filter=lfs diff=lfs merge=lfs -text
|
| 30 |
+
*.tgz filter=lfs diff=lfs merge=lfs -text
|
| 31 |
+
*.wasm filter=lfs diff=lfs merge=lfs -text
|
| 32 |
+
*.xz filter=lfs diff=lfs merge=lfs -text
|
| 33 |
+
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
+
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
+
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
models/chronos-2/model.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:ddcda3c7508bf2528087723e98a20707cc04b7f370ae275a9fd88078ddba4f42
|
| 3 |
+
size 477930472
|
models/feature_importance_v2.csv
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Feature,Importance
|
| 2 |
+
MACD_CROSS,0.31674883
|
| 3 |
+
RSI,0.14755936
|
| 4 |
+
RSI_ZONE,0.12874237
|
| 5 |
+
EMA200_SIDE,0.075590245
|
| 6 |
+
MACD_SIGNAL,0.0396897
|
| 7 |
+
EMA_CROSS,0.036550965
|
| 8 |
+
MACD,0.03448979
|
| 9 |
+
ADX_TREND,0.030452669
|
| 10 |
+
IS_CLOSE_NOISE,0.023035046
|
| 11 |
+
HOUR,0.01999872
|
| 12 |
+
IS_OPEN_NOISE,0.019336423
|
| 13 |
+
ADX,0.0159953
|
| 14 |
+
ATR_NORM,0.015831186
|
| 15 |
+
CHRONOS_SPREAD,0.014848304
|
| 16 |
+
EMA200_DISTANCE,0.013593393
|
| 17 |
+
ATR,0.012044532
|
| 18 |
+
EMA200,0.008684688
|
| 19 |
+
EMA20,0.008623727
|
| 20 |
+
EMA50,0.008539548
|
| 21 |
+
CHRONOS_Q75,0.008275545
|
| 22 |
+
CHRONOS_Q25,0.0076590073
|
| 23 |
+
CHRONOS_RETURN,0.007072594
|
| 24 |
+
CHRONOS_AGREE,0.006638173
|
models/nifty_stage1_tradeable.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
models/nifty_stage2_direction.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
models/nifty_xgboost.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
models/nifty_xgboost_v2.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
requirements.txt
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
fastapi
|
| 2 |
+
uvicorn
|
| 3 |
+
python-multipart
|
| 4 |
+
python-dotenv
|
| 5 |
+
requests
|
| 6 |
+
numpy
|
| 7 |
+
pandas
|
| 8 |
+
torch
|
| 9 |
+
xgboost
|
| 10 |
+
ta
|