Metadata-Version: 2.4
Name: kronos-finance
Version: 0.1.2
Summary: Pythonic wrapper around the Kronos foundation model for OHLCV forecasting across any market
Author-email: lordxmen2k <lordxmen2k@users.noreply.github.com>
License-Expression: MIT
Project-URL: Homepage, https://github.com/lordxmen2k/kronos-finance
Project-URL: Repository, https://github.com/lordxmen2k/kronos-finance
Project-URL: Issues, https://github.com/lordxmen2k/kronos-finance/issues
Project-URL: Changelog, https://github.com/lordxmen2k/kronos-finance/blob/main/CHANGELOG.md
Project-URL: Citation, https://github.com/lordxmen2k/kronos-finance#citation
Keywords: kronos,finance,ohlcv,forecasting,foundation-model,time-series,quant
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Financial and Insurance Industry
Classifier: Intended Audience :: Science/Research
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering
Classifier: Topic :: Office/Business :: Financial :: Investment
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: torch>=2.0.0
Requires-Dist: numpy>=1.26
Requires-Dist: pandas>=2.2
Requires-Dist: einops>=0.8.1
Requires-Dist: huggingface_hub>=0.33.1
Requires-Dist: safetensors>=0.6.2
Requires-Dist: tqdm>=4.67.1
Requires-Dist: matplotlib>=3.9.3
Provides-Extra: cn
Requires-Dist: akshare>=1.18.0; extra == "cn"
Provides-Extra: global
Requires-Dist: yfinance>=0.2.60; extra == "global"
Provides-Extra: crypto
Requires-Dist: ccxt>=4.0.0; extra == "crypto"
Provides-Extra: qlib
Requires-Dist: pyqlib>=0.9.7; extra == "qlib"
Provides-Extra: ui
Requires-Dist: flask>=2.3; extra == "ui"
Requires-Dist: flask-cors>=4.0; extra == "ui"
Requires-Dist: plotly>=5.17; extra == "ui"
Provides-Extra: analysis
Requires-Dist: pandas-ta>=0.3.14b; extra == "analysis"
Requires-Dist: quantstats>=0.0.62; extra == "analysis"
Provides-Extra: finetune
Requires-Dist: pyqlib>=0.9.7; extra == "finetune"
Requires-Dist: pyyaml>=6.0; extra == "finetune"
Requires-Dist: comet-ml>=3.0; extra == "finetune"
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == "dev"
Requires-Dist: pytest-cov>=5.0; extra == "dev"
Requires-Dist: ruff>=0.6; extra == "dev"
Requires-Dist: mypy>=1.11; extra == "dev"
Requires-Dist: pre-commit>=4.0; extra == "dev"
Requires-Dist: ipython>=8.0; extra == "dev"
Provides-Extra: test
Requires-Dist: pytest-playwright>=0.5; extra == "test"
Requires-Dist: playwright>=1.47; extra == "test"
Provides-Extra: docs
Requires-Dist: mkdocs>=1.5; extra == "docs"
Requires-Dist: mkdocstrings[python]>=0.24; extra == "docs"
Requires-Dist: mkdocs-material>=9.5; extra == "docs"
Provides-Extra: all
Requires-Dist: akshare>=1.18.0; extra == "all"
Requires-Dist: yfinance>=0.2.60; extra == "all"
Requires-Dist: ccxt>=4.0.0; extra == "all"
Requires-Dist: pyqlib>=0.9.7; extra == "all"
Requires-Dist: flask>=2.3; extra == "all"
Requires-Dist: flask-cors>=4.0; extra == "all"
Requires-Dist: plotly>=5.17; extra == "all"
Requires-Dist: pandas-ta>=0.3.14b; extra == "all"
Requires-Dist: quantstats>=0.0.62; extra == "all"
Requires-Dist: pyyaml>=6.0; extra == "all"
Requires-Dist: comet-ml>=3.0; extra == "all"
Dynamic: license-file

# kronos-finance

[![](https://img.shields.io/pypi/v/kronos-finance.svg)](https://pypi.org/project/kronos-finance/)
[![](https://img.shields.io/pypi/pyversions/kronos-finance.svg)](https://pypi.org/project/kronos-finance/)
[![](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
[![](https://img.shields.io/badge/code%20style-ruff-000000.svg)](https://github.com/astral-sh/ruff)
[![](https://img.shields.io/badge/python-3.10%20|%203.11%20|%203.12-blue.svg)](#)

> Pythonic wrapper around the Kronos foundation model for OHLCV forecasting across any market.

## Built on Kronos

Kronos is the first open-source foundation model for financial candlesticks (K-lines),
by the [NeoQuasar team](https://github.com/shiyu-coder/Kronos), accepted at AAAI 2026,
MIT-licensed.

This package (`kronos-finance`) is a **wrapper** that turns the upstream research codebase
into a pip-installable library with a CLI, a dashboard, multi-source data loaders, and
comprehensive tests. All model code comes from the original project — see the
[Citation](#citation) section.

- Original repo: <https://github.com/shiyu-coder/Kronos>
- Paper: <https://arxiv.org/abs/2508.02739>
- Model zoo on HuggingFace: <https://huggingface.co/NeoQuasar>

## Use a virtual environment (recommended)

A virtual environment keeps your system Python clean and avoids the
`error: externally-managed-environment` (PEP 668) error on Ubuntu 23.04+,
macOS Homebrew Python, and Fedora 39+.

```bash
python -m venv .venv
source .venv/bin/activate          # macOS / Linux
# .venv\Scripts\activate           # Windows PowerShell
```

Every install command below assumes you've activated a venv first.

## Installation

```bash
pip install kronos-finance                       # core (CUDA-enabled PyTorch, ~800MB)
pip install kronos-finance[cn]                   # + AKShare for Chinese A-shares
pip install kronos-finance[global]               # + yfinance for global equities
pip install kronos-finance[crypto]               # + CCXT for crypto exchanges
pip install kronos-finance[qlib]                 # + Qlib for CN finetune data
pip install kronos-finance[ui]                   # + Flask + Plotly for the dashboard
pip install kronos-finance[analysis]             # + pandas-ta + quantstats
pip install kronos-finance[all]                  # everything above
```

The default install includes CUDA-enabled PyTorch and works on CPU or GPU.
For CPU-only or a specific CUDA version, see [Hardware](#hardware-cpu-vs-cuda)
below before installing.

Verify the install:

```bash
kronos --version
```

## Quickstart (60 seconds)

```python
from kronos_finance import load_kronos
from kronos_finance.data import load_ohlcv
import pandas as pd

df = load_ohlcv("AAPL", period="2y", interval="1d")
wrapper = load_kronos(model_id="small")
y_ts = pd.date_range(df["timestamps"].iloc[-1], periods=31, freq="1D")[1:]
pred = wrapper.predict(
    df=df[["open", "high", "low", "close", "volume", "amount"]].tail(400),
    x_timestamp=df["timestamps"].tail(400), y_timestamp=y_ts, pred_len=30,
)
print(pred.head())
```

## Features

- One-line predict on any market — US equities, CN A-shares, crypto, HK, JP, EU.
- Multi-source loaders — AKShare, yfinance, CCXT, Qlib, local CSV.
- Ticker auto-detection — type `"600519"` and AKShare is picked; type `"BTC/USDT"` and
  CCXT is picked.
- Bundled ticker catalog + user-extendable `~/.kronos/tickers.json`.
- CLI: `kronos predict`, `kronos backtest`, `kronos ui`, `kronos tickers`.
- Flask dashboard with candlestick chart, autocomplete, model selector, indicator overlay.
- Optional indicators (RSI, MACD, BBands) and HTML tearsheets (quantstats).
- 12 runnable examples + comprehensive docs + a 35-term glossary.

## How to predict any ticker in the world

| Market | Ticker format | Source | Install extra |
|---|---|---|---|
| US equity | `AAPL`, `MSFT`, `NVDA` | yfinance | `[global]` |
| US ETF | `SPY`, `QQQ`, `IWM` | yfinance | `[global]` |
| US index | `^GSPC`, `^DJI`, `^IXIC` | yfinance | `[global]` |
| CN A-share | `600519`, `000001`, `002594` | AKShare | `[cn]` |
| CN index | `000300`, `000905` | AKShare | `[cn]` |
| Crypto pair | `BTC/USDT`, `ETH/USDT` | CCXT (Binance default) | `[crypto]` |
| HK stock | `0700.HK`, `9988.HK` | yfinance | `[global]` |
| JP stock | `7203.T`, `6758.T` | yfinance | `[global]` |
| EU stock | `ASML.AS`, `SAP.DE` | yfinance | `[global]` |
| Local CSV | path to `.csv` | `csv_path=` | (core) |

The `source="auto"` default routes the ticker to the right loader based on its shape.

## CLI reference

```bash
kronos predict TICKER [--source auto] [--model small] [--interval 1d]
                     [--pred-len 30] [--lookback 400] [--export forecast.csv]
                     [--device cpu]
kronos batch TICKERS_FILE [--output ./out] [--model small] [--pred-len 30]
kronos backtest TICKER [--period 1y] [--interval 1d] [--source auto]
                      [--export tearsheet.html]
kronos ui [--host 127.0.0.1] [--port 5000] [--debug]
kronos tickers list
kronos tickers search QUERY [--market cn|us|crypto|...]
kronos tickers add SYMBOL NAME SOURCE [--exchange binance]
kronos --version
kronos --help
```

Examples:

```bash
kronos predict 600519 --source akshare
kronos predict BTC/USDT --source ccxt --exchange binance
```

Exit codes: `0` ok, `1` generic error, `2` usage error, `130` SIGINT (clean Ctrl+C).

## Python API

```python
from kronos_finance import load_kronos          # model
from kronos_finance.data import load_ohlcv       # data fetchers
from kronos_finance.tickers import catalog, search, add_user_ticker
from kronos_finance.analysis import (
    enrich_with_indicators, forecast_to_returns, make_tearsheet,
)
from kronos_finance import (                      # errors
    KronosFinanceError, TickerNotFoundError,
    DataSourceError, ModelLoadError, PredictionError, CatalogError,
)
```

Full reference: [`docs/API.md`](docs/API.md).

## Dashboard

Launch with `kronos ui` (default `http://127.0.0.1:5000`):

- Ticker input with autocomplete from the bundled + user catalog.
- Candlestick chart with historical in green/red and forecast in blue/purple.
- Model selector (mini / small / base with parameter counts).
- Source + interval pickers.
- Indicator overlay (RSI / MACD / BBands).
- Recent predictions history with CSV export.
- Dark / light theme toggle.

### Dashboard quickstart

1. `kronos ui` from your shell.
2. Open `http://localhost:5000` in any modern browser.
3. Type a ticker (e.g. `AAPL`, `600519`, `BTC/USDT`).
4. Click **Predict**.
5. The forecast paints on the chart; the metrics card shows the
   predicted close and expected return; the row appears in the
   Recent predictions table.
6. Click **CSV** on any row to download that prediction.

The dashboard is also a JSON API. You can drive it from any HTTP
client — see `examples/22_dashboard_api_reference.py` for curl,
Python `requests`, and JavaScript `fetch` examples for every endpoint.

Full tour (anatomy of the page, every UI element, every error message,
production deployment, extending the dashboard): [`docs/DASHBOARD.md`](docs/DASHBOARD.md).

## Examples

**Twenty-two** runnable examples covering beginner through advanced
workflows. Each one is a complete, runnable file with a docstring
explaining what it demonstrates, when to use it, what to expect, and
common pitfalls.

| #  | Scenario | Extra needed |
|---|---|---|
| 01 | Quickstart: predict AAPL 30 days | `[global]` |
| 02 | Multi-ticker US watchlist | `[global]` |
| 03 | CN A-share with column-rename walkthrough | `[cn]` |
| 04 | Crypto: BTC/USDT 5m from Binance | `[crypto]` |
| 05 | Batch sweep across many tickers | `[global]` |
| 06 | Indicators + quantstats HTML tearsheet | `[global,analysis]` |
| 07 | CLI: `kronos predict` from a shell script | `[global]` |
| 08 | CLI: `kronos backtest` from a shell script | `[global]` |
| 09 | Launch the Flask dashboard | `[ui]` |
| 10 | Save/load predictions: CSV, JSON, Parquet | `[global,analysis]` |
| 11 | Qlib-format CSV for the upstream finetune | `[qlib]` |
| 12 | Load a local Kronos checkpoint | (none) |
| 13 | Multi-timeframe: 1d + 1h + 5m on one ticker | `[global]` |
| 14 | Quantile bands via sample paths | `[global]` |
| 15 | Recursive (autoregressive) 1-year forecast | `[global]` |
| 16 | Adapt any CSV (English / Chinese / custom columns) | (none) |
| 17 | Pre-flight environment health check (CI-friendly) | (none) |
| 18 | Failure mode runbook (6 cases + recovery) | (none) |
| 19 | Daily cron-job style forecast with lockfile + logs | `[global]` |
| 20 | Forecast entirely from a local CSV (no network) | (none) |
| 21 | Portfolio construction: 3 weighting schemes | `[global]` |
| 22 | Dashboard JSON API reference (curl/Python/JS) | (none) |

Quick-pick by goal:

- *"Show me how to forecast one ticker"* → `examples/01_quickstart_predict.py`
- *"Run a daily forecast across my watchlist"* → `examples/19_cronjob_daily_forecast.py`
- *"Evaluate Kronos vs buy-and-hold"* → `examples/06_indicators_and_tearsheet.py`
- *"I have my own CSV / proprietary data"* → `examples/16_csv_with_arbitrary_columns.py` or `examples/20_local_csv_user_data.py`
- *"Troubleshoot my installation"* → `examples/17_healthcheck_environment.py` then `examples/18_failure_modes_and_recovery.py`
- *"Build a portfolio with Kronos signals"* → `examples/21_portfolio_kronos_weighting.py`

Each file starts with a docstring explaining what the example teaches.
Browse the index in [`examples/README.md`](examples/README.md).

**Want to wire Kronos into a trading strategy?** See
[Trading Strategy use cases](#trading-strategy-use-cases) for
backtesting frameworks, broker APIs (IBKR / Alpaca / ccxt), creative
uses (volatility sizing, options premium, pairs), live automation
patterns, and the disclaimers you need to read first.

## Trading Strategy use cases

> **⚠️ Disclaimer — read this before you trade real money.**
>
> This software is for **research, education, and software development**. Kronos
> is a statistical model — its outputs are *predictions*, not advice. The
> authors, contributors, and Kronos upstream maintainers are **not licensed
> financial advisors, brokers, or dealers**. Nothing in this package or
> repository constitutes a recommendation to buy, sell, or hold any
> security, derivative, cryptocurrency, or other instrument.
>
> **No warranty of profit.** Any trading strategy you build using these
> forecasts can — and will, eventually — lose money. Past model accuracy
> is not a guarantee of future returns. Backtesting is not the same as
> live trading because (a) you saw the historical data the model was
> trained on, (b) you didn't pay slippage, spreads, commissions, fees,
> funding, borrow, taxes, or market impact, (c) you assumed infinite
> liquidity and immediate fills. Real markets punish all three.
>
> **Regulatory.** Depending on where you live, running automated trading
> software against a brokerage may require a license, registration, or
> disclosure. You are solely responsible for understanding the law in
> your jurisdiction before you connect any of the code below to a real
> account. Examples below reference third-party libraries for *technical*
> capability — they are not endorsements.
>
> **Risk controls first.** Before any live automation: paper-trade it
> for ≥30 trading days, log every decision, set position-size limits,
> hard-stop daily-loss circuit breakers, and never risk more than you
> can afford to lose outright. If a strategy can't survive paper trading,
> it won't survive real trading.

So: read on for *what's possible*, build with care, and own the risks.

### From forecast to actionable strategy

A Kronos prediction is one input — not a complete strategy. A complete
strategy is the loop:

```
[Forecast]  ->  [Signal]  ->  [Sizing]  ->  [Execution]  ->  [Review]
     ^                                                      |
     +------------------------------------------------------+
```

This section walks through each ring of that loop with the libraries,
APIs, and patterns people actually use.

### 1. Signal generation — turning forecasts into trades

A Kronos forecast is a 30-bar (or whatever horizon) predicted close
trajectory. To turn that into a *trade signal*, you have many choices.
Each has different risk profiles.

| Signal logic | What it does | When to use it |
|---|---|---|
| **Direction** | Long if `pred_close > last_close`, short otherwise | First-pass prototype. Loses to spread + slippage. |
| **Threshold** | Long only if `expected_return > +X%` (e.g. +3%) | Skips weak forecasts; better hit rate. |
| **Magnitude-weighted** | Position size scales with `expected_return` (with cap) | "Conviction" sizing. Common in quant funds. |
| **Volatility-adjusted** | Compare predicted return to predicted path vol (Sharpe-like) | Avoids being long into a forecasted-messy period. |
| **Regime-conditional** | Long only when `RSI<70` AND `expected_return>+2%` | Reduces drawdown vs raw direction. |
| **Crossover** | Long when forecast close crosses predicted SMA from below | Trend-following flavor. |
| **Path consistency** | Long if the forecast is monotonic up (no flip-flops) | Filters "noise" predictions. |

A small pattern, copyable:

```python
import pandas as pd
from kronos_finance import load_kronos
from kronos_finance.data import load_ohlcv

wrapper = load_kronos(model_id="small", device="cpu")
df = load_ohlcv("AAPL", period="1y", interval="1d")
last_close = df["close"].iloc[-1]
y_ts = pd.date_range(df["timestamps"].iloc[-1], periods=31, freq="1D")[1:]
pred = wrapper.predict(
    df=df[["open", "high", "low", "close", "volume", "amount"]].tail(400),
    x_timestamp=df["timestamps"].tail(400),
    y_timestamp=pd.Series(y_ts, name="timestamps"),
    pred_len=30,
)
close_30d = pred["close"].iloc[-1]
expected_return = (close_30d - last_close) / last_close

# Magnitude-weighted long-only with a confidence threshold.
THRESHOLD = 0.03       # require >3% predicted return to engage
SIZE_CAP = 0.10        # never more than 10% of equity in this name
if expected_return > THRESHOLD:
    target_weight = min(expected_return, SIZE_CAP) * 1.0  # tune the multiplier
    side, weight = "BUY", float(target_weight)
elif expected_return < -THRESHOLD:
    side, weight = "SELL", float(min(-expected_return, SIZE_CAP))
else:
    side, weight = "HOLD", 0.0
print(f"{side} {weight:+.2%}")
```

> Don't trust the above numbers. They're a starting point. Backtest,
> paper-trade, and tune — don't trust a single backtest either; it
> overfits by construction.

### 2. Backtesting frameworks

You can wire the `wrapper.predict()` output into any standard Python
backtesting framework. The list below is ordered roughly from simplest
to most production-grade.

**Quick-and-dirty (you write the loop):** see `examples/05_batch_predict.py`
and `examples/06_indicators_and_tearsheet.py`. ~50 lines of Python, total
control, zero dependencies.

**`backtrader`** — event-driven, indicator-rich, mature.
```python
import backtrader as bt
from kronos_finance import load_kronos
from kronos_finance.data import load_ohlcv

class KronosSignal(bt.Strategy):
    params = dict(horizon=30, retrain_every=20, threshold=0.03)
    def next(self):
        if len(self.data) % self.p.retrain_every != 0:
            return
        df = self.data.p.dataname  # pre-fetched DataFrame
        # ... call wrapper.predict on df.iloc[:len(self.data)] ...
        # ... emit self.buy() / self.sell() based on expected_return ...

cerebro = bt.Cerebro()
cerebro.addstrategy(KronosSignal)
cerebro.adddata(load_ohlcv("AAPL", period="5y", interval="1d"))
cerebro.broker.setcash(100_000)
cerebro.run()
```

**`vectorbt`** — vectorized, fast, lots of plots. Best for parameter
sweeps because it's 100x faster than event-driven frameworks.

**`zipline-reloaded`** — the original Quantopian engine. Best if you're
porting an old Quantopian algo.

**`lean` / QuantConnect Lean (C# / Python)** — institutional-grade,
multi-asset, comes with a cloud research environment. Free for paper
trading.

**`freqtrade`** — dedicated to crypto. Has its own strategy DSL and a
backtesting CLI. Plug Kronos as a custom "predictor" source.

**`nautilus_trader`** — Rust core, Python API. Professional-grade
event-driven backtest + live. Designed for HFT-grade realism.

**`backtesting.py`** — minimal, well-documented, ~5-line strategies.
Perfect for "I just want to know if the idea is nonsense" sanity
checks.

> **The most common backtest bug is look-ahead bias.** Kronos is fit on
> history up to time `T`. To predict `T+1`, it must see *only* data up
> to and including `T`. Re-feeding the actual `T+1` close (even by
> accident via an off-by-one) gives you an oracle that doesn't exist
> live. The recursive-prediction pattern in
> `examples/15_recursive_predict.py` shows the safe way to chain
> multi-step predictions without leaking.

### 3. Live trading APIs (brokerage integrations)

Once a backtest is convincing, you can wire the same signal-generation
code to a live broker. *You* are responsible for testing in paper mode
first, complying with broker terms of service, and any regulatory
requirements in your jurisdiction.

| Broker / API | Asset classes | API style | Notes |
|---|---|---|---|
| **Interactive Brokers (`ib_insync`)** | Stocks, options, futures, FX, bonds worldwide | Python wrapper over TWS API | Mature. Supports paper trading. Read [IBKR docs](https://ibkrcampus.com/ibkr-api-page/). |
| **Alpaca (`alpaca-py`)** | US stocks + crypto | REST + WebSocket | Commission-free, paper-trading key is free in minutes. Great starting point. |
| **TD Ameritrade / Schwab** | US stocks + options | REST | Being deprecated — Schwab is the successor. OAuth flow. |
| **Tradier** | US stocks + options | REST | Developer-friendly. Free sandbox. |
| **Binance / Coinbase / Kraken** (via `ccxt`) | Crypto | REST + WebSocket | `ccxt` gives a uniform interface to 100+ exchanges. |
| **OANDA (v20 REST)** | FX, CFDs, metals | REST | Practice account available. |
| **Polygon.io** | US stocks, options, forex, crypto | REST + WebSocket | Real-time + historical ticks. Free tier limited. |
| **Tradegate / DEGIRO / IBKR EU** | EU stocks | varies | For European markets. |

A minimal Alpaca example to show the wiring (paper trading only — do
NOT use live keys until you've tested):

```python
# pip install alpaca-py
from alpaca_trade_api.rest import REST, TimeFrame
from kronos_finance import load_kronos
from kronos_finance.data import load_ohlcv

API_KEY = "PAPER_KEY_HERE"          # <-- from alpaca.markets paper account
API_SECRET = "PAPER_SECRET_HERE"    # <-- never commit real keys
BASE_URL = "https://paper-api.alpaca.markets"

api = REST(API_KEY, API_SECRET, BASE_URL)

# 1. Get Kronos forecast for a ticker
wrapper = load_kronos(model_id="small", device="cpu")
df = load_ohlcv("AAPL", period="1y", interval="1d")
pred = wrapper.predict(...)
last_close = float(df["close"].iloc[-1])
expected = (float(pred["close"].iloc[-1]) - last_close) / last_close

# 2. Decide side + size from the forecast
if expected > 0.03:
    side, qty = "buy", 10
elif expected < -0.03:
    side, qty = "sell", 10
else:
    side, qty = None, 0

# 3. Submit a paper order
if side:
    api.submit_order(
        symbol="AAPL", qty=qty, side=side,
        type="market", time_in_force="day",
    )
```

> **Do not run this code with live keys without weeks of paper trading.**
> The model can (and will) make confident wrong predictions. Position
> sizing, stop-losses, daily-loss circuit breakers, and broker kill
> switches must be in place first.

### 4. Creative non-obvious uses

Beyond "buy if up, sell if down," Kronos predictions have uses that
don't fit the simple long/short template:

- **Volatility-aware position sizing.** Use the *width* of the
  predicted distribution (e.g., P90-P10 from `examples/14_quantile_bands.py`)
  to *shrink* positions on uncertain forecasts and *enlarge* on
  confident ones — the opposite of how most retail traders size.
- **Options premium selling.** When Kronos forecasts a flat-to-down
  trajectory, sell covered calls; when it forecasts a strong up move,
  sell cash-secured puts. The signal isn't direction — it's *expected
  move vs implied vol*. If Kronos's predicted range is tighter than
  the options market's implied vol, premium is overpriced.
- **Pairs / stat-arb.** Forecast two correlated instruments (e.g.,
  `KO` and `PEP`, `BTC` and `ETH`). When the spread's predicted move
  diverges from the realized spread, you have a mean-reversion signal.
  Pair trading is a separate skill; Kronos is just the forecast leg.
- **Event-driven reaction.** Earnings, Fed meetings, CPI releases.
  Run Kronos *before* the event to establish a "no-event" baseline,
  run it again *after* the event with the new price action, and trade
  the gap between the two.
- **Crypto funding-rate arb.** When Kronos forecasts a price move
  *against* the direction implied by perpetual funding, take the
  opposite side of the perp (and delta-hedge with spot). Funding-rate
  info isn't in Kronos — you combine two models.
- **Slack / Discord / Telegram bot.** Wrap `wrapper.predict()` in a
  small bot that posts the daily forecast for your watchlist into a
  private channel. No execution — just signal. Many quant shops use
  exactly this pattern as a "second opinion" before clicking buy.
- **Risk dashboard.** Run Kronos daily on every position you hold and
  alert if the *predicted* drawdown over the next 30 days exceeds
  your real position's loss tolerance. You don't have to *trade* on
  the forecast — you can use it as an early-warning system for the
  positions you already have.
- **Macro overlay.** Run Kronos on broad indexes (SPY, QQQ, BTC, gold
  ETF) once a day and use the *aggregate* expected return as a
  market-timing filter — be long only when the broad-market forecast
  is positive, raise cash otherwise. Crude but historically robust.
- **News corroboration.** Pair Kronos with a news-sentiment model
  (e.g., `finbert`, `newsapi`). When both models agree (news says
  bullish + Kronos says bullish), the conviction is higher than
  either alone. When they disagree, that's an opportunity *or* a
  warning, depending on which one is your edge.

### 5. Live automation patterns

A daily forecast that fires automatically (cron / Task Scheduler) is
the most common production pattern. See
`examples/19_cronjob_daily_forecast.py` for the basics. To go further:

- **Multi-ticker fan-out with retry.** Wrap each forecast in
  try/except + exponential backoff. One bad ticker (rate-limited,
  delisted) should not stop the rest.
- **Slack/email on anomaly.** If a forecast's expected return moves
  >3% from yesterday's prediction, send an alert. The model's
  *change* is often more informative than its *level*.
- **Health checks before orders.** Run the health-check example
  (`examples/17_healthcheck_environment.py`) as a precondition. If
  CUDA is broken or HF cache is corrupt, halt the auto-trader.
- **Audit log every order.** Persist *every* order decision (input
  DataFrame, prediction, signal logic, sizing, timestamp, account
  state) to a JSONL file. When (not if) you need to debug a bad day,
  the audit log is the only way.
- **Daily-loss circuit breaker.** Track cumulative P&L for the day;
  if it's worse than `-X%` of starting equity, halt the bot for the
  rest of the day. This is more important than the strategy itself.
- **Idempotency keys.** Network retries can submit duplicate orders.
  Use idempotency keys (Alpaca, IBKR both support them) keyed on
  `(ticker, date, side, qty)`.
- **Read-only mode first.** For the first 30 days, run the bot with
  execution disabled — log what it *would* have done. Compare against
  your paper broker's actual fill prices. Only enable execution when
  the read-only logs match the broker.

### 6. Tools that pair well with Kronos

You don't need to write everything from scratch. These composable
pieces each fill a gap.

- **`vectorbt.pro`** — paid, but the only Python backtester that runs
  a 10-year tick-level crypto strategy in seconds. Worth it for
  serious sweeps.
- **`quantstats`** — already a dep of `[analysis]`. Pull-lev, factor
  analysis, HTML tearsheets. Use it to compare strategy variants.
- **`riskfolio-lib`** — portfolio optimization (HRP, mean-variance,
  Black-Litterman). Combine Kronos expected returns with
  riskfolio-lib's covariance model for a complete portfolio
  construction stack.
- **`empyrical`** (deprecated) / **`pyfolio-reloaded`** — risk and
  performance metrics.
- **`pandas-ta`** — already a dep. ~130 indicators. Don't reinvent
  RSI / MACD / Bollinger / ATR / OBV.
- **`yfinance`** — already a dep. Free OHLCV for US/CN/HK tickers
  with no API key.
- **`akshare`** — already a dep. CN A-share data.
- **`ccxt`** — already a dep. 100+ crypto exchanges.
- **`alpaca-trade-api` / `ib_insync` / `binance`** — broker APIs as
  listed above.
- **`great-expectations`** — schema validation on input data. Catches
  "today's data has NaN, the model silently predicted NaN, and the
  bot bought 10,000 shares of garbage." Cheap insurance.
- **`pydantic`** — already a dep. Validate signal outputs before
  they hit the broker.
- **`apscheduler` / `croniter`** — robust scheduling if you don't want
  raw cron.

### 7. What "good" looks like

After 6 months of running a Kronos-based strategy on a paper account,
expect:

- **Win rate**: 50-60% on daily-bar direction. Higher than random but
  lower than naive backtests suggest.
- **Sharpe ratio**: 0.5-1.5 after costs, if you've tuned the signal
  logic well. Realistic, not glamorous.
- **Max drawdown**: 10-25% on the underlying, regardless of strategy.
  The model doesn't prevent drawdowns; it filters which *direction*
  you take them.
- **Turnover**: 1-5 trades/day across a 10-ticker watchlist if you
  retrain daily. Costs matter: even $0.005/share adds up at 1k
  shares/day.
- **Drift**: the model's accuracy will *slowly degrade* over months
  as market regime shifts. Plan to re-evaluate the signal logic
  quarterly.

If your backtest claims >2.0 Sharpe, >70% win rate, and <5% drawdown
on daily bars, it has a bug. Go find it.

### 8. Where to learn more

- `examples/05_batch_predict.py` — multi-ticker sweep
- `examples/06_indicators_and_tearsheet.py` — indicators + quantstats
- `examples/14_quantile_bands.py` — distribution-aware sizing
- `examples/19_cronjob_daily_forecast.py` — daily automation
- `examples/21_portfolio_kronos_weighting.py` — three weighting schemes
- Backtesting frameworks: see the table above; start with
  `backtesting.py` for sanity checks, then `vectorbt` for sweeps,
  then `backtrader` for realism.
- Live execution: start with **Alpaca paper trading** (free API key,
  5-minute setup) before touching any real-money broker.

And again: this is research software. Don't risk what you can't afford
to lose. The first version of your strategy should run in paper mode
for at least 30 trading days before you ever let it touch a live
account.

## Troubleshooting

The most common pitfalls — full list in [`docs/TROUBLESHOOTING.md`](docs/TROUBLESHOOTING.md):

- **`error: externally-managed-environment`** — you're trying to `pip install` into
  system Python. Use a venv (see the section at the top of this README).
- **Model download stalls / 401 from HuggingFace** — set `HF_TOKEN` or run
  `huggingface-cli login`.
- **CUDA version mismatch** — install PyTorch from the matching CUDA index URL.
- **yfinance rate limit** — switch to `auto` source or add `period=` to limit.
- **AKShare returns empty** — the ticker may have delisted. Try yfinance with
  `600519.SS`.
- **Playwright browser missing** — `playwright install --with-deps chromium`.
- **`max_context` exceeded** — reduce `lookback` or use `Kronos-mini` (2048 context).
- **Tz-aware timestamp warning** — convert to UTC and drop the tz before passing in.
- **PermissionError on Windows** — run your terminal as Administrator or use a venv.

## Hardware (CPU vs CUDA)

Kronos runs on **both CPU and CUDA GPUs**. The default `pip install kronos-finance`
installs the standard PyPI `torch` wheel, which is **CUDA-enabled by default**
and works on either. There's no separate "GPU version" of `kronos-finance`.

You pick the device at runtime via `--device` (CLI) or `device=` (Python):

```bash
kronos predict AAPL --device cpu       # default; works everywhere
kronos predict AAPL --device cuda     # first GPU
kronos predict AAPL --device cuda:0   # specific GPU
```

```python
wrapper = load_kronos(model_id="small", device="cuda")
```

### Which device should I use?

| Model | Params | CPU latency (30-step forecast) | CUDA latency | Recommendation |
|---|---|---|---|---|
| `Kronos-mini`  | 4.1M   | ~2s   | ~0.2s | Either works |
| `Kronos-small` | 24.7M  | ~5s   | ~0.3s | Either works |
| `Kronos-base`  | 102.3M | ~15s  | ~1s   | CUDA recommended |

### Memory

- **CPU**: ~1 GB RAM for `small`, +500 MB for `base`.
- **CUDA**: ~1 GB VRAM for `small`, ~2 GB VRAM for `base`. An RTX 3060 (12 GB) is plenty.

### Pinning your CUDA version

If you have an NVIDIA GPU, install PyTorch from the matching CUDA index URL
**before** installing kronos-finance to control which CUDA toolkit version is
bundled:

```bash
# CUDA 12.1 — match your NVIDIA driver
pip install torch --index-url https://download.pytorch.org/whl/cu121
pip install kronos-finance[global]

# CUDA 11.8
pip install torch --index-url https://download.pytorch.org/whl/cu118
pip install kronos-finance[global]

# CPU-only (smaller download, ~200 MB instead of ~800 MB)
pip install torch --index-url https://download.pytorch.org/whl/cpu
pip install kronos-finance[global]
```

### Apple Silicon (M1/M2/M3)

`pip install kronos-finance` on Apple Silicon uses PyTorch's MPS backend
automatically. Pass `--device mps` in the CLI or `device="mps"` in the API.

### Common CUDA errors

- **`CUDA error: no kernel image is available`** — your PyTorch CUDA version
  doesn't match your NVIDIA driver. Reinstall PyTorch from the matching index
  URL above.
- **`CUDA out of memory`** — your GPU is too small. Use `Kronos-mini` or
  reduce `lookback`. On CPU there's no such limit (just slower).
- **`CUDA unavailable but requested`** — your install doesn't have CUDA
  support, or no GPU is visible. `nvidia-smi` to check.

## How it works

```
Ticker (e.g. "AAPL")
    │
    ▼  load_ohlcv() auto-detects source -> yfinance
pd.DataFrame [timestamps, open, high, low, close, volume, amount]
    │
    ▼  load_kronos() downloads Kronos-small from HuggingFace
KronosWrapper (model + tokenizer + predictor)
    │
    ▼  wrapper.predict() runs autoregressive Transformer
pd.DataFrame [predicted OHLCV]
    │
    ▼  analysis: indicators + backtest -> HTML tearsheet
```

## Performance & limits

| Setting | Default | Cap | Note |
|---|---|---|---|
| `pred_len` | 30 | 1000 (CLI), no cap in API | Larger = slower inference |
| `lookback` | 400 | 512 (small/base/large), 2048 (mini) | Auto-truncated |
| `sample_count` | 1 | 20 | Quantile bands need >1 |
| Memory (CPU, small) | ~1GB | — | +500MB for base |
| Memory (CUDA, base) | ~2GB VRAM | — | RTX 3060+ recommended |
| Latency (CPU, 30-step, 1 ticker) | ~5s | — | ~1s on CUDA |

## Development

```bash
git clone https://github.com/lordxmen2k/kronos-finance.git
cd kronos-finance
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev,test,ui]"
pytest                         # unit + CLI tests
ruff check src/                # lint
```

See [`docs/CONTRIBUTING.md`](docs/CONTRIBUTING.md).

## Citation

If you use this in research, please cite the original Kronos paper:

```bibtex
@inproceedings{kronos2026,
  title  = {Kronos: A Foundation Model for the Language of Financial Markets},
  author = {Shi, Yu and others},
  booktitle = {AAAI},
  year   = {2026},
}
```

And this wrapper:

```bibtex
@software{kronos_finance,
  author = {lordxmen2k},
  title  = {kronos-finance: A Python wrapper for Kronos},
  year   = {2026},
  url    = {https://github.com/lordxmen2k/kronos-finance}
}
```

## License

MIT — see [`LICENSE`](LICENSE) for the full text. The original Kronos project is also
MIT; see `src/kronos_finance/_vendor/LICENSE_KRONOS` for the vendored upstream license.

## Acknowledgements

- The [NeoQuasar team](https://github.com/shiyu-coder/Kronos) for the Kronos
  foundation model.
- [HuggingFace](https://huggingface.co/) for model hosting.
- [AKShare](https://github.com/akfamily/akshare), [yfinance](https://github.com/ranaroussi/yfinance),
  [CCXT](https://github.com/ccxt/ccxt), [Qlib](https://github.com/microsoft/qlib) — the
  data layer.
- [pandas-ta](https://github.com/twopirllc/pandas-ta), [quantstats](https://github.com/ranaroussi/quantstats) — analysis.
- [Plotly](https://plotly.com/), [Flask](https://flask.palletsprojects.com/) — the dashboard.

## Glossary

See [`docs/INSTALL.md#glossary`](docs/INSTALL.md#glossary) for the full 35-term glossary.
A quick index of the most important ones:

- **OHLCV** — Open, High, Low, Close, Volume. The five columns Kronos expects.
- **K-line** — Chinese term for candlestick; same thing.
- **Context length / max_context** — maximum past bars the model can see (512 for
  small/base/large; 2048 for mini).
- **AR / autoregressive** — generates outputs one step at a time.
- **Tokenizer** — converts continuous OHLCV to discrete tokens before the Transformer.
- **Sample count** — number of forecast paths to draw; more = smoother quantile band.
- **Tearsheet** — one-page performance report; quantstats generates HTML.
- **Nucleus sampling (top-p)** — sampling from smallest token set whose cumulative prob ≥ p.
- **Temperature (T)** — sampling temperature; T<1 conservative, T>1 exploratory.
- **Quantile band** — uncertainty interval drawn when `sample_count > 1`.
- **PEP 668** — Python spec marking system Python as externally managed; use venv.
- **Twine** — `twine upload dist/*` publishes to PyPI.
- **Wheel (.whl)** — built distribution format.
