@decafhub/decaf-client-extras 0.0.4 → 0.1.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/.release-please-manifest.json +1 -1
- package/CHANGELOG.md +22 -0
- package/commons/-currency.d.ts +22 -6
- package/commons/-currency.js +12 -6
- package/commons/{-date-type.d.ts → -datetype.d.ts} +2 -2
- package/commons/{-date-type.js → -datetype.js} +2 -2
- package/commons/-id.d.ts +109 -17
- package/commons/-id.js +73 -0
- package/commons/index.d.ts +4 -1
- package/commons/index.js +17 -1
- package/es/commons/-currency.d.ts +22 -6
- package/es/commons/-currency.js +12 -6
- package/es/commons/{-date-type.d.ts → -datetype.d.ts} +2 -2
- package/es/commons/{-date-type.js → -datetype.js} +1 -1
- package/es/commons/-id.d.ts +109 -17
- package/es/commons/-id.js +70 -1
- package/es/commons/index.d.ts +4 -1
- package/es/commons/index.js +4 -1
- package/es/reports/valuation/-remote-valuation-report-portfolio.d.ts +15 -15
- package/es/reports/valuation/-remote-valuation-report-portfolio.js +32 -32
- package/es/reports/valuation/-remote-valuation-report-shared.d.ts +4 -4
- package/es/reports/valuation/-remote-valuation-report-shared.js +29 -26
- package/es/reports/valuation/-valuation-report-consolidated.d.ts +1 -1
- package/es/reports/valuation/-valuation-report-holdings-tree/-machinery.js +6 -5
- package/es/reports/valuation/-valuation-report-portfolio.d.ts +14 -14
- package/es/reports/valuation/-valuation-report-shared.d.ts +7 -7
- package/nix/default.nix +59 -0
- package/nix/sources.json +14 -0
- package/nix/sources.nix +194 -0
- package/package.json +16 -16
- package/reports/valuation/-remote-valuation-report-consolidated.js +1 -1
- package/reports/valuation/-remote-valuation-report-portfolio.d.ts +15 -15
- package/reports/valuation/-remote-valuation-report-portfolio.js +32 -32
- package/reports/valuation/-remote-valuation-report-shared.d.ts +4 -4
- package/reports/valuation/-remote-valuation-report-shared.js +28 -25
- package/reports/valuation/-valuation-report-consolidated.d.ts +1 -1
- package/reports/valuation/-valuation-report-holdings-tree/-machinery.js +14 -11
- package/reports/valuation/-valuation-report-portfolio.d.ts +14 -14
- package/reports/valuation/-valuation-report-shared.d.ts +7 -7
- package/shell.nix +5 -20
- package/src/commons/-currency.test.ts +27 -0
- package/src/commons/-currency.ts +24 -9
- package/src/commons/-datetype.test.ts +10 -0
- package/src/commons/{-date-type.ts → -datetype.ts} +1 -1
- package/src/commons/-id.test.ts +27 -0
- package/src/commons/-id.ts +112 -17
- package/src/commons/index.ts +4 -1
- package/src/index.test.ts +34 -5
- package/src/reports/valuation/-remote-valuation-report-portfolio.ts +54 -54
- package/src/reports/valuation/-remote-valuation-report-shared.ts +34 -31
- package/src/reports/valuation/-valuation-report-holdings-tree/-machinery.ts +14 -5
- package/src/reports/valuation/-valuation-report-portfolio.ts +20 -20
- package/src/reports/valuation/-valuation-report-shared.ts +13 -6
package/src/commons/-id.ts
CHANGED
|
@@ -1,72 +1,167 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* This module provides a collection of DECAF record identifier type
|
|
3
|
+
* definitions. It is not exhaustive and it will be improved on an ongoing
|
|
4
|
+
* basis.
|
|
5
|
+
*
|
|
6
|
+
* Typically, a DECAF record identifier is either number or string. Some DECAF
|
|
7
|
+
* API endoints can consume string values even though a number is expected. We
|
|
8
|
+
* are sticking here to the original type: No `number | string` definitions.
|
|
9
|
+
*
|
|
10
|
+
* Methodologically, we are using a type trick to emulate newtypes in this
|
|
11
|
+
* module: For example, DECAF artifact identifier type is defined as:
|
|
12
|
+
*
|
|
13
|
+
* ```ts
|
|
14
|
+
* export type DecafArtifactId = number & { readonly __tag: unique symbol };
|
|
15
|
+
* ```
|
|
16
|
+
*
|
|
17
|
+
* In runtime, there is only a number. The `& { readonly __tag: unique symbol }`
|
|
18
|
+
* is provided to the compiler to distinguish in between `number` identifier
|
|
19
|
+
* values which are representing different DECAF record types.
|
|
20
|
+
*
|
|
21
|
+
* The construction and deconstruction of DECAF record identifiers are done via,
|
|
22
|
+
* respecively, `mkDecafRecordId` and `unDecafRecordId`:
|
|
23
|
+
*
|
|
24
|
+
* ```ts
|
|
25
|
+
* const exampleDecafArtifactIdValue: number = unDecafRecordId(exampleDecafArtifactId);
|
|
26
|
+
* const exampleDecafArtifactId: DecafArtifactId = mkDecafRecordId(42);
|
|
27
|
+
* expect(exampleDecafArtifactIdValue).toBe(42);
|
|
28
|
+
*
|
|
29
|
+
* const exampleDecafActionId: DecafActionId = mkDecafRecordId(42);
|
|
30
|
+
* const exampleDecafActionIdValue: number = unDecafRecordId(exampleDecafActionId);
|
|
31
|
+
* expect(exampleDecafActionIdValue).toBe(42);
|
|
32
|
+
*
|
|
33
|
+
* const exampleDecafArtifactTypeId: DecafArtifactTypeId = mkDecafRecordId('CCY');
|
|
34
|
+
* const exampleDecafArtifactTypeIdValue: string = unDecafRecordId(exampleDecafArtifactTypeId);
|
|
35
|
+
* expect(exampleDecafArtifactTypeIdValue).toBe('CCY');
|
|
36
|
+
* ```
|
|
37
|
+
*
|
|
38
|
+
* To re-iterate, the runtime representation is not affected by how DECAF record
|
|
39
|
+
* identifier types are defined:
|
|
40
|
+
*
|
|
41
|
+
* ```ts
|
|
42
|
+
* interface DecafArtifact {
|
|
43
|
+
* id: DecafArtifactId;
|
|
44
|
+
* type: DecafArtifactTypeId;
|
|
45
|
+
* }
|
|
46
|
+
*
|
|
47
|
+
* const exampleDecafArtifact: DecafArtifact = { id: mkDecafRecordId(10), type: mkDecafRecordId('CCY') };
|
|
48
|
+
* expect(exampleDecafArtifact).toStrictEqual({ id: 10, type: 'CCY' });
|
|
49
|
+
* ```
|
|
50
|
+
*
|
|
51
|
+
* @module
|
|
52
|
+
*/
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Type definition covering all possible DECAF record identifiers based on
|
|
56
|
+
* `number` values.
|
|
57
|
+
*
|
|
58
|
+
* This type definition must be extended whenever there is a new DECAF record
|
|
59
|
+
* identifier is defined in this module.
|
|
60
|
+
*/
|
|
61
|
+
export type _DecafRecordIdFromNumber = DecafArtifactId | DecafActionId;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Type definition covering all possible DECAF record identifiers based on
|
|
65
|
+
* `string` values.
|
|
66
|
+
*
|
|
67
|
+
* This type definition must be extended whenever there is a new DECAF record
|
|
68
|
+
* identifier is defined in this module.
|
|
69
|
+
*/
|
|
70
|
+
export type _DecafRecordIdFromString = DecafArtifactTypeId;
|
|
71
|
+
|
|
72
|
+
/* Signature for overloaded `mkDecafRecordId` function consuming a `number`. */
|
|
73
|
+
export function mkDecafRecordId<T extends _DecafRecordIdFromNumber>(x: number): T;
|
|
74
|
+
|
|
75
|
+
/* Signature for overloaded `mkDecafRecordId` function consuming a `string`. */
|
|
76
|
+
export function mkDecafRecordId<T extends _DecafRecordIdFromString>(x: string): T;
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Constructor for DECAF record identifiers.
|
|
80
|
+
*
|
|
81
|
+
* @param x Value to create DECAF record identifier from.
|
|
82
|
+
* @returns DECAF record identifier of type deduced from call-site usage.
|
|
83
|
+
*/
|
|
84
|
+
export function mkDecafRecordId<T>(x: any): T {
|
|
85
|
+
return x as T;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/* Signature for overloaded `unDecafRecordId` function producing a `number`. */
|
|
89
|
+
export function unDecafRecordId<T extends _DecafRecordIdFromNumber>(x: T): number;
|
|
90
|
+
|
|
91
|
+
/* Signature for overloaded `unDecafRecordId` function producing a `string`. */
|
|
92
|
+
export function unDecafRecordId<K extends _DecafRecordIdFromString>(x: K): string;
|
|
2
93
|
|
|
3
94
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
95
|
+
* Deconstructor for DECAF record identifiers.
|
|
96
|
+
*
|
|
97
|
+
* @param x DECAF record identifier.
|
|
98
|
+
* @returns Value of the DECAF record identifier (deduced from call-site usage).
|
|
6
99
|
*/
|
|
7
|
-
export
|
|
100
|
+
export function unDecafRecordId<T>(x: T): any {
|
|
101
|
+
return x as unknown;
|
|
102
|
+
}
|
|
8
103
|
|
|
9
104
|
/**
|
|
10
105
|
* Type definition for DECAF artifact identifiers.
|
|
11
106
|
*/
|
|
12
|
-
export type
|
|
107
|
+
export type DecafArtifactId = number & { readonly __tag: unique symbol };
|
|
13
108
|
|
|
14
109
|
/**
|
|
15
110
|
* Type definition for DECAF artifact type identifiers.
|
|
16
111
|
*/
|
|
17
|
-
export type
|
|
112
|
+
export type DecafArtifactTypeId = string & { readonly __tag: unique symbol };
|
|
18
113
|
|
|
19
114
|
/**
|
|
20
115
|
* Type definition for DECAF share class identifiers.
|
|
21
116
|
*/
|
|
22
|
-
export type
|
|
117
|
+
export type DecafShareClassId = number & { readonly __tag: unique symbol };
|
|
23
118
|
|
|
24
119
|
/**
|
|
25
120
|
* Type definition for DECAF principal identifiers.
|
|
26
121
|
*/
|
|
27
|
-
export type
|
|
122
|
+
export type DecafPrincipalId = number & { readonly __tag: unique symbol };
|
|
28
123
|
|
|
29
124
|
/**
|
|
30
125
|
* Type definition for DECAF institution identifiers.
|
|
31
126
|
*/
|
|
32
|
-
export type
|
|
127
|
+
export type DecafInstitutionId = number & { readonly __tag: unique symbol };
|
|
33
128
|
|
|
34
129
|
/**
|
|
35
130
|
* Type definition for DECAF team identifiers.
|
|
36
131
|
*/
|
|
37
|
-
export type
|
|
132
|
+
export type DecafTeamId = number & { readonly __tag: unique symbol };
|
|
38
133
|
|
|
39
134
|
/**
|
|
40
135
|
* Type definition for DECAF portfolio identifiers.
|
|
41
136
|
*/
|
|
42
|
-
export type
|
|
137
|
+
export type DecafPortfolioId = number & { readonly __tag: unique symbol };
|
|
43
138
|
|
|
44
139
|
/**
|
|
45
140
|
* Type definition for DECAF portfolio group identifiers.
|
|
46
141
|
*/
|
|
47
|
-
export type
|
|
142
|
+
export type DecafPortfolioGroupId = number & { readonly __tag: unique symbol };
|
|
48
143
|
|
|
49
144
|
/**
|
|
50
145
|
* Type definition for DECAF account identifiers.
|
|
51
146
|
*/
|
|
52
|
-
export type
|
|
147
|
+
export type DecafAccountId = number & { readonly __tag: unique symbol };
|
|
53
148
|
|
|
54
149
|
/**
|
|
55
150
|
* Type definition for DECAF OHLC series identifiers.
|
|
56
151
|
*/
|
|
57
|
-
export type
|
|
152
|
+
export type DecafOhlcSeriesId = number & { readonly __tag: unique symbol };
|
|
58
153
|
|
|
59
154
|
/**
|
|
60
155
|
* Type definition for DECAF share class fee schedule identifiers.
|
|
61
156
|
*/
|
|
62
|
-
export type
|
|
157
|
+
export type DecafShareClassFeeScheduleId = number & { readonly __tag: unique symbol };
|
|
63
158
|
|
|
64
159
|
/**
|
|
65
160
|
* Type definition for DECAF action identifiers.
|
|
66
161
|
*/
|
|
67
|
-
export type
|
|
162
|
+
export type DecafActionId = number & { readonly __tag: unique symbol };
|
|
68
163
|
|
|
69
164
|
/**
|
|
70
165
|
* Type definition for DECAF external valuation identifiers.
|
|
71
166
|
*/
|
|
72
|
-
export type
|
|
167
|
+
export type DecafExternalValuationId = number & { readonly __tag: unique symbol };
|
package/src/commons/index.ts
CHANGED
package/src/index.test.ts
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import { buildDecafClient, DecafClient, gql } from '@decafhub/decaf-client';
|
|
2
|
-
import {
|
|
2
|
+
import { PDateTime, safeDiv, zero } from '@telostat/prelude';
|
|
3
3
|
import { fail } from 'assert';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import { DecafPortfolioId, mkCurrencyCodeError } from './commons';
|
|
5
|
+
import { makeValuationReportHoldingsTree } from './reports/valuation/';
|
|
6
|
+
import {
|
|
7
|
+
fetchPortfolioValuationReport,
|
|
8
|
+
fetchRemotePortfolioValuationReport,
|
|
9
|
+
} from './reports/valuation/-remote-valuation-report-portfolio';
|
|
6
10
|
|
|
7
11
|
const API_URL = process.env.TESTING_API_URL;
|
|
8
12
|
const API_KEY = process.env.TESTING_API_KEY;
|
|
@@ -19,7 +23,7 @@ const FIRST_PORTFOLIO_QUERY = gql`
|
|
|
19
23
|
|
|
20
24
|
describe('Main', () => {
|
|
21
25
|
let client: DecafClient;
|
|
22
|
-
let portfolioId:
|
|
26
|
+
let portfolioId: DecafPortfolioId;
|
|
23
27
|
|
|
24
28
|
beforeAll(() => {
|
|
25
29
|
jest.resetModules();
|
|
@@ -52,7 +56,7 @@ describe('Main', () => {
|
|
|
52
56
|
portfolio: portfolioId,
|
|
53
57
|
date: PDateTime(new Date()).format('YYYY-MM-DD'),
|
|
54
58
|
dateType: 'settlement',
|
|
55
|
-
currency:
|
|
59
|
+
currency: mkCurrencyCodeError('EUR'),
|
|
56
60
|
});
|
|
57
61
|
eValue.caseOf({
|
|
58
62
|
Left: (e) => fail('Error while fetching the remote portfolio report: ' + e.msg),
|
|
@@ -64,4 +68,29 @@ describe('Main', () => {
|
|
|
64
68
|
},
|
|
65
69
|
});
|
|
66
70
|
});
|
|
71
|
+
|
|
72
|
+
test('get a portfolio report, check the tree', async () => {
|
|
73
|
+
const eValue = await fetchPortfolioValuationReport(client, {
|
|
74
|
+
portfolio: portfolioId,
|
|
75
|
+
date: PDateTime(new Date()).format('YYYY-MM-DD'),
|
|
76
|
+
dateType: 'settlement',
|
|
77
|
+
currency: mkCurrencyCodeError('EUR'),
|
|
78
|
+
});
|
|
79
|
+
eValue.caseOf({
|
|
80
|
+
Left: (e) => fail('Error while fetching the remote portfolio report: ' + e.msg),
|
|
81
|
+
Right: (value) => {
|
|
82
|
+
console.log(`Success! remote valuation for portfolio ID ${value.portfolio.id} is reported at ${value.asof}`);
|
|
83
|
+
|
|
84
|
+
expect(value).toBeDefined();
|
|
85
|
+
|
|
86
|
+
const nav = value.figures.nav;
|
|
87
|
+
const inv = value.figures.investment;
|
|
88
|
+
const holdings = value.holdings;
|
|
89
|
+
const tree = makeValuationReportHoldingsTree(nav, inv, holdings);
|
|
90
|
+
|
|
91
|
+
expect(tree).toBeDefined();
|
|
92
|
+
expect(safeDiv(tree.totals.netExposure, nav).orDefault(zero)).toEqual(tree.totals.netExposureRatio);
|
|
93
|
+
},
|
|
94
|
+
});
|
|
95
|
+
});
|
|
67
96
|
});
|
|
@@ -1,28 +1,28 @@
|
|
|
1
1
|
import { DecafClient } from '@decafhub/decaf-client';
|
|
2
2
|
import {
|
|
3
|
-
asDecimal,
|
|
4
3
|
CustomError,
|
|
5
4
|
customError,
|
|
5
|
+
decimalFromNullable,
|
|
6
6
|
Either,
|
|
7
7
|
Left,
|
|
8
8
|
Maybe,
|
|
9
|
-
maybeDecimal,
|
|
10
9
|
Right,
|
|
11
10
|
sanitizedNonEmptyText,
|
|
12
11
|
SDate,
|
|
13
12
|
SDateTime,
|
|
13
|
+
unsafeDecimal,
|
|
14
14
|
zero,
|
|
15
15
|
} from '@telostat/prelude';
|
|
16
16
|
import {
|
|
17
|
-
ActionId,
|
|
18
17
|
CurrencyCode,
|
|
19
18
|
DateType,
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
19
|
+
DecafActionId,
|
|
20
|
+
DecafExternalValuationId,
|
|
21
|
+
DecafOhlcSeriesId,
|
|
22
|
+
DecafPortfolioId,
|
|
23
|
+
DecafPrincipalId,
|
|
24
|
+
DecafShareClassFeeScheduleId,
|
|
25
|
+
DecafShareClassId,
|
|
26
26
|
} from '../../commons';
|
|
27
27
|
import { recompileBaseValuationReport, RemoteBaseValuationReport } from './-remote-valuation-report-shared';
|
|
28
28
|
import { PortfolioValuationReport, PortfolioValuationReportShareClassValue } from './-valuation-report-portfolio';
|
|
@@ -50,7 +50,7 @@ export interface PortfolioValuationReportQuery {
|
|
|
50
50
|
/**
|
|
51
51
|
* Portfolio the valuation report is requested for.
|
|
52
52
|
*/
|
|
53
|
-
portfolio:
|
|
53
|
+
portfolio: DecafPortfolioId;
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
/**
|
|
@@ -88,13 +88,13 @@ export interface RemoteValuationShareClassValue {
|
|
|
88
88
|
* Type definition for share class on the remote portfolio valuation report.
|
|
89
89
|
*/
|
|
90
90
|
export interface RemoteValuationShareClass {
|
|
91
|
-
id:
|
|
91
|
+
id: DecafShareClassId;
|
|
92
92
|
created: SDateTime;
|
|
93
|
-
creator:
|
|
93
|
+
creator: DecafPrincipalId;
|
|
94
94
|
updated: SDateTime;
|
|
95
|
-
updater:
|
|
95
|
+
updater: DecafPrincipalId;
|
|
96
96
|
guid: string;
|
|
97
|
-
portfolio:
|
|
97
|
+
portfolio: DecafPortfolioId;
|
|
98
98
|
name: string;
|
|
99
99
|
currency: CurrencyCode;
|
|
100
100
|
isin?: string;
|
|
@@ -106,11 +106,11 @@ export interface RemoteValuationShareClass {
|
|
|
106
106
|
subredperiod?: string;
|
|
107
107
|
freqmngt?: number;
|
|
108
108
|
freqperf?: number;
|
|
109
|
-
benchmark?:
|
|
109
|
+
benchmark?: DecafOhlcSeriesId;
|
|
110
110
|
description?: string;
|
|
111
|
-
feeschedules:
|
|
112
|
-
effectivefeeschedule?:
|
|
113
|
-
subscriptions:
|
|
111
|
+
feeschedules: DecafShareClassFeeScheduleId[];
|
|
112
|
+
effectivefeeschedule?: DecafShareClassFeeScheduleId;
|
|
113
|
+
subscriptions: DecafActionId[];
|
|
114
114
|
outstanding?: number;
|
|
115
115
|
}
|
|
116
116
|
|
|
@@ -119,14 +119,14 @@ export interface RemoteValuationShareClass {
|
|
|
119
119
|
* report.
|
|
120
120
|
*/
|
|
121
121
|
export interface RemoteValuationExternalValue {
|
|
122
|
-
id:
|
|
122
|
+
id: DecafExternalValuationId;
|
|
123
123
|
created: SDateTime;
|
|
124
|
-
creator:
|
|
124
|
+
creator: DecafPrincipalId;
|
|
125
125
|
updated: SDateTime;
|
|
126
|
-
updater:
|
|
126
|
+
updater: DecafPrincipalId;
|
|
127
127
|
guid: string;
|
|
128
|
-
portfolio:
|
|
129
|
-
shareclass?:
|
|
128
|
+
portfolio: DecafPortfolioId;
|
|
129
|
+
shareclass?: DecafShareClassId;
|
|
130
130
|
date: SDate;
|
|
131
131
|
ccy: CurrencyCode;
|
|
132
132
|
shares?: number;
|
|
@@ -203,7 +203,7 @@ export function toShareClassValue(x: RemoteValuationShareClassValue): PortfolioV
|
|
|
203
203
|
feeScheduleIds: x.shareclass.feeschedules,
|
|
204
204
|
effectiveFeeScheduleId: Maybe.fromNullable(x.shareclass.effectivefeeschedule),
|
|
205
205
|
subscriptionIds: x.shareclass.subscriptions,
|
|
206
|
-
outstanding:
|
|
206
|
+
outstanding: decimalFromNullable(x.shareclass.outstanding),
|
|
207
207
|
},
|
|
208
208
|
external: Maybe.fromNullable(x.external).map((ev) => ({
|
|
209
209
|
id: ev.id,
|
|
@@ -216,36 +216,36 @@ export function toShareClassValue(x: RemoteValuationShareClassValue): PortfolioV
|
|
|
216
216
|
shareclass: Maybe.fromNullable(ev.shareclass),
|
|
217
217
|
date: ev.date,
|
|
218
218
|
ccy: ev.ccy,
|
|
219
|
-
shares:
|
|
220
|
-
price:
|
|
221
|
-
nav:
|
|
222
|
-
aum:
|
|
223
|
-
hedgepnl:
|
|
224
|
-
feemngt:
|
|
225
|
-
feeperf:
|
|
226
|
-
otheraccrued:
|
|
227
|
-
totalaccrued:
|
|
228
|
-
subred:
|
|
229
|
-
perfdaily:
|
|
230
|
-
perfweekly:
|
|
231
|
-
perfmonthly:
|
|
232
|
-
perfytd:
|
|
233
|
-
perfstart:
|
|
234
|
-
coefficient:
|
|
219
|
+
shares: decimalFromNullable(ev.shares),
|
|
220
|
+
price: decimalFromNullable(ev.price),
|
|
221
|
+
nav: decimalFromNullable(ev.nav),
|
|
222
|
+
aum: decimalFromNullable(ev.aum),
|
|
223
|
+
hedgepnl: decimalFromNullable(ev.hedgepnl),
|
|
224
|
+
feemngt: decimalFromNullable(ev.feemngt),
|
|
225
|
+
feeperf: decimalFromNullable(ev.feeperf),
|
|
226
|
+
otheraccrued: decimalFromNullable(ev.otheraccrued),
|
|
227
|
+
totalaccrued: decimalFromNullable(ev.totalaccrued),
|
|
228
|
+
subred: decimalFromNullable(ev.subred),
|
|
229
|
+
perfdaily: decimalFromNullable(ev.perfdaily),
|
|
230
|
+
perfweekly: decimalFromNullable(ev.perfweekly),
|
|
231
|
+
perfmonthly: decimalFromNullable(ev.perfmonthly),
|
|
232
|
+
perfytd: decimalFromNullable(ev.perfytd),
|
|
233
|
+
perfstart: decimalFromNullable(ev.perfstart),
|
|
234
|
+
coefficient: decimalFromNullable(ev.coefficient),
|
|
235
235
|
})),
|
|
236
|
-
nav:
|
|
237
|
-
navAdjusted:
|
|
238
|
-
navAdjustedTotal:
|
|
239
|
-
coefficient:
|
|
240
|
-
gavRefccy:
|
|
241
|
-
gavClsccy:
|
|
242
|
-
sharecountPrev:
|
|
243
|
-
sharecountCurr:
|
|
244
|
-
sharecountDiff:
|
|
245
|
-
pxRefCcy:
|
|
246
|
-
pxClsCcy:
|
|
247
|
-
ytdExt:
|
|
248
|
-
ytdInt:
|
|
236
|
+
nav: unsafeDecimal(x.nav),
|
|
237
|
+
navAdjusted: unsafeDecimal(x.nav_adjusted),
|
|
238
|
+
navAdjustedTotal: unsafeDecimal(x.nav_adjusted_total),
|
|
239
|
+
coefficient: unsafeDecimal(x.coefficient),
|
|
240
|
+
gavRefccy: unsafeDecimal(x.gav_refccy),
|
|
241
|
+
gavClsccy: unsafeDecimal(x.gav_clsccy),
|
|
242
|
+
sharecountPrev: unsafeDecimal(x.sharecount_prev),
|
|
243
|
+
sharecountCurr: unsafeDecimal(x.sharecount_curr),
|
|
244
|
+
sharecountDiff: unsafeDecimal(x.sharecount_diff),
|
|
245
|
+
pxRefCcy: decimalFromNullable(x.px_refccy),
|
|
246
|
+
pxClsCcy: decimalFromNullable(x.px_clsccy),
|
|
247
|
+
ytdExt: decimalFromNullable(x.ytdext),
|
|
248
|
+
ytdInt: decimalFromNullable(x.ytdint),
|
|
249
249
|
};
|
|
250
250
|
}
|
|
251
251
|
|
|
@@ -268,7 +268,7 @@ export function recompilePortfolioValuationReport(
|
|
|
268
268
|
return {
|
|
269
269
|
...report,
|
|
270
270
|
portfolio: x.portfolio,
|
|
271
|
-
subscriptions:
|
|
271
|
+
subscriptions: decimalFromNullable(x.subscriptions).orDefault(zero),
|
|
272
272
|
shareClassValues: x.scvals.map(toShareClassValue),
|
|
273
273
|
};
|
|
274
274
|
});
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import {
|
|
2
|
-
asDecimal,
|
|
3
2
|
CustomError,
|
|
4
3
|
Decimal,
|
|
4
|
+
decimalFromNullable,
|
|
5
5
|
Either,
|
|
6
6
|
Just,
|
|
7
7
|
Maybe,
|
|
8
|
-
maybeDecimal,
|
|
9
8
|
Right,
|
|
10
9
|
safeDiv,
|
|
11
10
|
sanitizedNonEmptyText,
|
|
12
11
|
SDate,
|
|
13
12
|
SDateTime,
|
|
13
|
+
unsafeDecimal,
|
|
14
14
|
zero,
|
|
15
15
|
} from '@telostat/prelude';
|
|
16
|
-
import {
|
|
16
|
+
import { CurrencyCode, DateType, DecafArtifactId, DecafArtifactTypeId } from '../../commons';
|
|
17
17
|
import {
|
|
18
18
|
BaseValuationReport,
|
|
19
19
|
BaseValuationReportHolding,
|
|
@@ -124,9 +124,9 @@ export interface RemoteValuationReportChildHolding {
|
|
|
124
124
|
* Valuation artifact.
|
|
125
125
|
*/
|
|
126
126
|
export interface RemoteValuationReportArtifact {
|
|
127
|
-
id:
|
|
127
|
+
id: DecafArtifactId;
|
|
128
128
|
guid: string;
|
|
129
|
-
type: { id:
|
|
129
|
+
type: { id: DecafArtifactTypeId; name: string; order: number };
|
|
130
130
|
stype?: string;
|
|
131
131
|
symbol: string;
|
|
132
132
|
name?: string;
|
|
@@ -140,7 +140,7 @@ export interface RemoteValuationReportArtifact {
|
|
|
140
140
|
isin?: string;
|
|
141
141
|
figi?: string;
|
|
142
142
|
expiry?: SDate;
|
|
143
|
-
underlying_id?:
|
|
143
|
+
underlying_id?: DecafArtifactId;
|
|
144
144
|
}
|
|
145
145
|
|
|
146
146
|
/**
|
|
@@ -179,7 +179,7 @@ export function toArtifact(x: RemoteValuationReportArtifact): ValuationReportArt
|
|
|
179
179
|
symbol: x.symbol,
|
|
180
180
|
name: sanitizedNonEmptyText(x.name),
|
|
181
181
|
ccy: Maybe.fromNullable(x.ccy),
|
|
182
|
-
quantity:
|
|
182
|
+
quantity: unsafeDecimal(x.quantity),
|
|
183
183
|
country: sanitizedNonEmptyText(x.country),
|
|
184
184
|
issuer: sanitizedNonEmptyText(x.issuer),
|
|
185
185
|
sector: sanitizedNonEmptyText(x.sector),
|
|
@@ -195,14 +195,17 @@ export function toArtifact(x: RemoteValuationReportArtifact): ValuationReportArt
|
|
|
195
195
|
export function toAccrual(x: RemoteValuationReportAccrual): ValuationReportAccrual {
|
|
196
196
|
return {
|
|
197
197
|
name: x.name,
|
|
198
|
-
value:
|
|
198
|
+
value: unsafeDecimal(x.value),
|
|
199
199
|
accounts: x.accounts.map((y) => ({
|
|
200
200
|
account: y.account,
|
|
201
|
-
value:
|
|
201
|
+
value: unsafeDecimal(y.value),
|
|
202
202
|
accruals: y.accruals.map((z) => ({
|
|
203
203
|
artifact: toArtifact(z.artifact),
|
|
204
204
|
ccy: z.ccy,
|
|
205
|
-
value: {
|
|
205
|
+
value: {
|
|
206
|
+
org: decimalFromNullable(z.value.org).orDefault(zero),
|
|
207
|
+
ref: decimalFromNullable(z.value.ref).orDefault(zero),
|
|
208
|
+
},
|
|
206
209
|
})),
|
|
207
210
|
})),
|
|
208
211
|
};
|
|
@@ -210,14 +213,14 @@ export function toAccrual(x: RemoteValuationReportAccrual): ValuationReportAccru
|
|
|
210
213
|
|
|
211
214
|
export function toOrgRef(x: { org?: number; ref?: number }): ValuationReportFigureOrgRef {
|
|
212
215
|
return {
|
|
213
|
-
org:
|
|
214
|
-
ref:
|
|
216
|
+
org: decimalFromNullable(x.org).orDefault(zero),
|
|
217
|
+
ref: decimalFromNullable(x.ref).orDefault(zero),
|
|
215
218
|
};
|
|
216
219
|
}
|
|
217
220
|
|
|
218
221
|
export function toMaybeOrgRef(x?: { org?: number; ref?: number }): Maybe<ValuationReportFigureOrgRef> {
|
|
219
222
|
return Maybe.fromNullable(x).chain(({ org, ref }) =>
|
|
220
|
-
|
|
223
|
+
decimalFromNullable(org).chain((o) => decimalFromNullable(ref).chain((r) => Just({ org: o, ref: r })))
|
|
221
224
|
);
|
|
222
225
|
}
|
|
223
226
|
|
|
@@ -227,7 +230,7 @@ export function toBaseHolding(
|
|
|
227
230
|
): BaseValuationReportHolding {
|
|
228
231
|
return {
|
|
229
232
|
artifact: toArtifact(x.artifact),
|
|
230
|
-
quantity:
|
|
233
|
+
quantity: unsafeDecimal(x.quantity),
|
|
231
234
|
investment: {
|
|
232
235
|
px: toOrgRef(x.investment.px),
|
|
233
236
|
txncosts: toMaybeOrgRef(x.investment.txncosts),
|
|
@@ -246,12 +249,12 @@ export function toBaseHolding(
|
|
|
246
249
|
abs: toOrgRef(x.valuation.exposure.abs),
|
|
247
250
|
},
|
|
248
251
|
},
|
|
249
|
-
valuePercentage: safeDiv(
|
|
250
|
-
netExposurePercentage: safeDiv(
|
|
251
|
-
absExposurePercentage: safeDiv(
|
|
252
|
-
change:
|
|
253
|
-
pnl:
|
|
254
|
-
pnlToInvestment:
|
|
252
|
+
valuePercentage: safeDiv(decimalFromNullable(x.valuation.value.net.ref).orDefault(zero), nav),
|
|
253
|
+
netExposurePercentage: safeDiv(decimalFromNullable(x.valuation.exposure.net.ref).orDefault(zero), nav),
|
|
254
|
+
absExposurePercentage: safeDiv(decimalFromNullable(x.valuation.exposure.abs.ref).orDefault(zero), nav),
|
|
255
|
+
change: decimalFromNullable(x.change),
|
|
256
|
+
pnl: decimalFromNullable(x.pnl).orDefault(zero),
|
|
257
|
+
pnlToInvestment: decimalFromNullable(x.pnl_to_investment),
|
|
255
258
|
opendate: x.opendate,
|
|
256
259
|
lastdate: x.lastdate,
|
|
257
260
|
};
|
|
@@ -282,7 +285,7 @@ export function toHolding(nav: Decimal, x: RemoteValuationReportHolding): Valuat
|
|
|
282
285
|
* report.
|
|
283
286
|
*/
|
|
284
287
|
export function recompileBaseValuationReport(x: RemoteBaseValuationReport): Either<CustomError, BaseValuationReport> {
|
|
285
|
-
const nav =
|
|
288
|
+
const nav = decimalFromNullable(x.nav).orDefault(zero);
|
|
286
289
|
|
|
287
290
|
const report: BaseValuationReport = {
|
|
288
291
|
asof: x.reported,
|
|
@@ -292,20 +295,20 @@ export function recompileBaseValuationReport(x: RemoteBaseValuationReport): Eith
|
|
|
292
295
|
accounts: x.accounts,
|
|
293
296
|
holdings: x.holdings.map((rh) => toHolding(nav, rh)),
|
|
294
297
|
accruals: x.accruals.map(toAccrual),
|
|
295
|
-
fxRates: x.fxrates.map((r) => ({ ccy1: r.ccy1, ccy2: r.ccy2, value:
|
|
298
|
+
fxRates: x.fxrates.map((r) => ({ ccy1: r.ccy1, ccy2: r.ccy2, value: unsafeDecimal(r.value), asof: r.asof })),
|
|
296
299
|
figures: {
|
|
297
|
-
investment:
|
|
300
|
+
investment: decimalFromNullable(x.investment).orDefault(zero),
|
|
298
301
|
valuation: {
|
|
299
|
-
net:
|
|
300
|
-
abs:
|
|
302
|
+
net: decimalFromNullable(x.valuation_net).orDefault(zero),
|
|
303
|
+
abs: decimalFromNullable(x.valuation_abs).orDefault(zero),
|
|
301
304
|
},
|
|
302
|
-
accrued:
|
|
303
|
-
liabilities:
|
|
304
|
-
gav:
|
|
305
|
+
accrued: decimalFromNullable(x.accrued).orDefault(zero),
|
|
306
|
+
liabilities: decimalFromNullable(x.liabilities).orDefault(zero),
|
|
307
|
+
gav: decimalFromNullable(x.gav).orDefault(zero),
|
|
305
308
|
nav,
|
|
306
|
-
aum:
|
|
307
|
-
pnl:
|
|
308
|
-
pnlToInvestment:
|
|
309
|
+
aum: decimalFromNullable(x.aum).orDefault(zero),
|
|
310
|
+
pnl: decimalFromNullable(x.pnl).orDefault(zero),
|
|
311
|
+
pnlToInvestment: decimalFromNullable(x.pnl_to_investment),
|
|
309
312
|
},
|
|
310
313
|
};
|
|
311
314
|
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { Decimal, safeDiv, sumDecimals, Tuple, zero } from '@telostat/prelude';
|
|
2
|
-
import { Just, Maybe, Nothing } from 'purify-ts';
|
|
3
|
-
import { List } from 'purify-ts/List';
|
|
1
|
+
import { Decimal, Just, List, Maybe, Nothing, safeDiv, sumDecimals, Tuple, zero } from '@telostat/prelude';
|
|
4
2
|
import { ValuationReportHolding, ValuationReportHoldingClassification } from '../-valuation-report-shared';
|
|
3
|
+
import { DecafArtifactTypeId } from '../../../commons';
|
|
5
4
|
import { ValuationReportHoldingsTreeNode, ValuationReportHoldingsTreeNodeValue } from './-types';
|
|
6
5
|
import { compareStringArrays } from './-utils';
|
|
7
6
|
|
|
@@ -36,10 +35,20 @@ export function updateTotals(
|
|
|
36
35
|
const absValue = sumDecimals(holdings.map((x) => x.valuation.value.abs.ref)).add(
|
|
37
36
|
sumDecimals(children.map((x) => x.totals.absValue))
|
|
38
37
|
);
|
|
39
|
-
|
|
38
|
+
|
|
39
|
+
const holdingsForExposure = holdings.filter(
|
|
40
|
+
(h) =>
|
|
41
|
+
!(
|
|
42
|
+
h.artifact.type.id === ('CCY' as unknown as DecafArtifactTypeId) ||
|
|
43
|
+
h.artifact.type.id === ('DEPO' as unknown as DecafArtifactTypeId) ||
|
|
44
|
+
h.artifact.type.id === ('LOAN' as unknown as DecafArtifactTypeId)
|
|
45
|
+
)
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
const netExposure = sumDecimals(holdingsForExposure.map((x) => x.valuation.exposure.net.ref)).add(
|
|
40
49
|
sumDecimals(children.map((x) => x.totals.netExposure))
|
|
41
50
|
);
|
|
42
|
-
const absExposure = sumDecimals(
|
|
51
|
+
const absExposure = sumDecimals(holdingsForExposure.map((x) => x.valuation.exposure.abs.ref)).add(
|
|
43
52
|
sumDecimals(children.map((x) => x.totals.absExposure))
|
|
44
53
|
);
|
|
45
54
|
const pnl = sumDecimals(holdings.map((x) => x.pnl)).add(sumDecimals(children.map((x) => x.totals.pnl)));
|