Skip to main content

ledger_models/
fintekkers.models.security.rs

1#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
2#[repr(i32)]
3pub enum IdentifierTypeProto {
4    UnknownIdentifierType = 0,
5    ExchTicker = 1,
6    Isin = 2,
7    Cusip = 3,
8    Osi = 4,
9    Figi = 5,
10    SeriesId = 6,
11    /// Identifier for index securities (e.g. 'US Treasury Curve', 'S&P 500',
12    /// 'CDX.NA.IG'). Used when productType is one of the *_INDEX leaves and
13    /// there's no exchange-listed ticker or ISIN that uniquely identifies
14    /// the index. Added per second-brain#268.
15    IndexName = 7,
16    Cash = 50,
17}
18impl IdentifierTypeProto {
19    /// String value of the enum field names used in the ProtoBuf definition.
20    ///
21    /// The values are not transformed in any way and thus are considered stable
22    /// (if the ProtoBuf definition does not change) and safe for programmatic use.
23    pub fn as_str_name(&self) -> &'static str {
24        match self {
25            IdentifierTypeProto::UnknownIdentifierType => "UNKNOWN_IDENTIFIER_TYPE",
26            IdentifierTypeProto::ExchTicker => "EXCH_TICKER",
27            IdentifierTypeProto::Isin => "ISIN",
28            IdentifierTypeProto::Cusip => "CUSIP",
29            IdentifierTypeProto::Osi => "OSI",
30            IdentifierTypeProto::Figi => "FIGI",
31            IdentifierTypeProto::SeriesId => "SERIES_ID",
32            IdentifierTypeProto::IndexName => "INDEX_NAME",
33            IdentifierTypeProto::Cash => "CASH",
34        }
35    }
36    /// Creates an enum from field names used in the ProtoBuf definition.
37    pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
38        match value {
39            "UNKNOWN_IDENTIFIER_TYPE" => Some(Self::UnknownIdentifierType),
40            "EXCH_TICKER" => Some(Self::ExchTicker),
41            "ISIN" => Some(Self::Isin),
42            "CUSIP" => Some(Self::Cusip),
43            "OSI" => Some(Self::Osi),
44            "FIGI" => Some(Self::Figi),
45            "SERIES_ID" => Some(Self::SeriesId),
46            "INDEX_NAME" => Some(Self::IndexName),
47            "CASH" => Some(Self::Cash),
48            _ => None,
49        }
50    }
51}
52#[allow(clippy::derive_partial_eq_without_eq)]
53#[derive(Clone, PartialEq, ::prost::Message)]
54pub struct IdentifierProto {
55    #[prost(string, tag = "1")]
56    pub object_class: ::prost::alloc::string::String,
57    #[prost(string, tag = "2")]
58    pub version: ::prost::alloc::string::String,
59    /// Primary Key
60    #[prost(string, tag = "5")]
61    pub identifier_value: ::prost::alloc::string::String,
62    #[prost(enumeration = "IdentifierTypeProto", tag = "6")]
63    pub identifier_type: i32,
64}
65/// Leaf product types — the kind of contract a Security represents.
66///
67/// Authoritative shape lives in ledger-models-protos/hierarchy.json
68/// (single source of truth: parent chain, asset_class, instrument_type,
69/// label, status). Every active leaf in hierarchy.json must have a
70/// matching enum value here; CI guard enforces the round-trip.
71///
72/// Abstract parent nodes (BOND, GOV_BOND, OPTION, EQUITY_OPTION, etc.)
73/// live only in hierarchy.json — they are never assigned to a Security.
74///
75/// Strategies (butterfly, vertical spread, calendar spread, condor,
76/// straddle, ...) are intentionally absent. They are derived from the
77/// SecurityProto.legs field, not from a productType enum value.
78///
79/// Multi-language wrapper helpers (parentOf, descendantsOf,
80/// isDescendantOf, labelOf, assetClassOf, instrumentTypeOf) load
81/// hierarchy.json at startup and dispatch on the leaf identity carried
82/// by ProductTypeProto.
83///
84/// See ../../../hierarchy-examples.md for worked examples and
85/// ../../../registry-versioning.md for compatibility rules on changes
86/// to this enum.
87#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
88#[repr(i32)]
89pub enum ProductTypeProto {
90    ProductTypeUnknown = 0,
91    /// Bonds (1-19)
92    Tbill = 1,
93    TreasuryNote = 2,
94    TreasuryBond = 3,
95    Tips = 4,
96    TreasuryFrn = 5,
97    Strips = 6,
98    SovereignBond = 7,
99    CorpBond = 8,
100    MuniBond = 9,
101    MortgageBacked = 10,
102    /// Stocks (20-29)
103    CommonStock = 20,
104    PreferredStock = 21,
105    Adr = 22,
106    Etf = 23,
107    /// Reference indices and rate series (30-39)
108    EquityIndex = 30,
109    BondIndex = 31,
110    CommodityIndex = 32,
111    VixSpot = 33,
112    CpiSeries = 34,
113    SofrSeries = 35,
114    /// Cash and FX (40-49)
115    Currency = 40,
116    FxSpot = 41,
117    MoneyMarketFund = 42,
118    /// Crypto (50-59)
119    Cryptocurrency = 50,
120    Stablecoin = 51,
121    /// Commodity spot (60-69)
122    Gold = 60,
123    Silver = 61,
124}
125impl ProductTypeProto {
126    /// String value of the enum field names used in the ProtoBuf definition.
127    ///
128    /// The values are not transformed in any way and thus are considered stable
129    /// (if the ProtoBuf definition does not change) and safe for programmatic use.
130    pub fn as_str_name(&self) -> &'static str {
131        match self {
132            ProductTypeProto::ProductTypeUnknown => "PRODUCT_TYPE_UNKNOWN",
133            ProductTypeProto::Tbill => "TBILL",
134            ProductTypeProto::TreasuryNote => "TREASURY_NOTE",
135            ProductTypeProto::TreasuryBond => "TREASURY_BOND",
136            ProductTypeProto::Tips => "TIPS",
137            ProductTypeProto::TreasuryFrn => "TREASURY_FRN",
138            ProductTypeProto::Strips => "STRIPS",
139            ProductTypeProto::SovereignBond => "SOVEREIGN_BOND",
140            ProductTypeProto::CorpBond => "CORP_BOND",
141            ProductTypeProto::MuniBond => "MUNI_BOND",
142            ProductTypeProto::MortgageBacked => "MORTGAGE_BACKED",
143            ProductTypeProto::CommonStock => "COMMON_STOCK",
144            ProductTypeProto::PreferredStock => "PREFERRED_STOCK",
145            ProductTypeProto::Adr => "ADR",
146            ProductTypeProto::Etf => "ETF",
147            ProductTypeProto::EquityIndex => "EQUITY_INDEX",
148            ProductTypeProto::BondIndex => "BOND_INDEX",
149            ProductTypeProto::CommodityIndex => "COMMODITY_INDEX",
150            ProductTypeProto::VixSpot => "VIX_SPOT",
151            ProductTypeProto::CpiSeries => "CPI_SERIES",
152            ProductTypeProto::SofrSeries => "SOFR_SERIES",
153            ProductTypeProto::Currency => "CURRENCY",
154            ProductTypeProto::FxSpot => "FX_SPOT",
155            ProductTypeProto::MoneyMarketFund => "MONEY_MARKET_FUND",
156            ProductTypeProto::Cryptocurrency => "CRYPTOCURRENCY",
157            ProductTypeProto::Stablecoin => "STABLECOIN",
158            ProductTypeProto::Gold => "GOLD",
159            ProductTypeProto::Silver => "SILVER",
160        }
161    }
162    /// Creates an enum from field names used in the ProtoBuf definition.
163    pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
164        match value {
165            "PRODUCT_TYPE_UNKNOWN" => Some(Self::ProductTypeUnknown),
166            "TBILL" => Some(Self::Tbill),
167            "TREASURY_NOTE" => Some(Self::TreasuryNote),
168            "TREASURY_BOND" => Some(Self::TreasuryBond),
169            "TIPS" => Some(Self::Tips),
170            "TREASURY_FRN" => Some(Self::TreasuryFrn),
171            "STRIPS" => Some(Self::Strips),
172            "SOVEREIGN_BOND" => Some(Self::SovereignBond),
173            "CORP_BOND" => Some(Self::CorpBond),
174            "MUNI_BOND" => Some(Self::MuniBond),
175            "MORTGAGE_BACKED" => Some(Self::MortgageBacked),
176            "COMMON_STOCK" => Some(Self::CommonStock),
177            "PREFERRED_STOCK" => Some(Self::PreferredStock),
178            "ADR" => Some(Self::Adr),
179            "ETF" => Some(Self::Etf),
180            "EQUITY_INDEX" => Some(Self::EquityIndex),
181            "BOND_INDEX" => Some(Self::BondIndex),
182            "COMMODITY_INDEX" => Some(Self::CommodityIndex),
183            "VIX_SPOT" => Some(Self::VixSpot),
184            "CPI_SERIES" => Some(Self::CpiSeries),
185            "SOFR_SERIES" => Some(Self::SofrSeries),
186            "CURRENCY" => Some(Self::Currency),
187            "FX_SPOT" => Some(Self::FxSpot),
188            "MONEY_MARKET_FUND" => Some(Self::MoneyMarketFund),
189            "CRYPTOCURRENCY" => Some(Self::Cryptocurrency),
190            "STABLECOIN" => Some(Self::Stablecoin),
191            "GOLD" => Some(Self::Gold),
192            "SILVER" => Some(Self::Silver),
193            _ => None,
194        }
195    }
196}
197/// Mechanical structure of a Security — orthogonal to productType.
198///
199/// Three values:
200///
201///    CASH             A tradable underlying that settles to a position.
202///                     T-Bill, common stock, BTC, FX spot, money-market
203///                     fund, ETF.
204///
205///    DERIVATIVE       A contract whose value derives from an underlying.
206///                     Future, option, swap, forward, FX swap, variance
207///                     swap.
208///
209///    REFERENCE_INDEX  Observational only, never positioned. Used as
210///                     fixings for derivatives or as display benchmarks.
211///                     Cash-index values (.SPX, .NDX, .VIX), reference
212///                     rate series (.SOFR, .CPI), and benchmark indices
213///                     (Bloomberg Commodity Index).
214///
215/// The distinction matters because: .SPX (REFERENCE_INDEX) and SPY (CASH
216/// ETF that tracks .SPX) are both "EQUITY index"-flavoured but only SPY
217/// is positionable; ES future (DERIVATIVE) is positionable but isn't the
218/// same instrument as either.
219///
220/// Enum-value names are prefixed INSTRUMENT_TYPE_* because proto3
221/// enforces package-wide uniqueness for enum value names — bare CASH
222/// would collide with IdentifierTypeProto.CASH in this package.
223#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
224#[repr(i32)]
225pub enum InstrumentTypeProto {
226    InstrumentTypeUnknown = 0,
227    InstrumentTypeCash = 1,
228    InstrumentTypeDerivative = 2,
229    InstrumentTypeReferenceIndex = 3,
230}
231impl InstrumentTypeProto {
232    /// String value of the enum field names used in the ProtoBuf definition.
233    ///
234    /// The values are not transformed in any way and thus are considered stable
235    /// (if the ProtoBuf definition does not change) and safe for programmatic use.
236    pub fn as_str_name(&self) -> &'static str {
237        match self {
238            InstrumentTypeProto::InstrumentTypeUnknown => "INSTRUMENT_TYPE_UNKNOWN",
239            InstrumentTypeProto::InstrumentTypeCash => "INSTRUMENT_TYPE_CASH",
240            InstrumentTypeProto::InstrumentTypeDerivative => "INSTRUMENT_TYPE_DERIVATIVE",
241            InstrumentTypeProto::InstrumentTypeReferenceIndex => {
242                "INSTRUMENT_TYPE_REFERENCE_INDEX"
243            }
244        }
245    }
246    /// Creates an enum from field names used in the ProtoBuf definition.
247    pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
248        match value {
249            "INSTRUMENT_TYPE_UNKNOWN" => Some(Self::InstrumentTypeUnknown),
250            "INSTRUMENT_TYPE_CASH" => Some(Self::InstrumentTypeCash),
251            "INSTRUMENT_TYPE_DERIVATIVE" => Some(Self::InstrumentTypeDerivative),
252            "INSTRUMENT_TYPE_REFERENCE_INDEX" => Some(Self::InstrumentTypeReferenceIndex),
253            _ => None,
254        }
255    }
256}
257#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
258#[repr(i32)]
259pub enum SecurityQuantityTypeProto {
260    /// Maps to Security
261    UnknownQuantityType = 0,
262    OriginalFaceValue = 1,
263    Notional = 2,
264    Units = 3,
265}
266impl SecurityQuantityTypeProto {
267    /// String value of the enum field names used in the ProtoBuf definition.
268    ///
269    /// The values are not transformed in any way and thus are considered stable
270    /// (if the ProtoBuf definition does not change) and safe for programmatic use.
271    pub fn as_str_name(&self) -> &'static str {
272        match self {
273            SecurityQuantityTypeProto::UnknownQuantityType => "UNKNOWN_QUANTITY_TYPE",
274            SecurityQuantityTypeProto::OriginalFaceValue => "ORIGINAL_FACE_VALUE",
275            SecurityQuantityTypeProto::Notional => "NOTIONAL",
276            SecurityQuantityTypeProto::Units => "UNITS",
277        }
278    }
279    /// Creates an enum from field names used in the ProtoBuf definition.
280    pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
281        match value {
282            "UNKNOWN_QUANTITY_TYPE" => Some(Self::UnknownQuantityType),
283            "ORIGINAL_FACE_VALUE" => Some(Self::OriginalFaceValue),
284            "NOTIONAL" => Some(Self::Notional),
285            "UNITS" => Some(Self::Units),
286            _ => None,
287        }
288    }
289}
290#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
291#[repr(i32)]
292pub enum CouponFrequencyProto {
293    /// Maps to Security
294    UnknownCouponFrequency = 0,
295    Annually = 1,
296    Semiannually = 2,
297    Quarterly = 3,
298    Monthly = 4,
299    NoCoupon = 5,
300}
301impl CouponFrequencyProto {
302    /// String value of the enum field names used in the ProtoBuf definition.
303    ///
304    /// The values are not transformed in any way and thus are considered stable
305    /// (if the ProtoBuf definition does not change) and safe for programmatic use.
306    pub fn as_str_name(&self) -> &'static str {
307        match self {
308            CouponFrequencyProto::UnknownCouponFrequency => "UNKNOWN_COUPON_FREQUENCY",
309            CouponFrequencyProto::Annually => "ANNUALLY",
310            CouponFrequencyProto::Semiannually => "SEMIANNUALLY",
311            CouponFrequencyProto::Quarterly => "QUARTERLY",
312            CouponFrequencyProto::Monthly => "MONTHLY",
313            CouponFrequencyProto::NoCoupon => "NO_COUPON",
314        }
315    }
316    /// Creates an enum from field names used in the ProtoBuf definition.
317    pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
318        match value {
319            "UNKNOWN_COUPON_FREQUENCY" => Some(Self::UnknownCouponFrequency),
320            "ANNUALLY" => Some(Self::Annually),
321            "SEMIANNUALLY" => Some(Self::Semiannually),
322            "QUARTERLY" => Some(Self::Quarterly),
323            "MONTHLY" => Some(Self::Monthly),
324            "NO_COUPON" => Some(Self::NoCoupon),
325            _ => None,
326        }
327    }
328}
329#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
330#[repr(i32)]
331pub enum CouponTypeProto {
332    /// Maps to Security
333    UnknownCouponType = 0,
334    Fixed = 1,
335    Float = 2,
336    Zero = 3,
337}
338impl CouponTypeProto {
339    /// String value of the enum field names used in the ProtoBuf definition.
340    ///
341    /// The values are not transformed in any way and thus are considered stable
342    /// (if the ProtoBuf definition does not change) and safe for programmatic use.
343    pub fn as_str_name(&self) -> &'static str {
344        match self {
345            CouponTypeProto::UnknownCouponType => "UNKNOWN_COUPON_TYPE",
346            CouponTypeProto::Fixed => "FIXED",
347            CouponTypeProto::Float => "FLOAT",
348            CouponTypeProto::Zero => "ZERO",
349        }
350    }
351    /// Creates an enum from field names used in the ProtoBuf definition.
352    pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
353        match value {
354            "UNKNOWN_COUPON_TYPE" => Some(Self::UnknownCouponType),
355            "FIXED" => Some(Self::Fixed),
356            "FLOAT" => Some(Self::Float),
357            "ZERO" => Some(Self::Zero),
358            _ => None,
359        }
360    }
361}
362#[allow(clippy::derive_partial_eq_without_eq)]
363#[derive(Clone, PartialEq, ::prost::Message)]
364pub struct SecurityProto {
365    #[prost(string, tag = "1")]
366    pub object_class: ::prost::alloc::string::String,
367    #[prost(string, tag = "2")]
368    pub version: ::prost::alloc::string::String,
369    /// Primary Key
370    #[prost(message, optional, tag = "5")]
371    pub uuid: ::core::option::Option<super::util::UuidProto>,
372    #[prost(message, optional, tag = "6")]
373    pub as_of: ::core::option::Option<super::util::LocalTimestampProto>,
374    /// When true, this message is a lightweight reference — only uuid is populated.
375    /// The caller must resolve the full entity by calling SecurityService.GetByIds
376    /// with this UUID. Used when embedding a SecurityProto inside another message
377    /// (e.g. PriceProto.security, TransactionProto.security) to avoid duplicating
378    /// the full security data. See docs/adr/is_link_pattern.md for details.
379    #[prost(bool, tag = "7")]
380    pub is_link: bool,
381    #[prost(message, optional, tag = "8")]
382    pub valid_from: ::core::option::Option<super::util::LocalTimestampProto>,
383    #[prost(message, optional, tag = "9")]
384    pub valid_to: ::core::option::Option<super::util::LocalTimestampProto>,
385    #[prost(enumeration = "ProductTypeProto", tag = "10")]
386    pub product_type: i32,
387    /// Orthogonal to product_type — see instrument_type.proto.
388    /// CASH (positionable), DERIVATIVE (value derives from underlying),
389    /// REFERENCE_INDEX (observational only).
390    #[prost(enumeration = "InstrumentTypeProto", tag = "16")]
391    pub instrument_type: i32,
392    /// Multi-leg strategy package legs — each leg is itself a Security
393    /// referenced by UUID using the is_link=true pattern (see
394    /// docs/adr/is_link_pattern.md). See hierarchy-examples.md for the
395    /// pattern: butterflies, calendar spreads, iron condors, etc. are not
396    /// productTypes; they're a Security whose product_type is the
397    /// underlying vanilla type with `legs` populated.
398    ///
399    /// Each leg MUST have is_link=true with uuid and as_of populated.
400    /// Resolve full legs via SecurityService.GetByIds.
401    ///
402    /// WIRE COMPATIBLE with the prior SecurityIdProto type at this tag:
403    /// SecurityIdProto carried uuid at tag 1, identical to SecurityProto.
404    /// Legacy persisted bytes parse correctly under the new type.
405    #[prost(message, repeated, tag = "17")]
406    pub legs: ::prost::alloc::vec::Vec<SecurityProto>,
407    /// Soft-delete marker. null/unset = active record; non-null = soft-deleted
408    /// at this timestamp. SecurityService.Search and GetByIds filter out
409    /// soft-deleted records by default. Setting deleted_at via CreateOrUpdate
410    /// is a soft-delete; clearing it on a subsequent CreateOrUpdate resurrects
411    /// the record.
412    /// See: <https://github.com/FinTekkers/second-brain/issues/188>
413    #[prost(message, optional, tag = "15")]
414    pub deleted_at: ::core::option::Option<super::util::LocalTimestampProto>,
415    /// Biz fields
416    #[prost(string, tag = "11")]
417    pub asset_class: ::prost::alloc::string::String,
418    #[prost(string, tag = "12")]
419    pub issuer_name: ::prost::alloc::string::String,
420    #[prost(message, optional, boxed, tag = "13")]
421    pub settlement_currency: ::core::option::Option<
422        ::prost::alloc::boxed::Box<SecurityProto>,
423    >,
424    #[prost(enumeration = "SecurityQuantityTypeProto", tag = "14")]
425    pub quantity_type: i32,
426    #[prost(string, tag = "41")]
427    pub description: ::prost::alloc::string::String,
428    /// All known identifiers for this security. The primary identifier (used as
429    /// the human-readable ID) is the first entry. Secondary identifiers follow.
430    /// For Gilts, entry 0 will be {type=ISIN, value="GB..."}; for US Treasuries,
431    /// entry 0 will be {type=CUSIP, value="912828..."}.
432    #[prost(message, repeated, tag = "42")]
433    pub identifiers: ::prost::alloc::vec::Vec<IdentifierProto>,
434    /// Bond-shape details. Populated for any product_type descending from BOND
435    /// in hierarchy.json (TBILL, TREASURY_NOTE, TREASURY_BOND, TIPS,
436    /// TREASURY_FRN, STRIPS, SOVEREIGN_BOND, CORP_BOND, MUNI_BOND, ...).
437    /// Single canonical home for the 8 shared bond fields. Null for non-bonds.
438    #[prost(message, optional, tag = "200")]
439    pub bond_details: ::core::option::Option<BondDetailsProto>,
440    /// TIPS-specific extras. Populated when product_type == TIPS.
441    /// Co-exists with bond_details (does NOT replace it).
442    #[prost(message, optional, tag = "201")]
443    pub tips_extension: ::core::option::Option<TipsExtensionProto>,
444    /// FRN-specific extras. Populated when product_type == TREASURY_FRN.
445    /// Co-exists with bond_details (does NOT replace it).
446    #[prost(message, optional, tag = "202")]
447    pub frn_extension: ::core::option::Option<FrnExtensionProto>,
448    /// Agency MBS pass-through extras. Populated when
449    /// product_type == MORTGAGE_BACKED. Co-exists with bond_details
450    /// (does NOT replace it) — pool-level coupon / face / maturity
451    /// are still on bond_details.
452    #[prost(message, optional, tag = "207")]
453    pub mbs_extension: ::core::option::Option<MbsExtensionProto>,
454    /// Non-bond product details. These ARE mutually exclusive — Cash, Equity,
455    /// Index, FxSpot have no shared shape — so a oneof fits.
456    #[prost(oneof = "security_proto::NonBondDetails", tags = "203, 204, 205, 206")]
457    pub non_bond_details: ::core::option::Option<security_proto::NonBondDetails>,
458}
459/// Nested message and enum types in `SecurityProto`.
460pub mod security_proto {
461    /// Non-bond product details. These ARE mutually exclusive — Cash, Equity,
462    /// Index, FxSpot have no shared shape — so a oneof fits.
463    #[allow(clippy::derive_partial_eq_without_eq)]
464    #[derive(Clone, PartialEq, ::prost::Oneof)]
465    pub enum NonBondDetails {
466        #[prost(message, tag = "203")]
467        IndexDetails(super::IndexDetailsProto),
468        #[prost(message, tag = "204")]
469        EquityDetails(super::EquityDetailsProto),
470        #[prost(message, tag = "205")]
471        CashDetails(super::CashDetailsProto),
472        #[prost(message, tag = "206")]
473        FxSpotDetails(::prost::alloc::boxed::Box<super::FxSpotDetailsProto>),
474    }
475}
476/// Bond security details: fixed-rate coupon bonds (US Treasuries, corporates, etc.)
477#[allow(clippy::derive_partial_eq_without_eq)]
478#[derive(Clone, PartialEq, ::prost::Message)]
479pub struct BondDetailsProto {
480    /// Expressed as a decimal fraction (0.05=5%, 0.0075=0.75%). Do NOT use percentage form (5.0 will be rejected).
481    #[prost(message, optional, tag = "1")]
482    pub coupon_rate: ::core::option::Option<super::util::DecimalValueProto>,
483    #[prost(enumeration = "CouponTypeProto", tag = "2")]
484    pub coupon_type: i32,
485    #[prost(enumeration = "CouponFrequencyProto", tag = "3")]
486    pub coupon_frequency: i32,
487    #[prost(message, optional, tag = "4")]
488    pub dated_date: ::core::option::Option<super::util::LocalDateProto>,
489    #[prost(message, optional, tag = "5")]
490    pub face_value: ::core::option::Option<super::util::DecimalValueProto>,
491    #[prost(message, optional, tag = "6")]
492    pub issue_date: ::core::option::Option<super::util::LocalDateProto>,
493    #[prost(message, optional, tag = "7")]
494    pub maturity_date: ::core::option::Option<super::util::LocalDateProto>,
495    #[prost(message, repeated, tag = "8")]
496    pub issuance_info: ::prost::alloc::vec::Vec<bond::IssuanceProto>,
497}
498/// TIPS (Treasury Inflation-Protected Securities) extras.
499/// Carries ONLY the TIPS-specific fields; shared bond fields live in
500/// SecurityProto.bond_details. Populated when product_type == TIPS.
501#[allow(clippy::derive_partial_eq_without_eq)]
502#[derive(Clone, PartialEq, ::prost::Message)]
503pub struct TipsExtensionProto {
504    /// Reference CPI at bond issuance (e.g. 256.394)
505    #[prost(message, optional, tag = "1")]
506    pub base_cpi: ::core::option::Option<super::util::DecimalValueProto>,
507    /// The date the base CPI was observed
508    #[prost(message, optional, tag = "2")]
509    pub index_date: ::core::option::Option<super::util::LocalDateProto>,
510    /// Which inflation index (e.g. CPI_U)
511    #[prost(enumeration = "index::IndexTypeProto", tag = "3")]
512    pub inflation_index_type: i32,
513}
514/// Floating Rate Note (FRN) extras.
515/// Carries ONLY the FRN-specific fields; shared bond fields live in
516/// SecurityProto.bond_details. Populated when product_type == TREASURY_FRN.
517#[allow(clippy::derive_partial_eq_without_eq)]
518#[derive(Clone, PartialEq, ::prost::Message)]
519pub struct FrnExtensionProto {
520    /// Fixed spread over the reference rate, in basis points
521    #[prost(message, optional, tag = "1")]
522    pub spread: ::core::option::Option<super::util::DecimalValueProto>,
523    /// Which floating rate benchmark (e.g. SOFR)
524    #[prost(enumeration = "index::IndexTypeProto", tag = "2")]
525    pub reference_rate_index: i32,
526    /// How often the floating coupon rate resets
527    #[prost(enumeration = "CouponFrequencyProto", tag = "3")]
528    pub reset_frequency: i32,
529}
530/// Agency MBS pass-through extras (FNMA / FHLMC / GNMA).
531/// Carries pool-level fields beyond what BondDetailsProto already covers
532/// (coupon, face value, maturity date). Populated when
533/// product_type == MORTGAGE_BACKED.
534#[allow(clippy::derive_partial_eq_without_eq)]
535#[derive(Clone, PartialEq, ::prost::Message)]
536pub struct MbsExtensionProto {
537    /// Agency pool identifier (e.g. "FN AS1234")
538    #[prost(string, tag = "1")]
539    pub pool_number: ::prost::alloc::string::String,
540    /// Issuing agency
541    #[prost(enumeration = "bond::AgencyProto", tag = "2")]
542    pub agency: i32,
543    /// Weighted-average coupon (decimal fraction; 0.045 = 4.5%)
544    #[prost(message, optional, tag = "3")]
545    pub wac: ::core::option::Option<super::util::DecimalValueProto>,
546    /// Weighted-average maturity, in months
547    #[prost(int32, tag = "4")]
548    pub wam: i32,
549    /// Pass-through coupon paid to investors (decimal fraction)
550    #[prost(message, optional, tag = "5")]
551    pub pass_through_rate: ::core::option::Option<super::util::DecimalValueProto>,
552    /// Current pool factor (fraction of original principal remaining)
553    #[prost(message, optional, tag = "6")]
554    pub current_factor: ::core::option::Option<super::util::DecimalValueProto>,
555    /// Original face / par at issuance
556    #[prost(message, optional, tag = "7")]
557    pub original_face_value: ::core::option::Option<super::util::DecimalValueProto>,
558    /// Current unpaid principal balance
559    #[prost(message, optional, tag = "8")]
560    pub current_upb: ::core::option::Option<super::util::DecimalValueProto>,
561    /// Prepayment speed assumption (PSA model multiplier)
562    #[prost(message, optional, tag = "9")]
563    pub psa_speed: ::core::option::Option<super::util::DecimalValueProto>,
564}
565/// Index security details (e.g. CPI-U, SOFR index, S&P 500).
566#[allow(clippy::derive_partial_eq_without_eq)]
567#[derive(Clone, PartialEq, ::prost::Message)]
568pub struct IndexDetailsProto {
569    #[prost(enumeration = "index::IndexTypeProto", tag = "1")]
570    pub index_type: i32,
571    /// Populated when QuerySecurityRequestProto.lookthrough=true. Server-side
572    /// resolver computes constituents for the request asOf. Each constituent
573    /// is a SecurityProto with is_link=true (uuid + as_of populated; resolve
574    /// full security via SecurityService.GetByIds).
575    /// See docs/adr/is_link_pattern.md.
576    #[prost(message, repeated, tag = "2")]
577    pub constituents: ::prost::alloc::vec::Vec<SecurityProto>,
578}
579/// Equity security details. Minimal for now — placeholder for future fields
580/// (e.g. shares_outstanding, dividend_yield, sector).
581///
582/// No equity-specific fields exist yet. This message serves as a type marker
583/// in the oneof and a home for future equity-specific fields.
584#[allow(clippy::derive_partial_eq_without_eq)]
585#[derive(Clone, PartialEq, ::prost::Message)]
586pub struct EquityDetailsProto {}
587/// Cash security details.
588#[allow(clippy::derive_partial_eq_without_eq)]
589#[derive(Clone, PartialEq, ::prost::Message)]
590pub struct CashDetailsProto {
591    /// e.g. "USD", "EUR", "GBP"
592    #[prost(string, tag = "1")]
593    pub cash_id: ::prost::alloc::string::String,
594}
595/// FX spot pair details.
596/// Represents a spot foreign exchange rate between two currencies.
597/// The pair is expressed as: price = units of quote_currency per 1 unit of base_currency.
598/// Example: USD/GBP with convention UNITS_OF_QUOTE_PER_BASE means the price is
599/// "how many GBP you receive for 1 USD" (e.g. 0.79).
600#[allow(clippy::derive_partial_eq_without_eq)]
601#[derive(Clone, PartialEq, ::prost::Message)]
602pub struct FxSpotDetailsProto {
603    /// The currency being bought/sold (e.g. USD cash security). Must be a CashDetailsProto with is_link=true.
604    #[prost(message, optional, boxed, tag = "1")]
605    pub base_currency: ::core::option::Option<::prost::alloc::boxed::Box<SecurityProto>>,
606    /// The currency in which the price is expressed (e.g. GBP cash security). Must be a CashDetailsProto with is_link=true.
607    #[prost(message, optional, boxed, tag = "2")]
608    pub quote_currency: ::core::option::Option<
609        ::prost::alloc::boxed::Box<SecurityProto>,
610    >,
611    /// Quoting convention — always "UNITS_OF_QUOTE_PER_BASE" for spot FX (ISO standard)
612    #[prost(string, tag = "3")]
613    pub convention: ::prost::alloc::string::String,
614}
615/// Canonical vocabulary for the asset class of a security.
616///
617/// Note: the SecurityProto.asset_class field is currently `string` (security.proto
618/// field 11). This enum defines the canonical values; the field type stays
619/// string in this release to avoid coordinating a breaking change with
620/// ledger-service / valuation-service / market-data-inputs. A follow-up
621/// will flip the field type after a data-normalization audit.
622///
623/// Initial values are conservative — only those with active usage in the
624/// codebase as of the v0.1.x line:
625///    Cash, Equity, Fixed Income, Index
626/// Add new variants only when there is concrete consumer demand.
627///
628/// Naming note: proto3 enforces package-wide uniqueness for enum value
629/// names (C++ scoping rules — enum values are siblings of their type, not
630/// children of it). `IdentifierTypeProto.CASH` already exists in this
631/// package, so the cash-asset-class value is named `CASH_ASSET_CLASS` to
632/// disambiguate. The other values (FIXED_INCOME, EQUITY, INDEX) are
633/// unique within the package and stay bare.
634#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
635#[repr(i32)]
636pub enum AssetClassProto {
637    UnknownAssetClass = 0,
638    FixedIncome = 1,
639    Equity = 2,
640    CashAssetClass = 3,
641    /// INDEX covers reference instruments like SP500, CMT-derived treasury
642    /// indices, etc. — used in market-data-inputs today. Borderline as an
643    /// "asset class" in finance terminology, but matches in-use data.
644    Index = 4,
645    /// VOLATILITY covers volatility-class reference instruments — VIX
646    /// (CBOE Volatility Index), VVIX, etc. Stored as INDEX_SECURITY at the
647    /// proto type level (these are reference indices, not holdable
648    /// instruments) but distinct asset_class to differentiate from
649    /// equity / fixed-income reference indices like SP500 or CMT yields.
650    /// Added per FinTekkers/second-brain#236.
651    Volatility = 5,
652    /// CRYPTO covers cryptocurrency holdings — BTC, ETH, and other crypto
653    /// assets. Pairs with ProductTypeProto.CRYPTOCURRENCY. Added per
654    /// FinTekkers/second-brain#237.
655    Crypto = 6,
656}
657impl AssetClassProto {
658    /// String value of the enum field names used in the ProtoBuf definition.
659    ///
660    /// The values are not transformed in any way and thus are considered stable
661    /// (if the ProtoBuf definition does not change) and safe for programmatic use.
662    pub fn as_str_name(&self) -> &'static str {
663        match self {
664            AssetClassProto::UnknownAssetClass => "UNKNOWN_ASSET_CLASS",
665            AssetClassProto::FixedIncome => "FIXED_INCOME",
666            AssetClassProto::Equity => "EQUITY",
667            AssetClassProto::CashAssetClass => "CASH_ASSET_CLASS",
668            AssetClassProto::Index => "INDEX",
669            AssetClassProto::Volatility => "VOLATILITY",
670            AssetClassProto::Crypto => "CRYPTO",
671        }
672    }
673    /// Creates an enum from field names used in the ProtoBuf definition.
674    pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
675        match value {
676            "UNKNOWN_ASSET_CLASS" => Some(Self::UnknownAssetClass),
677            "FIXED_INCOME" => Some(Self::FixedIncome),
678            "EQUITY" => Some(Self::Equity),
679            "CASH_ASSET_CLASS" => Some(Self::CashAssetClass),
680            "INDEX" => Some(Self::Index),
681            "VOLATILITY" => Some(Self::Volatility),
682            "CRYPTO" => Some(Self::Crypto),
683            _ => None,
684        }
685    }
686}
687/// A point-in-time snapshot of an equity index's constituent securities and weights.
688///
689/// Temporal model (identical to PriceProto):
690///    uuid        — stable identity for this composition record
691///    as_of       — the timestamp this composition was observed / recorded
692///    valid_from  — bitemporal: when this record became system-valid
693///    valid_to    — bitemporal: when this record was superseded
694///    is_link     — if true, only uuid is meaningful; resolve via GetByIds
695///
696/// A new IndexCompositionProto is created whenever the index is rebalanced.
697/// The effective_date field marks the business date the new composition took effect.
698/// To find the composition active on a given date D, query for the most recent
699/// record where effective_date <= D.
700#[allow(clippy::derive_partial_eq_without_eq)]
701#[derive(Clone, PartialEq, ::prost::Message)]
702pub struct IndexCompositionProto {
703    #[prost(string, tag = "1")]
704    pub object_class: ::prost::alloc::string::String,
705    #[prost(string, tag = "2")]
706    pub version: ::prost::alloc::string::String,
707    /// Primary Key (same temporal pattern as SecurityProto and PriceProto)
708    #[prost(message, optional, tag = "5")]
709    pub uuid: ::core::option::Option<super::util::UuidProto>,
710    #[prost(message, optional, tag = "6")]
711    pub as_of: ::core::option::Option<super::util::LocalTimestampProto>,
712    #[prost(bool, tag = "7")]
713    pub is_link: bool,
714    #[prost(message, optional, tag = "8")]
715    pub valid_from: ::core::option::Option<super::util::LocalTimestampProto>,
716    #[prost(message, optional, tag = "9")]
717    pub valid_to: ::core::option::Option<super::util::LocalTimestampProto>,
718    /// The index security this composition belongs to (EQUITY_INDEX_SECURITY type).
719    /// Typically is_link = true; resolve via SecurityService.GetByIds.
720    #[prost(message, optional, tag = "10")]
721    pub index_security: ::core::option::Option<SecurityProto>,
722    /// The calendar date on which this composition became effective (the rebalance date).
723    /// Temporal lookup key: given as_of_date D, return the composition where
724    /// effective_date <= D, ordered by effective_date DESC, LIMIT 1.
725    #[prost(message, optional, tag = "11")]
726    pub effective_date: ::core::option::Option<super::util::LocalDateProto>,
727    /// The full list of constituents at this rebalance point.
728    #[prost(message, repeated, tag = "20")]
729    pub constituents: ::prost::alloc::vec::Vec<IndexConstituentProto>,
730    /// For price-weighted indices (e.g. DJIA), the divisor at this rebalance point.
731    /// Divisors change when constituents change or corporate actions occur.
732    /// index_level = sum(price_i * shares_i) / index_divisor
733    #[prost(message, optional, tag = "21")]
734    pub index_divisor: ::core::option::Option<super::util::DecimalValueProto>,
735    /// Free-form notes (e.g. "Quarterly rebalance — removed XYZ, added ABC").
736    #[prost(string, tag = "31")]
737    pub notes: ::prost::alloc::string::String,
738}
739/// A single constituent within an index at a specific rebalance point.
740#[allow(clippy::derive_partial_eq_without_eq)]
741#[derive(Clone, PartialEq, ::prost::Message)]
742pub struct IndexConstituentProto {
743    /// The constituent equity security.
744    /// Typically is_link = true; resolve via SecurityService.GetByIds.
745    #[prost(message, optional, tag = "1")]
746    pub security: ::core::option::Option<SecurityProto>,
747    /// Weight of this constituent in the index, expressed as a decimal fraction
748    /// (e.g. 0.05 = 5%). Used for market-cap-weighted and equal-weighted indices.
749    /// For price-weighted indices, leave unset; use shares_in_index instead.
750    #[prost(message, optional, tag = "2")]
751    pub weight: ::core::option::Option<super::util::DecimalValueProto>,
752    /// Number of shares used in price-weighted index calculation (e.g. DJIA).
753    /// For non-price-weighted indices, leave unset; use weight instead.
754    #[prost(message, optional, tag = "3")]
755    pub shares_in_index: ::core::option::Option<super::util::DecimalValueProto>,
756    /// The currency of the constituent's price (e.g. "USD"). Needed for multi-currency indices.
757    #[prost(string, tag = "5")]
758    pub currency: ::prost::alloc::string::String,
759}
760#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
761#[repr(i32)]
762pub enum TenorTypeProto {
763    UnknownTenorType = 0,
764    Perpetual = 1,
765    Term = 2,
766}
767impl TenorTypeProto {
768    /// String value of the enum field names used in the ProtoBuf definition.
769    ///
770    /// The values are not transformed in any way and thus are considered stable
771    /// (if the ProtoBuf definition does not change) and safe for programmatic use.
772    pub fn as_str_name(&self) -> &'static str {
773        match self {
774            TenorTypeProto::UnknownTenorType => "UNKNOWN_TENOR_TYPE",
775            TenorTypeProto::Perpetual => "PERPETUAL",
776            TenorTypeProto::Term => "TERM",
777        }
778    }
779    /// Creates an enum from field names used in the ProtoBuf definition.
780    pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
781        match value {
782            "UNKNOWN_TENOR_TYPE" => Some(Self::UnknownTenorType),
783            "PERPETUAL" => Some(Self::Perpetual),
784            "TERM" => Some(Self::Term),
785            _ => None,
786        }
787    }
788}
789#[allow(clippy::derive_partial_eq_without_eq)]
790#[derive(Clone, PartialEq, ::prost::Message)]
791pub struct TenorProto {
792    #[prost(string, tag = "1")]
793    pub object_class: ::prost::alloc::string::String,
794    #[prost(string, tag = "2")]
795    pub version: ::prost::alloc::string::String,
796    #[prost(string, tag = "5")]
797    pub term_value: ::prost::alloc::string::String,
798    #[prost(enumeration = "TenorTypeProto", tag = "6")]
799    pub tenor_type: i32,
800}