mirror of https://github.com/ghostfolio/ghostfolio
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
248 lines
7.9 KiB
248 lines
7.9 KiB
<div class="container">
|
|
<div class="row">
|
|
<div class="col">
|
|
<h2 class="d-none d-sm-block h3 mb-3 text-center">X-ray</h2>
|
|
<p i18n>
|
|
Ghostfolio X-ray uses static analysis to uncover potential issues and
|
|
risks in your portfolio. Adjust the rules below and set custom
|
|
thresholds to align with your personal investment strategy.
|
|
</p>
|
|
<div class="d-flex pb-3">
|
|
@if (isLoading) {
|
|
<div class="d-flex">
|
|
<ngx-skeleton-loader
|
|
animation="pulse"
|
|
class="mr-2"
|
|
[theme]="{
|
|
height: '2rem',
|
|
width: '2rem'
|
|
}"
|
|
/>
|
|
<ngx-skeleton-loader
|
|
animation="pulse"
|
|
class="mt-2 mb-1"
|
|
[theme]="{
|
|
height: '1rem',
|
|
width: '15rem'
|
|
}"
|
|
/>
|
|
</div>
|
|
} @else {
|
|
<div
|
|
class="align-items-center d-flex icon-container mr-2 px-2"
|
|
[ngClass]="{
|
|
okay:
|
|
statistics?.rulesFulfilledCount ===
|
|
statistics?.rulesActiveCount,
|
|
warn:
|
|
statistics?.rulesFulfilledCount !== statistics?.rulesActiveCount
|
|
}"
|
|
>
|
|
@if (
|
|
statistics?.rulesActiveCount === 0 ||
|
|
statistics?.rulesFulfilledCount === 0
|
|
) {
|
|
<ion-icon class="text-muted" name="remove-circle-outline" />
|
|
} @else if (
|
|
statistics?.rulesFulfilledCount === statistics?.rulesActiveCount
|
|
) {
|
|
<ion-icon name="checkmark-circle-outline" />
|
|
} @else {
|
|
<ion-icon name="warning-outline" />
|
|
}
|
|
</div>
|
|
<div class="d-flex align-items-center">
|
|
<ng-container>{{ statistics?.rulesFulfilledCount }} </ng-container>
|
|
<ng-container i18n>out of</ng-container>
|
|
{{ statistics?.rulesActiveCount }}
|
|
<ng-container i18n>rules align with your portfolio.</ng-container>
|
|
</div>
|
|
}
|
|
</div>
|
|
<div
|
|
class="mb-4"
|
|
[ngClass]="{
|
|
'd-none': emergencyFundRules?.length === 0
|
|
}"
|
|
>
|
|
<h4 class="align-items-center d-flex m-0">
|
|
<span i18n>Emergency Fund</span>
|
|
@if (user?.subscription?.type === 'Basic') {
|
|
<gf-premium-indicator class="ml-1" />
|
|
}
|
|
</h4>
|
|
<gf-rules
|
|
[hasPermissionToUpdateUserSettings]="
|
|
!hasImpersonationId &&
|
|
hasPermissionToUpdateUserSettings &&
|
|
user?.settings?.isExperimentalFeatures
|
|
"
|
|
[isLoading]="isLoading"
|
|
[rules]="emergencyFundRules"
|
|
[settings]="user?.settings?.xRayRules"
|
|
(rulesUpdated)="onRulesUpdated($event)"
|
|
/>
|
|
</div>
|
|
<div
|
|
class="mb-4"
|
|
[ngClass]="{
|
|
'd-none': currencyClusterRiskRules?.length === 0
|
|
}"
|
|
>
|
|
<h4 class="align-items-center d-flex m-0">
|
|
<span i18n>Currency Cluster Risks</span>
|
|
@if (user?.subscription?.type === 'Basic') {
|
|
<gf-premium-indicator class="ml-1" />
|
|
}
|
|
</h4>
|
|
<gf-rules
|
|
[hasPermissionToUpdateUserSettings]="
|
|
!hasImpersonationId &&
|
|
hasPermissionToUpdateUserSettings &&
|
|
user?.settings?.isExperimentalFeatures
|
|
"
|
|
[isLoading]="isLoading"
|
|
[rules]="currencyClusterRiskRules"
|
|
[settings]="user?.settings?.xRayRules"
|
|
(rulesUpdated)="onRulesUpdated($event)"
|
|
/>
|
|
</div>
|
|
<div
|
|
class="mb-4"
|
|
[ngClass]="{
|
|
'd-none': assetClassClusterRiskRules?.length === 0
|
|
}"
|
|
>
|
|
<h4 class="align-items-center d-flex m-0">
|
|
<span i18n>Asset Class Cluster Risks</span>
|
|
@if (user?.subscription?.type === 'Basic') {
|
|
<gf-premium-indicator class="ml-1" />
|
|
}
|
|
</h4>
|
|
<gf-rules
|
|
[hasPermissionToUpdateUserSettings]="
|
|
!hasImpersonationId &&
|
|
hasPermissionToUpdateUserSettings &&
|
|
user?.settings?.isExperimentalFeatures
|
|
"
|
|
[isLoading]="isLoading"
|
|
[rules]="assetClassClusterRiskRules"
|
|
[settings]="user?.settings?.xRayRules"
|
|
(rulesUpdated)="onRulesUpdated($event)"
|
|
/>
|
|
</div>
|
|
<div
|
|
class="mb-4"
|
|
[ngClass]="{
|
|
'd-none': accountClusterRiskRules?.length === 0
|
|
}"
|
|
>
|
|
<h4 class="align-items-center d-flex m-0">
|
|
<span i18n>Account Cluster Risks</span>
|
|
@if (user?.subscription?.type === 'Basic') {
|
|
<gf-premium-indicator class="ml-1" />
|
|
}
|
|
</h4>
|
|
<gf-rules
|
|
[hasPermissionToUpdateUserSettings]="
|
|
!hasImpersonationId &&
|
|
hasPermissionToUpdateUserSettings &&
|
|
user?.settings?.isExperimentalFeatures
|
|
"
|
|
[isLoading]="isLoading"
|
|
[rules]="accountClusterRiskRules"
|
|
[settings]="user?.settings?.xRayRules"
|
|
(rulesUpdated)="onRulesUpdated($event)"
|
|
/>
|
|
</div>
|
|
<div
|
|
class="mb-4"
|
|
[ngClass]="{
|
|
'd-none': economicMarketClusterRiskRules?.length === 0
|
|
}"
|
|
>
|
|
<h4 class="align-items-center d-flex m-0">
|
|
<span i18n>Economic Market Cluster Risks</span>
|
|
@if (user?.subscription?.type === 'Basic') {
|
|
<gf-premium-indicator class="ml-1" />
|
|
}
|
|
</h4>
|
|
<gf-rules
|
|
[hasPermissionToUpdateUserSettings]="
|
|
!hasImpersonationId &&
|
|
hasPermissionToUpdateUserSettings &&
|
|
user?.settings?.isExperimentalFeatures
|
|
"
|
|
[isLoading]="isLoading"
|
|
[rules]="economicMarketClusterRiskRules"
|
|
[settings]="user?.settings?.xRayRules"
|
|
(rulesUpdated)="onRulesUpdated($event)"
|
|
/>
|
|
</div>
|
|
<div
|
|
class="mb-4"
|
|
[ngClass]="{
|
|
'd-none': regionalMarketClusterRiskRules?.length === 0
|
|
}"
|
|
>
|
|
<h4 class="align-items-center d-flex m-0">
|
|
<span i18n>Regional Market Cluster Risks</span>
|
|
@if (user?.subscription?.type === 'Basic') {
|
|
<gf-premium-indicator class="ml-1" />
|
|
}
|
|
</h4>
|
|
<gf-rules
|
|
[hasPermissionToUpdateUserSettings]="
|
|
!hasImpersonationId &&
|
|
hasPermissionToUpdateUserSettings &&
|
|
user?.settings?.isExperimentalFeatures
|
|
"
|
|
[isLoading]="isLoading"
|
|
[rules]="regionalMarketClusterRiskRules"
|
|
[settings]="user?.settings?.xRayRules"
|
|
(rulesUpdated)="onRulesUpdated($event)"
|
|
/>
|
|
</div>
|
|
<div
|
|
class="mb-4"
|
|
[ngClass]="{
|
|
'd-none': feeRules?.length === 0
|
|
}"
|
|
>
|
|
<h4 class="align-items-center d-flex m-0">
|
|
<span i18n>Fees</span>
|
|
@if (user?.subscription?.type === 'Basic') {
|
|
<gf-premium-indicator class="ml-1" />
|
|
}
|
|
</h4>
|
|
<gf-rules
|
|
[hasPermissionToUpdateUserSettings]="
|
|
!hasImpersonationId &&
|
|
hasPermissionToUpdateUserSettings &&
|
|
user?.settings?.isExperimentalFeatures
|
|
"
|
|
[isLoading]="isLoading"
|
|
[rules]="feeRules"
|
|
[settings]="user?.settings?.xRayRules"
|
|
(rulesUpdated)="onRulesUpdated($event)"
|
|
/>
|
|
</div>
|
|
@if (inactiveRules?.length > 0) {
|
|
<div>
|
|
<h4 class="m-0" i18n>Inactive</h4>
|
|
<gf-rules
|
|
[hasPermissionToUpdateUserSettings]="
|
|
!hasImpersonationId &&
|
|
hasPermissionToUpdateUserSettings &&
|
|
user?.settings?.isExperimentalFeatures
|
|
"
|
|
[isLoading]="isLoading"
|
|
[rules]="inactiveRules"
|
|
[settings]="user?.settings?.xRayRules"
|
|
(rulesUpdated)="onRulesUpdated($event)"
|
|
/>
|
|
</div>
|
|
}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|