Skip to main content

ledger_models/
fintekkers.models.position.rs

1#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
2#[repr(i32)]
3pub enum FieldProto {
4    UnknownField = 0,
5    /// (UUID.class)
6    Id = 1,
7    /// ZonedDateTime
8    AsOf = 2,
9    /// Attribute fields. Likely to be fields that one would pivot on.
10    ///
11    /// LocalDate.class
12    EffectiveDate = 10,
13    /// common.model.strategy.Strategy.class
14    Strategy = 11,
15    /// common.model.security.Security.class
16    Security = 12,
17    SecurityDescription = 61,
18    SecurityIssuerName = 62,
19    /// common.model.security.Security.class
20    CashImpactSecurity = 13,
21    /// Security Fields
22    ///
23    ///   AssetClass(String.class), //FixedIncome, Equity, etc
24    AssetClass = 50,
25    /// ProductClass(String.class), //Bond, CashEquity, etc
26    ProductClass = 51,
27    /// ProductType (String.class), //TBILL, BOND, etc
28    ProductType = 52,
29    SecurityId = 53,
30    Identifier = 54,
31    /// 1M
32    Tenor = 55,
33    IssueDate = 58,
34    MaturityDate = 56,
35    AdjustedTenor = 57,
36    /// Portfolio fields
37    ///
38    /// common.model.portfolio.Portfolio.class
39    Portfolio = 14,
40    /// UUID
41    PortfolioId = 15,
42    PortfolioName = 60,
43    /// Miscellaneous
44    ///
45    /// common.model.price.Price.class
46    Price = 16,
47    /// UUID
48    PriceId = 17,
49    /// Boolean.class
50    IsCancelled = 18,
51    /// PositionStatus.class
52    PositionStatus = 19,
53    /// Transaction only
54    ///
55    /// TradeDate(LocalDate.class),
56    TradeDate = 30,
57    ///   SettlementDate(LocalDate.class),
58    SettlementDate = 31,
59    /// BUY, SELL, MATURATION, etc (TransactionType.class)
60    TransactionType = 32,
61    /// Tax Lot only
62    ///
63    ///   TaxLotOpenDate(LocalDate.class),
64    TaxLotOpenDate = 40,
65    ///   TaxLotCloseDate(LocalDate.class),
66    TaxLotCloseDate = 41,
67}
68impl FieldProto {
69    /// String value of the enum field names used in the ProtoBuf definition.
70    ///
71    /// The values are not transformed in any way and thus are considered stable
72    /// (if the ProtoBuf definition does not change) and safe for programmatic use.
73    pub fn as_str_name(&self) -> &'static str {
74        match self {
75            FieldProto::UnknownField => "UNKNOWN_FIELD",
76            FieldProto::Id => "ID",
77            FieldProto::AsOf => "AS_OF",
78            FieldProto::EffectiveDate => "EFFECTIVE_DATE",
79            FieldProto::Strategy => "STRATEGY",
80            FieldProto::Security => "SECURITY",
81            FieldProto::SecurityDescription => "SECURITY_DESCRIPTION",
82            FieldProto::SecurityIssuerName => "SECURITY_ISSUER_NAME",
83            FieldProto::CashImpactSecurity => "CASH_IMPACT_SECURITY",
84            FieldProto::AssetClass => "ASSET_CLASS",
85            FieldProto::ProductClass => "PRODUCT_CLASS",
86            FieldProto::ProductType => "PRODUCT_TYPE",
87            FieldProto::SecurityId => "SECURITY_ID",
88            FieldProto::Identifier => "IDENTIFIER",
89            FieldProto::Tenor => "TENOR",
90            FieldProto::IssueDate => "ISSUE_DATE",
91            FieldProto::MaturityDate => "MATURITY_DATE",
92            FieldProto::AdjustedTenor => "ADJUSTED_TENOR",
93            FieldProto::Portfolio => "PORTFOLIO",
94            FieldProto::PortfolioId => "PORTFOLIO_ID",
95            FieldProto::PortfolioName => "PORTFOLIO_NAME",
96            FieldProto::Price => "PRICE",
97            FieldProto::PriceId => "PRICE_ID",
98            FieldProto::IsCancelled => "IS_CANCELLED",
99            FieldProto::PositionStatus => "POSITION_STATUS",
100            FieldProto::TradeDate => "TRADE_DATE",
101            FieldProto::SettlementDate => "SETTLEMENT_DATE",
102            FieldProto::TransactionType => "TRANSACTION_TYPE",
103            FieldProto::TaxLotOpenDate => "TAX_LOT_OPEN_DATE",
104            FieldProto::TaxLotCloseDate => "TAX_LOT_CLOSE_DATE",
105        }
106    }
107    /// Creates an enum from field names used in the ProtoBuf definition.
108    pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
109        match value {
110            "UNKNOWN_FIELD" => Some(Self::UnknownField),
111            "ID" => Some(Self::Id),
112            "AS_OF" => Some(Self::AsOf),
113            "EFFECTIVE_DATE" => Some(Self::EffectiveDate),
114            "STRATEGY" => Some(Self::Strategy),
115            "SECURITY" => Some(Self::Security),
116            "SECURITY_DESCRIPTION" => Some(Self::SecurityDescription),
117            "SECURITY_ISSUER_NAME" => Some(Self::SecurityIssuerName),
118            "CASH_IMPACT_SECURITY" => Some(Self::CashImpactSecurity),
119            "ASSET_CLASS" => Some(Self::AssetClass),
120            "PRODUCT_CLASS" => Some(Self::ProductClass),
121            "PRODUCT_TYPE" => Some(Self::ProductType),
122            "SECURITY_ID" => Some(Self::SecurityId),
123            "IDENTIFIER" => Some(Self::Identifier),
124            "TENOR" => Some(Self::Tenor),
125            "ISSUE_DATE" => Some(Self::IssueDate),
126            "MATURITY_DATE" => Some(Self::MaturityDate),
127            "ADJUSTED_TENOR" => Some(Self::AdjustedTenor),
128            "PORTFOLIO" => Some(Self::Portfolio),
129            "PORTFOLIO_ID" => Some(Self::PortfolioId),
130            "PORTFOLIO_NAME" => Some(Self::PortfolioName),
131            "PRICE" => Some(Self::Price),
132            "PRICE_ID" => Some(Self::PriceId),
133            "IS_CANCELLED" => Some(Self::IsCancelled),
134            "POSITION_STATUS" => Some(Self::PositionStatus),
135            "TRADE_DATE" => Some(Self::TradeDate),
136            "SETTLEMENT_DATE" => Some(Self::SettlementDate),
137            "TRANSACTION_TYPE" => Some(Self::TransactionType),
138            "TAX_LOT_OPEN_DATE" => Some(Self::TaxLotOpenDate),
139            "TAX_LOT_CLOSE_DATE" => Some(Self::TaxLotCloseDate),
140            _ => None,
141        }
142    }
143}
144#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
145#[repr(i32)]
146pub enum MeasureProto {
147    /// Placeholder for unset or unrecognized measure values.
148    /// Should never be requested in a valuation call.
149    UnknownMeasure = 0,
150    /// The signed quantity of a position (e.g. number of shares, or total face value of bonds held).
151    /// This is an input measure provided on the PositionProto, not a computed output.
152    ///
153    /// Formula: N/A — user-supplied input.
154    /// Applicability: All security types (Bond, TIPS, FRN, Equity, Cash).
155    /// Units: Units of the security (shares for equity, face-value dollars for bonds).
156    DirectedQuantity = 1,
157    /// The current dollar value of a position at the given market price.
158    ///
159    /// Formula:
160    ///    MarketValue = (price * face_value / 100) * (directed_quantity / face_value)
161    ///                = price / 100 * directed_quantity
162    ///    Where price is quoted as a percentage of par (e.g. 95 means 95% of face).
163    ///
164    /// Example: face=1000, price=95, qty=20000 → MV = 95/100 * 20000 = 19,000.
165    ///
166    /// Model assumptions: None — this is a direct mark-to-market calculation.
167    /// Applicability: Bond, TIPS, FRN, Equity (price=share price, face_value=1), Cash.
168    /// Units: Dollars (or settlement currency).
169    MarketValue = 2,
170    /// The original purchase price of the security, before any adjustments for
171    /// amortization, accretion, or corporate actions.
172    ///
173    /// Formula: Returns the price_input as-is (quoted as % of par for bonds).
174    ///    Over time this may incorporate adjustments such as stock splits.
175    ///
176    /// Model assumptions: None — pass-through of the input price.
177    /// Applicability: Bond, TIPS, FRN, Equity, Cash.
178    /// Units: Quoted price (% of par for bonds; dollar price for equities).
179    UnadjustedCostBasis = 3,
180    /// Reserved for future use. The cost basis adjusted for amortization of premium,
181    /// accretion of discount, or corporate actions (e.g. stock splits, return of capital).
182    ///
183    /// Not currently implemented.
184    /// Applicability: Bond, TIPS, FRN, Equity.
185    /// Units: Quoted price (% of par for bonds; dollar price for equities).
186    AdjustedCostBasis = 4,
187    /// Annual coupon income as a percentage of the current market price.
188    ///
189    /// Formula (coupon-bearing bonds):
190    ///    CurrentYield = (coupon_rate * principal) / (price * face_value / 100)
191    ///    Where principal = face_value for nominal bonds, or inflation-adjusted principal for TIPS.
192    ///
193    /// Formula (zero-coupon bonds):
194    ///    CurrentYield = (face_value / dollar_price)^(1 / years_to_maturity) - 1
195    ///    This is the annualized investment yield from discount to par.
196    ///
197    /// Model assumptions: Assumes coupon income is constant (no reinvestment assumption).
198    ///    For TIPS, uses the inflation-adjusted principal for the annual coupon calculation.
199    ///    Day count: Actual/365 for years-to-maturity calculation.
200    /// Applicability: Bond, TIPS. (Equity dividend yield not yet supported.)
201    /// Units: Decimal (0-1 scale; e.g. 0.0526 = 5.26%).
202    CurrentYield = 5,
203    /// The annualized rate of return assuming the bond is held to maturity and all
204    /// coupons are reinvested at the same rate. This is the internal rate of return
205    /// that equates the present value of all future cashflows to the current price.
206    ///
207    /// Formula:
208    ///    Solve for r (annual) such that:
209    ///    price * (face / 100) = Sum_{t=1}^{N} [C / (1 + r/m)^t] + F / (1 + r/m)^N
210    ///    Where C = periodic coupon, F = principal (face or inflation-adjusted),
211    ///    m = coupon frequency, N = number of periods.
212    ///
213    /// Solver: Newton-Raphson iteration (ytm_solver.rs) with the linear approximation
214    ///    YTM ≈ (annual_coupon + (F - P) / years) / ((F + P) / 2)
215    ///    as the initial guess. Converges to the exact YTM where PV = price.
216    ///
217    /// Model assumptions:
218    ///    - Coupon reinvestment at the YTM rate (standard bond math assumption).
219    ///    - For TIPS: uses inflation-adjusted principal for cashflows, but the input
220    ///      price is real — yielding a "mixed" rate, not the true real yield. Use
221    ///      REAL_YIELD for the economically correct TIPS yield.
222    ///    - Settlement on a coupon date (no accrued interest adjustment currently).
223    ///    - Day count: Actual/365 for years-to-maturity.
224    ///
225    /// Applicability: Bond, TIPS. Not meaningful for FRN (use DISCOUNT_MARGIN) or Equity.
226    /// Units: Decimal (0-1 scale; e.g. 0.06 = 6.00% annual).
227    YieldToMaturity = 7,
228    /// The weighted average time (in years) to receive all cashflows from a bond,
229    /// where each cashflow's weight is its proportion of the bond's total present value.
230    ///
231    /// Formula:
232    ///    D = Sum_{t=1}^{N} [(t / m) * PV_t / TotalPV]
233    ///    Where PV_t = cashflow_t / (1 + r/m)^t, TotalPV = Sum(PV_t),
234    ///    m = coupon frequency, r = YTM.
235    ///
236    /// Model assumptions:
237    ///    - Uses the bond's YTM (from Newton-Raphson solver) as the discount rate.
238    ///    - Flat yield curve (single rate for all maturities).
239    ///    - Settlement on a coupon date (integer period exponents).
240    ///
241    /// Applicability: Bond, TIPS. Not typically used for FRN (spread duration is the
242    ///    relevant risk measure). Not applicable to Equity or Cash.
243    /// Units: Years (e.g. 4.41 = 4.41 years).
244    MacaulayDuration = 8,
245    /// The theoretical price of a bond computed as the sum of all future cashflows
246    /// (coupons + principal) discounted at the bond's yield to maturity.
247    ///
248    /// Formula:
249    ///    PV = Sum_{t=1}^{N} [C / (1 + r/m)^t] + F / (1 + r/m)^N
250    ///    Returned as: PV_dollar / (face_value / 100)  (quoted price, % of par).
251    ///
252    /// The YTM used for discounting is computed via Newton-Raphson from the input price,
253    /// which guarantees the three-way invariant:
254    ///    price == present_value == sum(cashflow_pvs)
255    ///
256    /// Model assumptions:
257    ///    - Same as YIELD_TO_MATURITY (the discount rate is derived from the input price).
258    ///    - For TIPS: cashflows use inflation-adjusted principal; discount rate is the
259    ///      Newton-Raphson-solved rate equating nominal cashflows to the real price.
260    ///
261    /// Applicability: Bond, TIPS. For FRN, PV uses the discount margin framework instead.
262    /// Units: Quoted price (% of par; e.g. 95.00 = $95 per $100 face).
263    PresentValue = 9,
264    /// The yield of a TIPS bond in real (inflation-adjusted) terms. This is the return
265    /// an investor earns above the rate of inflation.
266    ///
267    /// Formula: Currently delegates to the YTM calculator, which uses inflation-adjusted
268    ///    principal for cashflows. For a par TIPS (real coupon = real yield), the solver
269    ///    finds a "mixed" rate rather than the true real yield (see YIELD_TO_MATURITY notes).
270    ///
271    /// Model assumptions:
272    ///    - Same as YIELD_TO_MATURITY but applied to TIPS securities.
273    ///    - Known limitation: the current implementation mixes real price with nominal
274    ///      (inflation-adjusted) cashflows in the solver, which produces a rate that is
275    ///      not the true real yield for non-par TIPS.
276    ///
277    /// Applicability: TIPS only. For nominal bonds, returns the same value as YTM.
278    /// Units: Decimal (0-1 scale; e.g. 0.02 = 2.00% real annual yield).
279    RealYield = 10,
280    /// The inflation-adjusted principal of a TIPS bond, reflecting the cumulative
281    /// change in the Consumer Price Index (CPI) since the bond's issuance.
282    ///
283    /// Formula:
284    ///    index_ratio = current_cpi / base_cpi
285    ///    adjusted_principal = max(face_value * index_ratio, face_value)
286    ///    The max() enforces the deflation floor: at maturity, TIPS redeem at no less
287    ///    than the original face value, even if CPI has fallen.
288    ///
289    /// Model assumptions:
290    ///    - Uses the CPI values provided in the request (base_cpi on the security,
291    ///      current_cpi on the cpi_price_input).
292    ///    - Deflation floor applies only to the principal at maturity; interim coupons
293    ///      use the raw (potentially deflated) adjusted principal.
294    ///
295    /// Applicability: TIPS only.
296    /// Units: Dollars (e.g. 103.36 for face=100 with 3.36% cumulative inflation).
297    InflationAdjustedPrincipal = 11,
298    /// Requests the full schedule of future cashflows for a bond or TIPS.
299    /// When this measure is included in the request, the ValuationResponseProto will
300    /// populate the `cashflows` repeated field with one CashflowProto per payment period.
301    ///
302    /// Each CashflowProto contains:
303    ///    - cashflow_date: the payment date
304    ///    - fv_amount: the undiscounted (future) value of the cashflow
305    ///    - pv_amount: the cashflow discounted to settlement at the bond's YTM
306    ///    - coupon_rate: the annualized coupon rate for this period (constant for
307    ///      fixed-rate bonds; reference_rate + spread for FRNs)
308    ///
309    /// The sum of all pv_amounts equals the PRESENT_VALUE measure (three-way invariant).
310    ///
311    /// Model assumptions: Same as PRESENT_VALUE.
312    /// Applicability: Bond, TIPS, FRN.
313    /// Units: fv_amount and pv_amount in dollars; coupon_rate as percentage.
314    PresentValueCashflows = 12,
315    /// The discount margin of a Floating Rate Note (FRN) — the spread over the
316    /// reference rate at which the market discounts the FRN's projected cashflows
317    /// to arrive at its current price. This is the FRN analogue of YTM.
318    ///
319    /// Formula:
320    ///    Solve for DM such that:
321    ///    price = Sum_{t=1}^{N} [(R + QM)/m * FV / (1 + (R + DM)/m)^t]
322    ///          + FV / (1 + (R + DM)/m)^N
323    ///    Where R = reference rate, QM = quoted margin (fixed spread), FV = face value,
324    ///    m = payment frequency, N = number of remaining periods.
325    ///
326    /// Solver: Newton-Raphson — same solver as YTM (ytm_solver.rs). Solve for the
327    ///    periodic discount rate, then extract DM = (solved_rate * m) - R.
328    ///
329    /// Model assumptions:
330    ///    - Flat forward rates: all future reference rate fixings are assumed equal to
331    ///      the current observation of R. This is the standard FRN simplification.
332    ///    - When DM = QM, price = par (100) on a reset date.
333    ///    - When DM > QM, price < par (discount); when DM < QM, price > par (premium).
334    ///
335    /// Applicability: FRN only. For fixed-rate bonds, use YIELD_TO_MATURITY.
336    /// Units: Decimal (0-1 scale; e.g. 0.0075 = 75 basis points).
337    DiscountMargin = 13,
338    /// The sensitivity of an FRN's price to a 1 basis point change in the discount
339    /// margin. This is the primary risk measure for FRNs, analogous to modified
340    /// duration for fixed-rate bonds but measuring spread risk rather than rate risk.
341    ///
342    /// Formula (numerical differentiation):
343    ///    SpreadDuration = -(1/P) * dP/dDM
344    ///                   ≈ (P_down - P_up) / (2 * 0.0001 * P_base)
345    ///    Where P_down and P_up are the FRN prices when DM is bumped down and up by 1bp.
346    ///
347    /// For a 2-year quarterly FRN at par, spread duration ≈ 1.90 years.
348    /// This is approximately equal to the weighted average time to maturity.
349    ///
350    /// Model assumptions:
351    ///    - Same flat-forward assumption as DISCOUNT_MARGIN.
352    ///    - Uses a symmetric 1bp bump for numerical differentiation.
353    ///    - Interest rate duration of an FRN is near-zero (≈ time to next reset);
354    ///      spread duration captures the economically significant risk.
355    ///
356    /// Applicability: FRN only. For fixed-rate bonds, use MACAULAY_DURATION.
357    /// Units: Years (e.g. 1.90 = a 1bp spread widening causes ~1.90bp price decline).
358    SpreadDuration = 14,
359    /// The par yield at a given maturity point on the yield curve. The par yield is
360    /// the coupon rate at which a bond would trade at par (price = 100) for a given
361    /// maturity. This is the most commonly quoted yield curve.
362    ///
363    /// Formula:
364    ///    For each maturity point, the par yield is the coupon rate c such that:
365    ///    100 = Sum_{t=1}^{N} [c/m / (1 + r_t)^t] + 100 / (1 + r_N)^N
366    ///    Where r_t are spot rates, m = coupon frequency, N = number of periods.
367    ///
368    ///    In practice, for on-the-run bonds, par yield ≈ YTM when the bond trades
369    ///    near par. The par yield curve is bootstrapped from observed bond prices.
370    ///
371    /// Model assumptions:
372    ///    - Coupon frequency matches the market convention (semiannual for US Treasuries).
373    ///    - Interpolation between observed maturities uses the method specified in
374    ///      the CurveRequestProto (linear by default).
375    ///
376    /// Applicability: Bond, TIPS (real par yield curve).
377    ///    Not applicable to FRN, Equity, or Cash.
378    /// Units: Decimal (0-1 scale; e.g. 0.045 = 4.50% annual).
379    ParYield = 15,
380    /// The spot (zero-coupon) yield at a given maturity. The spot rate is the yield
381    /// on a zero-coupon bond maturing at that point — it represents the pure time
382    /// value of money with no reinvestment assumption.
383    ///
384    /// Formula:
385    ///    Bootstrapped from the par yield curve:
386    ///    P = 100 / (1 + s_N)^N  →  s_N = (100 / P)^(1/N) - 1
387    ///    Where s_N is the N-period spot rate, P is the zero-coupon bond price
388    ///    implied by stripping coupons from the par curve.
389    ///
390    ///    For the first period, spot rate = par yield. For subsequent periods,
391    ///    the bootstrap solves:
392    ///    100 = Sum_{t=1}^{N-1} [c/m / (1 + s_t)^t] + (100 + c/m) / (1 + s_N)^N
393    ///    for s_N, using previously computed spot rates s_1..s_{N-1}.
394    ///
395    /// Model assumptions:
396    ///    - Requires a complete par yield curve as input (no gaps).
397    ///    - Bootstrap assumes exact coupon dates (no day-count adjustments).
398    ///
399    /// Applicability: Derived from Bond par curve. Used for discounting cashflows
400    ///    and computing forward rates.
401    /// Units: Decimal (0-1 scale; e.g. 0.046 = 4.60% annual).
402    SpotYield = 16,
403    /// The forward yield between two future dates, implied by the spot curve.
404    /// The forward rate f(t1, t2) is the rate agreed today for borrowing/lending
405    /// between future times t1 and t2.
406    ///
407    /// Formula:
408    ///    f(t1, t2) = [(1 + s_{t2})^{t2} / (1 + s_{t1})^{t1}]^{1/(t2 - t1)} - 1
409    ///    Where s_t are spot rates for maturities t1 and t2.
410    ///
411    ///    For example, the 1-year forward rate 1 year from now (1y1y) is:
412    ///    f(1,2) = [(1 + s_2)^2 / (1 + s_1)]^1 - 1
413    ///
414    /// Model assumptions:
415    ///    - Derived from the spot curve (which is bootstrapped from par).
416    ///    - Assumes no arbitrage between spot and forward rates.
417    ///    - The forward period is defined by adjacent tenor points in the
418    ///      CurveRequestProto.
419    ///
420    /// Applicability: Derived from Bond spot curve. Used for rate expectations
421    ///    and forward-starting instrument pricing.
422    /// Units: Decimal (0-1 scale; e.g. 0.048 = 4.80% annual forward rate).
423    ForwardYield = 17,
424    /// The profit or loss on a position relative to its cost basis.
425    ///
426    /// Formula:
427    ///    ProfitLoss = MarketValue - (UnadjustedCostBasis / 100 * DirectedQuantity)
428    ///
429    /// Applicability: All security types.
430    /// Units: Dollars (or settlement currency).
431    ProfitLoss = 18,
432    /// The profit or loss as a percentage of the original cost basis.
433    ///
434    /// Formula:
435    ///    ProfitLossPercent = ProfitLoss / (UnadjustedCostBasis / 100 * DirectedQuantity)
436    ///
437    /// Applicability: All security types.
438    /// Units: Decimal (0-1 scale; e.g. 0.05 = 5.00% gain).
439    ProfitLossPercent = 19,
440    /// The accrued interest on a bond position — the pro-rated coupon income earned
441    /// since the last coupon payment date but not yet received.
442    ///
443    /// Formula (coupon-bearing bonds):
444    ///    AccruedInterest = (coupon_rate / coupon_frequency) * (days_since_last_coupon / days_in_period)
445    ///                      * directed_quantity
446    ///    Day count: Actual/Actual (ICMA) for US Treasuries.
447    ///
448    /// Accrued interest on settlement date T is the interest accumulated from the
449    /// last coupon date up to but not including T.
450    ///
451    /// Applicability: Bond, TIPS, FRN (coupon-bearing securities).
452    ///    Returns null/zero for Equity, Cash, and zero-coupon bonds.
453    /// Units: Dollars (absolute dollar amount for the position).
454    AccruedInterest = 20,
455    /// The second derivative of a bond's price with respect to yield, normalised by price.
456    /// Convexity measures how the duration of a bond changes as yield changes — a bond
457    /// with higher convexity gains more in price when yields fall and loses less when
458    /// yields rise, compared to a bond with lower convexity of equal duration.
459    ///
460    /// Formula:
461    ///    Convexity = (1/P) × Σ_{t=1}^{N} [CF_t × t × (t+1) / (1+y/n)^(t+2)] / n²
462    ///
463    ///    Equivalently, in terms of periodic-discount PVs:
464    ///    Convexity = Σ_{t=1}^{N} [t(t+1) × PV_t] / (P_dollar × n² × (1+r)²)
465    ///    Where r = y/n (periodic yield), P_dollar = dollar price,
466    ///    PV_t = CF_t / (1+r)^t, n = coupon frequency (periods per year).
467    ///
468    /// Model assumptions:
469    ///    - Same as MACAULAY_DURATION (flat yield curve, YTM-based discounting).
470    ///    - For FRN: uses flat-forwards effective YTM (same model as PRESENT_VALUE).
471    ///    - Settlement on a coupon date (integer period exponents).
472    ///
473    /// Applicability: Bond, TIPS, FRN. UNIMPLEMENTED for Equity and Cash.
474    /// Units: Years² (e.g. 20.5 = 20.5 years²).
475    Convexity = 21,
476    /// The full (invoice) price of a bond including accrued interest, expressed as a
477    /// percentage of face value.
478    ///
479    /// Formula:
480    ///    DirtyPrice = market_value / (num_bonds * face_value) * 100
481    ///    where num_bonds = directed_quantity / face_value
482    ///    Equivalently: market_value / directed_quantity * 100
483    ///
484    /// Applicability: Bond, TIPS. UNIMPLEMENTED for Equity and Cash.
485    /// Units: Percentage of par (e.g. 99.5 = 99.5% of par).
486    DirtyPrice = 22,
487    /// The quoted price of a bond excluding accrued interest, expressed as a
488    /// percentage of face value. This is the price conventionally quoted in bond markets.
489    ///
490    /// Formula:
491    ///    CleanPrice = DirtyPrice - (accrued_interest / directed_quantity * 100)
492    ///
493    /// Applicability: Bond, TIPS. UNIMPLEMENTED for Equity and Cash.
494    /// Units: Percentage of par (e.g. 98.75 = 98.75% of par).
495    CleanPrice = 23,
496    /// Modified Duration = MacaulayDuration / (1 + ytm/coupon_frequency).
497    ///
498    /// Measures the percentage price change of a bond for a 1% (100bp) change in yield.
499    /// Unlike Macaulay Duration (which is expressed in years), Modified Duration is a
500    /// direct measure of price sensitivity: a bond with ModifiedDuration=5 will move
501    /// approximately 5% in price for a 100bp parallel shift in yield.
502    ///
503    /// Formula:
504    ///    ModifiedDuration = MacaulayDuration / (1 + ytm/n)
505    ///    where ytm = yield to maturity (annual), n = coupon periods per year.
506    ///
507    /// Applicability: Bond, TIPS, FRN. UNIMPLEMENTED for Equity and Cash.
508    /// Units: Years (dimensionally equivalent to years, interpreted as % per 100bp).
509    ModifiedDuration = 24,
510    /// DV01 (Dollar Value of 01) = the dollar P&L impact of a 1bp (0.01%) yield increase.
511    ///
512    /// Formula:
513    ///    DV01 = ModifiedDuration × MarketValue × 0.0001
514    ///
515    /// For a $1M market value position with ModifiedDuration=5:
516    ///    DV01 = 5 × 1,000,000 × 0.0001 = $500 per bp
517    ///
518    /// Applicability: Bond, TIPS, FRN. UNIMPLEMENTED for Equity and Cash.
519    /// Units: Dollars per basis point.
520    Dv01 = 25,
521    /// U.S. Treasury Bill discount-basis yield. The market convention used by
522    /// TreasuryDirect auction results ("High discount rate"), Bloomberg TBILL
523    /// screens, and most short-tenor money-market quotes.
524    ///
525    /// Formula:
526    ///    DiscountYield = (F - P) / F × 360 / days_to_maturity
527    ///    Where F = face value (par), P = dollar price, day count is Actual/360.
528    ///
529    /// Example: 13W TBill 912797TW7 priced at 99.082, days_to_maturity=91:
530    ///    DiscountYield = (100 - 99.082) / 100 × 360 / 91 = 0.0363 = 3.63%
531    ///
532    /// Distinct from YIELD_TO_MATURITY which uses the annual-compound convention
533    /// (F/P)^(1/years) - 1; the two differ by 5-14bp at typical TBill tenors.
534    /// The U.S. Treasury publishes BOTH conventions for each auction plus
535    /// BOND_EQUIVALENT_YIELD; the industry-standard wire format for TBills is
536    /// DiscountYield. See #209.
537    ///
538    /// Model assumptions:
539    ///    - Simple (non-compounded) discount basis — standard U.S. money-market.
540    ///    - 360-day year (Actual/360 day count).
541    ///    - Assumes the security has a defined maturity_date and face_value;
542    ///      null for instruments where days_to_maturity is undefined.
543    ///
544    /// Applicability: Zero-coupon short-tenor securities — Tbill, principal-only
545    ///    Strips with <1yr remaining. Returns null/error for other product types.
546    /// Units: Decimal (0-1 scale; e.g. 0.0363 = 3.63%).
547    DiscountYield = 26,
548    /// Bond-Equivalent Yield (BEY) for U.S. Treasury Bills — also known as the
549    /// "investment rate" published alongside DISCOUNT_YIELD on TreasuryDirect.
550    /// The conventional way to compare TBill returns to coupon-bearing bond
551    /// yields (which conventionally use a 365-day year).
552    ///
553    /// Formula:
554    ///    BondEquivalentYield = (F - P) / P × 365 / days_to_maturity
555    ///    Where F = face value (par), P = dollar price, day count is Actual/365.
556    ///
557    /// Example: 13W TBill 912797TW7 priced at 99.082, days_to_maturity=91:
558    ///    BEY = (100 - 99.082) / 99.082 × 365 / 91 = 0.0371 = 3.71%
559    ///
560    /// Distinct from DISCOUNT_YIELD which uses 360-day simple discount; BEY's
561    /// dividing-by-P (not F) and 365-day basis make it directly comparable to
562    /// YTM on a coupon-bearing Treasury Note of equivalent tenor. The Treasury
563    /// calls this the "investment rate" on auction results. See #209.
564    ///
565    /// Model assumptions:
566    ///    - Simple (non-compounded) basis.
567    ///    - 365-day year (Actual/365 day count).
568    ///    - Same applicability constraints as DISCOUNT_YIELD.
569    ///
570    /// Applicability: Zero-coupon short-tenor securities — Tbill, principal-only
571    ///    Strips with <1yr remaining. Returns null/error for other product types.
572    /// Units: Decimal (0-1 scale; e.g. 0.0371 = 3.71%).
573    BondEquivalentYield = 27,
574}
575impl MeasureProto {
576    /// String value of the enum field names used in the ProtoBuf definition.
577    ///
578    /// The values are not transformed in any way and thus are considered stable
579    /// (if the ProtoBuf definition does not change) and safe for programmatic use.
580    pub fn as_str_name(&self) -> &'static str {
581        match self {
582            MeasureProto::UnknownMeasure => "UNKNOWN_MEASURE",
583            MeasureProto::DirectedQuantity => "DIRECTED_QUANTITY",
584            MeasureProto::MarketValue => "MARKET_VALUE",
585            MeasureProto::UnadjustedCostBasis => "UNADJUSTED_COST_BASIS",
586            MeasureProto::AdjustedCostBasis => "ADJUSTED_COST_BASIS",
587            MeasureProto::CurrentYield => "CURRENT_YIELD",
588            MeasureProto::YieldToMaturity => "YIELD_TO_MATURITY",
589            MeasureProto::MacaulayDuration => "MACAULAY_DURATION",
590            MeasureProto::PresentValue => "PRESENT_VALUE",
591            MeasureProto::RealYield => "REAL_YIELD",
592            MeasureProto::InflationAdjustedPrincipal => "INFLATION_ADJUSTED_PRINCIPAL",
593            MeasureProto::PresentValueCashflows => "PRESENT_VALUE_CASHFLOWS",
594            MeasureProto::DiscountMargin => "DISCOUNT_MARGIN",
595            MeasureProto::SpreadDuration => "SPREAD_DURATION",
596            MeasureProto::ParYield => "PAR_YIELD",
597            MeasureProto::SpotYield => "SPOT_YIELD",
598            MeasureProto::ForwardYield => "FORWARD_YIELD",
599            MeasureProto::ProfitLoss => "PROFIT_LOSS",
600            MeasureProto::ProfitLossPercent => "PROFIT_LOSS_PERCENT",
601            MeasureProto::AccruedInterest => "ACCRUED_INTEREST",
602            MeasureProto::Convexity => "CONVEXITY",
603            MeasureProto::DirtyPrice => "DIRTY_PRICE",
604            MeasureProto::CleanPrice => "CLEAN_PRICE",
605            MeasureProto::ModifiedDuration => "MODIFIED_DURATION",
606            MeasureProto::Dv01 => "DV01",
607            MeasureProto::DiscountYield => "DISCOUNT_YIELD",
608            MeasureProto::BondEquivalentYield => "BOND_EQUIVALENT_YIELD",
609        }
610    }
611    /// Creates an enum from field names used in the ProtoBuf definition.
612    pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
613        match value {
614            "UNKNOWN_MEASURE" => Some(Self::UnknownMeasure),
615            "DIRECTED_QUANTITY" => Some(Self::DirectedQuantity),
616            "MARKET_VALUE" => Some(Self::MarketValue),
617            "UNADJUSTED_COST_BASIS" => Some(Self::UnadjustedCostBasis),
618            "ADJUSTED_COST_BASIS" => Some(Self::AdjustedCostBasis),
619            "CURRENT_YIELD" => Some(Self::CurrentYield),
620            "YIELD_TO_MATURITY" => Some(Self::YieldToMaturity),
621            "MACAULAY_DURATION" => Some(Self::MacaulayDuration),
622            "PRESENT_VALUE" => Some(Self::PresentValue),
623            "REAL_YIELD" => Some(Self::RealYield),
624            "INFLATION_ADJUSTED_PRINCIPAL" => Some(Self::InflationAdjustedPrincipal),
625            "PRESENT_VALUE_CASHFLOWS" => Some(Self::PresentValueCashflows),
626            "DISCOUNT_MARGIN" => Some(Self::DiscountMargin),
627            "SPREAD_DURATION" => Some(Self::SpreadDuration),
628            "PAR_YIELD" => Some(Self::ParYield),
629            "SPOT_YIELD" => Some(Self::SpotYield),
630            "FORWARD_YIELD" => Some(Self::ForwardYield),
631            "PROFIT_LOSS" => Some(Self::ProfitLoss),
632            "PROFIT_LOSS_PERCENT" => Some(Self::ProfitLossPercent),
633            "ACCRUED_INTEREST" => Some(Self::AccruedInterest),
634            "CONVEXITY" => Some(Self::Convexity),
635            "DIRTY_PRICE" => Some(Self::DirtyPrice),
636            "CLEAN_PRICE" => Some(Self::CleanPrice),
637            "MODIFIED_DURATION" => Some(Self::ModifiedDuration),
638            "DV01" => Some(Self::Dv01),
639            "DISCOUNT_YIELD" => Some(Self::DiscountYield),
640            "BOND_EQUIVALENT_YIELD" => Some(Self::BondEquivalentYield),
641            _ => None,
642        }
643    }
644}
645#[allow(clippy::derive_partial_eq_without_eq)]
646#[derive(Clone, PartialEq, ::prost::Message)]
647pub struct MeasureMapEntry {
648    #[prost(enumeration = "MeasureProto", tag = "1")]
649    pub measure: i32,
650    #[prost(message, optional, tag = "2")]
651    pub measure_decimal_value: ::core::option::Option<super::util::DecimalValueProto>,
652}
653#[allow(clippy::derive_partial_eq_without_eq)]
654#[derive(Clone, PartialEq, ::prost::Message)]
655pub struct FieldMapEntry {
656    #[prost(enumeration = "FieldProto", tag = "1")]
657    pub field: i32,
658    /// Used for position filters, but not for responses
659    #[prost(enumeration = "PositionFilterOperator", tag = "20")]
660    pub operator: i32,
661    #[prost(oneof = "field_map_entry::FieldMapValueOneOf", tags = "4, 5, 6")]
662    pub field_map_value_one_of: ::core::option::Option<
663        field_map_entry::FieldMapValueOneOf,
664    >,
665}
666/// Nested message and enum types in `FieldMapEntry`.
667pub mod field_map_entry {
668    #[allow(clippy::derive_partial_eq_without_eq)]
669    #[derive(Clone, PartialEq, ::prost::Oneof)]
670    pub enum FieldMapValueOneOf {
671        /// If the field is a 'complex' proto type (e.g. a full enum) we serialize the enum and wrap it in an Any. You can think of the Any as a string describing the type, and a binary of the proto itself
672        #[prost(message, tag = "4")]
673        FieldValuePacked(::prost_types::Any),
674        /// If the field is an enum type, then we use the number to denote which value it is
675        #[prost(int32, tag = "5")]
676        EnumValue(i32),
677        /// If the field is a string type, we just serialize the string (packing has an overhead)
678        #[prost(string, tag = "6")]
679        StringValue(::prost::alloc::string::String),
680    }
681}
682#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
683#[repr(i32)]
684pub enum PositionFilterOperator {
685    UnknownOperator = 0,
686    Equals = 1,
687    NotEquals = 2,
688    LessThan = 3,
689    LessThanOrEquals = 4,
690    MoreThan = 5,
691    MoreThanOrEquals = 6,
692}
693impl PositionFilterOperator {
694    /// String value of the enum field names used in the ProtoBuf definition.
695    ///
696    /// The values are not transformed in any way and thus are considered stable
697    /// (if the ProtoBuf definition does not change) and safe for programmatic use.
698    pub fn as_str_name(&self) -> &'static str {
699        match self {
700            PositionFilterOperator::UnknownOperator => "UNKNOWN_OPERATOR",
701            PositionFilterOperator::Equals => "EQUALS",
702            PositionFilterOperator::NotEquals => "NOT_EQUALS",
703            PositionFilterOperator::LessThan => "LESS_THAN",
704            PositionFilterOperator::LessThanOrEquals => "LESS_THAN_OR_EQUALS",
705            PositionFilterOperator::MoreThan => "MORE_THAN",
706            PositionFilterOperator::MoreThanOrEquals => "MORE_THAN_OR_EQUALS",
707        }
708    }
709    /// Creates an enum from field names used in the ProtoBuf definition.
710    pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
711        match value {
712            "UNKNOWN_OPERATOR" => Some(Self::UnknownOperator),
713            "EQUALS" => Some(Self::Equals),
714            "NOT_EQUALS" => Some(Self::NotEquals),
715            "LESS_THAN" => Some(Self::LessThan),
716            "LESS_THAN_OR_EQUALS" => Some(Self::LessThanOrEquals),
717            "MORE_THAN" => Some(Self::MoreThan),
718            "MORE_THAN_OR_EQUALS" => Some(Self::MoreThanOrEquals),
719            _ => None,
720        }
721    }
722}
723#[allow(clippy::derive_partial_eq_without_eq)]
724#[derive(Clone, PartialEq, ::prost::Message)]
725pub struct PositionProto {
726    #[prost(string, tag = "1")]
727    pub object_class: ::prost::alloc::string::String,
728    #[prost(string, tag = "2")]
729    pub version: ::prost::alloc::string::String,
730    #[prost(enumeration = "PositionViewProto", tag = "10")]
731    pub position_view: i32,
732    #[prost(enumeration = "PositionTypeProto", tag = "11")]
733    pub position_type: i32,
734    #[prost(message, repeated, tag = "20")]
735    pub measures: ::prost::alloc::vec::Vec<MeasureMapEntry>,
736    #[prost(message, repeated, tag = "21")]
737    pub fields: ::prost::alloc::vec::Vec<FieldMapEntry>,
738    /// The base/reporting currency for monetary measures in this position.
739    /// Set to the portfolio's base currency (e.g. USD cash security).
740    /// Allows the UI to display the currency alongside MARKET_VALUE and other measures.
741    #[prost(message, optional, tag = "22")]
742    pub reporting_currency: ::core::option::Option<super::security::SecurityProto>,
743}
744#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
745#[repr(i32)]
746pub enum PositionViewProto {
747    UnknownPositionView = 0,
748    DefaultView = 1,
749    StrategyView = 2,
750}
751impl PositionViewProto {
752    /// String value of the enum field names used in the ProtoBuf definition.
753    ///
754    /// The values are not transformed in any way and thus are considered stable
755    /// (if the ProtoBuf definition does not change) and safe for programmatic use.
756    pub fn as_str_name(&self) -> &'static str {
757        match self {
758            PositionViewProto::UnknownPositionView => "UNKNOWN_POSITION_VIEW",
759            PositionViewProto::DefaultView => "DEFAULT_VIEW",
760            PositionViewProto::StrategyView => "STRATEGY_VIEW",
761        }
762    }
763    /// Creates an enum from field names used in the ProtoBuf definition.
764    pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
765        match value {
766            "UNKNOWN_POSITION_VIEW" => Some(Self::UnknownPositionView),
767            "DEFAULT_VIEW" => Some(Self::DefaultView),
768            "STRATEGY_VIEW" => Some(Self::StrategyView),
769            _ => None,
770        }
771    }
772}
773#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
774#[repr(i32)]
775pub enum PositionTypeProto {
776    UnknownPositionType = 0,
777    Transaction = 1,
778    TaxLot = 2,
779}
780impl PositionTypeProto {
781    /// String value of the enum field names used in the ProtoBuf definition.
782    ///
783    /// The values are not transformed in any way and thus are considered stable
784    /// (if the ProtoBuf definition does not change) and safe for programmatic use.
785    pub fn as_str_name(&self) -> &'static str {
786        match self {
787            PositionTypeProto::UnknownPositionType => "UNKNOWN_POSITION_TYPE",
788            PositionTypeProto::Transaction => "TRANSACTION",
789            PositionTypeProto::TaxLot => "TAX_LOT",
790        }
791    }
792    /// Creates an enum from field names used in the ProtoBuf definition.
793    pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
794        match value {
795            "UNKNOWN_POSITION_TYPE" => Some(Self::UnknownPositionType),
796            "TRANSACTION" => Some(Self::Transaction),
797            "TAX_LOT" => Some(Self::TaxLot),
798            _ => None,
799        }
800    }
801}
802#[allow(clippy::derive_partial_eq_without_eq)]
803#[derive(Clone, PartialEq, ::prost::Message)]
804pub struct PositionFilterProto {
805    #[prost(string, tag = "1")]
806    pub object_class: ::prost::alloc::string::String,
807    #[prost(string, tag = "2")]
808    pub version: ::prost::alloc::string::String,
809    #[prost(message, repeated, tag = "21")]
810    pub filters: ::prost::alloc::vec::Vec<FieldMapEntry>,
811}
812#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
813#[repr(i32)]
814pub enum PositionStatusProto {
815    Unknown = 0,
816    /// Hypothetical status means a transaction, tax lot or position that may never occur. This can be used to understand how potential actions could impact a portfolio
817    Hypothetical = 1,
818    /// Intended status means a transaction, tax lot or position that is expected to occur if nothing changes. For example a fixed income bond that is expected to pay a coupon, or a security that is expected to mature in a specific point in the future
819    Intended = 2,
820    /// Executed status means a transaction, tax lot or position that is the result of a legally binding transaction
821    Executed = 3,
822}
823impl PositionStatusProto {
824    /// String value of the enum field names used in the ProtoBuf definition.
825    ///
826    /// The values are not transformed in any way and thus are considered stable
827    /// (if the ProtoBuf definition does not change) and safe for programmatic use.
828    pub fn as_str_name(&self) -> &'static str {
829        match self {
830            PositionStatusProto::Unknown => "UNKNOWN",
831            PositionStatusProto::Hypothetical => "HYPOTHETICAL",
832            PositionStatusProto::Intended => "INTENDED",
833            PositionStatusProto::Executed => "EXECUTED",
834        }
835    }
836    /// Creates an enum from field names used in the ProtoBuf definition.
837    pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
838        match value {
839            "UNKNOWN" => Some(Self::Unknown),
840            "HYPOTHETICAL" => Some(Self::Hypothetical),
841            "INTENDED" => Some(Self::Intended),
842            "EXECUTED" => Some(Self::Executed),
843            _ => None,
844        }
845    }
846}