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