Compare commits

..

52 Commits

Author SHA1 Message Date
a2277dea2c Release 2.69.0 (#3212) 2024-03-30 13:43:43 +01:00
debd233c32 Feature/set up Tini to avoid zombie processes (#3195)
* Set up Tini to avoid zombie processes

* Update changelog
2024-03-30 13:42:02 +01:00
f1eeee0525 Feature/extend date range support by specific years (#3190)
* Extend date range support by specific years

* Support date range in benchmark endpoint

* Support date range in activities endpoint

* Update changelog
2024-03-30 13:06:42 +01:00
5ffc39c32f Feature/improve usability to delete asset profile (#3208)
* Disable delete button for benchmarks

* Update changelog
2024-03-30 11:23:59 +01:00
a668a66e84 Feature/add missing dates to edit historical market data in asset profile details dialog (#3206)
* Add missing dates to edit historical market data in asset profile details dialog

* Update changelog
2024-03-30 08:50:06 +01:00
0581b8b9ec Release 2.68.0 (#3205) 2024-03-29 17:54:17 +01:00
63a61fb492 Move portfolio calculator (#3204)
* Move portfolio calculator
2024-03-29 17:47:44 +01:00
5788c6474e Refactor portfolio calculator (#3203)
* Refactor portfolio calculator

* Consume Activity[]
* Change computeTransactionPoints() to private
* Eliminate getTransactionPoints()

* Update changelog
2024-03-29 17:34:22 +01:00
5529fdc0ee Move transaction points to constructor (#3202) 2024-03-29 13:50:24 +01:00
88a9b518f6 Bugfix/fix issue with overridden names in activities table (#3200)
* Fix issue with overridden names

* Update changelog
2024-03-29 09:50:04 +01:00
98de2355c4 Feature/Support overriding name of asset profile dialog (#3199)
* Support overriding name of asset profile dialog

* Update changelog
2024-03-29 09:35:41 +01:00
b41eb60348 Fix chart tooltip of benchmark comparator (#3167)
* Fix chart tooltip of benchmark comparator

* Update changelog
2024-03-28 18:23:56 +01:00
0edebe30e1 Feature/Add user account currency to export (#3194)
* Add user account currency to export

* Update changelog
2024-03-27 18:08:34 +01:00
e3abe4feee Release 2.67.0 (#3197) 2024-03-26 17:45:32 +01:00
50391e199a Feature/improve generation of random strings (#3196)
* Replace Math.random() with crypto.randomBytes()

* Update changelog
2024-03-26 17:43:42 +01:00
a33f8d5bed Upgrade @types/big.js to version 6.2.2 (#3191)
* Upgrade @types/big.js to version 6.2.2

* Refactor imports
2024-03-25 08:34:30 +01:00
636be8441e Feature/upgrade zone.js to version 0.14.4 (#3184)
* Upgrade zone.js to version 0.14.4

* Update changelog
2024-03-24 10:30:06 +01:00
654dc2ba32 Feature/upgrade yahoo finance2 to version 2.11.0 (#3183)
* Upgrade yahoo-finance2 to version 2.11.0

* Update changelog
2024-03-24 09:50:45 +01:00
458ef169f4 Feature/add support for toncoin cryptocurrency (#3189)
* Add Toincoin

* Update changelog
2024-03-24 09:50:00 +01:00
5bb01bb03c Feature/upgrade ionicons to version 7.3.0 (#3182)
* Upgrade ionicons to version 7.3.0

* Update changelog
2024-03-24 09:09:09 +01:00
43e9528d8c Release 2.66.3 (#3188) 2024-03-23 20:56:22 +01:00
522c54c9b4 Release 2.66.2 (#3187) 2024-03-23 20:40:09 +01:00
0004ced4e1 Release 2.66.1 (#3186) 2024-03-23 20:26:10 +01:00
274c60e961 Release 2.66.0 (#3185) 2024-03-23 19:55:17 +01:00
754e98099c Feature/Set up tini (#3168)
* Set up tini to avoid zombie processes and perform signal forwarding in docker image

* Update changelog
2024-03-23 19:53:27 +01:00
87bf8df1c3 Bugfix/missing performance chart in presenter view (#3181)
* Fix missing performance chart in presenter view

* Update changelog
2024-03-23 19:41:28 +01:00
3f7d6b25c7 Feature/extend faq by backup strategy (#3180)
* Add backup strategy

* Update changelog
2024-03-23 19:10:23 +01:00
8a062e03ab Feature/add benchmark name to tooltip of benchmark comparator (#3177)
* Add benchmark name to chart tooltip

* Update changelog
2024-03-23 09:38:35 +01:00
a70f45cbf3 Feature/add index for data source symbol to market data table (#3179)
* Add index

* Update changelog
2024-03-23 09:23:59 +01:00
f268264c46 Feature/upgrade nx to version 18.1.2 (#3174)
* Upgrade angular and Nx dependencies

* Update changelog
2024-03-23 09:09:10 +01:00
bbe5d70720 Rename Twitter to X (#3009) 2024-03-21 15:10:35 +01:00
f1d2a52cba Release 2.65.0 (#3170) 2024-03-19 20:13:22 +01:00
87cc887865 Feature/Set meta theme color dynamically to respect appearance (#3129)
* Set meta theme color dynamically to respect appearance (dark mode)

* Update changelog
2024-03-19 20:11:34 +01:00
61ecd15f1d Feature/change edit button to a in admin market data page (#3164)
* Change edit button to a

* Update changelog
2024-03-19 19:55:08 +01:00
eb853f05ae Feature/add support to delete asset profile from dialog (#3165)
* Add support to delete asset profile from dialog

* Update changelog
2024-03-19 19:27:16 +01:00
6285417903 Feature/change grant private access with permissions to general availability (#3169)
* Change grant private access with permissions from experimental to general availability

* Update changelog
2024-03-19 19:25:43 +01:00
ca674a654e Feature/add symbol and isin to position detail dialog (#3163)
* Add symbol and ISIN

* Update translations

* Update changelog
2024-03-18 13:58:46 +01:00
2729c5651f Release 2.64.0 (#3161) 2024-03-16 19:00:50 +01:00
7e28e42995 Feature/exclude fees from holdings (#3160) 2024-03-16 18:59:23 +01:00
e21563d903 Feature/increase timeout to load benchmarks (#3158)
* Increase request timeout

* Update changelog
2024-03-16 18:15:34 +01:00
3ede69650c Feature/upgrade prisma to version 5.11.0 (#3159)
* Upgrade prisma to version 5.11.0

* Update changelog
2024-03-16 16:51:07 +01:00
c289793c6d Feature/switch between active and closed holdings (#3146)
* Switch between active and closed holdings on the portfolio holdings page

* Update changelog

---------

Co-authored-by: Thomas Kaul <4159106+dtslvr@users.noreply.github.com>
2024-03-16 14:20:58 +01:00
a90c067da0 Clean up (#3157) 2024-03-16 13:40:23 +01:00
38c2baf943 Feature/improve exception handling of current investments in various rules (#3156)
* Improve exception handling

* Update changelog
2024-03-16 12:29:21 +01:00
82c78cad6b Format (#3155) 2024-03-16 12:28:58 +01:00
bffe6060bd Pass portfolio calculator to getChart() (#3153) 2024-03-16 10:05:16 +01:00
841bd5c33f Bugfix/fix dividend accumulation in symbol metrics (#3152)
* Fix total dividend calculation

* Update changelog
2024-03-16 10:04:57 +01:00
3b895afc9e Enable account balance update for fee and interest activities (#3145)
* Enable account balance update for fee and interest activities

* Update changelog
2024-03-15 18:56:17 +01:00
00c2ede85e Feature/improve usability of platform and tag management (#3144)
* Improve usability

* Update changelog
2024-03-15 08:37:41 +01:00
8420cb830c Feature/add product roadmap to faq (#3143)
* Add product roadmap

* Update changelog
2024-03-14 14:09:20 +01:00
a0ddd1f9b9 Fix date conversion in import of historical market data (#3117)
* Fix date conversion in import of historical market data

* Update changelog
2024-03-13 20:44:33 +01:00
40d93066ff Introduce .env.dev (#3120) 2024-03-13 20:21:54 +01:00
120 changed files with 3412 additions and 2377 deletions

25
.env.dev Normal file
View File

@ -0,0 +1,25 @@
COMPOSE_PROJECT_NAME=ghostfolio-development
# CACHE
REDIS_HOST=localhost
REDIS_PORT=6379
REDIS_PASSWORD=<INSERT_REDIS_PASSWORD>
# POSTGRES
POSTGRES_DB=ghostfolio-db
POSTGRES_USER=user
POSTGRES_PASSWORD=<INSERT_POSTGRES_PASSWORD>
# VARIOUS
ACCESS_TOKEN_SALT=<INSERT_RANDOM_STRING>
DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@localhost:5432/${POSTGRES_DB}?connect_timeout=300&sslmode=prefer
JWT_SECRET_KEY=<INSERT_RANDOM_STRING>
# DEVELOPMENT
# Nx 18 enables using plugins to infer targets by default
# This is disabled for existing workspaces to maintain compatibility
# For more info, see: https://nx.dev/concepts/inferred-tasks
NX_ADD_PLUGINS=false
NX_NATIVE_COMMAND_RUNNER=false

View File

@ -1,4 +1,4 @@
COMPOSE_PROJECT_NAME=ghostfolio-development
COMPOSE_PROJECT_NAME=ghostfolio
# CACHE
REDIS_HOST=localhost
@ -10,6 +10,7 @@ POSTGRES_DB=ghostfolio-db
POSTGRES_USER=user
POSTGRES_PASSWORD=<INSERT_POSTGRES_PASSWORD>
# VARIOUS
ACCESS_TOKEN_SALT=<INSERT_RANDOM_STRING>
DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@localhost:5432/${POSTGRES_DB}?connect_timeout=300&sslmode=prefer
JWT_SECRET_KEY=<INSERT_RANDOM_STRING>

View File

@ -5,6 +5,103 @@ 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).
## 2.69.0 - 2024-03-30
### Added
- Added the date range support in the activities table on the portfolio activities page (experimental)
- Extended the date range support by specific years (`2023`, `2022`, `2021`, etc.) in the assistant (experimental)
- Set up `Tini` to avoid zombie processes and perform signal forwarding in docker image
### Changed
- Improved the usability to delete an asset profile in the historical market data table and the asset profile details dialog of the admin control
### Fixed
- Added missing dates to edit historical market data in the asset profile details dialog of the admin control panel
## 2.68.0 - 2024-03-29
### Added
- Extended the export functionality by the user accounts currency
- Added support to override the name of an asset profile in the asset profile details dialog of the admin control
### Changed
- Optimized the portfolio calculations
### Fixed
- Fixed the chart tooltip of the benchmark comparator
- Fixed an issue with names in the activities table on the portfolio activities page while using symbol profile overrides
## 2.67.0 - 2024-03-26
### Added
- Added support for the cryptocurrency _Toncoin_ (`TON11419-USD`)
### Changed
- Replaced `Math.random()` with `crypto.randomBytes()` for generating cryptographically secure random strings
- Upgraded `ionicons` from version `7.1.0` to `7.3.0`
- Upgraded `yahoo-finance2` from version `2.10.0` to `2.11.0`
- Upgraded `zone.js` from version `0.14.3` to `0.14.4`
## 2.66.3 - 2024-03-23
### Added
- Extended the content of the _SaaS_ and _Self-Hosting_ sections by the backup strategy on the Frequently Asked Questions (FAQ) page
- Added an index for `dataSource` / `symbol` to the market data database table
### Changed
- Improved the chart tooltip of the benchmark comparator by adding the benchmark name
- Upgraded `angular` from version `17.1.3` to `17.2.4`
- Upgraded `Nx` from version `18.0.4` to `18.1.2`
### Fixed
- Fixed the missing portfolio performance chart in the _Presenter View_ / _Zen Mode_
## 2.65.0 - 2024-03-19
### Added
- Added the symbol and ISIN number to the position detail dialog
- Added support to delete an asset profile in the asset profile details dialog of the admin control
### Changed
- Moved the support to grant private access with permissions from experimental to general availability
- Set the meta theme color dynamically to respect the appearance (dark mode)
- Improved the usability to edit market data in the admin control panel
## 2.64.0 - 2024-03-16
### Added
- Added a toggle to switch between active and closed holdings on the portfolio holdings page
- Added support to update the cash balance of an account when adding a fee activity
- Added support to update the cash balance of an account when adding an interest activity
- Extended the content of the _General_ section by the product roadmap on the Frequently Asked Questions (FAQ) page
### Changed
- Improved the usability of the platform management in the admin control panel
- Improved the usability of the tag management in the admin control panel
- Improved the exception handling of various rules in the _X-ray_ section
- Increased the timeout to load benchmarks
- Upgraded `prisma` from version `5.10.2` to `5.11.0`
### Fixed
- Fixed an issue in the dividend calculation of the portfolio holdings
- Fixed the date conversion of the import of historical market data in the admin control panel
## 2.63.2 - 2024-03-12
### Added

View File

@ -56,7 +56,15 @@ RUN apt update && apt install -y \
openssl \
&& rm -rf /var/lib/apt/lists/*
# Add tini, which is an init process that handles signaling within the container
# and with the host. See https://github.com/krallin/tini
ENV TINI_VERSION v0.19.0
ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini /tini
RUN chmod +x /tini
ENTRYPOINT ["/tini", "--"]
COPY --from=builder /ghostfolio/dist/apps /ghostfolio/apps
COPY ./docker/entrypoint.sh /ghostfolio/entrypoint.sh
WORKDIR /ghostfolio/apps/api
EXPOSE ${PORT:-3333}
CMD [ "yarn", "start:production" ]
CMD [ "/ghostfolio/entrypoint.sh" ]

View File

@ -7,7 +7,7 @@
**Open Source Wealth Management Software**
[**Ghostfol.io**](https://ghostfol.io) | [**Live Demo**](https://ghostfol.io/en/demo) | [**Ghostfolio Premium**](https://ghostfol.io/en/pricing) | [**FAQ**](https://ghostfol.io/en/faq) |
[**Blog**](https://ghostfol.io/en/blog) | [**Slack**](https://join.slack.com/t/ghostfolio/shared_invite/zt-vsaan64h-F_I0fEo5M0P88lP9ibCxFg) | [**Twitter**](https://twitter.com/ghostfolio_)
[**Blog**](https://ghostfol.io/en/blog) | [**Slack**](https://join.slack.com/t/ghostfolio/shared_invite/zt-vsaan64h-F_I0fEo5M0P88lP9ibCxFg) | [**X**](https://twitter.com/ghostfolio_)
[![Shield: Buy me a coffee](https://img.shields.io/badge/Buy%20me%20a%20coffee-Support-yellow?logo=buymeacoffee)](https://www.buymeacoffee.com/ghostfolio)
[![Shield: Contributions Welcome](https://img.shields.io/badge/Contributions-Welcome-orange.svg)](#contributing)
@ -154,7 +154,7 @@ Ghostfolio is available for various home server systems, including [CasaOS](http
- [Node.js](https://nodejs.org/en/download) (version 18+)
- [Yarn](https://yarnpkg.com/en/docs/install)
- Create a local copy of this Git repository (clone)
- Copy the file `.env.example` to `.env` and populate it with your data (`cp .env.example .env`)
- Copy the file `.env.dev` to `.env` and populate it with your data (`cp .env.dev .env`)
### Setup

View File

@ -83,7 +83,7 @@ export class AccessController {
}
try {
return await this.accessService.createAccess({
return this.accessService.createAccess({
alias: data.alias || undefined,
GranteeUser: data.granteeUserId
? { connect: { id: data.granteeUserId } }

View File

@ -5,7 +5,7 @@ import { Filter } from '@ghostfolio/common/interfaces';
import { Injectable } from '@nestjs/common';
import { Account, Order, Platform, Prisma } from '@prisma/client';
import Big from 'big.js';
import { Big } from 'big.js';
import { groupBy } from 'lodash';
import { CashDetails } from './interfaces/cash-details.interface';

View File

@ -339,6 +339,6 @@ export class AdminController {
@Param('key') key: string,
@Body() data: PropertyDto
) {
return await this.adminService.putSetting(key, data.value);
return this.adminService.putSetting(key, data.value);
}
}

View File

@ -71,7 +71,7 @@ export class AdminService {
);
}
return await this.symbolProfileService.add(
return this.symbolProfileService.add(
assetProfiles[symbol] as Prisma.SymbolProfileCreateInput
);
} catch (error) {
@ -212,6 +212,7 @@ export class AdminService {
countries: true,
currency: true,
dataSource: true,
id: true,
name: true,
Order: {
orderBy: [{ date: 'asc' }],
@ -235,6 +236,7 @@ export class AdminService {
countries,
currency,
dataSource,
id,
name,
Order,
sectors,
@ -257,6 +259,7 @@ export class AdminService {
currency,
countriesCount,
dataSource,
id,
name,
symbol,
marketDataItemCount,
@ -331,19 +334,35 @@ export class AdminService {
symbol,
symbolMapping
}: Prisma.SymbolProfileUpdateInput & UniqueAsset) {
await this.symbolProfileService.updateSymbolProfile({
assetClass,
assetSubClass,
comment,
countries,
currency,
dataSource,
name,
scraperConfiguration,
sectors,
symbol,
symbolMapping
});
const updatedSymbolProfile: Prisma.SymbolProfileUpdateInput & UniqueAsset =
{
assetClass,
assetSubClass,
comment,
countries,
currency,
dataSource,
scraperConfiguration,
sectors,
symbol,
symbolMapping,
...(dataSource === 'MANUAL'
? { name }
: {
SymbolProfileOverrides: {
upsert: {
create: {
name: name as string
},
update: {
name: name as string
}
}
}
})
};
await this.symbolProfileService.updateSymbolProfile(updatedSymbolProfile);
const [symbolProfile] = await this.symbolProfileService.getSymbolProfiles([
{
@ -397,6 +416,7 @@ export class AdminService {
assetClass: 'CASH',
countriesCount: 0,
currency: symbol.replace(DEFAULT_CURRENCY, ''),
id: undefined,
name: symbol,
sectorsCount: 0
};

View File

@ -1,5 +1,6 @@
import { HasPermission } from '@ghostfolio/api/decorators/has-permission.decorator';
import { HasPermissionGuard } from '@ghostfolio/api/guards/has-permission.guard';
import { getInterval } from '@ghostfolio/api/helper/portfolio.helper';
import { TransformDataSourceInRequestInterceptor } from '@ghostfolio/api/interceptors/transform-data-source-in-request.interceptor';
import { TransformDataSourceInResponseInterceptor } from '@ghostfolio/api/interceptors/transform-data-source-in-response.interceptor';
import type {
@ -8,7 +9,7 @@ import type {
UniqueAsset
} from '@ghostfolio/common/interfaces';
import { permissions } from '@ghostfolio/common/permissions';
import type { RequestWithUser } from '@ghostfolio/common/types';
import type { DateRange, RequestWithUser } from '@ghostfolio/common/types';
import {
Body,
@ -19,6 +20,7 @@ import {
Inject,
Param,
Post,
Query,
UseGuards,
UseInterceptors
} from '@nestjs/common';
@ -106,13 +108,18 @@ export class BenchmarkController {
public async getBenchmarkMarketDataBySymbol(
@Param('dataSource') dataSource: DataSource,
@Param('startDateString') startDateString: string,
@Param('symbol') symbol: string
@Param('symbol') symbol: string,
@Query('range') dateRange: DateRange = 'max'
): Promise<BenchmarkMarketDataDetails> {
const startDate = new Date(startDateString);
const { endDate, startDate } = getInterval(
dateRange,
new Date(startDateString)
);
const userCurrency = this.request.user.Settings.settings.baseCurrency;
return this.benchmarkService.getMarketDataBySymbol({
dataSource,
endDate,
startDate,
symbol,
userCurrency

View File

@ -13,7 +13,8 @@ import {
import {
DATE_FORMAT,
calculateBenchmarkTrend,
parseDate
parseDate,
resetHours
} from '@ghostfolio/common/helper';
import {
Benchmark,
@ -26,8 +27,14 @@ import { BenchmarkTrend } from '@ghostfolio/common/types';
import { Injectable, Logger } from '@nestjs/common';
import { SymbolProfile } from '@prisma/client';
import Big from 'big.js';
import { format, isSameDay, subDays } from 'date-fns';
import { Big } from 'big.js';
import {
differenceInDays,
eachDayOfInterval,
format,
isSameDay,
subDays
} from 'date-fns';
import { isNumber, last, uniqBy } from 'lodash';
import ms from 'ms';
@ -110,7 +117,9 @@ export class BenchmarkService {
const quotes = await this.dataProviderService.getQuotes({
items: benchmarkAssetProfiles.map(({ dataSource, symbol }) => {
return { dataSource, symbol };
})
}),
requestTimeout: ms('30 seconds'),
useCache: false
});
for (const { dataSource, symbol } of benchmarkAssetProfiles) {
@ -163,7 +172,7 @@ export class BenchmarkService {
await this.redisCacheService.set(
this.CACHE_KEY_BENCHMARKS,
JSON.stringify(benchmarks),
ms('4 hours') / 1000
ms('2 hours') / 1000
);
}
@ -206,15 +215,28 @@ export class BenchmarkService {
public async getMarketDataBySymbol({
dataSource,
endDate = new Date(),
startDate,
symbol,
userCurrency
}: {
endDate?: Date;
startDate: Date;
userCurrency: string;
} & UniqueAsset): Promise<BenchmarkMarketDataDetails> {
const marketData: { date: string; value: number }[] = [];
const days = differenceInDays(endDate, startDate) + 1;
const dates = eachDayOfInterval(
{
start: startDate,
end: endDate
},
{ step: Math.round(days / Math.min(days, MAX_CHART_ITEMS)) }
).map((date) => {
return resetHours(date);
});
const [currentSymbolItem, marketDataItems] = await Promise.all([
this.symbolService.get({
dataGatheringItem: {
@ -230,7 +252,7 @@ export class BenchmarkService {
dataSource,
symbol,
date: {
gte: startDate
in: dates
}
}
})
@ -264,17 +286,7 @@ export class BenchmarkService {
return { marketData };
}
const step = Math.round(
marketDataItems.length / Math.min(marketDataItems.length, MAX_CHART_ITEMS)
);
let i = 0;
for (let marketDataItem of marketDataItems) {
if (i % step !== 0) {
continue;
}
const exchangeRate =
exchangeRates[`${currentSymbolItem.currency}${userCurrency}`]?.[
format(marketDataItem.date, DATE_FORMAT)
@ -297,15 +309,15 @@ export class BenchmarkService {
});
}
const includesToday = isSameDay(
const includesEndDate = isSameDay(
parseDate(last(marketData).date),
new Date()
endDate
);
if (currentSymbolItem?.marketPrice && !includesToday) {
if (currentSymbolItem?.marketPrice && !includesEndDate) {
const exchangeRate =
exchangeRates[`${currentSymbolItem.currency}${userCurrency}`]?.[
format(new Date(), DATE_FORMAT)
format(endDate, DATE_FORMAT)
];
const exchangeRateFactor =
@ -314,7 +326,7 @@ export class BenchmarkService {
: 1;
marketData.push({
date: format(new Date(), DATE_FORMAT),
date: format(endDate, DATE_FORMAT),
value:
this.calculateChangeInPercentage(
marketPriceAtStartDate,

View File

@ -95,7 +95,10 @@ export class ExportService {
: SymbolProfile.symbol
};
}
)
),
user: {
settings: { currency: userCurrency }
}
};
}
}

View File

@ -27,7 +27,7 @@ import {
import { Injectable } from '@nestjs/common';
import { DataSource, Prisma, SymbolProfile } from '@prisma/client';
import Big from 'big.js';
import { Big } from 'big.js';
import { endOfToday, format, isAfter, isSameSecond, parseISO } from 'date-fns';
import { uniqBy } from 'lodash';
import { v4 as uuidv4 } from 'uuid';
@ -117,7 +117,7 @@ export class ImportService {
feeInBaseCurrency: 0,
id: assetProfile.id,
isDraft: false,
SymbolProfile: <SymbolProfile>(<unknown>assetProfile),
SymbolProfile: assetProfile,
symbolProfileId: assetProfile.id,
type: 'DIVIDEND',
unitPrice: marketPrice,
@ -521,22 +521,14 @@ export class ImportService {
currency,
dataSource,
symbol,
assetClass: null,
assetSubClass: null,
comment: null,
countries: null,
activitiesCount: undefined,
assetClass: undefined,
assetSubClass: undefined,
countries: undefined,
createdAt: undefined,
figi: null,
figiComposite: null,
figiShareClass: null,
id: undefined,
isin: null,
name: null,
scraperConfiguration: null,
sectors: null,
symbolMapping: null,
updatedAt: undefined,
url: null
sectors: undefined,
updatedAt: undefined
}
};
}

View File

@ -1,13 +1,19 @@
import { OrderWithAccount } from '@ghostfolio/common/types';
import { EnhancedSymbolProfile } from '@ghostfolio/common/interfaces';
import { AccountWithPlatform } from '@ghostfolio/common/types';
import { Order, Tag } from '@prisma/client';
export interface Activities {
activities: Activity[];
count: number;
}
export interface Activity extends OrderWithAccount {
export interface Activity extends Order {
Account?: AccountWithPlatform;
error?: ActivityError;
feeInBaseCurrency: number;
SymbolProfile?: EnhancedSymbolProfile;
tags?: Tag[];
updateAccountBalance?: boolean;
value: number;
valueInBaseCurrency: number;

View File

@ -1,5 +1,6 @@
import { HasPermission } from '@ghostfolio/api/decorators/has-permission.decorator';
import { HasPermissionGuard } from '@ghostfolio/api/guards/has-permission.guard';
import { getInterval } from '@ghostfolio/api/helper/portfolio.helper';
import { RedactValuesInResponseInterceptor } from '@ghostfolio/api/interceptors/redact-values-in-response.interceptor';
import { TransformDataSourceInRequestInterceptor } from '@ghostfolio/api/interceptors/transform-data-source-in-request.interceptor';
import { TransformDataSourceInResponseInterceptor } from '@ghostfolio/api/interceptors/transform-data-source-in-response.interceptor';
@ -8,7 +9,7 @@ import { DataGatheringService } from '@ghostfolio/api/services/data-gathering/da
import { ImpersonationService } from '@ghostfolio/api/services/impersonation/impersonation.service';
import { HEADER_KEY_IMPERSONATION } from '@ghostfolio/common/config';
import { hasPermission, permissions } from '@ghostfolio/common/permissions';
import type { RequestWithUser } from '@ghostfolio/common/types';
import type { DateRange, RequestWithUser } from '@ghostfolio/common/types';
import {
Body,
@ -84,6 +85,7 @@ export class OrderController {
@Headers(HEADER_KEY_IMPERSONATION.toLowerCase()) impersonationId,
@Query('accounts') filterByAccounts?: string,
@Query('assetClasses') filterByAssetClasses?: string,
@Query('range') dateRange: DateRange = 'max',
@Query('skip') skip?: number,
@Query('sortColumn') sortColumn?: string,
@Query('sortDirection') sortDirection?: Prisma.SortOrder,
@ -96,14 +98,18 @@ export class OrderController {
filterByTags
});
const { endDate, startDate } = getInterval(dateRange);
const impersonationUserId =
await this.impersonationService.validateImpersonationId(impersonationId);
const userCurrency = this.request.user.Settings.settings.baseCurrency;
const { activities, count } = await this.orderService.getOrders({
endDate,
filters,
sortColumn,
sortDirection,
startDate,
userCurrency,
includeDrafts: true,
skip: isNaN(skip) ? undefined : skip,

View File

@ -21,9 +21,9 @@ import {
Tag,
Type as ActivityType
} from '@prisma/client';
import Big from 'big.js';
import { Big } from 'big.js';
import { endOfToday, isAfter } from 'date-fns';
import { groupBy } from 'lodash';
import { groupBy, uniqBy } from 'lodash';
import { v4 as uuidv4 } from 'uuid';
import { Activities } from './interfaces/activities.interface';
@ -148,7 +148,7 @@ export class OrderService {
.plus(data.fee)
.toNumber();
if (data.type === 'BUY') {
if (['BUY', 'FEE'].includes(data.type)) {
amount = new Big(amount).mul(-1).toNumber();
}
@ -198,22 +198,26 @@ export class OrderService {
}
public async getOrders({
endDate,
filters,
includeDrafts = false,
skip,
sortColumn,
sortDirection,
startDate,
take = Number.MAX_SAFE_INTEGER,
types,
userCurrency,
userId,
withExcludedAccounts = false
}: {
endDate?: Date;
filters?: Filter[];
includeDrafts?: boolean;
skip?: number;
sortColumn?: string;
sortDirection?: Prisma.SortOrder;
startDate?: Date;
take?: number;
types?: ActivityType[];
userCurrency: string;
@ -225,6 +229,18 @@ export class OrderService {
];
const where: Prisma.OrderWhereInput = { userId };
if (endDate || startDate) {
where.AND = [];
if (endDate) {
where.AND.push({ date: { lte: endDate } });
}
if (startDate) {
where.AND.push({ date: { gt: startDate } });
}
}
const {
ACCOUNT: filtersByAccount,
ASSET_CLASS: filtersByAssetClass,
@ -320,7 +336,32 @@ export class OrderService {
this.prismaService.order.count({ where })
]);
const uniqueAssets = uniqBy(
orders.map(({ SymbolProfile }) => {
return {
dataSource: SymbolProfile.dataSource,
symbol: SymbolProfile.symbol
};
}),
({ dataSource, symbol }) => {
return getAssetProfileIdentifier({
dataSource,
symbol
});
}
);
const assetProfiles =
await this.symbolProfileService.getSymbolProfiles(uniqueAssets);
const activities = orders.map((order) => {
const assetProfile = assetProfiles.find(({ dataSource, symbol }) => {
return (
dataSource === order.SymbolProfile.dataSource &&
symbol === order.SymbolProfile.symbol
);
});
const value = new Big(order.quantity).mul(order.unitPrice).toNumber();
return {
@ -332,6 +373,7 @@ export class OrderService {
order.SymbolProfile.currency,
userCurrency
),
SymbolProfile: assetProfile,
// TODO: Use exchange rate of date
valueInBaseCurrency: this.exchangeRateDataService.toCurrency(
value,

View File

@ -1,10 +1,11 @@
import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface';
import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service';
import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock';
import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service';
import { parseDate } from '@ghostfolio/common/helper';
import Big from 'big.js';
import { Big } from 'big.js';
import { CurrentRateServiceMock } from './current-rate.service.mock';
import { PortfolioCalculator } from './portfolio-calculator';
jest.mock('@ghostfolio/api/app/portfolio/current-rate.service', () => {
@ -36,46 +37,50 @@ describe('PortfolioCalculator', () => {
const portfolioCalculator = new PortfolioCalculator({
currentRateService,
exchangeRateDataService,
currency: 'CHF',
orders: [
activities: <Activity[]>[
{
currency: 'CHF',
date: '2021-11-22',
dataSource: 'YAHOO',
fee: new Big(1.55),
name: 'Bâloise Holding AG',
quantity: new Big(2),
symbol: 'BALN.SW',
date: new Date('2021-11-22'),
fee: 1.55,
quantity: 2,
SymbolProfile: {
currency: 'CHF',
dataSource: 'YAHOO',
name: 'Bâloise Holding AG',
symbol: 'BALN.SW'
},
type: 'BUY',
unitPrice: new Big(142.9)
unitPrice: 142.9
},
{
currency: 'CHF',
date: '2021-11-30',
dataSource: 'YAHOO',
fee: new Big(1.65),
name: 'Bâloise Holding AG',
quantity: new Big(1),
symbol: 'BALN.SW',
date: new Date('2021-11-30'),
fee: 1.65,
quantity: 1,
SymbolProfile: {
currency: 'CHF',
dataSource: 'YAHOO',
name: 'Bâloise Holding AG',
symbol: 'BALN.SW'
},
type: 'SELL',
unitPrice: new Big(136.6)
unitPrice: 136.6
},
{
currency: 'CHF',
date: '2021-11-30',
dataSource: 'YAHOO',
fee: new Big(0),
name: 'Bâloise Holding AG',
quantity: new Big(1),
symbol: 'BALN.SW',
date: new Date('2021-11-30'),
fee: 0,
quantity: 1,
SymbolProfile: {
currency: 'CHF',
dataSource: 'YAHOO',
name: 'Bâloise Holding AG',
symbol: 'BALN.SW'
},
type: 'SELL',
unitPrice: new Big(136.6)
unitPrice: 136.6
}
]
],
currency: 'CHF'
});
portfolioCalculator.computeTransactionPoints();
const spy = jest
.spyOn(Date, 'now')
.mockImplementation(() => parseDate('2021-12-18').getTime());

View File

@ -1,10 +1,11 @@
import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface';
import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service';
import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock';
import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service';
import { parseDate } from '@ghostfolio/common/helper';
import Big from 'big.js';
import { Big } from 'big.js';
import { CurrentRateServiceMock } from './current-rate.service.mock';
import { PortfolioCalculator } from './portfolio-calculator';
jest.mock('@ghostfolio/api/app/portfolio/current-rate.service', () => {
@ -36,35 +37,37 @@ describe('PortfolioCalculator', () => {
const portfolioCalculator = new PortfolioCalculator({
currentRateService,
exchangeRateDataService,
currency: 'CHF',
orders: [
activities: <Activity[]>[
{
currency: 'CHF',
date: '2021-11-22',
dataSource: 'YAHOO',
fee: new Big(1.55),
name: 'Bâloise Holding AG',
quantity: new Big(2),
symbol: 'BALN.SW',
date: new Date('2021-11-22'),
fee: 1.55,
quantity: 2,
SymbolProfile: {
currency: 'CHF',
dataSource: 'YAHOO',
name: 'Bâloise Holding AG',
symbol: 'BALN.SW'
},
type: 'BUY',
unitPrice: new Big(142.9)
unitPrice: 142.9
},
{
currency: 'CHF',
date: '2021-11-30',
dataSource: 'YAHOO',
fee: new Big(1.65),
name: 'Bâloise Holding AG',
quantity: new Big(2),
symbol: 'BALN.SW',
date: new Date('2021-11-30'),
fee: 1.65,
quantity: 2,
SymbolProfile: {
currency: 'CHF',
dataSource: 'YAHOO',
name: 'Bâloise Holding AG',
symbol: 'BALN.SW'
},
type: 'SELL',
unitPrice: new Big(136.6)
unitPrice: 136.6
}
]
],
currency: 'CHF'
});
portfolioCalculator.computeTransactionPoints();
const spy = jest
.spyOn(Date, 'now')
.mockImplementation(() => parseDate('2021-12-18').getTime());

View File

@ -1,10 +1,11 @@
import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface';
import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service';
import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock';
import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service';
import { parseDate } from '@ghostfolio/common/helper';
import Big from 'big.js';
import { Big } from 'big.js';
import { CurrentRateServiceMock } from './current-rate.service.mock';
import { PortfolioCalculator } from './portfolio-calculator';
jest.mock('@ghostfolio/api/app/portfolio/current-rate.service', () => {
@ -36,24 +37,24 @@ describe('PortfolioCalculator', () => {
const portfolioCalculator = new PortfolioCalculator({
currentRateService,
exchangeRateDataService,
currency: 'CHF',
orders: [
activities: <Activity[]>[
{
currency: 'CHF',
date: '2021-11-30',
dataSource: 'YAHOO',
fee: new Big(1.55),
name: 'Bâloise Holding AG',
quantity: new Big(2),
symbol: 'BALN.SW',
date: new Date('2021-11-30'),
fee: 1.55,
quantity: 2,
SymbolProfile: {
currency: 'CHF',
dataSource: 'YAHOO',
name: 'Bâloise Holding AG',
symbol: 'BALN.SW'
},
type: 'BUY',
unitPrice: new Big(136.6)
unitPrice: 136.6
}
]
],
currency: 'CHF'
});
portfolioCalculator.computeTransactionPoints();
const spy = jest
.spyOn(Date, 'now')
.mockImplementation(() => parseDate('2021-12-18').getTime());

View File

@ -1,11 +1,12 @@
import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface';
import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service';
import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock';
import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service';
import { ExchangeRateDataServiceMock } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service.mock';
import { parseDate } from '@ghostfolio/common/helper';
import Big from 'big.js';
import { Big } from 'big.js';
import { CurrentRateServiceMock } from './current-rate.service.mock';
import { PortfolioCalculator } from './portfolio-calculator';
jest.mock('@ghostfolio/api/app/portfolio/current-rate.service', () => {
@ -49,35 +50,37 @@ describe('PortfolioCalculator', () => {
const portfolioCalculator = new PortfolioCalculator({
currentRateService,
exchangeRateDataService,
currency: 'CHF',
orders: [
activities: <Activity[]>[
{
currency: 'USD',
date: '2015-01-01',
dataSource: 'YAHOO',
fee: new Big(0),
name: 'Bitcoin USD',
quantity: new Big(2),
symbol: 'BTCUSD',
date: new Date('2015-01-01'),
fee: 0,
quantity: 2,
SymbolProfile: {
currency: 'USD',
dataSource: 'YAHOO',
name: 'Bitcoin USD',
symbol: 'BTCUSD'
},
type: 'BUY',
unitPrice: new Big(320.43)
unitPrice: 320.43
},
{
currency: 'USD',
date: '2017-12-31',
dataSource: 'YAHOO',
fee: new Big(0),
name: 'Bitcoin USD',
quantity: new Big(1),
symbol: 'BTCUSD',
date: new Date('2017-12-31'),
fee: 0,
quantity: 1,
SymbolProfile: {
currency: 'USD',
dataSource: 'YAHOO',
name: 'Bitcoin USD',
symbol: 'BTCUSD'
},
type: 'SELL',
unitPrice: new Big(14156.4)
unitPrice: 14156.4
}
]
],
currency: 'CHF'
});
portfolioCalculator.computeTransactionPoints();
const spy = jest
.spyOn(Date, 'now')
.mockImplementation(() => parseDate('2018-01-01').getTime());

View File

@ -1,11 +1,12 @@
import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface';
import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service';
import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock';
import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service';
import { ExchangeRateDataServiceMock } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service.mock';
import { parseDate } from '@ghostfolio/common/helper';
import Big from 'big.js';
import { Big } from 'big.js';
import { CurrentRateServiceMock } from './current-rate.service.mock';
import { PortfolioCalculator } from './portfolio-calculator';
jest.mock('@ghostfolio/api/app/portfolio/current-rate.service', () => {
@ -49,24 +50,24 @@ describe('PortfolioCalculator', () => {
const portfolioCalculator = new PortfolioCalculator({
currentRateService,
exchangeRateDataService,
currency: 'CHF',
orders: [
activities: <Activity[]>[
{
currency: 'USD',
date: '2023-01-03',
dataSource: 'YAHOO',
fee: new Big(1),
name: 'Alphabet Inc.',
quantity: new Big(1),
symbol: 'GOOGL',
date: new Date('2023-01-03'),
fee: 1,
quantity: 1,
SymbolProfile: {
currency: 'USD',
dataSource: 'YAHOO',
name: 'Alphabet Inc.',
symbol: 'GOOGL'
},
type: 'BUY',
unitPrice: new Big(89.12)
unitPrice: 89.12
}
]
],
currency: 'CHF'
});
portfolioCalculator.computeTransactionPoints();
const spy = jest
.spyOn(Date, 'now')
.mockImplementation(() => parseDate('2023-07-10').getTime());

View File

@ -1,11 +1,12 @@
import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface';
import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service';
import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock';
import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service';
import { ExchangeRateDataServiceMock } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service.mock';
import { parseDate } from '@ghostfolio/common/helper';
import Big from 'big.js';
import { Big } from 'big.js';
import { CurrentRateServiceMock } from './current-rate.service.mock';
import { PortfolioCalculator } from './portfolio-calculator';
jest.mock('@ghostfolio/api/app/portfolio/current-rate.service', () => {
@ -49,35 +50,37 @@ describe('PortfolioCalculator', () => {
const portfolioCalculator = new PortfolioCalculator({
currentRateService,
exchangeRateDataService,
currency: 'USD',
orders: [
activities: <Activity[]>[
{
currency: 'USD',
date: '2021-09-16',
dataSource: 'YAHOO',
fee: new Big(19),
name: 'Microsoft Inc.',
quantity: new Big(1),
symbol: 'MSFT',
date: new Date('2021-09-16'),
fee: 19,
quantity: 1,
SymbolProfile: {
currency: 'USD',
dataSource: 'YAHOO',
name: 'Microsoft Inc.',
symbol: 'MSFT'
},
type: 'BUY',
unitPrice: new Big(298.58)
unitPrice: 298.58
},
{
currency: 'USD',
date: '2021-11-16',
dataSource: 'YAHOO',
fee: new Big(0),
name: 'Microsoft Inc.',
quantity: new Big(1),
symbol: 'MSFT',
date: new Date('2021-11-16'),
fee: 0,
quantity: 1,
SymbolProfile: {
currency: 'USD',
dataSource: 'YAHOO',
name: 'Microsoft Inc.',
symbol: 'MSFT'
},
type: 'DIVIDEND',
unitPrice: new Big(0.62)
unitPrice: 0.62
}
]
],
currency: 'USD'
});
portfolioCalculator.computeTransactionPoints();
const spy = jest
.spyOn(Date, 'now')
.mockImplementation(() => parseDate('2023-07-10').getTime());

View File

@ -1,10 +1,11 @@
import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service';
import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock';
import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service';
import { parseDate } from '@ghostfolio/common/helper';
import Big from 'big.js';
import { Big } from 'big.js';
import { subDays } from 'date-fns';
import { CurrentRateServiceMock } from './current-rate.service.mock';
import { PortfolioCalculator } from './portfolio-calculator';
jest.mock('@ghostfolio/api/app/portfolio/current-rate.service', () => {
@ -36,23 +37,20 @@ describe('PortfolioCalculator', () => {
const portfolioCalculator = new PortfolioCalculator({
currentRateService,
exchangeRateDataService,
currency: 'CHF',
orders: []
activities: [],
currency: 'CHF'
});
portfolioCalculator.computeTransactionPoints();
const spy = jest
.spyOn(Date, 'now')
.mockImplementation(() => parseDate('2021-12-18').getTime());
const chartData = await portfolioCalculator.getChartData({
start: new Date()
});
const start = subDays(new Date(Date.now()), 10);
const currentPositions = await portfolioCalculator.getCurrentPositions(
new Date()
);
const chartData = await portfolioCalculator.getChartData({ start });
const currentPositions =
await portfolioCalculator.getCurrentPositions(start);
const investments = portfolioCalculator.getInvestments();

View File

@ -1,10 +1,11 @@
import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface';
import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service';
import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock';
import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service';
import { parseDate } from '@ghostfolio/common/helper';
import Big from 'big.js';
import { Big } from 'big.js';
import { CurrentRateServiceMock } from './current-rate.service.mock';
import { PortfolioCalculator } from './portfolio-calculator';
jest.mock('@ghostfolio/api/app/portfolio/current-rate.service', () => {
@ -36,35 +37,37 @@ describe('PortfolioCalculator', () => {
const portfolioCalculator = new PortfolioCalculator({
currentRateService,
exchangeRateDataService,
currency: 'CHF',
orders: [
activities: <Activity[]>[
{
currency: 'CHF',
date: '2022-03-07',
dataSource: 'YAHOO',
fee: new Big(1.3),
name: 'Novartis AG',
quantity: new Big(2),
symbol: 'NOVN.SW',
date: new Date('2022-03-07'),
fee: 1.3,
quantity: 2,
SymbolProfile: {
currency: 'CHF',
dataSource: 'YAHOO',
name: 'Novartis AG',
symbol: 'NOVN.SW'
},
type: 'BUY',
unitPrice: new Big(75.8)
unitPrice: 75.8
},
{
currency: 'CHF',
date: '2022-04-08',
dataSource: 'YAHOO',
fee: new Big(2.95),
name: 'Novartis AG',
quantity: new Big(1),
symbol: 'NOVN.SW',
date: new Date('2022-04-08'),
fee: 2.95,
quantity: 1,
SymbolProfile: {
currency: 'CHF',
dataSource: 'YAHOO',
name: 'Novartis AG',
symbol: 'NOVN.SW'
},
type: 'SELL',
unitPrice: new Big(85.73)
unitPrice: 85.73
}
]
],
currency: 'CHF'
});
portfolioCalculator.computeTransactionPoints();
const spy = jest
.spyOn(Date, 'now')
.mockImplementation(() => parseDate('2022-04-11').getTime());

View File

@ -1,10 +1,11 @@
import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface';
import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service';
import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock';
import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service';
import { parseDate } from '@ghostfolio/common/helper';
import Big from 'big.js';
import { Big } from 'big.js';
import { CurrentRateServiceMock } from './current-rate.service.mock';
import { PortfolioCalculator } from './portfolio-calculator';
jest.mock('@ghostfolio/api/app/portfolio/current-rate.service', () => {
@ -36,35 +37,37 @@ describe('PortfolioCalculator', () => {
const portfolioCalculator = new PortfolioCalculator({
currentRateService,
exchangeRateDataService,
currency: 'CHF',
orders: [
activities: <Activity[]>[
{
currency: 'CHF',
date: '2022-03-07',
dataSource: 'YAHOO',
fee: new Big(0),
name: 'Novartis AG',
quantity: new Big(2),
symbol: 'NOVN.SW',
date: new Date('2022-03-07'),
fee: 0,
quantity: 2,
SymbolProfile: {
currency: 'CHF',
dataSource: 'YAHOO',
name: 'Novartis AG',
symbol: 'NOVN.SW'
},
type: 'BUY',
unitPrice: new Big(75.8)
unitPrice: 75.8
},
{
currency: 'CHF',
date: '2022-04-08',
dataSource: 'YAHOO',
fee: new Big(0),
name: 'Novartis AG',
quantity: new Big(2),
symbol: 'NOVN.SW',
date: new Date('2022-04-08'),
fee: 0,
quantity: 2,
SymbolProfile: {
currency: 'CHF',
dataSource: 'YAHOO',
name: 'Novartis AG',
symbol: 'NOVN.SW'
},
type: 'SELL',
unitPrice: new Big(85.73)
unitPrice: 85.73
}
]
],
currency: 'CHF'
});
portfolioCalculator.computeTransactionPoints();
const spy = jest
.spyOn(Date, 'now')
.mockImplementation(() => parseDate('2022-04-11').getTime());

View File

@ -1,8 +1,8 @@
import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service';
import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service';
import Big from 'big.js';
import { Big } from 'big.js';
import { CurrentRateService } from './current-rate.service';
import { PortfolioCalculator } from './portfolio-calculator';
describe('PortfolioCalculator', () => {
@ -22,10 +22,10 @@ describe('PortfolioCalculator', () => {
describe('annualized performance percentage', () => {
const portfolioCalculator = new PortfolioCalculator({
activities: [],
currentRateService,
exchangeRateDataService,
currency: 'USD',
orders: []
currency: 'USD'
});
it('Get annualized performance', async () => {

View File

@ -1,3 +1,10 @@
import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface';
import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service';
import { CurrentPositions } from '@ghostfolio/api/app/portfolio/interfaces/current-positions.interface';
import { PortfolioOrderItem } from '@ghostfolio/api/app/portfolio/interfaces/portfolio-calculator.interface';
import { PortfolioOrder } from '@ghostfolio/api/app/portfolio/interfaces/portfolio-order.interface';
import { TransactionPointSymbol } from '@ghostfolio/api/app/portfolio/interfaces/transaction-point-symbol.interface';
import { TransactionPoint } from '@ghostfolio/api/app/portfolio/interfaces/transaction-point.interface';
import { getFactor } from '@ghostfolio/api/helper/portfolio.helper';
import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service';
import { IDataGatheringItem } from '@ghostfolio/api/services/interfaces/interfaces';
@ -8,16 +15,18 @@ import {
InvestmentItem,
ResponseError,
SymbolMetrics,
TimelinePosition
TimelinePosition,
UniqueAsset
} from '@ghostfolio/common/interfaces';
import { GroupBy } from '@ghostfolio/common/types';
import { Logger } from '@nestjs/common';
import Big from 'big.js';
import { Big } from 'big.js';
import {
addDays,
addMilliseconds,
differenceInDays,
eachDayOfInterval,
endOfDay,
format,
isBefore,
@ -27,13 +36,6 @@ import {
} from 'date-fns';
import { cloneDeep, first, isNumber, last, sortBy, uniq } from 'lodash';
import { CurrentRateService } from './current-rate.service';
import { CurrentPositions } from './interfaces/current-positions.interface';
import { PortfolioOrderItem } from './interfaces/portfolio-calculator.interface';
import { PortfolioOrder } from './interfaces/portfolio-order.interface';
import { TransactionPointSymbol } from './interfaces/transaction-point-symbol.interface';
import { TransactionPoint } from './interfaces/transaction-point.interface';
export class PortfolioCalculator {
private static readonly ENABLE_LOGGING = false;
@ -45,116 +47,37 @@ export class PortfolioCalculator {
private transactionPoints: TransactionPoint[];
public constructor({
activities,
currency,
currentRateService,
exchangeRateDataService,
orders
exchangeRateDataService
}: {
activities: Activity[];
currency: string;
currentRateService: CurrentRateService;
exchangeRateDataService: ExchangeRateDataService;
orders: PortfolioOrder[];
}) {
this.currency = currency;
this.currentRateService = currentRateService;
this.exchangeRateDataService = exchangeRateDataService;
this.orders = orders;
this.orders = activities.map(
({ date, fee, quantity, SymbolProfile, type, unitPrice }) => {
return {
SymbolProfile,
type,
date: format(date, DATE_FORMAT),
fee: new Big(fee),
quantity: new Big(quantity),
unitPrice: new Big(unitPrice)
};
}
);
this.orders.sort((a, b) => {
return a.date?.localeCompare(b.date);
});
}
public computeTransactionPoints() {
this.transactionPoints = [];
const symbols: { [symbol: string]: TransactionPointSymbol } = {};
let lastDate: string = null;
let lastTransactionPoint: TransactionPoint = null;
for (const order of this.orders) {
const currentDate = order.date;
let currentTransactionPointItem: TransactionPointSymbol;
const oldAccumulatedSymbol = symbols[order.symbol];
const factor = getFactor(order.type);
if (oldAccumulatedSymbol) {
let investment = oldAccumulatedSymbol.investment;
const newQuantity = order.quantity
.mul(factor)
.plus(oldAccumulatedSymbol.quantity);
if (order.type === 'BUY') {
investment = oldAccumulatedSymbol.investment.plus(
order.quantity.mul(order.unitPrice)
);
} else if (order.type === 'SELL') {
investment = oldAccumulatedSymbol.investment.minus(
order.quantity.mul(oldAccumulatedSymbol.averagePrice)
);
}
currentTransactionPointItem = {
investment,
averagePrice: newQuantity.gt(0)
? investment.div(newQuantity)
: new Big(0),
currency: order.currency,
dataSource: order.dataSource,
dividend: new Big(0),
fee: order.fee.plus(oldAccumulatedSymbol.fee),
firstBuyDate: oldAccumulatedSymbol.firstBuyDate,
quantity: newQuantity,
symbol: order.symbol,
tags: order.tags,
transactionCount: oldAccumulatedSymbol.transactionCount + 1
};
} else {
currentTransactionPointItem = {
averagePrice: order.unitPrice,
currency: order.currency,
dataSource: order.dataSource,
dividend: new Big(0),
fee: order.fee,
firstBuyDate: order.date,
investment: order.unitPrice.mul(order.quantity).mul(factor),
quantity: order.quantity.mul(factor),
symbol: order.symbol,
tags: order.tags,
transactionCount: 1
};
}
symbols[order.symbol] = currentTransactionPointItem;
const items = lastTransactionPoint?.items ?? [];
const newItems = items.filter(
(transactionPointItem) => transactionPointItem.symbol !== order.symbol
);
newItems.push(currentTransactionPointItem);
newItems.sort((a, b) => {
return a.symbol?.localeCompare(b.symbol);
});
if (lastDate !== currentDate || lastTransactionPoint === null) {
lastTransactionPoint = {
date: currentDate,
items: newItems
};
this.transactionPoints.push(lastTransactionPoint);
} else {
lastTransactionPoint.items = newItems;
}
lastDate = currentDate;
}
this.computeTransactionPoints();
}
public getAnnualizedPerformancePercent({
@ -174,14 +97,6 @@ export class PortfolioCalculator {
return new Big(0);
}
public getTransactionPoints(): TransactionPoint[] {
return this.transactionPoints;
}
public setTransactionPoints(transactionPoints: TransactionPoint[]) {
this.transactionPoints = transactionPoints;
}
public async getChartData({
end = new Date(Date.now()),
start,
@ -199,29 +114,31 @@ export class PortfolioCalculator {
}) ?? [];
const currencies: { [symbol: string]: string } = {};
const dates: Date[] = [];
const dataGatheringItems: IDataGatheringItem[] = [];
const firstIndex = transactionPointsBeforeEndDate.length;
let day = start;
let dates = eachDayOfInterval({ start, end }, { step }).map((date) => {
return resetHours(date);
});
while (isBefore(day, end)) {
dates.push(resetHours(day));
day = addDays(day, step);
}
const includesEndDate = isSameDay(last(dates), end);
if (!isSameDay(last(dates), end)) {
if (!includesEndDate) {
dates.push(resetHours(end));
}
if (transactionPointsBeforeEndDate.length > 0) {
for (const item of transactionPointsBeforeEndDate[firstIndex - 1].items) {
for (const {
currency,
dataSource,
symbol
} of transactionPointsBeforeEndDate[firstIndex - 1].items) {
dataGatheringItems.push({
dataSource: item.dataSource,
symbol: item.symbol
dataSource,
symbol
});
currencies[item.symbol] = item.currency;
symbols[item.symbol] = true;
currencies[symbol] = currency;
symbols[symbol] = true;
}
}
@ -243,7 +160,7 @@ export class PortfolioCalculator {
await this.exchangeRateDataService.getExchangeRatesByCurrency({
currencies: uniq(Object.values(currencies)),
endDate: endOfDay(end),
startDate: parseDate(this.transactionPoints?.[0]?.date),
startDate: this.getStartDate(),
targetCurrency: this.currency
});
@ -304,6 +221,7 @@ export class PortfolioCalculator {
start,
step,
symbol,
dataSource: null,
exchangeRates:
exchangeRatesByCurrency[`${currencies[symbol]}${this.currency}`],
isChartMode: true
@ -546,7 +464,7 @@ export class PortfolioCalculator {
await this.exchangeRateDataService.getExchangeRatesByCurrency({
currencies: uniq(Object.values(currencies)),
endDate: endOfDay(endDate),
startDate: parseDate(this.transactionPoints?.[0]?.date),
startDate: this.getStartDate(),
targetCurrency: this.currency
});
@ -602,8 +520,6 @@ export class PortfolioCalculator {
);
const {
dividend,
dividendInBaseCurrency,
grossPerformance,
grossPerformancePercentage,
grossPerformancePercentageWithCurrencyEffect,
@ -615,11 +531,14 @@ export class PortfolioCalculator {
netPerformanceWithCurrencyEffect,
timeWeightedInvestment,
timeWeightedInvestmentWithCurrencyEffect,
totalDividend,
totalDividendInBaseCurrency,
totalInvestment,
totalInvestmentWithCurrencyEffect
} = this.getSymbolMetrics({
marketSymbolMap,
start,
dataSource: item.dataSource,
end: endDate,
exchangeRates:
exchangeRatesByCurrency[`${item.currency}${this.currency}`],
@ -629,8 +548,8 @@ export class PortfolioCalculator {
hasAnySymbolMetricsErrors = hasAnySymbolMetricsErrors || hasErrors;
positions.push({
dividend,
dividendInBaseCurrency,
dividend: totalDividend,
dividendInBaseCurrency: totalDividendInBaseCurrency,
timeWeightedInvestment,
timeWeightedInvestmentWithCurrencyEffect,
averagePrice: item.averagePrice,
@ -839,7 +758,116 @@ export class PortfolioCalculator {
};
}
public getStartDate() {
return this.transactionPoints.length > 0
? parseDate(this.transactionPoints[0].date)
: new Date();
}
public getTransactionPoints() {
return this.transactionPoints;
}
private computeTransactionPoints() {
this.transactionPoints = [];
const symbols: { [symbol: string]: TransactionPointSymbol } = {};
let lastDate: string = null;
let lastTransactionPoint: TransactionPoint = null;
for (const {
fee,
date,
quantity,
SymbolProfile,
tags,
type,
unitPrice
} of this.orders) {
let currentTransactionPointItem: TransactionPointSymbol;
const oldAccumulatedSymbol = symbols[SymbolProfile.symbol];
const factor = getFactor(type);
if (oldAccumulatedSymbol) {
let investment = oldAccumulatedSymbol.investment;
const newQuantity = quantity
.mul(factor)
.plus(oldAccumulatedSymbol.quantity);
if (type === 'BUY') {
investment = oldAccumulatedSymbol.investment.plus(
quantity.mul(unitPrice)
);
} else if (type === 'SELL') {
investment = oldAccumulatedSymbol.investment.minus(
quantity.mul(oldAccumulatedSymbol.averagePrice)
);
}
currentTransactionPointItem = {
investment,
tags,
averagePrice: newQuantity.gt(0)
? investment.div(newQuantity)
: new Big(0),
currency: SymbolProfile.currency,
dataSource: SymbolProfile.dataSource,
dividend: new Big(0),
fee: fee.plus(oldAccumulatedSymbol.fee),
firstBuyDate: oldAccumulatedSymbol.firstBuyDate,
quantity: newQuantity,
symbol: SymbolProfile.symbol,
transactionCount: oldAccumulatedSymbol.transactionCount + 1
};
} else {
currentTransactionPointItem = {
fee,
tags,
averagePrice: unitPrice,
currency: SymbolProfile.currency,
dataSource: SymbolProfile.dataSource,
dividend: new Big(0),
firstBuyDate: date,
investment: unitPrice.mul(quantity).mul(factor),
quantity: quantity.mul(factor),
symbol: SymbolProfile.symbol,
transactionCount: 1
};
}
symbols[SymbolProfile.symbol] = currentTransactionPointItem;
const items = lastTransactionPoint?.items ?? [];
const newItems = items.filter(({ symbol }) => {
return symbol !== SymbolProfile.symbol;
});
newItems.push(currentTransactionPointItem);
newItems.sort((a, b) => {
return a.symbol?.localeCompare(b.symbol);
});
if (lastDate !== date || lastTransactionPoint === null) {
lastTransactionPoint = {
date,
items: newItems
};
this.transactionPoints.push(lastTransactionPoint);
} else {
lastTransactionPoint.items = newItems;
}
lastDate = date;
}
}
private getSymbolMetrics({
dataSource,
end,
exchangeRates,
isChartMode = false,
@ -856,13 +884,10 @@ export class PortfolioCalculator {
};
start: Date;
step?: number;
symbol: string;
}): SymbolMetrics {
} & UniqueAsset): SymbolMetrics {
const currentExchangeRate = exchangeRates[format(new Date(), DATE_FORMAT)];
const currentValues: { [date: string]: Big } = {};
const currentValuesWithCurrencyEffect: { [date: string]: Big } = {};
let dividend = new Big(0);
let dividendInBaseCurrency = new Big(0);
let fees = new Big(0);
let feesAtStartDate = new Big(0);
let feesAtStartDateWithCurrencyEffect = new Big(0);
@ -892,6 +917,8 @@ export class PortfolioCalculator {
[date: string]: Big;
} = {};
let totalDividend = new Big(0);
let totalDividendInBaseCurrency = new Big(0);
let totalInvestment = new Big(0);
let totalInvestmentFromBuyTransactions = new Big(0);
let totalInvestmentFromBuyTransactionsWithCurrencyEffect = new Big(0);
@ -903,8 +930,8 @@ export class PortfolioCalculator {
// Clone orders to keep the original values in this.orders
let orders: PortfolioOrderItem[] = cloneDeep(this.orders).filter(
(order) => {
return order.symbol === symbol;
({ SymbolProfile }) => {
return SymbolProfile.symbol === symbol;
}
);
@ -912,8 +939,6 @@ export class PortfolioCalculator {
return {
currentValues: {},
currentValuesWithCurrencyEffect: {},
dividend: new Big(0),
dividendInBaseCurrency: new Big(0),
grossPerformance: new Big(0),
grossPerformancePercentage: new Big(0),
grossPerformancePercentageWithCurrencyEffect: new Big(0),
@ -934,6 +959,8 @@ export class PortfolioCalculator {
timeWeightedInvestmentValues: {},
timeWeightedInvestmentValuesWithCurrencyEffect: {},
timeWeightedInvestmentWithCurrencyEffect: new Big(0),
totalDividend: new Big(0),
totalDividendInBaseCurrency: new Big(0),
totalInvestment: new Big(0),
totalInvestmentWithCurrencyEffect: new Big(0)
};
@ -954,8 +981,6 @@ export class PortfolioCalculator {
return {
currentValues: {},
currentValuesWithCurrencyEffect: {},
dividend: new Big(0),
dividendInBaseCurrency: new Big(0),
grossPerformance: new Big(0),
grossPerformancePercentage: new Big(0),
grossPerformancePercentageWithCurrencyEffect: new Big(0),
@ -976,6 +1001,8 @@ export class PortfolioCalculator {
timeWeightedInvestmentValues: {},
timeWeightedInvestmentValuesWithCurrencyEffect: {},
timeWeightedInvestmentWithCurrencyEffect: new Big(0),
totalDividend: new Big(0),
totalDividendInBaseCurrency: new Big(0),
totalInvestment: new Big(0),
totalInvestmentWithCurrencyEffect: new Big(0)
};
@ -983,28 +1010,28 @@ export class PortfolioCalculator {
// Add a synthetic order at the start and the end date
orders.push({
symbol,
currency: null,
date: format(start, DATE_FORMAT),
dataSource: null,
fee: new Big(0),
feeInBaseCurrency: new Big(0),
itemType: 'start',
name: '',
quantity: new Big(0),
SymbolProfile: {
dataSource,
symbol
},
type: 'BUY',
unitPrice: unitPriceAtStartDate
});
orders.push({
symbol,
currency: null,
date: format(end, DATE_FORMAT),
dataSource: null,
fee: new Big(0),
feeInBaseCurrency: new Big(0),
itemType: 'end',
name: '',
SymbolProfile: {
dataSource,
symbol
},
quantity: new Big(0),
type: 'BUY',
unitPrice: unitPriceAtEndDate
@ -1025,14 +1052,14 @@ export class PortfolioCalculator {
if (!hasDate) {
orders.push({
symbol,
currency: null,
date: format(day, DATE_FORMAT),
dataSource: null,
fee: new Big(0),
feeInBaseCurrency: new Big(0),
name: '',
quantity: new Big(0),
SymbolProfile: {
dataSource,
symbol
},
type: 'BUY',
unitPrice:
marketSymbolMap[format(day, DATE_FORMAT)]?.[symbol] ??
@ -1219,8 +1246,10 @@ export class PortfolioCalculator {
totalUnits = totalUnits.plus(order.quantity.mul(getFactor(order.type)));
if (order.type === 'DIVIDEND') {
dividend = dividend.plus(order.quantity.mul(order.unitPrice));
dividendInBaseCurrency = dividendInBaseCurrency.plus(
const dividend = order.quantity.mul(order.unitPrice);
totalDividend = totalDividend.plus(dividend);
totalDividendInBaseCurrency = totalDividendInBaseCurrency.plus(
dividend.mul(exchangeRateAtOrderDate ?? 1)
);
}
@ -1495,7 +1524,7 @@ export class PortfolioCalculator {
Time weighted investment with currency effect: ${timeWeightedAverageInvestmentBetweenStartAndEndDateWithCurrencyEffect.toFixed(
2
)}
Total dividend: ${dividend.toFixed(2)}
Total dividend: ${totalDividend.toFixed(2)}
Gross performance: ${totalGrossPerformance.toFixed(
2
)} / ${grossPerformancePercentage.mul(100).toFixed(2)}%
@ -1520,8 +1549,6 @@ export class PortfolioCalculator {
return {
currentValues,
currentValuesWithCurrencyEffect,
dividend,
dividendInBaseCurrency,
grossPerformancePercentage,
grossPerformancePercentageWithCurrencyEffect,
initialValue,
@ -1535,6 +1562,8 @@ export class PortfolioCalculator {
netPerformanceValuesWithCurrencyEffect,
timeWeightedInvestmentValues,
timeWeightedInvestmentValuesWithCurrencyEffect,
totalDividend,
totalDividendInBaseCurrency,
totalInvestment,
totalInvestmentWithCurrencyEffect,
grossPerformance: totalGrossPerformance,

View File

@ -34,7 +34,7 @@ export class CurrentRateService {
}: GetValuesParams): Promise<GetValuesObject> {
const dataProviderInfos: DataProviderInfo[] = [];
const includeToday =
const includesToday =
(!dateQuery.lt || isBefore(new Date(), dateQuery.lt)) &&
(!dateQuery.gte || isBefore(dateQuery.gte, new Date())) &&
(!dateQuery.in || this.containsToday(dateQuery.in));
@ -43,7 +43,7 @@ export class CurrentRateService {
const quoteErrors: ResponseError['errors'] = [];
const today = resetHours(new Date());
if (includeToday) {
if (includesToday) {
promises.push(
this.dataProviderService
.getQuotes({ items: dataGatheringItems, user: this.request?.user })

View File

@ -1,6 +1,6 @@
import { ResponseError, TimelinePosition } from '@ghostfolio/common/interfaces';
import Big from 'big.js';
import { Big } from 'big.js';
export interface CurrentPositions extends ResponseError {
currentValueInBaseCurrency: Big;

View File

@ -1,4 +1,4 @@
import Big from 'big.js';
import { Big } from 'big.js';
import { PortfolioOrder } from './portfolio-order.interface';

View File

@ -1,15 +1,12 @@
import { DataSource, Tag, Type as ActivityType } from '@prisma/client';
import Big from 'big.js';
import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface';
export interface PortfolioOrder {
currency: string;
export interface PortfolioOrder extends Pick<Activity, 'tags' | 'type'> {
date: string;
dataSource: DataSource;
fee: Big;
name: string;
quantity: Big;
symbol: string;
tags?: Tag[];
type: ActivityType;
SymbolProfile: Pick<
Activity['SymbolProfile'],
'currency' | 'dataSource' | 'name' | 'symbol'
>;
unitPrice: Big;
}

View File

@ -1,9 +1,9 @@
import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface';
import {
DataProviderInfo,
EnhancedSymbolProfile,
HistoricalDataItem
} from '@ghostfolio/common/interfaces';
import { OrderWithAccount } from '@ghostfolio/common/types';
import { Account, Tag } from '@prisma/client';
@ -27,7 +27,7 @@ export interface PortfolioPositionDetail {
netPerformancePercent: number;
netPerformancePercentWithCurrencyEffect: number;
netPerformanceWithCurrencyEffect: number;
orders: OrderWithAccount[];
orders: Activity[];
quantity: number;
SymbolProfile: EnhancedSymbolProfile;
tags: Tag[];

View File

@ -1,5 +1,5 @@
import { DataSource, Tag } from '@prisma/client';
import Big from 'big.js';
import { Big } from 'big.js';
export interface TransactionPointSymbol {
averagePrice: Big;

View File

@ -6,6 +6,7 @@ import {
hasNotDefinedValuesInObject,
nullifyValuesInObject
} from '@ghostfolio/api/helper/object.helper';
import { getInterval } from '@ghostfolio/api/helper/portfolio.helper';
import { RedactValuesInResponseInterceptor } from '@ghostfolio/api/interceptors/redact-values-in-response.interceptor';
import { TransformDataSourceInRequestInterceptor } from '@ghostfolio/api/interceptors/transform-data-source-in-request.interceptor';
import { TransformDataSourceInResponseInterceptor } from '@ghostfolio/api/interceptors/transform-data-source-in-response.interceptor';
@ -46,7 +47,7 @@ import {
} from '@nestjs/common';
import { REQUEST } from '@nestjs/core';
import { AuthGuard } from '@nestjs/passport';
import Big from 'big.js';
import { Big } from 'big.js';
import { StatusCodes, getReasonPhrase } from 'http-status-codes';
import { PortfolioPositionDetail } from './interfaces/portfolio-position-detail.interface';
@ -236,8 +237,12 @@ export class PortfolioController {
await this.impersonationService.validateImpersonationId(impersonationId);
const userCurrency = this.request.user.Settings.settings.baseCurrency;
const { endDate, startDate } = getInterval(dateRange);
const { activities } = await this.orderService.getOrders({
endDate,
filters,
startDate,
userCurrency,
userId: impersonationUserId || this.request.user.id,
types: ['DIVIDEND']
@ -245,7 +250,6 @@ export class PortfolioController {
let dividends = await this.portfolioService.getDividends({
activities,
dateRange,
groupBy
});
@ -284,12 +288,14 @@ export class PortfolioController {
@Headers(HEADER_KEY_IMPERSONATION.toLowerCase()) impersonationId: string,
@Query('accounts') filterByAccounts?: string,
@Query('assetClasses') filterByAssetClasses?: string,
@Query('holdingType') filterByHoldingType?: string,
@Query('query') filterBySearchQuery?: string,
@Query('tags') filterByTags?: string
): Promise<PortfolioHoldingsResponse> {
const filters = this.apiService.buildFiltersFromQueryParams({
filterByAccounts,
filterByAssetClasses,
filterByHoldingType,
filterBySearchQuery,
filterByTags
});
@ -416,6 +422,7 @@ export class PortfolioController {
({
date,
netPerformanceInPercentage,
netPerformanceInPercentageWithCurrencyEffect,
netWorth,
totalInvestment,
value
@ -423,6 +430,7 @@ export class PortfolioController {
return {
date,
netPerformanceInPercentage,
netPerformanceInPercentageWithCurrencyEffect,
netWorthInPercentage:
performanceInformation.performance.currentNetWorth === 0
? 0

View File

@ -4,10 +4,11 @@ import { CashDetails } from '@ghostfolio/api/app/account/interfaces/cash-details
import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface';
import { OrderService } from '@ghostfolio/api/app/order/order.service';
import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service';
import { PortfolioOrder } from '@ghostfolio/api/app/portfolio/interfaces/portfolio-order.interface';
import { TransactionPoint } from '@ghostfolio/api/app/portfolio/interfaces/transaction-point.interface';
import { UserService } from '@ghostfolio/api/app/user/user.service';
import { getFactor } from '@ghostfolio/api/helper/portfolio.helper';
import {
getFactor,
getInterval
} from '@ghostfolio/api/helper/portfolio.helper';
import { AccountClusterRiskCurrentInvestment } from '@ghostfolio/api/models/rules/account-cluster-risk/current-investment';
import { AccountClusterRiskSingleAccount } from '@ghostfolio/api/models/rules/account-cluster-risk/single-account';
import { CurrencyClusterRiskBaseCurrencyCurrentInvestment } from '@ghostfolio/api/models/rules/currency-cluster-risk/base-currency-current-investment';
@ -50,7 +51,6 @@ import type {
AccountWithValue,
DateRange,
GroupBy,
OrderWithAccount,
RequestWithUser,
UserWithSettings
} from '@ghostfolio/common/types';
@ -67,7 +67,7 @@ import {
Prisma,
Tag
} from '@prisma/client';
import Big from 'big.js';
import { Big } from 'big.js';
import { isUUID } from 'class-validator';
import {
differenceInDays,
@ -76,24 +76,16 @@ import {
isBefore,
isSameMonth,
isSameYear,
isValid,
max,
min,
parseISO,
set,
startOfWeek,
startOfMonth,
startOfYear,
subDays,
subYears
set
} from 'date-fns';
import { isEmpty, last, uniq, uniqBy } from 'lodash';
import { PortfolioCalculator } from './calculator/twr/portfolio-calculator';
import {
HistoricalDataContainer,
PortfolioPositionDetail
} from './interfaces/portfolio-position-detail.interface';
import { PortfolioCalculator } from './portfolio-calculator';
import { RulesService } from './rules.service';
const asiaPacificMarkets = require('../../assets/countries/asia-pacific-markets.json');
@ -224,11 +216,9 @@ export class PortfolioService {
public async getDividends({
activities,
dateRange = 'max',
groupBy
}: {
activities: Activity[];
dateRange?: DateRange;
groupBy?: GroupBy;
}): Promise<InvestmentItem[]> {
let dividends = activities.map(({ date, valueInBaseCurrency }) => {
@ -242,14 +232,7 @@ export class PortfolioService {
dividends = this.getDividendsByGroup({ dividends, groupBy });
}
const startDate = this.getStartDate(
dateRange,
parseDate(dividends[0]?.date)
);
return dividends.filter(({ date }) => {
return !isBefore(parseDate(date), startDate);
});
return dividends;
}
public async getInvestments({
@ -267,15 +250,15 @@ export class PortfolioService {
}): Promise<PortfolioInvestments> {
const userId = await this.getUserId(impersonationId, this.request.user.id);
const { portfolioOrders, transactionPoints } =
await this.getTransactionPoints({
filters,
userId,
includeDrafts: true,
types: ['BUY', 'SELL']
});
const { activities } = await this.orderService.getOrders({
filters,
userId,
includeDrafts: true,
types: ['BUY', 'SELL'],
userCurrency: this.getUserCurrency()
});
if (transactionPoints.length === 0) {
if (activities.length === 0) {
return {
investments: [],
streaks: { currentStreak: 0, longestStreak: 0 }
@ -283,21 +266,17 @@ export class PortfolioService {
}
const portfolioCalculator = new PortfolioCalculator({
activities,
currency: this.request.user.Settings.settings.baseCurrency,
currentRateService: this.currentRateService,
exchangeRateDataService: this.exchangeRateDataService,
orders: portfolioOrders
exchangeRateDataService: this.exchangeRateDataService
});
portfolioCalculator.setTransactionPoints(transactionPoints);
const { items } = await this.getChart({
dateRange,
impersonationId,
portfolioOrders,
transactionPoints,
portfolioCalculator,
userId,
userCurrency: this.request.user.Settings.settings.baseCurrency,
withDataDecimation: false
});
@ -357,31 +336,35 @@ export class PortfolioService {
(user.Settings?.settings as UserSettings)?.emergencyFund ?? 0
);
const { activities, portfolioOrders, transactionPoints } =
await this.getTransactionPoints({
filters,
userId,
withExcludedAccounts,
types: withLiabilities
? undefined
: getAllActivityTypes().filter((activityType) => {
return activityType !== 'LIABILITY';
})
});
const portfolioCalculator = new PortfolioCalculator({
currency: userCurrency,
currentRateService: this.currentRateService,
exchangeRateDataService: this.exchangeRateDataService,
orders: portfolioOrders
let types = getAllActivityTypes().filter((activityType) => {
return activityType !== 'FEE';
});
portfolioCalculator.setTransactionPoints(transactionPoints);
if (withLiabilities === false) {
types = types.filter((activityType) => {
return activityType !== 'LIABILITY';
});
}
const portfolioStart = parseDate(
transactionPoints[0]?.date ?? format(new Date(), DATE_FORMAT)
const { activities } = await this.orderService.getOrders({
filters,
types,
userCurrency,
userId,
withExcludedAccounts
});
const portfolioCalculator = new PortfolioCalculator({
activities,
currency: userCurrency,
currentRateService: this.currentRateService,
exchangeRateDataService: this.exchangeRateDataService
});
const { startDate } = getInterval(
dateRange,
portfolioCalculator.getStartDate()
);
const startDate = this.getStartDate(dateRange, portfolioStart);
const currentPositions =
await portfolioCalculator.getCurrentPositions(startDate);
@ -399,8 +382,17 @@ export class PortfolioService {
);
const isFilteredByAccount =
filters?.some((filter) => {
return filter.type === 'ACCOUNT';
filters?.some(({ type }) => {
return type === 'ACCOUNT';
}) ?? false;
const isFilteredByCash = filters?.some(({ id, type }) => {
return id === 'CASH' && type === 'ASSET_CLASS';
});
const isFilteredByClosedHoldings =
filters?.some(({ id, type }) => {
return id === 'CLOSED' && type === 'HOLDING_TYPE';
}) ?? false;
let filteredValueInBaseCurrency = isFilteredByAccount
@ -452,7 +444,6 @@ export class PortfolioService {
grossPerformancePercentageWithCurrencyEffect,
investment,
marketPrice,
marketPriceInBaseCurrency,
netPerformance,
netPerformancePercentage,
netPerformancePercentageWithCurrencyEffect,
@ -463,9 +454,16 @@ export class PortfolioService {
transactionCount,
valueInBaseCurrency
} of currentPositions.positions) {
if (quantity.eq(0)) {
// Ignore positions without any quantity
continue;
if (isFilteredByClosedHoldings === true) {
if (!quantity.eq(0)) {
// Ignore positions with a quantity
continue;
}
} else {
if (quantity.eq(0)) {
// Ignore positions without any quantity
continue;
}
}
const symbolProfile = symbolProfileMap[symbol];
@ -580,10 +578,6 @@ export class PortfolioService {
};
}
const isFilteredByCash = filters?.some((filter) => {
return filter.type === 'ASSET_CLASS' && filter.id === 'CASH';
});
if (filters?.length === 0 || isFilteredByAccount || isFilteredByCash) {
const cashPositions = await this.getCashPositions({
cashDetails,
@ -724,39 +718,22 @@ export class PortfolioService {
{ dataSource: aDataSource, symbol: aSymbol }
]);
const portfolioOrders: PortfolioOrder[] = orders
.filter((order) => {
tags = tags.concat(order.tags);
return ['BUY', 'DIVIDEND', 'ITEM', 'SELL'].includes(order.type);
})
.map((order) => ({
currency: order.SymbolProfile.currency,
dataSource: order.SymbolProfile.dataSource,
date: format(order.date, DATE_FORMAT),
fee: new Big(order.fee),
name: order.SymbolProfile?.name,
quantity: new Big(order.quantity),
symbol: order.SymbolProfile.symbol,
tags: order.tags,
type: order.type,
unitPrice: new Big(order.unitPrice)
}));
tags = uniqBy(tags, 'id');
const portfolioCalculator = new PortfolioCalculator({
activities: orders.filter((order) => {
tags = tags.concat(order.tags);
return ['BUY', 'DIVIDEND', 'ITEM', 'SELL'].includes(order.type);
}),
currency: userCurrency,
currentRateService: this.currentRateService,
exchangeRateDataService: this.exchangeRateDataService,
orders: portfolioOrders
exchangeRateDataService: this.exchangeRateDataService
});
portfolioCalculator.computeTransactionPoints();
const portfolioStart = portfolioCalculator.getStartDate();
const transactionPoints = portfolioCalculator.getTransactionPoints();
const portfolioStart = parseDate(transactionPoints[0].date);
const currentPositions =
await portfolioCalculator.getCurrentPositions(portfolioStart);
@ -969,14 +946,17 @@ export class PortfolioService {
const userId = await this.getUserId(impersonationId, this.request.user.id);
const user = await this.userService.user({ id: userId });
const { portfolioOrders, transactionPoints } =
await this.getTransactionPoints({
filters,
userId,
types: ['BUY', 'SELL']
});
const { endDate, startDate } = getInterval(dateRange);
if (transactionPoints?.length <= 0) {
const { activities } = await this.orderService.getOrders({
endDate,
filters,
userId,
types: ['BUY', 'SELL'],
userCurrency: this.getUserCurrency()
});
if (activities?.length <= 0) {
return {
hasErrors: false,
positions: []
@ -984,18 +964,16 @@ export class PortfolioService {
}
const portfolioCalculator = new PortfolioCalculator({
activities,
currency: this.request.user.Settings.settings.baseCurrency,
currentRateService: this.currentRateService,
exchangeRateDataService: this.exchangeRateDataService,
orders: portfolioOrders
exchangeRateDataService: this.exchangeRateDataService
});
portfolioCalculator.setTransactionPoints(transactionPoints);
const portfolioStart = parseDate(transactionPoints[0].date);
const startDate = this.getStartDate(dateRange, portfolioStart);
const currentPositions =
await portfolioCalculator.getCurrentPositions(startDate);
const currentPositions = await portfolioCalculator.getCurrentPositions(
startDate,
endDate
);
let positions = currentPositions.positions.filter(({ quantity }) => {
return !quantity.eq(0);
@ -1142,22 +1120,18 @@ export class PortfolioService {
)
);
const { portfolioOrders, transactionPoints } =
await this.getTransactionPoints({
filters,
userId,
withExcludedAccounts,
types: withItems ? ['BUY', 'ITEM', 'SELL'] : ['BUY', 'SELL']
});
const { endDate, startDate } = getInterval(dateRange);
const portfolioCalculator = new PortfolioCalculator({
currency: userCurrency,
currentRateService: this.currentRateService,
exchangeRateDataService: this.exchangeRateDataService,
orders: portfolioOrders
const { activities } = await this.orderService.getOrders({
endDate,
filters,
userCurrency,
userId,
withExcludedAccounts,
types: withItems ? ['BUY', 'ITEM', 'SELL'] : ['BUY', 'SELL']
});
if (accountBalanceItems?.length <= 0 && transactionPoints?.length <= 0) {
if (accountBalanceItems?.length <= 0 && activities?.length <= 0) {
return {
chart: [],
firstOrderDate: undefined,
@ -1178,18 +1152,13 @@ export class PortfolioService {
};
}
portfolioCalculator.setTransactionPoints(transactionPoints);
const portfolioCalculator = new PortfolioCalculator({
activities,
currency: userCurrency,
currentRateService: this.currentRateService,
exchangeRateDataService: this.exchangeRateDataService
});
const portfolioStart = min(
[
parseDate(accountBalanceItems[0]?.date),
parseDate(transactionPoints[0]?.date)
].filter((date) => {
return isValid(date);
})
);
const startDate = this.getStartDate(dateRange, portfolioStart);
const {
currentValueInBaseCurrency,
errors,
@ -1203,7 +1172,7 @@ export class PortfolioService {
netPerformancePercentageWithCurrencyEffect,
netPerformanceWithCurrencyEffect,
totalInvestment
} = await portfolioCalculator.getCurrentPositions(startDate);
} = await portfolioCalculator.getCurrentPositions(startDate, endDate);
let currentNetPerformance = netPerformance;
@ -1218,9 +1187,7 @@ export class PortfolioService {
const { items } = await this.getChart({
dateRange,
impersonationId,
portfolioOrders,
transactionPoints,
userCurrency,
portfolioCalculator,
userId
});
@ -1297,26 +1264,22 @@ export class PortfolioService {
const user = await this.userService.user({ id: userId });
const userCurrency = this.getUserCurrency(user);
const { activities, portfolioOrders, transactionPoints } =
await this.getTransactionPoints({
userId,
types: ['BUY', 'SELL']
});
const portfolioCalculator = new PortfolioCalculator({
currency: userCurrency,
currentRateService: this.currentRateService,
exchangeRateDataService: this.exchangeRateDataService,
orders: portfolioOrders
const { activities } = await this.orderService.getOrders({
userCurrency,
userId,
types: ['BUY', 'SELL']
});
portfolioCalculator.setTransactionPoints(transactionPoints);
const portfolioCalculator = new PortfolioCalculator({
activities,
currency: userCurrency,
currentRateService: this.currentRateService,
exchangeRateDataService: this.exchangeRateDataService
});
const portfolioStart = parseDate(
transactionPoints[0]?.date ?? format(new Date(), DATE_FORMAT)
const currentPositions = await portfolioCalculator.getCurrentPositions(
portfolioCalculator.getStartDate()
);
const currentPositions =
await portfolioCalculator.getCurrentPositions(portfolioStart);
const positions = currentPositions.positions.filter(
(item) => !item.quantity.eq(0)
@ -1445,21 +1408,17 @@ export class PortfolioService {
private async getChart({
dateRange = 'max',
impersonationId,
portfolioOrders,
transactionPoints,
userCurrency,
portfolioCalculator,
userId,
withDataDecimation = true
}: {
dateRange?: DateRange;
impersonationId: string;
portfolioOrders: PortfolioOrder[];
transactionPoints: TransactionPoint[];
userCurrency: string;
portfolioCalculator: PortfolioCalculator;
userId: string;
withDataDecimation?: boolean;
}): Promise<HistoricalDataContainer> {
if (transactionPoints.length === 0) {
if (portfolioCalculator.getTransactionPoints().length === 0) {
return {
isAllTimeHigh: false,
isAllTimeLow: false,
@ -1469,26 +1428,15 @@ export class PortfolioService {
userId = await this.getUserId(impersonationId, userId);
const portfolioCalculator = new PortfolioCalculator({
currency: userCurrency,
currentRateService: this.currentRateService,
exchangeRateDataService: this.exchangeRateDataService,
orders: portfolioOrders
});
const { endDate, startDate } = getInterval(
dateRange,
portfolioCalculator.getStartDate()
);
portfolioCalculator.setTransactionPoints(transactionPoints);
const endDate = new Date();
const portfolioStart = parseDate(transactionPoints[0].date);
const startDate = this.getStartDate(dateRange, portfolioStart);
let step = 1;
if (withDataDecimation) {
const daysInMarket = differenceInDays(new Date(), startDate);
step = Math.round(daysInMarket / Math.min(daysInMarket, MAX_CHART_ITEMS));
}
const daysInMarket = differenceInDays(endDate, startDate) + 1;
const step = withDataDecimation
? Math.round(daysInMarket / Math.min(daysInMarket, MAX_CHART_ITEMS))
: 1;
const items = await portfolioCalculator.getChartData({
step,
@ -1592,7 +1540,7 @@ export class PortfolioService {
activities,
userCurrency
}: {
activities: OrderWithAccount[];
activities: Activity[];
userCurrency: string;
}) {
return getSum(
@ -1649,52 +1597,6 @@ export class PortfolioService {
};
}
private getStartDate(aDateRange: DateRange, portfolioStart: Date) {
switch (aDateRange) {
case '1d':
portfolioStart = max([
portfolioStart,
subDays(new Date().setHours(0, 0, 0, 0), 1)
]);
break;
case 'mtd':
portfolioStart = max([
portfolioStart,
subDays(startOfMonth(new Date().setHours(0, 0, 0, 0)), 1)
]);
break;
case 'wtd':
portfolioStart = max([
portfolioStart,
subDays(
startOfWeek(new Date().setHours(0, 0, 0, 0), { weekStartsOn: 1 }),
1
)
]);
break;
case 'ytd':
portfolioStart = max([
portfolioStart,
subDays(startOfYear(new Date().setHours(0, 0, 0, 0)), 1)
]);
break;
case '1y':
portfolioStart = max([
portfolioStart,
subYears(new Date().setHours(0, 0, 0, 0), 1)
]);
break;
case '5y':
portfolioStart = max([
portfolioStart,
subYears(new Date().setHours(0, 0, 0, 0), 5)
]);
break;
}
return portfolioStart;
}
private getStreaks({
investments,
savingsRate
@ -1871,10 +1773,10 @@ export class PortfolioService {
const daysInMarket = differenceInDays(new Date(), firstOrderDate);
const annualizedPerformancePercent = new PortfolioCalculator({
activities: [],
currency: userCurrency,
currentRateService: this.currentRateService,
exchangeRateDataService: this.exchangeRateDataService,
orders: []
exchangeRateDataService: this.exchangeRateDataService
})
.getAnnualizedPerformancePercent({
daysInMarket,
@ -1886,10 +1788,10 @@ export class PortfolioService {
const annualizedPerformancePercentWithCurrencyEffect =
new PortfolioCalculator({
activities: [],
currency: userCurrency,
currentRateService: this.currentRateService,
exchangeRateDataService: this.exchangeRateDataService,
orders: []
exchangeRateDataService: this.exchangeRateDataService
})
.getAnnualizedPerformancePercent({
daysInMarket,
@ -1940,7 +1842,7 @@ export class PortfolioService {
activityType,
userCurrency
}: {
activities: OrderWithAccount[];
activities: Activity[];
activityType: ActivityType;
userCurrency: string;
}) {
@ -1961,71 +1863,9 @@ export class PortfolioService {
);
}
private async getTransactionPoints({
filters,
includeDrafts = false,
types = getAllActivityTypes(),
userId,
withExcludedAccounts = false
}: {
filters?: Filter[];
includeDrafts?: boolean;
types?: ActivityType[];
userId: string;
withExcludedAccounts?: boolean;
}): Promise<{
activities: Activity[];
transactionPoints: TransactionPoint[];
portfolioOrders: PortfolioOrder[];
}> {
const userCurrency =
this.request.user?.Settings?.settings.baseCurrency ?? DEFAULT_CURRENCY;
const { activities, count } = await this.orderService.getOrders({
filters,
includeDrafts,
types,
userCurrency,
userId,
withExcludedAccounts
});
if (count <= 0) {
return { activities: [], transactionPoints: [], portfolioOrders: [] };
}
const portfolioOrders: PortfolioOrder[] = activities.map((order) => ({
currency: order.SymbolProfile.currency,
dataSource: order.SymbolProfile.dataSource,
date: format(order.date, DATE_FORMAT),
fee: new Big(order.fee),
name: order.SymbolProfile?.name,
quantity: new Big(order.quantity),
symbol: order.SymbolProfile.symbol,
tags: order.tags,
type: order.type,
unitPrice: new Big(order.unitPrice)
}));
const portfolioCalculator = new PortfolioCalculator({
currency: userCurrency,
currentRateService: this.currentRateService,
exchangeRateDataService: this.exchangeRateDataService,
orders: portfolioOrders
});
portfolioCalculator.computeTransactionPoints();
return {
activities,
portfolioOrders,
transactionPoints: portfolioCalculator.getTransactionPoints()
};
}
private getUserCurrency(aUser: UserWithSettings) {
private getUserCurrency(aUser?: UserWithSettings) {
return (
aUser.Settings?.settings.baseCurrency ??
aUser?.Settings?.settings.baseCurrency ??
this.request.user?.Settings?.settings.baseCurrency ??
DEFAULT_CURRENCY
);

View File

@ -21,7 +21,7 @@ export class RedisCacheService {
}
public async get(key: string): Promise<string> {
return await this.cache.get(key);
return this.cache.get(key);
}
public getQuoteKey({ dataSource, symbol }: UniqueAsset) {
@ -29,15 +29,15 @@ export class RedisCacheService {
}
public async remove(key: string) {
await this.cache.del(key);
return this.cache.del(key);
}
public async reset() {
await this.cache.reset();
return this.cache.reset();
}
public async set(key: string, value: string, ttlInSeconds?: number) {
await this.cache.set(
return this.cache.set(
key,
value,
ttlInSeconds ?? this.configurationService.get('CACHE_TTL')

View File

@ -116,7 +116,7 @@ export class SubscriptionController {
@Body() { couponId, priceId }: { couponId: string; priceId: string }
) {
try {
return await this.subscriptionService.createCheckoutSession({
return this.subscriptionService.createCheckoutSession({
couponId,
priceId,
user: this.request.user

View File

@ -14,6 +14,7 @@ import {
IsOptional,
IsString
} from 'class-validator';
import { eachYearOfInterval, format } from 'date-fns';
export class UpdateUserSettingDto {
@IsNumber()
@ -32,7 +33,20 @@ export class UpdateUserSettingDto {
@IsOptional()
colorScheme?: ColorScheme;
@IsIn(<DateRange[]>['1d', '1y', '5y', 'max', 'mtd', 'wtd', 'ytd'])
@IsIn(<DateRange[]>[
'1d',
'1y',
'5y',
'max',
'mtd',
'wtd',
'ytd',
...eachYearOfInterval({ end: new Date(), start: new Date(0) }).map(
(date) => {
return format(date, 'yyyy');
}
)
])
@IsOptional()
dateRange?: DateRange;

View File

@ -135,7 +135,7 @@ export class UserController {
}
}
return await this.userService.updateUserSetting({
return this.userService.updateUserSetting({
userSettings,
userId: this.request.user.id
});

View File

@ -51,13 +51,22 @@ export class UserService {
{ Account, id, permissions, Settings, subscription }: UserWithSettings,
aLocale = locale
): Promise<IUser> {
const access = await this.prismaService.access.findMany({
include: {
User: true
},
orderBy: { alias: 'asc' },
where: { GranteeUser: { id } }
});
let [access, firstActivity, tags] = await Promise.all([
this.prismaService.access.findMany({
include: {
User: true
},
orderBy: { alias: 'asc' },
where: { GranteeUser: { id } }
}),
this.prismaService.order.findFirst({
orderBy: {
date: 'asc'
},
where: { userId: id }
}),
this.tagService.getByUser(id)
]);
let systemMessage: SystemMessage;
@ -69,8 +78,6 @@ export class UserService {
systemMessage = systemMessageProperty;
}
let tags = await this.tagService.getByUser(id);
if (
this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION') &&
subscription.type === 'Basic'
@ -91,6 +98,7 @@ export class UserService {
};
}),
accounts: Account,
dateOfFirstActivity: firstActivity?.date ?? new Date(),
settings: {
...(<UserSettings>Settings.settings),
locale: (<UserSettings>Settings.settings)?.locale ?? aLocale
@ -452,14 +460,15 @@ export class UserService {
}
private getRandomString(length: number) {
const bytes = crypto.randomBytes(length);
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
const result = [];
for (let i = 0; i < length; i++) {
result.push(
characters.charAt(Math.floor(Math.random() * characters.length))
);
const randomByte = bytes[i];
result.push(characters[randomByte % characters.length]);
}
return result.join('');
}
}

View File

@ -5,6 +5,7 @@
"LUNA2": "Terra",
"SGB1": "Songbird",
"SMURFCAT": "Real Smurf Cat",
"TON11419": "Toncoin",
"UNI1": "Uniswap",
"UNI7083": "Uniswap",
"UST": "TerraUSD"

View File

@ -1,4 +1,4 @@
import Big from 'big.js';
import { Big } from 'big.js';
import { cloneDeep, isArray, isObject } from 'lodash';
export function hasNotDefinedValuesInObject(aObject: Object): boolean {

View File

@ -1,4 +1,17 @@
import { resetHours } from '@ghostfolio/common/helper';
import { DateRange } from '@ghostfolio/common/types';
import { Type as ActivityType } from '@prisma/client';
import {
endOfDay,
max,
subDays,
startOfMonth,
startOfWeek,
startOfYear,
subYears,
endOfYear
} from 'date-fns';
export function getFactor(activityType: ActivityType) {
let factor: number;
@ -19,3 +32,49 @@ export function getFactor(activityType: ActivityType) {
return factor;
}
export function getInterval(
aDateRange: DateRange,
portfolioStart = new Date(0)
) {
let endDate = endOfDay(new Date());
let startDate = portfolioStart;
switch (aDateRange) {
case '1d':
startDate = max([startDate, subDays(resetHours(new Date()), 1)]);
break;
case 'mtd':
startDate = max([
startDate,
subDays(startOfMonth(resetHours(new Date())), 1)
]);
break;
case 'wtd':
startDate = max([
startDate,
subDays(startOfWeek(resetHours(new Date()), { weekStartsOn: 1 }), 1)
]);
break;
case 'ytd':
startDate = max([
startDate,
subDays(startOfYear(resetHours(new Date())), 1)
]);
break;
case '1y':
startDate = max([startDate, subYears(resetHours(new Date()), 1)]);
break;
case '5y':
startDate = max([startDate, subYears(resetHours(new Date()), 5)]);
break;
case 'max':
break;
default:
// '2024', '2023', '2022', etc.
endDate = endOfYear(new Date(aDateRange));
startDate = max([startDate, new Date(aDateRange)]);
}
return { endDate, startDate };
}

View File

@ -35,7 +35,7 @@ export class AccountClusterRiskCurrentInvestment extends Rule<Settings> {
};
}
let maxItem;
let maxItem: (typeof accounts)[0];
let totalInvestment = 0;
for (const account of Object.values(accounts)) {
@ -52,7 +52,7 @@ export class AccountClusterRiskCurrentInvestment extends Rule<Settings> {
}
}
const maxInvestmentRatio = maxItem.investment / totalInvestment;
const maxInvestmentRatio = maxItem?.investment / totalInvestment || 0;
if (maxInvestmentRatio > ruleSettings.threshold) {
return {

View File

@ -43,7 +43,7 @@ export class CurrencyClusterRiskBaseCurrencyCurrentInvestment extends Rule<Setti
const baseCurrencyValueRatio = baseCurrencyItem?.value / totalValue || 0;
if (maxItem.groupKey !== ruleSettings.baseCurrency) {
if (maxItem?.groupKey !== ruleSettings.baseCurrency) {
return {
evaluation: `The major part of your current investment is not in your base currency (${(
baseCurrencyValueRatio * 100

View File

@ -37,7 +37,7 @@ export class CurrencyClusterRiskCurrentInvestment extends Rule<Settings> {
}
});
const maxValueRatio = maxItem.value / totalValue;
const maxValueRatio = maxItem?.value / totalValue || 0;
if (maxValueRatio > ruleSettings.threshold) {
return {
@ -52,7 +52,7 @@ export class CurrencyClusterRiskCurrentInvestment extends Rule<Settings> {
return {
evaluation: `The major part of your current investment is in ${
maxItem.groupKey
maxItem?.groupKey ?? ruleSettings.baseCurrency
} (${(maxValueRatio * 100).toPrecision(3)}%) and does not exceed ${
ruleSettings.threshold * 100
}%`,

View File

@ -10,18 +10,21 @@ export class ApiService {
filterByAccounts,
filterByAssetClasses,
filterByAssetSubClasses,
filterByHoldingType,
filterBySearchQuery,
filterByTags
}: {
filterByAccounts?: string;
filterByAssetClasses?: string;
filterByAssetSubClasses?: string;
filterByHoldingType?: string;
filterBySearchQuery?: string;
filterByTags?: string;
}): Filter[] {
const accountIds = filterByAccounts?.split(',') ?? [];
const assetClasses = filterByAssetClasses?.split(',') ?? [];
const assetSubClasses = filterByAssetSubClasses?.split(',') ?? [];
const holdingType = filterByHoldingType;
const searchQuery = filterBySearchQuery?.toLowerCase();
const tagIds = filterByTags?.split(',') ?? [];
@ -52,6 +55,13 @@ export class ApiService {
})
];
if (holdingType) {
filters.push({
id: holdingType,
type: 'HOLDING_TYPE'
});
}
if (searchQuery) {
filters.push({
id: searchQuery,

View File

@ -20,7 +20,7 @@ import type { Granularity, UserWithSettings } from '@ghostfolio/common/types';
import { Inject, Injectable, Logger } from '@nestjs/common';
import { DataSource, MarketData, SymbolProfile } from '@prisma/client';
import Big from 'big.js';
import { Big } from 'big.js';
import { eachDayOfInterval, format, isValid } from 'date-fns';
import { groupBy, isEmpty, isNumber, uniqWith } from 'lodash';
import ms from 'ms';
@ -204,13 +204,14 @@ export class DataProviderService {
});
try {
const queryRaw = `SELECT *
FROM "MarketData"
WHERE "dataSource" IN ('${dataSources.join(`','`)}')
AND "symbol" IN ('${symbols.join(
`','`
)}') ${granularityQuery} ${rangeQuery}
ORDER BY date;`;
const queryRaw = `
SELECT *
FROM "MarketData"
WHERE "dataSource" IN ('${dataSources.join(`','`)}')
AND "symbol" IN ('${symbols.join(
`','`
)}') ${granularityQuery} ${rangeQuery}
ORDER BY date;`;
const marketDataByGranularity: MarketData[] =
await this.prismaService.$queryRawUnsafe(queryRaw);

View File

@ -97,7 +97,8 @@ export class SymbolProfileService {
scraperConfiguration,
sectors,
symbol,
symbolMapping
symbolMapping,
SymbolProfileOverrides
}: Prisma.SymbolProfileUpdateInput & UniqueAsset) {
return this.prismaService.symbolProfile.update({
data: {
@ -109,7 +110,8 @@ export class SymbolProfileService {
name,
scraperConfiguration,
sectors,
symbolMapping
symbolMapping,
SymbolProfileOverrides
},
where: { dataSource_symbol: { dataSource, symbol } }
});

View File

@ -1,3 +1,4 @@
import { getCssVariable } from '@ghostfolio/common/helper';
import { InfoItem, User } from '@ghostfolio/common/interfaces';
import { hasPermission, permissions } from '@ghostfolio/common/permissions';
import { ColorScheme } from '@ghostfolio/common/types';
@ -187,20 +188,28 @@ export class AppComponent implements OnDestroy, OnInit {
? userPreferredColorScheme === 'DARK'
: window.matchMedia('(prefers-color-scheme: dark)').matches;
this.toggleThemeStyleClass(isDarkTheme);
this.toggleTheme(isDarkTheme);
window.matchMedia('(prefers-color-scheme: dark)').addListener((event) => {
if (!this.user?.settings.colorScheme) {
this.toggleThemeStyleClass(event.matches);
this.toggleTheme(event.matches);
}
});
}
private toggleThemeStyleClass(isDarkTheme: boolean) {
private toggleTheme(isDarkTheme: boolean) {
const themeColor = getCssVariable(
isDarkTheme ? '--dark-background' : '--light-background'
);
if (isDarkTheme) {
this.document.body.classList.add('is-dark-theme');
} else {
this.document.body.classList.remove('is-dark-theme');
}
this.document
.querySelector('meta[name="theme-color"]')
.setAttribute('content', themeColor);
}
}

View File

@ -1,3 +1,4 @@
import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface';
import { DataService } from '@ghostfolio/client/services/data.service';
import { UserService } from '@ghostfolio/client/services/user/user.service';
import { downloadAsFile } from '@ghostfolio/common/helper';
@ -21,7 +22,7 @@ import {
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { Sort, SortDirection } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table';
import Big from 'big.js';
import { Big } from 'big.js';
import { format, parseISO } from 'date-fns';
import { isNumber } from 'lodash';
import { Subject } from 'rxjs';
@ -41,7 +42,7 @@ export class AccountDetailDialog implements OnDestroy, OnInit {
public activities: OrderWithAccount[];
public balance: number;
public currency: string;
public dataSource: MatTableDataSource<OrderWithAccount>;
public dataSource: MatTableDataSource<Activity>;
public equity: number;
public hasPermissionToDeleteAccountBalance: boolean;
public historicalDataItems: HistoricalDataItem[];

View File

@ -9,11 +9,7 @@
[showYAxis]="true"
[symbol]="symbol"
/>
<div
*ngFor="let itemByMonth of marketDataByMonth | keyvalue"
class="d-flex"
[hidden]="!marketData.length > 0"
>
<div *ngFor="let itemByMonth of marketDataByMonth | keyvalue" class="d-flex">
<div class="date px-1 text-nowrap">{{ itemByMonth.key }}</div>
<div class="align-items-center d-flex flex-grow-1 px-1">
<div

View File

@ -19,15 +19,17 @@ import { MatDialog } from '@angular/material/dialog';
import { DataSource, MarketData } from '@prisma/client';
import {
addDays,
addMonths,
format,
isBefore,
isSameDay,
isToday,
isValid,
min,
parse,
parseISO
} from 'date-fns';
import { last } from 'lodash';
import { first, last } from 'lodash';
import { DeviceDetectorService } from 'ngx-device-detector';
import { Subject, takeUntil } from 'rxjs';
@ -135,6 +137,27 @@ export class AdminMarketDataDetailComponent implements OnChanges, OnInit {
marketPrice: marketDataItem.marketPrice
};
}
if (this.dateOfFirstActivity) {
// Fill up missing months
const dates = Object.keys(this.marketDataByMonth).sort();
const startDate = min([
parseISO(this.dateOfFirstActivity),
parseISO(first(dates))
]);
const endDate = parseISO(last(dates));
let currentDate = startDate;
while (isBefore(currentDate, endDate)) {
const key = format(currentDate, 'yyyy-MM');
if (!this.marketDataByMonth[key]) {
this.marketDataByMonth[key] = {};
}
currentDate = addMonths(currentDate, 1);
}
}
}
public isDateOfInterest(aDateString: string) {
@ -155,15 +178,14 @@ export class AdminMarketDataDetailComponent implements OnChanges, OnInit {
day: string;
yearMonth: string;
}) {
const date = parseISO(`${yearMonth}-${day}`);
const marketPrice = this.marketDataByMonth[yearMonth]?.[day]?.marketPrice;
const dialogRef = this.dialog.open(MarketDataDetailDialog, {
data: <MarketDataDetailDialogParams>{
date,
marketPrice,
currency: this.currency,
dataSource: this.dataSource,
dateString: `${yearMonth}-${day}`,
symbol: this.symbol,
user: this.user
},

View File

@ -5,7 +5,7 @@ import { DataSource } from '@prisma/client';
export interface MarketDataDetailDialogParams {
currency: string;
dataSource: DataSource;
date: Date;
dateString: string;
marketPrice: number;
symbol: string;
user: User;

View File

@ -45,7 +45,7 @@ export class MarketDataDetailDialog implements OnDestroy {
this.adminService
.fetchSymbolForDate({
dataSource: this.data.dataSource,
date: this.data.date,
dateString: this.data.dateString,
symbol: this.data.symbol
})
.pipe(takeUntil(this.unsubscribeSubject))
@ -63,7 +63,7 @@ export class MarketDataDetailDialog implements OnDestroy {
marketData: {
marketData: [
{
date: this.data.date.toISOString(),
date: this.data.dateString,
marketPrice: this.data.marketPrice
}
]

View File

@ -9,7 +9,7 @@
matInput
name="date"
[matDatepicker]="date"
[(ngModel)]="data.date"
[(ngModel)]="data.dateString"
/>
<mat-datepicker-toggle class="mr-2" matSuffix [for]="date">
<ion-icon

View File

@ -1,6 +1,10 @@
import { AdminService } from '@ghostfolio/client/services/admin.service';
import { DataService } from '@ghostfolio/client/services/data.service';
import { UserService } from '@ghostfolio/client/services/user/user.service';
import { DEFAULT_PAGE_SIZE } from '@ghostfolio/common/config';
import {
DEFAULT_PAGE_SIZE,
ghostfolioScraperApiSymbolPrefix
} from '@ghostfolio/common/config';
import { getDateFormatString } from '@ghostfolio/common/helper';
import { Filter, UniqueAsset, User } from '@ghostfolio/common/interfaces';
import { AdminMarketDataItem } from '@ghostfolio/common/interfaces/admin-market-data.interface';
@ -20,12 +24,13 @@ import { MatPaginator, PageEvent } from '@angular/material/paginator';
import { MatSort, Sort, SortDirection } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table';
import { ActivatedRoute, Router } from '@angular/router';
import { AssetSubClass, DataSource } from '@prisma/client';
import { AssetSubClass, DataSource, SymbolProfile } from '@prisma/client';
import { isUUID } from 'class-validator';
import { DeviceDetectorService } from 'ngx-device-detector';
import { Subject } from 'rxjs';
import { distinctUntilChanged, switchMap, takeUntil } from 'rxjs/operators';
import { AdminMarketDataService } from './admin-market-data.service';
import { AssetProfileDialog } from './asset-profile-dialog/asset-profile-dialog.component';
import { AssetProfileDialogParams } from './asset-profile-dialog/interfaces/interfaces';
import { CreateAssetProfileDialog } from './create-asset-profile-dialog/create-asset-profile-dialog.component';
@ -78,6 +83,7 @@ export class AdminMarketDataComponent
type: <Filter['type']>'PRESET_ID'
}
]);
public benchmarks: Partial<SymbolProfile>[];
public currentDataSource: DataSource;
public currentSymbol: string;
public dataSource: MatTableDataSource<AdminMarketDataItem> =
@ -98,6 +104,7 @@ export class AdminMarketDataComponent
'actions'
];
public filters$ = new Subject<Filter[]>();
public ghostfolioScraperApiSymbolPrefix = ghostfolioScraperApiSymbolPrefix;
public isLoading = false;
public isUUID = isUUID;
public placeholder = '';
@ -108,8 +115,10 @@ export class AdminMarketDataComponent
private unsubscribeSubject = new Subject<void>();
public constructor(
private adminMarketDataService: AdminMarketDataService,
private adminService: AdminService,
private changeDetectorRef: ChangeDetectorRef,
private dataService: DataService,
private deviceService: DeviceDetectorService,
private dialog: MatDialog,
private route: ActivatedRoute,
@ -169,6 +178,9 @@ export class AdminMarketDataComponent
}
public ngOnInit() {
const { benchmarks } = this.dataService.fetchInfo();
this.benchmarks = benchmarks;
this.deviceType = this.deviceService.getDeviceInfo().deviceType;
}
@ -181,20 +193,7 @@ export class AdminMarketDataComponent
}
public onDeleteProfileData({ dataSource, symbol }: UniqueAsset) {
const confirmation = confirm(
$localize`Do you really want to delete this asset profile?`
);
if (confirmation) {
this.adminService
.deleteProfileData({ dataSource, symbol })
.pipe(takeUntil(this.unsubscribeSubject))
.subscribe(() => {
setTimeout(() => {
window.location.reload();
}, 300);
});
}
this.adminMarketDataService.deleteProfileData({ dataSource, symbol });
}
public onGather7Days() {
@ -293,7 +292,16 @@ export class AdminMarketDataComponent
.subscribe(({ count, marketData }) => {
this.totalItems = count;
this.dataSource = new MatTableDataSource(marketData);
this.dataSource = new MatTableDataSource(
marketData.map((marketDataItem) => {
return {
...marketDataItem,
isBenchmark: this.benchmarks.some(({ id }) => {
return id === marketDataItem.id;
})
};
})
);
this.dataSource.sort = this.sort;
this.isLoading = false;

View File

@ -161,23 +161,27 @@
<ion-icon name="ellipsis-horizontal" />
</button>
<mat-menu #assetProfileActionsMenu="matMenu" xPosition="before">
<button
<a
mat-menu-item
(click)="
onOpenAssetProfileDialog({
dataSource: element.dataSource,
symbol: element.symbol
})
"
[queryParams]="{
assetProfileDialog: true,
dataSource: element.dataSource,
symbol: element.symbol
}"
[routerLink]="[]"
>
<span class="align-items-center d-flex">
<ion-icon class="mr-2" name="create-outline" />
<span i18n>Edit</span>
</span>
</button>
</a>
<button
mat-menu-item
[disabled]="element.activitiesCount !== 0"
[disabled]="
element.activitiesCount !== 0 ||
element.isBenchmark ||
element.symbol.startsWith(ghostfolioScraperApiSymbolPrefix)
"
(click)="
onDeleteProfileData({
dataSource: element.dataSource,

View File

@ -12,6 +12,7 @@ import { RouterModule } from '@angular/router';
import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
import { AdminMarketDataComponent } from './admin-market-data.component';
import { AdminMarketDataService } from './admin-market-data.service';
import { GfAssetProfileDialogModule } from './asset-profile-dialog/asset-profile-dialog.module';
import { GfCreateAssetProfileDialogModule } from './create-asset-profile-dialog/create-asset-profile-dialog.module';
@ -31,6 +32,7 @@ import { GfCreateAssetProfileDialogModule } from './create-asset-profile-dialog/
NgxSkeletonLoaderModule,
RouterModule
],
providers: [AdminMarketDataService],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class GfAdminMarketDataModule {}

View File

@ -0,0 +1,26 @@
import { AdminService } from '@ghostfolio/client/services/admin.service';
import { UniqueAsset } from '@ghostfolio/common/interfaces';
import { Injectable } from '@angular/core';
import { takeUntil } from 'rxjs';
@Injectable()
export class AdminMarketDataService {
public constructor(private adminService: AdminService) {}
public deleteProfileData({ dataSource, symbol }: UniqueAsset) {
const confirmation = confirm(
$localize`Do you really want to delete this asset profile?`
);
if (confirmation) {
this.adminService
.deleteProfileData({ dataSource, symbol })
.subscribe(() => {
setTimeout(() => {
window.location.reload();
}, 300);
});
}
}
}

View File

@ -1,7 +1,10 @@
import { UpdateAssetProfileDto } from '@ghostfolio/api/app/admin/update-asset-profile.dto';
import { UpdateMarketDataDto } from '@ghostfolio/api/app/admin/update-market-data.dto';
import { AdminMarketDataService } from '@ghostfolio/client/components/admin-market-data/admin-market-data.service';
import { AdminService } from '@ghostfolio/client/services/admin.service';
import { DataService } from '@ghostfolio/client/services/data.service';
import { DATE_FORMAT, parseDate } from '@ghostfolio/common/helper';
import { ghostfolioScraperApiSymbolPrefix } from '@ghostfolio/common/config';
import { DATE_FORMAT } from '@ghostfolio/common/helper';
import {
AdminMarketDataDetails,
Currency,
@ -69,6 +72,7 @@ export class AssetProfileDialog implements OnDestroy, OnInit {
[code: string]: { name: string; value: number };
};
public currencies: Currency[] = [];
public ghostfolioScraperApiSymbolPrefix = ghostfolioScraperApiSymbolPrefix;
public isBenchmark = false;
public marketDataDetails: MarketData[] = [];
public sectors: {
@ -82,6 +86,7 @@ export class AssetProfileDialog implements OnDestroy, OnInit {
private unsubscribeSubject = new Subject<void>();
public constructor(
private adminMarketDataService: AdminMarketDataService,
private adminService: AdminService,
private changeDetectorRef: ChangeDetectorRef,
@Inject(MAT_DIALOG_DATA) public data: AssetProfileDialogParams,
@ -171,6 +176,12 @@ export class AssetProfileDialog implements OnDestroy, OnInit {
this.dialogRef.close();
}
public onDeleteProfileData({ dataSource, symbol }: UniqueAsset) {
this.adminMarketDataService.deleteProfileData({ dataSource, symbol });
this.dialogRef.close();
}
public onGatherProfileDataBySymbol({ dataSource, symbol }: UniqueAsset) {
this.adminService
.gatherProfileDataBySymbol({ dataSource, symbol })
@ -195,15 +206,13 @@ export class AssetProfileDialog implements OnDestroy, OnInit {
header: true,
skipEmptyLines: true
}
).data;
).data as UpdateMarketDataDto[];
this.adminService
.postMarketData({
dataSource: this.data.dataSource,
marketData: {
marketData: marketData.map(({ date, marketPrice }) => {
return { marketPrice, date: parseDate(date).toISOString() };
})
marketData
},
symbol: this.data.symbol
})

View File

@ -44,6 +44,23 @@
>
<ng-container i18n>Gather Profile Data</ng-container>
</button>
<button
mat-menu-item
type="button"
[disabled]="
assetProfile?.activitiesCount !== 0 ||
isBenchmark ||
data.symbol.startsWith(ghostfolioScraperApiSymbolPrefix)
"
(click)="
onDeleteProfileData({
dataSource: data.dataSource,
symbol: data.symbol
})
"
>
<ng-container i18n>Delete</ng-container>
</button>
</mat-menu>
</div>
@ -192,7 +209,7 @@
}
</ng-container>
</div>
<div *ngIf="assetProfile?.dataSource === 'MANUAL'" class="mt-3">
<div class="mt-3">
<mat-form-field appearance="outline" class="w-100 without-hint">
<mat-label i18n>Name</mat-label>
<input formControlName="name" matInput type="text" />

View File

@ -1,4 +1,5 @@
import { GfAdminMarketDataDetailModule } from '@ghostfolio/client/components/admin-market-data-detail/admin-market-data-detail.module';
import { AdminMarketDataService } from '@ghostfolio/client/components/admin-market-data/admin-market-data.service';
import { GfCurrencySelectorModule } from '@ghostfolio/ui/currency-selector/currency-selector.module';
import { GfPortfolioProportionChartModule } from '@ghostfolio/ui/portfolio-proportion-chart/portfolio-proportion-chart.module';
import { GfValueModule } from '@ghostfolio/ui/value';
@ -36,6 +37,7 @@ import { AssetProfileDialog } from './asset-profile-dialog.component';
ReactiveFormsModule,
TextFieldModule
],
providers: [AdminMarketDataService],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class GfAssetProfileDialogModule {}

View File

@ -91,7 +91,11 @@
<span i18n>Edit</span>
</span>
</button>
<button mat-menu-item (click)="onDeletePlatform(element.id)">
<button
mat-menu-item
[disabled]="element.accountCount > 0"
(click)="onDeletePlatform(element.id)"
>
<span class="align-items-center d-flex">
<ion-icon class="mr-2" name="trash-outline" />
<span i18n>Delete</span>

View File

@ -71,7 +71,11 @@
<span i18n>Edit</span>
</span>
</button>
<button mat-menu-item (click)="onDeleteTag(element.id)">
<button
mat-menu-item
[disabled]="element.activityCount > 0"
(click)="onDeleteTag(element.id)"
>
<span class="align-items-center d-flex">
<ion-icon class="mr-2" name="trash-outline" />
<span i18n>Delete</span>

View File

@ -20,7 +20,7 @@
<mat-select
name="benchmark"
[disabled]="user?.subscription?.type === 'Basic'"
[value]="benchmark"
[value]="benchmark?.id"
(selectionChange)="onChangeBenchmark($event.value)"
>
<mat-option [value]="null" />

View File

@ -46,8 +46,8 @@ import annotationPlugin from 'chartjs-plugin-annotation';
styleUrls: ['./benchmark-comparator.component.scss']
})
export class BenchmarkComparatorComponent implements OnChanges, OnDestroy {
@Input() benchmark: Partial<SymbolProfile>;
@Input() benchmarkDataItems: LineChartItem[] = [];
@Input() benchmark: string;
@Input() benchmarks: Partial<SymbolProfile>[];
@Input() colorScheme: ColorScheme;
@Input() daysInMarket: number;
@ -98,6 +98,12 @@ export class BenchmarkComparatorComponent implements OnChanges, OnDestroy {
}
private initialize() {
const benchmarkDataValues: { [date: string]: number } = {};
for (const { date, value } of this.benchmarkDataItems) {
benchmarkDataValues[date] = value;
}
const data: ChartData<'line'> = {
datasets: [
{
@ -113,10 +119,13 @@ export class BenchmarkComparatorComponent implements OnChanges, OnDestroy {
backgroundColor: `rgb(${secondaryColorRgb.r}, ${secondaryColorRgb.g}, ${secondaryColorRgb.b})`,
borderColor: `rgb(${secondaryColorRgb.r}, ${secondaryColorRgb.g}, ${secondaryColorRgb.b})`,
borderWidth: 2,
data: this.benchmarkDataItems.map(({ date, value }) => {
return { x: parseDate(date).getTime(), y: value };
data: this.performanceDataItems.map(({ date }) => {
return {
x: parseDate(date).getTime(),
y: benchmarkDataValues[date]
};
}),
label: $localize`Benchmark`
label: this.benchmark?.name ?? $localize`Benchmark`
}
]
};
@ -228,7 +237,7 @@ export class BenchmarkComparatorComponent implements OnChanges, OnDestroy {
locale: this.locale,
unit: '%'
}),
mode: 'x',
mode: 'index',
position: <unknown>'top',
xAlign: 'center',
yAlign: 'bottom'

View File

@ -124,7 +124,6 @@ export class HomeOverviewComponent implements OnDestroy, OnInit {
.subscribe(({ chart, errors, performance }) => {
this.errors = errors;
this.performance = performance;
this.isLoadingPerformance = false;
this.historicalDataItems = chart.map(
({ date, netPerformanceInPercentageWithCurrencyEffect }) => {
@ -135,6 +134,8 @@ export class HomeOverviewComponent implements OnDestroy, OnInit {
}
);
this.isLoadingPerformance = false;
this.changeDetectorRef.markForCheck();
});

View File

@ -6,7 +6,6 @@ import {
} from '@ghostfolio/common/chart-helper';
import { primaryColorRgb, secondaryColorRgb } from '@ghostfolio/common/config';
import {
DATE_FORMAT,
getBackgroundColor,
getDateFormatString,
getLocale,
@ -39,16 +38,8 @@ import {
} from 'chart.js';
import 'chartjs-adapter-date-fns';
import annotationPlugin from 'chartjs-plugin-annotation';
import {
addDays,
format,
isAfter,
isValid,
min,
parseISO,
subDays
} from 'date-fns';
import { first, last } from 'lodash';
import { isAfter, isValid, min, subDays } from 'date-fns';
import { first } from 'lodash';
@Component({
selector: 'gf-investment-chart',
@ -112,46 +103,6 @@ export class InvestmentChartComponent implements OnChanges, OnDestroy {
Object.assign({}, item)
);
if (!this.groupBy && this.investments?.length > 0) {
let date: string;
if (this.range === 'max') {
// Extend chart by 5% of days in market (before)
date = format(
subDays(
parseISO(this.investments[0].date),
this.daysInMarket * 0.05 || 90
),
DATE_FORMAT
);
this.investments.unshift({
date,
investment: 0
});
this.values.unshift({
date,
value: 0
});
}
// Extend chart by 5% of days in market (after)
date = format(
addDays(
parseDate(last(this.investments).date),
this.daysInMarket * 0.05 || 90
),
DATE_FORMAT
);
this.investments.push({
date,
investment: last(this.investments).investment
});
this.values.push({
date,
value: last(this.values).value
});
}
const chartData: ChartData<'bar' | 'line'> = {
labels: this.historicalDataItems.map(({ date }) => {
return parseDate(date);
@ -303,7 +254,6 @@ export class InvestmentChartComponent implements OnChanges, OnDestroy {
display: false
},
min: scaleXMin,
suggestedMax: new Date().toISOString(),
type: 'time',
time: {
tooltipFormat: getDateFormatString(this.locale),

View File

@ -1,3 +1,4 @@
import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface';
import { DataService } from '@ghostfolio/client/services/data.service';
import { UserService } from '@ghostfolio/client/services/user/user.service';
import { DATE_FORMAT, downloadAsFile } from '@ghostfolio/common/helper';
@ -7,7 +8,6 @@ import {
LineChartItem,
User
} from '@ghostfolio/common/interfaces';
import { OrderWithAccount } from '@ghostfolio/common/types';
import { translate } from '@ghostfolio/ui/i18n';
import {
@ -37,7 +37,7 @@ import { PositionDetailDialogParams } from './interfaces/interfaces';
})
export class PositionDetailDialog implements OnDestroy, OnInit {
public accounts: Account[];
public activities: OrderWithAccount[];
public activities: Activity[];
public assetClass: string;
public assetSubClass: string;
public averagePrice: number;
@ -46,7 +46,7 @@ export class PositionDetailDialog implements OnDestroy, OnInit {
[code: string]: { name: string; value: number };
};
public dataProviderInfo: DataProviderInfo;
public dataSource: MatTableDataSource<OrderWithAccount>;
public dataSource: MatTableDataSource<Activity>;
public dividendInBaseCurrency: number;
public feeInBaseCurrency: number;
public firstBuyDate: string;

View File

@ -171,11 +171,13 @@
size="medium"
[locale]="data.locale"
[value]="transactionCount"
><ng-container *ngIf="transactionCount === 1">Activity</ng-container
><ng-container *ngIf="transactionCount !== 1"
>Activities</ng-container
></gf-value
>
@if (transactionCount === 1) {
<ng-container i18n>Activity</ng-container>
} @else {
<ng-container i18n>Activities</ng-container>
}
</gf-value>
</div>
<div class="col-6 mb-3">
<gf-value i18n size="medium" [hidden]="!assetClass" [value]="assetClass"
@ -191,17 +193,15 @@
>Asset Sub Class</gf-value
>
</div>
<ng-container
*ngIf="
SymbolProfile?.countries?.length > 0 ||
SymbolProfile?.sectors?.length > 0
"
>
@if (
SymbolProfile?.countries?.length > 0 ||
SymbolProfile?.sectors?.length > 0
) {
@if (
SymbolProfile?.countries?.length === 1 &&
SymbolProfile?.sectors?.length === 1
) {
<div *ngIf="SymbolProfile?.sectors?.length === 1" class="col-6 mb-3">
<div class="col-6 mb-3">
<gf-value
i18n
size="medium"
@ -210,18 +210,17 @@
>Sector</gf-value
>
</div>
<div
*ngIf="SymbolProfile?.countries?.length === 1"
class="col-6 mb-3"
>
<gf-value
i18n
size="medium"
[locale]="data.locale"
[value]="SymbolProfile.countries[0].name"
>Country</gf-value
>
</div>
@if (SymbolProfile?.countries?.length === 1) {
<div class="col-6 mb-3">
<gf-value
i18n
size="medium"
[locale]="data.locale"
[value]="SymbolProfile.countries[0].name"
>Country</gf-value
>
</div>
}
} @else {
<div class="col-md-6 mb-3">
<div class="h5" i18n>Sectors</div>
@ -248,13 +247,32 @@
/>
</div>
}
</ng-container>
<div *ngIf="dataProviderInfo" class="col-md-12 mb-3 text-center">
<hr />
<gf-data-provider-credits [dataProviderInfos]="[dataProviderInfo]">
</gf-data-provider-credits>
<hr />
}
<div class="col-6 mb-3">
<gf-value
i18n
size="medium"
[hidden]="!SymbolProfile?.symbol"
[value]="SymbolProfile?.symbol"
>Symbol</gf-value
>
</div>
<div class="col-6 mb-3">
<gf-value
size="medium"
[hidden]="!SymbolProfile?.isin"
[value]="SymbolProfile?.isin"
>ISIN</gf-value
>
</div>
@if (dataProviderInfo) {
<div class="col-md-12 mb-3 text-center">
<hr />
<gf-data-provider-credits [dataProviderInfos]="[dataProviderInfo]" />
<hr />
</div>
}
</div>
<mat-tab-group
@ -308,31 +326,32 @@
</mat-tab>
</mat-tab-group>
<div *ngIf="tags?.length > 0" class="row">
<div class="col">
<div class="h5" i18n>Tags</div>
<mat-chip-listbox>
<mat-chip-option *ngFor="let tag of tags" disabled>{{
tag.name
}}</mat-chip-option>
</mat-chip-listbox>
@if (tags?.length > 0) {
<div class="row">
<div class="col">
<div class="h5" i18n>Tags</div>
<mat-chip-listbox>
<mat-chip-option *ngFor="let tag of tags" disabled>{{
tag.name
}}</mat-chip-option>
</mat-chip-listbox>
</div>
</div>
</div>
}
<div
*ngIf="
activities?.length > 0 && data.hasPermissionToReportDataGlitch === true
"
class="row"
>
<div class="col">
<hr />
<a color="warn" mat-stroked-button [href]="reportDataGlitchMail"
><ion-icon class="mr-1" name="flag-outline"></ion-icon
><span i18n>Report Data Glitch</span></a
>
@if (
activities?.length > 0 && data.hasPermissionToReportDataGlitch === true
) {
<div class="row">
<div class="col">
<hr />
<a color="warn" mat-stroked-button [href]="reportDataGlitchMail"
><ion-icon class="mr-1" name="flag-outline"></ion-icon
><span i18n>Report Data Glitch</span></a
>
</div>
</div>
</div>
}
</div>
</div>

View File

@ -29,7 +29,7 @@ export class CreateOrUpdateAccessDialog implements OnDestroy {
public constructor(
private changeDetectorRef: ChangeDetectorRef,
@Inject(MAT_DIALOG_DATA) public data: CreateOrUpdateAccessDialogParams,
@Inject(MAT_DIALOG_DATA) private data: CreateOrUpdateAccessDialogParams,
public dialogRef: MatDialogRef<CreateOrUpdateAccessDialog>,
private dataService: DataService,
private formBuilder: FormBuilder

View File

@ -35,9 +35,7 @@
<mat-option i18n value="READ_RESTRICTED"
>Restricted view</mat-option
>
@if (data?.user?.settings?.isExperimentalFeatures) {
<mat-option i18n value="READ">View</mat-option>
}
<mat-option i18n value="READ">View</mat-option>
</mat-select>
</mat-form-field>
</div>

View File

@ -1,6 +1,5 @@
import { Access, User } from '@ghostfolio/common/interfaces';
import { Access } from '@ghostfolio/common/interfaces';
export interface CreateOrUpdateAccessDialogParams {
access: Access;
user: User;
}

View File

@ -107,8 +107,7 @@ export class UserAccountAccessComponent implements OnDestroy, OnInit {
alias: '',
permissions: ['READ_RESTRICTED'],
type: 'PRIVATE'
},
user: this.user
}
},
height: this.deviceType === 'mobile' ? '97.5vh' : '80vh',
width: this.deviceType === 'mobile' ? '100vw' : '50rem'

View File

@ -33,10 +33,8 @@
</mat-card>
<mat-card appearance="outlined" class="mb-3">
<mat-card-header>
<mat-card-title
>What else is included in Ghostfolio?</mat-card-title
></mat-card-header
>
<mat-card-title>What else is included in Ghostfolio?</mat-card-title>
</mat-card-header>
<mat-card-content>
Please find a feature overview to manage your wealth
<a [routerLink]="routerLinkFeatures">here</a>.
@ -44,10 +42,8 @@
</mat-card>
<mat-card appearance="outlined" class="mb-3">
<mat-card-header>
<mat-card-title
>Can I use Ghostfolio anonymously?</mat-card-title
></mat-card-header
>
<mat-card-title>Can I use Ghostfolio anonymously?</mat-card-title>
</mat-card-header>
<mat-card-content>
Yes, the authentication system via security token enables you to sign
in securely and anonymously to Ghostfolio. There is no need for an
@ -56,10 +52,8 @@
</mat-card>
<mat-card appearance="outlined" class="mb-3">
<mat-card-header>
<mat-card-title
>How can Ghostfolio be free?</mat-card-title
></mat-card-header
>
<mat-card-title>How can Ghostfolio be free?</mat-card-title>
</mat-card-header>
<mat-card-content
>This project is driven by the efforts of contributors from around the
world. The
@ -75,8 +69,8 @@
<mat-card-header>
<mat-card-title
>Do you monetize or sell my financial data?</mat-card-title
></mat-card-header
>
>
</mat-card-header>
<mat-card-content
>No, we value your privacy. We do not sell or share your financial
data with any third parties.</mat-card-content
@ -84,10 +78,8 @@
</mat-card>
<mat-card appearance="outlined" class="mb-3">
<mat-card-header>
<mat-card-title
>What is your business model?</mat-card-title
></mat-card-header
>
<mat-card-title>What is your business model?</mat-card-title>
</mat-card-header>
<mat-card-content
>By offering
<a href="https://ghostfol.io/en/pricing">Ghostfolio Premium</a>, a
@ -96,6 +88,15 @@
users.</mat-card-content
>
</mat-card>
<mat-card appearance="outlined" class="mb-3">
<mat-card-header>
<mat-card-title>What is your product roadmap?</mat-card-title>
</mat-card-header>
<mat-card-content
>At this time, we do not have a public roadmap
available.</mat-card-content
>
</mat-card>
<mat-card appearance="outlined" class="mb-3">
<mat-card-header>
<mat-card-title

View File

@ -66,8 +66,9 @@
<mat-card-content
>Yes, you can try
<a [routerLink]="routerLinkPricing">Ghostfolio Premium</a> by signing
up for Ghostfolio and applying for a trial (see “My Ghostfolio”). It
is easy, free and there is no commitment. You can stop using it at any
up for Ghostfolio and applying for a trial (see
<a [routerLink]="['/account', 'membership']">Membership</a>). It is
easy, free and there is no commitment. You can stop using it at any
time.</mat-card-content
>
</mat-card>
@ -128,6 +129,18 @@
>.</mat-card-content
>
</mat-card>
<mat-card appearance="outlined" class="mb-3">
<mat-card-header>
<mat-card-title
>What is the best approach to managing backups?</mat-card-title
>
</mat-card-header>
<mat-card-content
>It is suggested to regularly back up your data via
<a [routerLink]="['/account']">My Ghostfolio</a>
<i>Export Data</i>.</mat-card-content
>
</mat-card>
<mat-card appearance="outlined" class="mb-3">
<mat-card-header>
<mat-card-title>Got any other questions?</mat-card-title>

View File

@ -116,6 +116,17 @@
and desktop computers.</mat-card-content
>
</mat-card>
<mat-card appearance="outlined" class="mb-3">
<mat-card-header>
<mat-card-title
>What is the best approach to managing backups?</mat-card-title
>
</mat-card-header>
<mat-card-content
>It is suggested to regularly back up your data by utilizing full
database dumps.</mat-card-content
>
</mat-card>
<mat-card appearance="outlined" class="mb-3">
<mat-card-header>
<mat-card-title>Got any other questions?</mat-card-title>

View File

@ -124,6 +124,9 @@ export class ActivitiesPageComponent implements OnDestroy, OnInit {
this.dataService
.fetchActivities({
filters: this.userService.getFilters(),
range: this.user?.settings?.isExperimentalFeatures
? this.user?.settings?.dateRange
: undefined,
skip: this.pageIndex * this.pageSize,
sortColumn: this.sortColumn,
sortDirection: this.sortDirection,

View File

@ -260,6 +260,17 @@ export class CreateOrUpdateActivityDialog implements OnDestroy {
this.activityForm.controls['currency'].setValue(currency);
this.activityForm.controls['currencyOfFee'].setValue(currency);
this.activityForm.controls['currencyOfUnitPrice'].setValue(currency);
if (['FEE', 'INTEREST'].includes(type)) {
if (this.activityForm.controls['accountId'].value) {
this.activityForm.controls['updateAccountBalance'].enable();
} else {
this.activityForm.controls['updateAccountBalance'].disable();
this.activityForm.controls['updateAccountBalance'].setValue(
false
);
}
}
}
}
);
@ -374,8 +385,15 @@ export class CreateOrUpdateActivityDialog implements OnDestroy {
this.activityForm.controls['unitPriceInCustomCurrency'].setValue(0);
}
this.activityForm.controls['updateAccountBalance'].disable();
this.activityForm.controls['updateAccountBalance'].setValue(false);
if (
['FEE', 'INTEREST'].includes(type) &&
this.activityForm.controls['accountId'].value
) {
this.activityForm.controls['updateAccountBalance'].enable();
} else {
this.activityForm.controls['updateAccountBalance'].disable();
this.activityForm.controls['updateAccountBalance'].setValue(false);
}
} else {
this.activityForm.controls['accountId'].setValidators(
Validators.required

View File

@ -32,6 +32,7 @@ import { takeUntil } from 'rxjs/operators';
templateUrl: './analysis-page.html'
})
export class AnalysisPageComponent implements OnDestroy, OnInit {
public benchmark: Partial<SymbolProfile>;
public benchmarkDataItems: HistoricalDataItem[] = [];
public benchmarks: Partial<SymbolProfile>[];
public bottom3: Position[];
@ -122,6 +123,10 @@ export class AnalysisPageComponent implements OnDestroy, OnInit {
if (state?.user) {
this.user = state.user;
this.benchmark = this.benchmarks.find(({ id }) => {
return id === this.user.settings?.benchmark;
});
this.update();
}
});
@ -347,6 +352,7 @@ export class AnalysisPageComponent implements OnDestroy, OnInit {
.fetchBenchmarkBySymbol({
dataSource,
symbol,
range: this.user?.settings?.dateRange,
startDate: this.firstOrderDate
})
.pipe(takeUntil(this.unsubscribeSubject))

View File

@ -4,7 +4,7 @@
<div class="col-lg">
<gf-benchmark-comparator
class="h-100"
[benchmark]="user?.settings?.benchmark"
[benchmark]="benchmark"
[benchmarkDataItems]="benchmarkDataItems"
[benchmarks]="benchmarks"
[colorScheme]="user?.settings?.colorScheme"

View File

@ -5,7 +5,7 @@ import { PortfolioReportRule, User } from '@ghostfolio/common/interfaces';
import { hasPermission, permissions } from '@ghostfolio/common/permissions';
import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core';
import Big from 'big.js';
import { Big } from 'big.js';
import { DeviceDetectorService } from 'ngx-device-detector';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';

View File

@ -5,6 +5,7 @@ import { ImpersonationStorageService } from '@ghostfolio/client/services/imperso
import { UserService } from '@ghostfolio/client/services/user/user.service';
import { PortfolioPosition, User } from '@ghostfolio/common/interfaces';
import { hasPermission, permissions } from '@ghostfolio/common/permissions';
import { HoldingType, ToggleOption } from '@ghostfolio/common/types';
import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
@ -24,6 +25,11 @@ export class HoldingsPageComponent implements OnDestroy, OnInit {
public hasImpersonationId: boolean;
public hasPermissionToCreateOrder: boolean;
public holdings: PortfolioPosition[];
public holdingType: HoldingType = 'ACTIVE';
public holdingTypeOptions: ToggleOption[] = [
{ label: $localize`Active`, value: 'ACTIVE' },
{ label: $localize`Closed`, value: 'CLOSED' }
];
public user: User;
private unsubscribeSubject = new Subject<void>();
@ -90,14 +96,34 @@ export class HoldingsPageComponent implements OnDestroy, OnInit {
});
}
public onChangeHoldingType(aHoldingType: HoldingType) {
this.holdingType = aHoldingType;
this.holdings = undefined;
this.fetchHoldings()
.pipe(takeUntil(this.unsubscribeSubject))
.subscribe(({ holdings }) => {
this.holdings = holdings;
this.changeDetectorRef.markForCheck();
});
}
public ngOnDestroy() {
this.unsubscribeSubject.next();
this.unsubscribeSubject.complete();
}
private fetchHoldings() {
const filters = this.userService.getFilters();
if (this.holdingType === 'CLOSED') {
filters.push({ id: 'CLOSED', type: 'HOLDING_TYPE' });
}
return this.dataService.fetchPortfolioHoldings({
filters: this.userService.getFilters()
filters
});
}

View File

@ -6,6 +6,15 @@
</div>
<div class="row">
<div class="col-lg">
<div class="d-flex justify-content-end">
<gf-toggle
class="d-none d-lg-block"
[defaultValue]="holdingType"
[isLoading]="false"
[options]="holdingTypeOptions"
(change)="onChangeHoldingType($event.value)"
/>
</div>
<gf-holdings-table
[baseCurrency]="user?.settings?.baseCurrency"
[deviceType]="deviceType"

View File

@ -1,3 +1,4 @@
import { GfToggleModule } from '@ghostfolio/client/components/toggle/toggle.module';
import { GfHoldingsTableModule } from '@ghostfolio/ui/holdings-table/holdings-table.module';
import { CommonModule } from '@angular/common';
@ -12,6 +13,7 @@ import { HoldingsPageComponent } from './holdings-page.component';
imports: [
CommonModule,
GfHoldingsTableModule,
GfToggleModule,
HoldingsPageRoutingModule,
MatButtonModule
],

View File

@ -2,7 +2,7 @@
<div class="row">
<div class="col">
<h1 class="d-none d-sm-block h3 mb-4 text-center" i18n>Resources</h1>
<h2 class="h4 mb-3" i18n>Ghostfolio</h2>
<h2 class="h4 mb-3">Ghostfolio</h2>
<div class="mb-5">
<div class="mb-4 media">
<div class="media-body">

View File

@ -188,17 +188,14 @@ export class AdminService {
public fetchSymbolForDate({
dataSource,
date,
dateString,
symbol
}: {
dataSource: DataSource;
date: Date;
dateString: string;
symbol: string;
}) {
const url = `/api/v1/symbol/${dataSource}/${symbol}/${format(
date,
DATE_FORMAT
)}`;
const url = `/api/v1/symbol/${dataSource}/${symbol}/${dateString}`;
return this.http.get<IDataProviderHistoricalResponse>(url);
}

View File

@ -62,6 +62,7 @@ export class DataService {
ACCOUNT: filtersByAccount,
ASSET_CLASS: filtersByAssetClass,
ASSET_SUB_CLASS: filtersByAssetSubClass,
HOLDING_TYPE: filtersByHoldingType,
PRESET_ID: filtersByPresetId,
SEARCH_QUERY: filtersBySearchQuery,
TAG: filtersByTag
@ -102,6 +103,10 @@ export class DataService {
);
}
if (filtersByHoldingType) {
params = params.append('holdingType', filtersByHoldingType[0].id);
}
if (filtersByPresetId) {
params = params.append('presetId', filtersByPresetId[0].id);
}
@ -154,12 +159,14 @@ export class DataService {
public fetchActivities({
filters,
range,
skip,
sortColumn,
sortDirection,
take
}: {
filters?: Filter[];
range?: DateRange;
skip?: number;
sortColumn?: string;
sortDirection?: SortDirection;
@ -167,6 +174,10 @@ export class DataService {
}): Observable<Activities> {
let params = this.buildFiltersAsQueryParams({ filters });
if (range) {
params = params.append('range', range);
}
if (skip) {
params = params.append('skip', skip);
}
@ -264,16 +275,25 @@ export class DataService {
public fetchBenchmarkBySymbol({
dataSource,
range,
startDate,
symbol
}: {
range: DateRange;
startDate: Date;
} & UniqueAsset): Observable<BenchmarkMarketDataDetails> {
let params = new HttpParams();
if (range) {
params = params.append('range', range);
}
return this.http.get<BenchmarkMarketDataDetails>(
`/api/v1/benchmark/${dataSource}/${symbol}/${format(
startDate,
DATE_FORMAT
)}`
)}`,
{ params }
);
}

View File

@ -82,6 +82,10 @@ export class UserService extends ObservableStore<UserStoreState> {
private fetchUser(): Observable<User> {
return this.http.get<any>('/api/v1/user').pipe(
map((user) => {
if (user.dateOfFirstActivity) {
user.dateOfFirstActivity = parseISO(user.dateOfFirstActivity);
}
if (user.settings?.retirementDate) {
user.settings.retirementDate = parseISO(user.settings.retirementDate);
}

View File

@ -102,11 +102,15 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">126</context>
<context context-type="linenumber">134</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">269</context>
<context context-type="linenumber">178</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">287</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/activities-page.html</context>
@ -278,11 +282,11 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-platform/admin-platform.component.html</context>
<context context-type="linenumber">97</context>
<context context-type="linenumber">101</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-tag/admin-tag.component.html</context>
<context context-type="linenumber">77</context>
<context context-type="linenumber">81</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/account-balances/account-balances.component.html</context>
@ -328,6 +332,10 @@
<context context-type="sourcefile">apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html</context>
<context context-type="linenumber">34</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">257</context>
</context-group>
</trans-unit>
<trans-unit id="1b6bc6d5daaa6ec75d201690bb6f782f30bf98a0" datatype="html">
<source>Data Source</source>
@ -754,7 +762,7 @@
<target state="translated">Registrierung</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">88</context>
<context context-type="linenumber">96</context>
</context-group>
</trans-unit>
<trans-unit id="ee6a93295a4311c0968e99a6a8d0521684af361b" datatype="html">
@ -762,7 +770,7 @@
<target state="translated">Engagement pro Tag</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">150</context>
<context context-type="linenumber">158</context>
</context-group>
</trans-unit>
<trans-unit id="623f499e6a4ab7f48d7bd483fa49af15713346dd" datatype="html">
@ -770,7 +778,7 @@
<target state="translated">Letzte Abfrage</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">175</context>
<context context-type="linenumber">183</context>
</context-group>
</trans-unit>
<trans-unit id="68ca4a6d3699c0b1141421f8ca995cb1ed736128" datatype="html">
@ -814,7 +822,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">105</context>
<context context-type="linenumber">113</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/header/header.component.html</context>
@ -826,7 +834,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">294</context>
<context context-type="linenumber">312</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/accounts/accounts-page.html</context>
@ -1166,7 +1174,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/resources-page.html</context>
<context context-type="linenumber">39</context>
<context context-type="linenumber">56</context>
</context-group>
</trans-unit>
<trans-unit id="802222cb4754d74846b18f651b1f94e21576185d" datatype="html">
@ -1210,7 +1218,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/holdings/holdings-page.html</context>
<context context-type="linenumber">23</context>
<context context-type="linenumber">32</context>
</context-group>
</trans-unit>
<trans-unit id="ce718ababbce63d776cf8b1f91412beb4c0a6e04" datatype="html">
@ -1492,7 +1500,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">227</context>
<context context-type="linenumber">226</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -1512,7 +1520,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">239</context>
<context context-type="linenumber">238</context>
</context-group>
</trans-unit>
<trans-unit id="cafc87479686947e2590b9f588a88040aeaf660b" datatype="html">
@ -1524,7 +1532,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">313</context>
<context context-type="linenumber">332</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html</context>
@ -1540,7 +1548,7 @@
<target state="translated">Datenfehler melden</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">332</context>
<context context-type="linenumber">350</context>
</context-group>
</trans-unit>
<trans-unit id="2ee26d58f2707416e636887111d5603b35346c4a" datatype="html">
@ -2212,7 +2220,7 @@
<target state="translated">Nach Konto</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">269</context>
<context context-type="linenumber">270</context>
</context-group>
</trans-unit>
<trans-unit id="b79f5520c0cb9a00bd589e8a4c86ffcf5ae439d7" datatype="html">
@ -2220,7 +2228,7 @@
<target state="translated">Nach Währung</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">62</context>
<context context-type="linenumber">63</context>
</context-group>
</trans-unit>
<trans-unit id="8288ff761f2d259625d2e5a3d96db727926d9cd4" datatype="html">
@ -2228,7 +2236,7 @@
<target state="translated">Nach Anlageklasse</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">85</context>
<context context-type="linenumber">86</context>
</context-group>
</trans-unit>
<trans-unit id="b64539bb7815eb3275b55ad723d3897fc6ba8d23" datatype="html">
@ -2236,7 +2244,7 @@
<target state="translated">Nach Position</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">108</context>
<context context-type="linenumber">109</context>
</context-group>
</trans-unit>
<trans-unit id="9f86714c9a6b74e13c96ab02102ce40c34fe13b9" datatype="html">
@ -2244,7 +2252,7 @@
<target state="translated">Nach Sektor</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">131</context>
<context context-type="linenumber">132</context>
</context-group>
</trans-unit>
<trans-unit id="7017e0e26b53ef322c3e3bbf95f06a85487a12b2" datatype="html">
@ -2252,7 +2260,7 @@
<target state="translated">Nach Kontinent</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">155</context>
<context context-type="linenumber">156</context>
</context-group>
</trans-unit>
<trans-unit id="f27e9dd8de80176286e02312e694cb8d1e485a5d" datatype="html">
@ -2260,7 +2268,7 @@
<target state="translated">Nach Land</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">312</context>
<context context-type="linenumber">313</context>
</context-group>
</trans-unit>
<trans-unit id="85780db87ac6c9f202615ac63754551c061e7236" datatype="html">
@ -2268,7 +2276,7 @@
<target state="translated">Regionen</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">202</context>
<context context-type="linenumber">203</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -2516,7 +2524,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">182</context>
<context context-type="linenumber">184</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html</context>
@ -2880,7 +2888,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">191</context>
<context context-type="linenumber">193</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html</context>
@ -2908,11 +2916,11 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">69</context>
<context context-type="linenumber">77</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">222</context>
<context context-type="linenumber">220</context>
</context-group>
</trans-unit>
<trans-unit id="034c2b473d0b76acbc938453375b13cb2491dc17" datatype="html">
@ -2920,7 +2928,7 @@
<target state="translated">Entwickelte Länder</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">227</context>
<context context-type="linenumber">228</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -2932,7 +2940,7 @@
<target state="translated">Schwellenländer</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">236</context>
<context context-type="linenumber">237</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -2944,7 +2952,7 @@
<target state="translated">Übrige Länder</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">245</context>
<context context-type="linenumber">246</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -4076,7 +4084,7 @@
<target state="translated">Benutzer verwenden</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">214</context>
<context context-type="linenumber">222</context>
</context-group>
</trans-unit>
<trans-unit id="3c32a07710e402b2c056bd346e7c42f6015334a6" datatype="html">
@ -4084,7 +4092,7 @@
<target state="translated">Benutzer löschen</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">224</context>
<context context-type="linenumber">232</context>
</context-group>
</trans-unit>
<trans-unit id="5316879909526485230" datatype="html">
@ -4100,7 +4108,7 @@
<target state="translated">Nach ETF-Anbieter</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">289</context>
<context context-type="linenumber">290</context>
</context-group>
</trans-unit>
<trans-unit id="e0c92dc95e1e0fc33d21b5e2df5ea28a86439d56" datatype="html">
@ -4168,7 +4176,7 @@
<target state="translated">Nach Plattform</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">43</context>
<context context-type="linenumber">44</context>
</context-group>
</trans-unit>
<trans-unit id="dff74da4ffb45a2fd54f31f9db9da66f7012a702" datatype="html">
@ -9800,7 +9808,7 @@
<target state="translated">Ratgeber</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/resources-page.html</context>
<context context-type="linenumber">5</context>
<context context-type="linenumber">22</context>
</context-group>
</trans-unit>
<trans-unit id="6edd1a650db2af580ebe746813024c45f1d854b1" datatype="html">
@ -9808,7 +9816,7 @@
<target state="translated">Lexikon</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/resources-page.html</context>
<context context-type="linenumber">75</context>
<context context-type="linenumber">92</context>
</context-group>
</trans-unit>
<trans-unit id="c2fe62534c65e66f2456e568a8f85ba471e6824b" datatype="html">
@ -9892,7 +9900,7 @@
<target state="translated">Nach Markt</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">178</context>
<context context-type="linenumber">179</context>
</context-group>
</trans-unit>
<trans-unit id="2075160647498894947" datatype="html">
@ -9972,7 +9980,7 @@
<target state="translated">Keine Daten verfügbar</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">257</context>
<context context-type="linenumber">258</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -10490,6 +10498,10 @@
<context context-type="sourcefile">apps/client/src/app/pages/faq/faq-page.component.ts</context>
<context context-type="linenumber">48</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/resources-page.component.ts</context>
<context context-type="linenumber">17</context>
</context-group>
</trans-unit>
<trans-unit id="6703761340382395781" datatype="html">
<source>features</source>
@ -11448,7 +11460,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/resources-page.component.ts</context>
<context context-type="linenumber">18</context>
<context context-type="linenumber">19</context>
</context-group>
</trans-unit>
<trans-unit id="a92a0e8a2e70e4a0735b714680629187d2b6f23e" datatype="html">
@ -13764,7 +13776,7 @@
<target state="translated">Ups! Die historischen Daten konnten nicht geparsed werden.</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts</context>
<context context-type="linenumber">224</context>
<context context-type="linenumber">223</context>
</context-group>
</trans-unit>
<trans-unit id="297546430113071258" datatype="html">
@ -14636,7 +14648,7 @@
<target state="translated">Der aktuelle Marktpreis ist</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts</context>
<context context-type="linenumber">318</context>
<context context-type="linenumber">317</context>
</context-group>
</trans-unit>
<trans-unit id="a79d938b5ed20249b4ab6bef86c12633d2f346a0" datatype="html">
@ -14959,6 +14971,30 @@
<context context-type="linenumber">13</context>
</context-group>
</trans-unit>
<trans-unit id="8204176479746810612" datatype="html">
<source>Active</source>
<target state="translated">Aktiv</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/holdings/holdings-page.component.ts</context>
<context context-type="linenumber">30</context>
</context-group>
</trans-unit>
<trans-unit id="7860418101283165917" datatype="html">
<source>Closed</source>
<target state="translated">Abgeschlossen</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/holdings/holdings-page.component.ts</context>
<context context-type="linenumber">31</context>
</context-group>
</trans-unit>
<trans-unit id="f2005fa461c06dc2e04d8918bbabedf23604b5b7" datatype="html">
<source>Activity</source>
<target state="translated">Aktivität</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">176</context>
</context-group>
</trans-unit>
</body>
</file>
</xliff>

View File

@ -103,11 +103,15 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">126</context>
<context context-type="linenumber">134</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">269</context>
<context context-type="linenumber">178</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">287</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/activities-page.html</context>
@ -279,11 +283,11 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-platform/admin-platform.component.html</context>
<context context-type="linenumber">97</context>
<context context-type="linenumber">101</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-tag/admin-tag.component.html</context>
<context context-type="linenumber">77</context>
<context context-type="linenumber">81</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/account-balances/account-balances.component.html</context>
@ -329,6 +333,10 @@
<context context-type="sourcefile">apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html</context>
<context context-type="linenumber">34</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">257</context>
</context-group>
</trans-unit>
<trans-unit id="1b6bc6d5daaa6ec75d201690bb6f782f30bf98a0" datatype="html">
<source>Data Source</source>
@ -755,7 +763,7 @@
<target state="translated">Registro</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">88</context>
<context context-type="linenumber">96</context>
</context-group>
</trans-unit>
<trans-unit id="ee6a93295a4311c0968e99a6a8d0521684af361b" datatype="html">
@ -763,7 +771,7 @@
<target state="translated">Contratación diaria</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">150</context>
<context context-type="linenumber">158</context>
</context-group>
</trans-unit>
<trans-unit id="623f499e6a4ab7f48d7bd483fa49af15713346dd" datatype="html">
@ -771,7 +779,7 @@
<target state="new">Última petición</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">175</context>
<context context-type="linenumber">183</context>
</context-group>
</trans-unit>
<trans-unit id="68ca4a6d3699c0b1141421f8ca995cb1ed736128" datatype="html">
@ -815,7 +823,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">105</context>
<context context-type="linenumber">113</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/header/header.component.html</context>
@ -827,7 +835,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">294</context>
<context context-type="linenumber">312</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/accounts/accounts-page.html</context>
@ -1167,7 +1175,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/resources-page.html</context>
<context context-type="linenumber">39</context>
<context context-type="linenumber">56</context>
</context-group>
</trans-unit>
<trans-unit id="802222cb4754d74846b18f651b1f94e21576185d" datatype="html">
@ -1211,7 +1219,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/holdings/holdings-page.html</context>
<context context-type="linenumber">23</context>
<context context-type="linenumber">32</context>
</context-group>
</trans-unit>
<trans-unit id="ce718ababbce63d776cf8b1f91412beb4c0a6e04" datatype="html">
@ -1490,7 +1498,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">227</context>
<context context-type="linenumber">226</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -1510,7 +1518,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">239</context>
<context context-type="linenumber">238</context>
</context-group>
</trans-unit>
<trans-unit id="cafc87479686947e2590b9f588a88040aeaf660b" datatype="html">
@ -1522,7 +1530,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">313</context>
<context context-type="linenumber">332</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html</context>
@ -1538,7 +1546,7 @@
<target state="translated">Reporta un anomalía de los datos</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">332</context>
<context context-type="linenumber">350</context>
</context-group>
</trans-unit>
<trans-unit id="2ee26d58f2707416e636887111d5603b35346c4a" datatype="html">
@ -2210,7 +2218,7 @@
<target state="translated">Por cuenta</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">269</context>
<context context-type="linenumber">270</context>
</context-group>
</trans-unit>
<trans-unit id="b79f5520c0cb9a00bd589e8a4c86ffcf5ae439d7" datatype="html">
@ -2218,7 +2226,7 @@
<target state="translated">Por divisa</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">62</context>
<context context-type="linenumber">63</context>
</context-group>
</trans-unit>
<trans-unit id="8288ff761f2d259625d2e5a3d96db727926d9cd4" datatype="html">
@ -2226,7 +2234,7 @@
<target state="translated">Por tipo de activo</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">85</context>
<context context-type="linenumber">86</context>
</context-group>
</trans-unit>
<trans-unit id="b64539bb7815eb3275b55ad723d3897fc6ba8d23" datatype="html">
@ -2234,7 +2242,7 @@
<target state="translated">Por participación</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">108</context>
<context context-type="linenumber">109</context>
</context-group>
</trans-unit>
<trans-unit id="9f86714c9a6b74e13c96ab02102ce40c34fe13b9" datatype="html">
@ -2242,7 +2250,7 @@
<target state="translated">Por sector</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">131</context>
<context context-type="linenumber">132</context>
</context-group>
</trans-unit>
<trans-unit id="7017e0e26b53ef322c3e3bbf95f06a85487a12b2" datatype="html">
@ -2250,7 +2258,7 @@
<target state="translated">Por continente</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">155</context>
<context context-type="linenumber">156</context>
</context-group>
</trans-unit>
<trans-unit id="f27e9dd8de80176286e02312e694cb8d1e485a5d" datatype="html">
@ -2258,7 +2266,7 @@
<target state="translated">Por país</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">312</context>
<context context-type="linenumber">313</context>
</context-group>
</trans-unit>
<trans-unit id="85780db87ac6c9f202615ac63754551c061e7236" datatype="html">
@ -2266,7 +2274,7 @@
<target state="translated">Regiones</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">202</context>
<context context-type="linenumber">203</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -2514,7 +2522,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">182</context>
<context context-type="linenumber">184</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html</context>
@ -2842,7 +2850,7 @@
<target state="translated">Mercados desarrollados</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">227</context>
<context context-type="linenumber">228</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -2866,7 +2874,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">191</context>
<context context-type="linenumber">193</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html</context>
@ -2894,7 +2902,7 @@
<target state="translated">Otros mercados</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">245</context>
<context context-type="linenumber">246</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -2906,7 +2914,7 @@
<target state="translated">Mercados emergentes</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">236</context>
<context context-type="linenumber">237</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -2934,11 +2942,11 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">69</context>
<context context-type="linenumber">77</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">222</context>
<context context-type="linenumber">220</context>
</context-group>
</trans-unit>
<trans-unit id="b1c1c6a43da1ad3e41b7a6e3aa5dcc24226cf580" datatype="html">
@ -4074,7 +4082,7 @@
<target state="new">Impersonate User</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">214</context>
<context context-type="linenumber">222</context>
</context-group>
</trans-unit>
<trans-unit id="3c32a07710e402b2c056bd346e7c42f6015334a6" datatype="html">
@ -4082,7 +4090,7 @@
<target state="new">Delete User</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">224</context>
<context context-type="linenumber">232</context>
</context-group>
</trans-unit>
<trans-unit id="5316879909526485230" datatype="html">
@ -4098,7 +4106,7 @@
<target state="new">By ETF Provider</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">289</context>
<context context-type="linenumber">290</context>
</context-group>
</trans-unit>
<trans-unit id="e0c92dc95e1e0fc33d21b5e2df5ea28a86439d56" datatype="html">
@ -4166,7 +4174,7 @@
<target state="new">By Platform</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">43</context>
<context context-type="linenumber">44</context>
</context-group>
</trans-unit>
<trans-unit id="dff74da4ffb45a2fd54f31f9db9da66f7012a702" datatype="html">
@ -9798,7 +9806,7 @@
<target state="new">Guides</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/resources-page.html</context>
<context context-type="linenumber">5</context>
<context context-type="linenumber">22</context>
</context-group>
</trans-unit>
<trans-unit id="6edd1a650db2af580ebe746813024c45f1d854b1" datatype="html">
@ -9806,7 +9814,7 @@
<target state="new">Glossary</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/resources-page.html</context>
<context context-type="linenumber">75</context>
<context context-type="linenumber">92</context>
</context-group>
</trans-unit>
<trans-unit id="c2fe62534c65e66f2456e568a8f85ba471e6824b" datatype="html">
@ -9890,7 +9898,7 @@
<target state="new">By Market</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">178</context>
<context context-type="linenumber">179</context>
</context-group>
</trans-unit>
<trans-unit id="2075160647498894947" datatype="html">
@ -9970,7 +9978,7 @@
<target state="new">No data available</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">257</context>
<context context-type="linenumber">258</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -10488,6 +10496,10 @@
<context context-type="sourcefile">apps/client/src/app/pages/faq/faq-page.component.ts</context>
<context context-type="linenumber">48</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/resources-page.component.ts</context>
<context context-type="linenumber">17</context>
</context-group>
</trans-unit>
<trans-unit id="6703761340382395781" datatype="html">
<source>features</source>
@ -11446,7 +11458,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/resources-page.component.ts</context>
<context context-type="linenumber">18</context>
<context context-type="linenumber">19</context>
</context-group>
</trans-unit>
<trans-unit id="a92a0e8a2e70e4a0735b714680629187d2b6f23e" datatype="html">
@ -13762,7 +13774,7 @@
<target state="new">Oops! Could not parse historical data.</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts</context>
<context context-type="linenumber">224</context>
<context context-type="linenumber">223</context>
</context-group>
</trans-unit>
<trans-unit id="297546430113071258" datatype="html">
@ -14634,7 +14646,7 @@
<target state="new">The current market price is</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts</context>
<context context-type="linenumber">318</context>
<context context-type="linenumber">317</context>
</context-group>
</trans-unit>
<trans-unit id="a79d938b5ed20249b4ab6bef86c12633d2f346a0" datatype="html">
@ -14957,6 +14969,30 @@
<context context-type="linenumber">13</context>
</context-group>
</trans-unit>
<trans-unit id="8204176479746810612" datatype="html">
<source>Active</source>
<target state="new">Active</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/holdings/holdings-page.component.ts</context>
<context context-type="linenumber">30</context>
</context-group>
</trans-unit>
<trans-unit id="7860418101283165917" datatype="html">
<source>Closed</source>
<target state="new">Closed</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/holdings/holdings-page.component.ts</context>
<context context-type="linenumber">31</context>
</context-group>
</trans-unit>
<trans-unit id="f2005fa461c06dc2e04d8918bbabedf23604b5b7" datatype="html">
<source>Activity</source>
<target state="new">Activity</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">176</context>
</context-group>
</trans-unit>
</body>
</file>
</xliff>

View File

@ -114,11 +114,15 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">126</context>
<context context-type="linenumber">134</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">269</context>
<context context-type="linenumber">178</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">287</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/activities-page.html</context>
@ -334,11 +338,11 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-platform/admin-platform.component.html</context>
<context context-type="linenumber">97</context>
<context context-type="linenumber">101</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-tag/admin-tag.component.html</context>
<context context-type="linenumber">77</context>
<context context-type="linenumber">81</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/account-balances/account-balances.component.html</context>
@ -376,6 +380,10 @@
<context context-type="sourcefile">apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html</context>
<context context-type="linenumber">34</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">257</context>
</context-group>
</trans-unit>
<trans-unit id="1b6bc6d5daaa6ec75d201690bb6f782f30bf98a0" datatype="html">
<source>Data Source</source>
@ -618,7 +626,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">182</context>
<context context-type="linenumber">184</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html</context>
@ -642,7 +650,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">191</context>
<context context-type="linenumber">193</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html</context>
@ -762,11 +770,11 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">69</context>
<context context-type="linenumber">77</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">222</context>
<context context-type="linenumber">220</context>
</context-group>
</trans-unit>
<trans-unit id="fc61416d48adb7af122b8697e806077eb251fb57" datatype="html">
@ -782,7 +790,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">227</context>
<context context-type="linenumber">226</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -802,7 +810,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">239</context>
<context context-type="linenumber">238</context>
</context-group>
</trans-unit>
<trans-unit id="638bbddabc5883a7a4087f45592944ce6558409c" datatype="html">
@ -918,7 +926,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">313</context>
<context context-type="linenumber">332</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html</context>
@ -1014,7 +1022,7 @@
<target state="translated">Inscription</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">88</context>
<context context-type="linenumber">96</context>
</context-group>
</trans-unit>
<trans-unit id="4fe84c1d0eef5726c017f64c691145db7a61f879" datatype="html">
@ -1026,7 +1034,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">105</context>
<context context-type="linenumber">113</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/header/header.component.html</context>
@ -1038,7 +1046,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">294</context>
<context context-type="linenumber">312</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/accounts/accounts-page.html</context>
@ -1054,7 +1062,7 @@
<target state="translated">Engagement par Jour</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">150</context>
<context context-type="linenumber">158</context>
</context-group>
</trans-unit>
<trans-unit id="623f499e6a4ab7f48d7bd483fa49af15713346dd" datatype="html">
@ -1062,7 +1070,7 @@
<target state="new"> Dernière Requête </target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">175</context>
<context context-type="linenumber">183</context>
</context-group>
</trans-unit>
<trans-unit id="3cc9c2ae277393b3946b38c088dabff671b1ee1b" datatype="html">
@ -1470,7 +1478,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/resources-page.html</context>
<context context-type="linenumber">39</context>
<context context-type="linenumber">56</context>
</context-group>
</trans-unit>
<trans-unit id="287d3301a32a65a1b31116bda5d3a6463158c42a" datatype="html">
@ -1522,7 +1530,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/holdings/holdings-page.html</context>
<context context-type="linenumber">23</context>
<context context-type="linenumber">32</context>
</context-group>
</trans-unit>
<trans-unit id="5486880308148746399" datatype="html">
@ -1901,7 +1909,7 @@
<target state="translated">Signaler une Erreur de Données</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">332</context>
<context context-type="linenumber">350</context>
</context-group>
</trans-unit>
<trans-unit id="6048892649018070225" datatype="html">
@ -2781,7 +2789,7 @@
<target state="translated">Par Compte</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">269</context>
<context context-type="linenumber">270</context>
</context-group>
</trans-unit>
<trans-unit id="b79f5520c0cb9a00bd589e8a4c86ffcf5ae439d7" datatype="html">
@ -2789,7 +2797,7 @@
<target state="translated">Par Devise</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">62</context>
<context context-type="linenumber">63</context>
</context-group>
</trans-unit>
<trans-unit id="8288ff761f2d259625d2e5a3d96db727926d9cd4" datatype="html">
@ -2797,7 +2805,7 @@
<target state="translated">Par Classe d&apos;Actifs</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">85</context>
<context context-type="linenumber">86</context>
</context-group>
</trans-unit>
<trans-unit id="b64539bb7815eb3275b55ad723d3897fc6ba8d23" datatype="html">
@ -2805,7 +2813,7 @@
<target state="translated">Par Position</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">108</context>
<context context-type="linenumber">109</context>
</context-group>
</trans-unit>
<trans-unit id="9f86714c9a6b74e13c96ab02102ce40c34fe13b9" datatype="html">
@ -2813,7 +2821,7 @@
<target state="translated">Par Secteur</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">131</context>
<context context-type="linenumber">132</context>
</context-group>
</trans-unit>
<trans-unit id="7017e0e26b53ef322c3e3bbf95f06a85487a12b2" datatype="html">
@ -2821,7 +2829,7 @@
<target state="translated">Par Continent</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">155</context>
<context context-type="linenumber">156</context>
</context-group>
</trans-unit>
<trans-unit id="f27e9dd8de80176286e02312e694cb8d1e485a5d" datatype="html">
@ -2829,7 +2837,7 @@
<target state="translated">Par Pays</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">312</context>
<context context-type="linenumber">313</context>
</context-group>
</trans-unit>
<trans-unit id="85780db87ac6c9f202615ac63754551c061e7236" datatype="html">
@ -2837,7 +2845,7 @@
<target state="translated">Régions</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">202</context>
<context context-type="linenumber">203</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -2849,7 +2857,7 @@
<target state="translated">Marchés Développés</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">227</context>
<context context-type="linenumber">228</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -2861,7 +2869,7 @@
<target state="translated">Marchés Émergents</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">236</context>
<context context-type="linenumber">237</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -2873,7 +2881,7 @@
<target state="translated">Autres marchés</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">245</context>
<context context-type="linenumber">246</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -4073,7 +4081,7 @@
<target state="translated">Voir en tant que ...</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">214</context>
<context context-type="linenumber">222</context>
</context-group>
</trans-unit>
<trans-unit id="3c32a07710e402b2c056bd346e7c42f6015334a6" datatype="html">
@ -4081,7 +4089,7 @@
<target state="translated">Supprimer l&apos;Utilisateur</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">224</context>
<context context-type="linenumber">232</context>
</context-group>
</trans-unit>
<trans-unit id="5316879909526485230" datatype="html">
@ -4097,7 +4105,7 @@
<target state="translated">Par Émetteur d&apos;ETF</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">289</context>
<context context-type="linenumber">290</context>
</context-group>
</trans-unit>
<trans-unit id="e0c92dc95e1e0fc33d21b5e2df5ea28a86439d56" datatype="html">
@ -4165,7 +4173,7 @@
<target state="translated">Par Plateforme</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">43</context>
<context context-type="linenumber">44</context>
</context-group>
</trans-unit>
<trans-unit id="dff74da4ffb45a2fd54f31f9db9da66f7012a702" datatype="html">
@ -9797,7 +9805,7 @@
<target state="new">Guides</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/resources-page.html</context>
<context context-type="linenumber">5</context>
<context context-type="linenumber">22</context>
</context-group>
</trans-unit>
<trans-unit id="6edd1a650db2af580ebe746813024c45f1d854b1" datatype="html">
@ -9805,7 +9813,7 @@
<target state="new">Glossary</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/resources-page.html</context>
<context context-type="linenumber">75</context>
<context context-type="linenumber">92</context>
</context-group>
</trans-unit>
<trans-unit id="c2fe62534c65e66f2456e568a8f85ba471e6824b" datatype="html">
@ -9889,7 +9897,7 @@
<target state="new">By Market</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">178</context>
<context context-type="linenumber">179</context>
</context-group>
</trans-unit>
<trans-unit id="2075160647498894947" datatype="html">
@ -9969,7 +9977,7 @@
<target state="new">No data available</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">257</context>
<context context-type="linenumber">258</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -10487,6 +10495,10 @@
<context context-type="sourcefile">apps/client/src/app/pages/faq/faq-page.component.ts</context>
<context context-type="linenumber">48</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/resources-page.component.ts</context>
<context context-type="linenumber">17</context>
</context-group>
</trans-unit>
<trans-unit id="6703761340382395781" datatype="html">
<source>features</source>
@ -11445,7 +11457,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/resources-page.component.ts</context>
<context context-type="linenumber">18</context>
<context context-type="linenumber">19</context>
</context-group>
</trans-unit>
<trans-unit id="a92a0e8a2e70e4a0735b714680629187d2b6f23e" datatype="html">
@ -13761,7 +13773,7 @@
<target state="new">Oops! Could not parse historical data.</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts</context>
<context context-type="linenumber">224</context>
<context context-type="linenumber">223</context>
</context-group>
</trans-unit>
<trans-unit id="297546430113071258" datatype="html">
@ -14633,7 +14645,7 @@
<target state="new">The current market price is</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts</context>
<context context-type="linenumber">318</context>
<context context-type="linenumber">317</context>
</context-group>
</trans-unit>
<trans-unit id="a79d938b5ed20249b4ab6bef86c12633d2f346a0" datatype="html">
@ -14956,6 +14968,30 @@
<context context-type="linenumber">13</context>
</context-group>
</trans-unit>
<trans-unit id="8204176479746810612" datatype="html">
<source>Active</source>
<target state="new">Active</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/holdings/holdings-page.component.ts</context>
<context context-type="linenumber">30</context>
</context-group>
</trans-unit>
<trans-unit id="7860418101283165917" datatype="html">
<source>Closed</source>
<target state="new">Closed</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/holdings/holdings-page.component.ts</context>
<context context-type="linenumber">31</context>
</context-group>
</trans-unit>
<trans-unit id="f2005fa461c06dc2e04d8918bbabedf23604b5b7" datatype="html">
<source>Activity</source>
<target state="new">Activity</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">176</context>
</context-group>
</trans-unit>
</body>
</file>
</xliff>

View File

@ -103,11 +103,15 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">126</context>
<context context-type="linenumber">134</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">269</context>
<context context-type="linenumber">178</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">287</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/activities-page.html</context>
@ -279,11 +283,11 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-platform/admin-platform.component.html</context>
<context context-type="linenumber">97</context>
<context context-type="linenumber">101</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-tag/admin-tag.component.html</context>
<context context-type="linenumber">77</context>
<context context-type="linenumber">81</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/account-balances/account-balances.component.html</context>
@ -329,6 +333,10 @@
<context context-type="sourcefile">apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html</context>
<context context-type="linenumber">34</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">257</context>
</context-group>
</trans-unit>
<trans-unit id="1b6bc6d5daaa6ec75d201690bb6f782f30bf98a0" datatype="html">
<source>Data Source</source>
@ -755,7 +763,7 @@
<target state="translated">Iscrizione</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">88</context>
<context context-type="linenumber">96</context>
</context-group>
</trans-unit>
<trans-unit id="ee6a93295a4311c0968e99a6a8d0521684af361b" datatype="html">
@ -763,7 +771,7 @@
<target state="translated">Partecipazione giornaliera</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">150</context>
<context context-type="linenumber">158</context>
</context-group>
</trans-unit>
<trans-unit id="623f499e6a4ab7f48d7bd483fa49af15713346dd" datatype="html">
@ -771,7 +779,7 @@
<target state="new">Ultima richiesta</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">175</context>
<context context-type="linenumber">183</context>
</context-group>
</trans-unit>
<trans-unit id="68ca4a6d3699c0b1141421f8ca995cb1ed736128" datatype="html">
@ -815,7 +823,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">105</context>
<context context-type="linenumber">113</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/header/header.component.html</context>
@ -827,7 +835,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">294</context>
<context context-type="linenumber">312</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/accounts/accounts-page.html</context>
@ -1167,7 +1175,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/resources-page.html</context>
<context context-type="linenumber">39</context>
<context context-type="linenumber">56</context>
</context-group>
</trans-unit>
<trans-unit id="802222cb4754d74846b18f651b1f94e21576185d" datatype="html">
@ -1211,7 +1219,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/holdings/holdings-page.html</context>
<context context-type="linenumber">23</context>
<context context-type="linenumber">32</context>
</context-group>
</trans-unit>
<trans-unit id="ce718ababbce63d776cf8b1f91412beb4c0a6e04" datatype="html">
@ -1490,7 +1498,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">227</context>
<context context-type="linenumber">226</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -1510,7 +1518,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">239</context>
<context context-type="linenumber">238</context>
</context-group>
</trans-unit>
<trans-unit id="cafc87479686947e2590b9f588a88040aeaf660b" datatype="html">
@ -1522,7 +1530,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">313</context>
<context context-type="linenumber">332</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html</context>
@ -1538,7 +1546,7 @@
<target state="translated">Segnala un&apos;anomalia dei dati</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">332</context>
<context context-type="linenumber">350</context>
</context-group>
</trans-unit>
<trans-unit id="2ee26d58f2707416e636887111d5603b35346c4a" datatype="html">
@ -2210,7 +2218,7 @@
<target state="translated">Per account</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">269</context>
<context context-type="linenumber">270</context>
</context-group>
</trans-unit>
<trans-unit id="b79f5520c0cb9a00bd589e8a4c86ffcf5ae439d7" datatype="html">
@ -2218,7 +2226,7 @@
<target state="translated">Per valuta</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">62</context>
<context context-type="linenumber">63</context>
</context-group>
</trans-unit>
<trans-unit id="8288ff761f2d259625d2e5a3d96db727926d9cd4" datatype="html">
@ -2226,7 +2234,7 @@
<target state="translated">Per classe asset</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">85</context>
<context context-type="linenumber">86</context>
</context-group>
</trans-unit>
<trans-unit id="b64539bb7815eb3275b55ad723d3897fc6ba8d23" datatype="html">
@ -2234,7 +2242,7 @@
<target state="translated">Per partecipazione</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">108</context>
<context context-type="linenumber">109</context>
</context-group>
</trans-unit>
<trans-unit id="9f86714c9a6b74e13c96ab02102ce40c34fe13b9" datatype="html">
@ -2242,7 +2250,7 @@
<target state="translated">Per settore</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">131</context>
<context context-type="linenumber">132</context>
</context-group>
</trans-unit>
<trans-unit id="7017e0e26b53ef322c3e3bbf95f06a85487a12b2" datatype="html">
@ -2250,7 +2258,7 @@
<target state="translated">Per continente</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">155</context>
<context context-type="linenumber">156</context>
</context-group>
</trans-unit>
<trans-unit id="f27e9dd8de80176286e02312e694cb8d1e485a5d" datatype="html">
@ -2258,7 +2266,7 @@
<target state="translated">Per paese</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">312</context>
<context context-type="linenumber">313</context>
</context-group>
</trans-unit>
<trans-unit id="85780db87ac6c9f202615ac63754551c061e7236" datatype="html">
@ -2266,7 +2274,7 @@
<target state="translated">Regioni</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">202</context>
<context context-type="linenumber">203</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -2514,7 +2522,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">182</context>
<context context-type="linenumber">184</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html</context>
@ -2842,7 +2850,7 @@
<target state="translated">Mercati sviluppati</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">227</context>
<context context-type="linenumber">228</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -2866,7 +2874,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">191</context>
<context context-type="linenumber">193</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html</context>
@ -2894,7 +2902,7 @@
<target state="translated">Altri mercati</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">245</context>
<context context-type="linenumber">246</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -2906,7 +2914,7 @@
<target state="translated">Mercati emergenti</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">236</context>
<context context-type="linenumber">237</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -2934,11 +2942,11 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">69</context>
<context context-type="linenumber">77</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">222</context>
<context context-type="linenumber">220</context>
</context-group>
</trans-unit>
<trans-unit id="b1c1c6a43da1ad3e41b7a6e3aa5dcc24226cf580" datatype="html">
@ -4074,7 +4082,7 @@
<target state="translated">Imita l&apos;utente</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">214</context>
<context context-type="linenumber">222</context>
</context-group>
</trans-unit>
<trans-unit id="3c32a07710e402b2c056bd346e7c42f6015334a6" datatype="html">
@ -4082,7 +4090,7 @@
<target state="translated">Elimina l&apos;utente</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">224</context>
<context context-type="linenumber">232</context>
</context-group>
</trans-unit>
<trans-unit id="5316879909526485230" datatype="html">
@ -4098,7 +4106,7 @@
<target state="translated">Per fornitore di ETF</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">289</context>
<context context-type="linenumber">290</context>
</context-group>
</trans-unit>
<trans-unit id="e0c92dc95e1e0fc33d21b5e2df5ea28a86439d56" datatype="html">
@ -4166,7 +4174,7 @@
<target state="translated">Per piattaforma</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">43</context>
<context context-type="linenumber">44</context>
</context-group>
</trans-unit>
<trans-unit id="dff74da4ffb45a2fd54f31f9db9da66f7012a702" datatype="html">
@ -9798,7 +9806,7 @@
<target state="translated">Guide</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/resources-page.html</context>
<context context-type="linenumber">5</context>
<context context-type="linenumber">22</context>
</context-group>
</trans-unit>
<trans-unit id="6edd1a650db2af580ebe746813024c45f1d854b1" datatype="html">
@ -9806,7 +9814,7 @@
<target state="translated">Glossario</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/resources-page.html</context>
<context context-type="linenumber">75</context>
<context context-type="linenumber">92</context>
</context-group>
</trans-unit>
<trans-unit id="c2fe62534c65e66f2456e568a8f85ba471e6824b" datatype="html">
@ -9890,7 +9898,7 @@
<target state="translated">Per mercato</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">178</context>
<context context-type="linenumber">179</context>
</context-group>
</trans-unit>
<trans-unit id="2075160647498894947" datatype="html">
@ -9970,7 +9978,7 @@
<target state="translated">Nessun dato disponibile</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">257</context>
<context context-type="linenumber">258</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -10488,6 +10496,10 @@
<context context-type="sourcefile">apps/client/src/app/pages/faq/faq-page.component.ts</context>
<context context-type="linenumber">48</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/resources-page.component.ts</context>
<context context-type="linenumber">17</context>
</context-group>
</trans-unit>
<trans-unit id="6703761340382395781" datatype="html">
<source>features</source>
@ -11446,7 +11458,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/resources-page.component.ts</context>
<context context-type="linenumber">18</context>
<context context-type="linenumber">19</context>
</context-group>
</trans-unit>
<trans-unit id="a92a0e8a2e70e4a0735b714680629187d2b6f23e" datatype="html">
@ -13762,7 +13774,7 @@
<target state="new">Oops! Could not parse historical data.</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts</context>
<context context-type="linenumber">224</context>
<context context-type="linenumber">223</context>
</context-group>
</trans-unit>
<trans-unit id="297546430113071258" datatype="html">
@ -14634,7 +14646,7 @@
<target state="new">The current market price is</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts</context>
<context context-type="linenumber">318</context>
<context context-type="linenumber">317</context>
</context-group>
</trans-unit>
<trans-unit id="a79d938b5ed20249b4ab6bef86c12633d2f346a0" datatype="html">
@ -14957,6 +14969,30 @@
<context context-type="linenumber">13</context>
</context-group>
</trans-unit>
<trans-unit id="8204176479746810612" datatype="html">
<source>Active</source>
<target state="new">Active</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/holdings/holdings-page.component.ts</context>
<context context-type="linenumber">30</context>
</context-group>
</trans-unit>
<trans-unit id="7860418101283165917" datatype="html">
<source>Closed</source>
<target state="new">Closed</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/holdings/holdings-page.component.ts</context>
<context context-type="linenumber">31</context>
</context-group>
</trans-unit>
<trans-unit id="f2005fa461c06dc2e04d8918bbabedf23604b5b7" datatype="html">
<source>Activity</source>
<target state="new">Activity</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">176</context>
</context-group>
</trans-unit>
</body>
</file>
</xliff>

View File

@ -102,11 +102,15 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">126</context>
<context context-type="linenumber">134</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">269</context>
<context context-type="linenumber">178</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">287</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/activities-page.html</context>
@ -278,11 +282,11 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-platform/admin-platform.component.html</context>
<context context-type="linenumber">97</context>
<context context-type="linenumber">101</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-tag/admin-tag.component.html</context>
<context context-type="linenumber">77</context>
<context context-type="linenumber">81</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/account-balances/account-balances.component.html</context>
@ -328,6 +332,10 @@
<context context-type="sourcefile">apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html</context>
<context context-type="linenumber">34</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">257</context>
</context-group>
</trans-unit>
<trans-unit id="1b6bc6d5daaa6ec75d201690bb6f782f30bf98a0" datatype="html">
<source>Data Source</source>
@ -754,7 +762,7 @@
<target state="translated">Registratie</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">88</context>
<context context-type="linenumber">96</context>
</context-group>
</trans-unit>
<trans-unit id="ee6a93295a4311c0968e99a6a8d0521684af361b" datatype="html">
@ -762,7 +770,7 @@
<target state="translated">Betrokkenheid per dag</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">150</context>
<context context-type="linenumber">158</context>
</context-group>
</trans-unit>
<trans-unit id="623f499e6a4ab7f48d7bd483fa49af15713346dd" datatype="html">
@ -770,7 +778,7 @@
<target state="new">Laatste verzoek</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">175</context>
<context context-type="linenumber">183</context>
</context-group>
</trans-unit>
<trans-unit id="68ca4a6d3699c0b1141421f8ca995cb1ed736128" datatype="html">
@ -814,7 +822,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">105</context>
<context context-type="linenumber">113</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/header/header.component.html</context>
@ -826,7 +834,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">294</context>
<context context-type="linenumber">312</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/accounts/accounts-page.html</context>
@ -1166,7 +1174,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/resources-page.html</context>
<context context-type="linenumber">39</context>
<context context-type="linenumber">56</context>
</context-group>
</trans-unit>
<trans-unit id="802222cb4754d74846b18f651b1f94e21576185d" datatype="html">
@ -1210,7 +1218,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/holdings/holdings-page.html</context>
<context context-type="linenumber">23</context>
<context context-type="linenumber">32</context>
</context-group>
</trans-unit>
<trans-unit id="ce718ababbce63d776cf8b1f91412beb4c0a6e04" datatype="html">
@ -1489,7 +1497,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">227</context>
<context context-type="linenumber">226</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -1509,7 +1517,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">239</context>
<context context-type="linenumber">238</context>
</context-group>
</trans-unit>
<trans-unit id="cafc87479686947e2590b9f588a88040aeaf660b" datatype="html">
@ -1521,7 +1529,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">313</context>
<context context-type="linenumber">332</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html</context>
@ -1537,7 +1545,7 @@
<target state="translated">Gegevensstoring melden</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">332</context>
<context context-type="linenumber">350</context>
</context-group>
</trans-unit>
<trans-unit id="2ee26d58f2707416e636887111d5603b35346c4a" datatype="html">
@ -2209,7 +2217,7 @@
<target state="translated">Per rekening</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">269</context>
<context context-type="linenumber">270</context>
</context-group>
</trans-unit>
<trans-unit id="b79f5520c0cb9a00bd589e8a4c86ffcf5ae439d7" datatype="html">
@ -2217,7 +2225,7 @@
<target state="translated">Per valuta</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">62</context>
<context context-type="linenumber">63</context>
</context-group>
</trans-unit>
<trans-unit id="8288ff761f2d259625d2e5a3d96db727926d9cd4" datatype="html">
@ -2225,7 +2233,7 @@
<target state="translated">Per asset klasse</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">85</context>
<context context-type="linenumber">86</context>
</context-group>
</trans-unit>
<trans-unit id="b64539bb7815eb3275b55ad723d3897fc6ba8d23" datatype="html">
@ -2233,7 +2241,7 @@
<target state="translated">Per positie</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">108</context>
<context context-type="linenumber">109</context>
</context-group>
</trans-unit>
<trans-unit id="9f86714c9a6b74e13c96ab02102ce40c34fe13b9" datatype="html">
@ -2241,7 +2249,7 @@
<target state="translated">Per sector</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">131</context>
<context context-type="linenumber">132</context>
</context-group>
</trans-unit>
<trans-unit id="7017e0e26b53ef322c3e3bbf95f06a85487a12b2" datatype="html">
@ -2249,7 +2257,7 @@
<target state="translated">Per continent</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">155</context>
<context context-type="linenumber">156</context>
</context-group>
</trans-unit>
<trans-unit id="f27e9dd8de80176286e02312e694cb8d1e485a5d" datatype="html">
@ -2257,7 +2265,7 @@
<target state="translated">Per land</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">312</context>
<context context-type="linenumber">313</context>
</context-group>
</trans-unit>
<trans-unit id="85780db87ac6c9f202615ac63754551c061e7236" datatype="html">
@ -2265,7 +2273,7 @@
<target state="translated">Regio&apos;s</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">202</context>
<context context-type="linenumber">203</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -2513,7 +2521,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">182</context>
<context context-type="linenumber">184</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html</context>
@ -2841,7 +2849,7 @@
<target state="translated">Ontwikkelde markten</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">227</context>
<context context-type="linenumber">228</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -2865,7 +2873,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">191</context>
<context context-type="linenumber">193</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html</context>
@ -2893,7 +2901,7 @@
<target state="translated">Andere markten</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">245</context>
<context context-type="linenumber">246</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -2905,7 +2913,7 @@
<target state="translated">Opkomende markten</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">236</context>
<context context-type="linenumber">237</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -2933,11 +2941,11 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">69</context>
<context context-type="linenumber">77</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">222</context>
<context context-type="linenumber">220</context>
</context-group>
</trans-unit>
<trans-unit id="b1c1c6a43da1ad3e41b7a6e3aa5dcc24226cf580" datatype="html">
@ -4073,7 +4081,7 @@
<target state="translated">Gebruiker nadoen</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">214</context>
<context context-type="linenumber">222</context>
</context-group>
</trans-unit>
<trans-unit id="3c32a07710e402b2c056bd346e7c42f6015334a6" datatype="html">
@ -4081,7 +4089,7 @@
<target state="translated">Gebruiker verwijderen</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">224</context>
<context context-type="linenumber">232</context>
</context-group>
</trans-unit>
<trans-unit id="5316879909526485230" datatype="html">
@ -4097,7 +4105,7 @@
<target state="translated">Per ETF-aanbieder</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">289</context>
<context context-type="linenumber">290</context>
</context-group>
</trans-unit>
<trans-unit id="e0c92dc95e1e0fc33d21b5e2df5ea28a86439d56" datatype="html">
@ -4165,7 +4173,7 @@
<target state="translated">Per platform</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">43</context>
<context context-type="linenumber">44</context>
</context-group>
</trans-unit>
<trans-unit id="dff74da4ffb45a2fd54f31f9db9da66f7012a702" datatype="html">
@ -9797,7 +9805,7 @@
<target state="translated">Gidsen</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/resources-page.html</context>
<context context-type="linenumber">5</context>
<context context-type="linenumber">22</context>
</context-group>
</trans-unit>
<trans-unit id="6edd1a650db2af580ebe746813024c45f1d854b1" datatype="html">
@ -9805,7 +9813,7 @@
<target state="translated">Woordenlijst</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/resources-page.html</context>
<context context-type="linenumber">75</context>
<context context-type="linenumber">92</context>
</context-group>
</trans-unit>
<trans-unit id="c2fe62534c65e66f2456e568a8f85ba471e6824b" datatype="html">
@ -9889,7 +9897,7 @@
<target state="translated">Per markt</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">178</context>
<context context-type="linenumber">179</context>
</context-group>
</trans-unit>
<trans-unit id="2075160647498894947" datatype="html">
@ -9969,7 +9977,7 @@
<target state="translated">Geen data beschikbaar</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">257</context>
<context context-type="linenumber">258</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -10487,6 +10495,10 @@
<context context-type="sourcefile">apps/client/src/app/pages/faq/faq-page.component.ts</context>
<context context-type="linenumber">48</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/resources-page.component.ts</context>
<context context-type="linenumber">17</context>
</context-group>
</trans-unit>
<trans-unit id="6703761340382395781" datatype="html">
<source>features</source>
@ -11445,7 +11457,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/resources-page.component.ts</context>
<context context-type="linenumber">18</context>
<context context-type="linenumber">19</context>
</context-group>
</trans-unit>
<trans-unit id="a92a0e8a2e70e4a0735b714680629187d2b6f23e" datatype="html">
@ -13761,7 +13773,7 @@
<target state="new">Oops! Could not parse historical data.</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts</context>
<context context-type="linenumber">224</context>
<context context-type="linenumber">223</context>
</context-group>
</trans-unit>
<trans-unit id="297546430113071258" datatype="html">
@ -14633,7 +14645,7 @@
<target state="new">The current market price is</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts</context>
<context context-type="linenumber">318</context>
<context context-type="linenumber">317</context>
</context-group>
</trans-unit>
<trans-unit id="a79d938b5ed20249b4ab6bef86c12633d2f346a0" datatype="html">
@ -14956,6 +14968,30 @@
<context context-type="linenumber">13</context>
</context-group>
</trans-unit>
<trans-unit id="8204176479746810612" datatype="html">
<source>Active</source>
<target state="new">Active</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/holdings/holdings-page.component.ts</context>
<context context-type="linenumber">30</context>
</context-group>
</trans-unit>
<trans-unit id="7860418101283165917" datatype="html">
<source>Closed</source>
<target state="new">Closed</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/holdings/holdings-page.component.ts</context>
<context context-type="linenumber">31</context>
</context-group>
</trans-unit>
<trans-unit id="f2005fa461c06dc2e04d8918bbabedf23604b5b7" datatype="html">
<source>Activity</source>
<target state="new">Activity</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">176</context>
</context-group>
</trans-unit>
</body>
</file>
</xliff>

View File

@ -308,6 +308,10 @@
<context context-type="sourcefile">apps/client/src/app/pages/faq/faq-page.component.ts</context>
<context context-type="linenumber">48</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/resources-page.component.ts</context>
<context context-type="linenumber">17</context>
</context-group>
</trans-unit>
<trans-unit id="6703761340382395781" datatype="html">
<source>features</source>
@ -986,7 +990,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/resources-page.component.ts</context>
<context context-type="linenumber">18</context>
<context context-type="linenumber">19</context>
</context-group>
</trans-unit>
<trans-unit id="1c0638816928ae45284e60504936ca985960df5c" datatype="html">
@ -1038,7 +1042,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/resources-page.html</context>
<context context-type="linenumber">39</context>
<context context-type="linenumber">56</context>
</context-group>
</trans-unit>
<trans-unit id="452ef1b96854fe05618303ee601f8fed3b866c9f" datatype="html">
@ -1610,11 +1614,15 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">126</context>
<context context-type="linenumber">134</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">269</context>
<context context-type="linenumber">178</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">287</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/activities-page.html</context>
@ -1842,11 +1850,11 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-platform/admin-platform.component.html</context>
<context context-type="linenumber">97</context>
<context context-type="linenumber">101</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-tag/admin-tag.component.html</context>
<context context-type="linenumber">77</context>
<context context-type="linenumber">81</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/account-balances/account-balances.component.html</context>
@ -1900,6 +1908,10 @@
<context context-type="sourcefile">apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html</context>
<context context-type="linenumber">34</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">257</context>
</context-group>
</trans-unit>
<trans-unit id="1b6bc6d5daaa6ec75d201690bb6f782f30bf98a0" datatype="html">
<source>Data Source</source>
@ -2158,7 +2170,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">182</context>
<context context-type="linenumber">184</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html</context>
@ -2182,7 +2194,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">191</context>
<context context-type="linenumber">193</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html</context>
@ -2278,7 +2290,7 @@
<target state="new">Oops! Could not parse historical data.</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts</context>
<context context-type="linenumber">224</context>
<context context-type="linenumber">223</context>
</context-group>
</trans-unit>
<trans-unit id="c8d1785038d461ec66b5799db21864182b35900a" datatype="html">
@ -2334,11 +2346,11 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">69</context>
<context context-type="linenumber">77</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">222</context>
<context context-type="linenumber">220</context>
</context-group>
</trans-unit>
<trans-unit id="fc61416d48adb7af122b8697e806077eb251fb57" datatype="html">
@ -2354,7 +2366,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">227</context>
<context context-type="linenumber">226</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -2374,7 +2386,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">239</context>
<context context-type="linenumber">238</context>
</context-group>
</trans-unit>
<trans-unit id="0b05507801c7eca260d8978c36621e826f07aaaa" datatype="html">
@ -2642,7 +2654,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">105</context>
<context context-type="linenumber">113</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/header/header.component.html</context>
@ -2654,7 +2666,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">294</context>
<context context-type="linenumber">312</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/accounts/accounts-page.html</context>
@ -2706,7 +2718,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">313</context>
<context context-type="linenumber">332</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html</context>
@ -2770,7 +2782,7 @@
<target state="new">Registration</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">88</context>
<context context-type="linenumber">96</context>
</context-group>
</trans-unit>
<trans-unit id="ee6a93295a4311c0968e99a6a8d0521684af361b" datatype="html">
@ -2778,7 +2790,7 @@
<target state="new">Engagement per Day</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">150</context>
<context context-type="linenumber">158</context>
</context-group>
</trans-unit>
<trans-unit id="623f499e6a4ab7f48d7bd483fa49af15713346dd" datatype="html">
@ -2786,7 +2798,7 @@
<target state="new"> Last Request </target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">175</context>
<context context-type="linenumber">183</context>
</context-group>
</trans-unit>
<trans-unit id="f8ff0eb5c040edbffded4b792c0ba85d3b12fe1a" datatype="html">
@ -2794,7 +2806,7 @@
<target state="new">Impersonate User</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">214</context>
<context context-type="linenumber">222</context>
</context-group>
</trans-unit>
<trans-unit id="3c32a07710e402b2c056bd346e7c42f6015334a6" datatype="html">
@ -2802,7 +2814,7 @@
<target state="new">Delete User</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">224</context>
<context context-type="linenumber">232</context>
</context-group>
</trans-unit>
<trans-unit id="3cc9c2ae277393b3946b38c088dabff671b1ee1b" datatype="html">
@ -2986,7 +2998,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/holdings/holdings-page.html</context>
<context context-type="linenumber">23</context>
<context context-type="linenumber">32</context>
</context-group>
</trans-unit>
<trans-unit id="5486880308148746399" datatype="html">
@ -3504,7 +3516,7 @@
<target state="new">Report Data Glitch</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">332</context>
<context context-type="linenumber">350</context>
</context-group>
</trans-unit>
<trans-unit id="280c5b1f5b5b748fbbb37bf7a12c37f41539c1ff" datatype="html">
@ -5208,7 +5220,7 @@
<target state="new">By Platform</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">43</context>
<context context-type="linenumber">44</context>
</context-group>
</trans-unit>
<trans-unit id="b79f5520c0cb9a00bd589e8a4c86ffcf5ae439d7" datatype="html">
@ -5216,7 +5228,7 @@
<target state="new">By Currency</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">62</context>
<context context-type="linenumber">63</context>
</context-group>
</trans-unit>
<trans-unit id="8288ff761f2d259625d2e5a3d96db727926d9cd4" datatype="html">
@ -5224,7 +5236,7 @@
<target state="new">By Asset Class</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">85</context>
<context context-type="linenumber">86</context>
</context-group>
</trans-unit>
<trans-unit id="b64539bb7815eb3275b55ad723d3897fc6ba8d23" datatype="html">
@ -5232,7 +5244,7 @@
<target state="new">By Holding</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">108</context>
<context context-type="linenumber">109</context>
</context-group>
</trans-unit>
<trans-unit id="9f86714c9a6b74e13c96ab02102ce40c34fe13b9" datatype="html">
@ -5240,7 +5252,7 @@
<target state="new">By Sector</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">131</context>
<context context-type="linenumber">132</context>
</context-group>
</trans-unit>
<trans-unit id="7017e0e26b53ef322c3e3bbf95f06a85487a12b2" datatype="html">
@ -5248,7 +5260,7 @@
<target state="new">By Continent</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">155</context>
<context context-type="linenumber">156</context>
</context-group>
</trans-unit>
<trans-unit id="834807cba8928b6f8b27ea62c886f7f3715079b0" datatype="html">
@ -5256,7 +5268,7 @@
<target state="new">By Market</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">178</context>
<context context-type="linenumber">179</context>
</context-group>
</trans-unit>
<trans-unit id="85780db87ac6c9f202615ac63754551c061e7236" datatype="html">
@ -5264,7 +5276,7 @@
<target state="new">Regions</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">202</context>
<context context-type="linenumber">203</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -5276,7 +5288,7 @@
<target state="new">Developed Markets</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">227</context>
<context context-type="linenumber">228</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -5288,7 +5300,7 @@
<target state="new">Emerging Markets</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">236</context>
<context context-type="linenumber">237</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -5300,7 +5312,7 @@
<target state="new">Other Markets</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">245</context>
<context context-type="linenumber">246</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -5312,7 +5324,7 @@
<target state="new">No data available</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">257</context>
<context context-type="linenumber">258</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -5324,7 +5336,7 @@
<target state="new">By Account</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">269</context>
<context context-type="linenumber">270</context>
</context-group>
</trans-unit>
<trans-unit id="166ccc92e1aa598f9056a260be209a0bab64d37a" datatype="html">
@ -5332,7 +5344,7 @@
<target state="new">By ETF Provider</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">289</context>
<context context-type="linenumber">290</context>
</context-group>
</trans-unit>
<trans-unit id="f27e9dd8de80176286e02312e694cb8d1e485a5d" datatype="html">
@ -5340,7 +5352,7 @@
<target state="new">By Country</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">312</context>
<context context-type="linenumber">313</context>
</context-group>
</trans-unit>
<trans-unit id="2948175671993825247" datatype="html">
@ -13044,7 +13056,7 @@
<target state="new">Guides</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/resources-page.html</context>
<context context-type="linenumber">5</context>
<context context-type="linenumber">22</context>
</context-group>
</trans-unit>
<trans-unit id="6edd1a650db2af580ebe746813024c45f1d854b1" datatype="html">
@ -13052,7 +13064,7 @@
<target state="new">Glossary</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/resources-page.html</context>
<context context-type="linenumber">75</context>
<context context-type="linenumber">92</context>
</context-group>
</trans-unit>
<trans-unit id="3737711445155929474" datatype="html">
@ -14636,7 +14648,7 @@
<target state="new">The current market price is</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts</context>
<context context-type="linenumber">318</context>
<context context-type="linenumber">317</context>
</context-group>
</trans-unit>
<trans-unit id="a79d938b5ed20249b4ab6bef86c12633d2f346a0" datatype="html">
@ -14959,6 +14971,30 @@
<context context-type="linenumber">13</context>
</context-group>
</trans-unit>
<trans-unit id="8204176479746810612" datatype="html">
<source>Active</source>
<target state="new">Active</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/holdings/holdings-page.component.ts</context>
<context context-type="linenumber">30</context>
</context-group>
</trans-unit>
<trans-unit id="7860418101283165917" datatype="html">
<source>Closed</source>
<target state="new">Closed</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/holdings/holdings-page.component.ts</context>
<context context-type="linenumber">31</context>
</context-group>
</trans-unit>
<trans-unit id="f2005fa461c06dc2e04d8918bbabedf23604b5b7" datatype="html">
<source>Activity</source>
<target state="new">Activity</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">176</context>
</context-group>
</trans-unit>
</body>
</file>
</xliff>

View File

@ -114,11 +114,15 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">126</context>
<context context-type="linenumber">134</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">269</context>
<context context-type="linenumber">178</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">287</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/activities-page.html</context>
@ -334,11 +338,11 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-platform/admin-platform.component.html</context>
<context context-type="linenumber">97</context>
<context context-type="linenumber">101</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-tag/admin-tag.component.html</context>
<context context-type="linenumber">77</context>
<context context-type="linenumber">81</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/account-balances/account-balances.component.html</context>
@ -376,6 +380,10 @@
<context context-type="sourcefile">apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html</context>
<context context-type="linenumber">34</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">257</context>
</context-group>
</trans-unit>
<trans-unit id="1b6bc6d5daaa6ec75d201690bb6f782f30bf98a0" datatype="html">
<source>Data Source</source>
@ -618,7 +626,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">182</context>
<context context-type="linenumber">184</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html</context>
@ -642,7 +650,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">191</context>
<context context-type="linenumber">193</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html</context>
@ -882,7 +890,7 @@
<target state="translated">Registo</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">88</context>
<context context-type="linenumber">96</context>
</context-group>
</trans-unit>
<trans-unit id="4fe84c1d0eef5726c017f64c691145db7a61f879" datatype="html">
@ -894,7 +902,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">105</context>
<context context-type="linenumber">113</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/header/header.component.html</context>
@ -906,7 +914,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">294</context>
<context context-type="linenumber">312</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/accounts/accounts-page.html</context>
@ -922,7 +930,7 @@
<target state="translated">Envolvimento por Dia</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">150</context>
<context context-type="linenumber">158</context>
</context-group>
</trans-unit>
<trans-unit id="623f499e6a4ab7f48d7bd483fa49af15713346dd" datatype="html">
@ -930,7 +938,7 @@
<target state="new"> Último Pedido </target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">175</context>
<context context-type="linenumber">183</context>
</context-group>
</trans-unit>
<trans-unit id="3cc9c2ae277393b3946b38c088dabff671b1ee1b" datatype="html">
@ -1338,7 +1346,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/resources-page.html</context>
<context context-type="linenumber">39</context>
<context context-type="linenumber">56</context>
</context-group>
</trans-unit>
<trans-unit id="287d3301a32a65a1b31116bda5d3a6463158c42a" datatype="html">
@ -1390,7 +1398,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/holdings/holdings-page.html</context>
<context context-type="linenumber">23</context>
<context context-type="linenumber">32</context>
</context-group>
</trans-unit>
<trans-unit id="5486880308148746399" datatype="html">
@ -1793,11 +1801,11 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">69</context>
<context context-type="linenumber">77</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">222</context>
<context context-type="linenumber">220</context>
</context-group>
</trans-unit>
<trans-unit id="fc61416d48adb7af122b8697e806077eb251fb57" datatype="html">
@ -1813,7 +1821,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">227</context>
<context context-type="linenumber">226</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -1833,7 +1841,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">239</context>
<context context-type="linenumber">238</context>
</context-group>
</trans-unit>
<trans-unit id="cafc87479686947e2590b9f588a88040aeaf660b" datatype="html">
@ -1845,7 +1853,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">313</context>
<context context-type="linenumber">332</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html</context>
@ -1861,7 +1869,7 @@
<target state="translated">Dados do Relatório com Problema</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">332</context>
<context context-type="linenumber">350</context>
</context-group>
</trans-unit>
<trans-unit id="2ee26d58f2707416e636887111d5603b35346c4a" datatype="html">
@ -2681,7 +2689,7 @@
<target state="translated">Por Conta</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">269</context>
<context context-type="linenumber">270</context>
</context-group>
</trans-unit>
<trans-unit id="b79f5520c0cb9a00bd589e8a4c86ffcf5ae439d7" datatype="html">
@ -2689,7 +2697,7 @@
<target state="translated">Por Moeda</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">62</context>
<context context-type="linenumber">63</context>
</context-group>
</trans-unit>
<trans-unit id="8288ff761f2d259625d2e5a3d96db727926d9cd4" datatype="html">
@ -2697,7 +2705,7 @@
<target state="translated">Por Classe de Ativo</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">85</context>
<context context-type="linenumber">86</context>
</context-group>
</trans-unit>
<trans-unit id="b64539bb7815eb3275b55ad723d3897fc6ba8d23" datatype="html">
@ -2705,7 +2713,7 @@
<target state="translated">Por Posse</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">108</context>
<context context-type="linenumber">109</context>
</context-group>
</trans-unit>
<trans-unit id="9f86714c9a6b74e13c96ab02102ce40c34fe13b9" datatype="html">
@ -2713,7 +2721,7 @@
<target state="translated">Por Setor</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">131</context>
<context context-type="linenumber">132</context>
</context-group>
</trans-unit>
<trans-unit id="7017e0e26b53ef322c3e3bbf95f06a85487a12b2" datatype="html">
@ -2721,7 +2729,7 @@
<target state="translated">Por Continente</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">155</context>
<context context-type="linenumber">156</context>
</context-group>
</trans-unit>
<trans-unit id="f27e9dd8de80176286e02312e694cb8d1e485a5d" datatype="html">
@ -2729,7 +2737,7 @@
<target state="translated">Por País</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">312</context>
<context context-type="linenumber">313</context>
</context-group>
</trans-unit>
<trans-unit id="85780db87ac6c9f202615ac63754551c061e7236" datatype="html">
@ -2737,7 +2745,7 @@
<target state="translated">Regiões</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">202</context>
<context context-type="linenumber">203</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -2749,7 +2757,7 @@
<target state="translated">Mercados Desenvoldidos</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">227</context>
<context context-type="linenumber">228</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -2761,7 +2769,7 @@
<target state="translated">Mercados Emergentes</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">236</context>
<context context-type="linenumber">237</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -2773,7 +2781,7 @@
<target state="translated">Outros Mercados</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">245</context>
<context context-type="linenumber">246</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -4073,7 +4081,7 @@
<target state="translated">Personificar Utilizador</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">214</context>
<context context-type="linenumber">222</context>
</context-group>
</trans-unit>
<trans-unit id="3c32a07710e402b2c056bd346e7c42f6015334a6" datatype="html">
@ -4081,7 +4089,7 @@
<target state="translated">Apagar Utilizador</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">224</context>
<context context-type="linenumber">232</context>
</context-group>
</trans-unit>
<trans-unit id="5316879909526485230" datatype="html">
@ -4097,7 +4105,7 @@
<target state="translated">Por Prestador de ETF</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">289</context>
<context context-type="linenumber">290</context>
</context-group>
</trans-unit>
<trans-unit id="e0c92dc95e1e0fc33d21b5e2df5ea28a86439d56" datatype="html">
@ -4165,7 +4173,7 @@
<target state="translated">Por Plataforma</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">43</context>
<context context-type="linenumber">44</context>
</context-group>
</trans-unit>
<trans-unit id="dff74da4ffb45a2fd54f31f9db9da66f7012a702" datatype="html">
@ -9797,7 +9805,7 @@
<target state="new">Guides</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/resources-page.html</context>
<context context-type="linenumber">5</context>
<context context-type="linenumber">22</context>
</context-group>
</trans-unit>
<trans-unit id="6edd1a650db2af580ebe746813024c45f1d854b1" datatype="html">
@ -9805,7 +9813,7 @@
<target state="new">Glossary</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/resources-page.html</context>
<context context-type="linenumber">75</context>
<context context-type="linenumber">92</context>
</context-group>
</trans-unit>
<trans-unit id="c2fe62534c65e66f2456e568a8f85ba471e6824b" datatype="html">
@ -9889,7 +9897,7 @@
<target state="new">By Market</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">178</context>
<context context-type="linenumber">179</context>
</context-group>
</trans-unit>
<trans-unit id="2075160647498894947" datatype="html">
@ -9969,7 +9977,7 @@
<target state="new">No data available</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">257</context>
<context context-type="linenumber">258</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -10487,6 +10495,10 @@
<context context-type="sourcefile">apps/client/src/app/pages/faq/faq-page.component.ts</context>
<context context-type="linenumber">48</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/resources-page.component.ts</context>
<context context-type="linenumber">17</context>
</context-group>
</trans-unit>
<trans-unit id="6703761340382395781" datatype="html">
<source>features</source>
@ -11445,7 +11457,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/resources-page.component.ts</context>
<context context-type="linenumber">18</context>
<context context-type="linenumber">19</context>
</context-group>
</trans-unit>
<trans-unit id="a92a0e8a2e70e4a0735b714680629187d2b6f23e" datatype="html">
@ -13761,7 +13773,7 @@
<target state="new">Oops! Could not parse historical data.</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts</context>
<context context-type="linenumber">224</context>
<context context-type="linenumber">223</context>
</context-group>
</trans-unit>
<trans-unit id="297546430113071258" datatype="html">
@ -14633,7 +14645,7 @@
<target state="new">The current market price is</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts</context>
<context context-type="linenumber">318</context>
<context context-type="linenumber">317</context>
</context-group>
</trans-unit>
<trans-unit id="a79d938b5ed20249b4ab6bef86c12633d2f346a0" datatype="html">
@ -14956,6 +14968,30 @@
<context context-type="linenumber">13</context>
</context-group>
</trans-unit>
<trans-unit id="8204176479746810612" datatype="html">
<source>Active</source>
<target state="new">Active</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/holdings/holdings-page.component.ts</context>
<context context-type="linenumber">30</context>
</context-group>
</trans-unit>
<trans-unit id="7860418101283165917" datatype="html">
<source>Closed</source>
<target state="new">Closed</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/holdings/holdings-page.component.ts</context>
<context context-type="linenumber">31</context>
</context-group>
</trans-unit>
<trans-unit id="f2005fa461c06dc2e04d8918bbabedf23604b5b7" datatype="html">
<source>Activity</source>
<target state="new">Activity</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">176</context>
</context-group>
</trans-unit>
</body>
</file>
</xliff>

View File

@ -308,6 +308,10 @@
<context context-type="sourcefile">apps/client/src/app/pages/faq/faq-page.component.ts</context>
<context context-type="linenumber">48</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/resources-page.component.ts</context>
<context context-type="linenumber">17</context>
</context-group>
</trans-unit>
<trans-unit id="6703761340382395781" datatype="html">
<source>features</source>
@ -986,7 +990,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/resources-page.component.ts</context>
<context context-type="linenumber">18</context>
<context context-type="linenumber">19</context>
</context-group>
</trans-unit>
<trans-unit id="41d338980f469b334618a07e799b4aa40fcf4834" datatype="html">
@ -1014,7 +1018,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/resources-page.html</context>
<context context-type="linenumber">39</context>
<context context-type="linenumber">56</context>
</context-group>
</trans-unit>
<trans-unit id="452ef1b96854fe05618303ee601f8fed3b866c9f" datatype="html">
@ -1602,11 +1606,15 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">126</context>
<context context-type="linenumber">134</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">269</context>
<context context-type="linenumber">178</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">287</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/activities-page.html</context>
@ -1806,11 +1814,11 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-platform/admin-platform.component.html</context>
<context context-type="linenumber">97</context>
<context context-type="linenumber">101</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-tag/admin-tag.component.html</context>
<context context-type="linenumber">77</context>
<context context-type="linenumber">81</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/account-balances/account-balances.component.html</context>
@ -1848,6 +1856,10 @@
<context context-type="sourcefile">apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html</context>
<context context-type="linenumber">34</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">257</context>
</context-group>
</trans-unit>
<trans-unit id="1b6bc6d5daaa6ec75d201690bb6f782f30bf98a0" datatype="html">
<source>Data Source</source>
@ -2114,7 +2126,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">182</context>
<context context-type="linenumber">184</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html</context>
@ -2138,7 +2150,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">191</context>
<context context-type="linenumber">193</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html</context>
@ -2266,11 +2278,11 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">69</context>
<context context-type="linenumber">77</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">222</context>
<context context-type="linenumber">220</context>
</context-group>
</trans-unit>
<trans-unit id="fc61416d48adb7af122b8697e806077eb251fb57" datatype="html">
@ -2286,7 +2298,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">227</context>
<context context-type="linenumber">226</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -2306,7 +2318,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">239</context>
<context context-type="linenumber">238</context>
</context-group>
</trans-unit>
<trans-unit id="638bbddabc5883a7a4087f45592944ce6558409c" datatype="html">
@ -2450,7 +2462,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">313</context>
<context context-type="linenumber">332</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html</context>
@ -2554,7 +2566,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">105</context>
<context context-type="linenumber">113</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/header/header.component.html</context>
@ -2566,7 +2578,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">294</context>
<context context-type="linenumber">312</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/accounts/accounts-page.html</context>
@ -2630,7 +2642,7 @@
<target state="translated">Kayıt</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">88</context>
<context context-type="linenumber">96</context>
</context-group>
</trans-unit>
<trans-unit id="ee6a93295a4311c0968e99a6a8d0521684af361b" datatype="html">
@ -2638,7 +2650,7 @@
<target state="translated">Günlük etkileşim</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">150</context>
<context context-type="linenumber">158</context>
</context-group>
</trans-unit>
<trans-unit id="623f499e6a4ab7f48d7bd483fa49af15713346dd" datatype="html">
@ -2646,7 +2658,7 @@
<target state="translated"> Son Talep </target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">175</context>
<context context-type="linenumber">183</context>
</context-group>
</trans-unit>
<trans-unit id="f8ff0eb5c040edbffded4b792c0ba85d3b12fe1a" datatype="html">
@ -2654,7 +2666,7 @@
<target state="translated">Kullanıcıyı Taklit Et</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">214</context>
<context context-type="linenumber">222</context>
</context-group>
</trans-unit>
<trans-unit id="3c32a07710e402b2c056bd346e7c42f6015334a6" datatype="html">
@ -2662,7 +2674,7 @@
<target state="translated">Kullanıcıyı Sil</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">224</context>
<context context-type="linenumber">232</context>
</context-group>
</trans-unit>
<trans-unit id="3cc9c2ae277393b3946b38c088dabff671b1ee1b" datatype="html">
@ -2838,7 +2850,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/holdings/holdings-page.html</context>
<context context-type="linenumber">23</context>
<context context-type="linenumber">32</context>
</context-group>
</trans-unit>
<trans-unit id="5486880308148746399" datatype="html">
@ -3345,7 +3357,7 @@
<target state="translated">Rapor Veri Sorunu</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">332</context>
<context context-type="linenumber">350</context>
</context-group>
</trans-unit>
<trans-unit id="280c5b1f5b5b748fbbb37bf7a12c37f41539c1ff" datatype="html">
@ -4685,7 +4697,7 @@
<target state="translated">Platforma Göre</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">43</context>
<context context-type="linenumber">44</context>
</context-group>
</trans-unit>
<trans-unit id="b79f5520c0cb9a00bd589e8a4c86ffcf5ae439d7" datatype="html">
@ -4693,7 +4705,7 @@
<target state="translated">Para Birimine Göre</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">62</context>
<context context-type="linenumber">63</context>
</context-group>
</trans-unit>
<trans-unit id="8288ff761f2d259625d2e5a3d96db727926d9cd4" datatype="html">
@ -4701,7 +4713,7 @@
<target state="translated">Varlık Sınıfına Göre</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">85</context>
<context context-type="linenumber">86</context>
</context-group>
</trans-unit>
<trans-unit id="b64539bb7815eb3275b55ad723d3897fc6ba8d23" datatype="html">
@ -4709,7 +4721,7 @@
<target state="translated">Varlığa Göre</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">108</context>
<context context-type="linenumber">109</context>
</context-group>
</trans-unit>
<trans-unit id="9f86714c9a6b74e13c96ab02102ce40c34fe13b9" datatype="html">
@ -4717,7 +4729,7 @@
<target state="translated">Sektöre Göre</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">131</context>
<context context-type="linenumber">132</context>
</context-group>
</trans-unit>
<trans-unit id="7017e0e26b53ef322c3e3bbf95f06a85487a12b2" datatype="html">
@ -4725,7 +4737,7 @@
<target state="translated">Kıtaya Göre</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">155</context>
<context context-type="linenumber">156</context>
</context-group>
</trans-unit>
<trans-unit id="834807cba8928b6f8b27ea62c886f7f3715079b0" datatype="html">
@ -4733,7 +4745,7 @@
<target state="translated">Piyasaya Göre</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">178</context>
<context context-type="linenumber">179</context>
</context-group>
</trans-unit>
<trans-unit id="85780db87ac6c9f202615ac63754551c061e7236" datatype="html">
@ -4741,7 +4753,7 @@
<target state="translated">Bölgeler</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">202</context>
<context context-type="linenumber">203</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -4753,7 +4765,7 @@
<target state="translated">Gelişmiş Piyasalar</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">227</context>
<context context-type="linenumber">228</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -4765,7 +4777,7 @@
<target state="translated">Gelişmekte Olan Piyasalar</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">236</context>
<context context-type="linenumber">237</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -4777,7 +4789,7 @@
<target state="translated">Diğer Piyasalar</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">245</context>
<context context-type="linenumber">246</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -4789,7 +4801,7 @@
<target state="translated">Veri mevcut değil</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">257</context>
<context context-type="linenumber">258</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -4801,7 +4813,7 @@
<target state="translated">Hesaba Göre</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">269</context>
<context context-type="linenumber">270</context>
</context-group>
</trans-unit>
<trans-unit id="166ccc92e1aa598f9056a260be209a0bab64d37a" datatype="html">
@ -4809,7 +4821,7 @@
<target state="translated">ETF Sağlayıcısına Göre</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">289</context>
<context context-type="linenumber">290</context>
</context-group>
</trans-unit>
<trans-unit id="f27e9dd8de80176286e02312e694cb8d1e485a5d" datatype="html">
@ -4817,7 +4829,7 @@
<target state="translated">Ülkeye Göre</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">312</context>
<context context-type="linenumber">313</context>
</context-group>
</trans-unit>
<trans-unit id="2948175671993825247" datatype="html">
@ -12261,7 +12273,7 @@
<target state="translated">Kılavuzlar</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/resources-page.html</context>
<context context-type="linenumber">5</context>
<context context-type="linenumber">22</context>
</context-group>
</trans-unit>
<trans-unit id="6edd1a650db2af580ebe746813024c45f1d854b1" datatype="html">
@ -12269,7 +12281,7 @@
<target state="translated">Sözlük</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/resources-page.html</context>
<context context-type="linenumber">75</context>
<context context-type="linenumber">92</context>
</context-group>
</trans-unit>
<trans-unit id="5e41f1b4c46ad9e0a9bc83fa36445483aa5cc324" datatype="html">
@ -13761,7 +13773,7 @@
<target state="new">Oops! Could not parse historical data.</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts</context>
<context context-type="linenumber">224</context>
<context context-type="linenumber">223</context>
</context-group>
</trans-unit>
<trans-unit id="297546430113071258" datatype="html">
@ -14633,7 +14645,7 @@
<target state="new">The current market price is</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts</context>
<context context-type="linenumber">318</context>
<context context-type="linenumber">317</context>
</context-group>
</trans-unit>
<trans-unit id="a79d938b5ed20249b4ab6bef86c12633d2f346a0" datatype="html">
@ -14956,6 +14968,30 @@
<context context-type="linenumber">13</context>
</context-group>
</trans-unit>
<trans-unit id="8204176479746810612" datatype="html">
<source>Active</source>
<target state="new">Active</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/holdings/holdings-page.component.ts</context>
<context context-type="linenumber">30</context>
</context-group>
</trans-unit>
<trans-unit id="7860418101283165917" datatype="html">
<source>Closed</source>
<target state="new">Closed</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/holdings/holdings-page.component.ts</context>
<context context-type="linenumber">31</context>
</context-group>
</trans-unit>
<trans-unit id="f2005fa461c06dc2e04d8918bbabedf23604b5b7" datatype="html">
<source>Activity</source>
<target state="new">Activity</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">176</context>
</context-group>
</trans-unit>
</body>
</file>
</xliff>

View File

@ -307,6 +307,10 @@
<context context-type="sourcefile">apps/client/src/app/pages/faq/faq-page.component.ts</context>
<context context-type="linenumber">48</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/resources-page.component.ts</context>
<context context-type="linenumber">17</context>
</context-group>
</trans-unit>
<trans-unit id="6703761340382395781" datatype="html">
<source>features</source>
@ -978,7 +982,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/resources-page.component.ts</context>
<context context-type="linenumber">18</context>
<context context-type="linenumber">19</context>
</context-group>
</trans-unit>
<trans-unit id="1c0638816928ae45284e60504936ca985960df5c" datatype="html">
@ -1026,7 +1030,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/resources-page.html</context>
<context context-type="linenumber">39</context>
<context context-type="linenumber">56</context>
</context-group>
</trans-unit>
<trans-unit id="452ef1b96854fe05618303ee601f8fed3b866c9f" datatype="html">
@ -1578,11 +1582,15 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">126</context>
<context context-type="linenumber">134</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">269</context>
<context context-type="linenumber">178</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">287</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/activities-page.html</context>
@ -1809,11 +1817,11 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-platform/admin-platform.component.html</context>
<context context-type="linenumber">97</context>
<context context-type="linenumber">101</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-tag/admin-tag.component.html</context>
<context context-type="linenumber">77</context>
<context context-type="linenumber">81</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/account-balances/account-balances.component.html</context>
@ -1863,6 +1871,10 @@
<context context-type="sourcefile">apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html</context>
<context context-type="linenumber">34</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">257</context>
</context-group>
</trans-unit>
<trans-unit id="1b6bc6d5daaa6ec75d201690bb6f782f30bf98a0" datatype="html">
<source>Data Source</source>
@ -2101,7 +2113,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">182</context>
<context context-type="linenumber">184</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html</context>
@ -2124,7 +2136,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">191</context>
<context context-type="linenumber">193</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html</context>
@ -2211,7 +2223,7 @@
<source>Oops! Could not parse historical data.</source>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts</context>
<context context-type="linenumber">224</context>
<context context-type="linenumber">223</context>
</context-group>
</trans-unit>
<trans-unit id="c8d1785038d461ec66b5799db21864182b35900a" datatype="html">
@ -2262,11 +2274,11 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">69</context>
<context context-type="linenumber">77</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">222</context>
<context context-type="linenumber">220</context>
</context-group>
</trans-unit>
<trans-unit id="fc61416d48adb7af122b8697e806077eb251fb57" datatype="html">
@ -2281,7 +2293,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">227</context>
<context context-type="linenumber">226</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -2300,7 +2312,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">239</context>
<context context-type="linenumber">238</context>
</context-group>
</trans-unit>
<trans-unit id="0b05507801c7eca260d8978c36621e826f07aaaa" datatype="html">
@ -2544,7 +2556,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">105</context>
<context context-type="linenumber">113</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/header/header.component.html</context>
@ -2556,7 +2568,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">294</context>
<context context-type="linenumber">312</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/accounts/accounts-page.html</context>
@ -2603,7 +2615,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">313</context>
<context context-type="linenumber">332</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html</context>
@ -2660,35 +2672,35 @@
<source>Registration</source>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">88</context>
<context context-type="linenumber">96</context>
</context-group>
</trans-unit>
<trans-unit id="ee6a93295a4311c0968e99a6a8d0521684af361b" datatype="html">
<source>Engagement per Day</source>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">150</context>
<context context-type="linenumber">158</context>
</context-group>
</trans-unit>
<trans-unit id="623f499e6a4ab7f48d7bd483fa49af15713346dd" datatype="html">
<source> Last Request </source>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">175</context>
<context context-type="linenumber">183</context>
</context-group>
</trans-unit>
<trans-unit id="f8ff0eb5c040edbffded4b792c0ba85d3b12fe1a" datatype="html">
<source>Impersonate User</source>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">214</context>
<context context-type="linenumber">222</context>
</context-group>
</trans-unit>
<trans-unit id="3c32a07710e402b2c056bd346e7c42f6015334a6" datatype="html">
<source>Delete User</source>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">224</context>
<context context-type="linenumber">232</context>
</context-group>
</trans-unit>
<trans-unit id="3cc9c2ae277393b3946b38c088dabff671b1ee1b" datatype="html">
@ -2854,7 +2866,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/holdings/holdings-page.html</context>
<context context-type="linenumber">23</context>
<context context-type="linenumber">32</context>
</context-group>
</trans-unit>
<trans-unit id="5486880308148746399" datatype="html">
@ -3316,7 +3328,7 @@
<source>Report Data Glitch</source>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">332</context>
<context context-type="linenumber">350</context>
</context-group>
</trans-unit>
<trans-unit id="280c5b1f5b5b748fbbb37bf7a12c37f41539c1ff" datatype="html">
@ -4840,56 +4852,56 @@
<source>By Platform</source>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">43</context>
<context context-type="linenumber">44</context>
</context-group>
</trans-unit>
<trans-unit id="b79f5520c0cb9a00bd589e8a4c86ffcf5ae439d7" datatype="html">
<source>By Currency</source>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">62</context>
<context context-type="linenumber">63</context>
</context-group>
</trans-unit>
<trans-unit id="8288ff761f2d259625d2e5a3d96db727926d9cd4" datatype="html">
<source>By Asset Class</source>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">85</context>
<context context-type="linenumber">86</context>
</context-group>
</trans-unit>
<trans-unit id="b64539bb7815eb3275b55ad723d3897fc6ba8d23" datatype="html">
<source>By Holding</source>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">108</context>
<context context-type="linenumber">109</context>
</context-group>
</trans-unit>
<trans-unit id="9f86714c9a6b74e13c96ab02102ce40c34fe13b9" datatype="html">
<source>By Sector</source>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">131</context>
<context context-type="linenumber">132</context>
</context-group>
</trans-unit>
<trans-unit id="7017e0e26b53ef322c3e3bbf95f06a85487a12b2" datatype="html">
<source>By Continent</source>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">155</context>
<context context-type="linenumber">156</context>
</context-group>
</trans-unit>
<trans-unit id="834807cba8928b6f8b27ea62c886f7f3715079b0" datatype="html">
<source>By Market</source>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">178</context>
<context context-type="linenumber">179</context>
</context-group>
</trans-unit>
<trans-unit id="85780db87ac6c9f202615ac63754551c061e7236" datatype="html">
<source>Regions</source>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">202</context>
<context context-type="linenumber">203</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -4900,7 +4912,7 @@
<source>Developed Markets</source>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">227</context>
<context context-type="linenumber">228</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -4911,7 +4923,7 @@
<source>Emerging Markets</source>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">236</context>
<context context-type="linenumber">237</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -4922,7 +4934,7 @@
<source>Other Markets</source>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">245</context>
<context context-type="linenumber">246</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -4933,7 +4945,7 @@
<source>No data available</source>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">257</context>
<context context-type="linenumber">258</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -4944,21 +4956,21 @@
<source>By Account</source>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">269</context>
<context context-type="linenumber">270</context>
</context-group>
</trans-unit>
<trans-unit id="166ccc92e1aa598f9056a260be209a0bab64d37a" datatype="html">
<source>By ETF Provider</source>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">289</context>
<context context-type="linenumber">290</context>
</context-group>
</trans-unit>
<trans-unit id="f27e9dd8de80176286e02312e694cb8d1e485a5d" datatype="html">
<source>By Country</source>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">312</context>
<context context-type="linenumber">313</context>
</context-group>
</trans-unit>
<trans-unit id="2948175671993825247" datatype="html">
@ -13371,14 +13383,14 @@
<source>Guides</source>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/resources-page.html</context>
<context context-type="linenumber">5</context>
<context context-type="linenumber">22</context>
</context-group>
</trans-unit>
<trans-unit id="6edd1a650db2af580ebe746813024c45f1d854b1" datatype="html">
<source>Glossary</source>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/resources-page.html</context>
<context context-type="linenumber">75</context>
<context context-type="linenumber">92</context>
</context-group>
</trans-unit>
<trans-unit id="3737711445155929474" datatype="html">
@ -14055,7 +14067,7 @@
<source>The current market price is</source>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts</context>
<context context-type="linenumber">318</context>
<context context-type="linenumber">317</context>
</context-group>
</trans-unit>
<trans-unit id="a79d938b5ed20249b4ab6bef86c12633d2f346a0" datatype="html">
@ -14335,6 +14347,27 @@
<context context-type="linenumber">13</context>
</context-group>
</trans-unit>
<trans-unit id="7860418101283165917" datatype="html">
<source>Closed</source>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/holdings/holdings-page.component.ts</context>
<context context-type="linenumber">31</context>
</context-group>
</trans-unit>
<trans-unit id="8204176479746810612" datatype="html">
<source>Active</source>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/holdings/holdings-page.component.ts</context>
<context context-type="linenumber">30</context>
</context-group>
</trans-unit>
<trans-unit id="f2005fa461c06dc2e04d8918bbabedf23604b5b7" datatype="html">
<source>Activity</source>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html</context>
<context context-type="linenumber">176</context>
</context-group>
</trans-unit>
</body>
</file>
</xliff>

12
docker/entrypoint.sh Executable file
View File

@ -0,0 +1,12 @@
#!/bin/sh
set -ex
echo "Running database migrations"
npx prisma migrate deploy
echo "Seeding the database"
npx prisma db seed
echo "Starting the server"
node main

Some files were not shown because too many files have changed in this diff Show More