|
|
@ -6,6 +6,7 @@ import { UserService } from '@ghostfolio/client/services/user/user.service';
|
|
|
|
import { UNKNOWN_KEY } from '@ghostfolio/common/config';
|
|
|
|
import { UNKNOWN_KEY } from '@ghostfolio/common/config';
|
|
|
|
import { prettifySymbol } from '@ghostfolio/common/helper';
|
|
|
|
import { prettifySymbol } from '@ghostfolio/common/helper';
|
|
|
|
import {
|
|
|
|
import {
|
|
|
|
|
|
|
|
Holding,
|
|
|
|
PortfolioDetails,
|
|
|
|
PortfolioDetails,
|
|
|
|
PortfolioPosition,
|
|
|
|
PortfolioPosition,
|
|
|
|
UniqueAsset,
|
|
|
|
UniqueAsset,
|
|
|
@ -84,6 +85,11 @@ export class AllocationsPageComponent implements OnDestroy, OnInit {
|
|
|
|
value: number;
|
|
|
|
value: number;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
public topHoldings: Holding[] = [];
|
|
|
|
|
|
|
|
public topHoldingsMap: {
|
|
|
|
|
|
|
|
[name: string]: { name: string; value: number };
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
public totalValueInEtf = 0;
|
|
|
|
public UNKNOWN_KEY = UNKNOWN_KEY;
|
|
|
|
public UNKNOWN_KEY = UNKNOWN_KEY;
|
|
|
|
public user: User;
|
|
|
|
public user: User;
|
|
|
|
public worldMapChartFormat: string;
|
|
|
|
public worldMapChartFormat: string;
|
|
|
@ -288,6 +294,7 @@ export class AllocationsPageComponent implements OnDestroy, OnInit {
|
|
|
|
value: 0
|
|
|
|
value: 0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
this.topHoldingsMap = {};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private initializeAllocationsData() {
|
|
|
|
private initializeAllocationsData() {
|
|
|
@ -337,7 +344,7 @@ export class AllocationsPageComponent implements OnDestroy, OnInit {
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
if (position.assetClass !== AssetClass.LIQUIDITY) {
|
|
|
|
if (position.assetClass !== AssetClass.LIQUIDITY) {
|
|
|
|
// Prepare analysis data by continents, countries and sectors except for liquidity
|
|
|
|
// Prepare analysis data by continents, countries, holdings and sectors except for liquidity
|
|
|
|
|
|
|
|
|
|
|
|
if (position.countries.length > 0) {
|
|
|
|
if (position.countries.length > 0) {
|
|
|
|
this.markets.developedMarkets.value +=
|
|
|
|
this.markets.developedMarkets.value +=
|
|
|
@ -445,6 +452,29 @@ export class AllocationsPageComponent implements OnDestroy, OnInit {
|
|
|
|
: this.portfolioDetails.holdings[symbol].valueInPercentage;
|
|
|
|
: this.portfolioDetails.holdings[symbol].valueInPercentage;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (position.holdings.length > 0) {
|
|
|
|
|
|
|
|
for (const holding of position.holdings) {
|
|
|
|
|
|
|
|
const { name, valueInBaseCurrency } = holding;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (this.topHoldingsMap[name]?.value) {
|
|
|
|
|
|
|
|
this.topHoldingsMap[name].value +=
|
|
|
|
|
|
|
|
valueInBaseCurrency *
|
|
|
|
|
|
|
|
(isNumber(position.valueInBaseCurrency)
|
|
|
|
|
|
|
|
? position.valueInBaseCurrency
|
|
|
|
|
|
|
|
: position.valueInPercentage);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
this.topHoldingsMap[name] = {
|
|
|
|
|
|
|
|
name,
|
|
|
|
|
|
|
|
value:
|
|
|
|
|
|
|
|
valueInBaseCurrency *
|
|
|
|
|
|
|
|
(isNumber(position.valueInBaseCurrency)
|
|
|
|
|
|
|
|
? this.portfolioDetails.holdings[symbol].valueInBaseCurrency
|
|
|
|
|
|
|
|
: this.portfolioDetails.holdings[symbol].valueInPercentage)
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (position.sectors.length > 0) {
|
|
|
|
if (position.sectors.length > 0) {
|
|
|
|
for (const sector of position.sectors) {
|
|
|
|
for (const sector of position.sectors) {
|
|
|
|
const { name, weight } = sector;
|
|
|
|
const { name, weight } = sector;
|
|
|
@ -475,6 +505,14 @@ export class AllocationsPageComponent implements OnDestroy, OnInit {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (
|
|
|
|
|
|
|
|
this.positions[symbol].assetSubClass === 'ETF' &&
|
|
|
|
|
|
|
|
!this.hasImpersonationId &&
|
|
|
|
|
|
|
|
!this.user.settings.isRestrictedView
|
|
|
|
|
|
|
|
) {
|
|
|
|
|
|
|
|
this.totalValueInEtf += this.positions[symbol].value;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
this.symbols[prettifySymbol(symbol)] = {
|
|
|
|
this.symbols[prettifySymbol(symbol)] = {
|
|
|
|
dataSource: position.dataSource,
|
|
|
|
dataSource: position.dataSource,
|
|
|
|
name: position.name,
|
|
|
|
name: position.name,
|
|
|
@ -518,6 +556,21 @@ export class AllocationsPageComponent implements OnDestroy, OnInit {
|
|
|
|
this.markets.otherMarkets.value / marketsTotal;
|
|
|
|
this.markets.otherMarkets.value / marketsTotal;
|
|
|
|
this.markets[UNKNOWN_KEY].value =
|
|
|
|
this.markets[UNKNOWN_KEY].value =
|
|
|
|
this.markets[UNKNOWN_KEY].value / marketsTotal;
|
|
|
|
this.markets[UNKNOWN_KEY].value / marketsTotal;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!this.hasImpersonationId && !this.user.settings.isRestrictedView) {
|
|
|
|
|
|
|
|
this.topHoldings = Object.values(this.topHoldingsMap)
|
|
|
|
|
|
|
|
.map(({ name, value }) => {
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
|
|
|
name,
|
|
|
|
|
|
|
|
allocationInPercentage:
|
|
|
|
|
|
|
|
this.totalValueInEtf > 0 ? value / this.totalValueInEtf : 0,
|
|
|
|
|
|
|
|
valueInBaseCurrency: value
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
.sort((a, b) => {
|
|
|
|
|
|
|
|
return b.valueInBaseCurrency - a.valueInBaseCurrency;
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private openAccountDetailDialog(aAccountId: string) {
|
|
|
|
private openAccountDetailDialog(aAccountId: string) {
|
|
|
|