@quantform/core 0.7.21 → 0.7.24

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 (194) hide show
  1. package/lib/app.d.ts +12 -0
  2. package/lib/app.d.ts.map +1 -0
  3. package/lib/app.js +35 -0
  4. package/lib/cli/build.d.ts.map +1 -1
  5. package/lib/cli/build.js +8 -18
  6. package/lib/cli/index.js +3 -12
  7. package/lib/cli/internal/script.d.ts +1 -1
  8. package/lib/cli/internal/script.d.ts.map +1 -1
  9. package/lib/cli/internal/script.js +8 -28
  10. package/lib/cli/live.js +10 -22
  11. package/lib/cli/paper.js +10 -22
  12. package/lib/cli/replay.d.ts.map +1 -1
  13. package/lib/cli/replay.js +15 -26
  14. package/lib/index.d.ts +1 -6
  15. package/lib/index.d.ts.map +1 -1
  16. package/lib/index.js +1 -6
  17. package/lib/make-test-module.d.ts.map +1 -1
  18. package/lib/make-test-module.js +18 -20
  19. package/lib/module.d.ts.map +1 -1
  20. package/lib/module.js +9 -24
  21. package/lib/module.spec.js +8 -17
  22. package/lib/replay/use-replay-options.d.ts +5 -4
  23. package/lib/replay/use-replay-options.d.ts.map +1 -1
  24. package/lib/replay/use-replay-options.js +5 -1
  25. package/lib/replay/use-replay-scheduler.d.ts +7 -6
  26. package/lib/replay/use-replay-scheduler.d.ts.map +1 -1
  27. package/lib/replay/use-replay-scheduler.js +64 -70
  28. package/lib/replay/use-replay-storage-buffer.d.ts +3 -2
  29. package/lib/replay/use-replay-storage-buffer.d.ts.map +1 -1
  30. package/lib/replay/use-replay-storage-buffer.js +12 -23
  31. package/lib/replay/use-replay-storage-cursor.d.ts +9 -8
  32. package/lib/replay/use-replay-storage-cursor.d.ts.map +1 -1
  33. package/lib/replay/use-replay-storage-cursor.js +17 -25
  34. package/lib/replay/use-replay-storage.d.ts +5 -4
  35. package/lib/replay/use-replay-storage.d.ts.map +1 -1
  36. package/lib/replay/use-replay-storage.js +32 -39
  37. package/lib/session/use-session-storage.d.ts +1 -1
  38. package/lib/session/use-session-storage.d.ts.map +1 -1
  39. package/lib/session/use-session-storage.js +8 -5
  40. package/lib/shared/environment.js +1 -1
  41. package/lib/shared/index.d.ts +0 -1
  42. package/lib/shared/index.d.ts.map +1 -1
  43. package/lib/shared/index.js +0 -1
  44. package/lib/simulator/use-simulator.spec.js +17 -30
  45. package/lib/storage/in-memory/in-memory-storage.d.ts.map +1 -1
  46. package/lib/storage/in-memory/in-memory-storage.factory.js +2 -2
  47. package/lib/storage/in-memory/in-memory-storage.js +56 -55
  48. package/lib/storage/in-memory/in-memory-storage.spec.js +90 -100
  49. package/lib/storage/storage.d.ts +9 -8
  50. package/lib/storage/storage.d.ts.map +1 -1
  51. package/lib/storage/storage.js +8 -2
  52. package/lib/storage/use-cache.d.ts +1 -1
  53. package/lib/storage/use-cache.d.ts.map +1 -1
  54. package/lib/storage/use-cache.js +5 -5
  55. package/lib/storage/use-cache.spec.js +14 -25
  56. package/lib/storage/use-storage.d.ts +1 -1
  57. package/lib/storage/use-storage.d.ts.map +1 -1
  58. package/lib/storage/use-storage.js +9 -6
  59. package/lib/use-execution-mode.js +2 -2
  60. package/lib/use-hash.spec.js +3 -6
  61. package/lib/use-logger.d.ts +1 -1
  62. package/lib/use-logger.d.ts.map +1 -1
  63. package/lib/use-logger.js +10 -7
  64. package/lib/use-memo.spec.js +14 -25
  65. package/lib/use-socket.d.ts +3 -2
  66. package/lib/use-socket.d.ts.map +1 -1
  67. package/lib/use-socket.js +2 -2
  68. package/lib/use-timestamp.d.ts +14 -1
  69. package/lib/use-timestamp.d.ts.map +1 -1
  70. package/lib/use-timestamp.js +30 -3
  71. package/lib/with-request.d.ts +2 -1
  72. package/lib/with-request.d.ts.map +1 -1
  73. package/lib/with-request.js +4 -13
  74. package/package.json +6 -10
  75. package/src/app.ts +52 -0
  76. package/src/cli/build.ts +11 -6
  77. package/src/cli/internal/script.ts +25 -54
  78. package/src/cli/replay.ts +13 -2
  79. package/src/index.ts +1 -6
  80. package/src/make-test-module.ts +12 -2
  81. package/src/module.ts +0 -3
  82. package/src/replay/use-replay-options.ts +7 -3
  83. package/src/replay/use-replay-scheduler.ts +75 -67
  84. package/src/replay/use-replay-storage-buffer.ts +2 -1
  85. package/src/replay/use-replay-storage-cursor.ts +33 -28
  86. package/src/replay/use-replay-storage.ts +36 -27
  87. package/src/session/use-session-storage.ts +7 -5
  88. package/src/shared/index.ts +0 -1
  89. package/src/storage/in-memory/in-memory-storage.spec.ts +55 -54
  90. package/src/storage/in-memory/in-memory-storage.ts +24 -7
  91. package/src/storage/storage.ts +16 -7
  92. package/src/storage/use-cache.ts +4 -4
  93. package/src/storage/use-storage.ts +8 -6
  94. package/src/use-hash.spec.ts +3 -6
  95. package/src/use-logger.ts +9 -6
  96. package/src/use-socket.ts +5 -5
  97. package/src/use-timestamp.ts +41 -3
  98. package/src/with-request.ts +3 -3
  99. package/lib/asset/asset.d.ts +0 -41
  100. package/lib/asset/asset.d.ts.map +0 -1
  101. package/lib/asset/asset.js +0 -76
  102. package/lib/asset/asset.spec.d.ts +0 -2
  103. package/lib/asset/asset.spec.d.ts.map +0 -1
  104. package/lib/asset/asset.spec.js +0 -54
  105. package/lib/asset/index.d.ts +0 -2
  106. package/lib/asset/index.d.ts.map +0 -1
  107. package/lib/asset/index.js +0 -17
  108. package/lib/component/distinct-until-timesamp-changed.d.ts +0 -5
  109. package/lib/component/distinct-until-timesamp-changed.d.ts.map +0 -1
  110. package/lib/component/distinct-until-timesamp-changed.js +0 -9
  111. package/lib/component/error.d.ts +0 -17
  112. package/lib/component/error.d.ts.map +0 -1
  113. package/lib/component/error.js +0 -33
  114. package/lib/component/index.d.ts +0 -8
  115. package/lib/component/index.d.ts.map +0 -1
  116. package/lib/component/index.js +0 -23
  117. package/lib/component/ohlc-operator.d.ts +0 -11
  118. package/lib/component/ohlc-operator.d.ts.map +0 -1
  119. package/lib/component/ohlc-operator.js +0 -69
  120. package/lib/component/ohlc-operator.spec.d.ts +0 -2
  121. package/lib/component/ohlc-operator.spec.d.ts.map +0 -1
  122. package/lib/component/ohlc-operator.spec.js +0 -110
  123. package/lib/component/ohlc.d.ts +0 -12
  124. package/lib/component/ohlc.d.ts.map +0 -1
  125. package/lib/component/ohlc.js +0 -20
  126. package/lib/component/ohlc.spec.d.ts +0 -2
  127. package/lib/component/ohlc.spec.d.ts.map +0 -1
  128. package/lib/component/ohlc.spec.js +0 -25
  129. package/lib/component/timeframe.d.ts +0 -15
  130. package/lib/component/timeframe.d.ts.map +0 -1
  131. package/lib/component/timeframe.js +0 -21
  132. package/lib/core.d.ts +0 -3
  133. package/lib/core.d.ts.map +0 -1
  134. package/lib/core.js +0 -17
  135. package/lib/instrument/commission/commission.d.ts +0 -16
  136. package/lib/instrument/commission/commission.d.ts.map +0 -1
  137. package/lib/instrument/commission/commission.js +0 -28
  138. package/lib/instrument/commission/commission.spec.d.ts +0 -2
  139. package/lib/instrument/commission/commission.spec.d.ts.map +0 -1
  140. package/lib/instrument/commission/commission.spec.js +0 -30
  141. package/lib/instrument/index.d.ts +0 -3
  142. package/lib/instrument/index.d.ts.map +0 -1
  143. package/lib/instrument/index.js +0 -18
  144. package/lib/instrument/instrument.d.ts +0 -28
  145. package/lib/instrument/instrument.d.ts.map +0 -1
  146. package/lib/instrument/instrument.js +0 -53
  147. package/lib/instrument/instrument.spec.d.ts +0 -2
  148. package/lib/instrument/instrument.spec.d.ts.map +0 -1
  149. package/lib/instrument/instrument.spec.js +0 -51
  150. package/lib/operators.d.ts +0 -5
  151. package/lib/operators.d.ts.map +0 -1
  152. package/lib/operators.js +0 -16
  153. package/lib/shared/datetime.d.ts +0 -3
  154. package/lib/shared/datetime.d.ts.map +0 -1
  155. package/lib/shared/datetime.js +0 -7
  156. package/lib/strategy.d.ts +0 -15
  157. package/lib/strategy.d.ts.map +0 -1
  158. package/lib/strategy.js +0 -26
  159. package/lib/strategy.spec.d.ts +0 -2
  160. package/lib/strategy.spec.d.ts.map +0 -1
  161. package/lib/strategy.spec.js +0 -34
  162. package/lib/when-socket.d.ts +0 -8
  163. package/lib/when-socket.d.ts.map +0 -1
  164. package/lib/when-socket.js +0 -53
  165. package/lib/with-memo.d.ts +0 -5
  166. package/lib/with-memo.d.ts.map +0 -1
  167. package/lib/with-memo.js +0 -20
  168. package/lib/with-memo.spec.d.ts +0 -2
  169. package/lib/with-memo.spec.d.ts.map +0 -1
  170. package/lib/with-memo.spec.js +0 -47
  171. package/src/asset/asset.spec.ts +0 -70
  172. package/src/asset/asset.ts +0 -89
  173. package/src/asset/index.ts +0 -1
  174. package/src/component/distinct-until-timesamp-changed.ts +0 -11
  175. package/src/component/error.ts +0 -32
  176. package/src/component/index.ts +0 -7
  177. package/src/component/ohlc-operator.spec.ts +0 -125
  178. package/src/component/ohlc-operator.ts +0 -122
  179. package/src/component/ohlc.spec.ts +0 -30
  180. package/src/component/ohlc.ts +0 -18
  181. package/src/component/timeframe.ts +0 -17
  182. package/src/core.ts +0 -16
  183. package/src/instrument/commission/commission.spec.ts +0 -35
  184. package/src/instrument/commission/commission.ts +0 -27
  185. package/src/instrument/index.ts +0 -2
  186. package/src/instrument/instrument.spec.ts +0 -76
  187. package/src/instrument/instrument.ts +0 -65
  188. package/src/operators.ts +0 -18
  189. package/src/shared/datetime.ts +0 -5
  190. package/src/strategy.spec.ts +0 -42
  191. package/src/strategy.ts +0 -36
  192. package/src/when-socket.ts +0 -61
  193. package/src/with-memo.spec.ts +0 -46
  194. package/src/with-memo.ts +0 -33
@@ -1,122 +0,0 @@
1
- import {
2
- concat,
3
- filter,
4
- last,
5
- map,
6
- mergeMap,
7
- Observable,
8
- OperatorFunction,
9
- share,
10
- skipLast,
11
- switchMap
12
- } from 'rxjs';
13
-
14
- import { Ohlc, tf } from '@lib/component';
15
- import { decimal } from '@lib/shared';
16
-
17
- function aggregate(
18
- candle: Ohlc | undefined,
19
- timeframe: number,
20
- value: decimal,
21
- timestamp: number
22
- ) {
23
- const frame = tf(timestamp, timeframe);
24
-
25
- if (!candle) {
26
- return new Ohlc(frame, value, value, value, value);
27
- }
28
-
29
- if (candle.timestamp === frame) {
30
- candle.apply(value);
31
- return undefined;
32
- } else {
33
- return new Ohlc(frame, candle.close, value, value, value);
34
- }
35
- }
36
-
37
- export function ohlc<T extends { timestamp: number }>(
38
- timeframe: number,
39
- fn: (x: T) => decimal,
40
- candleToStartWith?: Ohlc
41
- ) {
42
- return function (source: Observable<T>): Observable<Ohlc> {
43
- let candle = candleToStartWith;
44
-
45
- return source.pipe(
46
- map(it => {
47
- const newCandle = aggregate(candle, timeframe, fn(it), it.timestamp);
48
- if (newCandle) {
49
- const prevCandle = candle;
50
- candle = newCandle;
51
-
52
- if (candleToStartWith && candleToStartWith.timestamp < newCandle.timestamp) {
53
- candleToStartWith = undefined;
54
-
55
- if (prevCandle) {
56
- return [prevCandle, candle];
57
- }
58
-
59
- return [candle];
60
- }
61
- }
62
-
63
- if (candleToStartWith) {
64
- candleToStartWith = undefined;
65
- }
66
-
67
- if (candle) {
68
- return [candle];
69
- }
70
-
71
- return [];
72
- }),
73
- mergeMap(it => it),
74
- share()
75
- );
76
- };
77
- }
78
-
79
- export function mergeOhlc<T extends { timestamp: number }>(
80
- timeframe: number,
81
- fn: (x: T) => decimal,
82
- history$: Observable<Ohlc>
83
- ) {
84
- return function (source$: Observable<T>): Observable<Ohlc> {
85
- return concat(
86
- history$.pipe(skipLast(1)),
87
- history$.pipe(
88
- last(),
89
- switchMap(lastHistoricalCandle =>
90
- source$.pipe(ohlc(timeframe, fn, lastHistoricalCandle))
91
- ),
92
- share()
93
- )
94
- );
95
- };
96
- }
97
-
98
- export function ohlcCompleted(): (source: Observable<Ohlc>) => Observable<Ohlc> {
99
- let currCandle: Ohlc;
100
-
101
- return (source: Observable<Ohlc>) =>
102
- source.pipe(
103
- map(it => {
104
- if (!currCandle) {
105
- currCandle = it;
106
-
107
- return undefined;
108
- } else {
109
- if (currCandle.timestamp !== it.timestamp) {
110
- const prevCandle = currCandle;
111
- currCandle = it;
112
-
113
- return prevCandle;
114
- }
115
-
116
- return undefined;
117
- }
118
- }),
119
- filter(it => it !== undefined) as OperatorFunction<Ohlc | undefined, Ohlc>,
120
- share()
121
- );
122
- }
@@ -1,30 +0,0 @@
1
- import { Ohlc } from '@lib/component';
2
- import { d, now } from '@lib/shared';
3
-
4
- describe('Ohlc', () => {
5
- test('should construct a ohlc', () => {
6
- const timestamp = now();
7
-
8
- const sut = new Ohlc(timestamp, d(2), d(4), d(1), d(3));
9
-
10
- expect(sut.timestamp).toEqual(timestamp);
11
- expect(sut.open).toEqual(d(2));
12
- expect(sut.high).toEqual(d(4));
13
- expect(sut.low).toEqual(d(1));
14
- expect(sut.close).toEqual(d(3));
15
- });
16
-
17
- test('should modify a ohlc', () => {
18
- const timestamp = now();
19
-
20
- const sut = new Ohlc(timestamp, d(2), d(4), d(1), d(3));
21
-
22
- sut.apply(d(10));
23
-
24
- expect(sut.timestamp).toEqual(timestamp);
25
- expect(sut.open).toEqual(d(2));
26
- expect(sut.high).toEqual(d(10));
27
- expect(sut.low).toEqual(d(1));
28
- expect(sut.close).toEqual(d(10));
29
- });
30
- });
@@ -1,18 +0,0 @@
1
- import { decimal, timestamp } from '@lib/shared';
2
-
3
- export class Ohlc {
4
- constructor(
5
- public timestamp: timestamp,
6
- public open: decimal,
7
- public high: decimal,
8
- public low: decimal,
9
- public close: decimal,
10
- public volume?: decimal
11
- ) {}
12
-
13
- apply(value: decimal) {
14
- this.high = decimal.max(this.high, value);
15
- this.low = decimal.min(this.low, value);
16
- this.close = value;
17
- }
18
- }
@@ -1,17 +0,0 @@
1
- export class Timeframe {
2
- static S1 = 1000;
3
- static M1 = Timeframe.S1 * 60;
4
- static M5 = Timeframe.M1 * 5;
5
- static M15 = Timeframe.M5 * 3;
6
- static M30 = Timeframe.M15 * 2;
7
- static H1 = Timeframe.M30 * 2;
8
- static H4 = Timeframe.H1 * 4;
9
- static H6 = Timeframe.H1 * 6;
10
- static H12 = Timeframe.H6 * 2;
11
- static D1 = Timeframe.H12 * 2;
12
- static W1 = Timeframe.D1 * 7;
13
- }
14
-
15
- export function tf(timestamp: number, timeframe: number): number {
16
- return timestamp - (timestamp % timeframe);
17
- }
package/src/core.ts DELETED
@@ -1,16 +0,0 @@
1
- import { Dependency } from '@lib/module';
2
- import { useMemo } from '@lib/use-memo';
3
-
4
- import { InMemoryStorageFactory } from './storage';
5
- import { useStorageFactory } from './storage/use-storage-factory';
6
- import { useExecutionMode } from './use-execution-mode';
7
- import { ConsoleLoggerFactory, logger } from './use-logger';
8
-
9
- export function core(): Dependency[] {
10
- return [
11
- useMemo.options(),
12
- logger(new ConsoleLoggerFactory()),
13
- useExecutionMode.paperOptions({ recording: false }),
14
- useStorageFactory.options(new InMemoryStorageFactory())
15
- ];
16
- }
@@ -1,35 +0,0 @@
1
- import { d } from '@lib/shared';
2
-
3
- import { Commission, commissionPercentOf } from './commission';
4
-
5
- describe(Commission.name, () => {
6
- test('should construct a Commission', () => {
7
- const sut = commissionPercentOf({
8
- maker: d(0.1),
9
- taker: d(0.2)
10
- });
11
-
12
- expect(sut.makerRate).toEqual(d(0.001));
13
- expect(sut.takerRate).toEqual(d(0.002));
14
- });
15
-
16
- test('should calculate a maker fee', () => {
17
- const sut = commissionPercentOf({
18
- maker: d(0.1),
19
- taker: d(0.2)
20
- });
21
-
22
- expect(sut.calculateMakerFee(d(2000))).toEqual(d(2));
23
- expect(sut.applyMakerFee(d(2000))).toEqual(d(1998));
24
- });
25
-
26
- test('should calculate a taker fee', () => {
27
- const sut = commissionPercentOf({
28
- maker: d(0.1),
29
- taker: d(0.2)
30
- });
31
-
32
- expect(sut.calculateTakerFee(d(2000))).toEqual(d(4));
33
- expect(sut.applyTakerFee(d(2000))).toEqual(d(1996));
34
- });
35
- });
@@ -1,27 +0,0 @@
1
- import { d, decimal } from '@lib/shared';
2
-
3
- export class Commission {
4
- static readonly Zero = commissionPercentOf({ maker: d.Zero, taker: d.Zero });
5
-
6
- constructor(readonly makerRate: decimal, readonly takerRate: decimal) {}
7
-
8
- calculateMakerFee(value: decimal) {
9
- return value.mul(this.makerRate);
10
- }
11
-
12
- calculateTakerFee(value: decimal) {
13
- return value.mul(this.takerRate);
14
- }
15
-
16
- applyMakerFee(value: decimal): decimal {
17
- return value.minus(this.calculateMakerFee(value));
18
- }
19
-
20
- applyTakerFee(value: decimal): decimal {
21
- return value.minus(this.calculateTakerFee(value));
22
- }
23
- }
24
-
25
- export function commissionPercentOf(fees: { maker: decimal; taker: decimal }) {
26
- return new Commission(fees.maker.div(100.0), fees.taker.div(100.0));
27
- }
@@ -1,2 +0,0 @@
1
- export * from '@lib/instrument/instrument';
2
- export * from '@lib/instrument/commission/commission';
@@ -1,76 +0,0 @@
1
- import {
2
- Asset,
3
- assetOf,
4
- commissionPercentOf,
5
- Instrument,
6
- instrumentOf,
7
- InstrumentSelector
8
- } from '@lib/component';
9
- import { d } from '@lib/shared';
10
-
11
- describe(Instrument.name, () => {
12
- test('should construct a instrument', () => {
13
- const sut = new Instrument(
14
- 0,
15
- new Asset('abc', 'xyz', 4),
16
- new Asset('def', 'xyz', 4),
17
- 'abc-def',
18
- commissionPercentOf({
19
- maker: d.Zero,
20
- taker: d.Zero
21
- })
22
- );
23
-
24
- expect(sut.base.name).toEqual('abc');
25
- expect(sut.base.adapterName).toEqual('xyz');
26
- expect(sut.quote.name).toEqual('def');
27
- expect(sut.quote.adapterName).toEqual('xyz');
28
- expect(sut.id).toEqual('xyz:abc-def');
29
- });
30
- });
31
-
32
- describe(InstrumentSelector.name, () => {
33
- test('should construct a instrument selector', () => {
34
- const sut = instrumentOf('xyz:abc-def');
35
-
36
- expect(sut.base.name).toEqual('abc');
37
- expect(sut.base.adapterName).toEqual('xyz');
38
- expect(sut.quote.name).toEqual('def');
39
- expect(sut.quote.adapterName).toEqual('xyz');
40
- expect(sut.id).toEqual('xyz:abc-def');
41
- });
42
-
43
- test('should construct a instrument selector capital case', () => {
44
- const sut = instrumentOf('XYZ:ABC-DEF');
45
-
46
- expect(sut.base.name).toEqual('abc');
47
- expect(sut.base.adapterName).toEqual('xyz');
48
- expect(sut.quote.name).toEqual('def');
49
- expect(sut.quote.adapterName).toEqual('xyz');
50
- expect(sut.id).toEqual('xyz:abc-def');
51
- });
52
-
53
- test('should throw invalid format message for missing separator', () => {
54
- const fn = () => instrumentOf('xyzabc-def');
55
-
56
- expect(fn).toThrowError();
57
- });
58
-
59
- test('should throw invalid format message for multiple separators', () => {
60
- const fn = () => instrumentOf('xyz:abc:-def');
61
-
62
- expect(fn).toThrowError();
63
- });
64
-
65
- test('should throw invalid format message for missing pair name', () => {
66
- const fn = () => instrumentOf('xyz:');
67
-
68
- expect(fn).toThrowError();
69
- });
70
-
71
- test('should throw invalid format message for missing adapter name', () => {
72
- const fn = () => assetOf(':abc-def');
73
-
74
- expect(fn).toThrowError();
75
- });
76
- });
@@ -1,65 +0,0 @@
1
- import { Asset, AssetSelector, AssetSelectorSeparator } from '@lib/asset';
2
- import { AdapterMismatchError, InvalidInstrumentSelectorError } from '@lib/component';
3
-
4
- import { Commission } from './commission/commission';
5
-
6
- export const InstrumentSelectorSeparator = '-';
7
-
8
- export class MissingInstrumentError extends Error {
9
- constructor(instrument: InstrumentSelector) {
10
- super(`Missing instrument: ${instrument}`);
11
- }
12
- }
13
-
14
- export class InstrumentSelector {
15
- readonly id: string;
16
- readonly base: AssetSelector;
17
- readonly quote: AssetSelector;
18
-
19
- constructor(base: string, quote: string, adapter: string) {
20
- this.base = new AssetSelector(base.toLowerCase(), adapter.toLowerCase());
21
- this.quote = new AssetSelector(quote.toLowerCase(), adapter.toLowerCase());
22
-
23
- this.id = `${this.base.id}${InstrumentSelectorSeparator}${this.quote.name}`;
24
- }
25
-
26
- toString() {
27
- return this.id;
28
- }
29
- }
30
-
31
- /**
32
- * Represents trading market which is made up by two trading assets (base and quoted).
33
- */
34
- export class Instrument extends InstrumentSelector {
35
- readonly cross: Instrument | undefined;
36
- leverage: number | undefined = undefined;
37
-
38
- constructor(
39
- public timestamp: number,
40
- override readonly base: Asset,
41
- override readonly quote: Asset,
42
- readonly raw: string,
43
- public commission: Commission
44
- ) {
45
- super(base.name, quote.name, base.adapterName);
46
-
47
- if (base.adapterName != quote.adapterName) {
48
- throw new AdapterMismatchError();
49
- }
50
- }
51
- }
52
-
53
- export function instrumentOf(selector: string): InstrumentSelector {
54
- const [adapterName, asset, ...rest] = selector.split(AssetSelectorSeparator);
55
- if (!adapterName || !asset || rest.length) {
56
- throw new InvalidInstrumentSelectorError(selector);
57
- }
58
-
59
- const [baseAssetName, quoteAssetName] = asset.split(InstrumentSelectorSeparator);
60
- if (!baseAssetName || !quoteAssetName) {
61
- throw new InvalidInstrumentSelectorError(selector);
62
- }
63
-
64
- return new InstrumentSelector(baseAssetName, quoteAssetName, adapterName);
65
- }
package/src/operators.ts DELETED
@@ -1,18 +0,0 @@
1
- import { filter, map, Observable } from 'rxjs';
2
-
3
- export function asReadonly<T>() {
4
- return (input: Observable<T>) => input.pipe(map(it => it as Readonly<T>));
5
- }
6
-
7
- export function defined<T>() {
8
- return (observable: Observable<T | undefined | null>) =>
9
- observable.pipe(filter(it => it !== undefined && it !== null));
10
- }
11
-
12
- export function exclude<T, S extends symbol>(s: S) {
13
- return (observable: Observable<T | S>) =>
14
- observable.pipe(
15
- filter(it => it !== s),
16
- map(it => it as Exclude<T, typeof s>)
17
- );
18
- }
@@ -1,5 +0,0 @@
1
- export type timestamp = number;
2
-
3
- export function now(): timestamp {
4
- return new Date().getTime();
5
- }
@@ -1,42 +0,0 @@
1
- import { of } from 'rxjs';
2
-
3
- import { Dependency } from './module';
4
- import { after, before, behavior, strategy } from './strategy';
5
-
6
- describe(strategy.name, () => {
7
- let fixtures: ReturnType<typeof getFixtures>;
8
-
9
- beforeEach(() => {
10
- fixtures = getFixtures();
11
- });
12
-
13
- test('happy path', () => {
14
- const sut = strategy(() => {
15
- before(() => of('before'));
16
- behavior(() => of('behavior 1'));
17
- behavior(() => of('behavior 2'));
18
- after(() => of('after'));
19
-
20
- return fixtures.given.dependencies();
21
- });
22
-
23
- expect(sut.dependencies).toEqual(
24
- expect.arrayContaining(fixtures.given.dependencies())
25
- );
26
- expect(sut.description).toEqual({
27
- before: [expect.any(Function)],
28
- behavior: [expect.any(Function), expect.any(Function)],
29
- after: [expect.any(Function)]
30
- });
31
- });
32
- });
33
-
34
- function getFixtures() {
35
- return {
36
- given: {
37
- dependencies(): Dependency[] {
38
- return [];
39
- }
40
- }
41
- };
42
- }
package/src/strategy.ts DELETED
@@ -1,36 +0,0 @@
1
- import { Observable, of } from 'rxjs';
2
-
3
- import { Dependency } from './module';
4
-
5
- export type Descriptor = () => Observable<unknown>;
6
-
7
- export let before: (descriptor: Descriptor) => void;
8
- export let behavior: (descriptor: Descriptor) => void;
9
- export let after: (descriptor: Descriptor) => void;
10
-
11
- export function strategy(descriptor: () => Dependency[]) {
12
- const description = {
13
- before: Array.of<Descriptor>(),
14
- behavior: Array.of<Descriptor>(),
15
- after: Array.of<Descriptor>()
16
- };
17
-
18
- before = descriptor => description.before.push(descriptor);
19
- behavior = descriptor => description.behavior.push(descriptor);
20
- after = descriptor => description.after.push(descriptor);
21
-
22
- const dependencies = descriptor();
23
-
24
- if (!description.before.length) {
25
- description.before.push(() => of(true));
26
- }
27
-
28
- if (!description.after.length) {
29
- description.after.push(() => of(true));
30
- }
31
-
32
- return {
33
- dependencies,
34
- description
35
- };
36
- }
@@ -1,61 +0,0 @@
1
- import { Observable } from 'rxjs';
2
- import { WebSocket } from 'ws';
3
-
4
- import { useLogger } from './use-logger';
5
- import { useTimestamp } from './use-timestamp';
6
-
7
- export function whenSocket(
8
- url: string,
9
- options: { pingInterval?: number } = { pingInterval: 5000 }
10
- ): [Observable<{ timestamp: number; payload: unknown }>, (message: unknown) => void] {
11
- const { debug } = useLogger('whenSocket');
12
-
13
- const message = new Observable<{ timestamp: number; payload: unknown }>(stream => {
14
- const socket = new WebSocket(url);
15
- let isAlive = false;
16
- let interval: NodeJS.Timeout | undefined;
17
-
18
- socket.onmessage = it =>
19
- stream.next({ timestamp: useTimestamp(), payload: JSON.parse(it.data as string) });
20
- socket.onerror = it => {
21
- clearInterval(interval);
22
- debug('errored', url);
23
- stream.error(it);
24
- };
25
- socket.onclose = () => {
26
- debug('closed', url);
27
- clearInterval(interval);
28
- stream.error();
29
- };
30
- socket.onopen = () => {
31
- debug('opened', url);
32
- isAlive = true;
33
- interval = setInterval(() => {
34
- if (isAlive) {
35
- isAlive = false;
36
-
37
- socket.ping();
38
- } else {
39
- socket.terminate();
40
- clearInterval(interval);
41
- }
42
- }, options.pingInterval);
43
-
44
- socket.on('pong', () => {
45
- isAlive = true;
46
- });
47
-
48
- socket.on('ping', () => {
49
- isAlive = true;
50
- socket.pong();
51
- });
52
- };
53
-
54
- return () => {
55
- socket.terminate();
56
- clearInterval(interval);
57
- };
58
- });
59
-
60
- return [message, (message: unknown) => JSON.stringify(message)];
61
- }
@@ -1,46 +0,0 @@
1
- import { makeTestModule } from '@lib/make-test-module';
2
-
3
- import { instrumentOf, InstrumentSelector } from './instrument';
4
- import { withMemo } from './with-memo';
5
-
6
- describe(withMemo.name, () => {
7
- let fixtures: Awaited<ReturnType<typeof getFixtures>>;
8
-
9
- beforeEach(async () => {
10
- fixtures = await getFixtures();
11
- });
12
-
13
- test('memorize same values for same arguments', () => {
14
- const { act, getValue } = fixtures;
15
-
16
- act(() => {
17
- const value1 = getValue(instrumentOf('binance:btc-usdt'));
18
- const value2 = getValue(instrumentOf('binance:btc-usdt'));
19
-
20
- expect(Object.is(value1, value2)).toBeTruthy();
21
- });
22
- });
23
-
24
- test('memorize different values for different arguments', () => {
25
- const { act, getValue } = fixtures;
26
-
27
- act(() => {
28
- const value1 = getValue(instrumentOf('binance:btc-usdt'));
29
- const value2 = getValue(instrumentOf('binance:btc-busd'));
30
-
31
- expect(value1).toEqual('binance:btc-usdt');
32
- expect(value2).toEqual('binance:btc-busd');
33
- });
34
- });
35
- });
36
-
37
- async function getFixtures() {
38
- const { act } = await makeTestModule([]);
39
-
40
- const getValue = withMemo((instrument: InstrumentSelector) => instrument.id);
41
-
42
- return {
43
- act,
44
- getValue: act(() => (instrument: InstrumentSelector) => getValue(instrument))
45
- };
46
- }
package/src/with-memo.ts DELETED
@@ -1,33 +0,0 @@
1
- import { isObservable, Observable, shareReplay } from 'rxjs';
2
- import { v4 } from 'uuid';
3
-
4
- import { throwWithContext } from './module';
5
- import { asReadonly } from './operators';
6
- import { dependency } from './use-hash';
7
- import { useMemo } from './use-memo';
8
-
9
- export function withMemo<T extends Array<dependency>, U>(
10
- fn: (...args: T) => U
11
- ): (...args: T) => U;
12
- export function withMemo<T extends Array<dependency>, U>(
13
- fn: (...args: T) => Observable<U>
14
- ): (...args: T) => Observable<U>;
15
-
16
- export function withMemo<T extends Array<dependency>, U>(
17
- fn: (...args: T) => U | Observable<U>
18
- ): (...args: T) => U | Observable<U> {
19
- throwWithContext();
20
-
21
- const uniqueId = v4();
22
-
23
- return (...args: T): U | Observable<U> =>
24
- useMemo(() => {
25
- const value = fn(...args);
26
-
27
- if (isObservable(value)) {
28
- return value.pipe(asReadonly(), shareReplay(1));
29
- }
30
-
31
- return value;
32
- }, [uniqueId, ...args]);
33
- }