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}
522impl MeasureProto {
523 /// String value of the enum field names used in the ProtoBuf definition.
524 ///
525 /// The values are not transformed in any way and thus are considered stable
526 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
527 pub fn as_str_name(&self) -> &'static str {
528 match self {
529 MeasureProto::UnknownMeasure => "UNKNOWN_MEASURE",
530 MeasureProto::DirectedQuantity => "DIRECTED_QUANTITY",
531 MeasureProto::MarketValue => "MARKET_VALUE",
532 MeasureProto::UnadjustedCostBasis => "UNADJUSTED_COST_BASIS",
533 MeasureProto::AdjustedCostBasis => "ADJUSTED_COST_BASIS",
534 MeasureProto::CurrentYield => "CURRENT_YIELD",
535 MeasureProto::YieldToMaturity => "YIELD_TO_MATURITY",
536 MeasureProto::MacaulayDuration => "MACAULAY_DURATION",
537 MeasureProto::PresentValue => "PRESENT_VALUE",
538 MeasureProto::RealYield => "REAL_YIELD",
539 MeasureProto::InflationAdjustedPrincipal => "INFLATION_ADJUSTED_PRINCIPAL",
540 MeasureProto::PresentValueCashflows => "PRESENT_VALUE_CASHFLOWS",
541 MeasureProto::DiscountMargin => "DISCOUNT_MARGIN",
542 MeasureProto::SpreadDuration => "SPREAD_DURATION",
543 MeasureProto::ParYield => "PAR_YIELD",
544 MeasureProto::SpotYield => "SPOT_YIELD",
545 MeasureProto::ForwardYield => "FORWARD_YIELD",
546 MeasureProto::ProfitLoss => "PROFIT_LOSS",
547 MeasureProto::ProfitLossPercent => "PROFIT_LOSS_PERCENT",
548 MeasureProto::AccruedInterest => "ACCRUED_INTEREST",
549 MeasureProto::Convexity => "CONVEXITY",
550 MeasureProto::DirtyPrice => "DIRTY_PRICE",
551 MeasureProto::CleanPrice => "CLEAN_PRICE",
552 MeasureProto::ModifiedDuration => "MODIFIED_DURATION",
553 MeasureProto::Dv01 => "DV01",
554 }
555 }
556 /// Creates an enum from field names used in the ProtoBuf definition.
557 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
558 match value {
559 "UNKNOWN_MEASURE" => Some(Self::UnknownMeasure),
560 "DIRECTED_QUANTITY" => Some(Self::DirectedQuantity),
561 "MARKET_VALUE" => Some(Self::MarketValue),
562 "UNADJUSTED_COST_BASIS" => Some(Self::UnadjustedCostBasis),
563 "ADJUSTED_COST_BASIS" => Some(Self::AdjustedCostBasis),
564 "CURRENT_YIELD" => Some(Self::CurrentYield),
565 "YIELD_TO_MATURITY" => Some(Self::YieldToMaturity),
566 "MACAULAY_DURATION" => Some(Self::MacaulayDuration),
567 "PRESENT_VALUE" => Some(Self::PresentValue),
568 "REAL_YIELD" => Some(Self::RealYield),
569 "INFLATION_ADJUSTED_PRINCIPAL" => Some(Self::InflationAdjustedPrincipal),
570 "PRESENT_VALUE_CASHFLOWS" => Some(Self::PresentValueCashflows),
571 "DISCOUNT_MARGIN" => Some(Self::DiscountMargin),
572 "SPREAD_DURATION" => Some(Self::SpreadDuration),
573 "PAR_YIELD" => Some(Self::ParYield),
574 "SPOT_YIELD" => Some(Self::SpotYield),
575 "FORWARD_YIELD" => Some(Self::ForwardYield),
576 "PROFIT_LOSS" => Some(Self::ProfitLoss),
577 "PROFIT_LOSS_PERCENT" => Some(Self::ProfitLossPercent),
578 "ACCRUED_INTEREST" => Some(Self::AccruedInterest),
579 "CONVEXITY" => Some(Self::Convexity),
580 "DIRTY_PRICE" => Some(Self::DirtyPrice),
581 "CLEAN_PRICE" => Some(Self::CleanPrice),
582 "MODIFIED_DURATION" => Some(Self::ModifiedDuration),
583 "DV01" => Some(Self::Dv01),
584 _ => None,
585 }
586 }
587}
588#[allow(clippy::derive_partial_eq_without_eq)]
589#[derive(Clone, PartialEq, ::prost::Message)]
590pub struct MeasureMapEntry {
591 #[prost(enumeration = "MeasureProto", tag = "1")]
592 pub measure: i32,
593 #[prost(message, optional, tag = "2")]
594 pub measure_decimal_value: ::core::option::Option<super::util::DecimalValueProto>,
595}
596#[allow(clippy::derive_partial_eq_without_eq)]
597#[derive(Clone, PartialEq, ::prost::Message)]
598pub struct FieldMapEntry {
599 #[prost(enumeration = "FieldProto", tag = "1")]
600 pub field: i32,
601 /// Used for position filters, but not for responses
602 #[prost(enumeration = "PositionFilterOperator", tag = "20")]
603 pub operator: i32,
604 #[prost(oneof = "field_map_entry::FieldMapValueOneOf", tags = "4, 5, 6")]
605 pub field_map_value_one_of: ::core::option::Option<
606 field_map_entry::FieldMapValueOneOf,
607 >,
608}
609/// Nested message and enum types in `FieldMapEntry`.
610pub mod field_map_entry {
611 #[allow(clippy::derive_partial_eq_without_eq)]
612 #[derive(Clone, PartialEq, ::prost::Oneof)]
613 pub enum FieldMapValueOneOf {
614 /// 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
615 #[prost(message, tag = "4")]
616 FieldValuePacked(::prost_types::Any),
617 /// If the field is an enum type, then we use the number to denote which value it is
618 #[prost(int32, tag = "5")]
619 EnumValue(i32),
620 /// If the field is a string type, we just serialize the string (packing has an overhead)
621 #[prost(string, tag = "6")]
622 StringValue(::prost::alloc::string::String),
623 }
624}
625#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
626#[repr(i32)]
627pub enum PositionFilterOperator {
628 UnknownOperator = 0,
629 Equals = 1,
630 NotEquals = 2,
631 LessThan = 3,
632 LessThanOrEquals = 4,
633 MoreThan = 5,
634 MoreThanOrEquals = 6,
635}
636impl PositionFilterOperator {
637 /// String value of the enum field names used in the ProtoBuf definition.
638 ///
639 /// The values are not transformed in any way and thus are considered stable
640 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
641 pub fn as_str_name(&self) -> &'static str {
642 match self {
643 PositionFilterOperator::UnknownOperator => "UNKNOWN_OPERATOR",
644 PositionFilterOperator::Equals => "EQUALS",
645 PositionFilterOperator::NotEquals => "NOT_EQUALS",
646 PositionFilterOperator::LessThan => "LESS_THAN",
647 PositionFilterOperator::LessThanOrEquals => "LESS_THAN_OR_EQUALS",
648 PositionFilterOperator::MoreThan => "MORE_THAN",
649 PositionFilterOperator::MoreThanOrEquals => "MORE_THAN_OR_EQUALS",
650 }
651 }
652 /// Creates an enum from field names used in the ProtoBuf definition.
653 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
654 match value {
655 "UNKNOWN_OPERATOR" => Some(Self::UnknownOperator),
656 "EQUALS" => Some(Self::Equals),
657 "NOT_EQUALS" => Some(Self::NotEquals),
658 "LESS_THAN" => Some(Self::LessThan),
659 "LESS_THAN_OR_EQUALS" => Some(Self::LessThanOrEquals),
660 "MORE_THAN" => Some(Self::MoreThan),
661 "MORE_THAN_OR_EQUALS" => Some(Self::MoreThanOrEquals),
662 _ => None,
663 }
664 }
665}
666#[allow(clippy::derive_partial_eq_without_eq)]
667#[derive(Clone, PartialEq, ::prost::Message)]
668pub struct PositionProto {
669 #[prost(string, tag = "1")]
670 pub object_class: ::prost::alloc::string::String,
671 #[prost(string, tag = "2")]
672 pub version: ::prost::alloc::string::String,
673 #[prost(enumeration = "PositionViewProto", tag = "10")]
674 pub position_view: i32,
675 #[prost(enumeration = "PositionTypeProto", tag = "11")]
676 pub position_type: i32,
677 #[prost(message, repeated, tag = "20")]
678 pub measures: ::prost::alloc::vec::Vec<MeasureMapEntry>,
679 #[prost(message, repeated, tag = "21")]
680 pub fields: ::prost::alloc::vec::Vec<FieldMapEntry>,
681 /// The base/reporting currency for monetary measures in this position.
682 /// Set to the portfolio's base currency (e.g. USD cash security).
683 /// Allows the UI to display the currency alongside MARKET_VALUE and other measures.
684 #[prost(message, optional, tag = "22")]
685 pub reporting_currency: ::core::option::Option<super::security::SecurityProto>,
686}
687#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
688#[repr(i32)]
689pub enum PositionViewProto {
690 UnknownPositionView = 0,
691 DefaultView = 1,
692 StrategyView = 2,
693}
694impl PositionViewProto {
695 /// String value of the enum field names used in the ProtoBuf definition.
696 ///
697 /// The values are not transformed in any way and thus are considered stable
698 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
699 pub fn as_str_name(&self) -> &'static str {
700 match self {
701 PositionViewProto::UnknownPositionView => "UNKNOWN_POSITION_VIEW",
702 PositionViewProto::DefaultView => "DEFAULT_VIEW",
703 PositionViewProto::StrategyView => "STRATEGY_VIEW",
704 }
705 }
706 /// Creates an enum from field names used in the ProtoBuf definition.
707 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
708 match value {
709 "UNKNOWN_POSITION_VIEW" => Some(Self::UnknownPositionView),
710 "DEFAULT_VIEW" => Some(Self::DefaultView),
711 "STRATEGY_VIEW" => Some(Self::StrategyView),
712 _ => None,
713 }
714 }
715}
716#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
717#[repr(i32)]
718pub enum PositionTypeProto {
719 UnknownPositionType = 0,
720 Transaction = 1,
721 TaxLot = 2,
722}
723impl PositionTypeProto {
724 /// String value of the enum field names used in the ProtoBuf definition.
725 ///
726 /// The values are not transformed in any way and thus are considered stable
727 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
728 pub fn as_str_name(&self) -> &'static str {
729 match self {
730 PositionTypeProto::UnknownPositionType => "UNKNOWN_POSITION_TYPE",
731 PositionTypeProto::Transaction => "TRANSACTION",
732 PositionTypeProto::TaxLot => "TAX_LOT",
733 }
734 }
735 /// Creates an enum from field names used in the ProtoBuf definition.
736 pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
737 match value {
738 "UNKNOWN_POSITION_TYPE" => Some(Self::UnknownPositionType),
739 "TRANSACTION" => Some(Self::Transaction),
740 "TAX_LOT" => Some(Self::TaxLot),
741 _ => None,
742 }
743 }
744}
745#[allow(clippy::derive_partial_eq_without_eq)]
746#[derive(Clone, PartialEq, ::prost::Message)]
747pub struct PositionFilterProto {
748 #[prost(string, tag = "1")]
749 pub object_class: ::prost::alloc::string::String,
750 #[prost(string, tag = "2")]
751 pub version: ::prost::alloc::string::String,
752 #[prost(message, repeated, tag = "21")]
753 pub filters: ::prost::alloc::vec::Vec<FieldMapEntry>,
754}
755#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
756#[repr(i32)]
757pub enum PositionStatusProto {
758 Unknown = 0,
759 /// 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
760 Hypothetical = 1,
761 /// 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
762 Intended = 2,
763 /// Executed status means a transaction, tax lot or position that is the result of a legally binding transaction
764 Executed = 3,
765}
766impl PositionStatusProto {
767 /// String value of the enum field names used in the ProtoBuf definition.
768 ///
769 /// The values are not transformed in any way and thus are considered stable
770 /// (if the ProtoBuf definition does not change) and safe for programmatic use.
771 pub fn as_str_name(&self) -> &'static str {
772 match self {
773 PositionStatusProto::Unknown => "UNKNOWN",
774 PositionStatusProto::Hypothetical => "HYPOTHETICAL",
775 PositionStatusProto::Intended => "INTENDED",
776 PositionStatusProto::Executed => "EXECUTED",
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" => Some(Self::Unknown),
783 "HYPOTHETICAL" => Some(Self::Hypothetical),
784 "INTENDED" => Some(Self::Intended),
785 "EXECUTED" => Some(Self::Executed),
786 _ => None,
787 }
788 }
789}