@quantform/core 0.3.222 → 0.3.230
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 +3 -2
- package/dist/adapter/adapter.event.js.map +1 -1
- package/dist/adapter/adapter.js +3 -3
- 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 +2 -2
- package/dist/adapter/backtester/backtester-cursor.js +5 -1
- package/dist/adapter/backtester/backtester-cursor.js.map +1 -1
- package/dist/adapter/backtester/backtester-cursor.spec.js +5 -5
- 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 -2
- package/dist/bin.js +6 -4
- 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 +1 -2
- package/dist/index.js +1 -2
- package/dist/index.js.map +1 -1
- package/dist/indicator/truerange.spec.js +6 -6
- 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 +3 -3
- package/dist/session/session.js +14 -27
- 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/feed.d.ts +7 -4
- package/dist/storage/feed.js +21 -0
- package/dist/storage/feed.js.map +1 -1
- package/dist/storage/index.d.ts +1 -2
- package/dist/storage/index.js +1 -2
- package/dist/storage/index.js.map +1 -1
- package/dist/storage/measurement.d.ts +7 -9
- package/dist/storage/measurement.js +25 -0
- package/dist/storage/measurement.js.map +1 -1
- package/dist/storage/storage.d.ts +23 -0
- package/dist/storage/storage.js +48 -0
- package/dist/storage/storage.js.map +1 -0
- 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 +7 -7
- 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 +4 -4
- package/src/adapter/backtester/backtester-adapter.ts +4 -6
- package/src/adapter/backtester/backtester-cursor.spec.ts +8 -8
- package/src/adapter/backtester/backtester-cursor.ts +7 -3
- 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 +8 -6
- 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 +1 -7
- package/src/indicator/truerange.spec.ts +1 -1
- package/src/session/index.ts +1 -0
- package/src/session/session-descriptor.ts +29 -7
- package/src/session/session-statement.ts +119 -0
- package/src/session/session.spec.ts +6 -4
- package/src/session/session.ts +67 -33
- 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/feed.ts +32 -7
- package/src/storage/index.ts +1 -2
- package/src/storage/measurement.ts +28 -14
- package/src/storage/storage.ts +76 -0
- 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 +10 -10
- 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/dist/storage/feed.interceptor.d.ts +0 -14
- package/dist/storage/feed.interceptor.js +0 -52
- package/dist/storage/feed.interceptor.js.map +0 -1
- package/dist/storage/in-memory.feed.d.ts +0 -10
- package/dist/storage/in-memory.feed.js +0 -30
- package/dist/storage/in-memory.feed.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
- package/src/storage/feed.interceptor.ts +0 -92
- package/src/storage/in-memory.feed.ts +0 -38
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { InstrumentSelector } from '../../domain';
|
|
2
2
|
import { StoreEvent } from '../../store/event';
|
|
3
3
|
import { Feed } from '../../storage';
|
|
4
|
-
import { timestamp } from '../../
|
|
4
|
+
import { timestamp } from '../../shared';
|
|
5
5
|
|
|
6
6
|
export class BacktesterCursor {
|
|
7
7
|
private page = new Array<StoreEvent>();
|
|
@@ -26,7 +26,7 @@ export class BacktesterCursor {
|
|
|
26
26
|
return this.page[this.pageIndex++];
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
async fetchNextPage(from: timestamp, to:
|
|
29
|
+
async fetchNextPage(from: timestamp, to: number): Promise<void> {
|
|
30
30
|
if (this.completed) {
|
|
31
31
|
return;
|
|
32
32
|
}
|
|
@@ -36,7 +36,11 @@ export class BacktesterCursor {
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
this.pageIndex = 0;
|
|
39
|
-
this.page = await this.feed.
|
|
39
|
+
this.page = await this.feed.query(this.instrument, {
|
|
40
|
+
from,
|
|
41
|
+
to,
|
|
42
|
+
count: 10000
|
|
43
|
+
});
|
|
40
44
|
|
|
41
45
|
this.completed = this.page.length == 0;
|
|
42
46
|
}
|
|
@@ -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
|
@@ -8,8 +8,9 @@ import { PaperAdapter, PaperOptions } from './adapter/paper';
|
|
|
8
8
|
import { Session, SessionDescriptor } from './session';
|
|
9
9
|
import { Store } from './store';
|
|
10
10
|
import { instrumentOf } from './domain';
|
|
11
|
-
import { Topic, event, handler } from './
|
|
11
|
+
import { Topic, event, handler } from './shared/topic';
|
|
12
12
|
import minimist = require('minimist');
|
|
13
|
+
import { Logger } from './shared';
|
|
13
14
|
|
|
14
15
|
export interface IpcCommand {
|
|
15
16
|
type;
|
|
@@ -86,7 +87,7 @@ class ExecutionHandler extends Topic<{ type: string }, ExecutionAccessor> {
|
|
|
86
87
|
@handler(IpcBacktestModeCommand)
|
|
87
88
|
onBacktestMode(command: IpcBacktestModeCommand, accessor: ExecutionAccessor) {
|
|
88
89
|
return new Promise<void>(async resolve => {
|
|
89
|
-
|
|
90
|
+
const [session, streamer] = backtest(this.descriptor, {
|
|
90
91
|
from: command.from,
|
|
91
92
|
to: command.to,
|
|
92
93
|
balance: command.balance,
|
|
@@ -102,17 +103,18 @@ class ExecutionHandler extends Topic<{ type: string }, ExecutionAccessor> {
|
|
|
102
103
|
|
|
103
104
|
await accessor.session.dispose();
|
|
104
105
|
|
|
105
|
-
accessor.session.statement(statement);
|
|
106
|
-
|
|
107
106
|
this.notify({ type: 'backtest:completed', statement });
|
|
108
107
|
|
|
109
108
|
resolve();
|
|
110
109
|
}
|
|
111
110
|
});
|
|
112
111
|
|
|
112
|
+
accessor.session = session;
|
|
113
|
+
|
|
113
114
|
this.notify({ type: 'backtest:started' });
|
|
114
115
|
|
|
115
116
|
await accessor.session.awake();
|
|
117
|
+
await streamer.tryContinue().catch(it => Logger.error(it));
|
|
116
118
|
});
|
|
117
119
|
}
|
|
118
120
|
|
|
@@ -197,7 +199,7 @@ export async function run(
|
|
|
197
199
|
export function backtest(
|
|
198
200
|
descriptor: SessionDescriptor,
|
|
199
201
|
options: BacktesterOptions
|
|
200
|
-
): Session {
|
|
202
|
+
): [Session, BacktesterStreamer] {
|
|
201
203
|
const store = new Store();
|
|
202
204
|
|
|
203
205
|
const streamer = new BacktesterStreamer(store, descriptor.feed, options);
|
|
@@ -208,7 +210,7 @@ export function backtest(
|
|
|
208
210
|
)
|
|
209
211
|
);
|
|
210
212
|
|
|
211
|
-
return new Session(store, aggregate, descriptor);
|
|
213
|
+
return [new Session(store, aggregate, descriptor), streamer];
|
|
212
214
|
}
|
|
213
215
|
|
|
214
216
|
export function paper(descriptor: SessionDescriptor, options: PaperOptions): Session {
|
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,11 @@
|
|
|
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';
|
|
@@ -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 => {
|
package/src/session/index.ts
CHANGED
|
@@ -2,27 +2,49 @@ import { Adapter } from '../adapter';
|
|
|
2
2
|
import { Session } from '.';
|
|
3
3
|
import { Measurement } from '../storage/measurement';
|
|
4
4
|
import { Feed } from '../storage';
|
|
5
|
-
import { Behaviour } from '../behaviour';
|
|
6
5
|
import { Observable } from 'rxjs';
|
|
7
6
|
|
|
7
|
+
/**
|
|
8
|
+
* Describes a single session.
|
|
9
|
+
* You can use @run function to start a new session managed by CLI.
|
|
10
|
+
* To start managed session you should install @quantform/cli package and run
|
|
11
|
+
* specific command:
|
|
12
|
+
* - qf paper (to paper trade strategy)
|
|
13
|
+
* - qf backtest (to backtest strategy based on provided feed)
|
|
14
|
+
* - qf live (to live trade strategy)
|
|
15
|
+
* or run on your own in code:
|
|
16
|
+
* - paper(descriptor, options)
|
|
17
|
+
* - backtest(descriptor, options)
|
|
18
|
+
* - live(descriptor)
|
|
19
|
+
*/
|
|
8
20
|
export interface SessionDescriptor {
|
|
9
|
-
|
|
21
|
+
/**
|
|
22
|
+
* Unique session identifier, used to identify session in the storage.
|
|
23
|
+
* You can generate new id every time you start the new session or provide
|
|
24
|
+
* session id explicitly to resume previous session (in code or via CLI).
|
|
25
|
+
* If you don't provide session id, it will generate new one based on time.
|
|
26
|
+
*/
|
|
27
|
+
id?: number;
|
|
10
28
|
|
|
11
29
|
/**
|
|
12
|
-
*
|
|
30
|
+
* Collection of adapters used to connect to the exchanges.
|
|
13
31
|
*/
|
|
14
32
|
adapter: Adapter[];
|
|
15
33
|
|
|
16
34
|
/**
|
|
17
|
-
*
|
|
35
|
+
* Provides historical data for backtest, it's not required for live and paper
|
|
36
|
+
* sessions.
|
|
18
37
|
*/
|
|
19
|
-
|
|
20
38
|
feed?: Feed;
|
|
21
39
|
|
|
22
40
|
/**
|
|
23
|
-
*
|
|
41
|
+
* Stores session variables i.e. indicators, orders, or any other type of time
|
|
42
|
+
* series data. You can install @quantform/editor to render this data in your browser.
|
|
24
43
|
*/
|
|
25
44
|
measurement?: Measurement;
|
|
26
45
|
|
|
27
|
-
|
|
46
|
+
/**
|
|
47
|
+
* Describes your trading strategy.
|
|
48
|
+
*/
|
|
49
|
+
describe?: (session: Session) => Observable<any>;
|
|
28
50
|
}
|