@quantform/core 0.3.233 → 0.3.239

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.
@@ -0,0 +1,84 @@
1
+ import { Session } from './session';
2
+ import {
3
+ Adapter,
4
+ AdapterFeedCommand,
5
+ AdapterAwakeCommand,
6
+ AdapterAccountCommand,
7
+ AdapterSubscribeCommand,
8
+ AdapterDisposeCommand
9
+ } from './adapter';
10
+ import { PaperAdapter, PaperSpotExecutor } from './adapter/paper';
11
+ import { PaperExecutor } from './adapter/paper/executor/paper-executor';
12
+ import { ipcSub, run } from './ipc';
13
+ import { Feed, InMemoryStorage } from './storage';
14
+ import { instrumentOf } from './domain';
15
+ import { handler } from './shared';
16
+
17
+ class DefaultAdapter extends Adapter {
18
+ name = 'default';
19
+
20
+ timestamp() {
21
+ return 123;
22
+ }
23
+
24
+ createPaperExecutor(adapter: PaperAdapter): PaperExecutor {
25
+ return new PaperSpotExecutor(adapter);
26
+ }
27
+
28
+ @handler(AdapterAwakeCommand)
29
+ onAwake(command: AdapterAwakeCommand) {}
30
+
31
+ @handler(AdapterDisposeCommand)
32
+ onDispose(command: AdapterDisposeCommand) {}
33
+
34
+ @handler(AdapterSubscribeCommand)
35
+ onSubscribe(command: AdapterSubscribeCommand) {}
36
+
37
+ @handler(AdapterAccountCommand)
38
+ onAccount(command: AdapterAccountCommand) {}
39
+
40
+ @handler(AdapterFeedCommand)
41
+ onFeed(command: AdapterFeedCommand) {}
42
+ }
43
+
44
+ describe('ipc feed tests', () => {
45
+ test('should trigger adapter feed command', async () => {
46
+ const command = {
47
+ type: 'feed',
48
+ instrument: 'default:btc-usdt',
49
+ from: 0,
50
+ to: 100
51
+ };
52
+
53
+ const session = await run(
54
+ {
55
+ adapter: [new DefaultAdapter()],
56
+ feed: new Feed(new InMemoryStorage()),
57
+ describe: (session: Session) => session.trade(instrumentOf('default:btc-usdt'))
58
+ },
59
+ command
60
+ );
61
+
62
+ expect(session.descriptor).toBeUndefined();
63
+ });
64
+
65
+ test('should dispatch session started event', done => {
66
+ const command = {
67
+ type: 'paper',
68
+ balance: { 'default:usd': 100 }
69
+ };
70
+
71
+ ipcSub.on('message', (message: any) => {
72
+ expect(message.type).toBe('paper:started');
73
+ done();
74
+ });
75
+
76
+ run(
77
+ {
78
+ adapter: [new DefaultAdapter()],
79
+ describe: (session: Session) => session.trade(instrumentOf('default:btc-usdt'))
80
+ },
81
+ command
82
+ );
83
+ });
84
+ });
package/src/ipc.ts CHANGED
@@ -4,8 +4,12 @@ import { instrumentOf } from './domain';
4
4
  import { Topic, event, handler } from './shared/topic';
5
5
  import { Logger } from './shared';
6
6
  import { backtest, idle, live, paper } from './bin';
7
+ import { BacktesterStreamer } from './adapter/backtester';
8
+ import { EventEmitter } from 'events';
7
9
  import minimist = require('minimist');
8
10
 
11
+ export const ipcSub = new EventEmitter();
12
+
9
13
  /**
10
14
  * Base command/query interface for IPC communication.
11
15
  */
@@ -127,6 +131,11 @@ class IpcHandler extends Topic<{ type: string }, IpcSessionAccessor> {
127
131
 
128
132
  accessor.session = live(this.descriptor);
129
133
 
134
+ this.notify({
135
+ type: 'live:started',
136
+ session: accessor.session.descriptor?.id
137
+ });
138
+
130
139
  await accessor.session.awake();
131
140
  }
132
141
 
@@ -143,6 +152,11 @@ class IpcHandler extends Topic<{ type: string }, IpcSessionAccessor> {
143
152
  balance: command.balance
144
153
  });
145
154
 
155
+ this.notify({
156
+ type: 'paper:started',
157
+ session: accessor.session.descriptor?.id
158
+ });
159
+
146
160
  await accessor.session.awake();
147
161
  }
148
162
 
@@ -156,28 +170,43 @@ class IpcHandler extends Topic<{ type: string }, IpcSessionAccessor> {
156
170
  from: command.from,
157
171
  to: command.to,
158
172
  balance: command.balance,
159
- progress: timestamp =>
160
- this.notify({
161
- type: 'backtest:updated',
162
- timestamp,
163
- from: command.from,
164
- to: command.to
165
- }),
166
- completed: async () => {
167
- const statement = {};
168
-
169
- await accessor.session.dispose();
170
-
171
- this.notify({ type: 'backtest:completed', statement });
172
-
173
- resolve();
173
+ listener: {
174
+ onBacktestStarted: (streamer: BacktesterStreamer) => {
175
+ this.notify({
176
+ type: 'backtest:started',
177
+ session: session.descriptor?.id,
178
+ timestamp: streamer.timestamp,
179
+ from: command.from,
180
+ to: command.to
181
+ });
182
+ },
183
+ onBacktestUpdated: (streamer: BacktesterStreamer) => {
184
+ this.notify({
185
+ type: 'backtest:updated',
186
+ session: session.descriptor?.id,
187
+ timestamp: streamer.timestamp,
188
+ from: command.from,
189
+ to: command.to
190
+ });
191
+ },
192
+ onBacktestCompleted: async (streamer: BacktesterStreamer) => {
193
+ await accessor.session.dispose();
194
+
195
+ this.notify({
196
+ type: 'backtest:completed',
197
+ session: session.descriptor?.id,
198
+ timestamp: streamer.timestamp,
199
+ from: command.from,
200
+ to: command.to
201
+ });
202
+
203
+ resolve();
204
+ }
174
205
  }
175
206
  });
176
207
 
177
208
  accessor.session = session;
178
209
 
179
- this.notify({ type: 'backtest:started' });
180
-
181
210
  await accessor.session.awake();
182
211
  await streamer.tryContinue().catch(it => Logger.error(it));
183
212
  });
@@ -229,11 +258,11 @@ class IpcHandler extends Topic<{ type: string }, IpcSessionAccessor> {
229
258
  * Sends a message to parent process.
230
259
  */
231
260
  private notify(message: any) {
232
- if (!process.send) {
233
- return;
261
+ if (process.send) {
262
+ process.send(message);
234
263
  }
235
264
 
236
- process.send(message);
265
+ ipcSub.emit('message', message);
237
266
  }
238
267
  }
239
268
 
@@ -67,7 +67,7 @@ export class Session {
67
67
  // awake all adapters and synchronize trading accounts with store.
68
68
  await this.aggregate.awake(this.descriptor != null);
69
69
 
70
- if (this.descriptor.describe) {
70
+ if (this.descriptor?.describe) {
71
71
  this.subscription = this.descriptor.describe(this).subscribe();
72
72
  }
73
73
  }
@@ -69,12 +69,14 @@ describe('backtester adapter tests', () => {
69
69
  },
70
70
  from: 0,
71
71
  to: 100,
72
- completed: () => {
73
- expect(store.snapshot.timestamp).toEqual(1);
74
- expect(store.snapshot.trade[instrument.toString()].rate).toEqual(100);
75
- expect(store.snapshot.trade[instrument.toString()].quantity).toEqual(10);
72
+ listener: {
73
+ onBacktestCompleted: () => {
74
+ expect(store.snapshot.timestamp).toEqual(1);
75
+ expect(store.snapshot.trade[instrument.toString()].rate).toEqual(100);
76
+ expect(store.snapshot.trade[instrument.toString()].quantity).toEqual(10);
76
77
 
77
- done();
78
+ done();
79
+ }
78
80
  }
79
81
  });
80
82