Merge branch 'main' of gitea.suda.codes:giteauser/ghostfolio-mirror
This commit is contained in:
commit
788c9d853c
14
CHANGELOG.md
14
CHANGELOG.md
@ -5,6 +5,20 @@ All notable changes to this project will be documented in this file.
|
|||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## Unreleased
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Added the logotype to the footer
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Improved the backgrounds of the chart of the holdings tab on the home page (experimental)
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Fixed an issue in the carousel component for the testimonial section on the landing page
|
||||||
|
|
||||||
## 2.116.0 - 2024-10-17
|
## 2.116.0 - 2024-10-17
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
@ -46,7 +46,7 @@
|
|||||||
</main>
|
</main>
|
||||||
|
|
||||||
@if (showFooter) {
|
@if (showFooter) {
|
||||||
<footer class="d-flex justify-content-center py-4 w-100">
|
<footer class="justify-content-center overflow-hidden py-4 w-100">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="mb-3 row">
|
<div class="mb-3 row">
|
||||||
<div class="col-sm">
|
<div class="col-sm">
|
||||||
@ -187,7 +187,7 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row text-center">
|
<div class="mb-2 row text-center">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
© 2021 - {{ currentYear }}
|
© 2021 - {{ currentYear }}
|
||||||
<a href="https://ghostfol.io">Ghostfolio</a>
|
<a href="https://ghostfol.io">Ghostfolio</a>
|
||||||
@ -195,12 +195,17 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="row text-center text-muted">
|
<div class="row text-center text-muted">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<small i18n
|
<small class="d-block" i18n
|
||||||
>The risk of loss in trading can be substantial. It is not advisable
|
>The risk of loss in trading can be substantial. It is not advisable
|
||||||
to invest money you may need in the short term.</small
|
to invest money you may need in the short term.</small
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="container d-none d-md-block mt-5">
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="font-weight-bold line-height-1 logotype">Ghostfolio</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,13 @@
|
|||||||
footer {
|
footer {
|
||||||
background-color: rgba(var(--palette-foreground-text), 0.05);
|
background-color: rgba(var(--palette-foreground-text), 0.05);
|
||||||
font-size: 90%;
|
font-size: 90%;
|
||||||
|
|
||||||
|
.logotype {
|
||||||
|
font-size: 13vw;
|
||||||
|
letter-spacing: -0.03em;
|
||||||
|
margin-bottom: -5svw;
|
||||||
|
opacity: 0.05;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
header {
|
header {
|
||||||
|
@ -115,6 +115,7 @@ export const personalFinanceTools: Product[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
founded: 2022,
|
founded: 2022,
|
||||||
|
isArchived: true,
|
||||||
key: 'capmon',
|
key: 'capmon',
|
||||||
name: 'CapMon.org',
|
name: 'CapMon.org',
|
||||||
origin: 'Germany',
|
origin: 'Germany',
|
||||||
@ -303,6 +304,7 @@ export const personalFinanceTools: Product[] = [
|
|||||||
{
|
{
|
||||||
hasFreePlan: true,
|
hasFreePlan: true,
|
||||||
hasSelfHostingAbility: false,
|
hasSelfHostingAbility: false,
|
||||||
|
isArchived: true,
|
||||||
key: 'intuit-mint',
|
key: 'intuit-mint',
|
||||||
name: 'Intuit Mint',
|
name: 'Intuit Mint',
|
||||||
note: 'Intuit Mint was discontinued in 2023',
|
note: 'Intuit Mint was discontinued in 2023',
|
||||||
@ -413,6 +415,7 @@ export const personalFinanceTools: Product[] = [
|
|||||||
{
|
{
|
||||||
founded: 1991,
|
founded: 1991,
|
||||||
hasSelfHostingAbility: true,
|
hasSelfHostingAbility: true,
|
||||||
|
isArchived: true,
|
||||||
key: 'microsoft-money',
|
key: 'microsoft-money',
|
||||||
name: 'Microsoft Money',
|
name: 'Microsoft Money',
|
||||||
note: 'Microsoft Money was discontinued in 2010',
|
note: 'Microsoft Money was discontinued in 2010',
|
||||||
@ -520,6 +523,7 @@ export const personalFinanceTools: Product[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
hasFreePlan: true,
|
hasFreePlan: true,
|
||||||
|
isArchived: true,
|
||||||
key: 'portfoloo',
|
key: 'portfoloo',
|
||||||
name: 'Portfoloo',
|
name: 'Portfoloo',
|
||||||
note: 'Portfoloo was discontinued',
|
note: 'Portfoloo was discontinued',
|
||||||
@ -558,6 +562,7 @@ export const personalFinanceTools: Product[] = [
|
|||||||
{
|
{
|
||||||
founded: 2019,
|
founded: 2019,
|
||||||
hasSelfHostingAbility: false,
|
hasSelfHostingAbility: false,
|
||||||
|
isArchived: true,
|
||||||
key: 'sarmaaya.pk',
|
key: 'sarmaaya.pk',
|
||||||
name: 'Sarmaaya.pk Portfolio Tracking',
|
name: 'Sarmaaya.pk Portfolio Tracking',
|
||||||
note: 'Sarmaaya.pk Portfolio Tracking was discontinued in 2024',
|
note: 'Sarmaaya.pk Portfolio Tracking was discontinued in 2024',
|
||||||
@ -594,6 +599,7 @@ export const personalFinanceTools: Product[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
hasFreePlan: true,
|
hasFreePlan: true,
|
||||||
|
isArchived: true,
|
||||||
key: 'sharesmaster',
|
key: 'sharesmaster',
|
||||||
name: 'SharesMaster',
|
name: 'SharesMaster',
|
||||||
note: 'SharesMaster was discontinued',
|
note: 'SharesMaster was discontinued',
|
||||||
@ -634,6 +640,7 @@ export const personalFinanceTools: Product[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
founded: 2008,
|
founded: 2008,
|
||||||
|
isArchived: true,
|
||||||
key: 'stockmarketeye',
|
key: 'stockmarketeye',
|
||||||
name: 'StockMarketEye',
|
name: 'StockMarketEye',
|
||||||
origin: 'France',
|
origin: 'France',
|
||||||
@ -746,6 +753,7 @@ export const personalFinanceTools: Product[] = [
|
|||||||
founded: 2021,
|
founded: 2021,
|
||||||
hasFreePlan: true,
|
hasFreePlan: true,
|
||||||
hasSelfHostingAbility: false,
|
hasSelfHostingAbility: false,
|
||||||
|
isArchived: true,
|
||||||
key: 'yeekatee',
|
key: 'yeekatee',
|
||||||
languages: ['Deutsch', 'English', 'Español', 'Français', 'Italiano'],
|
languages: ['Deutsch', 'English', 'Español', 'Français', 'Italiano'],
|
||||||
name: 'yeekatee',
|
name: 'yeekatee',
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
::ng-deep {
|
::ng-deep {
|
||||||
[gf-carousel-item] {
|
[gfCarouselItem] {
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
:host {
|
:host {
|
||||||
.label {
|
.label {
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
|
letter-spacing: -0.03em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.logo {
|
.logo {
|
||||||
|
@ -57,8 +57,6 @@ export class GfTreemapChartComponent
|
|||||||
|
|
||||||
@ViewChild('chartCanvas') chartCanvas: ElementRef<HTMLCanvasElement>;
|
@ViewChild('chartCanvas') chartCanvas: ElementRef<HTMLCanvasElement>;
|
||||||
|
|
||||||
public static readonly HEAT_MULTIPLIER = 5;
|
|
||||||
|
|
||||||
public chart: Chart<'treemap'>;
|
public chart: Chart<'treemap'>;
|
||||||
public isLoading = true;
|
public isLoading = true;
|
||||||
|
|
||||||
@ -87,6 +85,44 @@ export class GfTreemapChartComponent
|
|||||||
|
|
||||||
const { endDate, startDate } = getIntervalFromDateRange(this.dateRange);
|
const { endDate, startDate } = getIntervalFromDateRange(this.dateRange);
|
||||||
|
|
||||||
|
const netPerformancePercentsWithCurrencyEffect = this.holdings.map(
|
||||||
|
({ dateOfFirstActivity, netPerformancePercentWithCurrencyEffect }) => {
|
||||||
|
return getAnnualizedPerformancePercent({
|
||||||
|
daysInMarket: differenceInDays(
|
||||||
|
endDate,
|
||||||
|
max([dateOfFirstActivity ?? new Date(0), startDate])
|
||||||
|
),
|
||||||
|
netPerformancePercentage: new Big(
|
||||||
|
netPerformancePercentWithCurrencyEffect
|
||||||
|
)
|
||||||
|
}).toNumber();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const positiveNetPerformancePercents =
|
||||||
|
netPerformancePercentsWithCurrencyEffect.filter(
|
||||||
|
(annualizedNetPerformancePercent) => {
|
||||||
|
return annualizedNetPerformancePercent > 0;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const positiveNetPerformancePercentsRange = {
|
||||||
|
max: Math.max(...positiveNetPerformancePercents),
|
||||||
|
min: Math.min(...positiveNetPerformancePercents)
|
||||||
|
};
|
||||||
|
|
||||||
|
const negativeNetPerformancePercents =
|
||||||
|
netPerformancePercentsWithCurrencyEffect.filter(
|
||||||
|
(annualizedNetPerformancePercent) => {
|
||||||
|
return annualizedNetPerformancePercent < 0;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const negativeNetPerformancePercentsRange = {
|
||||||
|
max: Math.max(...negativeNetPerformancePercents),
|
||||||
|
min: Math.min(...negativeNetPerformancePercents)
|
||||||
|
};
|
||||||
|
|
||||||
const data: ChartConfiguration['data'] = {
|
const data: ChartConfiguration['data'] = {
|
||||||
datasets: [
|
datasets: [
|
||||||
{
|
{
|
||||||
@ -112,46 +148,58 @@ export class GfTreemapChartComponent
|
|||||||
) / 100;
|
) / 100;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
annualizedNetPerformancePercentWithCurrencyEffect >
|
|
||||||
0.03 * GfTreemapChartComponent.HEAT_MULTIPLIER
|
|
||||||
) {
|
|
||||||
return green[9];
|
|
||||||
} else if (
|
|
||||||
annualizedNetPerformancePercentWithCurrencyEffect >
|
|
||||||
0.02 * GfTreemapChartComponent.HEAT_MULTIPLIER
|
|
||||||
) {
|
|
||||||
return green[7];
|
|
||||||
} else if (
|
|
||||||
annualizedNetPerformancePercentWithCurrencyEffect >
|
|
||||||
0.01 * GfTreemapChartComponent.HEAT_MULTIPLIER
|
|
||||||
) {
|
|
||||||
return green[5];
|
|
||||||
} else if (annualizedNetPerformancePercentWithCurrencyEffect > 0) {
|
|
||||||
return green[3];
|
|
||||||
} else if (
|
|
||||||
Math.abs(annualizedNetPerformancePercentWithCurrencyEffect) === 0
|
Math.abs(annualizedNetPerformancePercentWithCurrencyEffect) === 0
|
||||||
) {
|
) {
|
||||||
annualizedNetPerformancePercentWithCurrencyEffect = Math.abs(
|
annualizedNetPerformancePercentWithCurrencyEffect = Math.abs(
|
||||||
annualizedNetPerformancePercentWithCurrencyEffect
|
annualizedNetPerformancePercentWithCurrencyEffect
|
||||||
);
|
);
|
||||||
return gray[3];
|
return gray[3];
|
||||||
} else if (
|
} else if (annualizedNetPerformancePercentWithCurrencyEffect > 0) {
|
||||||
annualizedNetPerformancePercentWithCurrencyEffect >
|
const range =
|
||||||
-0.01 * GfTreemapChartComponent.HEAT_MULTIPLIER
|
positiveNetPerformancePercentsRange.max -
|
||||||
) {
|
positiveNetPerformancePercentsRange.min;
|
||||||
return red[3];
|
|
||||||
} else if (
|
if (
|
||||||
annualizedNetPerformancePercentWithCurrencyEffect >
|
annualizedNetPerformancePercentWithCurrencyEffect >=
|
||||||
-0.02 * GfTreemapChartComponent.HEAT_MULTIPLIER
|
positiveNetPerformancePercentsRange.max - range * 0.25
|
||||||
) {
|
) {
|
||||||
return red[5];
|
return green[9];
|
||||||
} else if (
|
} else if (
|
||||||
annualizedNetPerformancePercentWithCurrencyEffect >
|
annualizedNetPerformancePercentWithCurrencyEffect >=
|
||||||
-0.03 * GfTreemapChartComponent.HEAT_MULTIPLIER
|
positiveNetPerformancePercentsRange.max - range * 0.5
|
||||||
) {
|
) {
|
||||||
return red[7];
|
return green[7];
|
||||||
|
} else if (
|
||||||
|
annualizedNetPerformancePercentWithCurrencyEffect >=
|
||||||
|
positiveNetPerformancePercentsRange.max - range * 0.75
|
||||||
|
) {
|
||||||
|
return green[5];
|
||||||
|
}
|
||||||
|
|
||||||
|
return green[3];
|
||||||
} else {
|
} else {
|
||||||
return red[9];
|
const range =
|
||||||
|
negativeNetPerformancePercentsRange.min -
|
||||||
|
negativeNetPerformancePercentsRange.max;
|
||||||
|
|
||||||
|
if (
|
||||||
|
annualizedNetPerformancePercentWithCurrencyEffect <=
|
||||||
|
negativeNetPerformancePercentsRange.min + range * 0.25
|
||||||
|
) {
|
||||||
|
return red[9];
|
||||||
|
} else if (
|
||||||
|
annualizedNetPerformancePercentWithCurrencyEffect <=
|
||||||
|
negativeNetPerformancePercentsRange.min + range * 0.5
|
||||||
|
) {
|
||||||
|
return red[7];
|
||||||
|
} else if (
|
||||||
|
annualizedNetPerformancePercentWithCurrencyEffect <=
|
||||||
|
negativeNetPerformancePercentsRange.min + range * 0.75
|
||||||
|
) {
|
||||||
|
return red[5];
|
||||||
|
}
|
||||||
|
|
||||||
|
return red[3];
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
borderRadius: 4,
|
borderRadius: 4,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user