Feature/refactor portfolio holding response (#4649)
* Refactor portfolio holding response * maxPrice -> marketPriceMax * minPrice -> marketPriceMin * orders -> activities
This commit is contained in:
parent
1bced96460
commit
3646fb7f77
@ -49,7 +49,7 @@ export class ImportService {
|
|||||||
symbol
|
symbol
|
||||||
}: AssetProfileIdentifier): Promise<Activity[]> {
|
}: AssetProfileIdentifier): Promise<Activity[]> {
|
||||||
try {
|
try {
|
||||||
const { firstBuyDate, historicalData, orders } =
|
const { activities, firstBuyDate, historicalData } =
|
||||||
await this.portfolioService.getHolding(dataSource, undefined, symbol);
|
await this.portfolioService.getHolding(dataSource, undefined, symbol);
|
||||||
|
|
||||||
const [[assetProfile], dividends] = await Promise.all([
|
const [[assetProfile], dividends] = await Promise.all([
|
||||||
@ -68,7 +68,7 @@ export class ImportService {
|
|||||||
})
|
})
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const accounts = orders
|
const accounts = activities
|
||||||
.filter(({ Account }) => {
|
.filter(({ Account }) => {
|
||||||
return !!Account;
|
return !!Account;
|
||||||
})
|
})
|
||||||
@ -88,7 +88,7 @@ export class ImportService {
|
|||||||
const value = new Big(quantity).mul(marketPrice).toNumber();
|
const value = new Big(quantity).mul(marketPrice).toNumber();
|
||||||
|
|
||||||
const date = parseDate(dateString);
|
const date = parseDate(dateString);
|
||||||
const isDuplicate = orders.some((activity) => {
|
const isDuplicate = activities.some((activity) => {
|
||||||
return (
|
return (
|
||||||
activity.accountId === Account?.id &&
|
activity.accountId === Account?.id &&
|
||||||
activity.SymbolProfile.currency === assetProfile.currency &&
|
activity.SymbolProfile.currency === assetProfile.currency &&
|
||||||
|
@ -648,6 +648,7 @@ export class PortfolioService {
|
|||||||
|
|
||||||
if (activities.length === 0) {
|
if (activities.length === 0) {
|
||||||
return {
|
return {
|
||||||
|
activities: [],
|
||||||
averagePrice: undefined,
|
averagePrice: undefined,
|
||||||
dataProviderInfo: undefined,
|
dataProviderInfo: undefined,
|
||||||
dividendInBaseCurrency: undefined,
|
dividendInBaseCurrency: undefined,
|
||||||
@ -662,13 +663,12 @@ export class PortfolioService {
|
|||||||
historicalData: [],
|
historicalData: [],
|
||||||
investment: undefined,
|
investment: undefined,
|
||||||
marketPrice: undefined,
|
marketPrice: undefined,
|
||||||
maxPrice: undefined,
|
marketPriceMax: undefined,
|
||||||
minPrice: undefined,
|
marketPriceMin: undefined,
|
||||||
netPerformance: undefined,
|
netPerformance: undefined,
|
||||||
netPerformancePercent: undefined,
|
netPerformancePercent: undefined,
|
||||||
netPerformancePercentWithCurrencyEffect: undefined,
|
netPerformancePercentWithCurrencyEffect: undefined,
|
||||||
netPerformanceWithCurrencyEffect: undefined,
|
netPerformanceWithCurrencyEffect: undefined,
|
||||||
orders: [],
|
|
||||||
quantity: undefined,
|
quantity: undefined,
|
||||||
SymbolProfile: undefined,
|
SymbolProfile: undefined,
|
||||||
tags: [],
|
tags: [],
|
||||||
@ -714,7 +714,7 @@ export class PortfolioService {
|
|||||||
transactionCount
|
transactionCount
|
||||||
} = position;
|
} = position;
|
||||||
|
|
||||||
const activitiesOfPosition = activities.filter(({ SymbolProfile }) => {
|
const activitiesOfHolding = activities.filter(({ SymbolProfile }) => {
|
||||||
return (
|
return (
|
||||||
SymbolProfile.dataSource === dataSource &&
|
SymbolProfile.dataSource === dataSource &&
|
||||||
SymbolProfile.symbol === symbol
|
SymbolProfile.symbol === symbol
|
||||||
@ -748,12 +748,12 @@ export class PortfolioService {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const historicalDataArray: HistoricalDataItem[] = [];
|
const historicalDataArray: HistoricalDataItem[] = [];
|
||||||
let maxPrice = Math.max(
|
let marketPriceMax = Math.max(
|
||||||
activitiesOfPosition[0].unitPriceInAssetProfileCurrency,
|
activitiesOfHolding[0].unitPriceInAssetProfileCurrency,
|
||||||
marketPrice
|
marketPrice
|
||||||
);
|
);
|
||||||
let minPrice = Math.min(
|
let marketPriceMin = Math.min(
|
||||||
activitiesOfPosition[0].unitPriceInAssetProfileCurrency,
|
activitiesOfHolding[0].unitPriceInAssetProfileCurrency,
|
||||||
marketPrice
|
marketPrice
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -793,27 +793,31 @@ export class PortfolioService {
|
|||||||
quantity: currentQuantity
|
quantity: currentQuantity
|
||||||
});
|
});
|
||||||
|
|
||||||
maxPrice = Math.max(marketPrice ?? 0, maxPrice);
|
marketPriceMax = Math.max(marketPrice ?? 0, marketPriceMax);
|
||||||
minPrice = Math.min(marketPrice ?? Number.MAX_SAFE_INTEGER, minPrice);
|
marketPriceMin = Math.min(
|
||||||
|
marketPrice ?? Number.MAX_SAFE_INTEGER,
|
||||||
|
marketPriceMin
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Add historical entry for buy date, if no historical data available
|
// Add historical entry for buy date, if no historical data available
|
||||||
historicalDataArray.push({
|
historicalDataArray.push({
|
||||||
averagePrice: activitiesOfPosition[0].unitPriceInAssetProfileCurrency,
|
averagePrice: activitiesOfHolding[0].unitPriceInAssetProfileCurrency,
|
||||||
date: firstBuyDate,
|
date: firstBuyDate,
|
||||||
marketPrice: activitiesOfPosition[0].unitPriceInAssetProfileCurrency,
|
marketPrice: activitiesOfHolding[0].unitPriceInAssetProfileCurrency,
|
||||||
quantity: activitiesOfPosition[0].quantity
|
quantity: activitiesOfHolding[0].quantity
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
firstBuyDate,
|
firstBuyDate,
|
||||||
marketPrice,
|
marketPrice,
|
||||||
maxPrice,
|
marketPriceMax,
|
||||||
minPrice,
|
marketPriceMin,
|
||||||
SymbolProfile,
|
SymbolProfile,
|
||||||
tags,
|
tags,
|
||||||
transactionCount,
|
transactionCount,
|
||||||
|
activities: activitiesOfHolding,
|
||||||
averagePrice: averagePrice.toNumber(),
|
averagePrice: averagePrice.toNumber(),
|
||||||
dataProviderInfo: portfolioCalculator.getDataProviderInfos()?.[0],
|
dataProviderInfo: portfolioCalculator.getDataProviderInfos()?.[0],
|
||||||
dividendInBaseCurrency: dividendInBaseCurrency.toNumber(),
|
dividendInBaseCurrency: dividendInBaseCurrency.toNumber(),
|
||||||
@ -842,7 +846,6 @@ export class PortfolioService {
|
|||||||
]?.toNumber(),
|
]?.toNumber(),
|
||||||
netPerformanceWithCurrencyEffect:
|
netPerformanceWithCurrencyEffect:
|
||||||
position.netPerformanceWithCurrencyEffectMap?.['max']?.toNumber(),
|
position.netPerformanceWithCurrencyEffectMap?.['max']?.toNumber(),
|
||||||
orders: activitiesOfPosition,
|
|
||||||
quantity: quantity.toNumber(),
|
quantity: quantity.toNumber(),
|
||||||
value: this.exchangeRateDataService.toCurrency(
|
value: this.exchangeRateDataService.toCurrency(
|
||||||
quantity.mul(marketPrice ?? 0).toNumber(),
|
quantity.mul(marketPrice ?? 0).toNumber(),
|
||||||
@ -881,8 +884,8 @@ export class PortfolioService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const historicalDataArray: HistoricalDataItem[] = [];
|
const historicalDataArray: HistoricalDataItem[] = [];
|
||||||
let maxPrice = marketPrice;
|
let marketPriceMax = marketPrice;
|
||||||
let minPrice = marketPrice;
|
let marketPriceMin = marketPrice;
|
||||||
|
|
||||||
for (const [date, { marketPrice }] of Object.entries(
|
for (const [date, { marketPrice }] of Object.entries(
|
||||||
historicalData[aSymbol]
|
historicalData[aSymbol]
|
||||||
@ -892,15 +895,19 @@ export class PortfolioService {
|
|||||||
value: marketPrice
|
value: marketPrice
|
||||||
});
|
});
|
||||||
|
|
||||||
maxPrice = Math.max(marketPrice ?? 0, maxPrice);
|
marketPriceMax = Math.max(marketPrice ?? 0, marketPriceMax);
|
||||||
minPrice = Math.min(marketPrice ?? Number.MAX_SAFE_INTEGER, minPrice);
|
marketPriceMin = Math.min(
|
||||||
|
marketPrice ?? Number.MAX_SAFE_INTEGER,
|
||||||
|
marketPriceMin
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
marketPrice,
|
marketPrice,
|
||||||
maxPrice,
|
marketPriceMax,
|
||||||
minPrice,
|
marketPriceMin,
|
||||||
SymbolProfile,
|
SymbolProfile,
|
||||||
|
activities: [],
|
||||||
averagePrice: 0,
|
averagePrice: 0,
|
||||||
dataProviderInfo: undefined,
|
dataProviderInfo: undefined,
|
||||||
dividendInBaseCurrency: 0,
|
dividendInBaseCurrency: 0,
|
||||||
@ -918,7 +925,6 @@ export class PortfolioService {
|
|||||||
netPerformancePercent: undefined,
|
netPerformancePercent: undefined,
|
||||||
netPerformancePercentWithCurrencyEffect: undefined,
|
netPerformancePercentWithCurrencyEffect: undefined,
|
||||||
netPerformanceWithCurrencyEffect: undefined,
|
netPerformanceWithCurrencyEffect: undefined,
|
||||||
orders: [],
|
|
||||||
quantity: 0,
|
quantity: 0,
|
||||||
tags: [],
|
tags: [],
|
||||||
transactionCount: undefined,
|
transactionCount: undefined,
|
||||||
|
@ -105,8 +105,8 @@ export class GfHoldingDetailDialogComponent implements OnDestroy, OnInit {
|
|||||||
public investmentPrecision = 2;
|
public investmentPrecision = 2;
|
||||||
public marketDataItems: MarketData[] = [];
|
public marketDataItems: MarketData[] = [];
|
||||||
public marketPrice: number;
|
public marketPrice: number;
|
||||||
public maxPrice: number;
|
public marketPriceMax: number;
|
||||||
public minPrice: number;
|
public marketPriceMin: number;
|
||||||
public netPerformance: number;
|
public netPerformance: number;
|
||||||
public netPerformancePrecision = 2;
|
public netPerformancePrecision = 2;
|
||||||
public netPerformancePercent: number;
|
public netPerformancePercent: number;
|
||||||
@ -234,8 +234,8 @@ export class GfHoldingDetailDialogComponent implements OnDestroy, OnInit {
|
|||||||
historicalData,
|
historicalData,
|
||||||
investment,
|
investment,
|
||||||
marketPrice,
|
marketPrice,
|
||||||
maxPrice,
|
marketPriceMax,
|
||||||
minPrice,
|
marketPriceMin,
|
||||||
netPerformance,
|
netPerformance,
|
||||||
netPerformancePercent,
|
netPerformancePercent,
|
||||||
netPerformancePercentWithCurrencyEffect,
|
netPerformancePercentWithCurrencyEffect,
|
||||||
@ -297,8 +297,8 @@ export class GfHoldingDetailDialogComponent implements OnDestroy, OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.marketPrice = marketPrice;
|
this.marketPrice = marketPrice;
|
||||||
this.maxPrice = maxPrice;
|
this.marketPriceMax = marketPriceMax;
|
||||||
this.minPrice = minPrice;
|
this.marketPriceMin = marketPriceMin;
|
||||||
this.netPerformance = netPerformance;
|
this.netPerformance = netPerformance;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
|
@ -106,11 +106,11 @@
|
|||||||
[locale]="data.locale"
|
[locale]="data.locale"
|
||||||
[ngClass]="{
|
[ngClass]="{
|
||||||
'text-danger':
|
'text-danger':
|
||||||
minPrice?.toFixed(2) === marketPrice?.toFixed(2) &&
|
marketPriceMin?.toFixed(2) === marketPrice?.toFixed(2) &&
|
||||||
maxPrice?.toFixed(2) !== minPrice?.toFixed(2)
|
marketPriceMax?.toFixed(2) !== marketPriceMin?.toFixed(2)
|
||||||
}"
|
}"
|
||||||
[unit]="SymbolProfile?.currency"
|
[unit]="SymbolProfile?.currency"
|
||||||
[value]="minPrice"
|
[value]="marketPriceMin"
|
||||||
>Minimum Price</gf-value
|
>Minimum Price</gf-value
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
@ -122,11 +122,11 @@
|
|||||||
[locale]="data.locale"
|
[locale]="data.locale"
|
||||||
[ngClass]="{
|
[ngClass]="{
|
||||||
'text-success':
|
'text-success':
|
||||||
maxPrice?.toFixed(2) === marketPrice?.toFixed(2) &&
|
marketPriceMax?.toFixed(2) === marketPrice?.toFixed(2) &&
|
||||||
maxPrice?.toFixed(2) !== minPrice?.toFixed(2)
|
marketPriceMax?.toFixed(2) !== marketPriceMin?.toFixed(2)
|
||||||
}"
|
}"
|
||||||
[unit]="SymbolProfile?.currency"
|
[unit]="SymbolProfile?.currency"
|
||||||
[value]="maxPrice"
|
[value]="marketPriceMax"
|
||||||
>Maximum Price</gf-value
|
>Maximum Price</gf-value
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
|
@ -411,8 +411,8 @@ export class DataService {
|
|||||||
)
|
)
|
||||||
.pipe(
|
.pipe(
|
||||||
map((data) => {
|
map((data) => {
|
||||||
if (data.orders) {
|
if (data.activities) {
|
||||||
for (const order of data.orders) {
|
for (const order of data.activities) {
|
||||||
order.createdAt = parseISO(order.createdAt as unknown as string);
|
order.createdAt = parseISO(order.createdAt as unknown as string);
|
||||||
order.date = parseISO(order.date as unknown as string);
|
order.date = parseISO(order.date as unknown as string);
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ import {
|
|||||||
import { Tag } from '@prisma/client';
|
import { Tag } from '@prisma/client';
|
||||||
|
|
||||||
export interface PortfolioHoldingResponse {
|
export interface PortfolioHoldingResponse {
|
||||||
|
activities: Activity[];
|
||||||
averagePrice: number;
|
averagePrice: number;
|
||||||
dataProviderInfo: DataProviderInfo;
|
dataProviderInfo: DataProviderInfo;
|
||||||
dividendInBaseCurrency: number;
|
dividendInBaseCurrency: number;
|
||||||
@ -22,13 +23,12 @@ export interface PortfolioHoldingResponse {
|
|||||||
historicalData: HistoricalDataItem[];
|
historicalData: HistoricalDataItem[];
|
||||||
investment: number;
|
investment: number;
|
||||||
marketPrice: number;
|
marketPrice: number;
|
||||||
maxPrice: number;
|
marketPriceMax: number;
|
||||||
minPrice: number;
|
marketPriceMin: number;
|
||||||
netPerformance: number;
|
netPerformance: number;
|
||||||
netPerformancePercent: number;
|
netPerformancePercent: number;
|
||||||
netPerformancePercentWithCurrencyEffect: number;
|
netPerformancePercentWithCurrencyEffect: number;
|
||||||
netPerformanceWithCurrencyEffect: number;
|
netPerformanceWithCurrencyEffect: number;
|
||||||
orders: Activity[];
|
|
||||||
quantity: number;
|
quantity: number;
|
||||||
SymbolProfile: EnhancedSymbolProfile;
|
SymbolProfile: EnhancedSymbolProfile;
|
||||||
tags: Tag[];
|
tags: Tag[];
|
||||||
|
Loading…
x
Reference in New Issue
Block a user