@quantform/core 0.3.239 → 0.3.246
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapter/adapter-aggregate.js +5 -5
- package/dist/adapter/adapter-aggregate.js.map +1 -1
- package/dist/adapter/backtester/backtester-adapter.d.ts +1 -2
- package/dist/adapter/backtester/backtester-adapter.js.map +1 -1
- package/dist/adapter/backtester/backtester-streamer.d.ts +2 -1
- package/dist/adapter/backtester/backtester-streamer.js +8 -7
- package/dist/adapter/backtester/backtester-streamer.js.map +1 -1
- package/dist/adapter/backtester/backtester-streamer.spec.js +9 -10
- package/dist/adapter/backtester/backtester-streamer.spec.js.map +1 -1
- package/dist/adapter/paper/paper-adapter.js +2 -2
- package/dist/adapter/paper/paper-adapter.js.map +1 -1
- package/dist/bin.d.ts +3 -5
- package/dist/bin.js +6 -12
- package/dist/bin.js.map +1 -1
- package/dist/domain/asset.d.ts +3 -3
- package/dist/domain/asset.js +8 -8
- package/dist/domain/asset.js.map +1 -1
- package/dist/domain/asset.spec.js +4 -4
- package/dist/domain/asset.spec.js.map +1 -1
- package/dist/domain/instrument.d.ts +1 -1
- package/dist/domain/instrument.js +6 -6
- package/dist/domain/instrument.js.map +1 -1
- package/dist/domain/instrument.spec.js +7 -7
- package/dist/domain/instrument.spec.js.map +1 -1
- package/dist/domain/orderbook.d.ts +0 -1
- package/dist/ipc.d.ts +10 -16
- package/dist/ipc.js +82 -68
- package/dist/ipc.js.map +1 -1
- package/dist/ipc.spec.js +24 -8
- package/dist/ipc.spec.js.map +1 -1
- package/dist/session/session-descriptor.d.ts +6 -3
- package/dist/session/session.d.ts +2 -2
- package/dist/session/session.js +10 -11
- package/dist/session/session.js.map +1 -1
- package/dist/session/session.spec.js +1 -5
- package/dist/session/session.spec.js.map +1 -1
- package/dist/shared/index.d.ts +1 -0
- package/dist/shared/index.js +1 -0
- package/dist/shared/index.js.map +1 -1
- package/dist/shared/task.d.ts +6 -0
- package/dist/shared/task.js +25 -0
- package/dist/shared/task.js.map +1 -0
- package/dist/store/event/store-instrument.event.js +1 -1
- package/dist/store/event/store-instrument.event.js.map +1 -1
- package/dist/store/event/store-order.event.js +0 -8
- package/dist/store/event/store-order.event.js.map +1 -1
- package/dist/tests/backtester-adapter.spec.js +7 -8
- package/dist/tests/backtester-adapter.spec.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -1
- package/src/adapter/adapter-aggregate.ts +5 -5
- package/src/adapter/backtester/backtester-adapter.ts +2 -3
- package/src/adapter/backtester/backtester-streamer.spec.ts +10 -6
- package/src/adapter/backtester/backtester-streamer.ts +8 -7
- package/src/adapter/paper/paper-adapter.ts +2 -2
- package/src/bin.ts +17 -18
- package/src/domain/asset.spec.ts +4 -4
- package/src/domain/asset.ts +9 -9
- package/src/domain/instrument.spec.ts +7 -7
- package/src/domain/instrument.ts +6 -6
- package/src/domain/orderbook.ts +1 -1
- package/src/ipc.spec.ts +36 -8
- package/src/ipc.ts +99 -88
- package/src/session/session-descriptor.ts +7 -4
- package/src/session/session.spec.ts +1 -5
- package/src/session/session.ts +11 -11
- package/src/shared/index.ts +1 -0
- package/src/shared/task.ts +30 -0
- package/src/store/event/store-instrument.event.ts +1 -1
- package/src/store/event/store-order.event.ts +0 -12
- package/src/tests/backtester-adapter.spec.ts +11 -7
package/src/ipc.ts
CHANGED
|
@@ -2,13 +2,17 @@ import { AdapterFeedCommand } from './adapter';
|
|
|
2
2
|
import { Session, SessionDescriptor } from './session';
|
|
3
3
|
import { instrumentOf } from './domain';
|
|
4
4
|
import { Topic, event, handler } from './shared/topic';
|
|
5
|
-
import { Logger } from './shared';
|
|
6
|
-
import { backtest,
|
|
5
|
+
import { runTask, Logger } from './shared';
|
|
6
|
+
import { backtest, live, paper } from './bin';
|
|
7
7
|
import { BacktesterStreamer } from './adapter/backtester';
|
|
8
|
+
import { Observable } from 'rxjs';
|
|
8
9
|
import { EventEmitter } from 'events';
|
|
10
|
+
import { join } from 'path';
|
|
9
11
|
import minimist = require('minimist');
|
|
12
|
+
import dotenv = require('dotenv');
|
|
10
13
|
|
|
11
|
-
|
|
14
|
+
// force to load environment variables from .env file if this file imported.
|
|
15
|
+
dotenv.config();
|
|
12
16
|
|
|
13
17
|
/**
|
|
14
18
|
* Base command/query interface for IPC communication.
|
|
@@ -44,12 +48,6 @@ export class IpcPaperCommand implements IpcCommand {
|
|
|
44
48
|
* The optional session identifier.
|
|
45
49
|
*/
|
|
46
50
|
id?: number;
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Specifies trading balance, for example:
|
|
50
|
-
* { "binance:usdt": 1000 }
|
|
51
|
-
*/
|
|
52
|
-
balance: { [key: string]: number };
|
|
53
51
|
}
|
|
54
52
|
|
|
55
53
|
/**
|
|
@@ -58,28 +56,6 @@ export class IpcPaperCommand implements IpcCommand {
|
|
|
58
56
|
@event
|
|
59
57
|
export class IpcBacktestCommand implements IpcCommand {
|
|
60
58
|
type = 'backtest';
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Start date of the backtest in unix timestamp.
|
|
64
|
-
*/
|
|
65
|
-
from: number;
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* Due date of the backtest in unix timestamp.
|
|
69
|
-
*/
|
|
70
|
-
to: number;
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* Specifies trading balance, for example:
|
|
74
|
-
* { "binance:usdt": 1000 }
|
|
75
|
-
*/
|
|
76
|
-
balance: { [key: string]: number };
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
@event
|
|
80
|
-
export class IpcUniverseQuery implements IpcCommand {
|
|
81
|
-
type = 'universe';
|
|
82
|
-
exchange: string;
|
|
83
59
|
}
|
|
84
60
|
|
|
85
61
|
/**
|
|
@@ -97,12 +73,25 @@ export class IpcFeedCommand implements IpcCommand {
|
|
|
97
73
|
/**
|
|
98
74
|
* Start date of the feed in unix timestamp.
|
|
99
75
|
*/
|
|
100
|
-
from
|
|
76
|
+
from?: number;
|
|
101
77
|
|
|
102
78
|
/**
|
|
103
79
|
* Due date of the feed in unix timestamp.
|
|
104
80
|
*/
|
|
105
|
-
to
|
|
81
|
+
to?: number;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Executes user task defined in quantform.ts file.
|
|
86
|
+
*/
|
|
87
|
+
@event
|
|
88
|
+
export class IpcTaskCommand implements IpcCommand {
|
|
89
|
+
type = 'task';
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Name of the task to execute.
|
|
93
|
+
*/
|
|
94
|
+
taskName: string;
|
|
106
95
|
}
|
|
107
96
|
|
|
108
97
|
/**
|
|
@@ -112,11 +101,13 @@ class IpcSessionAccessor {
|
|
|
112
101
|
session: Session;
|
|
113
102
|
}
|
|
114
103
|
|
|
104
|
+
export declare type IpcSessionDescriptor = SessionDescriptor & { ipcSub?: EventEmitter };
|
|
105
|
+
|
|
115
106
|
/**
|
|
116
107
|
* Inter process communication handler.
|
|
117
108
|
*/
|
|
118
109
|
class IpcHandler extends Topic<{ type: string }, IpcSessionAccessor> {
|
|
119
|
-
constructor(private readonly descriptor:
|
|
110
|
+
constructor(private readonly descriptor: IpcSessionDescriptor) {
|
|
120
111
|
super();
|
|
121
112
|
}
|
|
122
113
|
|
|
@@ -136,7 +127,7 @@ class IpcHandler extends Topic<{ type: string }, IpcSessionAccessor> {
|
|
|
136
127
|
session: accessor.session.descriptor?.id
|
|
137
128
|
});
|
|
138
129
|
|
|
139
|
-
await accessor.session.awake();
|
|
130
|
+
await accessor.session.awake(this.describe());
|
|
140
131
|
}
|
|
141
132
|
|
|
142
133
|
/**
|
|
@@ -148,16 +139,14 @@ class IpcHandler extends Topic<{ type: string }, IpcSessionAccessor> {
|
|
|
148
139
|
this.descriptor.id = command.id;
|
|
149
140
|
}
|
|
150
141
|
|
|
151
|
-
accessor.session = paper(this.descriptor
|
|
152
|
-
balance: command.balance
|
|
153
|
-
});
|
|
142
|
+
accessor.session = paper(this.descriptor);
|
|
154
143
|
|
|
155
144
|
this.notify({
|
|
156
145
|
type: 'paper:started',
|
|
157
146
|
session: accessor.session.descriptor?.id
|
|
158
147
|
});
|
|
159
148
|
|
|
160
|
-
await accessor.session.awake();
|
|
149
|
+
await accessor.session.awake(this.describe());
|
|
161
150
|
}
|
|
162
151
|
|
|
163
152
|
/**
|
|
@@ -167,73 +156,60 @@ class IpcHandler extends Topic<{ type: string }, IpcSessionAccessor> {
|
|
|
167
156
|
onBacktestMode(command: IpcBacktestCommand, accessor: IpcSessionAccessor) {
|
|
168
157
|
return new Promise<void>(async resolve => {
|
|
169
158
|
const [session, streamer] = backtest(this.descriptor, {
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
this.
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
this.
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
this.
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
to: command.to
|
|
201
|
-
});
|
|
202
|
-
|
|
203
|
-
resolve();
|
|
204
|
-
}
|
|
159
|
+
onBacktestStarted: (streamer: BacktesterStreamer) => {
|
|
160
|
+
this.notify({
|
|
161
|
+
type: 'backtest:started',
|
|
162
|
+
session: session.descriptor?.id,
|
|
163
|
+
timestamp: streamer.timestamp,
|
|
164
|
+
from: this.descriptor.options.backtester.from,
|
|
165
|
+
to: this.descriptor.options.backtester.to
|
|
166
|
+
});
|
|
167
|
+
},
|
|
168
|
+
onBacktestUpdated: (streamer: BacktesterStreamer) => {
|
|
169
|
+
this.notify({
|
|
170
|
+
type: 'backtest:updated',
|
|
171
|
+
session: session.descriptor?.id,
|
|
172
|
+
timestamp: streamer.timestamp,
|
|
173
|
+
from: this.descriptor.options.backtester.from,
|
|
174
|
+
to: this.descriptor.options.backtester.to
|
|
175
|
+
});
|
|
176
|
+
},
|
|
177
|
+
onBacktestCompleted: async (streamer: BacktesterStreamer) => {
|
|
178
|
+
await accessor.session.dispose();
|
|
179
|
+
|
|
180
|
+
this.notify({
|
|
181
|
+
type: 'backtest:completed',
|
|
182
|
+
session: session.descriptor?.id,
|
|
183
|
+
timestamp: streamer.timestamp,
|
|
184
|
+
from: this.descriptor.options.backtester.from,
|
|
185
|
+
to: this.descriptor.options.backtester.to
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
resolve();
|
|
205
189
|
}
|
|
206
190
|
});
|
|
207
191
|
|
|
208
192
|
accessor.session = session;
|
|
209
193
|
|
|
210
|
-
await accessor.session.awake();
|
|
194
|
+
await accessor.session.awake(this.describe());
|
|
211
195
|
await streamer.tryContinue().catch(it => Logger.error(it));
|
|
212
196
|
});
|
|
213
197
|
}
|
|
214
198
|
|
|
215
|
-
/**
|
|
216
|
-
* @see IpcUniverseQuery
|
|
217
|
-
*/
|
|
218
|
-
@handler(IpcUniverseQuery)
|
|
219
|
-
onUniverse(query: IpcUniverseQuery, accessor: IpcSessionAccessor) {
|
|
220
|
-
accessor.session = accessor.session ?? idle(this.descriptor);
|
|
221
|
-
}
|
|
222
|
-
|
|
223
199
|
/**
|
|
224
200
|
* @see IpcFeedCommand
|
|
225
201
|
*/
|
|
226
202
|
@handler(IpcFeedCommand)
|
|
227
203
|
async onFeed(command: IpcFeedCommand, accessor: IpcSessionAccessor) {
|
|
228
|
-
accessor.session = accessor.session ??
|
|
204
|
+
accessor.session = accessor.session ?? live(this.descriptor);
|
|
229
205
|
const instrument = instrumentOf(command.instrument);
|
|
230
206
|
|
|
231
|
-
await accessor.session.awake();
|
|
207
|
+
await accessor.session.awake(undefined);
|
|
232
208
|
|
|
233
209
|
this.notify({ type: 'feed:started' });
|
|
234
210
|
|
|
235
211
|
await accessor.session.aggregate.dispatch(
|
|
236
|
-
instrument.base.
|
|
212
|
+
instrument.base.adapter,
|
|
237
213
|
new AdapterFeedCommand(
|
|
238
214
|
instrument,
|
|
239
215
|
command.from,
|
|
@@ -254,6 +230,41 @@ class IpcHandler extends Topic<{ type: string }, IpcSessionAccessor> {
|
|
|
254
230
|
await accessor.session.dispose();
|
|
255
231
|
}
|
|
256
232
|
|
|
233
|
+
/**
|
|
234
|
+
* @see IpcTaskCommand
|
|
235
|
+
*/
|
|
236
|
+
@handler(IpcTaskCommand)
|
|
237
|
+
async onTask(query: IpcTaskCommand, accessor: IpcSessionAccessor) {
|
|
238
|
+
accessor.session = accessor.session ?? live(this.descriptor);
|
|
239
|
+
|
|
240
|
+
await accessor.session.awake(undefined);
|
|
241
|
+
|
|
242
|
+
this.notify({ type: 'task:started', taskName: query.taskName });
|
|
243
|
+
|
|
244
|
+
let result = undefined;
|
|
245
|
+
|
|
246
|
+
try {
|
|
247
|
+
result = await runTask(query.taskName, accessor.session);
|
|
248
|
+
} catch (e) {
|
|
249
|
+
result = e;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
this.notify({ type: 'task:completed', taskName: query.taskName, result });
|
|
253
|
+
|
|
254
|
+
await accessor.session.dispose();
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
describe(): (session: Session) => Observable<any> {
|
|
258
|
+
const pkg = require(join(process.cwd(), 'package.json'));
|
|
259
|
+
const describe = require(join(process.cwd(), pkg.main));
|
|
260
|
+
|
|
261
|
+
if (describe instanceof Function) {
|
|
262
|
+
return describe;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
return undefined;
|
|
266
|
+
}
|
|
267
|
+
|
|
257
268
|
/**
|
|
258
269
|
* Sends a message to parent process.
|
|
259
270
|
*/
|
|
@@ -262,7 +273,7 @@ class IpcHandler extends Topic<{ type: string }, IpcSessionAccessor> {
|
|
|
262
273
|
process.send(message);
|
|
263
274
|
}
|
|
264
275
|
|
|
265
|
-
ipcSub
|
|
276
|
+
this.descriptor.ipcSub?.emit('message', message);
|
|
266
277
|
}
|
|
267
278
|
}
|
|
268
279
|
|
|
@@ -273,7 +284,7 @@ class IpcHandler extends Topic<{ type: string }, IpcSessionAccessor> {
|
|
|
273
284
|
* @returns new session.
|
|
274
285
|
*/
|
|
275
286
|
export async function run(
|
|
276
|
-
descriptor:
|
|
287
|
+
descriptor: IpcSessionDescriptor,
|
|
277
288
|
...commands: IpcCommand[]
|
|
278
289
|
): Promise<Session> {
|
|
279
290
|
const handler = new IpcHandler(descriptor);
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Adapter } from '../adapter';
|
|
2
|
-
import { Session } from '.';
|
|
3
2
|
import { Measurement } from '../storage/measurement';
|
|
4
3
|
import { Feed } from '../storage';
|
|
5
|
-
import {
|
|
4
|
+
import { BacktesterOptions } from './../adapter/backtester';
|
|
5
|
+
import { PaperOptions } from './../adapter/paper';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Describes a single session.
|
|
@@ -44,7 +44,10 @@ export interface SessionDescriptor {
|
|
|
44
44
|
measurement?: Measurement;
|
|
45
45
|
|
|
46
46
|
/**
|
|
47
|
-
*
|
|
47
|
+
* Session additional options.
|
|
48
48
|
*/
|
|
49
|
-
|
|
49
|
+
options?: {
|
|
50
|
+
backtester?: BacktesterOptions;
|
|
51
|
+
paper?: PaperOptions;
|
|
52
|
+
};
|
|
50
53
|
}
|
|
@@ -13,11 +13,7 @@ describe('session tests', () => {
|
|
|
13
13
|
};
|
|
14
14
|
|
|
15
15
|
test('should trigger once', done => {
|
|
16
|
-
const session = paper(descriptor
|
|
17
|
-
balance: {
|
|
18
|
-
['binance:btc']: 1.23
|
|
19
|
-
}
|
|
20
|
-
});
|
|
16
|
+
const session = paper(descriptor);
|
|
21
17
|
|
|
22
18
|
session.instruments().subscribe({
|
|
23
19
|
next: it => {
|
package/src/session/session.ts
CHANGED
|
@@ -57,7 +57,7 @@ export class Session {
|
|
|
57
57
|
}
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
async awake(): Promise<void> {
|
|
60
|
+
async awake(describe: (session: Session) => Observable<any>): Promise<void> {
|
|
61
61
|
if (this.initialized) {
|
|
62
62
|
return;
|
|
63
63
|
}
|
|
@@ -67,8 +67,8 @@ 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 (
|
|
71
|
-
this.subscription =
|
|
70
|
+
if (describe) {
|
|
71
|
+
this.subscription = describe(this).subscribe();
|
|
72
72
|
}
|
|
73
73
|
}
|
|
74
74
|
|
|
@@ -151,12 +151,12 @@ export class Session {
|
|
|
151
151
|
const grouped = instrument
|
|
152
152
|
.filter(it => it != null)
|
|
153
153
|
.reduce((aggregate, it) => {
|
|
154
|
-
const
|
|
154
|
+
const adapter = it.base.adapter;
|
|
155
155
|
|
|
156
|
-
if (aggregate[
|
|
157
|
-
aggregate[
|
|
156
|
+
if (aggregate[adapter]) {
|
|
157
|
+
aggregate[adapter].push(it);
|
|
158
158
|
} else {
|
|
159
|
-
aggregate[
|
|
159
|
+
aggregate[adapter] = [it];
|
|
160
160
|
}
|
|
161
161
|
|
|
162
162
|
return aggregate;
|
|
@@ -176,7 +176,7 @@ export class Session {
|
|
|
176
176
|
await Promise.all(
|
|
177
177
|
orders.map(it =>
|
|
178
178
|
this.aggregate.dispatch<AdapterOrderOpenCommand, void>(
|
|
179
|
-
it.instrument.base.
|
|
179
|
+
it.instrument.base.adapter,
|
|
180
180
|
new AdapterOrderOpenCommand(it)
|
|
181
181
|
)
|
|
182
182
|
)
|
|
@@ -188,7 +188,7 @@ export class Session {
|
|
|
188
188
|
*/
|
|
189
189
|
cancel(order: Order): Promise<void> {
|
|
190
190
|
return this.aggregate.dispatch(
|
|
191
|
-
order.instrument.base.
|
|
191
|
+
order.instrument.base.adapter,
|
|
192
192
|
new AdapterOrderCancelCommand(order)
|
|
193
193
|
);
|
|
194
194
|
}
|
|
@@ -352,7 +352,7 @@ export class Session {
|
|
|
352
352
|
);
|
|
353
353
|
}
|
|
354
354
|
|
|
355
|
-
balance(selector
|
|
355
|
+
balance(selector: AssetSelector): Observable<Balance> {
|
|
356
356
|
return this.store.changes$.pipe(
|
|
357
357
|
startWith(selector ? this.store.snapshot.balance[selector.toString()] : null),
|
|
358
358
|
filter(
|
|
@@ -375,7 +375,7 @@ export class Session {
|
|
|
375
375
|
switchMap(() =>
|
|
376
376
|
from(
|
|
377
377
|
this.aggregate.dispatch<AdapterHistoryQuery, Candle[]>(
|
|
378
|
-
selector.base.
|
|
378
|
+
selector.base.adapter,
|
|
379
379
|
new AdapterHistoryQuery(selector, timeframe, length)
|
|
380
380
|
)
|
|
381
381
|
)
|
package/src/shared/index.ts
CHANGED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { lastValueFrom, Observable } from 'rxjs';
|
|
2
|
+
import { Session } from './../session';
|
|
3
|
+
|
|
4
|
+
declare type Task = (session: Session) => Observable<any> | Promise<any> | any;
|
|
5
|
+
|
|
6
|
+
const tasks: Record<string, Task> = {};
|
|
7
|
+
|
|
8
|
+
export function task(name: string, fn: Task) {
|
|
9
|
+
tasks[name] = fn;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export async function runTask(name: string, session: Session): Promise<void> {
|
|
13
|
+
const task = tasks[name];
|
|
14
|
+
|
|
15
|
+
if (!task) {
|
|
16
|
+
throw new Error('Unknown task: ' + name);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const result = tasks[name](session);
|
|
20
|
+
|
|
21
|
+
if (result instanceof Observable) {
|
|
22
|
+
return lastValueFrom(result);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (result instanceof Promise) {
|
|
26
|
+
return await result;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return result;
|
|
30
|
+
}
|
|
@@ -23,7 +23,7 @@ export function InstrumentPatchEventHandler(event: InstrumentPatchEvent, state:
|
|
|
23
23
|
const selector = new InstrumentSelector(
|
|
24
24
|
event.base.name,
|
|
25
25
|
event.quote.name,
|
|
26
|
-
event.base.
|
|
26
|
+
event.base.adapter
|
|
27
27
|
);
|
|
28
28
|
|
|
29
29
|
let instrument = state.universe.instrument[selector.toString()];
|
|
@@ -12,12 +12,6 @@ export class OrderLoadEvent implements StoreEvent {
|
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
export function OrderLoadEventHandler(event: OrderLoadEvent, state: State) {
|
|
15
|
-
const instrumentKey = event.order.instrument.toString();
|
|
16
|
-
|
|
17
|
-
if (!(instrumentKey in state.subscription.instrument)) {
|
|
18
|
-
throw new Error(`Trying to load order for unsubscribed instrument: ${instrumentKey}`);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
15
|
event.order.timestamp = event.timestamp;
|
|
22
16
|
|
|
23
17
|
switch (event.order.state) {
|
|
@@ -48,12 +42,6 @@ export class OrderNewEvent implements StoreEvent {
|
|
|
48
42
|
}
|
|
49
43
|
|
|
50
44
|
export function OrderNewEventHandler(event: OrderNewEvent, state: State) {
|
|
51
|
-
const instrumentKey = event.order.instrument.toString();
|
|
52
|
-
|
|
53
|
-
if (!(instrumentKey in state.subscription.instrument)) {
|
|
54
|
-
throw new Error(`Trying to order for unsubscribed instrument: ${instrumentKey}`);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
45
|
if (event.order.state != 'NEW') {
|
|
58
46
|
throw new Error(`Order is not new`);
|
|
59
47
|
}
|
|
@@ -63,13 +63,17 @@ describe('backtester adapter tests', () => {
|
|
|
63
63
|
});
|
|
64
64
|
|
|
65
65
|
test('should stream data from input array', done => {
|
|
66
|
-
const streamer = new BacktesterStreamer(
|
|
67
|
-
|
|
68
|
-
|
|
66
|
+
const streamer = new BacktesterStreamer(
|
|
67
|
+
store,
|
|
68
|
+
feed,
|
|
69
|
+
{
|
|
70
|
+
balance: {
|
|
71
|
+
['binance:usdt']: 1000
|
|
72
|
+
},
|
|
73
|
+
from: 0,
|
|
74
|
+
to: 100
|
|
69
75
|
},
|
|
70
|
-
|
|
71
|
-
to: 100,
|
|
72
|
-
listener: {
|
|
76
|
+
{
|
|
73
77
|
onBacktestCompleted: () => {
|
|
74
78
|
expect(store.snapshot.timestamp).toEqual(1);
|
|
75
79
|
expect(store.snapshot.trade[instrument.toString()].rate).toEqual(100);
|
|
@@ -78,7 +82,7 @@ describe('backtester adapter tests', () => {
|
|
|
78
82
|
done();
|
|
79
83
|
}
|
|
80
84
|
}
|
|
81
|
-
|
|
85
|
+
);
|
|
82
86
|
|
|
83
87
|
feed.save(instrument, [new TradePatchEvent(instrument, 100, 10, 1)]);
|
|
84
88
|
|