Table of Contents

Class AdjustmentFactor

Namespace
DatabentoDotNet.Reference
Assembly
DatabentoDotNet.Reference.dll

One row of an adjustment_factors.get_range response: an event that changes how a security's historical prices must be scaled, and the multiplier that does it.

public sealed record AdjustmentFactor : IEquatable<AdjustmentFactor>
Inheritance
AdjustmentFactor
Implements
Inherited Members

Remarks

Port of upstream's AdjustmentFactor (adjustment.rs:92-169), field for field and in its order. Twenty-eight properties, fourteen of them optional — upstream's Option in every case, never a judgement made here.

The four rate fields are decimal where upstream has f64, and this is the type that owns that decision for all three reference models. See Factor, which carries the measurement.

Two spellings of "absent" appear below, and the difference is upstream's rather than a choice. A missing string is null; a missing reference code — DividendCurrency, Frequency — is that type's default, whose HasValue is false. A nullable code struct would give the same field two ways to say nothing, and IReferenceCode<TSelf> already defines one.

Currency is a string while DividendCurrency is a Currency, and that asymmetry is reproduced rather than tidied. Upstream types the two fields differently in adjacent lines (adjustment.rs:147 against :157). Making them agree would be a behavioural change to a field neither library has probed: the closing-price currency would start rejecting nothing and start reporting IsKnown, which reads as new information when it would only be a new guess. #57 is where a real row says which spelling the server actually uses for each.

The rows arrive in the server's order and this library does not sort them. Upstream sorts its Vec by ExDate after buffering the whole response (adjustment.rs:51); GetRangeAsync(AdjustmentFactorsGetRangeParams, CancellationToken) streams, and a stream cannot be sorted. See that method, and ROADMAP.md §6.

Properties

Close

The closing price on ExDate, or null.

public decimal? Close { get; init; }

Property Value

decimal?

Remarks

decimal for the reason Factor gives.

Currency

The currency of Close, or null.

public string? Currency { get; init; }

Property Value

string

Remarks

A bare string, unlike DividendCurrency. Upstream's asymmetry, reproduced deliberately — see this type's remarks.

Detail

A human-readable description of the event.

public required string Detail { get; init; }

Property Value

string

DividendCurrency

The currency the dividend is paid in, or default when the row carries none.

public Currency DividendCurrency { get; init; }

Property Value

Currency

Remarks

A Currency where Currency is a string — upstream's asymmetry, reproduced. See this type's remarks.

Event

The event type.

public required Event Event { get; init; }

Property Value

Event

Remarks

An open carrier rather than an enum: a code Databento adds to the EVENT dictionary is kept rather than rejected. See Event.

EventId

Event identifier, unique at the event level. Links to a corporate action's event_id.

public required string EventId { get; init; }

Property Value

string

ExDate

The date from which the event is effective.

public required LocalDate ExDate { get; init; }

Property Value

LocalDate

Remarks

A LocalDate, not a DateOnly — CLAUDE.md, "Dates and times". It carries no zone because the wire does not: the field is yyyy-MM-dd, and attaching a zone here would invent one. This is the key upstream sorts its buffered response by.

Exchange

Exchange code for the listing, or null.

public string? Exchange { get; init; }

Property Value

string

Remarks

Equivalent to the MIC but more stable: a MIC may not be published in a timely fashion, and a MIC can change while the exchange stays the same.

Factor

The adjustment factor to apply.

public required decimal Factor { get; init; }

Property Value

decimal

Remarks

decimal rather than upstream's f64, and this property is where that decision was made for all four rate fields here and for the eight in #54 and #55. This is the multiplier applied to historical prices, so it is the field where the choice bites hardest; GetCostAsync(MetadataQueryParams, CancellationToken) and CostUsd already made the same call for money on the historical side.

What was measured, on .NET 10, because the obvious argument for it is wrong. The claim this decision was originally written around — that a rate round-trips through decimal and not through double — does not survive a probe. System.Text.Json writes a double in shortest-round-trip form, so any wire value of seventeen significant digits or fewer comes back out spelled exactly as it arrived; upstream's own fixture value 0.995833170541121 does, and so does 0.3333333333333333. What double actually loses is not the text but the value: 0.995833170541121 * 51.19 is 50.97669999999998399 exactly and 50.97669999999998 in binary floating point. A factor exists to be multiplied by a price, so that is the number that matters, and it is the reason the answer here is still decimal.

The cost, also measured rather than assumed, and it is two-sided. Above MaxValue (~7.9 × 10^28) System.Text.Json throws a JsonException naming the property path — loud, diagnosable, and confined to the row. Below ~10^-28 it does not throw: the value silently reads as zero, which is the worse of the two failures and the one to know about. Neither bound is reachable by a price, a dividend, a ratio near one, or a split factor, so the risk is remote rather than absent.

The magnitudes actually present in a live response are still unprobed, and #57 turned that from an unopened question into a measured obstacle. RealReferenceRequestTests.TheRateFields_CarryMagnitudesDecimalHoldsComfortably reads every factor, close, gross_dividend and sentiment a real response carries, plus the values of CorporateAction.RateInfo, and reports any magnitude outside a band far inside the two bounds above. Reaching its assertions at all is most of the answer — a value beyond MaxValue throws in the converter, before any assertion runs. On 2026-08-29 the account it ran under was answered 403 license_reference_dataset_no_subscription: reference data is a separate Databento product, and three separate subscriptions at that. So this remains the disclosure #53 asked for in place of a probe, and the probe now exists and is gated on DATABENTO_REFERENCE_REQUEST rather than on anyone remembering to write it.

Frequency

How often the dividend is paid, or default when the row carries none.

public Frequency Frequency { get; init; }

Property Value

Frequency

GrossDividend

The dividend before taxes or fees — the total declared by the company — or null.

public decimal? GrossDividend { get; init; }

Property Value

decimal?

Remarks

decimal for the reason Factor gives.

Isin

The ISIN global identifier, as an ISO 6166 string, or null.

public string? Isin { get; init; }

Property Value

string

IsinResulting

The resulting ISIN where applicable and known, or null.

public string? IsinResulting { get; init; }

Property Value

string

IssuerName

The issuer name.

public required string IssuerName { get; init; }

Property Value

string

LocalCode

The local code, or null.

public string? LocalCode { get; init; }

Property Value

string

Remarks

Usually unique at market level, with exceptions. Either an alphabetic string or a number, so it stays a string either way.

LocalCodeResulting

The resulting local code where applicable and known, or null.

public string? LocalCodeResulting { get; init; }

Property Value

string

NasdaqSymbol

The Nasdaq Integrated Platform suffix-convention symbol, or null.

public string? NasdaqSymbol { get; init; }

Property Value

string

OperatingMic

Market Identifier Code (MIC), as an ISO 10383 string.

public required string OperatingMic { get; init; }

Property Value

string

Option

The choice or option number, where shareholders were given several ways to take the benefit — cash or scrip, for instance.

public required uint Option { get; init; }

Property Value

uint

Remarks

A bare uint, for the reason Reason records: the vendored dictionary describes no vocabulary for it either. Named Option on the wire; the C# property keeps that name because it is what the field is called, and nothing in this language reserves it.

PrimaryExchange

Exchange code for the primary security, or null.

public string? PrimaryExchange { get; init; }

Property Value

string

Reason

The reason code, distinguishing event types within Event.

public required uint Reason { get; init; }

Property Value

uint

Remarks

A bare uint, and that was checked rather than assumed. #53's porting notes asked whether this is really a closed set before shipping one. The vendored corporate_actions.list_enums response — the oracle the ten open carriers and the nine closed enums were both transcribed from — has 235 groups and describes this field in none of them. Its REASON group is a different vocabulary entirely (C, H, blank); the four groups whose codes are numeric are CLASSCODE, INDUS, MKTSG and REPAYSRC, none of which is an adjustment reason. That is consistent with AdjustmentStatus: the dictionary documents corporate actions, and this is an adjustment_factors field.

So there is no table to model against and an enum here would be invented rather than ported. #57 is where real rows can say what values occur.

SecurityId

Security-level numerical ID, linking every listing of the same security together.

public required string SecurityId { get; init; }

Property Value

string

SecurityType

The security type.

public required SecurityType SecurityType { get; init; }

Property Value

SecurityType

Remarks

The field that makes SecurityType's open-carrier shape load-bearing rather than tidy. Upstream types this as a bare SecurityType — not an Option — over an enum modelling 30 of the 64 codes the live dictionary reports, so one of the 34 it does not know fails the whole row rather than one field. Here an unmodelled code arrives in Code with IsKnown false.

Sentiment

Market sentiment: the previous close divided by today's open — the market's reaction to the event.

public required decimal Sentiment { get; init; }

Property Value

decimal

Remarks

Only meaningful when the factor calculation required the previous close. Upstream carries the same caveat and the same non-optional type, so a row without one still reports a number. decimal for the reason Factor gives.

Status

The adjustment status.

public required AdjustmentStatus Status { get; init; }

Property Value

AdjustmentStatus

Remarks

One of the nine closed enums: three single-character codes, and an unrecognised one is an error rather than an opaque value. See AdjustmentStatus, which records that it is also the one of the nine with no independent check yet.

Symbol

The query input symbol this row matched, or null.

public string? Symbol { get; init; }

Property Value

string

TsCreated

When Databento added the record, in UTC.

public required Instant TsCreated { get; init; }

Property Value

Instant

Remarks

An Instant, not a DateTimeOffset. Upstream reads this through its own deserialize_date_time rather than serde's default, which is exactly the set of spellings InstantJsonConverter reads.

UsCode

The US domestic CUSIP, or null.

public string? UsCode { get; init; }

Property Value

string