Feature/add developed vs emerging markets calculation (#767)
* Add allocations by market * Update changelog
This commit is contained in:
@@ -14,7 +14,7 @@ import {
|
||||
User
|
||||
} from '@ghostfolio/common/interfaces';
|
||||
import { hasPermission, permissions } from '@ghostfolio/common/permissions';
|
||||
import { ToggleOption } from '@ghostfolio/common/types';
|
||||
import { Market, ToggleOption } from '@ghostfolio/common/types';
|
||||
import { Account, AssetClass, DataSource } from '@prisma/client';
|
||||
import { DeviceDetectorService } from 'ngx-device-detector';
|
||||
import { Subject, Subscription } from 'rxjs';
|
||||
@@ -42,6 +42,9 @@ export class AllocationsPageComponent implements OnDestroy, OnInit {
|
||||
public deviceType: string;
|
||||
public hasImpersonationId: boolean;
|
||||
public hasPermissionToCreateOrder: boolean;
|
||||
public markets: {
|
||||
[key in Market]: { name: string; value: number };
|
||||
};
|
||||
public period = 'current';
|
||||
public periodOptions: ToggleOption[] = [
|
||||
{ label: 'Initial', value: 'original' },
|
||||
@@ -160,6 +163,20 @@ export class AllocationsPageComponent implements OnDestroy, OnInit {
|
||||
value: 0
|
||||
}
|
||||
};
|
||||
this.markets = {
|
||||
developedMarkets: {
|
||||
name: 'developedMarkets',
|
||||
value: 0
|
||||
},
|
||||
emergingMarkets: {
|
||||
name: 'emergingMarkets',
|
||||
value: 0
|
||||
},
|
||||
otherMarkets: {
|
||||
name: 'otherMarkets',
|
||||
value: 0
|
||||
}
|
||||
};
|
||||
this.positions = {};
|
||||
this.positionsArray = [];
|
||||
this.sectors = {
|
||||
@@ -219,6 +236,16 @@ export class AllocationsPageComponent implements OnDestroy, OnInit {
|
||||
// Prepare analysis data by continents, countries and sectors except for cash
|
||||
|
||||
if (position.countries.length > 0) {
|
||||
this.markets.developedMarkets.value +=
|
||||
position.markets.developedMarkets *
|
||||
(aPeriod === 'original' ? position.investment : position.value);
|
||||
this.markets.emergingMarkets.value +=
|
||||
position.markets.emergingMarkets *
|
||||
(aPeriod === 'original' ? position.investment : position.value);
|
||||
this.markets.otherMarkets.value +=
|
||||
position.markets.otherMarkets *
|
||||
(aPeriod === 'original' ? position.investment : position.value);
|
||||
|
||||
for (const country of position.countries) {
|
||||
const { code, continent, name, weight } = country;
|
||||
|
||||
@@ -294,6 +321,18 @@ export class AllocationsPageComponent implements OnDestroy, OnInit {
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const marketsTotal =
|
||||
this.markets.developedMarkets.value +
|
||||
this.markets.emergingMarkets.value +
|
||||
this.markets.otherMarkets.value;
|
||||
|
||||
this.markets.developedMarkets.value =
|
||||
this.markets.developedMarkets.value / marketsTotal;
|
||||
this.markets.emergingMarkets.value =
|
||||
this.markets.emergingMarkets.value / marketsTotal;
|
||||
this.markets.otherMarkets.value =
|
||||
this.markets.otherMarkets.value / marketsTotal;
|
||||
}
|
||||
|
||||
public onChangePeriod(aValue: string) {
|
||||
|
@@ -190,6 +190,32 @@
|
||||
[countries]="countries"
|
||||
[isInPercent]="hasImpersonationId || user.settings.isRestrictedView"
|
||||
></gf-world-map-chart>
|
||||
<div class="row">
|
||||
<div class="col-xs-12 col-md-4 my-2">
|
||||
<gf-value
|
||||
label="Developed Markets"
|
||||
size="large"
|
||||
[isPercent]="true"
|
||||
[value]="markets?.developedMarkets?.value"
|
||||
></gf-value>
|
||||
</div>
|
||||
<div class="col-xs-12 col-md-4 my-2">
|
||||
<gf-value
|
||||
label="Emerging Markets"
|
||||
size="large"
|
||||
[isPercent]="true"
|
||||
[value]="markets?.emergingMarkets?.value"
|
||||
></gf-value>
|
||||
</div>
|
||||
<div class="col-xs-12 col-md-4 my-2">
|
||||
<gf-value
|
||||
label="Other Markets"
|
||||
size="large"
|
||||
[isPercent]="true"
|
||||
[value]="markets?.otherMarkets?.value"
|
||||
></gf-value>
|
||||
</div>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
</div>
|
||||
|
@@ -5,6 +5,7 @@ import { GfPositionsTableModule } from '@ghostfolio/client/components/positions-
|
||||
import { GfToggleModule } from '@ghostfolio/client/components/toggle/toggle.module';
|
||||
import { GfWorldMapChartModule } from '@ghostfolio/client/components/world-map-chart/world-map-chart.module';
|
||||
import { GfPortfolioProportionChartModule } from '@ghostfolio/ui/portfolio-proportion-chart/portfolio-proportion-chart.module';
|
||||
import { GfValueModule } from '@ghostfolio/ui/value';
|
||||
|
||||
import { AllocationsPageRoutingModule } from './allocations-page-routing.module';
|
||||
import { AllocationsPageComponent } from './allocations-page.component';
|
||||
@@ -19,6 +20,7 @@ import { AllocationsPageComponent } from './allocations-page.component';
|
||||
GfPositionsTableModule,
|
||||
GfToggleModule,
|
||||
GfWorldMapChartModule,
|
||||
GfValueModule,
|
||||
MatCardModule
|
||||
],
|
||||
providers: [],
|
||||
|
@@ -7,6 +7,7 @@ import {
|
||||
PortfolioPosition,
|
||||
PortfolioPublicDetails
|
||||
} from '@ghostfolio/common/interfaces';
|
||||
import { Market } from '@ghostfolio/common/types';
|
||||
import { StatusCodes } from 'http-status-codes';
|
||||
import { DeviceDetectorService } from 'ngx-device-detector';
|
||||
import { EMPTY, Subject } from 'rxjs';
|
||||
@@ -26,6 +27,9 @@ export class PublicPageComponent implements OnInit {
|
||||
[code: string]: { name: string; value: number };
|
||||
};
|
||||
public deviceType: string;
|
||||
public markets: {
|
||||
[key in Market]: { name: string; value: number };
|
||||
};
|
||||
public portfolioPublicDetails: PortfolioPublicDetails;
|
||||
public positions: {
|
||||
[symbol: string]: Pick<PortfolioPosition, 'currency' | 'name' | 'value'>;
|
||||
@@ -96,6 +100,20 @@ export class PublicPageComponent implements OnInit {
|
||||
value: 0
|
||||
}
|
||||
};
|
||||
this.markets = {
|
||||
developedMarkets: {
|
||||
name: 'developedMarkets',
|
||||
value: 0
|
||||
},
|
||||
emergingMarkets: {
|
||||
name: 'emergingMarkets',
|
||||
value: 0
|
||||
},
|
||||
otherMarkets: {
|
||||
name: 'otherMarkets',
|
||||
value: 0
|
||||
}
|
||||
};
|
||||
this.positions = {};
|
||||
this.sectors = {
|
||||
[UNKNOWN_KEY]: {
|
||||
@@ -123,6 +141,13 @@ export class PublicPageComponent implements OnInit {
|
||||
};
|
||||
|
||||
if (position.countries.length > 0) {
|
||||
this.markets.developedMarkets.value +=
|
||||
position.markets.developedMarkets * position.value;
|
||||
this.markets.emergingMarkets.value +=
|
||||
position.markets.emergingMarkets * position.value;
|
||||
this.markets.otherMarkets.value +=
|
||||
position.markets.otherMarkets * position.value;
|
||||
|
||||
for (const country of position.countries) {
|
||||
const { code, continent, name, weight } = country;
|
||||
|
||||
@@ -176,6 +201,18 @@ export class PublicPageComponent implements OnInit {
|
||||
value: position.value
|
||||
};
|
||||
}
|
||||
|
||||
const marketsTotal =
|
||||
this.markets.developedMarkets.value +
|
||||
this.markets.emergingMarkets.value +
|
||||
this.markets.otherMarkets.value;
|
||||
|
||||
this.markets.developedMarkets.value =
|
||||
this.markets.developedMarkets.value / marketsTotal;
|
||||
this.markets.emergingMarkets.value =
|
||||
this.markets.emergingMarkets.value / marketsTotal;
|
||||
this.markets.otherMarkets.value =
|
||||
this.markets.otherMarkets.value / marketsTotal;
|
||||
}
|
||||
|
||||
public ngOnDestroy() {
|
||||
|
@@ -79,12 +79,38 @@
|
||||
[countries]="countries"
|
||||
[isInPercent]="true"
|
||||
></gf-world-map-chart>
|
||||
<div class="row">
|
||||
<div class="col-xs-12 col-md-4 my-2">
|
||||
<gf-value
|
||||
label="Developed Markets"
|
||||
size="large"
|
||||
[isPercent]="true"
|
||||
[value]="markets?.developedMarkets?.value"
|
||||
></gf-value>
|
||||
</div>
|
||||
<div class="col-xs-12 col-md-4 my-2">
|
||||
<gf-value
|
||||
label="Emerging Markets"
|
||||
size="large"
|
||||
[isPercent]="true"
|
||||
[value]="markets?.emergingMarkets?.value"
|
||||
></gf-value>
|
||||
</div>
|
||||
<div class="col-xs-12 col-md-4 my-2">
|
||||
<gf-value
|
||||
label="Other Markets"
|
||||
size="large"
|
||||
[isPercent]="true"
|
||||
[value]="markets?.otherMarkets?.value"
|
||||
></gf-value>
|
||||
</div>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-5">
|
||||
<div class="col-md-8 offset-md-2">
|
||||
<div class="col-md-10 offset-md-1">
|
||||
<h2 class="h4 mb-1 text-center">
|
||||
Would you like to <strong>refine</strong> your
|
||||
<strong>personal investment strategy</strong>?
|
||||
|
@@ -4,6 +4,7 @@ import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatCardModule } from '@angular/material/card';
|
||||
import { GfWorldMapChartModule } from '@ghostfolio/client/components/world-map-chart/world-map-chart.module';
|
||||
import { GfPortfolioProportionChartModule } from '@ghostfolio/ui/portfolio-proportion-chart/portfolio-proportion-chart.module';
|
||||
import { GfValueModule } from '@ghostfolio/ui/value';
|
||||
|
||||
import { PublicPageRoutingModule } from './public-page-routing.module';
|
||||
import { PublicPageComponent } from './public-page.component';
|
||||
@@ -14,6 +15,7 @@ import { PublicPageComponent } from './public-page.component';
|
||||
imports: [
|
||||
CommonModule,
|
||||
GfPortfolioProportionChartModule,
|
||||
GfValueModule,
|
||||
GfWorldMapChartModule,
|
||||
MatButtonModule,
|
||||
MatCardModule,
|
||||
|
Reference in New Issue
Block a user