Skip to main content
Version: latest

Instruments

The Instrument base class represents the core specification for any tradable asset/contract. There are currently a number of subclasses representing a range of asset classes and instrument classes which are supported by the platform:

  • Equity (generic Equity)
  • Future (generic Futures Contract)
  • Option (generic Options Contract)
  • CurrencyPair (represents a Fiat FX or Cryptocurrency pair in a spot/cash market)
  • CryptoPerpetual (Perpetual Futures Contract a.k.a. Perpetual Swap)
  • CryptoFuture (Deliverable Futures Contract with Crypto assets as underlying, and for price quotes and settlement)
  • BettingInstrument (Sports, gaming, or other betting)

Symbology

All instruments should have a unique InstrumentId, which is made up of both the native symbol, and venue ID, separated by a period. For example, on the Binance Futures crypto exchange, the Ethereum Perpetual Futures Contract has the instrument ID ETHUSDT-PERP.BINANCE.

All native symbols should be unique for a venue (this is not always the case e.g. Binance share native symbols between spot and futures markets), and the {symbol.venue} combination must be unique for a Nautilus system.

warning

The correct instrument must be matched to a market dataset such as ticks or order book data for logically sound operation. An incorrectly specified instrument may truncate data or otherwise produce surprising results.

Backtesting

Generic test instruments can be instantiated through the TestInstrumentProvider:

from nautilus_trader.test_kit.providers import TestInstrumentProvider

audusd = TestInstrumentProvider.default_fx_ccy("AUD/USD")

Exchange specific instruments can be discovered from live exchange data using an adapters InstrumentProvider:

from nautilus_trader.adapters.binance.spot.providers import BinanceSpotInstrumentProvider
from nautilus_trader.model import InstrumentId

provider = BinanceSpotInstrumentProvider(client=binance_http_client)
await self.provider.load_all_async()

btcusdt = InstrumentId.from_str("BTCUSDT.BINANCE")
instrument = provider.find(btcusdt)

Or flexibly defined by the user through an Instrument constructor, or one of its more specific subclasses:

from nautilus_trader.model.instruments import Instrument

instrument = Instrument(...) # <-- provide all necessary parameters

See the full instrument API Reference.

Live trading

Live integration adapters have defined InstrumentProvider classes which work in an automated way to cache the latest instrument definitions for the exchange. Refer to a particular Instrument object by pass the matching InstrumentId to data and execution related methods, and classes which require one.

Finding instruments

Since the same actor/strategy classes can be used for both backtest and live trading, you can get instruments in exactly the same way through the central cache:

from nautilus_trader.model import InstrumentId

instrument_id = InstrumentId.from_str("ETHUSDT-PERP.BINANCE")
instrument = self.cache.instrument(instrument_id)

It's also possible to subscribe to any changes to a particular instrument:

self.subscribe_instrument(instrument_id)

Or subscribe to all instrument changes for an entire venue:

from nautilus_trader.model import Venue

binance = Venue("BINANCE")
self.subscribe_instruments(binance)

When an update to the instrument(s) is received by the DataEngine, the object(s) will be passed to the actors/strategies on_instrument() method. A user can override this method with actions to take upon receiving an instrument update:

def on_instrument(instrument: Instrument) -> None:
# Take some action on an instrument update
pass

Precisions and increments

The instrument objects are a convenient way to organize the specification of an instrument through read-only properties. Correct price and quantity precisions, as well as minimum price and size increments, multipliers and standard lot sizes, are available.

note

Most of these limits are checked by the Nautilus RiskEngine, otherwise invalid values for prices and quantities can result in the exchange rejecting orders.

Limits

Certain value limits are optional for instruments and can be None, these are exchange dependent and can include:

  • max_quantity (maximum quantity for a single order)
  • min_quantity (minimum quantity for a single order)
  • max_notional (maximum value of a single order)
  • min_notional (minimum value of a single order)
  • max_price (maximum valid quote or order price)
  • min_price (minimum valid quote or order price)
note

Most of these limits are checked by the Nautilus RiskEngine, otherwise exceeding published limits can result in the exchange rejecting orders.

Prices and quantities

Instrument objects also offer a convenient way to create correct prices and quantities based on given values.

instrument = self.cache.instrument(instrument_id)

price = instrument.make_price(0.90500)
quantity = instrument.make_qty(150)
tip

The above is the recommended method for creating valid prices and quantities, such as when passing them to the order factory to create an order.

Margins and fees

The current initial and maintenance margin requirements, as well as any trading fees are also available from an instrument:

  • margin_init (initial/order margin rate)
  • margin_maint (maintenance/position margin rate)
  • maker_fee (the fee percentage applied to notional order values when providing liquidity)
  • taker_fee (the fee percentage applied to notional order values when demanding liquidity)

Additional info

The raw instrument definition as provided by the exchange (typically from JSON serialized data) is also included as a generic Python dictionary. This is to retain all information which is not necessarily part of the unified Nautilus API, and is available to the user at runtime by calling the .info property.