feat(portfolio): visualize asset allocation

This commit is contained in:
2026-09-09 21:30:12 +03:00
parent daf1dca666
commit 0306526d33
19 changed files with 1142 additions and 12 deletions
+26
View File
@@ -379,6 +379,31 @@ export interface components {
ticker: string | null;
logoName: string | null;
};
PortfolioStructureCategoryDto: {
/** @enum {string} */
type: "STOCK" | "BOND" | "OTHER" | "CASH";
/** @description Exact known value as a decimal string. */
value: string;
/** @description Percentage including cash, rounded to six decimal places. Null for incomplete, negative or zero-total compositions. */
sharePercent: string | null;
};
PortfolioStructureCurrencyDto: {
currency: string;
totalValue: string;
/** @description Any negative constituent, even if netted positive. */
hasNegativeValues: boolean;
categories: components["schemas"]["PortfolioStructureCategoryDto"][];
};
PortfolioUnvaluedCategoryDto: {
/** @enum {string} */
type: "STOCK" | "BOND" | "OTHER";
count: number;
};
PortfolioStructureDto: {
currencies: components["schemas"]["PortfolioStructureCurrencyDto"][];
/** @description Positions without current value and known valuation currency. Shares are unavailable across all currencies when nonempty. */
unvaluedCategories: components["schemas"]["PortfolioUnvaluedCategoryDto"][];
};
PortfolioDto: {
/** Format: date-time */
lastSuccessfulAt: string;
@@ -386,6 +411,7 @@ export interface components {
totalsByCurrency: components["schemas"]["MoneyDto"][];
positions: components["schemas"]["PortfolioPositionDto"][];
cashBalances: components["schemas"]["MoneyDto"][];
structure: components["schemas"]["PortfolioStructureDto"];
};
UpcomingEventDto: {
account?: components["schemas"]["AccountReferenceDto"];
+103 -1
View File
@@ -2062,6 +2062,104 @@
"logoName"
]
},
"PortfolioStructureCategoryDto": {
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"STOCK",
"BOND",
"OTHER",
"CASH"
]
},
"value": {
"type": "string",
"description": "Exact known value as a decimal string."
},
"sharePercent": {
"type": "string",
"nullable": true,
"description": "Percentage including cash, rounded to six decimal places. Null for incomplete, negative or zero-total compositions."
}
},
"required": [
"type",
"value",
"sharePercent"
]
},
"PortfolioStructureCurrencyDto": {
"type": "object",
"properties": {
"currency": {
"type": "string"
},
"totalValue": {
"type": "string"
},
"hasNegativeValues": {
"type": "boolean",
"description": "Any negative constituent, even if netted positive."
},
"categories": {
"type": "array",
"items": {
"$ref": "#/components/schemas/PortfolioStructureCategoryDto"
}
}
},
"required": [
"currency",
"totalValue",
"hasNegativeValues",
"categories"
]
},
"PortfolioUnvaluedCategoryDto": {
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"STOCK",
"BOND",
"OTHER"
]
},
"count": {
"type": "number",
"minimum": 1
}
},
"required": [
"type",
"count"
]
},
"PortfolioStructureDto": {
"type": "object",
"properties": {
"currencies": {
"type": "array",
"items": {
"$ref": "#/components/schemas/PortfolioStructureCurrencyDto"
}
},
"unvaluedCategories": {
"description": "Positions without current value and known valuation currency. Shares are unavailable across all currencies when nonempty.",
"type": "array",
"items": {
"$ref": "#/components/schemas/PortfolioUnvaluedCategoryDto"
}
}
},
"required": [
"currencies",
"unvaluedCategories"
]
},
"PortfolioDto": {
"type": "object",
"properties": {
@@ -2089,6 +2187,9 @@
"items": {
"$ref": "#/components/schemas/MoneyDto"
}
},
"structure": {
"$ref": "#/components/schemas/PortfolioStructureDto"
}
},
"required": [
@@ -2096,7 +2197,8 @@
"isStale",
"totalsByCurrency",
"positions",
"cashBalances"
"cashBalances",
"structure"
]
},
"UpcomingEventDto": {
+21
View File
@@ -93,6 +93,27 @@ const ru = {
bonds: "Облигации",
otherPositions: "Другие позиции",
cashBalances: "Денежные остатки",
structure: {
title: "Структура портфеля",
other: "Другие активы",
cash: "Свободные деньги",
currency: "Валюта структуры портфеля",
categories: "Категории активов",
chartLabel:
"Структура по типам активов. Суммы и доли — в списке рядом.",
basis: "Доли учитывают свободные деньги и округлены до сотых процента.",
incomplete:
"Оценка неполная: ниже показаны только известные суммы. Валюта оценки части позиций неизвестна, поэтому доли и диаграмма недоступны.",
unvaluedCategory: "{{category}}: без оценки — {{count}}",
negative:
"Есть отрицательные стоимости. Кольцевая диаграмма и доли недоступны; в списке сохранены суммы со знаком.",
empty: "Нет положительной стоимости для кольцевой диаграммы.",
unavailable: "Данные о структуре портфеля пока недоступны.",
shareUnavailable: "Доля недоступна",
unvalued: "Нет оценки",
knownAmount: "Известно: {{amount}}",
smallShare: "< 0,01 %",
},
quantity: "Количество: {{value}}",
return: "Доход: {{value}}",
avgPrice: "Средняя цена: {{value}}",