Interface Instrument

All Known Implementing Classes:
DatedFutureInstrument, PerpetualInstrument, SpotInstrument

public sealed interface Instrument permits SpotInstrument, PerpetualInstrument, DatedFutureInstrument
Normalised instrument identity in the CCXT unified format.

Three market kinds, one per implementation:

The distinction matters for identity, not just display: two delivery contracts on the same pair with different expiries trade at different prices, so they must be unequal and usable as distinct map keys. A single record with an optional expiry field would also permit a spot instrument carrying one; this hierarchy makes that unrepresentable.

Construct through of(String, String) rather than the record constructors. Each overload names exactly one variant and accepts no absent component: no null, no blank string. A call site holding an optional settlement currency must therefore decide for itself what it means — the factory will not quietly turn a missing component into a simpler market kind, because that is how a derivative ends up recorded as spot.

symbol() is a persisted and transported format, not a display convenience: it is the QuestDB ins column, part of the NATS subject grammar, and the identity used by the cache and the signal stores. parse(String) is its exact inverse. Note that settle() is deliberately absent from this interface — it exists only on the variants that have one, so code composing a wire format out of an instrument's parts cannot silently omit the expiry.

Engine-owned, with no XChange dependency. XChange's own instrument types are confined to the exchange-adapter / order-execution boundary, where XChangeConvert (qtsurfer-engine-exchange) bridges the two.