@quantform/core 0.3.223 → 0.3.231
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 +3 -3
- package/dist/adapter/adapter-aggregate.js.map +1 -1
- package/dist/adapter/adapter.d.ts +4 -4
- package/dist/adapter/adapter.event.d.ts +1 -1
- package/dist/adapter/adapter.event.js +1 -1
- package/dist/adapter/adapter.js +3 -3
- package/dist/adapter/adapter.js.map +1 -1
- package/dist/adapter/backtester/backtester-adapter.d.ts +2 -2
- package/dist/adapter/backtester/backtester-adapter.js +3 -5
- package/dist/adapter/backtester/backtester-adapter.js.map +1 -1
- package/dist/adapter/backtester/backtester-cursor.d.ts +1 -1
- package/dist/adapter/backtester/backtester-cursor.spec.js.map +1 -1
- package/dist/adapter/backtester/backtester-streamer.d.ts +1 -1
- package/dist/{common/decimals.spec.d.ts → adapter/backtester/backtester-streamer.spec.d.ts} +0 -0
- package/dist/adapter/backtester/backtester-streamer.spec.js +45 -0
- package/dist/adapter/backtester/backtester-streamer.spec.js.map +1 -0
- package/dist/adapter/paper/{model/paper-model.d.ts → executor/paper-executor.d.ts} +1 -1
- package/dist/adapter/paper/{model/paper-model.js → executor/paper-executor.js} +4 -4
- package/dist/adapter/paper/executor/paper-executor.js.map +1 -0
- package/dist/adapter/paper/{model/paper-margin-model.d.ts → executor/paper-margin-executor.d.ts} +2 -2
- package/dist/adapter/paper/{model/paper-margin-model.js → executor/paper-margin-executor.js} +11 -11
- package/dist/adapter/paper/executor/paper-margin-executor.js.map +1 -0
- package/dist/adapter/paper/{model/paper-spot-model.d.ts → executor/paper-spot-executor.d.ts} +3 -3
- package/dist/adapter/paper/{model/paper-spot-model.js → executor/paper-spot-executor.js} +7 -7
- package/dist/adapter/paper/executor/paper-spot-executor.js.map +1 -0
- package/dist/adapter/paper/index.d.ts +2 -2
- package/dist/adapter/paper/index.js +2 -2
- package/dist/adapter/paper/index.js.map +1 -1
- package/dist/adapter/paper/paper-adapter.d.ts +3 -3
- package/dist/adapter/paper/paper-adapter.js +6 -6
- package/dist/adapter/paper/paper-adapter.js.map +1 -1
- package/dist/adapter/paper/paper-adapter.spec.js +2 -2
- package/dist/adapter/paper/paper-adapter.spec.js.map +1 -1
- package/dist/bin.d.ts +2 -35
- package/dist/bin.js +2 -187
- package/dist/bin.js.map +1 -1
- package/dist/domain/asset.js +1 -1
- package/dist/domain/balance.d.ts +1 -1
- package/dist/domain/balance.js +1 -3
- package/dist/domain/balance.js.map +1 -1
- package/dist/domain/candle-builder.d.ts +1 -1
- package/dist/domain/candle.d.ts +1 -1
- package/dist/domain/candle.spec.js +2 -2
- package/dist/domain/{commision.d.ts → commission.d.ts} +2 -2
- package/dist/domain/{commision.js → commission.js} +7 -7
- package/dist/domain/commission.js.map +1 -0
- package/dist/domain/component.d.ts +1 -1
- package/dist/domain/index.d.ts +1 -1
- package/dist/domain/index.js +1 -1
- package/dist/domain/index.js.map +1 -1
- package/dist/domain/instrument.d.ts +3 -3
- package/dist/domain/order.d.ts +1 -1
- package/dist/domain/orderbook.d.ts +1 -1
- package/dist/domain/position.d.ts +1 -1
- package/dist/domain/position.js +3 -3
- package/dist/domain/trade.d.ts +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/indicator/truerange.spec.js +6 -6
- package/dist/ipc.d.ts +34 -0
- package/dist/ipc.js +193 -0
- package/dist/ipc.js.map +1 -0
- package/dist/session/index.d.ts +1 -0
- package/dist/session/index.js +1 -0
- package/dist/session/index.js.map +1 -1
- package/dist/session/session-descriptor.d.ts +2 -3
- package/dist/session/session-statement.d.ts +5 -0
- package/dist/session/session-statement.js +87 -0
- package/dist/session/session-statement.js.map +1 -0
- package/dist/session/session.d.ts +2 -2
- package/dist/session/session.js +10 -19
- package/dist/session/session.js.map +1 -1
- package/dist/session/session.spec.js +3 -3
- package/dist/session/session.spec.js.map +1 -1
- package/dist/{common → shared}/datetime.d.ts +0 -0
- package/dist/{common → shared}/datetime.js +0 -0
- package/dist/{common → shared}/datetime.js.map +1 -1
- package/dist/{common → shared}/decimals.d.ts +0 -0
- package/dist/{common → shared}/decimals.js +0 -0
- package/dist/{common → shared}/decimals.js.map +1 -1
- package/dist/{common/policy.spec.d.ts → shared/decimals.spec.d.ts} +0 -0
- package/dist/{common → shared}/decimals.spec.js +0 -0
- package/dist/{common → shared}/decimals.spec.js.map +1 -1
- package/dist/{common → shared}/index.d.ts +0 -0
- package/dist/{common → shared}/index.js +0 -0
- package/dist/{common → shared}/index.js.map +1 -1
- package/dist/{common → shared}/io.d.ts +0 -0
- package/dist/{common → shared}/io.js +0 -0
- package/dist/shared/io.js.map +1 -0
- package/dist/{common → shared}/logger.d.ts +0 -0
- package/dist/{common → shared}/logger.js +0 -0
- package/dist/{common → shared}/logger.js.map +1 -1
- package/dist/{common → shared}/policy.d.ts +0 -0
- package/dist/{common → shared}/policy.js +0 -0
- package/dist/{common → shared}/policy.js.map +1 -1
- package/dist/{common/topic.spec.d.ts → shared/policy.spec.d.ts} +0 -0
- package/dist/{common → shared}/policy.spec.js +0 -0
- package/dist/{common → shared}/policy.spec.js.map +1 -1
- package/dist/{common → shared}/topic.d.ts +0 -0
- package/dist/{common → shared}/topic.js +0 -0
- package/dist/{common → shared}/topic.js.map +1 -1
- package/dist/{common/worker.spec.d.ts → shared/topic.spec.d.ts} +0 -0
- package/dist/{common → shared}/topic.spec.js +0 -0
- package/dist/{common → shared}/topic.spec.js.map +1 -1
- package/dist/{common → shared}/worker.d.ts +0 -0
- package/dist/{common → shared}/worker.js +0 -0
- package/dist/{common → shared}/worker.js.map +1 -1
- package/dist/shared/worker.spec.d.ts +1 -0
- package/dist/{common → shared}/worker.spec.js +0 -0
- package/dist/{common → shared}/worker.spec.js.map +1 -1
- package/dist/storage/measurement.d.ts +1 -1
- package/dist/store/event/store-balance.event.d.ts +1 -1
- package/dist/store/event/store-balance.event.js +1 -1
- package/dist/store/event/store-balance.event.spec.js +3 -3
- package/dist/store/event/store-balance.event.spec.js.map +1 -1
- package/dist/store/event/store-candle.event.d.ts +2 -2
- package/dist/store/event/store-candle.event.js +31 -3
- package/dist/store/event/store-candle.event.js.map +1 -1
- package/dist/store/event/store-candle.event.spec.d.ts +1 -0
- package/dist/store/event/store-candle.event.spec.js +24 -0
- package/dist/store/event/store-candle.event.spec.js.map +1 -0
- package/dist/store/event/store-instrument.event.d.ts +4 -4
- package/dist/store/event/store-instrument.event.js +3 -3
- package/dist/store/event/store-instrument.event.js.map +1 -1
- package/dist/store/event/store-instrument.event.spec.js +3 -3
- package/dist/store/event/store-instrument.event.spec.js.map +1 -1
- package/dist/store/event/store-order.event.d.ts +1 -1
- package/dist/store/event/store-order.event.js +1 -1
- package/dist/store/event/store-order.event.spec.js +2 -2
- package/dist/store/event/store-orderbook.event.d.ts +1 -1
- package/dist/store/event/store-orderbook.event.js +1 -1
- package/dist/store/event/store-position.event.d.ts +1 -1
- package/dist/store/event/store-position.event.js +1 -1
- package/dist/store/event/store-trade.event.d.ts +1 -1
- package/dist/store/event/store-trade.event.js +1 -1
- package/dist/store/event/store-trade.event.spec.js +6 -6
- package/dist/store/event/store-trade.event.spec.js.map +1 -1
- package/dist/store/event/store.event.d.ts +1 -1
- package/dist/store/store.d.ts +2 -2
- package/dist/store/store.js +1 -1
- package/dist/store/store.state.d.ts +1 -1
- package/dist/store/store.state.js.map +1 -1
- package/dist/tests/backtester-adapter.spec.js +5 -5
- package/dist/tests/backtester-adapter.spec.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/jestconfig.unit.json +2 -1
- package/package.json +1 -1
- package/src/adapter/adapter-aggregate.ts +4 -2
- package/src/adapter/adapter.event.ts +2 -2
- package/src/adapter/adapter.ts +14 -4
- package/src/adapter/backtester/backtester-adapter.ts +4 -6
- package/src/adapter/backtester/backtester-cursor.spec.ts +2 -2
- package/src/adapter/backtester/backtester-cursor.ts +1 -1
- package/src/adapter/backtester/backtester-streamer.spec.ts +53 -0
- package/src/adapter/backtester/backtester-streamer.ts +1 -1
- package/src/adapter/paper/{model/paper-model.ts → executor/paper-executor.ts} +1 -1
- package/src/adapter/paper/{model/paper-margin-model.ts → executor/paper-margin-executor.ts} +4 -4
- package/src/adapter/paper/{model/paper-spot-model.ts → executor/paper-spot-executor.ts} +5 -5
- package/src/adapter/paper/index.ts +2 -2
- package/src/adapter/paper/paper-adapter.spec.ts +4 -4
- package/src/adapter/paper/paper-adapter.ts +8 -8
- package/src/bin.ts +24 -189
- package/src/domain/asset.ts +2 -2
- package/src/domain/balance.ts +3 -5
- package/src/domain/candle-builder.ts +1 -1
- package/src/domain/candle.spec.ts +1 -1
- package/src/domain/candle.ts +1 -1
- package/src/domain/{commision.ts → commission.ts} +3 -3
- package/src/domain/component.ts +1 -1
- package/src/domain/index.ts +1 -1
- package/src/domain/instrument.ts +3 -3
- package/src/domain/order.ts +1 -1
- package/src/domain/orderbook.ts +1 -1
- package/src/domain/position.ts +2 -2
- package/src/domain/trade.ts +1 -1
- package/src/index.ts +2 -7
- package/src/indicator/truerange.spec.ts +1 -1
- package/src/ipc.ts +277 -0
- package/src/session/index.ts +1 -0
- package/src/session/session-descriptor.ts +35 -6
- package/src/session/session-statement.ts +119 -0
- package/src/session/session.spec.ts +6 -4
- package/src/session/session.ts +62 -20
- package/src/{common → shared}/datetime.ts +0 -0
- package/src/{common → shared}/decimals.spec.ts +0 -0
- package/src/{common → shared}/decimals.ts +0 -0
- package/src/{common → shared}/index.ts +0 -0
- package/src/{common → shared}/io.ts +0 -0
- package/src/{common → shared}/logger.ts +0 -0
- package/src/{common → shared}/policy.spec.ts +0 -0
- package/src/{common → shared}/policy.ts +0 -0
- package/src/{common → shared}/topic.spec.ts +0 -0
- package/src/{common → shared}/topic.ts +0 -0
- package/src/{common → shared}/worker.spec.ts +0 -0
- package/src/{common → shared}/worker.ts +0 -0
- package/src/storage/measurement.ts +1 -1
- package/src/store/event/store-balance.event.spec.ts +3 -3
- package/src/store/event/store-balance.event.ts +2 -2
- package/src/store/event/store-candle.event.spec.ts +32 -0
- package/src/store/event/store-candle.event.ts +26 -2
- package/src/store/event/store-instrument.event.spec.ts +3 -3
- package/src/store/event/store-instrument.event.ts +5 -5
- package/src/store/event/store-order.event.spec.ts +1 -1
- package/src/store/event/store-order.event.ts +2 -2
- package/src/store/event/store-orderbook.event.ts +2 -2
- package/src/store/event/store-position.event.ts +2 -2
- package/src/store/event/store-trade.event.spec.ts +2 -2
- package/src/store/event/store-trade.event.ts +2 -2
- package/src/store/event/store.event.ts +1 -1
- package/src/store/store.state.ts +2 -1
- package/src/store/store.ts +1 -1
- package/src/tests/backtester-adapter.spec.ts +7 -7
- package/dist/adapter/paper/model/paper-margin-model.js.map +0 -1
- package/dist/adapter/paper/model/paper-model.js.map +0 -1
- package/dist/adapter/paper/model/paper-spot-model.js.map +0 -1
- package/dist/behaviour/behaviour.d.ts +0 -6
- package/dist/behaviour/behaviour.js +0 -3
- package/dist/behaviour/behaviour.js.map +0 -1
- package/dist/behaviour/combined-behaviour.d.ts +0 -14
- package/dist/behaviour/combined-behaviour.js +0 -26
- package/dist/behaviour/combined-behaviour.js.map +0 -1
- package/dist/behaviour/index.d.ts +0 -3
- package/dist/behaviour/index.js +0 -16
- package/dist/behaviour/index.js.map +0 -1
- package/dist/behaviour/statement/benchmark-statement.behaviour.d.ts +0 -15
- package/dist/behaviour/statement/benchmark-statement.behaviour.js +0 -41
- package/dist/behaviour/statement/benchmark-statement.behaviour.js.map +0 -1
- package/dist/behaviour/statement/equity-statement.behaviour.d.ts +0 -15
- package/dist/behaviour/statement/equity-statement.behaviour.js +0 -54
- package/dist/behaviour/statement/equity-statement.behaviour.js.map +0 -1
- package/dist/behaviour/statement/index.d.ts +0 -1
- package/dist/behaviour/statement/index.js +0 -14
- package/dist/behaviour/statement/index.js.map +0 -1
- package/dist/behaviour/statement/period-statement.behaviour.d.ts +0 -9
- package/dist/behaviour/statement/period-statement.behaviour.js +0 -20
- package/dist/behaviour/statement/period-statement.behaviour.js.map +0 -1
- package/dist/behaviour/statement/statement.behaviour.d.ts +0 -7
- package/dist/behaviour/statement/statement.behaviour.js +0 -19
- package/dist/behaviour/statement/statement.behaviour.js.map +0 -1
- package/dist/common/io.js.map +0 -1
- package/dist/domain/commision.js.map +0 -1
- package/src/behaviour/behaviour.ts +0 -7
- package/src/behaviour/combined-behaviour.ts +0 -23
- package/src/behaviour/index.ts +0 -3
- package/src/behaviour/statement/benchmark-statement.behaviour.ts +0 -53
- package/src/behaviour/statement/equity-statement.behaviour.ts +0 -71
- package/src/behaviour/statement/index.ts +0 -1
- package/src/behaviour/statement/period-statement.behaviour.ts +0 -26
- package/src/behaviour/statement/statement.behaviour.ts +0 -19
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { Store } from '../../store';
|
|
2
|
+
import { Asset, Instrument, Timeframe } from '../../domain';
|
|
3
|
+
import { Feed, InMemoryStorage } from '../../storage';
|
|
4
|
+
import { CandleEvent } from '../../store/event';
|
|
5
|
+
import { BacktesterStreamer } from './backtester-streamer';
|
|
6
|
+
|
|
7
|
+
const instrument = new Instrument(
|
|
8
|
+
new Asset('btc', 'binance', 8),
|
|
9
|
+
new Asset('usdt', 'binance', 2),
|
|
10
|
+
'binance:btc-usdt'
|
|
11
|
+
);
|
|
12
|
+
|
|
13
|
+
describe('backtester streamer tests', () => {
|
|
14
|
+
test('should repeat specific events', done => {
|
|
15
|
+
const feed = new Feed(new InMemoryStorage());
|
|
16
|
+
const store = new Store();
|
|
17
|
+
|
|
18
|
+
store.snapshot.universe.instrument[instrument.toString()] = instrument;
|
|
19
|
+
store.snapshot.subscription.instrument[instrument.toString()] = instrument;
|
|
20
|
+
|
|
21
|
+
const streamer = new BacktesterStreamer(store, feed, {
|
|
22
|
+
balance: {},
|
|
23
|
+
from: 0,
|
|
24
|
+
to: 10,
|
|
25
|
+
completed: () => {
|
|
26
|
+
const trade = store.snapshot.trade[instrument.toString()];
|
|
27
|
+
|
|
28
|
+
expect(trade.timestamp).toEqual(8);
|
|
29
|
+
expect(trade.rate).toEqual(8);
|
|
30
|
+
expect(trade.quantity).toEqual(8);
|
|
31
|
+
expect(store.snapshot.timestamp).toEqual(8);
|
|
32
|
+
|
|
33
|
+
done();
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
feed
|
|
38
|
+
.save(instrument, [
|
|
39
|
+
new CandleEvent(instrument, Timeframe.M1, 1, 1, 1, 1, 1, 1),
|
|
40
|
+
new CandleEvent(instrument, Timeframe.M1, 2, 2, 2, 2, 2, 2),
|
|
41
|
+
new CandleEvent(instrument, Timeframe.M1, 3, 3, 3, 3, 3, 3),
|
|
42
|
+
new CandleEvent(instrument, Timeframe.M1, 4, 4, 4, 4, 4, 4),
|
|
43
|
+
new CandleEvent(instrument, Timeframe.M1, 5, 5, 5, 5, 5, 5),
|
|
44
|
+
new CandleEvent(instrument, Timeframe.M1, 6, 6, 6, 6, 6, 6),
|
|
45
|
+
new CandleEvent(instrument, Timeframe.M1, 7, 7, 7, 7, 7, 7),
|
|
46
|
+
new CandleEvent(instrument, Timeframe.M1, 8, 8, 8, 8, 8, 8)
|
|
47
|
+
])
|
|
48
|
+
.then(() => {
|
|
49
|
+
streamer.subscribe(instrument);
|
|
50
|
+
streamer.tryContinue();
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { InstrumentSelector } from '../../domain';
|
|
2
2
|
import { BacktesterCursor } from './backtester-cursor';
|
|
3
3
|
import { Store } from '../../store';
|
|
4
|
-
import { timestamp } from '../../
|
|
4
|
+
import { timestamp } from '../../shared';
|
|
5
5
|
import { Feed } from '../../storage';
|
|
6
6
|
import { BacktesterOptions } from './backtester-adapter';
|
|
7
7
|
|
|
@@ -3,7 +3,7 @@ import { Component, InstrumentSelector, Order, Orderbook, Trade } from '../../..
|
|
|
3
3
|
import { PaperAdapter } from '..';
|
|
4
4
|
import { Set } from 'typescript-collections';
|
|
5
5
|
|
|
6
|
-
export abstract class
|
|
6
|
+
export abstract class PaperExecutor {
|
|
7
7
|
private readonly pending: Record<string, Set<Order>> = {};
|
|
8
8
|
|
|
9
9
|
constructor(readonly adapter: PaperAdapter) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { pnl, weightedMean } from '../../../
|
|
1
|
+
import { pnl, weightedMean } from '../../../shared';
|
|
2
2
|
import { Order } from '../../../domain';
|
|
3
3
|
import {
|
|
4
4
|
BalanceTransactEvent,
|
|
@@ -10,9 +10,9 @@ import {
|
|
|
10
10
|
PositionPatchEvent
|
|
11
11
|
} from '../../../store/event';
|
|
12
12
|
import { PaperAdapter } from '..';
|
|
13
|
-
import {
|
|
13
|
+
import { PaperExecutor } from './paper-executor';
|
|
14
14
|
|
|
15
|
-
export class
|
|
15
|
+
export class PaperMarginExecutor extends PaperExecutor {
|
|
16
16
|
leverage = 10;
|
|
17
17
|
|
|
18
18
|
constructor(adapter: PaperAdapter) {
|
|
@@ -31,7 +31,7 @@ export class PaperMarginModel extends PaperModel {
|
|
|
31
31
|
this.adapter.store.snapshot.universe.instrument[order.instrument.toString()];
|
|
32
32
|
|
|
33
33
|
let transact = instrument.quote.floor(
|
|
34
|
-
-instrument.
|
|
34
|
+
-instrument.commission.calculateMakerFee(averageExecutionRate * order.quantity)
|
|
35
35
|
);
|
|
36
36
|
|
|
37
37
|
const id = instrument.toString();
|
|
@@ -10,10 +10,10 @@ import {
|
|
|
10
10
|
OrderPendingEvent
|
|
11
11
|
} from '../../../store/event';
|
|
12
12
|
import { PaperAdapter } from '..';
|
|
13
|
-
import {
|
|
14
|
-
import { timestamp } from '../../../
|
|
13
|
+
import { PaperExecutor } from './paper-executor';
|
|
14
|
+
import { timestamp } from '../../../shared';
|
|
15
15
|
|
|
16
|
-
export class
|
|
16
|
+
export class PaperSpotExecutor extends PaperExecutor {
|
|
17
17
|
constructor(readonly adapter: PaperAdapter) {
|
|
18
18
|
super(adapter);
|
|
19
19
|
}
|
|
@@ -39,7 +39,7 @@ export class PaperSpotModel extends PaperModel {
|
|
|
39
39
|
switch (order.side) {
|
|
40
40
|
case 'BUY':
|
|
41
41
|
transacted.base += instrument.base.floor(
|
|
42
|
-
instrument.
|
|
42
|
+
instrument.commission.applyMakerFee(order.quantity)
|
|
43
43
|
);
|
|
44
44
|
transacted.quote -= instrument.quote.floor(averageExecutionRate * order.quantity);
|
|
45
45
|
break;
|
|
@@ -47,7 +47,7 @@ export class PaperSpotModel extends PaperModel {
|
|
|
47
47
|
case 'SELL':
|
|
48
48
|
transacted.base -= instrument.base.floor(order.quantity);
|
|
49
49
|
transacted.quote += instrument.quote.floor(
|
|
50
|
-
instrument.
|
|
50
|
+
instrument.commission.applyMakerFee(averageExecutionRate * order.quantity)
|
|
51
51
|
);
|
|
52
52
|
break;
|
|
53
53
|
}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export * from './paper-adapter';
|
|
2
|
-
export * from './
|
|
3
|
-
export * from './
|
|
2
|
+
export * from './executor/paper-spot-executor';
|
|
3
|
+
export * from './executor/paper-margin-executor';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { PaperSpotExecutor } from '.';
|
|
2
2
|
import { Store } from '../../store';
|
|
3
3
|
import { Adapter } from '../adapter';
|
|
4
|
-
import {
|
|
4
|
+
import { PaperExecutor } from './executor/paper-executor';
|
|
5
5
|
import { PaperAdapter } from './paper-adapter';
|
|
6
6
|
|
|
7
7
|
class DefaultAdapter extends Adapter {
|
|
@@ -11,8 +11,8 @@ class DefaultAdapter extends Adapter {
|
|
|
11
11
|
return 123;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
return new
|
|
14
|
+
createPaperExecutor(adapter: PaperAdapter): PaperExecutor {
|
|
15
|
+
return new PaperSpotExecutor(adapter);
|
|
16
16
|
}
|
|
17
17
|
}
|
|
18
18
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Adapter, AdapterContext } from '..';
|
|
2
2
|
import { Store } from '../../store';
|
|
3
|
-
import {
|
|
4
|
-
import { handler } from '../../
|
|
3
|
+
import { PaperExecutor } from './executor/paper-executor';
|
|
4
|
+
import { handler } from '../../shared/topic';
|
|
5
5
|
import { assetOf } from '../../domain';
|
|
6
6
|
import { BalancePatchEvent } from '../../store/event';
|
|
7
7
|
import {
|
|
@@ -16,7 +16,7 @@ export class PaperOptions {
|
|
|
16
16
|
|
|
17
17
|
export class PaperAdapter extends Adapter {
|
|
18
18
|
readonly name = this.decoratedAdapter.name;
|
|
19
|
-
readonly
|
|
19
|
+
readonly executor: PaperExecutor;
|
|
20
20
|
|
|
21
21
|
constructor(
|
|
22
22
|
readonly decoratedAdapter: Adapter,
|
|
@@ -25,15 +25,15 @@ export class PaperAdapter extends Adapter {
|
|
|
25
25
|
) {
|
|
26
26
|
super();
|
|
27
27
|
|
|
28
|
-
this.
|
|
28
|
+
this.executor = this.createPaperExecutor(this);
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
timestamp() {
|
|
32
32
|
return this.decoratedAdapter.timestamp();
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
return this.decoratedAdapter.
|
|
35
|
+
createPaperExecutor(adapter: PaperAdapter): PaperExecutor {
|
|
36
|
+
return this.decoratedAdapter.createPaperExecutor(adapter);
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
onUnknownEvent(event: { type: string }, context: AdapterContext) {
|
|
@@ -67,14 +67,14 @@ export class PaperAdapter extends Adapter {
|
|
|
67
67
|
|
|
68
68
|
@handler(AdapterOrderOpenCommand)
|
|
69
69
|
onOrderOpen(event: AdapterOrderOpenCommand, context: AdapterContext) {
|
|
70
|
-
this.
|
|
70
|
+
this.executor.open(event.order);
|
|
71
71
|
|
|
72
72
|
return Promise.resolve();
|
|
73
73
|
}
|
|
74
74
|
|
|
75
75
|
@handler(AdapterOrderCancelCommand)
|
|
76
76
|
onOrderCancel(event: AdapterOrderCancelCommand, context: AdapterContext) {
|
|
77
|
-
this.
|
|
77
|
+
this.executor.cancel(event.order);
|
|
78
78
|
|
|
79
79
|
return Promise.resolve();
|
|
80
80
|
}
|
package/src/bin.ts
CHANGED
|
@@ -3,201 +3,21 @@ import {
|
|
|
3
3
|
BacktesterOptions,
|
|
4
4
|
BacktesterStreamer
|
|
5
5
|
} from './adapter/backtester';
|
|
6
|
-
import { AdapterAggregate
|
|
6
|
+
import { AdapterAggregate } from './adapter';
|
|
7
7
|
import { PaperAdapter, PaperOptions } from './adapter/paper';
|
|
8
8
|
import { Session, SessionDescriptor } from './session';
|
|
9
9
|
import { Store } from './store';
|
|
10
|
-
import { instrumentOf } from './domain';
|
|
11
|
-
import { Topic, event, handler } from './common/topic';
|
|
12
|
-
import minimist = require('minimist');
|
|
13
|
-
|
|
14
|
-
export interface IpcCommand {
|
|
15
|
-
type;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
@event
|
|
19
|
-
export class IpcPaperModeCommand implements IpcCommand {
|
|
20
|
-
type = 'paper';
|
|
21
|
-
id?: number;
|
|
22
|
-
balance: { [key: string]: number };
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
@event
|
|
26
|
-
export class IpcBacktestModeCommand implements IpcCommand {
|
|
27
|
-
type = 'backtest';
|
|
28
|
-
from: number;
|
|
29
|
-
to: number;
|
|
30
|
-
balance: { [key: string]: number };
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
@event
|
|
34
|
-
export class IpcLiveModeCommand implements IpcCommand {
|
|
35
|
-
id?: number;
|
|
36
|
-
type = 'live';
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
@event
|
|
40
|
-
export class IpcUniverseQuery implements IpcCommand {
|
|
41
|
-
type = 'universe';
|
|
42
|
-
exchange: string;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
@event
|
|
46
|
-
export class IpcFeedCommand implements IpcCommand {
|
|
47
|
-
type = 'feed';
|
|
48
|
-
instrument: string;
|
|
49
|
-
from: number;
|
|
50
|
-
to: number;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
class ExecutionAccessor {
|
|
54
|
-
session: Session;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
class ExecutionHandler extends Topic<{ type: string }, ExecutionAccessor> {
|
|
58
|
-
constructor(private readonly descriptor: SessionDescriptor) {
|
|
59
|
-
super();
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
@handler(IpcLiveModeCommand)
|
|
63
|
-
async onLiveMode(command: IpcLiveModeCommand, accessor: ExecutionAccessor) {
|
|
64
|
-
if (command.id) {
|
|
65
|
-
this.descriptor.id = command.id;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
accessor.session = live(this.descriptor);
|
|
69
|
-
|
|
70
|
-
await accessor.session.awake();
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
@handler(IpcPaperModeCommand)
|
|
74
|
-
async onPaperMode(command: IpcPaperModeCommand, accessor: ExecutionAccessor) {
|
|
75
|
-
if (command.id) {
|
|
76
|
-
this.descriptor.id = command.id;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
accessor.session = paper(this.descriptor, {
|
|
80
|
-
balance: command.balance
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
await accessor.session.awake();
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
@handler(IpcBacktestModeCommand)
|
|
87
|
-
onBacktestMode(command: IpcBacktestModeCommand, accessor: ExecutionAccessor) {
|
|
88
|
-
return new Promise<void>(async resolve => {
|
|
89
|
-
accessor.session = backtest(this.descriptor, {
|
|
90
|
-
from: command.from,
|
|
91
|
-
to: command.to,
|
|
92
|
-
balance: command.balance,
|
|
93
|
-
progress: timestamp =>
|
|
94
|
-
this.notify({
|
|
95
|
-
type: 'backtest:updated',
|
|
96
|
-
timestamp,
|
|
97
|
-
from: command.from,
|
|
98
|
-
to: command.to
|
|
99
|
-
}),
|
|
100
|
-
completed: async () => {
|
|
101
|
-
const statement = {};
|
|
102
|
-
|
|
103
|
-
await accessor.session.dispose();
|
|
104
|
-
|
|
105
|
-
accessor.session.statement(statement);
|
|
106
|
-
|
|
107
|
-
this.notify({ type: 'backtest:completed', statement });
|
|
108
|
-
|
|
109
|
-
resolve();
|
|
110
|
-
}
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
this.notify({ type: 'backtest:started' });
|
|
114
|
-
|
|
115
|
-
await accessor.session.awake();
|
|
116
|
-
});
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
@handler(IpcUniverseQuery)
|
|
120
|
-
onUniverse(query: IpcUniverseQuery, accessor: ExecutionAccessor) {
|
|
121
|
-
accessor.session = accessor.session ?? idle(this.descriptor);
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
@handler(IpcFeedCommand)
|
|
125
|
-
async onFeed(command: IpcFeedCommand, accessor: ExecutionAccessor) {
|
|
126
|
-
accessor.session = accessor.session ?? idle(this.descriptor);
|
|
127
|
-
const instrument = instrumentOf(command.instrument);
|
|
128
|
-
|
|
129
|
-
await accessor.session.awake();
|
|
130
|
-
|
|
131
|
-
this.notify({ type: 'feed:started' });
|
|
132
|
-
|
|
133
|
-
await accessor.session.aggregate.dispatch(
|
|
134
|
-
instrument.base.exchange,
|
|
135
|
-
new AdapterFeedCommand(
|
|
136
|
-
instrument,
|
|
137
|
-
command.from,
|
|
138
|
-
command.to,
|
|
139
|
-
this.descriptor.feed,
|
|
140
|
-
timestamp =>
|
|
141
|
-
this.notify({
|
|
142
|
-
type: 'feed:updated',
|
|
143
|
-
timestamp,
|
|
144
|
-
from: command.from,
|
|
145
|
-
to: command.to
|
|
146
|
-
})
|
|
147
|
-
)
|
|
148
|
-
);
|
|
149
|
-
|
|
150
|
-
this.notify({ type: 'feed:completed' });
|
|
151
|
-
|
|
152
|
-
await accessor.session.dispose();
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
private notify(message: any) {
|
|
156
|
-
if (!process.send) {
|
|
157
|
-
return;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
process.send(message);
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
export async function run(
|
|
165
|
-
descriptor: SessionDescriptor,
|
|
166
|
-
...commands: IpcCommand[]
|
|
167
|
-
): Promise<Session> {
|
|
168
|
-
const handler = new ExecutionHandler(descriptor);
|
|
169
|
-
const accessor = new ExecutionAccessor();
|
|
170
|
-
const argv = minimist(process.argv.slice(2));
|
|
171
|
-
|
|
172
|
-
if (argv.command) {
|
|
173
|
-
const json = Buffer.from(argv.command, 'base64').toString('utf-8');
|
|
174
|
-
|
|
175
|
-
commands.push(JSON.parse(json));
|
|
176
|
-
} else {
|
|
177
|
-
if (!commands.length) {
|
|
178
|
-
commands.push(new IpcPaperModeCommand());
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
for (const command of commands) {
|
|
183
|
-
await handler.dispatch(command, accessor);
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
process.on('message', async (request: any) => {
|
|
187
|
-
const response = await handler.dispatch(request, accessor);
|
|
188
|
-
|
|
189
|
-
if (response) {
|
|
190
|
-
process.send(response);
|
|
191
|
-
}
|
|
192
|
-
});
|
|
193
|
-
|
|
194
|
-
return accessor.session;
|
|
195
|
-
}
|
|
196
10
|
|
|
11
|
+
/**
|
|
12
|
+
* Starts a new backtest session.
|
|
13
|
+
* @param descriptor session descriptor.
|
|
14
|
+
* @param options backtest options.
|
|
15
|
+
* @returns new session object.
|
|
16
|
+
*/
|
|
197
17
|
export function backtest(
|
|
198
18
|
descriptor: SessionDescriptor,
|
|
199
19
|
options: BacktesterOptions
|
|
200
|
-
): Session {
|
|
20
|
+
): [Session, BacktesterStreamer] {
|
|
201
21
|
const store = new Store();
|
|
202
22
|
|
|
203
23
|
const streamer = new BacktesterStreamer(store, descriptor.feed, options);
|
|
@@ -208,9 +28,15 @@ export function backtest(
|
|
|
208
28
|
)
|
|
209
29
|
);
|
|
210
30
|
|
|
211
|
-
return new Session(store, aggregate, descriptor);
|
|
31
|
+
return [new Session(store, aggregate, descriptor), streamer];
|
|
212
32
|
}
|
|
213
33
|
|
|
34
|
+
/**
|
|
35
|
+
* Starts a new paper session.
|
|
36
|
+
* @param descriptor session descriptor.
|
|
37
|
+
* @param options backtest options.
|
|
38
|
+
* @returns new session object.
|
|
39
|
+
*/
|
|
214
40
|
export function paper(descriptor: SessionDescriptor, options: PaperOptions): Session {
|
|
215
41
|
const store = new Store();
|
|
216
42
|
|
|
@@ -222,6 +48,11 @@ export function paper(descriptor: SessionDescriptor, options: PaperOptions): Ses
|
|
|
222
48
|
return new Session(store, aggregate, descriptor);
|
|
223
49
|
}
|
|
224
50
|
|
|
51
|
+
/**
|
|
52
|
+
* Starts a new live session.
|
|
53
|
+
* @param descriptor session descriptor.
|
|
54
|
+
* @returns new session object.
|
|
55
|
+
*/
|
|
225
56
|
export function live(descriptor: SessionDescriptor): Session {
|
|
226
57
|
const store = new Store();
|
|
227
58
|
const aggregate = new AdapterAggregate(store, descriptor.adapter);
|
|
@@ -229,6 +60,10 @@ export function live(descriptor: SessionDescriptor): Session {
|
|
|
229
60
|
return new Session(store, aggregate, descriptor);
|
|
230
61
|
}
|
|
231
62
|
|
|
63
|
+
/**
|
|
64
|
+
* Starts a new idle session.
|
|
65
|
+
* @param descriptor session descriptor.
|
|
66
|
+
*/
|
|
232
67
|
export function idle(descriptor: SessionDescriptor): Session {
|
|
233
68
|
const store = new Store();
|
|
234
69
|
const aggregate = new AdapterAggregate(store, descriptor.adapter);
|
package/src/domain/asset.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { ceil, fixed, floor } from '../
|
|
1
|
+
import { ceil, fixed, floor } from '../shared/decimals';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Supposed to query specific @see Asset from
|
|
4
|
+
* Supposed to query specific @see Asset from based on string notation.
|
|
5
5
|
*/
|
|
6
6
|
export class AssetSelector {
|
|
7
7
|
private readonly id: string;
|
package/src/domain/balance.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { timestamp } from '../
|
|
1
|
+
import { timestamp } from '../shared';
|
|
2
2
|
import { Asset } from './';
|
|
3
3
|
import { Position, PositionMode } from './position';
|
|
4
4
|
import { Component } from './component';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
* Represents single asset
|
|
7
|
+
* Represents single asset balance in your wallet.
|
|
8
8
|
*/
|
|
9
9
|
export class Balance implements Component {
|
|
10
10
|
timestamp: timestamp;
|
|
@@ -38,9 +38,7 @@ export class Balance implements Component {
|
|
|
38
38
|
*/
|
|
39
39
|
get total(): number {
|
|
40
40
|
return (
|
|
41
|
-
this._free +
|
|
42
|
-
this._freezed +
|
|
43
|
-
this.getEstimatedUnrealizedPnL() /* +
|
|
41
|
+
this._free + this._freezed + this.getEstimatedUnrealizedPnL() /* +
|
|
44
42
|
this.getEstimatedMaintenanceMargin()*/
|
|
45
43
|
);
|
|
46
44
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { from } from 'rxjs';
|
|
2
2
|
import { map } from 'rxjs/operators';
|
|
3
3
|
import { TradePatchEvent } from '../store/event';
|
|
4
|
-
import { now } from '../
|
|
4
|
+
import { now } from '../shared';
|
|
5
5
|
import { Candle } from './candle';
|
|
6
6
|
import { mergeCandle } from './candle-builder';
|
|
7
7
|
import { instrumentOf } from './instrument';
|
package/src/domain/candle.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export class
|
|
1
|
+
export class Commission {
|
|
2
2
|
constructor(readonly makerRate: number, readonly takerRate: number) {}
|
|
3
3
|
|
|
4
4
|
calculateMakerFee(value: number) {
|
|
@@ -18,6 +18,6 @@ export class Commision {
|
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
export function
|
|
22
|
-
return new
|
|
21
|
+
export function commissionPercentOf(maker: number, taker: number) {
|
|
22
|
+
return new Commission(maker / 100.0, taker / 100.0);
|
|
23
23
|
}
|
package/src/domain/component.ts
CHANGED
package/src/domain/index.ts
CHANGED
|
@@ -3,7 +3,7 @@ export * from './instrument';
|
|
|
3
3
|
export * from './balance';
|
|
4
4
|
export * from './order';
|
|
5
5
|
export * from './orderbook';
|
|
6
|
-
export * from './
|
|
6
|
+
export * from './commission';
|
|
7
7
|
export * from './component';
|
|
8
8
|
export * from './candle';
|
|
9
9
|
export * from './candle-builder';
|
package/src/domain/instrument.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { timestamp } from '../
|
|
1
|
+
import { timestamp } from '../shared';
|
|
2
2
|
import { Asset, AssetSelector } from './asset';
|
|
3
|
-
import {
|
|
3
|
+
import { Commission } from './commission';
|
|
4
4
|
import { Component } from './component';
|
|
5
5
|
|
|
6
6
|
export class InstrumentSelector {
|
|
@@ -23,7 +23,7 @@ export class InstrumentSelector {
|
|
|
23
23
|
|
|
24
24
|
export class Instrument extends InstrumentSelector implements Component {
|
|
25
25
|
timestamp: timestamp;
|
|
26
|
-
|
|
26
|
+
commission: Commission;
|
|
27
27
|
cross: Instrument;
|
|
28
28
|
leverage?: number = null;
|
|
29
29
|
|
package/src/domain/order.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Component } from './component';
|
|
2
2
|
import { v4 } from 'uuid';
|
|
3
3
|
import { InstrumentSelector } from './instrument';
|
|
4
|
-
import { timestamp } from '../
|
|
4
|
+
import { timestamp } from '../shared';
|
|
5
5
|
|
|
6
6
|
export type OrderSide = 'SELL' | 'BUY';
|
|
7
7
|
export type OrderType = 'MARKET' | 'LIMIT' | 'STOP-MARKET' | 'STOP-LIMIT';
|
package/src/domain/orderbook.ts
CHANGED
package/src/domain/position.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Instrument } from '../domain';
|
|
2
2
|
import { Component } from './component';
|
|
3
|
-
import { pnl, timestamp, weightedMean } from '../
|
|
3
|
+
import { pnl, timestamp, weightedMean } from '../shared';
|
|
4
4
|
import { Observable } from 'rxjs';
|
|
5
5
|
import { map, share } from 'rxjs/operators';
|
|
6
6
|
|
|
@@ -34,7 +34,7 @@ export class Position implements Component {
|
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
export function positionsFlat() {
|
|
37
|
-
return function(
|
|
37
|
+
return function (
|
|
38
38
|
source: Observable<Position[]>
|
|
39
39
|
): Observable<{ size: number; rate: number }> {
|
|
40
40
|
return source.pipe(
|
package/src/domain/trade.ts
CHANGED
package/src/index.ts
CHANGED
|
@@ -1,17 +1,12 @@
|
|
|
1
|
-
export * from './
|
|
2
|
-
export * from './common';
|
|
3
|
-
|
|
1
|
+
export * from './shared';
|
|
4
2
|
export * from './domain';
|
|
5
|
-
|
|
6
3
|
export * from './adapter';
|
|
7
4
|
export * from './adapter/backtester';
|
|
8
5
|
export * from './adapter/paper';
|
|
9
|
-
|
|
10
6
|
export * from './indicator';
|
|
11
7
|
export * from './session';
|
|
12
8
|
export * from './storage';
|
|
13
|
-
|
|
14
9
|
export * from './store';
|
|
15
10
|
export * from './store/event';
|
|
16
|
-
|
|
17
11
|
export * from './bin';
|
|
12
|
+
export * from './ipc';
|
|
@@ -2,7 +2,7 @@ import { from } from 'rxjs';
|
|
|
2
2
|
import { Candle } from '../domain';
|
|
3
3
|
import { truerange } from './truerange';
|
|
4
4
|
import { sma } from './sma';
|
|
5
|
-
import { now } from '../
|
|
5
|
+
import { now } from '../shared';
|
|
6
6
|
|
|
7
7
|
describe('truerange atr tests', () => {
|
|
8
8
|
test('should return expected value', done => {
|