naga-runtime
Run trained NAGA trading models live from MetaTrader 5, from Python, or from any web dashboard over a secure JSON API — with a built-in live dashboard.
naga-runtime is the distribution package for models produced by the NAGA-HGT training system. It takes a model
folder (model.safetensors + config.json), accepts ordinary market data (OHLC bars, news headlines, economic
calendar events, account state) and returns a complete, structured decision for XAUUSD, EURUSD and GBPUSD:
action, confidence, position size, stop-loss / take-profit, maximum holding time, and multi-horizon price forecasts.
It contains no training code and never asks for API keys of any kind. A broker connection is optional: live mode reads MetaTrader 5 read-only (it never places, modifies or closes orders).
pip install ".[all]"
naga-runtime live C:\path\to\NAGA_model --open # MT5 + news + calendar → model → dashboard in your browser
Risk notice. Model outputs are statistical estimates, not financial advice. Trading leveraged products carries a high risk of loss. Validate every model on a demo account before risking capital.
Contents
- Features
- Installation
- Live mode (MetaTrader 5)
- Quick start (Python)
- Model folder
- Input reference
- Output reference
- Command-line interface
- HTTP API for dashboards
- Client libraries
- Security
- Performance
- Troubleshooting
- Versioning and compatibility
Features
| One-line loading | NagaModel.load("NAGA_model") — CPU or GPU selected automatically. |
| Flexible input | pandas DataFrames, dicts of lists, or plain row lists; epoch seconds, milliseconds, ISO strings or datetime. |
| Complete output | Action + probabilities, confidence, lots, SL/TP (distance and price), max hold, forecasts for 5 / 15 / 60 / 240 minutes, expected favourable/adverse excursion, volatility outlook, market-session status. |
| Identical to training | The architecture, features and graph builder are generated from the training code; a parity test proves bit-identical outputs. |
| No lookahead by design | Bars, news and events after the decision time are ignored automatically; future economic "actual" values are hidden. |
| Secure distribution | SHA-256 integrity manifest, optional AES-256-GCM encryption of the weights (decrypted in memory only). |
| Live mode in one command | naga-runtime live MODEL reads bars, quotes, account and positions from MetaTrader 5 (read-only), free RSS headlines and the economic calendar, and re-decides on every bar close, high-impact headline, sharp price move or position change. |
| Built-in dashboard | Open http://localhost:8000 — live decisions, probabilities, trade plan, forecasts, upcoming events and headlines; light and dark themes; works on phones. |
| Dashboard-ready API | Bearer-token auth, CORS allow-list, rate limiting, size limits, live streaming (Server-Sent Events), no stack traces leaked. |
| Client libraries | NagaClient for Python and clients/naga-client.mjs for browsers / Node.js — info, latest, predict, stream. |
| Low latency | Bar features are computed once per new bar; quote/account refreshes cost a single forward pass. Model warm-up at start. |
| Built-in guards | New entries are blocked during abnormal spreads (> 3× normal) and after a 10 % daily loss, mirroring the live trading engine. |
| Zero extra services | Pure Python + PyTorch. No database, no message queue, no web framework required. |
| Cross-platform | Windows, Linux and macOS; Python 3.10 – 3.13 (MetaTrader 5 live mode: Windows). |
Installation
python -m venv .venv
# Windows (PowerShell): .\.venv\Scripts\Activate.ps1
# Linux / macOS: source .venv/bin/activate
# 1) PyTorch — pick the build for your machine (https://pytorch.org/get-started/locally/)
pip install torch --index-url https://download.pytorch.org/whl/cu128 # NVIDIA GPU
# pip install torch # CPU only
# 2) naga-runtime (from this folder, or from a wheel you received)
pip install ".[all]" # everything: encryption + MetaTrader 5 (Windows)
# or pick: pip install . | pip install ".[secure]" | pip install ".[mt5]"
Check the computer and the model in one step:
naga-runtime doctor path/to/NAGA_model
doctor reports Python, PyTorch, GPU, optional packages, the MetaTrader 5 terminal, the news and calendar feeds, the
model files (integrity + load) and the decision latency, with a fix for every problem it finds.
Live mode (MetaTrader 5)
- Open MetaTrader 5 and log in (demo account recommended).
- Start the runtime:
$env:NAGA_API_TOKEN = "choose-a-long-random-secret" # optional; otherwise a token is generated and printed
naga-runtime live C:\path\to\NAGA_model --open
- The dashboard opens in your browser — paste the token once.
What live mode does:
| Step | Detail |
|---|---|
| Market data | M5 / M15 / H1 history (exactly what the model needs), live bid/ask, account equity and open positions from MT5. Broker server time is converted to UTC automatically. |
| Symbols | Detected automatically, including broker suffixes (XAUUSDm, EURUSD.r, GOLD). Override with --symbols XAUUSD=XAUUSDm,EURUSD=EURUSDm,GBPUSD=GBPUSDm. |
| News | Free public RSS feeds (central banks, financial news), filtered to USD / EUR / GBP / gold. Refreshed every 2 minutes. |
| Calendar | This week's economic calendar (ForexFactory public feed), refreshed every 30 minutes. |
| Decisions | On every M5 bar close, high-impact headline, price move ≥ 0.8 × ATR, position change, and every --refresh seconds (default 30). |
| Account tracking | Peak and start-of-day equity are remembered across restarts (runtime_state.json in the model folder). |
| Output | Dashboard at /, GET /v1/latest, live stream GET /v1/stream, optional --journal predictions.jsonl. |
| Resilience | Reconnects to MT5 automatically; news/calendar outages never stop decisions; errors appear in /v1/status. |
Settings can also come from a .env file in the current folder (the same file the training system uses). Only these
keys are read: NAGA_*, MT5_LOGIN, MT5_PASSWORD, MT5_SERVER, MT5_TERMINAL_PATH, SYMBOL_MAP, RSS_FEEDS.
MT5_* are needed only to log in to a specific account; otherwise the open terminal is used.
Useful options: --port 8000, --refresh 30, --no-news, --no-calendar, --journal FILE, --floor 10,
--utc-offset 3 (only if automatic server-time detection is wrong), --device cpu.
Windows shortcut: scripts\start-live.ps1 -Model C:\path\to\NAGA_model.
Live mode in your own Python code:
from naga_runtime import NagaModel
from naga_runtime.feeds import MT5Feed, NewsFeed, CalendarFeed
from naga_runtime.live import LiveRunner
runner = LiveRunner(NagaModel.load("NAGA_model"), MT5Feed(), NewsFeed(), CalendarFeed())
runner.subscribe(lambda p: print(p.decisions["XAUUSD"].action, p.decisions["XAUUSD"].confidence))
runner.run_forever()
Quick start (Python)
from naga_runtime import NagaModel
model = NagaModel.load("NAGA_model") # device="auto" → CUDA when available, else CPU
prediction = model.predict(
bars={
"XAUUSD": {"M1": xau_m1_df}, # completed bars, oldest → newest
"EURUSD": {"M1": eur_m1_df}, # M5/M15/H1 are built automatically from M1
"GBPUSD": {"M1": gbp_m1_df}, # (or pass them explicitly: {"M5": ..., "M15": ..., "H1": ...})
},
news=[{"time": "2026-10-30T13:31:00Z", "title": "Fed signals patience on rate cuts"}],
events=[{"time": "2026-10-30T12:30:00Z", "name": "US CPI YoY", "currency": "USD",
"impact": "high", "actual": 3.1, "forecast": 3.0, "previous": 2.9}],
account={"equity": 1000},
)
for symbol, d in prediction.decisions.items():
print(symbol, d.action, f"{d.confidence:.0%}", d.lots, d.sl_price, d.tp_price)
payload = prediction.to_dict() # plain JSON-serialisable dict
A complete runnable script is in examples/predict_example.py.
Fast refreshes. predict() = prepare() + decide(). prepare() computes the bar features (the expensive part);
decide() is one forward pass. Between bar closes, keep the prepared state and call decide() with fresh quotes,
account and positions:
state = model.prepare(bars, news, events) # once per new M5 bar
pred = model.decide(state, account=acc, positions=pos, quotes=q, now=time.time()) # as often as you like
model.update_context(state, news=latest_news) # new headlines without recomputing bars
Model folder
| File | Purpose |
|---|---|
model.safetensors |
Weights in the open safetensors format (contains numbers only — no executable code). |
model.safetensors.enc |
Encrypted weights (instead of the file above) — see Security. |
config.json |
Architecture, version, training step, selected confidence threshold and validation results. |
manifest.json |
SHA-256 of every file; checked automatically on load. |
The training system writes this folder automatically (runs/NAGA_model/) or on demand with
python naga_hgt.py export. Only fully trained models (stage ppo) are accepted.
Input reference
bars (required)
{"XAUUSD": {...}, "EURUSD": {...}, "GBPUSD": {...}} — all three symbols are required because the model reasons
across markets (for example, separating US-dollar moves from gold-specific moves).
Each symbol maps timeframe → bars. Supported timeframes: M1, M5, M15, H1.
| Column | Required | Aliases | Notes |
|---|---|---|---|
time |
✔ | t, timestamp, datetime, date |
Bar open time. Epoch seconds/milliseconds, ISO-8601 string or datetime. Naive times are treated as UTC. |
open, high, low, close |
✔ | o, h, l, c |
Bid prices. |
tick_volume |
v, volume, tickvol |
Number of ticks (as provided by MetaTrader). | |
spread |
sp |
Price units (e.g. 0.00012 for EURUSD, 0.25 for XAUUSD). Defaults are used when missing. |
Accepted containers: pandas.DataFrame, dict of equal-length lists/arrays, or a list of rows
[time, open, high, low, close, tick_volume, spread].
History needed. The model looks back 2 days of M5 (plus 1 week of M5 for the live cross-market correlation), 4 days of M15 and 20 days of H1. Provide at least
30 calendar days (≈ 22 trading days) of M1 or M5 data (or M15/H1 explicitly) for full-quality results. Shorter history still works —
missing context is masked — but prediction.warnings will say so.
Completed bars only. Pass bars that have closed. When now is given, any bar not yet closed at now is dropped
automatically.
MetaTrader server time. Convert broker server time to UTC before calling the model. Many brokers use
New York time + 7 hours; some (for example Exness) use UTC. MT5Feed and live mode do this automatically.
Broker contract data (optional): symbols_info={"XAUUSD": {"point": 0.01, "contract": 100}, ...} makes lot sizing
use your broker's exact contract sizes. Live mode supplies it automatically.
news (optional)
List of headlines: {"time", "title", "body"?, "source"?, "sentiment"?, "currencies"?, "delayed"?}.
Any language is accepted (the text encoder reads raw UTF-8 bytes). The most recent 36 items from the last 72 hours
are used; items timestamped after now are ignored.
events (optional)
Economic calendar: {"time", "name", "currency", "impact" ("high"|"medium"|"low"|1–3), "actual"?, "forecast"?, "previous"?}.
Events within ±24 hours are used. For events still in the future, actual is ignored even if supplied.
account (optional)
{"equity", "margin"?, "peak_equity"?, "day_start_equity"?, "floor"?} (USD). With equity the response includes
suggested lots that respect the equity floor (default 10 USD): if every open position and the new one hit their
stop-loss at once, equity would still stay above the floor.
positions (optional)
Open positions per symbol: {"side": "long"|"short", "lots", "entry", "sl", "tp", "open_time", "max_hold_minutes"?, "mfe"?, "mae"?, "profit"?}.
quotes (optional)
Live prices between bar closes: {"EURUSD": {"bid": 1.0815, "ask": 1.0816}, ...}. Improves intra-bar decisions, uses
the real spread for stop placement and entry price (ask for LONG, bid for SHORT), and blocks new entries when the
spread is more than 3× its normal level.
now (optional)
Decision time (any accepted time format). Defaults to the close of the latest M5 bar.
Output reference
predict() returns a Prediction; prediction.to_dict() / to_json() give plain JSON.
{
"time": 1793376000, // decision time (UTC epoch seconds)
"model_version": "2.3.1",
"latency_ms": 41.7,
"bar_time": 1793375700, // close time of the newest completed M5 bar used
"warnings": [], // data-quality and guard notes (short history, daily loss limit, ...)
"decisions": {
"EURUSD": {
"action": "LONG", // HOLD | LONG | SHORT | CLOSE
"confidence": 0.62, // probability of the chosen action
"probabilities": {"HOLD": 0.31, "LONG": 0.62, "SHORT": 0.05, "CLOSE": 0.02},
"tradable": true, // market open and not within 15 minutes of a close
"market_note": "", // e.g. "UK holiday", "rollover", "weekend"
"last_close": 1.08123, "atr": 0.00031,
"size_fraction": 0.42, // 0–1 of the lot cap for the account size
"lots": 0.02, // null without account equity, 0 when the floor forbids a trade
"sl_distance": 0.00084, "tp_distance": 0.00151,
"sl_price": 1.08039, "tp_price": 1.08274,
"max_hold_minutes": 95.0,
"modify_sl_tp": false, // open position: move SL/TP to the distances above
"forecasts": [ // 5, 15, 60 and 240 minutes ahead
{"minutes": 60, "median_price": 1.08141, "low_price": 1.08010, "high_price": 1.08277,
"median_pct": 0.017, "low_pct": -0.104, "high_pct": 0.142}
],
"volatility_ratio": 1.12, // expected next-hour volatility ÷ current ATR level
"mfe_1h": 0.00062, "mae_1h": 0.00041, // expected best / worst excursion (price units)
"mfe_4h": 0.00118, "mae_4h": 0.00087,
"price": 1.08127, // live mid price (quotes) or last close
"spread": 0.00011, // live spread or last bar spread
"has_position": false
}
}
}
Interpreting the decision
HOLDwith no position = stay flat ·LONG/SHORTwith an opposite position = close and reverse ·CLOSE= exit the open position.tradable: falsemeans new entries are not allowed right now;market_notesays why (weekend, holiday, rollover, abnormally wide spread). After a 10 % loss since the start of the day (account.day_start_equity), new entries are blocked and a warning is added.- The model applies a confidence threshold selected on validation data during training (
min_confidenceinmodel.info): below it, new entries becomeHOLD. lots,sl_priceandtp_priceare suggestions. Your execution layer must still respect broker limits (minimum stop level, volume step, margin).
Command-line interface
naga-runtime live MODEL [--open --symbols --refresh --no-news --no-calendar --journal ...] real time from MT5
naga-runtime serve MODEL [--open --host --port --token --cors --rate --no-dashboard] API + dashboard
naga-runtime doctor [MODEL] check this computer, the feeds and the model
naga-runtime info MODEL model details (version, parameters, validation results)
naga-runtime predict MODEL request.json one prediction (same JSON as the HTTP API); "-" reads stdin
naga-runtime bench MODEL [request.json] latency: full predict vs. quote refresh (synthetic data by default)
naga-runtime verify MODEL check files against manifest.json
naga-runtime manifest MODEL (re)create manifest.json
naga-runtime encrypt MODEL [--key | NAGA_MODEL_KEY] [--keep-plain]
Common options: --device auto|cpu|cuda|cuda:N, --key (prefer the NAGA_MODEL_KEY environment variable),
--env-file PATH (default .env), -v for debug logging.
HTTP API for dashboards
export NAGA_API_TOKEN="a-long-random-secret" # PowerShell: $env:NAGA_API_TOKEN="..."
naga-runtime serve NAGA_model --port 8000 --cors https://dashboard.example.com
| Method | Path | Auth | Description |
|---|---|---|---|
GET |
/ |
— (page) | Built-in live dashboard; its data calls use the token |
GET |
/health |
— | Liveness probe → {"status": "ok"} |
GET |
/v1/info |
Bearer | Model information |
GET |
/v1/status |
Bearer | Live runner, MT5/news/calendar status, upcoming events, recent headlines, recent errors |
GET |
/v1/latest |
Bearer | Most recent prediction (404 until the first one) |
GET |
/v1/history?limit=100 |
Bearer | Recent predictions (up to 500) |
GET |
/v1/stream |
Bearer | Server-Sent Events — every new prediction as it is made |
POST |
/v1/predict |
Bearer | Body = the predict() arguments as JSON → the Prediction JSON |
Two ways to feed the model:
- Live mode (
naga-runtime live): the runtime collects data itself; your dashboard only readslatest/stream. - Request mode (
naga-runtime serve): your system sends market data withPOST /v1/predict. Each result is also published tolatest,historyandstream(send"publish": falseto skip that).
Full request/response schema, status codes and a production checklist: docs/REST_API.md.
Client libraries
Python (standard library only — no PyTorch needed on the client machine):
from naga_runtime.client import NagaClient
api = NagaClient("http://127.0.0.1:8000", token="...") # or NAGA_API_TOKEN
print(api.latest()["decisions"]["XAUUSD"]["action"])
for pred in api.stream(): # reconnects automatically
print(pred["time"], {s: d["action"] for s, d in pred["decisions"].items()})
JavaScript (browser or Node.js 18+, no dependencies) — copy clients/naga-client.mjs:
import { NagaClient } from "./naga-client.mjs";
const api = new NagaClient("http://127.0.0.1:8000", token);
const stop = api.stream((pred) => render(pred), (state) => setBadge(state)); // "live" | "reconnecting" | "unauthorised"
Public websites: never put the API token in browser code. Run a small backend that holds the token and forwards
results — examples/backend_proxy.mjs is a complete, dependency-free example.
Security
| Concern | Protection |
|---|---|
| Tampered or corrupted model files | SHA-256 manifest verified on every load (IntegrityError). |
| Malicious model files | safetensors stores numbers only — loading never executes code (unlike pickle .pt files). |
| Model confidentiality | Optional AES-256-GCM encryption; key derived with scrypt; decrypted in memory only. |
| Leaking secrets | Keys and tokens are read from environment variables, never logged, compared in constant time. The .env reader ignores every key except the runtime's own. |
| Unauthorised API use | Bearer token on every /v1 route, localhost binding by default, CORS allow-list, rate limit, stream cap. |
| Dashboard attacks | Strict per-request Content-Security-Policy (nonce), no framing, no third-party scripts, all data rendered as text; the token is never embedded in the page and is kept in tab storage unless "Remember" is ticked. |
| Accidental trading | MT5 access is read-only — the library contains no order functions. |
| Information disclosure | Errors return short messages only; no stack traces, headers or bodies are logged. |
Details and deployment guidance: docs/SECURITY.md.
Performance
- Inference runs under
torch.inference_mode()with automatic mixed precision on CUDA (BF16, or FP16 on older GPUs). - On CPU, all cores are used (override with
NagaModel.load(..., threads=N)). - Bar features are computed once per new bar (
prepare); refreshes on quotes, account or positions run only the model (decide). Live mode does this automatically. - The model is warmed up at start, so the first live decision is as fast as the rest.
- Time columns are parsed vectorised; pass M5 + M15 + H1 (or ≈30 days of M1) — more history only costs time.
naga-runtime bench MODELreports median and p90 latency for both paths on your hardware.NagaModelis thread-safe; concurrent requests are serialised on the device. For high throughput, run several server processes behind a load balancer.
Troubleshooting
| Message | Fix |
|---|---|
missing bars for GBPUSD |
All three symbols are required. |
cannot build H1 — provide H1 bars or a finer timeframe |
Supply M1 or M5 (or H1 directly). |
warning ... needed for full context |
Provide ≥ 30 calendar days of history for full quality. |
IntegrityError: ... does not match manifest.json |
The download is corrupted or modified — obtain the model again. |
KeyRequiredError |
The model is encrypted: set NAGA_MODEL_KEY or pass key=.... |
only fully trained (PPO) models can make decisions |
Export the model after the PPO stage (python naga_hgt.py export). |
HTTP 401 |
Send Authorization: Bearer <token> matching NAGA_API_TOKEN. |
| Browser CORS error | Start the server with --cors https://your-dashboard-origin. |
MetaTrader 5 initialize failed |
Open the MT5 terminal and log in first, then start again. Algorithmic trading does not need to be enabled (access is read-only). |
symbol for XAUUSD not found at this broker |
Pass --symbols XAUUSD=<your broker name> (see the Market Watch window). |
| Dashboard shows "Reconnecting…" | The server stopped or the network dropped; it reconnects by itself. Check the terminal window for errors. |
| Times look shifted by hours | Start with --utc-offset N (your broker's server UTC offset). |
Versioning and compatibility
naga-runtime 1.2.3loads models exported by NAGA-HGT 2.5 and 2.4 (the variant is detected fromconfig.json) — 1.2.3 uses much less VRAM on GPU (efficient attention).naga-runtime 1.2.0loads models exported by NAGA-HGT 2.4 (dynamic market graph, shared-expert MoE). Models exported by NAGA-HGT 2.3 neednaga-runtime 1.1(pip install "naga-runtime==1.1.0"); loading one here stops with a clearIntegrityErrorinstead of producing wrong numbers.- The model architecture is fully described by
config.json; different model sizes (small / medium / base) load with the same library version. - The HTTP API is versioned (
/v1); 1.x releases only add fields and endpoints. - Run the test suite with
python tests/test_runtime.py(setNAGA_TRAINING_DIRto the training folder to include the bit-exact parity check).
Metadata
Release files for naga-runtime 1.2.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| naga_runtime-1.2.3.tar.gz | 92.8 kB | Without provenance | Details for naga_runtime-1.2.3.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| naga_runtime-1.2.3-py3-none-any.whl | Python 3 | none | any | Details for naga_runtime-1.2.3-py3-none-any.whl |
Total release size: 174.5 kB
Release files / naga_runtime-1.2.3.tar.gz
| Download URL | naga_runtime-1.2.3.tar.gz |
|---|---|
| Size | 92.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
32d586e9e39cb38a04d9e60c5229e93399d84cfddb33f6f71b2f270b4655511e
|
|
BLAKE2b-256 checksum How to use checksums |
36f13e621ac8ff7daabf4fa50bccc26f34b2a9678ca7a23180afe58188fd2b8d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.0
|
Release files / naga_runtime-1.2.3-py3-none-any.whl
| Download URL | naga_runtime-1.2.3-py3-none-any.whl |
|---|---|
| Size | 81.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
d96225396167cdef14c4cd758c05580aed34015a7607e7aaed37f166935ec981
|
|
BLAKE2b-256 checksum How to use checksums |
252c4334abf81c491476e1618ac0f34b413b7eaaef40fa7f79339989117dbbdc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.0
|
Security for naga-runtime 1.2.3
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.