@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.
Files changed (53) hide show
  1. package/.release-please-manifest.json +1 -1
  2. package/CHANGELOG.md +22 -0
  3. package/commons/-currency.d.ts +22 -6
  4. package/commons/-currency.js +12 -6
  5. package/commons/{-date-type.d.ts → -datetype.d.ts} +2 -2
  6. package/commons/{-date-type.js → -datetype.js} +2 -2
  7. package/commons/-id.d.ts +109 -17
  8. package/commons/-id.js +73 -0
  9. package/commons/index.d.ts +4 -1
  10. package/commons/index.js +17 -1
  11. package/es/commons/-currency.d.ts +22 -6
  12. package/es/commons/-currency.js +12 -6
  13. package/es/commons/{-date-type.d.ts → -datetype.d.ts} +2 -2
  14. package/es/commons/{-date-type.js → -datetype.js} +1 -1
  15. package/es/commons/-id.d.ts +109 -17
  16. package/es/commons/-id.js +70 -1
  17. package/es/commons/index.d.ts +4 -1
  18. package/es/commons/index.js +4 -1
  19. package/es/reports/valuation/-remote-valuation-report-portfolio.d.ts +15 -15
  20. package/es/reports/valuation/-remote-valuation-report-portfolio.js +32 -32
  21. package/es/reports/valuation/-remote-valuation-report-shared.d.ts +4 -4
  22. package/es/reports/valuation/-remote-valuation-report-shared.js +29 -26
  23. package/es/reports/valuation/-valuation-report-consolidated.d.ts +1 -1
  24. package/es/reports/valuation/-valuation-report-holdings-tree/-machinery.js +6 -5
  25. package/es/reports/valuation/-valuation-report-portfolio.d.ts +14 -14
  26. package/es/reports/valuation/-valuation-report-shared.d.ts +7 -7
  27. package/nix/default.nix +59 -0
  28. package/nix/sources.json +14 -0
  29. package/nix/sources.nix +194 -0
  30. package/package.json +16 -16
  31. package/reports/valuation/-remote-valuation-report-consolidated.js +1 -1
  32. package/reports/valuation/-remote-valuation-report-portfolio.d.ts +15 -15
  33. package/reports/valuation/-remote-valuation-report-portfolio.js +32 -32
  34. package/reports/valuation/-remote-valuation-report-shared.d.ts +4 -4
  35. package/reports/valuation/-remote-valuation-report-shared.js +28 -25
  36. package/reports/valuation/-valuation-report-consolidated.d.ts +1 -1
  37. package/reports/valuation/-valuation-report-holdings-tree/-machinery.js +14 -11
  38. package/reports/valuation/-valuation-report-portfolio.d.ts +14 -14
  39. package/reports/valuation/-valuation-report-shared.d.ts +7 -7
  40. package/shell.nix +5 -20
  41. package/src/commons/-currency.test.ts +27 -0
  42. package/src/commons/-currency.ts +24 -9
  43. package/src/commons/-datetype.test.ts +10 -0
  44. package/src/commons/{-date-type.ts → -datetype.ts} +1 -1
  45. package/src/commons/-id.test.ts +27 -0
  46. package/src/commons/-id.ts +112 -17
  47. package/src/commons/index.ts +4 -1
  48. package/src/index.test.ts +34 -5
  49. package/src/reports/valuation/-remote-valuation-report-portfolio.ts +54 -54
  50. package/src/reports/valuation/-remote-valuation-report-shared.ts +34 -31
  51. package/src/reports/valuation/-valuation-report-holdings-tree/-machinery.ts +14 -5
  52. package/src/reports/valuation/-valuation-report-portfolio.ts +20 -20
  53. package/src/reports/valuation/-valuation-report-shared.ts +13 -6
@@ -1,72 +1,167 @@
1
- import { NewTypeWithPhantom } from '@telostat/prelude';
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
- * Type definition for identifiers with value spaces discriminated over the
5
- * given phantom type.
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 type Id<P, V> = NewTypeWithPhantom<P, V>;
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 ArtifactId = NewTypeWithPhantom<'DecafArtifact', string | number>;
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 ArtifactTypeId = NewTypeWithPhantom<'DecafArtifactType', string>;
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 ShareClassId = NewTypeWithPhantom<'DecafShareClass', string | number>;
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 PrincipalId = NewTypeWithPhantom<'DecafPrincipal', string | number>;
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 InstitutionId = NewTypeWithPhantom<'DecafInstitution', string | number>;
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 TeamId = NewTypeWithPhantom<'DecafTeam', string | number>;
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 PortfolioId = NewTypeWithPhantom<'DecafPortfolio', string | number>;
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 PortfolioGroupId = NewTypeWithPhantom<'DecafPortfolioGroup', string | number>;
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 AccountId = NewTypeWithPhantom<'DecafAccount', string | number>;
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 OhlcSeriesId = NewTypeWithPhantom<'DecafOhlcSeries', string | number>;
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 ShareClassFeeScheduleId = NewTypeWithPhantom<'DecafShareClassFeeSchedule', string | number>;
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 ActionId = NewTypeWithPhantom<'DecafAction', string | number>;
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 ExternalValuationId = NewTypeWithPhantom<'DecafExternalValuation', string | number>;
167
+ export type DecafExternalValuationId = number & { readonly __tag: unique symbol };
@@ -1,3 +1,6 @@
1
1
  export * from './-currency';
2
- export * from './-date-type';
2
+ export * as currency from './-currency';
3
+ export * from './-datetype';
4
+ export * as datetype from './-datetype';
3
5
  export * from './-id';
6
+ export * as id from './-id';
package/src/index.test.ts CHANGED
@@ -1,8 +1,12 @@
1
1
  import { buildDecafClient, DecafClient, gql } from '@decafhub/decaf-client';
2
- import { mk, PDateTime } from '@telostat/prelude';
2
+ import { PDateTime, safeDiv, zero } from '@telostat/prelude';
3
3
  import { fail } from 'assert';
4
- import { PortfolioId } from './commons';
5
- import { fetchRemotePortfolioValuationReport } from './reports/valuation/-remote-valuation-report-portfolio';
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: 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: mk('EUR'),
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
- ExternalValuationId,
21
- OhlcSeriesId,
22
- PortfolioId,
23
- PrincipalId,
24
- ShareClassFeeScheduleId,
25
- ShareClassId,
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: PortfolioId;
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: ShareClassId;
91
+ id: DecafShareClassId;
92
92
  created: SDateTime;
93
- creator: PrincipalId;
93
+ creator: DecafPrincipalId;
94
94
  updated: SDateTime;
95
- updater: PrincipalId;
95
+ updater: DecafPrincipalId;
96
96
  guid: string;
97
- portfolio: PortfolioId;
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?: OhlcSeriesId;
109
+ benchmark?: DecafOhlcSeriesId;
110
110
  description?: string;
111
- feeschedules: ShareClassFeeScheduleId[];
112
- effectivefeeschedule?: ShareClassFeeScheduleId;
113
- subscriptions: ActionId[];
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: ExternalValuationId;
122
+ id: DecafExternalValuationId;
123
123
  created: SDateTime;
124
- creator: PrincipalId;
124
+ creator: DecafPrincipalId;
125
125
  updated: SDateTime;
126
- updater: PrincipalId;
126
+ updater: DecafPrincipalId;
127
127
  guid: string;
128
- portfolio: PortfolioId;
129
- shareclass?: ShareClassId;
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: maybeDecimal(x.shareclass.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: maybeDecimal(ev.shares),
220
- price: maybeDecimal(ev.price),
221
- nav: maybeDecimal(ev.nav),
222
- aum: maybeDecimal(ev.aum),
223
- hedgepnl: maybeDecimal(ev.hedgepnl),
224
- feemngt: maybeDecimal(ev.feemngt),
225
- feeperf: maybeDecimal(ev.feeperf),
226
- otheraccrued: maybeDecimal(ev.otheraccrued),
227
- totalaccrued: maybeDecimal(ev.totalaccrued),
228
- subred: maybeDecimal(ev.subred),
229
- perfdaily: maybeDecimal(ev.perfdaily),
230
- perfweekly: maybeDecimal(ev.perfweekly),
231
- perfmonthly: maybeDecimal(ev.perfmonthly),
232
- perfytd: maybeDecimal(ev.perfytd),
233
- perfstart: maybeDecimal(ev.perfstart),
234
- coefficient: maybeDecimal(ev.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: asDecimal(x.nav),
237
- navAdjusted: asDecimal(x.nav_adjusted),
238
- navAdjustedTotal: asDecimal(x.nav_adjusted_total),
239
- coefficient: asDecimal(x.coefficient),
240
- gavRefccy: asDecimal(x.gav_refccy),
241
- gavClsccy: asDecimal(x.gav_clsccy),
242
- sharecountPrev: asDecimal(x.sharecount_prev),
243
- sharecountCurr: asDecimal(x.sharecount_curr),
244
- sharecountDiff: asDecimal(x.sharecount_diff),
245
- pxRefCcy: maybeDecimal(x.px_refccy),
246
- pxClsCcy: maybeDecimal(x.px_clsccy),
247
- ytdExt: maybeDecimal(x.ytdext),
248
- ytdInt: maybeDecimal(x.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: maybeDecimal(x.subscriptions).orDefault(zero),
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 { ArtifactId, ArtifactTypeId, CurrencyCode, DateType } from '../../commons';
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: ArtifactId;
127
+ id: DecafArtifactId;
128
128
  guid: string;
129
- type: { id: ArtifactTypeId; name: string; order: number };
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?: ArtifactId;
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: asDecimal(x.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: asDecimal(x.value),
198
+ value: unsafeDecimal(x.value),
199
199
  accounts: x.accounts.map((y) => ({
200
200
  account: y.account,
201
- value: asDecimal(y.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: { org: asDecimal(z.value.org || 0), ref: asDecimal(z.value.ref || 0) },
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: maybeDecimal(x.org).orDefault(zero),
214
- ref: maybeDecimal(x.ref).orDefault(zero),
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
- maybeDecimal(org).chain((o) => maybeDecimal(ref).chain((r) => Just({ org: o, ref: r })))
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: asDecimal(x.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(maybeDecimal(x.valuation.value.net.ref).orDefault(zero), nav),
250
- netExposurePercentage: safeDiv(maybeDecimal(x.valuation.exposure.net.ref).orDefault(zero), nav),
251
- absExposurePercentage: safeDiv(maybeDecimal(x.valuation.exposure.abs.ref).orDefault(zero), nav),
252
- change: maybeDecimal(x.change),
253
- pnl: maybeDecimal(x.pnl).orDefault(zero),
254
- pnlToInvestment: maybeDecimal(x.pnl_to_investment),
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 = maybeDecimal(x.nav).orDefault(zero);
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: asDecimal(r.value), asof: r.asof })),
298
+ fxRates: x.fxrates.map((r) => ({ ccy1: r.ccy1, ccy2: r.ccy2, value: unsafeDecimal(r.value), asof: r.asof })),
296
299
  figures: {
297
- investment: maybeDecimal(x.investment).orDefault(zero),
300
+ investment: decimalFromNullable(x.investment).orDefault(zero),
298
301
  valuation: {
299
- net: maybeDecimal(x.valuation_net).orDefault(zero),
300
- abs: maybeDecimal(x.valuation_abs).orDefault(zero),
302
+ net: decimalFromNullable(x.valuation_net).orDefault(zero),
303
+ abs: decimalFromNullable(x.valuation_abs).orDefault(zero),
301
304
  },
302
- accrued: maybeDecimal(x.accrued).orDefault(zero),
303
- liabilities: maybeDecimal(x.liabilities).orDefault(zero),
304
- gav: maybeDecimal(x.gav).orDefault(zero),
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: maybeDecimal(x.aum).orDefault(zero),
307
- pnl: maybeDecimal(x.pnl).orDefault(zero),
308
- pnlToInvestment: maybeDecimal(x.pnl_to_investment),
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
- const netExposure = sumDecimals(holdings.map((x) => x.valuation.exposure.net.ref)).add(
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(holdings.map((x) => x.valuation.exposure.abs.ref)).add(
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)));