Class TsSymbolMap
- Namespace
- DatabentoDotNet.Dbn
- Assembly
- DatabentoDotNet.Dbn.dll
A timeseries symbol map: resolves an instrument ID to its symbol on a specific date. Useful for a historical request spanning multiple days, where the same instrument ID can mean a different symbol on different dates (a continuous contract rolling to a new front-month instrument, for example).
public sealed class TsSymbolMap : ISymbolIndex
- Inheritance
-
TsSymbolMap
- Implements
- Inherited Members
Examples
using var decoder = new DbnDecoder(File.OpenRead("january.dbn.zst"));
TsSymbolMap symbols = TsSymbolMap.FromMetadata(decoder.Metadata!);
while (decoder.TryNextRecord(out RecordRef record))
{
// This overload takes the record itself, and reads both keys off it: the instrument id, and
// the date of the record's own IndexTs. Keying on Header.TsEvent instead would silently
// return the previous day's symbol for any schema that indexes on ts_recv.
if (symbols.TryGetSymbol(record, out string? symbol))
{
Console.WriteLine($"{record.Header.InstrumentId} is {symbol}");
}
}
// Or by date and id directly, where there is no record in hand.
symbols.TryGetSymbol(new LocalDate(2024, 1, 2), 12345u, out string? onThatDay);
Remarks
Port of upstream's TsSymbolMap (symbol_map.rs:34-211). Build one with
FromMetadata(Metadata) from a decoded stream's Metadata, then resolve with
TryGetSymbol(LocalDate, uint, out string?) for each record's date and instrument ID.
Storage is one entry per instrument-day, not per interval. Insert(uint, LocalDate, LocalDate, string) expands
a [startDate, endDate) interval into one dictionary entry for every calendar day in it,
trading memory for an O(1) exact-date lookup with no range search — the same trade-off
upstream makes. A query spanning many instruments over a wide date range can therefore build a
large map; that is expected, not a bug to "optimize away".
The same symbol string is reused across every day of an interval, deliberately. Upstream
stores Arc<String> so that expanding one interval into many day-keys costs a
reference-count bump per day, not a string copy. A .NET string is already a
reference type, so Insert(uint, LocalDate, LocalDate, string) gets the same sharing for free simply by storing the
same string instance in every day-key it writes — never by re-slicing or
re-allocating per day. Do not "simplify" this into a fresh string per day.
No date-range validation against Start/End happens here. FromMetadata(Metadata) inserts every interval of every mapping regardless of whether it falls inside the metadata's own query range — that is a property of well-formed input, not something this type enforces. Contrast FromMetadata(Metadata, LocalDate), which does validate its single date against the range.
Constructors
TsSymbolMap()
Creates a new, empty timeseries symbol map.
public TsSymbolMap()
Properties
Count
The number of instrument-day entries in the map.
public int Count { get; }
Property Value
Remarks
One entry per calendar day a mapping is valid for, not one per requested symbol or per mapping interval — see the remarks on TsSymbolMap.
IsEmpty
true when there are no mappings.
public bool IsEmpty { get; }
Property Value
Methods
FromMetadata(Metadata)
Builds a timeseries symbol map from a decoded stream's metadata, covering every mapping interval it carries.
public static TsSymbolMap FromMetadata(Metadata metadata)
Parameters
metadataMetadataThe metadata to build the map from.
Returns
- TsSymbolMap
The resulting map.
Remarks
Port of upstream's TsSymbolMap::from_metadata / TryFrom<&Metadata>
(symbol_map.rs:107-109, 173-211), reached via Metadata::symbol_map()
(metadata.rs:126-128).
Exceptions
- ArgumentNullException
metadatais null.- DbnDecodeException
Neither StypeIn nor StypeOut is InstrumentId, so
metadatacannot yield a symbol map; or a mapping's instrument-ID string does not parse as a uint.
Insert(uint, LocalDate, LocalDate, string)
Inserts a mapping for instrumentId, valid on every calendar day from
startDate (inclusive) up to but not including endDate
(exclusive).
public void Insert(uint instrumentId, LocalDate startDate, LocalDate endDate, string symbol)
Parameters
instrumentIduintThe instrument ID the mapping is for.
startDateLocalDateThe first day the mapping is valid for, inclusive.
endDateLocalDateThe day the mapping stops being valid, exclusive.
symbolstringThe symbol to map
instrumentIdto.
Remarks
Port of upstream's TsSymbolMap::insert (symbol_map.rs:117-146). Writes one
dictionary entry per calendar day in the half-open range
[startDate, endDate), overwriting any mapping already present for a given
day/instrument pair.
startDate equal to endDate is a silent no-op, matching
upstream's own comment on the degenerate case ("Shouldn't happen but better to just
ignore") — it is not an error, and it does not insert a single-day entry either.
Exceptions
- ArgumentNullException
symbolis null.- DbnDecodeException
startDatecomes afterendDate.
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(LocalDate, uint, out string?)
Looks up the symbol for an instrument ID on a specific date.
public bool TryGetSymbol(LocalDate date, uint instrumentId, out string? symbol)
Parameters
dateLocalDateThe date to resolve the symbol for.
instrumentIduintThe instrument ID to resolve.
symbolstringReceives the resolved symbol, or null when there is no mapping for
instrumentIdondate.
Returns
Remarks
Port of upstream's TsSymbolMap::get (symbol_map.rs:150-152), shaped as a
Try* member because a miss — an unmapped instrument ID, or a date the map has no
entry for — 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.