diff --git a/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts b/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts index 0afea3b31..87a0cab3c 100644 --- a/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts +++ b/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts @@ -137,6 +137,7 @@ export abstract class PortfolioCalculator { netPerformancePercentageWithCurrencyEffect: new Big(0), netPerformanceWithCurrencyEffect: new Big(0), positions: [], + totalFeesWithCurrencyEffect: new Big(0), totalInvestment: new Big(0), totalInvestmentWithCurrencyEffect: new Big(0) }; @@ -259,6 +260,7 @@ export abstract class PortfolioCalculator { ); const { + feesWithCurrencyEffect, grossPerformance, grossPerformancePercentage, grossPerformancePercentageWithCurrencyEffect, @@ -660,6 +662,12 @@ export abstract class PortfolioCalculator { ); } + public async getFeesInBaseCurrency() { + await this.snapshotPromise; + + return this.snapshot.totalFeesWithCurrencyEffect; + } + public getInvestments(): { date: string; investment: Big }[] { if (this.transactionPoints.length === 0) { return []; @@ -752,6 +760,12 @@ export abstract class PortfolioCalculator { type, unitPrice } of this.orders) { + if ( + [/*'DIVIDEND', 'FEE',*/ 'INTEREST', 'ITEM', 'LIABILITY'].includes(type) + ) { + continue; + } + let currentTransactionPointItem: TransactionPointSymbol; const oldAccumulatedSymbol = symbols[SymbolProfile.symbol]; @@ -824,14 +838,22 @@ export abstract class PortfolioCalculator { return a.symbol?.localeCompare(b.symbol); }); + let fees = new Big(0); + + if (type === 'FEE') { + fees = fee; + } + if (lastDate !== date || lastTransactionPoint === null) { lastTransactionPoint = { date, + fees, items: newItems }; this.transactionPoints.push(lastTransactionPoint); } else { + lastTransactionPoint.fees = lastTransactionPoint.fees.plus(fees); lastTransactionPoint.items = newItems; } diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy-and-sell-in-two-activities.spec.ts b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy-and-sell-in-two-activities.spec.ts index 421b3cf0b..35f7fbcc5 100644 --- a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy-and-sell-in-two-activities.spec.ts +++ b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy-and-sell-in-two-activities.spec.ts @@ -173,6 +173,7 @@ describe('PortfolioCalculator', () => { valueInBaseCurrency: new Big('0') } ], + totalFeesWithCurrencyEffect: new Big('3.2'), totalInvestment: new Big('0'), totalInvestmentWithCurrencyEffect: new Big('0') }); diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy-and-sell.spec.ts b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy-and-sell.spec.ts index d6828170c..95fe27347 100644 --- a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy-and-sell.spec.ts +++ b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy-and-sell.spec.ts @@ -156,6 +156,7 @@ describe('PortfolioCalculator', () => { valueInBaseCurrency: new Big('0') } ], + totalFeesWithCurrencyEffect: new Big('3.2'), totalInvestment: new Big('0'), totalInvestmentWithCurrencyEffect: new Big('0') }); diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy.spec.ts b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy.spec.ts index 0105837f2..efb53100f 100644 --- a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy.spec.ts +++ b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy.spec.ts @@ -141,6 +141,7 @@ describe('PortfolioCalculator', () => { valueInBaseCurrency: new Big('297.8') } ], + totalFeesWithCurrencyEffect: new Big('1.55'), totalInvestment: new Big('273.2'), totalInvestmentWithCurrencyEffect: new Big('273.2') }); diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-btcusd-buy-and-sell-partially.spec.ts b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-btcusd-buy-and-sell-partially.spec.ts index 0131e06be..4a9887e4e 100644 --- a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-btcusd-buy-and-sell-partially.spec.ts +++ b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-btcusd-buy-and-sell-partially.spec.ts @@ -175,6 +175,7 @@ describe('PortfolioCalculator', () => { valueInBaseCurrency: new Big('13298.425356') } ], + totalFeesWithCurrencyEffect: new Big('0'), totalInvestment: new Big('320.43'), totalInvestmentWithCurrencyEffect: new Big('318.542667299999967957') }); diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-fee.spec.ts b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-fee.spec.ts new file mode 100644 index 000000000..b4a108381 --- /dev/null +++ b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-fee.spec.ts @@ -0,0 +1,131 @@ +import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface'; +import { + activityDummyData, + symbolProfileDummyData +} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator-test-utils'; +import { + PortfolioCalculatorFactory, + PerformanceCalculationType +} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory'; +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'; + +jest.mock('@ghostfolio/api/app/portfolio/current-rate.service', () => { + return { + // eslint-disable-next-line @typescript-eslint/naming-convention + CurrentRateService: jest.fn().mockImplementation(() => { + return CurrentRateServiceMock; + }) + }; +}); + +describe('PortfolioCalculator', () => { + let currentRateService: CurrentRateService; + let exchangeRateDataService: ExchangeRateDataService; + let factory: PortfolioCalculatorFactory; + + beforeEach(() => { + currentRateService = new CurrentRateService(null, null, null, null); + + exchangeRateDataService = new ExchangeRateDataService( + null, + null, + null, + null + ); + + factory = new PortfolioCalculatorFactory( + currentRateService, + exchangeRateDataService + ); + }); + + describe('compute portfolio snapshot', () => { + it.only('with fee activity', async () => { + const spy = jest + .spyOn(Date, 'now') + .mockImplementation(() => parseDate('2021-12-18').getTime()); + + const activities: Activity[] = [ + { + ...activityDummyData, + date: new Date('2021-09-01'), + fee: 49, + quantity: 0, + SymbolProfile: { + ...symbolProfileDummyData, + currency: 'USD', + dataSource: 'MANUAL', + name: 'Account Opening Fee', + symbol: '2c463fb3-af07-486e-adb0-8301b3d72141' + }, + type: 'FEE', + unitPrice: 0 + } + ]; + + const portfolioCalculator = factory.createCalculator({ + activities, + calculationType: PerformanceCalculationType.TWR, + currency: 'USD' + }); + + const portfolioSnapshot = await portfolioCalculator.computeSnapshot( + parseDate('2021-11-30') + ); + + spy.mockRestore(); + + expect(portfolioSnapshot).toEqual({ + currentValueInBaseCurrency: new Big('0'), + errors: [], + grossPerformance: new Big('0'), + grossPerformancePercentage: new Big('0'), + grossPerformancePercentageWithCurrencyEffect: new Big('0'), + grossPerformanceWithCurrencyEffect: new Big('0'), + hasErrors: true, + netPerformance: new Big('0'), + netPerformancePercentage: new Big('0'), + netPerformancePercentageWithCurrencyEffect: new Big('0'), + netPerformanceWithCurrencyEffect: new Big('0'), + positions: [ + { + averagePrice: new Big('0'), + currency: 'USD', + dataSource: 'MANUAL', + dividend: new Big('0'), + dividendInBaseCurrency: new Big('0'), + fee: new Big('49'), + firstBuyDate: '2021-09-01', + grossPerformance: null, + grossPerformancePercentage: null, + grossPerformancePercentageWithCurrencyEffect: null, + grossPerformanceWithCurrencyEffect: null, + investment: new Big('0'), + investmentWithCurrencyEffect: new Big('0'), + marketPrice: null, + marketPriceInBaseCurrency: 0, + netPerformance: null, + netPerformancePercentage: null, + netPerformancePercentageWithCurrencyEffect: null, + netPerformanceWithCurrencyEffect: null, + quantity: new Big('0'), + symbol: '2c463fb3-af07-486e-adb0-8301b3d72141', + tags: [], + timeWeightedInvestment: new Big('0'), + timeWeightedInvestmentWithCurrencyEffect: new Big('0'), + transactionCount: 1, + valueInBaseCurrency: new Big('0') + } + ], + totalFeesWithCurrencyEffect: new Big('49'), + totalInvestment: new Big('0'), + totalInvestmentWithCurrencyEffect: new Big('0') + }); + }); + }); +}); diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-googl-buy.spec.ts b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-googl-buy.spec.ts index d7f557151..ffcf85b95 100644 --- a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-googl-buy.spec.ts +++ b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-googl-buy.spec.ts @@ -154,6 +154,7 @@ describe('PortfolioCalculator', () => { valueInBaseCurrency: new Big('103.10483') } ], + totalFeesWithCurrencyEffect: new Big('1'), totalInvestment: new Big('89.12'), totalInvestmentWithCurrencyEffect: new Big('82.329056') }); diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-msft-buy-with-dividend.spec.ts b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-msft-buy-with-dividend.spec.ts index b6e5be949..c05af223b 100644 --- a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-msft-buy-with-dividend.spec.ts +++ b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-msft-buy-with-dividend.spec.ts @@ -130,6 +130,7 @@ describe('PortfolioCalculator', () => { transactionCount: 2 } ], + totalFeesWithCurrencyEffect: new Big('19'), totalInvestment: new Big('298.58'), totalInvestmentWithCurrencyEffect: new Big('298.58') }); diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-no-orders.spec.ts b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-no-orders.spec.ts index 9a8c39459..e165e8aac 100644 --- a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-no-orders.spec.ts +++ b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-no-orders.spec.ts @@ -80,6 +80,7 @@ describe('PortfolioCalculator', () => { netPerformancePercentageWithCurrencyEffect: new Big(0), netPerformanceWithCurrencyEffect: new Big(0), positions: [], + totalFeesWithCurrencyEffect: new Big('0'), totalInvestment: new Big(0), totalInvestmentWithCurrencyEffect: new Big(0) }); diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-novn-buy-and-sell-partially.spec.ts b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-novn-buy-and-sell-partially.spec.ts index a3956515b..878e856f2 100644 --- a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-novn-buy-and-sell-partially.spec.ts +++ b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-novn-buy-and-sell-partially.spec.ts @@ -158,6 +158,7 @@ describe('PortfolioCalculator', () => { valueInBaseCurrency: new Big('87.8') } ], + totalFeesWithCurrencyEffect: new Big('4.25'), totalInvestment: new Big('75.80'), totalInvestmentWithCurrencyEffect: new Big('75.80') }); diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-novn-buy-and-sell.spec.ts b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-novn-buy-and-sell.spec.ts index 1b1e09f32..0efec77c0 100644 --- a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-novn-buy-and-sell.spec.ts +++ b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-novn-buy-and-sell.spec.ts @@ -182,6 +182,7 @@ describe('PortfolioCalculator', () => { valueInBaseCurrency: new Big('0') } ], + totalFeesWithCurrencyEffect: new Big('0'), totalInvestment: new Big('0'), totalInvestmentWithCurrencyEffect: new Big('0') }); diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator.ts b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator.ts index a04d331b1..30b15b98d 100644 --- a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator.ts +++ b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator.ts @@ -30,12 +30,19 @@ export class TWRPortfolioCalculator extends PortfolioCalculator { let hasErrors = false; let netPerformance = new Big(0); let netPerformanceWithCurrencyEffect = new Big(0); + let totalFeesWithCurrencyEffect = new Big(0); let totalInvestment = new Big(0); let totalInvestmentWithCurrencyEffect = new Big(0); let totalTimeWeightedInvestment = new Big(0); let totalTimeWeightedInvestmentWithCurrencyEffect = new Big(0); for (const currentPosition of positions) { + if (currentPosition.fee) { + totalFeesWithCurrencyEffect = totalFeesWithCurrencyEffect.plus( + currentPosition.fee + ); + } + if (currentPosition.valueInBaseCurrency) { currentValueInBaseCurrency = currentValueInBaseCurrency.plus( currentPosition.valueInBaseCurrency @@ -101,6 +108,7 @@ export class TWRPortfolioCalculator extends PortfolioCalculator { hasErrors, netPerformance, netPerformanceWithCurrencyEffect, + totalFeesWithCurrencyEffect, totalInvestment, totalInvestmentWithCurrencyEffect, netPerformancePercentage: totalTimeWeightedInvestment.eq(0) @@ -198,6 +206,7 @@ export class TWRPortfolioCalculator extends PortfolioCalculator { return { currentValues: {}, currentValuesWithCurrencyEffect: {}, + feesWithCurrencyEffect: new Big(0), grossPerformance: new Big(0), grossPerformancePercentage: new Big(0), grossPerformancePercentageWithCurrencyEffect: new Big(0), @@ -240,6 +249,7 @@ export class TWRPortfolioCalculator extends PortfolioCalculator { return { currentValues: {}, currentValuesWithCurrencyEffect: {}, + feesWithCurrencyEffect: new Big(0), grossPerformance: new Big(0), grossPerformancePercentage: new Big(0), grossPerformancePercentageWithCurrencyEffect: new Big(0), @@ -808,6 +818,7 @@ export class TWRPortfolioCalculator extends PortfolioCalculator { return { currentValues, currentValuesWithCurrencyEffect, + feesWithCurrencyEffect, grossPerformancePercentage, grossPerformancePercentageWithCurrencyEffect, initialValue, diff --git a/apps/api/src/app/portfolio/interfaces/portfolio-snapshot.interface.ts b/apps/api/src/app/portfolio/interfaces/portfolio-snapshot.interface.ts index 9fef758c4..37573e3bb 100644 --- a/apps/api/src/app/portfolio/interfaces/portfolio-snapshot.interface.ts +++ b/apps/api/src/app/portfolio/interfaces/portfolio-snapshot.interface.ts @@ -15,6 +15,7 @@ export interface PortfolioSnapshot extends ResponseError { netPerformancePercentage: Big; netPerformancePercentageWithCurrencyEffect: Big; positions: TimelinePosition[]; + totalFeesWithCurrencyEffect: Big; totalInvestment: Big; totalInvestmentWithCurrencyEffect: Big; } diff --git a/apps/api/src/app/portfolio/interfaces/transaction-point.interface.ts b/apps/api/src/app/portfolio/interfaces/transaction-point.interface.ts index 178df3456..f2645fbfd 100644 --- a/apps/api/src/app/portfolio/interfaces/transaction-point.interface.ts +++ b/apps/api/src/app/portfolio/interfaces/transaction-point.interface.ts @@ -1,6 +1,9 @@ +import { Big } from 'big.js'; + import { TransactionPointSymbol } from './transaction-point-symbol.interface'; export interface TransactionPoint { date: string; + fees: Big; items: TransactionPointSymbol[]; } diff --git a/apps/api/src/app/portfolio/portfolio.controller.ts b/apps/api/src/app/portfolio/portfolio.controller.ts index 3762aa352..7ee92e91c 100644 --- a/apps/api/src/app/portfolio/portfolio.controller.ts +++ b/apps/api/src/app/portfolio/portfolio.controller.ts @@ -390,11 +390,9 @@ export class PortfolioController { @Query('assetClasses') filterByAssetClasses?: string, @Query('range') dateRange: DateRange = 'max', @Query('tags') filterByTags?: string, - @Query('withExcludedAccounts') withExcludedAccountsParam = 'false', - @Query('withItems') withItemsParam = 'false' + @Query('withExcludedAccounts') withExcludedAccountsParam = 'false' ): Promise { const withExcludedAccounts = withExcludedAccountsParam === 'true'; - const withItems = withItemsParam === 'true'; const hasReadRestrictedAccessPermission = this.userService.hasReadRestrictedAccessPermission({ @@ -413,7 +411,6 @@ export class PortfolioController { filters, impersonationId, withExcludedAccounts, - withItems, userId: this.request.user.id }); diff --git a/apps/api/src/app/portfolio/portfolio.service.ts b/apps/api/src/app/portfolio/portfolio.service.ts index 45802baac..6353b033e 100644 --- a/apps/api/src/app/portfolio/portfolio.service.ts +++ b/apps/api/src/app/portfolio/portfolio.service.ts @@ -23,12 +23,7 @@ import { EMERGENCY_FUND_TAG_ID, UNKNOWN_KEY } from '@ghostfolio/common/config'; -import { - DATE_FORMAT, - getAllActivityTypes, - getSum, - parseDate -} from '@ghostfolio/common/helper'; +import { DATE_FORMAT, getSum, parseDate } from '@ghostfolio/common/helper'; import { Accounts, EnhancedSymbolProfile, @@ -350,19 +345,8 @@ export class PortfolioService { (user.Settings?.settings as UserSettings)?.emergencyFund ?? 0 ); - let types = getAllActivityTypes().filter((activityType) => { - return activityType !== 'FEE'; - }); - - if (withLiabilities === false) { - types = types.filter((activityType) => { - return activityType !== 'LIABILITY'; - }); - } - const { activities } = await this.orderService.getOrders({ filters, - types, userCurrency, userId, withExcludedAccounts @@ -917,7 +901,6 @@ export class PortfolioService { endDate, filters, userId, - types: ['BUY', 'SELL'], userCurrency: this.getUserCurrency() }); @@ -1043,15 +1026,13 @@ export class PortfolioService { filters, impersonationId, userId, - withExcludedAccounts = false, - withItems = false + withExcludedAccounts = false }: { dateRange?: DateRange; filters?: Filter[]; impersonationId: string; userId: string; withExcludedAccounts?: boolean; - withItems?: boolean; }): Promise { userId = await this.getUserId(impersonationId, userId); const user = await this.userService.user({ id: userId }); @@ -1089,10 +1070,7 @@ export class PortfolioService { filters, userCurrency, userId, - withExcludedAccounts, - types: withItems - ? ['BUY', 'DIVIDEND', 'ITEM', 'SELL'] - : ['BUY', 'DIVIDEND', 'SELL'] + withExcludedAccounts }); if (accountBalanceItems?.length <= 0 && activities?.length <= 0) { @@ -1227,8 +1205,7 @@ export class PortfolioService { const { activities } = await this.orderService.getOrders({ userCurrency, - userId, - types: ['BUY', 'SELL'] + userId }); const portfolioCalculator = this.calculatorFactory.createCalculator({ @@ -1237,7 +1214,7 @@ export class PortfolioService { currency: this.request.user.Settings.settings.baseCurrency }); - let { positions, totalInvestment } = + let { totalFeesWithCurrencyEffect, positions, totalInvestment } = await portfolioCalculator.getSnapshot(); positions = positions.filter((item) => !item.quantity.eq(0)); @@ -1303,7 +1280,7 @@ export class PortfolioService { new FeeRatioInitialInvestment( this.exchangeRateDataService, totalInvestment.toNumber(), - this.getFees({ activities, userCurrency }).toNumber() + totalFeesWithCurrencyEffect.toNumber() ) ], userSettings @@ -1447,30 +1424,6 @@ export class PortfolioService { return valueInBaseCurrencyOfEmergencyFundPositions.toNumber(); } - private getFees({ - activities, - userCurrency - }: { - activities: Activity[]; - userCurrency: string; - }) { - return getSum( - activities - .filter(({ isDraft }) => { - return isDraft === false; - }) - .map(({ fee, SymbolProfile }) => { - return new Big( - this.exchangeRateDataService.toCurrency( - fee, - SymbolProfile.currency, - userCurrency - ) - ); - }) - ); - } - private getInitialCashPosition({ balance, currency @@ -1664,15 +1617,20 @@ export class PortfolioService { ) ); - const fees = this.getFees({ activities, userCurrency }).toNumber(); - const firstOrderDate = activities[0]?.date; + const fees = await portfolioCalculator.getFeesInBaseCurrency(); + const firstOrderDate = portfolioCalculator.getStartDate(); + + // TODO const interest = this.getSumOfActivityType({ activities, userCurrency, activityType: 'INTEREST' }).toNumber(); + console.log(interest); + + // TODO const items = getSum( Object.keys(holdings) .filter((symbol) => { @@ -1687,6 +1645,7 @@ export class PortfolioService { }) ).toNumber(); + // TODO const liabilities = getSum( Object.keys(holdings) .filter((symbol) => { @@ -1777,7 +1736,6 @@ export class PortfolioService { annualizedPerformancePercentWithCurrencyEffect, cash, excludedAccountsAndActivities, - fees, firstOrderDate, interest, items, @@ -1793,6 +1751,7 @@ export class PortfolioService { .toNumber(), total: emergencyFund.toNumber() }, + fees: fees.toNumber(), filteredValueInBaseCurrency: filteredValueInBaseCurrency.toNumber(), filteredValueInPercentage: netWorth ? filteredValueInBaseCurrency.div(netWorth).toNumber() diff --git a/libs/common/src/lib/interfaces/symbol-metrics.interface.ts b/libs/common/src/lib/interfaces/symbol-metrics.interface.ts index ecb80ef92..efe757bf9 100644 --- a/libs/common/src/lib/interfaces/symbol-metrics.interface.ts +++ b/libs/common/src/lib/interfaces/symbol-metrics.interface.ts @@ -7,6 +7,7 @@ export interface SymbolMetrics { currentValuesWithCurrencyEffect: { [date: string]: Big; }; + feesWithCurrencyEffect: Big; grossPerformance: Big; grossPerformancePercentage: Big; grossPerformancePercentageWithCurrencyEffect: Big;