Module 06: Cache System – Shared Runtime StateThe shared in-memory state layer for the entire platform
The Cache acts as the system’s shared state store. Order state, positions, account information, and market data snapshots are kept here so other components can access them with very low latency.
1. Architectural Role of the Cache
flowchart LR
subgraph writers["✍️ Writer Components"]
direction TB
de["📊 DataEngine"]
ee["⚙️ ExecutionEngine"]
adapter["🔌 Adapters"]
end
cache["💾 Cache<br/>Central Memory"]
subgraph readers["👁️ Reader Components"]
direction TB
strategy["🎯 Your Strategy"]
risk["🛡️ RiskEngine"]
portfolio["💰 Portfolio"]
end
writers ==> cache ==> readers
style cache fill:#0f1419,stroke:#4fc3f7,stroke-width:2px
Think of the Cache as the node’s shared state store: market data, order state, account state, and risk-relevant values are available to the components that need them, while write access stays controlled by the owning subsystem.
2. What is Stored in the Cache?
| Category | Stored Content | Written By | Typical Query Scenario |
|---|---|---|---|
| Instruments | Complete definitions of all known instruments | Adapters | Strategy querying tick_size, lot_size |
| Accounts | Account balances, margin | ExecutionEngine | RiskEngine calculating free capital |
| Orders | Current states of all orders | ExecutionEngine | Strategy querying open orders |
| Positions | All open positions | ExecutionEngine | Strategy querying current position direction and size |
| Market Data | Latest quotes, bars, order books | DataEngine | Strategy fetching the latest price |
| Custom Data | Strategy-private key-value pairs | Strategy itself | Sharing calculation results across functions |
3. Query APIs in Strategies
The following are the most common cache query methods used in strategy development:
3.1 Instrument Queries
# Get instrument definition
instrument = self.cache.instrument(instrument_id)
# Get all known instruments
all_instruments = self.cache.instruments()
# Get all instruments for a specific venue
binance_instruments = self.cache.instruments(venue=BINANCE)3.2 Order and Position Queries
# Query all open orders
open_orders = self.cache.orders_open()
# Query open orders for a specific instrument
btc_orders = self.cache.orders_open(instrument_id=btc_usdt_id)
# Query all open positions
positions = self.cache.positions_open()
# Query open position for a specific instrument
btc_position = self.cache.positions_open(instrument_id=btc_usdt_id)
# Fast check if the position is flat
is_flat = self.cache.is_flat(instrument_id=btc_usdt_id)3.3 Market Data Queries
# Latest Top-of-Book (Quote Tick)
quote = self.cache.quote_tick(instrument_id)
# Latest Trade Tick
trade = self.cache.trade_tick(instrument_id)
# Latest Bar
bar = self.cache.bar(bar_type)
# Get the most recent N bars
bars = self.cache.bars(bar_type, count=100)
# Get Order Book (L2)
book = self.cache.order_book(instrument_id)3.4 Account Queries
# Get account
account = self.cache.account(account_id)
# Get account balances
balances = account.balances()
# Get free balance (after deducting margin)
free_balance = account.balance_free(Currency.from_str("USDT"))4. Cache Backends
The Cache defaults to an in-memory store (the fastest), but can be configured with a Redis backend for state persistence:
In-Memory Backend (Default)
• Fastest speed (nanosecond read latency)
• Data is lost when the process shuts down
• Ideal for backtesting and sandboxing
• Zero external dependencies
Redis Backend (Optional)
• Fast speed (microsecond latency)
• Data persists after system crashes
• Suitable for live production environments
• Supports cross-process state sharing
# Configure Redis cache backend
from nautilus_trader.cache.config import CacheConfig
config = CacheConfig(
database=CacheDatabaseConfig(
type="redis",
host="localhost",
port=6379,
),
flush_on_start=False, # Do not flush old data on start (used for crash recovery)
)5. Snapshots and Recovery
sequenceDiagram
participant Cache as 💾 Cache
participant Redis as 🔴 Redis
Note over Cache,Redis: Normal Operation
Cache->>Redis: Periodically write order states
Cache->>Redis: Periodically write position data
Cache->>Redis: Periodically write account balances
Note over Cache: 💥 System Crash
Note over Cache,Redis: Restart
Redis->>Cache: Recover all order states
Redis->>Cache: Recover all positions
Redis->>Cache: Recover account balances
Note over Cache: ✅ State fully recovered
6. Interactive Exercise
Suppose you are developing a strategy and need to accomplish the following tasks. Write the cache query methods you would use:
- Check if BTC-USDT has any open orders.
- Get the latest quote tick for BTC-USDT (to calculate an entry price).
- Query the instrument specifications for BTC-USDT (e.g., minimum lot size).
- Verify if the account has a sufficient free balance of USDT.
open_orders = self.cache.orders_open(instrument_id=btc_usdt_id) has_open = len(open_orders) > 0quote = self.cache.quote_tick(btc_usdt_id) best_ask = quote.ask_price # Best ask price (your buy price)instrument = self.cache.instrument(btc_usdt_id) min_qty = instrument.min_quantityaccount = self.cache.account(account_id) free = account.balance_free(Currency.from_str("USDT")) has_enough = free >= required_amount
7. Module Summary
- Cache = Shared Runtime State: Components use it to read instruments, orders, positions, accounts, and market data through a common state layer.
- Engines Write, Strategies Read: A clear separation of concerns.
- In-Memory Default, Redis Optional: The trade-off between fast local reads and durable state persistence.
- Crash Recovery: The Redis backend ensures state is not lost after a system restart.
- Rich Query APIs: Master commonly used methods like orders_open, positions_open, and quote_tick.