Class PitSymbolMap
- Namespace
- DatabentoDotNet.Dbn
- Assembly
- DatabentoDotNet.Dbn.dll
A point-in-time symbol map: resolves an instrument ID to its symbol with no date involved at all. Useful for live symbology, or a historical request over a single day where the mapping is known not to change.
public sealed class PitSymbolMap : ISymbolIndex
- Inheritance
-
PitSymbolMap
- Implements
- Inherited Members
Examples
Live, where the map is grown from the mappings the stream interleaves with the data:
var symbols = new PitSymbolMap();
while (true)
{
while (client.TryNextRecord(out RecordRef record))
{
// Ignores anything that is not a mapping, so it is safe to call on every record.
symbols.OnRecord(record);
if (symbols.TryGetSymbol(record.Header.InstrumentId, out string? symbol))
{
Console.WriteLine($"{symbol} {record.Header.RType}");
}
}
if (await client.FillBufferAsync() == 0)
{
break;
}
}
Historical, over a single day. No date takes part in the lookup, because the date was committed to when the map was built:
var symbols = PitSymbolMap.FromMetadata(decoder.Metadata!, new LocalDate(2024, 1, 2));
symbols.TryGetSymbol(12345u, out string? symbol);
Remarks
Port of upstream's PitSymbolMap (symbol_map.rs:73-374). Build one from a single
day of a decoded stream's metadata with FromMetadata(Metadata, LocalDate), or grow one incrementally
as a live or replayed stream is consumed with OnRecord(RecordRef). Resolve with
TryGetSymbol(uint, out string?).
No date or timestamp is ever involved in resolution — this is the whole point of
"point-in-time": the caller already committed to one date when the map was built (or has kept
it current via OnRecord(RecordRef)), so TryGetSymbol(uint, out string?) is unconditional
instrument_id -> symbol. This is a real, deliberate divergence from
TsSymbolMap, not an oversight to "fix" into checking a timestamp too.
The incremental update path (OnRecord(RecordRef), OnSymbolMapping(in SymbolMappingMsg))
is what M2's live client depends on: called once per record as a stream is consumed, so it
stays allocation-light — it allocates exactly the one string a genuine new
mapping requires, the same as upstream's own to_owned(), and nothing else.
Constructors
PitSymbolMap()
Creates a new, empty point-in-time symbol map.
public PitSymbolMap()
Properties
Count
The number of instrument IDs currently mapped.
public int Count { get; }
Property Value
IsEmpty
true when there are no mappings.
public bool IsEmpty { get; }
Property Value
Methods
FromMetadata(Metadata, LocalDate)
Builds a point-in-time symbol map from a decoded stream's metadata, resolved for one specific date.
public static PitSymbolMap FromMetadata(Metadata metadata, LocalDate date)
Parameters
metadataMetadataThe metadata to build the map from.
dateLocalDateThe date to resolve every mapping for.
Returns
- PitSymbolMap
The resulting map.
Remarks
Port of upstream's PitSymbolMap::from_metadata (symbol_map.rs:237-273),
reached via Metadata::symbol_map_for_date() (metadata.rs:113-115).
The date-range check compares at full nanosecond precision, not date granularity.
date is promoted to date at 00:00 UTC and compared
against End — itself a nanosecond timestamp — directly, not against
End truncated to a date. The upper bound is therefore exclusive at
nanosecond granularity: an End of exactly midnight on day D excludes
day D entirely (00:00 >= 00:00), while an End even one
nanosecond past midnight on day D includes all of day D
(00:00 < 00:00:00.000000001). Truncating End to a date
before comparing gets this boundary backwards — pinned upstream by
test_symbol_map_for_date_out_of_range (symbol_map.rs:870-890) and ported
as SymbolMapTests' own midnight-exact / midnight-plus-one-nanosecond tests.
Exceptions
- ArgumentNullException
metadatais null.- DbnDecodeException
Neither StypeIn nor StypeOut is InstrumentId; a mapping's instrument-ID string does not parse as a uint; or
datefalls outsidemetadata's query range.
OnInstrumentDef(in InstrumentDefMsg)
Updates this map from a current-version (DBN v3) instrument definition record.
public void OnInstrumentDef(in InstrumentDefMsg record)
Parameters
recordInstrumentDefMsgThe instrument definition record.
Remarks
Port of upstream's PitSymbolMap::on_instrument_def (symbol_map.rs:310-318).
An alternate incremental-update path to OnSymbolMapping(in SymbolMappingMsg):
a definition record carries its own raw_symbol, so a stream of definitions can keep
a map current without any symbol-mapping records at all. Neither this method nor its two
sibling overloads is called from OnRecord(RecordRef) — a caller who wants this path must
call it explicitly, matching upstream.
OnInstrumentDef(in InstrumentDefMsgV1)
Updates this map from a DBN v1 instrument definition record.
public void OnInstrumentDef(in InstrumentDefMsgV1 record)
Parameters
recordInstrumentDefMsgV1The instrument definition record.
Remarks
See the remarks on OnInstrumentDef(in InstrumentDefMsg).
OnInstrumentDef(in InstrumentDefMsgV2)
Updates this map from a DBN v2 instrument definition record.
public void OnInstrumentDef(in InstrumentDefMsgV2 record)
Parameters
recordInstrumentDefMsgV2The instrument definition record.
Remarks
See the remarks on OnInstrumentDef(in InstrumentDefMsg).
OnRecord(RecordRef)
Updates this map from one record if it carries a symbol mapping; otherwise does nothing.
public void OnRecord(RecordRef record)
Parameters
recordRecordRefThe record to inspect.
Remarks
Port of upstream's PitSymbolMap::on_record (symbol_map.rs:280-288). Tries the
current-version SymbolMappingMsg layout first, then the DBN v1 layout
(SymbolMappingMsgV1); any other record type — including an instrument
definition — is a silent no-op. Definition records update the map only through the
separate OnInstrumentDef(in InstrumentDefMsg) family, which a caller must
call explicitly; upstream does not fold that path into on_record either.
OnSymbolMapping(in SymbolMappingMsg)
Updates this map from a current-version (DBN v2/v3) symbol-mapping record.
public void OnSymbolMapping(in SymbolMappingMsg record)
Parameters
recordSymbolMappingMsgThe symbol-mapping record.
Remarks
Port of upstream's PitSymbolMap::on_symbol_mapping (symbol_map.rs:294-304).
Maps InstrumentId to StypeOutSymbol
— the output symbol, since a live symbol-mapping record always resolves an input symbol to
an instrument ID and reports back what that instrument's output symbol is.
OnSymbolMapping(in SymbolMappingMsgV1)
Updates this map from a DBN v1 symbol-mapping record.
public void OnSymbolMapping(in SymbolMappingMsgV1 record)
Parameters
recordSymbolMappingMsgV1The symbol-mapping record.
Remarks
See the remarks on OnSymbolMapping(in SymbolMappingMsg).
TryGetSymbol(RecordRef, out string?)
Looks up the symbol for a decoded record.
public bool TryGetSymbol(RecordRef record, out string? symbol)
Parameters
recordRecordRefThe record to resolve.
symbolstringReceives the resolved symbol, or null when the map has no mapping for this record.
Returns
Remarks
This is the overload a decoder loop uses, since RecordRef is what
TryNextRecord hands out and no downcast is needed to resolve a symbol.
TryGetSymbol(uint, out string?)
Looks up the symbol currently mapped to an instrument ID.
public bool TryGetSymbol(uint instrumentId, out string? symbol)
Parameters
instrumentIduintThe instrument ID to resolve.
symbolstringReceives the resolved symbol, or null when
instrumentIdhas no mapping.
Returns
Remarks
Port of upstream's PitSymbolMap::get (symbol_map.rs:321-323), shaped as a
Try* member because an unmapped instrument ID is an expected outcome, not an
exceptional one.
TryGetSymbol<TRecord>(in TRecord, out string?)
Looks up the symbol for a decoded record of a known type.
public bool TryGetSymbol<TRecord>(in TRecord record, out string? symbol) where TRecord : unmanaged, IRecord<TRecord>
Parameters
recordTRecordThe record to resolve.
symbolstringReceives the resolved symbol, or null when the map has no mapping for this record.
Returns
Type Parameters
TRecordThe record struct.
Remarks
For a record that has been downcast or copied out of the read buffer — one held in a collection, say, where no RecordRef survives to call the other overload with. Takes the record by in so a 520-byte InstrumentDefMsg is read in place rather than copied to be asked its symbol.