Bugfix/improve allocations (#710)
* Fix allocations by account for non-unique account names * Refactor calculations with big.js * Update changelog
This commit is contained in:
parent
baa6a3d0f0
commit
dced06ebb5
@ -12,6 +12,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- Moved the countries and sectors charts in the position detail dialog
|
- Moved the countries and sectors charts in the position detail dialog
|
||||||
- Restructured the server modules
|
- Restructured the server modules
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Fixed the allocations by account for non-unique account names
|
||||||
|
|
||||||
## 1.116.0 - 16.02.2022
|
## 1.116.0 - 16.02.2022
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
@ -14,7 +14,7 @@ import {
|
|||||||
} from '@ghostfolio/common/interfaces';
|
} from '@ghostfolio/common/interfaces';
|
||||||
import { hasPermission, permissions } from '@ghostfolio/common/permissions';
|
import { hasPermission, permissions } from '@ghostfolio/common/permissions';
|
||||||
import { ToggleOption } from '@ghostfolio/common/types';
|
import { ToggleOption } from '@ghostfolio/common/types';
|
||||||
import { AssetClass, DataSource } from '@prisma/client';
|
import { Account, AssetClass, DataSource } from '@prisma/client';
|
||||||
import { DeviceDetectorService } from 'ngx-device-detector';
|
import { DeviceDetectorService } from 'ngx-device-detector';
|
||||||
import { Subject, Subscription } from 'rxjs';
|
import { Subject, Subscription } from 'rxjs';
|
||||||
import { takeUntil } from 'rxjs/operators';
|
import { takeUntil } from 'rxjs/operators';
|
||||||
@ -27,7 +27,10 @@ import { takeUntil } from 'rxjs/operators';
|
|||||||
})
|
})
|
||||||
export class AllocationsPageComponent implements OnDestroy, OnInit {
|
export class AllocationsPageComponent implements OnDestroy, OnInit {
|
||||||
public accounts: {
|
public accounts: {
|
||||||
[symbol: string]: Pick<PortfolioPosition, 'name'> & { value: number };
|
[id: string]: Pick<Account, 'name'> & {
|
||||||
|
id: string;
|
||||||
|
value: number;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
public continents: {
|
public continents: {
|
||||||
[code: string]: { name: string; value: number };
|
[code: string]: { name: string; value: number };
|
||||||
@ -171,6 +174,7 @@ export class AllocationsPageComponent implements OnDestroy, OnInit {
|
|||||||
this.portfolioDetails.accounts
|
this.portfolioDetails.accounts
|
||||||
)) {
|
)) {
|
||||||
this.accounts[id] = {
|
this.accounts[id] = {
|
||||||
|
id,
|
||||||
name,
|
name,
|
||||||
value: aPeriod === 'original' ? original : current
|
value: aPeriod === 'original' ? original : current
|
||||||
};
|
};
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
<gf-portfolio-proportion-chart
|
<gf-portfolio-proportion-chart
|
||||||
[baseCurrency]="user?.settings?.baseCurrency"
|
[baseCurrency]="user?.settings?.baseCurrency"
|
||||||
[isInPercent]="hasImpersonationId || user.settings.isRestrictedView"
|
[isInPercent]="hasImpersonationId || user.settings.isRestrictedView"
|
||||||
[keys]="['name']"
|
[keys]="['id']"
|
||||||
[locale]="user?.settings?.locale"
|
[locale]="user?.settings?.locale"
|
||||||
[positions]="accounts"
|
[positions]="accounts"
|
||||||
></gf-portfolio-proportion-chart>
|
></gf-portfolio-proportion-chart>
|
||||||
|
@ -11,6 +11,7 @@ import {
|
|||||||
import { UNKNOWN_KEY } from '@ghostfolio/common/config';
|
import { UNKNOWN_KEY } from '@ghostfolio/common/config';
|
||||||
import { getTextColor } from '@ghostfolio/common/helper';
|
import { getTextColor } from '@ghostfolio/common/helper';
|
||||||
import { PortfolioPosition } from '@ghostfolio/common/interfaces';
|
import { PortfolioPosition } from '@ghostfolio/common/interfaces';
|
||||||
|
import Big from 'big.js';
|
||||||
import { Tooltip } from 'chart.js';
|
import { Tooltip } from 'chart.js';
|
||||||
import { LinearScale } from 'chart.js';
|
import { LinearScale } from 'chart.js';
|
||||||
import { ArcElement } from 'chart.js';
|
import { ArcElement } from 'chart.js';
|
||||||
@ -78,16 +79,17 @@ export class PortfolioProportionChartComponent
|
|||||||
[symbol: string]: {
|
[symbol: string]: {
|
||||||
color?: string;
|
color?: string;
|
||||||
name: string;
|
name: string;
|
||||||
subCategory: { [symbol: string]: { value: number } };
|
subCategory: { [symbol: string]: { value: Big } };
|
||||||
value: number;
|
value: Big;
|
||||||
};
|
};
|
||||||
} = {};
|
} = {};
|
||||||
|
|
||||||
Object.keys(this.positions).forEach((symbol) => {
|
Object.keys(this.positions).forEach((symbol) => {
|
||||||
if (this.positions[symbol][this.keys[0]]) {
|
if (this.positions[symbol][this.keys[0]]) {
|
||||||
if (chartData[this.positions[symbol][this.keys[0]]]) {
|
if (chartData[this.positions[symbol][this.keys[0]]]) {
|
||||||
chartData[this.positions[symbol][this.keys[0]]].value +=
|
chartData[this.positions[symbol][this.keys[0]]].value = chartData[
|
||||||
this.positions[symbol].value;
|
this.positions[symbol][this.keys[0]]
|
||||||
|
].value.plus(this.positions[symbol].value);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
chartData[this.positions[symbol][this.keys[0]]].subCategory[
|
chartData[this.positions[symbol][this.keys[0]]].subCategory[
|
||||||
@ -96,37 +98,43 @@ export class PortfolioProportionChartComponent
|
|||||||
) {
|
) {
|
||||||
chartData[this.positions[symbol][this.keys[0]]].subCategory[
|
chartData[this.positions[symbol][this.keys[0]]].subCategory[
|
||||||
this.positions[symbol][this.keys[1]]
|
this.positions[symbol][this.keys[1]]
|
||||||
].value += this.positions[symbol].value;
|
].value = chartData[
|
||||||
|
this.positions[symbol][this.keys[0]]
|
||||||
|
].subCategory[this.positions[symbol][this.keys[1]]].value.plus(
|
||||||
|
this.positions[symbol].value
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
chartData[this.positions[symbol][this.keys[0]]].subCategory[
|
chartData[this.positions[symbol][this.keys[0]]].subCategory[
|
||||||
this.positions[symbol][this.keys[1]] ?? UNKNOWN_KEY
|
this.positions[symbol][this.keys[1]] ?? UNKNOWN_KEY
|
||||||
] = { value: this.positions[symbol].value };
|
] = { value: new Big(this.positions[symbol].value) };
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
chartData[this.positions[symbol][this.keys[0]]] = {
|
chartData[this.positions[symbol][this.keys[0]]] = {
|
||||||
name: this.positions[symbol].name,
|
name: this.positions[symbol].name,
|
||||||
subCategory: {},
|
subCategory: {},
|
||||||
value: this.positions[symbol].value
|
value: new Big(this.positions[symbol].value)
|
||||||
};
|
};
|
||||||
|
|
||||||
if (this.positions[symbol][this.keys[1]]) {
|
if (this.positions[symbol][this.keys[1]]) {
|
||||||
chartData[this.positions[symbol][this.keys[0]]].subCategory = {
|
chartData[this.positions[symbol][this.keys[0]]].subCategory = {
|
||||||
[this.positions[symbol][this.keys[1]]]: {
|
[this.positions[symbol][this.keys[1]]]: {
|
||||||
value: this.positions[symbol].value
|
value: new Big(this.positions[symbol].value)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (chartData[UNKNOWN_KEY]) {
|
if (chartData[UNKNOWN_KEY]) {
|
||||||
chartData[UNKNOWN_KEY].value += this.positions[symbol].value;
|
chartData[UNKNOWN_KEY].value = chartData[UNKNOWN_KEY].value.plus(
|
||||||
|
this.positions[symbol].value
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
chartData[UNKNOWN_KEY] = {
|
chartData[UNKNOWN_KEY] = {
|
||||||
name: this.positions[symbol].name,
|
name: this.positions[symbol].name,
|
||||||
subCategory: this.keys[1]
|
subCategory: this.keys[1]
|
||||||
? { [this.keys[1]]: { value: 0 } }
|
? { [this.keys[1]]: { value: new Big(0) } }
|
||||||
: undefined,
|
: undefined,
|
||||||
value: this.positions[symbol].value
|
value: new Big(this.positions[symbol].value)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -134,7 +142,7 @@ export class PortfolioProportionChartComponent
|
|||||||
|
|
||||||
let chartDataSorted = Object.entries(chartData)
|
let chartDataSorted = Object.entries(chartData)
|
||||||
.sort((a, b) => {
|
.sort((a, b) => {
|
||||||
return a[1].value - b[1].value;
|
return a[1].value.minus(b[1].value).toNumber();
|
||||||
})
|
})
|
||||||
.reverse();
|
.reverse();
|
||||||
|
|
||||||
@ -152,7 +160,7 @@ export class PortfolioProportionChartComponent
|
|||||||
if (!unknownItem) {
|
if (!unknownItem) {
|
||||||
chartDataSorted.push([
|
chartDataSorted.push([
|
||||||
UNKNOWN_KEY,
|
UNKNOWN_KEY,
|
||||||
{ name: UNKNOWN_KEY, subCategory: {}, value: 0 }
|
{ name: UNKNOWN_KEY, subCategory: {}, value: new Big(0) }
|
||||||
]);
|
]);
|
||||||
unknownItem = chartDataSorted[chartDataSorted.length - 1];
|
unknownItem = chartDataSorted[chartDataSorted.length - 1];
|
||||||
}
|
}
|
||||||
@ -162,7 +170,7 @@ export class PortfolioProportionChartComponent
|
|||||||
unknownItem[1] = {
|
unknownItem[1] = {
|
||||||
name: UNKNOWN_KEY,
|
name: UNKNOWN_KEY,
|
||||||
subCategory: {},
|
subCategory: {},
|
||||||
value: unknownItem[1].value + restItem[1].value
|
value: unknownItem[1].value.plus(restItem[1].value)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -170,7 +178,7 @@ export class PortfolioProportionChartComponent
|
|||||||
// Sort data again
|
// Sort data again
|
||||||
chartDataSorted = chartDataSorted
|
chartDataSorted = chartDataSorted
|
||||||
.sort((a, b) => {
|
.sort((a, b) => {
|
||||||
return a[1].value - b[1].value;
|
return a[1].value.minus(b[1].value).toNumber();
|
||||||
})
|
})
|
||||||
.reverse();
|
.reverse();
|
||||||
}
|
}
|
||||||
@ -201,7 +209,7 @@ export class PortfolioProportionChartComponent
|
|||||||
backgroundColorSubCategory.push(
|
backgroundColorSubCategory.push(
|
||||||
Color(item.color).lighten(lightnessRatio).hex()
|
Color(item.color).lighten(lightnessRatio).hex()
|
||||||
);
|
);
|
||||||
dataSubCategory.push(item.subCategory[subCategory].value);
|
dataSubCategory.push(item.subCategory[subCategory].value.toNumber());
|
||||||
labelSubCategory.push(subCategory);
|
labelSubCategory.push(subCategory);
|
||||||
|
|
||||||
lightnessRatio += 0.1;
|
lightnessRatio += 0.1;
|
||||||
@ -215,7 +223,7 @@ export class PortfolioProportionChartComponent
|
|||||||
}),
|
}),
|
||||||
borderWidth: 0,
|
borderWidth: 0,
|
||||||
data: chartDataSorted.map(([, item]) => {
|
data: chartDataSorted.map(([, item]) => {
|
||||||
return item.value;
|
return item.value.toNumber();
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
Loading…
x
Reference in New Issue
Block a user