@cranberry-money/shared-services 1.2.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/services/portfolios/allocations/index.d.ts +7 -0
- package/dist/services/portfolios/allocations/index.d.ts.map +1 -0
- package/dist/services/portfolios/allocations/index.js +6 -0
- package/dist/services/portfolios/allocations/service.d.ts +6 -0
- package/dist/services/portfolios/allocations/service.d.ts.map +1 -0
- package/dist/services/portfolios/allocations/service.js +19 -0
- package/dist/services/portfolios/allocations/types.d.ts +17 -0
- package/dist/services/portfolios/allocations/types.d.ts.map +1 -0
- package/dist/services/portfolios/allocations/types.js +4 -0
- package/dist/services/portfolios/allocations/utils.d.ts +3 -0
- package/dist/services/portfolios/allocations/utils.d.ts.map +1 -0
- package/dist/services/portfolios/allocations/utils.js +7 -0
- package/dist/services/portfolios/holdings/index.d.ts +7 -0
- package/dist/services/portfolios/holdings/index.d.ts.map +1 -0
- package/dist/services/portfolios/holdings/index.js +6 -0
- package/dist/services/portfolios/holdings/service.d.ts +10 -0
- package/dist/services/portfolios/holdings/service.d.ts.map +1 -0
- package/dist/services/portfolios/holdings/service.js +53 -0
- package/dist/services/portfolios/holdings/types.d.ts +42 -0
- package/dist/services/portfolios/holdings/types.d.ts.map +1 -0
- package/dist/services/portfolios/holdings/types.js +4 -0
- package/dist/services/portfolios/holdings/utils.d.ts +8 -0
- package/dist/services/portfolios/holdings/utils.d.ts.map +1 -0
- package/dist/services/portfolios/holdings/utils.js +82 -0
- package/dist/services/portfolios/index.d.ts +2 -0
- package/dist/services/portfolios/index.d.ts.map +1 -1
- package/dist/services/portfolios/index.js +3 -0
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/services/portfolios/allocations/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { AssetAllocation, AssetAllocationPayload } from './types';
|
|
2
|
+
export declare const getPortfolioAllocations: (portfolioUuid: string) => Promise<import("axios").AxiosResponse<AssetAllocation[], any>>;
|
|
3
|
+
export declare const createAssetAllocation: (data: AssetAllocationPayload) => Promise<import("axios").AxiosResponse<AssetAllocation, any>>;
|
|
4
|
+
export declare const updateAssetAllocation: (uuid: string, data: Partial<AssetAllocationPayload>) => Promise<import("axios").AxiosResponse<AssetAllocation, any>>;
|
|
5
|
+
export declare const deleteAssetAllocation: (uuid: string) => Promise<import("axios").AxiosResponse<void, any>>;
|
|
6
|
+
//# sourceMappingURL=service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../../../src/services/portfolios/allocations/service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAC;AAKvE,eAAO,MAAM,uBAAuB,GAAI,eAAe,MAAM,mEAK5D,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAAI,MAAM,sBAAsB,iEAEjE,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAAI,MAAM,MAAM,EAAE,MAAM,OAAO,CAAC,sBAAsB,CAAC,iEAExF,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAAI,MAAM,MAAM,sDAEjD,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { webApiClient } from '../../../api/apiClient';
|
|
2
|
+
import { API_ENDPOINTS } from '../constants';
|
|
3
|
+
// ASSET ALLOCATIONS API FUNCTIONS
|
|
4
|
+
// Fetch allocations for a specific portfolio
|
|
5
|
+
export const getPortfolioAllocations = (portfolioUuid) => {
|
|
6
|
+
// Always sort by created_at to show allocations in their creation order
|
|
7
|
+
return webApiClient.get(`${API_ENDPOINTS.PORTFOLIOS}${portfolioUuid}/allocations/`, {
|
|
8
|
+
params: { order_by: 'created_at' },
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
export const createAssetAllocation = (data) => {
|
|
12
|
+
return webApiClient.post(API_ENDPOINTS.ASSET_ALLOCATIONS, data);
|
|
13
|
+
};
|
|
14
|
+
export const updateAssetAllocation = (uuid, data) => {
|
|
15
|
+
return webApiClient.patch(`${API_ENDPOINTS.ASSET_ALLOCATIONS}${uuid}/`, data);
|
|
16
|
+
};
|
|
17
|
+
export const deleteAssetAllocation = (uuid) => {
|
|
18
|
+
return webApiClient.delete(`${API_ENDPOINTS.ASSET_ALLOCATIONS}${uuid}/`);
|
|
19
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Asset Allocations types and interfaces
|
|
3
|
+
*/
|
|
4
|
+
export interface AssetAllocation {
|
|
5
|
+
uuid: string;
|
|
6
|
+
portfolio: string;
|
|
7
|
+
instrument: string;
|
|
8
|
+
instrumentName: string;
|
|
9
|
+
instrumentSymbol: string;
|
|
10
|
+
percentage: string;
|
|
11
|
+
}
|
|
12
|
+
export interface AssetAllocationPayload {
|
|
13
|
+
portfolio: string;
|
|
14
|
+
instrument: string;
|
|
15
|
+
percentage: string | number;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/services/portfolios/allocations/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;CACpB;AAGD,MAAM,WAAW,sBAAsB;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,GAAG,MAAM,CAAC;CAC7B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../../src/services/portfolios/allocations/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAK/C,eAAO,MAAM,mBAAmB,GAAI,aAAa,eAAe,EAAE,KAAG,OAKpE,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// ASSET ALLOCATIONS UTILITY FUNCTIONS
|
|
2
|
+
// Utility function to validate if allocation percentages sum to 100%
|
|
3
|
+
export const validateAllocations = (allocations) => {
|
|
4
|
+
const totalPercentage = allocations.reduce((sum, allocation) => sum + parseFloat(allocation.percentage), 0);
|
|
5
|
+
// Allow for small floating point errors (e.g., 99.99 or 100.01)
|
|
6
|
+
return Math.abs(totalPercentage - 100) < 0.01;
|
|
7
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/services/portfolios/holdings/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { PaginatedResponse } from '../../../api/types';
|
|
2
|
+
import type { AssetHolding, AssetHoldingSnapshot, AssetHoldingFilters, AssetHoldingSnapshotFilters } from './types';
|
|
3
|
+
export type PaginatedAssetHoldings = PaginatedResponse<AssetHolding>;
|
|
4
|
+
export type PaginatedAssetHoldingSnapshots = PaginatedResponse<AssetHoldingSnapshot>;
|
|
5
|
+
export declare const getAssetHoldings: (filters?: AssetHoldingFilters) => Promise<import("axios").AxiosResponse<PaginatedAssetHoldings, any>>;
|
|
6
|
+
export declare const getPortfolioHoldings: (portfolioUuid: string, orderBy?: string) => Promise<import("axios").AxiosResponse<AssetHolding[], any>>;
|
|
7
|
+
export declare const getAssetHoldingByUuid: (uuid: string) => Promise<import("axios").AxiosResponse<AssetHolding, any>>;
|
|
8
|
+
export declare const getAssetHoldingSnapshots: (filters?: AssetHoldingSnapshotFilters) => Promise<import("axios").AxiosResponse<PaginatedAssetHoldingSnapshots, any>>;
|
|
9
|
+
export declare const getAssetHoldingSnapshotById: (id: number) => Promise<import("axios").AxiosResponse<AssetHoldingSnapshot, any>>;
|
|
10
|
+
//# sourceMappingURL=service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../../../src/services/portfolios/holdings/service.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAE5D,OAAO,KAAK,EAAE,YAAY,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,2BAA2B,EAAE,MAAM,SAAS,CAAC;AAGpH,MAAM,MAAM,sBAAsB,GAAG,iBAAiB,CAAC,YAAY,CAAC,CAAC;AACrE,MAAM,MAAM,8BAA8B,GAAG,iBAAiB,CAAC,oBAAoB,CAAC,CAAC;AAKrF,eAAO,MAAM,gBAAgB,GAAI,UAAU,mBAAmB,wEAW7D,CAAC;AAGF,eAAO,MAAM,oBAAoB,GAAI,eAAe,MAAM,EAAE,UAAU,MAAM,gEAK3E,CAAC;AAGF,eAAO,MAAM,qBAAqB,GAAI,MAAM,MAAM,8DAEjD,CAAC;AAKF,eAAO,MAAM,wBAAwB,GAAI,UAAU,2BAA2B,gFAW7E,CAAC;AAGF,eAAO,MAAM,2BAA2B,GAAI,IAAI,MAAM,sEAErD,CAAC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { webApiClient } from '../../../api/apiClient';
|
|
2
|
+
import { API_ENDPOINTS } from '../constants';
|
|
3
|
+
// ASSET HOLDINGS API FUNCTIONS
|
|
4
|
+
// Fetch asset holdings with optional filtering
|
|
5
|
+
export const getAssetHoldings = (filters) => {
|
|
6
|
+
const params = {};
|
|
7
|
+
if (filters?.portfolioId)
|
|
8
|
+
params.portfolio_id = filters.portfolioId;
|
|
9
|
+
if (filters?.portfolioUuid)
|
|
10
|
+
params.portfolio_uuid = filters.portfolioUuid;
|
|
11
|
+
if (filters?.instrument)
|
|
12
|
+
params.instrument = filters.instrument;
|
|
13
|
+
if (filters?.minQuantity)
|
|
14
|
+
params.min_quantity = filters.minQuantity.toString();
|
|
15
|
+
if (filters?.maxQuantity)
|
|
16
|
+
params.max_quantity = filters.maxQuantity.toString();
|
|
17
|
+
if (filters?.orderBy)
|
|
18
|
+
params.order_by = filters.orderBy;
|
|
19
|
+
return webApiClient.get(API_ENDPOINTS.ASSET_HOLDINGS, { params });
|
|
20
|
+
};
|
|
21
|
+
// Fetch holdings for a specific portfolio
|
|
22
|
+
export const getPortfolioHoldings = (portfolioUuid, orderBy) => {
|
|
23
|
+
const params = {};
|
|
24
|
+
if (orderBy)
|
|
25
|
+
params.order_by = orderBy;
|
|
26
|
+
return webApiClient.get(`${API_ENDPOINTS.PORTFOLIOS}${portfolioUuid}/holdings/`, { params });
|
|
27
|
+
};
|
|
28
|
+
// Get asset holding by UUID
|
|
29
|
+
export const getAssetHoldingByUuid = (uuid) => {
|
|
30
|
+
return webApiClient.get(`${API_ENDPOINTS.ASSET_HOLDINGS}${uuid}/`);
|
|
31
|
+
};
|
|
32
|
+
// ASSET HOLDING SNAPSHOTS API FUNCTIONS
|
|
33
|
+
// Fetch asset holding snapshots with optional filtering
|
|
34
|
+
export const getAssetHoldingSnapshots = (filters) => {
|
|
35
|
+
const params = {};
|
|
36
|
+
if (filters?.assetHoldingId)
|
|
37
|
+
params.asset_holding_id = filters.assetHoldingId;
|
|
38
|
+
if (filters?.portfolioId)
|
|
39
|
+
params.portfolio_id = filters.portfolioId;
|
|
40
|
+
if (filters?.reason)
|
|
41
|
+
params.reason = filters.reason;
|
|
42
|
+
if (filters?.startDate)
|
|
43
|
+
params.start_date = filters.startDate;
|
|
44
|
+
if (filters?.endDate)
|
|
45
|
+
params.end_date = filters.endDate;
|
|
46
|
+
if (filters?.orderBy)
|
|
47
|
+
params.order_by = filters.orderBy;
|
|
48
|
+
return webApiClient.get(API_ENDPOINTS.ASSET_HOLDING_SNAPSHOTS, { params });
|
|
49
|
+
};
|
|
50
|
+
// Get asset holding snapshot by ID
|
|
51
|
+
export const getAssetHoldingSnapshotById = (id) => {
|
|
52
|
+
return webApiClient.get(`${API_ENDPOINTS.ASSET_HOLDING_SNAPSHOTS}${id}/`);
|
|
53
|
+
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Asset Holdings types and interfaces
|
|
3
|
+
*/
|
|
4
|
+
export interface AssetHolding {
|
|
5
|
+
uuid: string;
|
|
6
|
+
portfolio: string;
|
|
7
|
+
instrument: any;
|
|
8
|
+
instrumentName: string;
|
|
9
|
+
instrumentSymbol: string;
|
|
10
|
+
quantity: number;
|
|
11
|
+
createdAt: string;
|
|
12
|
+
updatedAt: string;
|
|
13
|
+
}
|
|
14
|
+
export interface AssetHoldingSnapshot {
|
|
15
|
+
id: number;
|
|
16
|
+
assetHolding: string;
|
|
17
|
+
portfolioId: number;
|
|
18
|
+
instrumentName: string;
|
|
19
|
+
instrumentSymbol: string;
|
|
20
|
+
quantity: number;
|
|
21
|
+
snapshotReason: 'TRADE' | 'REBALANCE' | 'VALUATION' | 'AUDIT';
|
|
22
|
+
snapshotDate: string;
|
|
23
|
+
createdAt: string;
|
|
24
|
+
updatedAt: string;
|
|
25
|
+
}
|
|
26
|
+
export interface AssetHoldingFilters {
|
|
27
|
+
portfolioId?: string;
|
|
28
|
+
portfolioUuid?: string;
|
|
29
|
+
instrument?: string;
|
|
30
|
+
minQuantity?: number;
|
|
31
|
+
maxQuantity?: number;
|
|
32
|
+
orderBy?: string;
|
|
33
|
+
}
|
|
34
|
+
export interface AssetHoldingSnapshotFilters {
|
|
35
|
+
assetHoldingId?: string;
|
|
36
|
+
portfolioId?: string;
|
|
37
|
+
reason?: 'TRADE' | 'REBALANCE' | 'VALUATION' | 'AUDIT';
|
|
38
|
+
startDate?: string;
|
|
39
|
+
endDate?: string;
|
|
40
|
+
orderBy?: string;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/services/portfolios/holdings/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,GAAG,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAGD,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,OAAO,GAAG,WAAW,GAAG,WAAW,GAAG,OAAO,CAAC;IAC9D,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAGD,MAAM,WAAW,mBAAmB;IAClC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAGD,MAAM,WAAW,2BAA2B;IAC1C,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,OAAO,GAAG,WAAW,GAAG,WAAW,GAAG,OAAO,CAAC;IACvD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { AssetHolding } from './types';
|
|
2
|
+
export declare const calculatePortfolioValue: (holdings: AssetHolding[], prices: Record<string, number>) => number;
|
|
3
|
+
export declare const calculateHoldingAllocations: (holdings: AssetHolding[]) => Record<string, number>;
|
|
4
|
+
export declare const groupHoldingsByInstrument: (holdings: AssetHolding[]) => Record<string, AssetHolding[]>;
|
|
5
|
+
export declare const filterHoldingsByMinQuantity: (holdings: AssetHolding[], minQuantity: number) => AssetHolding[];
|
|
6
|
+
export declare const sortHoldings: (holdings: AssetHolding[], sortBy: "quantity" | "symbol" | "name" | "createdAt", direction?: "asc" | "desc") => AssetHolding[];
|
|
7
|
+
export declare const formatQuantity: (quantity: number) => string;
|
|
8
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../../src/services/portfolios/holdings/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAK5C,eAAO,MAAM,uBAAuB,GAAI,UAAU,YAAY,EAAE,EAAE,QAAQ,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAG,MAKlG,CAAC;AAGF,eAAO,MAAM,2BAA2B,GAAI,UAAU,YAAY,EAAE,KAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAW3F,CAAC;AAGF,eAAO,MAAM,yBAAyB,GAAI,UAAU,YAAY,EAAE,KAAG,MAAM,CAAC,MAAM,EAAE,YAAY,EAAE,CAYjG,CAAC;AAGF,eAAO,MAAM,2BAA2B,GAAI,UAAU,YAAY,EAAE,EAAE,aAAa,MAAM,KAAG,YAAY,EAEvG,CAAC;AAGF,eAAO,MAAM,YAAY,GACvB,UAAU,YAAY,EAAE,EACxB,QAAQ,UAAU,GAAG,QAAQ,GAAG,MAAM,GAAG,WAAW,EACpD,YAAW,KAAK,GAAG,MAAe,KACjC,YAAY,EAsCd,CAAC;AAGF,eAAO,MAAM,cAAc,GAAI,UAAU,MAAM,KAAG,MAQjD,CAAC"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// ASSET HOLDINGS UTILITY FUNCTIONS
|
|
2
|
+
// Calculate total portfolio value based on holdings and prices
|
|
3
|
+
export const calculatePortfolioValue = (holdings, prices) => {
|
|
4
|
+
return holdings.reduce((total, holding) => {
|
|
5
|
+
const price = prices[holding.instrument.uuid] || 0;
|
|
6
|
+
return total + holding.quantity * price;
|
|
7
|
+
}, 0);
|
|
8
|
+
};
|
|
9
|
+
// Calculate holding allocation percentages within a portfolio
|
|
10
|
+
export const calculateHoldingAllocations = (holdings) => {
|
|
11
|
+
const totalQuantity = holdings.reduce((sum, holding) => sum + holding.quantity, 0);
|
|
12
|
+
if (totalQuantity === 0)
|
|
13
|
+
return {};
|
|
14
|
+
const allocations = {};
|
|
15
|
+
holdings.forEach((holding) => {
|
|
16
|
+
allocations[holding.instrument.uuid] = (holding.quantity / totalQuantity) * 100;
|
|
17
|
+
});
|
|
18
|
+
return allocations;
|
|
19
|
+
};
|
|
20
|
+
// Group holdings by instrument for aggregated view
|
|
21
|
+
export const groupHoldingsByInstrument = (holdings) => {
|
|
22
|
+
return holdings.reduce((groups, holding) => {
|
|
23
|
+
const instrumentUuid = holding.instrument.uuid;
|
|
24
|
+
if (!groups[instrumentUuid]) {
|
|
25
|
+
groups[instrumentUuid] = [];
|
|
26
|
+
}
|
|
27
|
+
groups[instrumentUuid].push(holding);
|
|
28
|
+
return groups;
|
|
29
|
+
}, {});
|
|
30
|
+
};
|
|
31
|
+
// Filter holdings with quantities above a threshold
|
|
32
|
+
export const filterHoldingsByMinQuantity = (holdings, minQuantity) => {
|
|
33
|
+
return holdings.filter((holding) => holding.quantity >= minQuantity);
|
|
34
|
+
};
|
|
35
|
+
// Sort holdings by various criteria
|
|
36
|
+
export const sortHoldings = (holdings, sortBy, direction = 'desc') => {
|
|
37
|
+
return [...holdings].sort((a, b) => {
|
|
38
|
+
let valueA;
|
|
39
|
+
let valueB;
|
|
40
|
+
switch (sortBy) {
|
|
41
|
+
case 'quantity':
|
|
42
|
+
valueA = a.quantity;
|
|
43
|
+
valueB = b.quantity;
|
|
44
|
+
break;
|
|
45
|
+
case 'symbol':
|
|
46
|
+
valueA = a.instrumentSymbol;
|
|
47
|
+
valueB = b.instrumentSymbol;
|
|
48
|
+
break;
|
|
49
|
+
case 'name':
|
|
50
|
+
valueA = a.instrumentName;
|
|
51
|
+
valueB = b.instrumentName;
|
|
52
|
+
break;
|
|
53
|
+
case 'createdAt':
|
|
54
|
+
valueA = a.createdAt;
|
|
55
|
+
valueB = b.createdAt;
|
|
56
|
+
break;
|
|
57
|
+
default:
|
|
58
|
+
return 0;
|
|
59
|
+
}
|
|
60
|
+
if (typeof valueA === 'string' && typeof valueB === 'string') {
|
|
61
|
+
const comparison = valueA.localeCompare(valueB);
|
|
62
|
+
return direction === 'asc' ? comparison : -comparison;
|
|
63
|
+
}
|
|
64
|
+
if (typeof valueA === 'number' && typeof valueB === 'number') {
|
|
65
|
+
const comparison = valueA - valueB;
|
|
66
|
+
return direction === 'asc' ? comparison : -comparison;
|
|
67
|
+
}
|
|
68
|
+
return 0;
|
|
69
|
+
});
|
|
70
|
+
};
|
|
71
|
+
// Format quantity for display with proper units
|
|
72
|
+
export const formatQuantity = (quantity) => {
|
|
73
|
+
if (quantity >= 1000000) {
|
|
74
|
+
return `${(quantity / 1000000).toFixed(1)}M`;
|
|
75
|
+
}
|
|
76
|
+
else if (quantity >= 1000) {
|
|
77
|
+
return `${(quantity / 1000).toFixed(1)}K`;
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
return quantity.toString();
|
|
81
|
+
}
|
|
82
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/services/portfolios/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,aAAa,CAAC;AAC5B,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/services/portfolios/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,aAAa,CAAC;AAC5B,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;AAGxB,OAAO,KAAK,WAAW,MAAM,eAAe,CAAC;AAC7C,OAAO,KAAK,QAAQ,MAAM,YAAY,CAAC"}
|