Table of Contents

Class SecurityMasterClient

Namespace
DatabentoDotNet.Reference
Assembly
DatabentoDotNet.Reference.dll

The security_master.* endpoints: what a listing is, where it trades, and every identifier it is known by.

public sealed class SecurityMasterClient
Inheritance
SecurityMasterClient
Inherited Members

Examples

// Every version of a listing over a window of one of its two timestamps.
await foreach (SecurityMaster version in client.SecurityMaster.GetRangeAsync(
    new SecurityMasterGetRangeParams
    {
        Symbols = Symbols.From("AAPL"),
        DateTimeRange = ReferenceDateTimeRange.Between(
            Instant.FromUtc(2024, 1, 1, 0, 0), Instant.FromUtc(2024, 2, 1, 0, 0)),

        // TsEffective — when the change took effect — rather than TsRecord, when Databento
        // recorded it. A late correction lands under a different window depending on which.
        Index = SecurityMasterIndex.TsEffective,

        // Defaults to true, and on an ISIN-limited plan that can spend quota rather than only
        // money. Set it deliberately.
        AllocateIsins = false,
    }))
{
    Console.WriteLine($"{version.TsEffective} {version.Symbol} {version.ListingStatus}");
}

// The latest version only, which takes no window at all.
await foreach (SecurityMaster latest in client.SecurityMaster.GetLastAsync(
    new SecurityMasterGetLastParams { Symbols = Symbols.From(["AAPL", "MSFT"]) }))
{
    Console.WriteLine($"{latest.Symbol} {latest.Isin} {latest.Figi}");
}

Remarks

Reached through SecurityMaster rather than constructed. Port of upstream's SecurityMasterClient (security.rs:20-82), which holds a mutable borrow of the outer client; this holds a reference, there being no borrow checker to satisfy.

Two methods, one row type, and the difference between them is which rows. GetRangeAsync(SecurityMasterGetRangeParams, CancellationToken) asks for every version of a record over a window of one of its two timestamps; GetLastAsync(SecurityMasterGetLastParams, CancellationToken) asks for the latest version and takes no window at all. Both return SecurityMaster.

Both methods bill. Reference data is a separate Databento product, so a 403 here is a legitimate outcome on an account entitled for historical data rather than a mysterious failure. Both also default to allocating ISINs — see AllocateIsins, which is the one property in this group whose default can spend an entitlement rather than only money.

Fields

RequestCompression

The compression both endpoints ask for. Not caller-settable.

public const string RequestCompression = "zstd"

Field Value

string

Remarks

Upstream hard-codes this (security.rs:40, :70) because the response handler requires the frame; the two parameter types render it and document why it is a constant rather than a property. Public and named so a test can assert the value on the wire against the value the library believes it sends, rather than against a string typed twice — the same reason RequestCompression is.

Methods

GetLastAsync(SecurityMasterGetLastParams, CancellationToken)

Streams the latest security master record for each security matching parameters, a row at a time as they decompress.

public IAsyncEnumerable<SecurityMaster> GetLastAsync(SecurityMasterGetLastParams parameters, CancellationToken cancellationToken = default)

Parameters

parameters SecurityMasterGetLastParams

Which symbols, narrowed how.

cancellationToken CancellationToken

Cancels the request and the enumeration.

Returns

IAsyncEnumerable<SecurityMaster>

The latest row per security, in the order the server sent them.

Remarks

Port of upstream's get_last (security.rs:62-79).

No range and no index. The endpoint's answer is "the current record", so there is nothing for a window to select — SecurityMasterGetLastParams has no property for either, and the form this posts carries neither key.

Upstream documents this one as sorted by ts_effective and it is not sorted here, which is #52's decision restated rather than a second one. That sort has no request counterpart at all — no index is sent, so it is purely a rearrangement of a buffer upstream had already paid for (security.rs:77). A stream has no buffer to rearrange. A caller who wants it writes rows.OrderBy(row => row.TsEffective) over the materialised sequence.

This costs money and defaults to allocating ISINs, exactly as GetRangeAsync(SecurityMasterGetRangeParams, CancellationToken) does, and sends nothing until the enumeration starts for the same reason.

Exceptions

ArgumentNullException

parameters is null.

InvalidOperationException

parameters leaves Symbols at its type's default value.

DatabentoApiException

The API answered with a non-success status.

GetRangeAsync(SecurityMasterGetRangeParams, CancellationToken)

Streams every security master record matching parameters over the requested range, a row at a time as they decompress.

public IAsyncEnumerable<SecurityMaster> GetRangeAsync(SecurityMasterGetRangeParams parameters, CancellationToken cancellationToken = default)

Parameters

parameters SecurityMasterGetRangeParams

Which symbols, over what range of which timestamp.

cancellationToken CancellationToken

Cancels the request and the enumeration.

Returns

IAsyncEnumerable<SecurityMaster>

One row per security master record, in the order the server sent them.

Remarks

Port of upstream's get_range (security.rs:31-53) — with one deliberate behavioural difference, below.

This costs money, and it is billed by what it returns. Reference data is a separate Databento product from historical market data: an API key entitled for one is not necessarily entitled for the other, and a 403 from this endpoint on an otherwise working key means exactly that rather than a broken credential. Unlike a batch job, a stream can be stopped part-way — break out of the await foreach and the response is disposed on the way out, which is half of why this streams.

Rows arrive in the server's order, and this method does not sort them. Upstream buffers the whole response into a Vec and then sorts it by whichever timestamp Index names (security.rs:50-53) — it can, because it has already paid for the buffer. A stream has not: sorting is what buffering is, so an IAsyncEnumerable<T> that sorted would be a list wearing a stream's type. The index is still sent, because it is also what the server filters on — dropping the sort does not drop the parameter. A caller who needs upstream's order can have it in one line over the materialised sequence, and pays for the buffer where they can see it. See ROADMAP.md §6, and ReadZstdJsonLinesStreamAsync<T>(HttpResponseMessage, JsonTypeInfo<T>, CancellationToken) where the argument is made in full.

Nothing is sent until the enumeration starts. Calling this method builds a query; the request goes out on the first MoveNextAsync. A caller who never enumerates never bills. The argument checks below run at the call rather than at that first step, so a mistake in them faults where it was made.

Exceptions

ArgumentNullException

parameters is null.

InvalidOperationException

parameters leaves Symbols or DateTimeRange at its type's default value.

DatabentoApiException

The API answered with a non-success status.