configs/claude-code/skills/using-nautilus-trader/SKILL.md
Use when building, backtesting, or deploying algorithmic trading systems with NautilusTrader (nautilus_trader) — writing Strategy/Actor classes and StrategyConfig, configuring BacktestNode/BacktestEngine, constructing instruments, order management, ParquetDataCatalog/wranglers, message bus and custom data streams, indicators, portfolio/analysis/report generation, or live TradingNode deployment. Curated for v1.230.0.
npx skillsauth add poorrican/dotfiles using-nautilus-traderInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Open-source, Rust-native, event-driven trading platform. The same strategy code runs unchanged in backtest, sandbox, and live — this is the central design idea, and most mistakes come from forgetting it. Python API over a Rust/Cython core.
Version pin: curated against v1.230.0 (current
latest, 2026-07). The online docs serve onlylatest/nightly(no per-version markdown), so the links here point to/docs/md/latest/…which is v1.230.0 today. Nautilus makes breaking changes between minor versions before v2.0 — if your installednautilus_trader.__version__differs, verify names/signatures against the release notes and API reference. See references/doc-map.md for the full online index.
You are not writing a backtest script. You are writing an event-driven
component (a Strategy, which is an Actor with order management) that
reacts to messages delivered by a MessageBus inside a NautilusKernel. A backtest
just feeds that component historical data through the same engines that a live venue
would. Consequences:
for-loops over data, no look-ahead. React inside on_bar / on_quote_tick
/ on_trade_tick / on_data / on_event. State lives on self.self.submit_order(...),
self.cache, self.portfolio, self.clock, self.msgbus, self.log,
self.subscribe_*, self.request_*.StrategyConfig, keep it immutable/serializable, and the
same class + config wiring deploys live.| Your task | Read |
|---|---|
| Understand the engine, kernel, config system, environment contexts, logging | architecture.md |
| Price / Quantity / Money / Currency, IDs, precision bugs | value-types.md |
| Quote/Trade/Bar/OrderBook types, BarType grammar, subscriptions, aggregation | data.md |
| Feed your own data type through the engine (signals, features, PBP, etc.) | custom-data.md |
| Build an Instrument + required metadata; providers; synthetics; options/greeks | instruments.md |
| Write a Strategy: config, handlers/hooks, timers, one strategy → many markets | strategies.md |
| Non-trading component (feature/data publisher) with Actor | actors.md |
| Order types, OrderFactory, brackets/contingencies, emulation, order events | orders.md |
| Execution flow, ExecAlgorithm (TWAP), OMS NETTING vs HEDGING, positions, fills | execution.md |
| MessageBus pub/sub, Cache queries, events, creating/subscribing to streams | message-bus.md |
| Configure & run a backtest — high-level BacktestNode vs low-level BacktestEngine | backtesting.md |
| ParquetDataCatalog, wranglers, persisting instruments, datasets, streaming | data-catalog.md |
| Portfolio/account/PnL queries, PortfolioAnalyzer stats, report DataFrames | portfolio-and-reports.md |
| Go live: TradingNode, reconciliation, adapters, production safety | live-trading.md |
| Non-obvious mistakes across all areas (read this early) | gotchas.md |
| Full link index back to the online docs | doc-map.md |
Instrument (instruments.md),
or grab one from TestInstrumentProvider for prototyping.ParquetDataCatalog (data-catalog.md).StrategyConfig + Strategy; subscribe in on_start;
trade in handlers (strategies.md).BacktestEngine for a quick single run, or high-level
BacktestNode + configs for reproducible, catalog-driven runs
(backtesting.md).generate_*_report DataFrames and PortfolioAnalyzer stats
(portfolio-and-reports.md).BacktestEngine/BacktestNode for a TradingNode; the
Strategy is untouched (live-trading.md).from nautilus_trader.model.identifiers import InstrumentId
from nautilus_trader.model.data import BarType
from nautilus_trader.model.objects import Price, Quantity
# InstrumentId = "{symbol}.{VENUE}"
InstrumentId.from_str("BTCUSDT.BINANCE")
InstrumentId.from_str("EUR/USD.SIM") # SIM = the built-in simulated venue
# BarType = "{instrument_id}-{step}-{aggregation}-{price_type}-{agg_source}"
# aggregation: MILLISECOND|SECOND|MINUTE|HOUR|DAY|WEEK|MONTH|YEAR | TICK|VOLUME|VALUE(+_IMBALANCE/_RUNS) | RENKO
# price_type: LAST | BID | ASK | MID
# agg_source: EXTERNAL (bars arrive pre-aggregated from the venue/data)
# INTERNAL (Nautilus aggregates them from ticks/quotes for you)
BarType.from_str("BTCUSDT.BINANCE-1-MINUTE-LAST-EXTERNAL")
BarType.from_str("BTCUSDT.BINANCE-15-MINUTE-LAST-INTERNAL")
# ALWAYS build Price/Quantity from strings (or the instrument helpers) — never floats.
Price.from_str("50000.00") # preserves precision
Quantity.from_str("1.5")
# instrument.make_price(50000.0) / instrument.make_qty(1.5) # snaps to increments
| Enum | Values | Use |
|---|---|---|
| OmsType | NETTING (one net position/instrument, crypto-style), HEDGING (multiple positions/instrument) | per-venue in backtest/live config |
| AccountType | CASH (spot), MARGIN (leverage), BETTING | per-venue |
| OrderSide | BUY, SELL | orders |
| TimeInForce | GTC, IOC, FOK, GTD (needs expire_time), DAY, AT_THE_OPEN, AT_THE_CLOSE | orders |
| Pitfall | Do this |
|---|---|
| Custom Data subclass never reaches on_data ("Cannot handle data: unrecognized type") | Feed it wrapped: CustomData(DataType(T), obj). Nautilus unwraps before on_data, so isinstance(data, T) still works. Inside a component use self.publish_data(DataType(T), obj). See custom-data.md. |
| float prices/quantities cause precision drift & silent rejects | Price.from_str/Quantity.from_str or instrument.make_price/make_qty. |
| Indicator never initializes / uses stale values | register_indicator_for_bars(bar_type, ind) before subscribe_bars(bar_type); guard on if not ind.initialized: return. |
| BarType string wrong → no data | Exact grammar above; INTERNAL vs EXTERNAL is not cosmetic — it decides whether Nautilus aggregates. |
| Wrote ticks/bars to catalog but backtest sees no instrument | Persist the instrument into the catalog too (catalog.write_data([instrument])), and match instrument_id exactly. |
| One strategy trading many instruments collides on order/position tracking | Give each Strategy instance a unique order_id_tag/StrategyId; key per-instrument state in dicts; see the multi-instrument pattern in strategies.md. |
| Subclassing Strategy but ignoring StrategyConfig | Put params in a frozen StrategyConfig subclass so the exact code deploys live and is reproducible. |
pip install -U nautilus_trader # or: uv add nautilus-trader
# High-precision (128-bit) build differs from standard — see architecture.md.
content-media
Create, read, edit .pptx decks, slides, notes, templates.
content-media
Create, read, edit .pptx decks, slides, notes, templates.
documentation
Extract text from PDFs/scans (pymupdf, marker-pdf).
documentation
Extract text from PDFs/scans (pymupdf, marker-pdf).