Phase 2: Core Components

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
Figure 1: The Cache serves as the bridge between writers and readers
💡 Analogy

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?

CategoryStored ContentWritten ByTypical Query Scenario
InstrumentsComplete definitions of all known instrumentsAdaptersStrategy querying tick_size, lot_size
AccountsAccount balances, marginExecutionEngineRiskEngine calculating free capital
OrdersCurrent states of all ordersExecutionEngineStrategy querying open orders
PositionsAll open positionsExecutionEngineStrategy querying current position direction and size
Market DataLatest quotes, bars, order booksDataEngineStrategy fetching the latest price
Custom DataStrategy-private key-value pairsStrategy itselfSharing 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
Figure 2: State recovery after a crash using Redis

6. Interactive Exercise

🧠 Exercise: Cache Queries in Strategies

Suppose you are developing a strategy and need to accomplish the following tasks. Write the cache query methods you would use:

  1. Check if BTC-USDT has any open orders.
  2. Get the latest quote tick for BTC-USDT (to calculate an entry price).
  3. Query the instrument specifications for BTC-USDT (e.g., minimum lot size).
  4. Verify if the account has a sufficient free balance of USDT.
  1. open_orders = self.cache.orders_open(instrument_id=btc_usdt_id)
    has_open = len(open_orders) > 0
  2. quote = self.cache.quote_tick(btc_usdt_id)
    best_ask = quote.ask_price  # Best ask price (your buy price)
  3. instrument = self.cache.instrument(btc_usdt_id)
    min_qty = instrument.min_quantity
  4. account = self.cache.account(account_id)
    free = account.balance_free(Currency.from_str("USDT"))
    has_enough = free >= required_amount

7. Module Summary

📋 Key Takeaways
  1. Cache = Shared Runtime State: Components use it to read instruments, orders, positions, accounts, and market data through a common state layer.
  2. Engines Write, Strategies Read: A clear separation of concerns.
  3. In-Memory Default, Redis Optional: The trade-off between fast local reads and durable state persistence.
  4. Crash Recovery: The Redis backend ensures state is not lost after a system restart.
  5. Rich Query APIs: Master commonly used methods like orders_open, positions_open, and quote_tick.