Compare commits
12 Commits
Author | SHA1 | Date | |
---|---|---|---|
1824413379 | |||
3332ade3d3 | |||
8d2e110e3d | |||
a8fcf09380 | |||
1071f446a8 | |||
03b050d1ac | |||
58eeff7001 | |||
76fb8825e4 | |||
0f9d142afe | |||
bd33855a27 | |||
5329e45e2c | |||
e990ecd12c |
1
.env
1
.env
@ -14,4 +14,3 @@ ACCESS_TOKEN_SALT=<INSERT_RANDOM_STRING>
|
||||
ALPHA_VANTAGE_API_KEY=
|
||||
DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@localhost:5432/${POSTGRES_DB}?sslmode=prefer
|
||||
JWT_SECRET_KEY=<INSERT_RANDOM_STRING>
|
||||
PORT=3333
|
||||
|
26
CHANGELOG.md
26
CHANGELOG.md
@ -5,12 +5,36 @@ 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.159.0 - 15.06.2022
|
||||
|
||||
### Changed
|
||||
|
||||
- Changed the default `HOST` to `0.0.0.0`
|
||||
- Refactored the endpoint of the public page (filter by equity)
|
||||
|
||||
## 1.158.1 - 12.06.2022
|
||||
|
||||
### Added
|
||||
|
||||
- Extended the queue jobs view in the admin control panel by a data dialog
|
||||
|
||||
### Changed
|
||||
|
||||
- Exposed the environment variable `HOST`
|
||||
- Decreased the number of attempts of queue jobs from `20` to `10` (fail earlier)
|
||||
- Improved the message for data provider errors in the client
|
||||
- Changed the label from _Balance_ to _Cash Balance_ in the account dialog
|
||||
- Restructured the documentation for self-hosting
|
||||
|
||||
## 1.157.0 - 11.06.2022
|
||||
|
||||
### Added
|
||||
|
||||
- Extended the queue jobs view in the admin control panel by the number of attempts and the status
|
||||
|
||||
### Changed
|
||||
|
||||
- Migrated the historical market data gathering to the queue design pattern
|
||||
- Extended the queue jobs view in the admin control panel by the number of attempts and the status
|
||||
- Refreshed the cryptocurrencies list to support more coins by default
|
||||
- Increased the historical data chart of the _Fear & Greed Index_ (market mood) to 180 days
|
||||
- Upgraded `chart.js` from version `3.7.0` to `3.8.0`
|
||||
|
27
README.md
27
README.md
@ -35,7 +35,7 @@
|
||||
|
||||
Our official **[Ghostfolio Premium](https://ghostfol.io/pricing)** cloud offering is the easiest way to get started. Due to the time it saves, this will be the best option for most people. The revenue is used for covering the hosting costs.
|
||||
|
||||
If you prefer to run Ghostfolio on your own infrastructure (self-hosting), please find further instructions in the section [Run with Docker](#run-with-docker-self-hosting).
|
||||
If you prefer to run Ghostfolio on your own infrastructure, please find further instructions in the [Self-hosting](#self-hosting) section.
|
||||
|
||||
## Why Ghostfolio?
|
||||
|
||||
@ -79,14 +79,17 @@ The backend is based on [NestJS](https://nestjs.com) using [PostgreSQL](https://
|
||||
|
||||
The frontend is built with [Angular](https://angular.io) and uses [Angular Material](https://material.angular.io) with utility classes from [Bootstrap](https://getbootstrap.com).
|
||||
|
||||
## Run with Docker (self-hosting)
|
||||
## Self-hosting
|
||||
|
||||
### Prerequisites
|
||||
### Run with Docker Compose
|
||||
|
||||
- [Docker](https://www.docker.com/products/docker-desktop)
|
||||
- A local copy of this Git repository (clone)
|
||||
#### Prerequisites
|
||||
|
||||
### a. Run environment
|
||||
- Basic knowledge of Docker
|
||||
- Installation of [Docker](https://www.docker.com/products/docker-desktop)
|
||||
- Local copy of this Git repository (clone)
|
||||
|
||||
#### a. Run environment
|
||||
|
||||
Run the following command to start the Docker images from [Docker Hub](https://hub.docker.com/r/ghostfolio/ghostfolio):
|
||||
|
||||
@ -94,7 +97,7 @@ Run the following command to start the Docker images from [Docker Hub](https://h
|
||||
docker-compose --env-file ./.env -f docker/docker-compose.yml up -d
|
||||
```
|
||||
|
||||
#### Setup Database
|
||||
##### Setup Database
|
||||
|
||||
Run the following command to setup the database once Ghostfolio is running:
|
||||
|
||||
@ -102,7 +105,7 @@ Run the following command to setup the database once Ghostfolio is running:
|
||||
docker-compose --env-file ./.env -f docker/docker-compose.yml exec ghostfolio yarn database:setup
|
||||
```
|
||||
|
||||
### b. Build and run environment
|
||||
#### b. Build and run environment
|
||||
|
||||
Run the following commands to build and start the Docker images:
|
||||
|
||||
@ -111,7 +114,7 @@ docker-compose --env-file ./.env -f docker/docker-compose.build.yml build
|
||||
docker-compose --env-file ./.env -f docker/docker-compose.build.yml up -d
|
||||
```
|
||||
|
||||
#### Setup Database
|
||||
##### Setup Database
|
||||
|
||||
Run the following command to setup the database once Ghostfolio is running:
|
||||
|
||||
@ -119,7 +122,7 @@ Run the following command to setup the database once Ghostfolio is running:
|
||||
docker-compose --env-file ./.env -f docker/docker-compose.build.yml exec ghostfolio yarn database:setup
|
||||
```
|
||||
|
||||
### Fetch Historical Data
|
||||
#### Fetch Historical Data
|
||||
|
||||
Open http://localhost:3333 in your browser and accomplish these steps:
|
||||
|
||||
@ -127,13 +130,13 @@ Open http://localhost:3333 in your browser and accomplish these steps:
|
||||
1. Go to the _Admin Control Panel_ and click _Gather All Data_ to fetch historical data
|
||||
1. Click _Sign out_ and check out the _Live Demo_
|
||||
|
||||
### Upgrade Version
|
||||
#### Upgrade Version
|
||||
|
||||
1. Increase the version of the `ghostfolio/ghostfolio` Docker image in `docker/docker-compose.yml`
|
||||
1. Run the following command to start the new Docker image: `docker-compose --env-file ./.env -f docker/docker-compose.yml up -d`
|
||||
1. Then, run the following command to keep your database schema in sync: `docker-compose --env-file ./.env -f docker/docker-compose.yml exec ghostfolio yarn database:migrate`
|
||||
|
||||
## Run with _Unraid_ (self-hosting)
|
||||
### Run with _Unraid_ (unofficial)
|
||||
|
||||
Please follow the instructions of the Ghostfolio [Unraid Community App](https://unraid.net/community/apps?q=ghostfolio).
|
||||
|
||||
|
@ -316,7 +316,9 @@ export class PortfolioController {
|
||||
|
||||
const { holdings } = await this.portfolioService.getDetails(
|
||||
access.userId,
|
||||
access.userId
|
||||
access.userId,
|
||||
'1d',
|
||||
[{ id: 'EQUITY', type: 'ASSET_CLASS' }]
|
||||
);
|
||||
|
||||
const portfolioPublicDetails: PortfolioPublicDetails = {
|
||||
@ -325,9 +327,6 @@ export class PortfolioController {
|
||||
};
|
||||
|
||||
const totalValue = Object.values(holdings)
|
||||
.filter((holding) => {
|
||||
return holding.assetClass === 'EQUITY';
|
||||
})
|
||||
.map((portfolioPosition) => {
|
||||
return this.exchangeRateDataService.toCurrency(
|
||||
portfolioPosition.quantity * portfolioPosition.marketPrice,
|
||||
@ -338,17 +337,15 @@ export class PortfolioController {
|
||||
.reduce((a, b) => a + b, 0);
|
||||
|
||||
for (const [symbol, portfolioPosition] of Object.entries(holdings)) {
|
||||
if (portfolioPosition.assetClass === 'EQUITY') {
|
||||
portfolioPublicDetails.holdings[symbol] = {
|
||||
allocationCurrent: portfolioPosition.allocationCurrent,
|
||||
countries: hasDetails ? portfolioPosition.countries : [],
|
||||
currency: portfolioPosition.currency,
|
||||
markets: portfolioPosition.markets,
|
||||
name: portfolioPosition.name,
|
||||
sectors: hasDetails ? portfolioPosition.sectors : [],
|
||||
value: portfolioPosition.value / totalValue
|
||||
};
|
||||
}
|
||||
portfolioPublicDetails.holdings[symbol] = {
|
||||
allocationCurrent: portfolioPosition.allocationCurrent,
|
||||
countries: hasDetails ? portfolioPosition.countries : [],
|
||||
currency: portfolioPosition.currency,
|
||||
markets: portfolioPosition.markets,
|
||||
name: portfolioPosition.name,
|
||||
sectors: hasDetails ? portfolioPosition.sectors : [],
|
||||
value: portfolioPosition.value / totalValue
|
||||
};
|
||||
}
|
||||
|
||||
return portfolioPublicDetails;
|
||||
|
@ -20,10 +20,11 @@ async function bootstrap() {
|
||||
})
|
||||
);
|
||||
|
||||
const host = process.env.HOST || '0.0.0.0';
|
||||
const port = process.env.PORT || 3333;
|
||||
await app.listen(port, () => {
|
||||
await app.listen(port, host, () => {
|
||||
logLogo();
|
||||
Logger.log(`Listening at http://localhost:${port}`);
|
||||
Logger.log(`Listening at http://${host}:${port}`);
|
||||
Logger.log('');
|
||||
});
|
||||
}
|
||||
|
@ -31,12 +31,13 @@ export class ConfigurationService {
|
||||
GOOGLE_SHEETS_ACCOUNT: str({ default: '' }),
|
||||
GOOGLE_SHEETS_ID: str({ default: '' }),
|
||||
GOOGLE_SHEETS_PRIVATE_KEY: str({ default: '' }),
|
||||
HOST: host({ default: '0.0.0.0' }),
|
||||
JWT_SECRET_KEY: str({}),
|
||||
MAX_ITEM_IN_CACHE: num({ default: 9999 }),
|
||||
MAX_ORDERS_TO_IMPORT: num({ default: Number.MAX_SAFE_INTEGER }),
|
||||
PORT: port({ default: 3333 }),
|
||||
RAKUTEN_RAPID_API_KEY: str({ default: '' }),
|
||||
REDIS_HOST: str({ default: 'localhost' }),
|
||||
REDIS_HOST: host({ default: 'localhost' }),
|
||||
REDIS_PASSWORD: str({ default: '' }),
|
||||
REDIS_PORT: port({ default: 6379 }),
|
||||
ROOT_URL: str({ default: 'http://localhost:4200' }),
|
||||
|
@ -90,6 +90,10 @@ export class AdminJobsComponent implements OnDestroy, OnInit {
|
||||
});
|
||||
}
|
||||
|
||||
public onViewData(aData: AdminJobs['jobs'][0]['data']) {
|
||||
alert(JSON.stringify(aData, null, ' '));
|
||||
}
|
||||
|
||||
public onViewStacktrace(aStacktrace: AdminJobs['jobs'][0]['stacktrace']) {
|
||||
alert(JSON.stringify(aStacktrace, null, ' '));
|
||||
}
|
||||
|
@ -105,6 +105,9 @@
|
||||
<ion-icon name="ellipsis-vertical"></ion-icon>
|
||||
</button>
|
||||
<mat-menu #accountMenu="matMenu" xPosition="before">
|
||||
<button i18n mat-menu-item (click)="onViewData(job.data)">
|
||||
View Data
|
||||
</button>
|
||||
<button
|
||||
i18n
|
||||
mat-menu-item
|
||||
|
@ -81,9 +81,11 @@ export class PortfolioPerformanceComponent implements OnChanges, OnInit {
|
||||
}
|
||||
|
||||
public onShowErrors() {
|
||||
const errorMessageParts = this.errors.map((error) => {
|
||||
return `${error.symbol} (${error.dataSource})`;
|
||||
});
|
||||
const errorMessageParts = ['Data Provider Errors for'];
|
||||
|
||||
for (const error of this.errors) {
|
||||
errorMessageParts.push(`${error.symbol} (${error.dataSource})`);
|
||||
}
|
||||
|
||||
alert(errorMessageParts.join('\n'));
|
||||
}
|
||||
|
@ -29,7 +29,7 @@
|
||||
</div>
|
||||
<div>
|
||||
<mat-form-field appearance="outline" class="w-100">
|
||||
<mat-label i18n>Balance</mat-label>
|
||||
<mat-label i18n>Cash Balance</mat-label>
|
||||
<input
|
||||
matInput
|
||||
name="balance"
|
||||
|
@ -52,7 +52,7 @@ export const DEFAULT_DATE_FORMAT_MONTH_YEAR = 'MMM yyyy';
|
||||
|
||||
export const GATHER_ASSET_PROFILE_PROCESS = 'GATHER_ASSET_PROFILE';
|
||||
export const GATHER_ASSET_PROFILE_PROCESS_OPTIONS: JobOptions = {
|
||||
attempts: 20,
|
||||
attempts: 10,
|
||||
backoff: {
|
||||
delay: ms('1 minute'),
|
||||
type: 'exponential'
|
||||
@ -65,7 +65,7 @@ export const GATHER_ASSET_PROFILE_PROCESS_OPTIONS: JobOptions = {
|
||||
export const GATHER_HISTORICAL_MARKET_DATA_PROCESS =
|
||||
'GATHER_HISTORICAL_MARKET_DATA';
|
||||
export const GATHER_HISTORICAL_MARKET_DATA_PROCESS_OPTIONS: JobOptions = {
|
||||
attempts: 20,
|
||||
attempts: 10,
|
||||
backoff: {
|
||||
delay: ms('1 minute'),
|
||||
type: 'exponential'
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ghostfolio",
|
||||
"version": "1.157.0",
|
||||
"version": "1.159.0",
|
||||
"homepage": "https://ghostfol.io",
|
||||
"license": "AGPL-3.0",
|
||||
"scripts": {
|
||||
|
Reference in New Issue
Block a user