feat: add bond pages and portfolio navigation

This commit is contained in:
2026-09-10 22:30:47 +03:00
parent 561222e468
commit 232d7f9990
39 changed files with 4217 additions and 221 deletions
+817
View File
@@ -212,6 +212,134 @@ export interface paths {
patch?: never;
trace?: never;
};
"/api/v1/bonds/{uid}/metrics": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
get: operations["BondController_metrics"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/bonds": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
get: operations["BondController_search"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/bonds/by-ticker/{ticker}": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
get: operations["BondController_getByTicker"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/bonds/{uid}": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
get: operations["BondController_get"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/bonds/{uid}/quote": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
get: operations["BondController_quote"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/bonds/{uid}/candles": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
get: operations["BondController_candles"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/bonds/{uid}/position": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
get: operations["BondController_position"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/bonds/{uid}/coupons": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
get: operations["BondController_coupons"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/tbank-connection": {
parameters: {
query?: never;
@@ -582,6 +710,165 @@ export interface components {
estimateUnavailable: boolean;
positionIsStale: boolean;
};
BondCreditRatingDto: {
/** @enum {string} */
agency: "NCR";
value: string | null;
/** @enum {string} */
status: "active" | "withdrawn";
/** Format: date */
date: string;
/** Format: uri */
sourceUrl: string;
/** Format: date-time */
observedAt: string;
};
BondYieldDto: {
/** @description MOEX effective annual yield in percent. */
value: string;
pricePercent: string;
/** Format: date */
date: string;
/** @description MOEX yield target, e.g. MATDATE or OFFERDATE. */
dateType: string | null;
/** Format: date-time */
tradeAt: string;
};
BondMetricsDto: {
creditRating: components["schemas"]["BondCreditRatingDto"] | null;
coupon: components["schemas"]["MoneyDto"] | null;
/** Format: date */
couponDate: string | null;
couponType: string | null;
couponPeriodDays: number | null;
/** @description Next coupon × 365 / period days / indicative clean price × 100. Not yield to maturity. */
couponYieldPercent: string | null;
/** Format: date-time */
couponYieldPriceAt: string | null;
effectiveYield: components["schemas"]["BondYieldDto"] | null;
unavailable: string[];
/** Format: date-time */
observedAt: string;
};
BondSearchResultDto: {
/** Format: uuid */
instrumentUid: string;
/** @description Unambiguous ticker URL segment, or the exact instrument UID. */
slug: string;
name: string;
isin: string | null;
classCode: string | null;
realExchange: string | null;
apiTradeAvailable: boolean | null;
ticker: string | null;
logoName: string | null;
currency: string | null;
sector: string | null;
lot: number | null;
/** Format: date-time */
historyFrom: string | null;
nominal: components["schemas"]["MoneyDto"] | null;
initialNominal: components["schemas"]["MoneyDto"] | null;
aci: components["schemas"]["MoneyDto"] | null;
maturityDate: string | null;
callDate: string | null;
bondType: string | null;
riskLevel: string | null;
couponQuantityPerYear: number | null;
floatingCoupon: boolean | null;
perpetual: boolean | null;
amortization: boolean | null;
subordinated: boolean | null;
/** @description Clean price in percent of nominal, not money. */
pricePercent: string | null;
/** Format: date-time */
priceAt: string | null;
};
BondDto: {
/** Format: uuid */
instrumentUid: string;
/** @description Unambiguous ticker URL segment, or the exact instrument UID. */
slug: string;
name: string;
isin: string | null;
classCode: string | null;
realExchange: string | null;
apiTradeAvailable: boolean | null;
ticker: string | null;
logoName: string | null;
currency: string | null;
sector: string | null;
lot: number | null;
/** Format: date-time */
historyFrom: string | null;
nominal: components["schemas"]["MoneyDto"] | null;
initialNominal: components["schemas"]["MoneyDto"] | null;
aci: components["schemas"]["MoneyDto"] | null;
maturityDate: string | null;
callDate: string | null;
bondType: string | null;
riskLevel: string | null;
couponQuantityPerYear: number | null;
floatingCoupon: boolean | null;
perpetual: boolean | null;
amortization: boolean | null;
subordinated: boolean | null;
};
BondQuoteDto: {
pricePercent: string | null;
/** @description Indicative clean value at the current nominal; no FX conversion. */
cleanPrice: components["schemas"]["MoneyDto"] | null;
aci: components["schemas"]["MoneyDto"] | null;
/** @description Indicative clean value plus current accrued interest, excluding fees. */
dirtyPrice: components["schemas"]["MoneyDto"] | null;
changePercentagePoints: string | null;
previousCloseDate: string | null;
tradingStatus: string | null;
/** Format: date-time */
priceAt: string | null;
unavailable: string[];
/** Format: date-time */
observedAt: string;
};
BondCandlesDto: {
candles: components["schemas"]["StockCandleDto"][];
currency: string | null;
/** Format: date-time */
historyFrom: string | null;
/** Format: date-time */
observedAt: string;
};
BondPositionDto: {
quantity: string;
currentValue: components["schemas"]["MoneyDto"] | null;
averagePurchasePrice: components["schemas"]["MoneyDto"] | null;
absoluteReturn: components["schemas"]["MoneyDto"] | null;
returnPercent: string | null;
accounts: components["schemas"]["StockPositionRowDto"][];
isStale: boolean;
/** Format: date-time */
observedAt: string;
};
BondCouponDto: {
number: string | null;
paymentDate: string | null;
recordDate: string | null;
couponType: string | null;
periodDays: number | null;
perBond: components["schemas"]["MoneyDto"] | null;
estimatedAmount: components["schemas"]["MoneyDto"] | null;
/** @enum {string} */
timing: "upcoming" | "past" | "undated";
};
BondCouponsDto: {
coupons: components["schemas"]["BondCouponDto"][];
from: string;
to: string;
observedAt: string;
positionAt: string | null;
estimateUnavailable: boolean;
positionIsStale: boolean;
};
TbankConnectionStatusDto: {
connected: boolean;
/** Format: date-time */
@@ -1651,6 +1938,536 @@ export interface operations {
};
};
};
BondController_metrics: {
parameters: {
query?: never;
header?: never;
path: {
uid: string;
};
cookie?: never;
};
requestBody?: never;
responses: {
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["BondMetricsDto"];
};
};
/** @description Invalid request */
400: {
headers: {
[name: string]: unknown;
};
content: {
"application/problem+json": components["schemas"]["ProblemDetailsDto"];
};
};
/** @description Authentication required */
401: {
headers: {
[name: string]: unknown;
};
content: {
"application/problem+json": components["schemas"]["ProblemDetailsDto"];
};
};
/** @description Resource not found */
404: {
headers: {
[name: string]: unknown;
};
content: {
"application/problem+json": components["schemas"]["ProblemDetailsDto"];
};
};
/** @description Internal server error */
500: {
headers: {
[name: string]: unknown;
};
content: {
"application/problem+json": components["schemas"]["ProblemDetailsDto"];
};
};
/** @description Upstream service unavailable */
503: {
headers: {
[name: string]: unknown;
};
content: {
"application/problem+json": components["schemas"]["ProblemDetailsDto"];
};
};
};
};
BondController_search: {
parameters: {
query: {
query: string;
};
header?: never;
path?: never;
cookie?: never;
};
requestBody?: never;
responses: {
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["BondSearchResultDto"][];
};
};
/** @description Invalid request */
400: {
headers: {
[name: string]: unknown;
};
content: {
"application/problem+json": components["schemas"]["ProblemDetailsDto"];
};
};
/** @description Authentication required */
401: {
headers: {
[name: string]: unknown;
};
content: {
"application/problem+json": components["schemas"]["ProblemDetailsDto"];
};
};
/** @description Resource not found */
404: {
headers: {
[name: string]: unknown;
};
content: {
"application/problem+json": components["schemas"]["ProblemDetailsDto"];
};
};
/** @description Internal server error */
500: {
headers: {
[name: string]: unknown;
};
content: {
"application/problem+json": components["schemas"]["ProblemDetailsDto"];
};
};
/** @description Upstream service unavailable */
503: {
headers: {
[name: string]: unknown;
};
content: {
"application/problem+json": components["schemas"]["ProblemDetailsDto"];
};
};
};
};
BondController_getByTicker: {
parameters: {
query?: never;
header?: never;
path: {
ticker: string;
};
cookie?: never;
};
requestBody?: never;
responses: {
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["BondDto"];
};
};
/** @description Invalid request */
400: {
headers: {
[name: string]: unknown;
};
content: {
"application/problem+json": components["schemas"]["ProblemDetailsDto"];
};
};
/** @description Authentication required */
401: {
headers: {
[name: string]: unknown;
};
content: {
"application/problem+json": components["schemas"]["ProblemDetailsDto"];
};
};
/** @description Resource not found */
404: {
headers: {
[name: string]: unknown;
};
content: {
"application/problem+json": components["schemas"]["ProblemDetailsDto"];
};
};
/** @description Internal server error */
500: {
headers: {
[name: string]: unknown;
};
content: {
"application/problem+json": components["schemas"]["ProblemDetailsDto"];
};
};
/** @description Upstream service unavailable */
503: {
headers: {
[name: string]: unknown;
};
content: {
"application/problem+json": components["schemas"]["ProblemDetailsDto"];
};
};
};
};
BondController_get: {
parameters: {
query?: never;
header?: never;
path: {
uid: string;
};
cookie?: never;
};
requestBody?: never;
responses: {
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["BondDto"];
};
};
/** @description Invalid request */
400: {
headers: {
[name: string]: unknown;
};
content: {
"application/problem+json": components["schemas"]["ProblemDetailsDto"];
};
};
/** @description Authentication required */
401: {
headers: {
[name: string]: unknown;
};
content: {
"application/problem+json": components["schemas"]["ProblemDetailsDto"];
};
};
/** @description Resource not found */
404: {
headers: {
[name: string]: unknown;
};
content: {
"application/problem+json": components["schemas"]["ProblemDetailsDto"];
};
};
/** @description Internal server error */
500: {
headers: {
[name: string]: unknown;
};
content: {
"application/problem+json": components["schemas"]["ProblemDetailsDto"];
};
};
/** @description Upstream service unavailable */
503: {
headers: {
[name: string]: unknown;
};
content: {
"application/problem+json": components["schemas"]["ProblemDetailsDto"];
};
};
};
};
BondController_quote: {
parameters: {
query?: never;
header?: never;
path: {
uid: string;
};
cookie?: never;
};
requestBody?: never;
responses: {
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["BondQuoteDto"];
};
};
/** @description Invalid request */
400: {
headers: {
[name: string]: unknown;
};
content: {
"application/problem+json": components["schemas"]["ProblemDetailsDto"];
};
};
/** @description Authentication required */
401: {
headers: {
[name: string]: unknown;
};
content: {
"application/problem+json": components["schemas"]["ProblemDetailsDto"];
};
};
/** @description Resource not found */
404: {
headers: {
[name: string]: unknown;
};
content: {
"application/problem+json": components["schemas"]["ProblemDetailsDto"];
};
};
/** @description Internal server error */
500: {
headers: {
[name: string]: unknown;
};
content: {
"application/problem+json": components["schemas"]["ProblemDetailsDto"];
};
};
/** @description Upstream service unavailable */
503: {
headers: {
[name: string]: unknown;
};
content: {
"application/problem+json": components["schemas"]["ProblemDetailsDto"];
};
};
};
};
BondController_candles: {
parameters: {
query?: {
period?: "month" | "halfYear" | "year" | "all";
};
header?: never;
path: {
uid: string;
};
cookie?: never;
};
requestBody?: never;
responses: {
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["BondCandlesDto"];
};
};
/** @description Invalid request */
400: {
headers: {
[name: string]: unknown;
};
content: {
"application/problem+json": components["schemas"]["ProblemDetailsDto"];
};
};
/** @description Authentication required */
401: {
headers: {
[name: string]: unknown;
};
content: {
"application/problem+json": components["schemas"]["ProblemDetailsDto"];
};
};
/** @description Resource not found */
404: {
headers: {
[name: string]: unknown;
};
content: {
"application/problem+json": components["schemas"]["ProblemDetailsDto"];
};
};
/** @description Internal server error */
500: {
headers: {
[name: string]: unknown;
};
content: {
"application/problem+json": components["schemas"]["ProblemDetailsDto"];
};
};
/** @description Upstream service unavailable */
503: {
headers: {
[name: string]: unknown;
};
content: {
"application/problem+json": components["schemas"]["ProblemDetailsDto"];
};
};
};
};
BondController_position: {
parameters: {
query?: never;
header?: never;
path: {
uid: string;
};
cookie?: never;
};
requestBody?: never;
responses: {
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["BondPositionDto"];
};
};
/** @description Invalid request */
400: {
headers: {
[name: string]: unknown;
};
content: {
"application/problem+json": components["schemas"]["ProblemDetailsDto"];
};
};
/** @description Authentication required */
401: {
headers: {
[name: string]: unknown;
};
content: {
"application/problem+json": components["schemas"]["ProblemDetailsDto"];
};
};
/** @description Resource not found */
404: {
headers: {
[name: string]: unknown;
};
content: {
"application/problem+json": components["schemas"]["ProblemDetailsDto"];
};
};
/** @description Internal server error */
500: {
headers: {
[name: string]: unknown;
};
content: {
"application/problem+json": components["schemas"]["ProblemDetailsDto"];
};
};
/** @description Upstream service unavailable */
503: {
headers: {
[name: string]: unknown;
};
content: {
"application/problem+json": components["schemas"]["ProblemDetailsDto"];
};
};
};
};
BondController_coupons: {
parameters: {
query?: never;
header?: never;
path: {
uid: string;
};
cookie?: never;
};
requestBody?: never;
responses: {
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["BondCouponsDto"];
};
};
/** @description Invalid request */
400: {
headers: {
[name: string]: unknown;
};
content: {
"application/problem+json": components["schemas"]["ProblemDetailsDto"];
};
};
/** @description Authentication required */
401: {
headers: {
[name: string]: unknown;
};
content: {
"application/problem+json": components["schemas"]["ProblemDetailsDto"];
};
};
/** @description Resource not found */
404: {
headers: {
[name: string]: unknown;
};
content: {
"application/problem+json": components["schemas"]["ProblemDetailsDto"];
};
};
/** @description Internal server error */
500: {
headers: {
[name: string]: unknown;
};
content: {
"application/problem+json": components["schemas"]["ProblemDetailsDto"];
};
};
/** @description Upstream service unavailable */
503: {
headers: {
[name: string]: unknown;
};
content: {
"application/problem+json": components["schemas"]["ProblemDetailsDto"];
};
};
};
};
TbankConnectionController_status: {
parameters: {
query?: never;
File diff suppressed because it is too large Load Diff