Compare commits
7 Commits
Author | SHA1 | Date | |
---|---|---|---|
f68f40fcc6 | |||
9623a363ed | |||
2d42549967 | |||
c934c5088b | |||
678b3cc57e | |||
cd5eb64a4c | |||
fc1507de4f |
@ -5,6 +5,14 @@ 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/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## 1.211.0 - 11.11.2022
|
||||
|
||||
### Changed
|
||||
|
||||
- Converted the client into a _Progressive Web App_ (PWA) with `@angular/pwa`
|
||||
- Removed the bottom margin from the body element
|
||||
- Improved the pricing page
|
||||
|
||||
## 1.210.0 - 08.11.2022
|
||||
|
||||
### Added
|
||||
|
16
README.md
16
README.md
@ -53,7 +53,7 @@ Ghostfolio is for you if you are...
|
||||
|
||||
- ✅ Create, update and delete transactions
|
||||
- ✅ Multi account management
|
||||
- ✅ Portfolio performance: Time-weighted rate of return (TWR) for `Today`, `YTD`, `1Y`, `5Y`, `Max`
|
||||
- ✅ Portfolio performance for `Today`, `YTD`, `1Y`, `5Y`, `Max`
|
||||
- ✅ Various charts
|
||||
- ✅ Static analysis to identify potential risks in your portfolio
|
||||
- ✅ Import and export transactions
|
||||
@ -81,6 +81,16 @@ The frontend is built with [Angular](https://angular.io) and uses [Angular Mater
|
||||
|
||||
We provide official container images hosted on [Docker Hub](https://hub.docker.com/r/ghostfolio/ghostfolio) for `linux/amd64` and `linux/arm64`.
|
||||
|
||||
<div align="center">
|
||||
<a href="https://www.buymeacoffee.com/ghostfolio">
|
||||
<img
|
||||
alt="Buy me a coffee button"
|
||||
src="./apps/client/src/assets/images/button-buy-me-a-coffee.png"
|
||||
width="150"
|
||||
/>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
### Supported Environment Variables
|
||||
|
||||
| Name | Default Value | Description |
|
||||
@ -256,6 +266,10 @@ You can get the _Bearer Token_ via `GET http://localhost:3333/api/v1/auth/anonym
|
||||
}
|
||||
```
|
||||
|
||||
## Community Projects
|
||||
|
||||
- [ghostfolio-cli](https://github.com/DerAndereJohannes/ghostfolio-cli): Command-line interface to access your portfolio
|
||||
|
||||
## Contributing
|
||||
|
||||
Ghostfolio is **100% free** and **open source**. We encourage and support an active and healthy community that accepts contributions from the public - including you.
|
||||
|
@ -917,12 +917,8 @@ export class PortfolioCalculator {
|
||||
const investmentValues: { [date: string]: Big } = {};
|
||||
const maxInvestmentValues: { [date: string]: Big } = {};
|
||||
let lastAveragePrice = new Big(0);
|
||||
// let lastTransactionInvestment = new Big(0);
|
||||
// let lastValueOfInvestmentBeforeTransaction = new Big(0);
|
||||
let maxTotalInvestment = new Big(0);
|
||||
const netPerformanceValues: { [date: string]: Big } = {};
|
||||
// let timeWeightedGrossPerformancePercentage = new Big(1);
|
||||
// let timeWeightedNetPerformancePercentage = new Big(1);
|
||||
let totalInvestment = new Big(0);
|
||||
let totalInvestmentWithGrossPerformanceFromSell = new Big(0);
|
||||
let totalUnits = new Big(0);
|
||||
@ -1128,55 +1124,8 @@ export class PortfolioCalculator {
|
||||
.minus(totalInvestment)
|
||||
.plus(grossPerformanceFromSells);
|
||||
|
||||
// if (
|
||||
// i > indexOfStartOrder &&
|
||||
// !lastValueOfInvestmentBeforeTransaction
|
||||
// .plus(lastTransactionInvestment)
|
||||
// .eq(0)
|
||||
// ) {
|
||||
// const grossHoldingPeriodReturn = valueOfInvestmentBeforeTransaction
|
||||
// .minus(
|
||||
// lastValueOfInvestmentBeforeTransaction.plus(
|
||||
// lastTransactionInvestment
|
||||
// )
|
||||
// )
|
||||
// .div(
|
||||
// lastValueOfInvestmentBeforeTransaction.plus(
|
||||
// lastTransactionInvestment
|
||||
// )
|
||||
// );
|
||||
|
||||
// timeWeightedGrossPerformancePercentage =
|
||||
// timeWeightedGrossPerformancePercentage.mul(
|
||||
// new Big(1).plus(grossHoldingPeriodReturn)
|
||||
// );
|
||||
|
||||
// const netHoldingPeriodReturn = valueOfInvestmentBeforeTransaction
|
||||
// .minus(fees.minus(feesAtStartDate))
|
||||
// .minus(
|
||||
// lastValueOfInvestmentBeforeTransaction.plus(
|
||||
// lastTransactionInvestment
|
||||
// )
|
||||
// )
|
||||
// .div(
|
||||
// lastValueOfInvestmentBeforeTransaction.plus(
|
||||
// lastTransactionInvestment
|
||||
// )
|
||||
// );
|
||||
|
||||
// timeWeightedNetPerformancePercentage =
|
||||
// timeWeightedNetPerformancePercentage.mul(
|
||||
// new Big(1).plus(netHoldingPeriodReturn)
|
||||
// );
|
||||
// }
|
||||
|
||||
grossPerformance = newGrossPerformance;
|
||||
|
||||
// lastTransactionInvestment = transactionInvestment;
|
||||
|
||||
// lastValueOfInvestmentBeforeTransaction =
|
||||
// valueOfInvestmentBeforeTransaction;
|
||||
|
||||
if (order.itemType === 'start') {
|
||||
feesAtStartDate = fees;
|
||||
grossPerformanceAtStartDate = grossPerformance;
|
||||
@ -1204,12 +1153,6 @@ export class PortfolioCalculator {
|
||||
}
|
||||
}
|
||||
|
||||
// timeWeightedGrossPerformancePercentage =
|
||||
// timeWeightedGrossPerformancePercentage.minus(1);
|
||||
|
||||
// timeWeightedNetPerformancePercentage =
|
||||
// timeWeightedNetPerformancePercentage.minus(1);
|
||||
|
||||
const totalGrossPerformance = grossPerformance.minus(
|
||||
grossPerformanceAtStartDate
|
||||
);
|
||||
|
30
apps/client/ngsw-config.json
Normal file
30
apps/client/ngsw-config.json
Normal file
@ -0,0 +1,30 @@
|
||||
{
|
||||
"$schema": "../../node_modules/@angular/service-worker/config/schema.json",
|
||||
"index": "/index.html",
|
||||
"assetGroups": [
|
||||
{
|
||||
"name": "app",
|
||||
"installMode": "prefetch",
|
||||
"resources": {
|
||||
"files": [
|
||||
"/favicon.ico",
|
||||
"/index.html",
|
||||
"/assets/site.webmanifest",
|
||||
"/*.css",
|
||||
"/*.js"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "assets",
|
||||
"installMode": "lazy",
|
||||
"updateMode": "prefetch",
|
||||
"resources": {
|
||||
"files": [
|
||||
"/assets/**",
|
||||
"/*.(svg|cur|jpg|jpeg|png|apng|webp|avif|gif|otf|ttf|woff|woff2)"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
{
|
||||
"name": "client",
|
||||
"$schema": "../../node_modules/nx/schemas/project-schema.json",
|
||||
"projectType": "application",
|
||||
"generators": {
|
||||
@ -43,6 +44,11 @@
|
||||
"input": "apps/client/src/assets",
|
||||
"output": "./../"
|
||||
},
|
||||
{
|
||||
"glob": "site.webmanifest",
|
||||
"input": "apps/client/src/assets",
|
||||
"output": "./../"
|
||||
},
|
||||
{
|
||||
"glob": "**/*",
|
||||
"input": "node_modules/ionicons/dist/ionicons",
|
||||
@ -66,7 +72,9 @@
|
||||
"buildOptimizer": false,
|
||||
"sourceMap": true,
|
||||
"optimization": false,
|
||||
"namedChunks": true
|
||||
"namedChunks": true,
|
||||
"serviceWorker": true,
|
||||
"ngswConfigPath": "apps/client/ngsw-config.json"
|
||||
},
|
||||
"configurations": {
|
||||
"development-de": {
|
||||
|
@ -26,6 +26,7 @@ import { GfHeaderModule } from './components/header/header.module';
|
||||
import { authInterceptorProviders } from './core/auth.interceptor';
|
||||
import { httpResponseInterceptorProviders } from './core/http-response.interceptor';
|
||||
import { LanguageService } from './core/language.service';
|
||||
import { ServiceWorkerModule } from '@angular/service-worker';
|
||||
|
||||
export function NgxStripeFactory(): string {
|
||||
return environment.stripePublicKey;
|
||||
@ -50,7 +51,11 @@ export function NgxStripeFactory(): string {
|
||||
MatNativeDateModule,
|
||||
MatSnackBarModule,
|
||||
NgxSkeletonLoaderModule,
|
||||
NgxStripeModule.forRoot(environment.stripePublicKey)
|
||||
NgxStripeModule.forRoot(environment.stripePublicKey),
|
||||
ServiceWorkerModule.register('ngsw-worker.js', {
|
||||
enabled: environment.production,
|
||||
registrationStrategy: 'registerImmediately'
|
||||
})
|
||||
],
|
||||
providers: [
|
||||
authInterceptorProviders,
|
||||
|
@ -12,7 +12,8 @@
|
||||
</p>
|
||||
<p *ngIf="user?.subscription?.type === 'Basic'">
|
||||
If you plan to open an account at <i>DEGIRO</i>, <i>frankly</i>,
|
||||
<i>Interactive Brokers</i>, <i>Swissquote</i>, or <i>VIAC</i>, please
|
||||
<i>Interactive Brokers</i>, <i>Swissquote</i>, <i>VIAC</i>, or
|
||||
<i>Zak</i>, please
|
||||
<a href="mailto:hi@ghostfol.io?Subject=Referral link for..."
|
||||
>contact us</a
|
||||
>
|
||||
@ -26,7 +27,7 @@
|
||||
</p>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xs-12 col-md-4 mb-3">
|
||||
<div class="col-xs-12 col-lg-4 mb-3">
|
||||
<mat-card class="d-flex flex-column h-100">
|
||||
<div class="flex-grow-1">
|
||||
<h4>Open Source</h4>
|
||||
@ -72,11 +73,20 @@
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<p>Self-hosted.</p>
|
||||
<p>Self-hosted, update manually.</p>
|
||||
<p class="h5 text-right">Free</p>
|
||||
<div
|
||||
*ngIf="user?.subscription?.type === 'Basic'"
|
||||
class="d-none d-lg-block hidden mt-3 text-center"
|
||||
>
|
||||
<a color="primary" mat-flat-button> </a>
|
||||
<p class="m-0 text-muted">
|
||||
<small> </small>
|
||||
</p>
|
||||
</div>
|
||||
</mat-card>
|
||||
</div>
|
||||
<div class="col-xs-12 col-md-4 mb-3">
|
||||
<div class="col-xs-12 col-lg-4 mb-3">
|
||||
<mat-card
|
||||
class="d-flex flex-column h-100"
|
||||
[ngClass]="{ 'active': user?.subscription?.type === 'Basic' }"
|
||||
@ -124,9 +134,18 @@
|
||||
</div>
|
||||
<p>Fully managed <strong>Ghostfolio</strong> cloud offering.</p>
|
||||
<p class="h5 text-right">Free</p>
|
||||
<div
|
||||
*ngIf="user?.subscription?.type === 'Basic'"
|
||||
class="d-none d-lg-block hidden mt-3 text-center"
|
||||
>
|
||||
<a color="primary" mat-flat-button> </a>
|
||||
<p class="m-0 text-muted">
|
||||
<small> </small>
|
||||
</p>
|
||||
</div>
|
||||
</mat-card>
|
||||
</div>
|
||||
<div class="col-xs-12 col-md-4 mb-3">
|
||||
<div class="col-xs-12 col-lg-4 mb-3">
|
||||
<mat-card
|
||||
class="d-flex flex-column h-100"
|
||||
[ngClass]="{ 'active': user?.subscription?.type === 'Premium' }"
|
||||
@ -198,24 +217,28 @@
|
||||
> <span>per year</span></span
|
||||
>
|
||||
</p>
|
||||
<div
|
||||
*ngIf="user?.subscription?.type === 'Basic'"
|
||||
class="mt-3 text-center"
|
||||
>
|
||||
<a color="primary" mat-flat-button [routerLink]="['/account']">
|
||||
Upgrade Plan
|
||||
</a>
|
||||
<p class="m-0 text-muted">
|
||||
<small>One-time payment, no auto-renewal.</small>
|
||||
</p>
|
||||
</div>
|
||||
</mat-card>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="user?.subscription?.type === 'Basic'" class="row">
|
||||
<div class="col mt-3 text-center">
|
||||
<a color="primary" mat-flat-button [routerLink]="['/account']">
|
||||
Upgrade Plan
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="!user" class="row">
|
||||
<div class="col mt-3 text-center">
|
||||
<a color="primary" mat-flat-button [routerLink]="['/register']">
|
||||
Get Started
|
||||
</a>
|
||||
<p class="text-muted"><small>It's free</small></p>
|
||||
<p class="m-0 text-muted"><small>It’s free.</small></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -12,6 +12,7 @@
|
||||
}
|
||||
|
||||
.mat-card {
|
||||
&:hover,
|
||||
&.active {
|
||||
border-color: rgba(var(--palette-primary-500), 1);
|
||||
box-shadow: 0 0 0 1px rgba(var(--palette-primary-500), 1);
|
||||
|
@ -1,24 +1,25 @@
|
||||
{
|
||||
"background_color": "transparent",
|
||||
"background_color": "#FFFFFF",
|
||||
"categories": ["finance", "utilities"],
|
||||
"description": "Open Source Wealth Management Software",
|
||||
"display": "standalone",
|
||||
"icons": [
|
||||
{
|
||||
"sizes": "192x192",
|
||||
"src": "/en/assets/android-chrome-192x192.png",
|
||||
"type": "image/png"
|
||||
"src": "/assets/android-chrome-192x192.png",
|
||||
"type": "image/png",
|
||||
"purpose": "any maskable"
|
||||
},
|
||||
{
|
||||
"sizes": "512x512",
|
||||
"src": "/en/assets/android-chrome-512x512.png",
|
||||
"src": "/assets/android-chrome-512x512.png",
|
||||
"type": "image/png"
|
||||
}
|
||||
],
|
||||
"name": "Ghostfolio",
|
||||
"orientation": "portrait",
|
||||
"short_name": "Ghostfolio",
|
||||
"start_url": "https://www.ghostfol.io",
|
||||
"start_url": "/en/",
|
||||
"theme_color": "#FFFFFF",
|
||||
"url": "https://www.ghostfol.io"
|
||||
}
|
||||
|
@ -28,6 +28,7 @@
|
||||
content="initial-scale=1, viewport-fit=cover, width=device-width"
|
||||
name="viewport"
|
||||
/>
|
||||
<meta content="#FFFFFF" name="theme-color" />
|
||||
<meta content="" property="og:description" />
|
||||
<meta
|
||||
content="Ghostfolio – Open Source Wealth Management Software"
|
||||
|
@ -25,7 +25,6 @@ $mat-css-light-theme-selector: '.is-light-theme';
|
||||
body {
|
||||
font-family: var(--font-family-sans-serif);
|
||||
margin: 0;
|
||||
margin-bottom: 5rem;
|
||||
min-height: 100%;
|
||||
|
||||
a {
|
||||
@ -166,6 +165,10 @@ ngx-skeleton-loader {
|
||||
@include gf-table;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.lead {
|
||||
font-weight: unset;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ghostfolio",
|
||||
"version": "1.210.0",
|
||||
"version": "1.211.0",
|
||||
"homepage": "https://ghostfol.io",
|
||||
"license": "AGPL-3.0",
|
||||
"scripts": {
|
||||
@ -63,6 +63,7 @@
|
||||
"@angular/platform-browser": "14.2.0",
|
||||
"@angular/platform-browser-dynamic": "14.2.0",
|
||||
"@angular/router": "14.2.0",
|
||||
"@angular/service-worker": "14.2.0",
|
||||
"@codewithdan/observable-store": "2.2.11",
|
||||
"@dfinity/agent": "0.12.1",
|
||||
"@dfinity/auth-client": "0.12.1",
|
||||
@ -138,6 +139,7 @@
|
||||
"@angular/compiler-cli": "14.2.0",
|
||||
"@angular/language-service": "14.2.0",
|
||||
"@angular/localize": "14.2.0",
|
||||
"@angular/pwa": "14.2.9",
|
||||
"@nestjs/schematics": "9.0.3",
|
||||
"@nestjs/testing": "9.1.4",
|
||||
"@nrwl/cli": "15.0.0",
|
||||
|
Reference in New Issue
Block a user