@quantform/core 0.6.5 → 0.6.7
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.d.ts +2 -2
- package/dist/adapter/adapter-aggregate.d.ts.map +1 -1
- package/dist/adapter/adapter-aggregate.js +12 -11
- package/dist/adapter/adapter.d.ts +2 -3
- package/dist/adapter/adapter.d.ts.map +1 -1
- package/dist/adapter/backtester/backtester-adapter.d.ts +1 -5
- package/dist/adapter/backtester/backtester-adapter.d.ts.map +1 -1
- package/dist/adapter/backtester/backtester-adapter.js +2 -2
- package/dist/adapter/backtester/backtester-cursor.d.ts.map +1 -1
- package/dist/adapter/backtester/backtester-cursor.js +2 -2
- package/dist/adapter/backtester/backtester-cursor.spec.d.ts +2 -0
- package/dist/adapter/backtester/backtester-cursor.spec.d.ts.map +1 -0
- package/dist/adapter/backtester/backtester-cursor.spec.js +47 -0
- package/dist/adapter/backtester/backtester-streamer.d.ts +1 -1
- package/dist/adapter/backtester/backtester-streamer.d.ts.map +1 -1
- package/dist/adapter/backtester/backtester-streamer.js +4 -5
- package/dist/adapter/backtester/backtester-streamer.spec.d.ts +2 -0
- package/dist/adapter/backtester/backtester-streamer.spec.d.ts.map +1 -0
- package/dist/adapter/backtester/backtester-streamer.spec.js +45 -0
- package/dist/adapter/backtester/error.d.ts +6 -2
- package/dist/adapter/backtester/error.d.ts.map +1 -1
- package/dist/adapter/backtester/error.js +11 -7
- package/dist/adapter/backtester/index.d.ts +4 -2
- package/dist/adapter/backtester/index.d.ts.map +1 -1
- package/dist/adapter/backtester/index.js +4 -2
- package/dist/adapter/error.d.ts +9 -3
- package/dist/adapter/error.d.ts.map +1 -1
- package/dist/adapter/error.js +16 -10
- package/dist/adapter/index.d.ts +5 -4
- package/dist/adapter/index.d.ts.map +1 -1
- package/dist/adapter/index.js +5 -4
- package/dist/adapter/paper/engine/paper-engine.d.ts.map +1 -1
- package/dist/adapter/paper/engine/paper-engine.js +7 -8
- package/dist/adapter/paper/engine/paper-engine.spec.d.ts +2 -0
- package/dist/adapter/paper/engine/paper-engine.spec.d.ts.map +1 -0
- package/dist/adapter/paper/engine/paper-engine.spec.js +63 -0
- package/dist/adapter/paper/index.d.ts +2 -2
- package/dist/adapter/paper/index.d.ts.map +1 -1
- package/dist/adapter/paper/index.js +2 -2
- package/dist/adapter/paper/paper-adapter.d.ts +1 -3
- package/dist/adapter/paper/paper-adapter.d.ts.map +1 -1
- package/dist/adapter/paper/paper-adapter.js +8 -7
- package/dist/cli/build.js +1 -1
- package/dist/cli/dev.js +6 -6
- package/dist/cli/index.js +5 -5
- package/dist/cli/internal/workspace.js +1 -1
- package/dist/cli/pull.js +6 -6
- package/dist/cli/run.js +6 -6
- package/dist/cli/test.d.ts.map +1 -1
- package/dist/cli/test.js +9 -8
- package/dist/domain/asset.d.ts +5 -1
- package/dist/domain/asset.d.ts.map +1 -1
- package/dist/domain/asset.js +13 -7
- package/dist/domain/asset.spec.d.ts +2 -0
- package/dist/domain/asset.spec.d.ts.map +1 -0
- package/dist/domain/asset.spec.js +54 -0
- package/dist/domain/balance-operator.d.ts +1 -3
- package/dist/domain/balance-operator.d.ts.map +1 -1
- package/dist/domain/balance-operator.js +2 -2
- package/dist/domain/balance-operator.spec.d.ts +2 -0
- package/dist/domain/balance-operator.spec.d.ts.map +1 -0
- package/dist/domain/balance-operator.spec.js +21 -0
- package/dist/domain/balance.d.ts +14 -15
- package/dist/domain/balance.d.ts.map +1 -1
- package/dist/domain/balance.js +30 -48
- package/dist/domain/balance.spec.d.ts +2 -0
- package/dist/domain/balance.spec.d.ts.map +1 -0
- package/dist/domain/balance.spec.js +32 -0
- package/dist/domain/commission.d.ts.map +1 -1
- package/dist/domain/commission.spec.d.ts +2 -0
- package/dist/domain/commission.spec.d.ts.map +1 -0
- package/dist/domain/commission.spec.js +30 -0
- package/dist/domain/component.d.ts +2 -2
- package/dist/domain/component.d.ts.map +1 -1
- package/dist/domain/error.d.ts +15 -5
- package/dist/domain/error.d.ts.map +1 -1
- package/dist/domain/error.js +26 -16
- package/dist/domain/index.d.ts +21 -21
- package/dist/domain/index.d.ts.map +1 -1
- package/dist/domain/index.js +21 -21
- package/dist/domain/instrument-operator.d.ts +1 -2
- package/dist/domain/instrument-operator.d.ts.map +1 -1
- package/dist/domain/instrument-operator.js +3 -3
- package/dist/domain/instrument-operator.spec.d.ts +2 -0
- package/dist/domain/instrument-operator.spec.d.ts.map +1 -0
- package/dist/domain/instrument-operator.spec.js +21 -0
- package/dist/domain/instrument.d.ts +3 -3
- package/dist/domain/instrument.d.ts.map +1 -1
- package/dist/domain/instrument.js +10 -8
- package/dist/domain/instrument.spec.d.ts +2 -0
- package/dist/domain/instrument.spec.d.ts.map +1 -0
- package/dist/domain/instrument.spec.js +51 -0
- package/dist/domain/ohlc-operator.d.ts +1 -1
- package/dist/domain/ohlc-operator.d.ts.map +1 -1
- package/dist/domain/ohlc-operator.js +4 -5
- package/dist/domain/ohlc-operator.spec.d.ts +2 -0
- package/dist/domain/ohlc-operator.spec.d.ts.map +1 -0
- package/dist/domain/ohlc-operator.spec.js +110 -0
- package/dist/domain/ohlc.d.ts.map +1 -1
- package/dist/domain/ohlc.spec.d.ts +2 -0
- package/dist/domain/ohlc.spec.d.ts.map +1 -0
- package/dist/domain/ohlc.spec.js +25 -0
- package/dist/domain/order-operator.d.ts +1 -3
- package/dist/domain/order-operator.d.ts.map +1 -1
- package/dist/domain/order-operator.js +3 -3
- package/dist/domain/order-operator.spec.d.ts +2 -0
- package/dist/domain/order-operator.spec.d.ts.map +1 -0
- package/dist/domain/order-operator.spec.js +61 -0
- package/dist/domain/order.d.ts +5 -8
- package/dist/domain/order.d.ts.map +1 -1
- package/dist/domain/order.js +14 -22
- package/dist/domain/order.spec.d.ts +2 -0
- package/dist/domain/order.spec.d.ts.map +1 -0
- package/dist/domain/order.spec.js +27 -0
- package/dist/domain/orderbook-operator.d.ts +1 -3
- package/dist/domain/orderbook-operator.d.ts.map +1 -1
- package/dist/domain/orderbook-operator.js +2 -2
- package/dist/domain/orderbook-operator.spec.d.ts +2 -0
- package/dist/domain/orderbook-operator.spec.d.ts.map +1 -0
- package/dist/domain/orderbook-operator.spec.js +19 -0
- package/dist/domain/orderbook.d.ts +3 -2
- package/dist/domain/orderbook.d.ts.map +1 -1
- package/dist/domain/orderbook.js +3 -0
- package/dist/domain/orderbook.spec.d.ts +2 -0
- package/dist/domain/orderbook.spec.d.ts.map +1 -0
- package/dist/domain/orderbook.spec.js +11 -0
- package/dist/domain/position-operator.d.ts +1 -3
- package/dist/domain/position-operator.d.ts.map +1 -1
- package/dist/domain/position-operator.js +3 -4
- package/dist/domain/position-operator.spec.d.ts +2 -0
- package/dist/domain/position-operator.spec.d.ts.map +1 -0
- package/dist/domain/position-operator.spec.js +44 -0
- package/dist/domain/position.d.ts +3 -2
- package/dist/domain/position.d.ts.map +1 -1
- package/dist/domain/position.js +2 -0
- package/dist/domain/position.spec.d.ts +2 -0
- package/dist/domain/position.spec.d.ts.map +1 -0
- package/dist/domain/position.spec.js +28 -0
- package/dist/domain/session-builder.d.ts +8 -4
- package/dist/domain/session-builder.d.ts.map +1 -1
- package/dist/domain/session-builder.js +10 -15
- package/dist/domain/session.d.ts +1 -1
- package/dist/domain/session.d.ts.map +1 -1
- package/dist/domain/session.js +11 -17
- package/dist/domain/session.spec.d.ts +2 -0
- package/dist/domain/session.spec.d.ts.map +1 -0
- package/dist/domain/session.spec.js +17 -0
- package/dist/domain/trade-operator.d.ts +1 -3
- package/dist/domain/trade-operator.d.ts.map +1 -1
- package/dist/domain/trade-operator.js +2 -2
- package/dist/domain/trade-operator.spec.d.ts +2 -0
- package/dist/domain/trade-operator.spec.d.ts.map +1 -0
- package/dist/domain/trade-operator.spec.js +21 -0
- package/dist/domain/trade.d.ts +3 -2
- package/dist/domain/trade.d.ts.map +1 -1
- package/dist/domain/trade.js +3 -0
- package/dist/domain/trade.spec.d.ts +2 -0
- package/dist/domain/trade.spec.d.ts.map +1 -0
- package/dist/domain/trade.spec.js +11 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -8
- package/dist/shared/collections.spec.d.ts +2 -0
- package/dist/shared/collections.spec.d.ts.map +1 -0
- package/dist/shared/collections.spec.js +29 -0
- package/dist/shared/decimals.spec.d.ts +2 -0
- package/dist/shared/decimals.spec.d.ts.map +1 -0
- package/dist/shared/decimals.spec.js +28 -0
- package/dist/shared/hash.d.ts +2 -0
- package/dist/shared/hash.d.ts.map +1 -0
- package/dist/shared/hash.js +12 -0
- package/dist/shared/index.d.ts +7 -7
- package/dist/shared/index.d.ts.map +1 -1
- package/dist/shared/index.js +7 -7
- package/dist/shared/logger.d.ts +8 -5
- package/dist/shared/logger.d.ts.map +1 -1
- package/dist/shared/logger.js +23 -16
- package/dist/storage/cache.d.ts +1 -1
- package/dist/storage/cache.d.ts.map +1 -1
- package/dist/storage/cache.spec.d.ts +2 -0
- package/dist/storage/cache.spec.d.ts.map +1 -0
- package/dist/storage/cache.spec.js +25 -0
- package/dist/storage/feed.d.ts +1 -1
- package/dist/storage/feed.d.ts.map +1 -1
- package/dist/storage/index.d.ts +4 -4
- package/dist/storage/index.d.ts.map +1 -1
- package/dist/storage/index.js +4 -4
- package/dist/storage/measurement.d.ts +1 -1
- package/dist/storage/measurement.d.ts.map +1 -1
- package/dist/store/error.d.ts +21 -7
- package/dist/store/error.d.ts.map +1 -1
- package/dist/store/error.js +36 -22
- package/dist/store/index.d.ts +10 -9
- package/dist/store/index.d.ts.map +1 -1
- package/dist/store/index.js +10 -9
- package/dist/store/store-balance-event.d.ts +10 -30
- package/dist/store/store-balance-event.d.ts.map +1 -1
- package/dist/store/store-balance-event.js +19 -94
- package/dist/store/store-balance-event.spec.d.ts +2 -0
- package/dist/store/store-balance-event.spec.d.ts.map +1 -0
- package/dist/store/store-balance-event.spec.js +24 -0
- package/dist/store/store-event.d.ts +1 -1
- package/dist/store/store-event.d.ts.map +1 -1
- package/dist/store/store-instrument-event.d.ts +1 -2
- package/dist/store/store-instrument-event.d.ts.map +1 -1
- package/dist/store/store-instrument-event.js +5 -6
- package/dist/store/store-instrument-event.spec.d.ts +2 -0
- package/dist/store/store-instrument-event.spec.d.ts.map +1 -0
- package/dist/store/store-instrument-event.spec.js +22 -0
- package/dist/store/store-order-event.d.ts +1 -2
- package/dist/store/store-order-event.d.ts.map +1 -1
- package/dist/store/store-order-event.js +60 -22
- package/dist/store/store-order-event.spec.d.ts +2 -0
- package/dist/store/store-order-event.spec.d.ts.map +1 -0
- package/dist/store/store-order-event.spec.js +23 -0
- package/dist/store/store-orderbook-event.d.ts +1 -2
- package/dist/store/store-orderbook-event.d.ts.map +1 -1
- package/dist/store/store-orderbook-event.js +3 -3
- package/dist/store/store-orderbook-event.spec.d.ts +2 -0
- package/dist/store/store-orderbook-event.spec.d.ts.map +1 -0
- package/dist/store/store-orderbook-event.spec.js +27 -0
- package/dist/store/store-position-event.d.ts +1 -2
- package/dist/store/store-position-event.d.ts.map +1 -1
- package/dist/store/store-position-event.js +5 -5
- package/dist/store/store-state.d.ts.map +1 -1
- package/dist/store/store-trade-event.d.ts +1 -2
- package/dist/store/store-trade-event.d.ts.map +1 -1
- package/dist/store/store-trade-event.js +3 -3
- package/dist/store/store-trade-event.spec.d.ts +2 -0
- package/dist/store/store-trade-event.spec.d.ts.map +1 -0
- package/dist/store/store-trade-event.spec.js +44 -0
- package/dist/store/store.d.ts +1 -2
- package/dist/store/store.d.ts.map +1 -1
- package/dist/store/store.js +5 -2
- package/dist/store/store.spec.d.ts +2 -0
- package/dist/store/store.spec.d.ts.map +1 -0
- package/dist/store/store.spec.js +122 -0
- package/jest.config.ts +23 -2
- package/package.json +2 -2
- package/src/adapter/adapter-aggregate.ts +35 -21
- package/src/adapter/adapter.ts +6 -7
- package/src/adapter/backtester/backtester-adapter.ts +12 -8
- package/src/adapter/backtester/backtester-cursor.spec.ts +6 -6
- package/src/adapter/backtester/backtester-cursor.ts +5 -5
- package/src/adapter/backtester/backtester-streamer.spec.ts +6 -6
- package/src/adapter/backtester/backtester-streamer.ts +12 -9
- package/src/adapter/backtester/error.ts +8 -4
- package/src/adapter/backtester/index.ts +4 -2
- package/src/adapter/error.ts +14 -8
- package/src/adapter/index.ts +5 -4
- package/src/adapter/paper/engine/paper-engine.spec.ts +6 -12
- package/src/adapter/paper/engine/paper-engine.ts +13 -28
- package/src/adapter/paper/index.ts +2 -2
- package/src/adapter/paper/paper-adapter.ts +18 -11
- package/src/cli/build.ts +1 -1
- package/src/cli/dev.ts +5 -5
- package/src/cli/index.ts +5 -5
- package/src/cli/internal/workspace.ts +1 -1
- package/src/cli/pull.ts +7 -7
- package/src/cli/run.ts +5 -5
- package/src/cli/test.ts +8 -7
- package/src/domain/asset.spec.ts +4 -4
- package/src/domain/asset.ts +13 -6
- package/src/domain/balance-operator.spec.ts +3 -6
- package/src/domain/balance-operator.ts +5 -6
- package/src/domain/balance.spec.ts +7 -77
- package/src/domain/balance.ts +51 -64
- package/src/domain/commission.spec.ts +3 -3
- package/src/domain/commission.ts +1 -1
- package/src/domain/component.ts +3 -3
- package/src/domain/error.ts +23 -18
- package/src/domain/index.ts +21 -21
- package/src/domain/instrument-operator.spec.ts +10 -7
- package/src/domain/instrument-operator.ts +6 -6
- package/src/domain/instrument.spec.ts +11 -6
- package/src/domain/instrument.ts +16 -7
- package/src/domain/ohlc-operator.spec.ts +5 -6
- package/src/domain/ohlc-operator.ts +2 -3
- package/src/domain/ohlc.spec.ts +2 -2
- package/src/domain/ohlc.ts +2 -2
- package/src/domain/order-operator.spec.ts +14 -10
- package/src/domain/order-operator.ts +8 -7
- package/src/domain/order.spec.ts +3 -6
- package/src/domain/order.ts +26 -29
- package/src/domain/orderbook-operator.spec.ts +11 -9
- package/src/domain/orderbook-operator.ts +5 -6
- package/src/domain/orderbook.spec.ts +3 -6
- package/src/domain/orderbook.ts +5 -3
- package/src/domain/position-operator.spec.ts +14 -11
- package/src/domain/position-operator.ts +12 -9
- package/src/domain/position.spec.ts +3 -6
- package/src/domain/position.ts +5 -3
- package/src/domain/session-builder.ts +14 -14
- package/src/domain/session.spec.ts +4 -4
- package/src/domain/session.ts +20 -15
- package/src/domain/trade-operator.spec.ts +4 -9
- package/src/domain/trade-operator.ts +5 -6
- package/src/domain/trade.spec.ts +3 -6
- package/src/domain/trade.ts +5 -3
- package/src/index.ts +15 -14
- package/src/shared/collections.spec.ts +2 -2
- package/src/shared/decimals.spec.ts +1 -1
- package/src/shared/hash.ts +10 -0
- package/src/shared/index.ts +7 -7
- package/src/shared/logger.ts +22 -15
- package/src/storage/cache.spec.ts +2 -3
- package/src/storage/cache.ts +2 -2
- package/src/storage/feed.ts +4 -4
- package/src/storage/index.ts +4 -4
- package/src/storage/measurement.ts +2 -2
- package/src/store/error.ts +33 -22
- package/src/store/index.ts +10 -9
- package/src/store/store-balance-event.spec.ts +5 -7
- package/src/store/store-balance-event.ts +20 -115
- package/src/store/store-event.ts +2 -2
- package/src/store/store-instrument-event.spec.ts +4 -5
- package/src/store/store-instrument-event.ts +13 -9
- package/src/store/store-order-event.spec.ts +6 -5
- package/src/store/store-order-event.ts +92 -23
- package/src/store/store-orderbook-event.spec.ts +4 -5
- package/src/store/store-orderbook-event.ts +11 -7
- package/src/store/store-position-event.ts +13 -9
- package/src/store/store-state.ts +2 -2
- package/src/store/store-trade-event.spec.ts +4 -5
- package/src/store/store-trade-event.ts +11 -7
- package/src/store/store.spec.ts +45 -31
- package/src/store/store.ts +6 -3
- package/tsconfig.json +7 -4
- package/dist/cli/error.d.ts +0 -2
- package/dist/cli/error.d.ts.map +0 -1
- package/dist/cli/error.js +0 -7
- package/dist/shared/pipe.d.ts +0 -5
- package/dist/shared/pipe.d.ts.map +0 -1
- package/dist/shared/pipe.js +0 -8
- package/src/cli/error.ts +0 -5
- package/src/shared/pipe.ts +0 -12
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.PositionPatchEvent = exports.PositionLoadEvent = void 0;
|
|
4
4
|
const domain_1 = require("../domain");
|
|
5
|
-
const
|
|
5
|
+
const store_1 = require("../store");
|
|
6
6
|
class PositionLoadEvent {
|
|
7
7
|
constructor(position, timestamp) {
|
|
8
8
|
this.position = position;
|
|
@@ -10,12 +10,12 @@ class PositionLoadEvent {
|
|
|
10
10
|
}
|
|
11
11
|
handle(state) {
|
|
12
12
|
if (!state.subscription.instrument.get(this.position.instrument.id)) {
|
|
13
|
-
throw
|
|
13
|
+
throw new store_1.InstrumentNotSubscribedError(this.position.instrument);
|
|
14
14
|
}
|
|
15
15
|
this.position.timestamp = this.timestamp;
|
|
16
16
|
const balance = state.balance.get(this.position.instrument.quote.id);
|
|
17
17
|
if (!balance) {
|
|
18
|
-
throw
|
|
18
|
+
throw new store_1.BalanceNotFoundError(this.position.instrument.quote);
|
|
19
19
|
}
|
|
20
20
|
balance.position[this.position.id] = this.position;
|
|
21
21
|
const orderbook = state.orderbook.get(this.position.instrument.id);
|
|
@@ -43,11 +43,11 @@ class PositionPatchEvent {
|
|
|
43
43
|
// eslint-disable-next-line complexity
|
|
44
44
|
handle(state, changes) {
|
|
45
45
|
if (!state.subscription.instrument.get(this.instrument.id)) {
|
|
46
|
-
throw
|
|
46
|
+
throw new store_1.InstrumentNotSubscribedError(this.instrument);
|
|
47
47
|
}
|
|
48
48
|
const balance = state.balance.get(this.instrument.quote.id);
|
|
49
49
|
if (!balance) {
|
|
50
|
-
throw
|
|
50
|
+
throw new store_1.BalanceNotFoundError(this.instrument.quote);
|
|
51
51
|
}
|
|
52
52
|
const orderbook = state.orderbook.get(this.instrument.id);
|
|
53
53
|
let position = balance.position[this.id];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store-state.d.ts","sourceRoot":"","sources":["../../src/store/store-state.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,EACL,aAAa,EACb,OAAO,EACP,SAAS,EACT,UAAU,EACV,kBAAkB,EAClB,KAAK,EACL,SAAS,EACT,KAAK,EACN,MAAM,
|
|
1
|
+
{"version":3,"file":"store-state.d.ts","sourceRoot":"","sources":["../../src/store/store-state.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,EACL,aAAa,EACb,OAAO,EACP,SAAS,EACT,UAAU,EACV,kBAAkB,EAClB,KAAK,EACL,SAAS,EACT,KAAK,EACN,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,WAAW,kBAAkB;IACjC,MAAM,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI,CAAC;IACnC,oBAAoB,IAAI,IAAI,CAAC;CAC9B;AAED,qBAAa,QAAQ,CAAC,CAAC,SAAS;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,CAAE,SAAQ,GAAG,CAAC,CAAC,CAAC;aAChC,EAAE,EAAE,MAAM;gBAAV,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC;CAGlE;AAED,qBAAa,KAAK;IAChB,SAAS,EAAE,SAAS,CAAK;IAEzB,QAAQ,EAAE;QACR,KAAK,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC;QAClB,UAAU,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC;KAC7B,CAGC;IAEF,YAAY,EAAE;QACZ,KAAK,EAAE,GAAG,CAAC,aAAa,CAAC,CAAC;QAC1B,UAAU,EAAE,GAAG,CAAC,kBAAkB,CAAC,CAAC;KACrC,CAGC;IAEF,KAAK,EAAE,GAAG,CAAC,KAAK,CAAC,CAAoB;IACrC,SAAS,EAAE,GAAG,CAAC,SAAS,CAAC,CAAwB;IACjD,OAAO,EAAE,GAAG,CAAC,OAAO,CAAC,CAAsB;IAC3C,KAAK,EAAE,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAA8B;CAC1D"}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { InstrumentSelector } from '../domain';
|
|
2
2
|
import { decimal, timestamp } from '../shared';
|
|
3
|
-
import { StoreEvent } from '
|
|
4
|
-
import { State, StateChangeTracker } from './store-state';
|
|
3
|
+
import { State, StateChangeTracker, StoreEvent } from '../store';
|
|
5
4
|
/**
|
|
6
5
|
* Patches a store with specific event @see TradePatchEvent
|
|
7
6
|
* If there is no specific @see Trade in store, it will create a new one.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store-trade-event.d.ts","sourceRoot":"","sources":["../../src/store/store-trade-event.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAS,MAAM,
|
|
1
|
+
{"version":3,"file":"store-trade-event.d.ts","sourceRoot":"","sources":["../../src/store/store-trade-event.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAS,MAAM,aAAa,CAAC;AACxD,OAAO,EAAK,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAGL,KAAK,EACL,kBAAkB,EAClB,UAAU,EACX,MAAM,YAAY,CAAC;AAEpB;;;GAGG;AACH,qBAAa,eAAgB,YAAW,UAAU;IAE9C,QAAQ,CAAC,UAAU,EAAE,kBAAkB;IACvC,QAAQ,CAAC,IAAI,EAAE,OAAO;IACtB,QAAQ,CAAC,QAAQ,EAAE,OAAO;IAC1B,QAAQ,CAAC,SAAS,EAAE,SAAS;gBAHpB,UAAU,EAAE,kBAAkB,EAC9B,IAAI,EAAE,OAAO,EACb,QAAQ,EAAE,OAAO,EACjB,SAAS,EAAE,SAAS;IAG/B,MAAM,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,kBAAkB,GAAG,IAAI;CAuBxD"}
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.TradePatchEvent = void 0;
|
|
4
4
|
const domain_1 = require("../domain");
|
|
5
5
|
const shared_1 = require("../shared");
|
|
6
|
-
const
|
|
6
|
+
const store_1 = require("../store");
|
|
7
7
|
/**
|
|
8
8
|
* Patches a store with specific event @see TradePatchEvent
|
|
9
9
|
* If there is no specific @see Trade in store, it will create a new one.
|
|
@@ -17,11 +17,11 @@ class TradePatchEvent {
|
|
|
17
17
|
}
|
|
18
18
|
handle(state, changes) {
|
|
19
19
|
if (!state.subscription.instrument.get(this.instrument.id)) {
|
|
20
|
-
throw
|
|
20
|
+
throw new store_1.InstrumentNotSubscribedError(this.instrument);
|
|
21
21
|
}
|
|
22
22
|
const instrument = state.universe.instrument.get(this.instrument.id);
|
|
23
23
|
if (!instrument) {
|
|
24
|
-
throw
|
|
24
|
+
throw new store_1.InstrumentNotSupportedError(this.instrument);
|
|
25
25
|
}
|
|
26
26
|
const trade = state.trade.tryGetOrSet(this.instrument.id, () => new domain_1.Trade(0, instrument, shared_1.d.Zero, shared_1.d.Zero));
|
|
27
27
|
state.timestamp = this.timestamp;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store-trade-event.spec.d.ts","sourceRoot":"","sources":["../../src/store/store-trade-event.spec.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const domain_1 = require("../domain");
|
|
4
|
+
const shared_1 = require("../shared");
|
|
5
|
+
const store_1 = require("../store");
|
|
6
|
+
const instrument = new domain_1.Instrument(0, new domain_1.Asset('btc', 'binance', 8), new domain_1.Asset('usdt', 'binance', 2), 'binance:btc-usdt', domain_1.Commission.Zero);
|
|
7
|
+
describe(store_1.TradePatchEvent.name, () => {
|
|
8
|
+
test('should create a new trade object and patch a store', () => {
|
|
9
|
+
var _a;
|
|
10
|
+
const timestamp = (0, shared_1.now)();
|
|
11
|
+
const store = new store_1.Store();
|
|
12
|
+
store.snapshot.universe.instrument.upsert(instrument);
|
|
13
|
+
store.snapshot.subscription.instrument.upsert(instrument);
|
|
14
|
+
store.dispatch(new store_1.TradePatchEvent(instrument, (0, shared_1.d)(1000), (0, shared_1.d)(0.1), timestamp));
|
|
15
|
+
const trade = (_a = store.snapshot.trade.get(instrument.id)) !== null && _a !== void 0 ? _a : fail();
|
|
16
|
+
expect(trade.timestamp).toEqual(timestamp);
|
|
17
|
+
expect(trade.instrument.id).toEqual(trade.instrument.id);
|
|
18
|
+
expect(trade.rate).toEqual((0, shared_1.d)(1000));
|
|
19
|
+
expect(trade.quantity).toEqual((0, shared_1.d)(0.1));
|
|
20
|
+
expect(store.snapshot.timestamp).toEqual(timestamp);
|
|
21
|
+
});
|
|
22
|
+
test('should use the existing instance of trade when patching a store', () => {
|
|
23
|
+
var _a;
|
|
24
|
+
const store = new store_1.Store();
|
|
25
|
+
const timestamp = (0, shared_1.now)();
|
|
26
|
+
store.snapshot.universe.instrument.upsert(instrument);
|
|
27
|
+
store.snapshot.subscription.instrument.upsert(instrument);
|
|
28
|
+
store.dispatch(new store_1.TradePatchEvent(instrument, (0, shared_1.d)(1000), (0, shared_1.d)(0.1), timestamp));
|
|
29
|
+
const trade = (_a = store.snapshot.trade.get(instrument.id)) !== null && _a !== void 0 ? _a : fail();
|
|
30
|
+
store.dispatch(new store_1.TradePatchEvent(instrument, (0, shared_1.d)(2000), (0, shared_1.d)(0.2), timestamp));
|
|
31
|
+
expect(trade.timestamp).toEqual(timestamp);
|
|
32
|
+
expect(trade.instrument.id).toEqual(instrument.id);
|
|
33
|
+
expect(trade.rate).toEqual((0, shared_1.d)(2000));
|
|
34
|
+
expect(trade.quantity).toEqual((0, shared_1.d)(0.2));
|
|
35
|
+
expect(store.snapshot.timestamp).toEqual(timestamp);
|
|
36
|
+
});
|
|
37
|
+
test('should throw exception when patching unsubscribed instrument', () => {
|
|
38
|
+
const store = new store_1.Store();
|
|
39
|
+
const fn = () => {
|
|
40
|
+
store.dispatch(new store_1.TradePatchEvent(instrument, (0, shared_1.d)(1000), (0, shared_1.d)(0.1), (0, shared_1.now)()));
|
|
41
|
+
};
|
|
42
|
+
expect(fn).toThrow(Error);
|
|
43
|
+
});
|
|
44
|
+
});
|
package/dist/store/store.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { Observable } from 'rxjs';
|
|
2
2
|
import { Component } from '../domain';
|
|
3
|
-
import { StoreEvent } from '
|
|
4
|
-
import { State, StateChangeTracker } from './store-state';
|
|
3
|
+
import { State, StateChangeTracker, StoreEvent } from '../store';
|
|
5
4
|
export declare class Store implements StateChangeTracker {
|
|
6
5
|
private readonly pendingChanges;
|
|
7
6
|
private readonly changes;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/store/store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAW,MAAM,MAAM,CAAC;AAE3C,OAAO,EAAE,SAAS,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/store/store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAW,MAAM,MAAM,CAAC;AAE3C,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,KAAK,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAEnE,qBAAa,KAAM,YAAW,kBAAkB;IAC9C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA0B;IACzD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA4B;IAEpD,QAAQ,CAAC,QAAQ,QAAe;IAEhC,IAAI,QAAQ,IAAI,UAAU,CAAC,SAAS,CAAC,CAEpC;IAED,QAAQ,CAAC,GAAG,MAAM,EAAE,UAAU,EAAE;IAQhC,MAAM,CAAC,SAAS,EAAE,SAAS;IAQ3B,oBAAoB;IAKpB,OAAO;CAGR"}
|
package/dist/store/store.js
CHANGED
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Store = void 0;
|
|
4
4
|
const rxjs_1 = require("rxjs");
|
|
5
|
-
const
|
|
5
|
+
const store_1 = require("../store");
|
|
6
6
|
class Store {
|
|
7
7
|
constructor() {
|
|
8
8
|
this.pendingChanges = new Array();
|
|
9
9
|
this.changes = new rxjs_1.Subject();
|
|
10
|
-
this.snapshot = new
|
|
10
|
+
this.snapshot = new store_1.State();
|
|
11
11
|
}
|
|
12
12
|
get changes$() {
|
|
13
13
|
return this.changes.asObservable();
|
|
@@ -19,6 +19,9 @@ class Store {
|
|
|
19
19
|
this.commitPendingChanges();
|
|
20
20
|
}
|
|
21
21
|
commit(component) {
|
|
22
|
+
if (this.pendingChanges.some(it => it === component)) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
22
25
|
this.pendingChanges.push(component);
|
|
23
26
|
}
|
|
24
27
|
commitPendingChanges() {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.spec.d.ts","sourceRoot":"","sources":["../../src/store/store.spec.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const rxjs_1 = require("rxjs");
|
|
4
|
+
const domain_1 = require("../domain");
|
|
5
|
+
const shared_1 = require("../shared");
|
|
6
|
+
const store_1 = require("../store");
|
|
7
|
+
const instrument = new domain_1.Instrument(0, new domain_1.Asset('abc', 'xyz', 4), new domain_1.Asset('def', 'xyz', 4), 'abc-def', domain_1.Commission.Zero);
|
|
8
|
+
describe(store_1.Store.name, () => {
|
|
9
|
+
let store;
|
|
10
|
+
beforeEach(() => {
|
|
11
|
+
store = new store_1.Store();
|
|
12
|
+
store.snapshot.universe.asset.upsert(instrument.base);
|
|
13
|
+
store.snapshot.universe.asset.upsert(instrument.quote);
|
|
14
|
+
store.snapshot.universe.instrument.upsert(instrument);
|
|
15
|
+
});
|
|
16
|
+
test('should load an existing order and not pipe a changes', () => {
|
|
17
|
+
let hasUpdatedOrder = false;
|
|
18
|
+
store.changes$.pipe((0, domain_1.order)(instrument)).subscribe({
|
|
19
|
+
next: () => {
|
|
20
|
+
hasUpdatedOrder = true;
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
store.dispatch(new store_1.BalanceLoadEvent(instrument.quote, (0, shared_1.d)(100), shared_1.d.Zero, (0, shared_1.now)()), new store_1.OrderLoadEvent(new domain_1.Order(0, '1', instrument, (0, shared_1.d)(10), 0), (0, shared_1.now)()));
|
|
24
|
+
expect(hasUpdatedOrder).toBe(false);
|
|
25
|
+
});
|
|
26
|
+
test('should create a new order and pipe a changes', () => {
|
|
27
|
+
let hasUpdatedOrder = false;
|
|
28
|
+
store.changes$.pipe((0, domain_1.order)(instrument)).subscribe({
|
|
29
|
+
next: () => {
|
|
30
|
+
hasUpdatedOrder = true;
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
store.dispatch(new store_1.BalanceLoadEvent(instrument.base, (0, shared_1.d)(100), shared_1.d.Zero, (0, shared_1.now)()), new store_1.BalanceLoadEvent(instrument.quote, (0, shared_1.d)(100), shared_1.d.Zero, (0, shared_1.now)()), new store_1.OrderNewEvent(new domain_1.Order(0, '1', instrument, (0, shared_1.d)(10), 0), (0, shared_1.now)()));
|
|
34
|
+
expect(hasUpdatedOrder).toBe(true);
|
|
35
|
+
});
|
|
36
|
+
test('should transition order state from new to pending', () => {
|
|
37
|
+
const states = ['NEW', 'PENDING'].reverse();
|
|
38
|
+
store.changes$.pipe((0, domain_1.order)(instrument)).subscribe({
|
|
39
|
+
next: it => {
|
|
40
|
+
expect(it.state).toBe(states.pop());
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
const buyOrder = new domain_1.Order(0, '1', instrument, (0, shared_1.d)(10), 0);
|
|
44
|
+
store.dispatch(new store_1.BalanceLoadEvent(instrument.base, (0, shared_1.d)(100), shared_1.d.Zero, (0, shared_1.now)()));
|
|
45
|
+
store.dispatch(new store_1.BalanceLoadEvent(instrument.quote, (0, shared_1.d)(100), shared_1.d.Zero, (0, shared_1.now)()));
|
|
46
|
+
store.dispatch(new store_1.OrderNewEvent(buyOrder, (0, shared_1.now)()));
|
|
47
|
+
store.dispatch(new store_1.OrderPendingEvent(buyOrder.id, instrument, (0, shared_1.now)()));
|
|
48
|
+
expect(buyOrder.state).toBe('PENDING');
|
|
49
|
+
expect(states.length).toBe(0);
|
|
50
|
+
});
|
|
51
|
+
test('should transition order state from new to filled', () => {
|
|
52
|
+
const states = ['NEW', 'PENDING', 'FILLED'].reverse();
|
|
53
|
+
store.changes$.pipe((0, domain_1.order)(instrument)).subscribe({
|
|
54
|
+
next: it => {
|
|
55
|
+
expect(it.state).toBe(states.pop());
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
const buyOrder = new domain_1.Order(0, '1', instrument, (0, shared_1.d)(10), 0);
|
|
59
|
+
store.dispatch(new store_1.BalanceLoadEvent(instrument.base, (0, shared_1.d)(100), shared_1.d.Zero, (0, shared_1.now)()));
|
|
60
|
+
store.dispatch(new store_1.BalanceLoadEvent(instrument.quote, (0, shared_1.d)(100), shared_1.d.Zero, (0, shared_1.now)()));
|
|
61
|
+
store.dispatch(new store_1.OrderNewEvent(buyOrder, (0, shared_1.now)()));
|
|
62
|
+
store.dispatch(new store_1.OrderPendingEvent(buyOrder.id, instrument, (0, shared_1.now)()));
|
|
63
|
+
store.dispatch(new store_1.OrderFilledEvent(buyOrder.id, instrument, (0, shared_1.d)(44), (0, shared_1.now)()));
|
|
64
|
+
expect(buyOrder.state).toBe('FILLED');
|
|
65
|
+
expect(buyOrder.averageExecutionRate).toEqual((0, shared_1.d)(44));
|
|
66
|
+
expect(states.length).toBe(0);
|
|
67
|
+
});
|
|
68
|
+
test('should transition order state from new to canceled', () => {
|
|
69
|
+
const states = ['NEW', 'PENDING', 'CANCELING', 'CANCELED'].reverse();
|
|
70
|
+
store.changes$.pipe((0, domain_1.order)(instrument)).subscribe({
|
|
71
|
+
next: it => {
|
|
72
|
+
expect(it.state).toBe(states.pop());
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
const buyOrder = new domain_1.Order(0, '1', instrument, (0, shared_1.d)(10), 0);
|
|
76
|
+
store.dispatch(new store_1.BalanceLoadEvent(instrument.base, (0, shared_1.d)(100), shared_1.d.Zero, (0, shared_1.now)()));
|
|
77
|
+
store.dispatch(new store_1.BalanceLoadEvent(instrument.quote, (0, shared_1.d)(100), shared_1.d.Zero, (0, shared_1.now)()));
|
|
78
|
+
store.dispatch(new store_1.OrderNewEvent(buyOrder, (0, shared_1.now)()));
|
|
79
|
+
store.dispatch(new store_1.OrderPendingEvent(buyOrder.id, instrument, (0, shared_1.now)()));
|
|
80
|
+
store.dispatch(new store_1.OrderCancelingEvent(buyOrder.id, instrument, (0, shared_1.now)()));
|
|
81
|
+
store.dispatch(new store_1.OrderCanceledEvent(buyOrder.id, instrument, (0, shared_1.now)()));
|
|
82
|
+
expect(buyOrder.state).toBe('CANCELED');
|
|
83
|
+
expect(states.length).toBe(0);
|
|
84
|
+
});
|
|
85
|
+
test('should patch balance with order and pipe changes once', done => {
|
|
86
|
+
(0, rxjs_1.combineLatest)([
|
|
87
|
+
store.changes$.pipe((0, domain_1.balance)(instrument.quote, store.snapshot)),
|
|
88
|
+
store.changes$.pipe((0, domain_1.order)(instrument))
|
|
89
|
+
]).subscribe({
|
|
90
|
+
next: ([balance, order]) => {
|
|
91
|
+
expect(balance.free).toEqual((0, shared_1.d)(10));
|
|
92
|
+
expect(order.state).toEqual('PENDING');
|
|
93
|
+
done();
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
const buyOrder = new domain_1.Order(0, '1', instrument, (0, shared_1.d)(10), 0);
|
|
97
|
+
store.dispatch(new store_1.BalanceLoadEvent(instrument.base, (0, shared_1.d)(10), shared_1.d.Zero, (0, shared_1.now)()), new store_1.BalanceLoadEvent(instrument.quote, (0, shared_1.d)(10), shared_1.d.Zero, (0, shared_1.now)()), new store_1.OrderNewEvent(buyOrder, (0, shared_1.now)()), new store_1.OrderPendingEvent(buyOrder.id, instrument, (0, shared_1.now)()), new store_1.BalancePatchEvent(instrument.quote, (0, shared_1.d)(10), shared_1.d.Zero, (0, shared_1.now)()));
|
|
98
|
+
});
|
|
99
|
+
test('should pipe balance and order changes', done => {
|
|
100
|
+
let counter = 2;
|
|
101
|
+
store.changes$.pipe((0, domain_1.balance)(instrument.quote, store.snapshot)).subscribe({
|
|
102
|
+
next: it => {
|
|
103
|
+
counter--;
|
|
104
|
+
expect(it.free).toEqual((0, shared_1.d)(10));
|
|
105
|
+
if (!counter) {
|
|
106
|
+
done();
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
store.changes$.pipe((0, domain_1.order)(instrument)).subscribe({
|
|
111
|
+
next: it => {
|
|
112
|
+
counter--;
|
|
113
|
+
expect(it.state).toEqual('PENDING');
|
|
114
|
+
if (!counter) {
|
|
115
|
+
done();
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
const buyOrder = new domain_1.Order(0, '1', instrument, (0, shared_1.d)(10), 0);
|
|
120
|
+
store.dispatch(new store_1.BalanceLoadEvent(instrument.base, (0, shared_1.d)(10), shared_1.d.Zero, (0, shared_1.now)()), new store_1.BalanceLoadEvent(instrument.quote, (0, shared_1.d)(10), shared_1.d.Zero, (0, shared_1.now)()), new store_1.OrderNewEvent(buyOrder, (0, shared_1.now)()), new store_1.OrderPendingEvent(buyOrder.id, instrument, (0, shared_1.now)()), new store_1.BalancePatchEvent(instrument.quote, (0, shared_1.d)(10), shared_1.d.Zero, (0, shared_1.now)()));
|
|
121
|
+
});
|
|
122
|
+
});
|
package/jest.config.ts
CHANGED
|
@@ -1,13 +1,34 @@
|
|
|
1
1
|
import { Config } from 'jest';
|
|
2
|
+
import { pathsToModuleNameMapper } from 'ts-jest';
|
|
3
|
+
import { parseJsonConfigFileContent, readConfigFile, sys } from 'typescript';
|
|
4
|
+
|
|
5
|
+
const tsconfig = parseJsonConfigFileContent(
|
|
6
|
+
readConfigFile('tsconfig.json', sys.readFile).config,
|
|
7
|
+
sys,
|
|
8
|
+
process.cwd()
|
|
9
|
+
);
|
|
10
|
+
|
|
11
|
+
const compilerOptions = tsconfig.raw.compilerOptions as any;
|
|
2
12
|
|
|
3
13
|
const config: Config = {
|
|
4
14
|
preset: 'ts-jest',
|
|
5
15
|
testEnvironment: 'node',
|
|
6
16
|
testMatch: ['**/src/**/?(*.)+(spec|test).[jt]s?(x)'],
|
|
7
17
|
transform: {
|
|
8
|
-
'^.+\\.ts?$':
|
|
18
|
+
'^.+\\.ts?$': [
|
|
19
|
+
'ts-jest',
|
|
20
|
+
{
|
|
21
|
+
isolatedModules: true,
|
|
22
|
+
tsconfig: { ...compilerOptions, sourceMap: true }
|
|
23
|
+
}
|
|
24
|
+
]
|
|
9
25
|
},
|
|
10
|
-
testPathIgnorePatterns: ['src/cli/test.ts']
|
|
26
|
+
testPathIgnorePatterns: ['<rootDir>/dist/', '<rootDir>/src/cli/test.ts'],
|
|
27
|
+
roots: ['<rootDir>'],
|
|
28
|
+
modulePaths: [compilerOptions.baseUrl],
|
|
29
|
+
moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths, {
|
|
30
|
+
prefix: '<rootDir>'
|
|
31
|
+
})
|
|
11
32
|
};
|
|
12
33
|
|
|
13
34
|
export default config;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@quantform/core",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.7",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": "Mateusz Majchrzak",
|
|
6
6
|
"description": "Node.js library for building systematic trading strategies in reactive way.",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"rxjs": "^7.5.6"
|
|
38
38
|
},
|
|
39
39
|
"scripts": {
|
|
40
|
-
"build": "tsc",
|
|
40
|
+
"build": "tsc && tsc-alias",
|
|
41
41
|
"test": "jest"
|
|
42
42
|
}
|
|
43
43
|
}
|
|
@@ -1,16 +1,21 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
import {
|
|
2
|
+
Adapter,
|
|
3
|
+
AdapterFactory,
|
|
4
|
+
AdapterNotFoundError,
|
|
5
|
+
AdapterTimeProvider,
|
|
6
|
+
FeedAsyncCallback
|
|
7
|
+
} from '@lib/adapter';
|
|
8
|
+
import { InstrumentSelector, Ohlc, Order } from '@lib/domain';
|
|
9
|
+
import { log, timestamp } from '@lib/shared';
|
|
10
|
+
import { Cache } from '@lib/storage';
|
|
11
|
+
import { Store } from '@lib/store';
|
|
8
12
|
|
|
9
13
|
/**
|
|
10
14
|
* Manages instances of all adapters provided in session descriptor.
|
|
11
15
|
* Awakes and disposes adapters, routes and executes commands.
|
|
12
16
|
*/
|
|
13
17
|
export class AdapterAggregate {
|
|
18
|
+
private readonly logger = log(AdapterAggregate.name);
|
|
14
19
|
private readonly adapter: Record<string, Adapter> = {};
|
|
15
20
|
|
|
16
21
|
constructor(
|
|
@@ -18,7 +23,7 @@ export class AdapterAggregate {
|
|
|
18
23
|
private readonly timeProvider: AdapterTimeProvider,
|
|
19
24
|
private readonly store: Store,
|
|
20
25
|
private readonly cache: Cache
|
|
21
|
-
) {
|
|
26
|
+
) {}
|
|
22
27
|
|
|
23
28
|
/**
|
|
24
29
|
* Returns adapter by name.
|
|
@@ -29,7 +34,7 @@ export class AdapterAggregate {
|
|
|
29
34
|
const adapter = this.adapter[adapterName];
|
|
30
35
|
|
|
31
36
|
if (!adapter) {
|
|
32
|
-
throw
|
|
37
|
+
throw new AdapterNotFoundError(adapterName);
|
|
33
38
|
}
|
|
34
39
|
|
|
35
40
|
return adapter;
|
|
@@ -46,7 +51,7 @@ export class AdapterAggregate {
|
|
|
46
51
|
await adapter.awake();
|
|
47
52
|
await adapter.account();
|
|
48
53
|
} catch (error) {
|
|
49
|
-
|
|
54
|
+
this.logger.error(`unable to awake for ${adapter.name}`, error);
|
|
50
55
|
}
|
|
51
56
|
|
|
52
57
|
this.adapter[adapter.name] = adapter;
|
|
@@ -61,7 +66,7 @@ export class AdapterAggregate {
|
|
|
61
66
|
try {
|
|
62
67
|
await adapter.dispose();
|
|
63
68
|
} catch (error) {
|
|
64
|
-
|
|
69
|
+
this.logger.error(`unable to dispose for ${adapter.name}`, error);
|
|
65
70
|
}
|
|
66
71
|
}
|
|
67
72
|
}
|
|
@@ -87,7 +92,11 @@ export class AdapterAggregate {
|
|
|
87
92
|
try {
|
|
88
93
|
await this.get(adapterName).subscribe(grouped[adapterName]);
|
|
89
94
|
} catch (error) {
|
|
90
|
-
|
|
95
|
+
this.logger.error(
|
|
96
|
+
`unable to subscribe for ${adapterName}`,
|
|
97
|
+
grouped[adapterName],
|
|
98
|
+
error
|
|
99
|
+
);
|
|
91
100
|
|
|
92
101
|
throw error;
|
|
93
102
|
}
|
|
@@ -101,15 +110,12 @@ export class AdapterAggregate {
|
|
|
101
110
|
async open(order: Order): Promise<void> {
|
|
102
111
|
const { adapterName } = order.instrument.base;
|
|
103
112
|
|
|
104
|
-
|
|
105
|
-
adapterName,
|
|
106
|
-
`opening a new order on ${order.instrument.id} as ${order.id}`
|
|
107
|
-
);
|
|
113
|
+
this.logger.debug(`opening a new order on ${order.instrument.id} as ${order.id}`);
|
|
108
114
|
|
|
109
115
|
try {
|
|
110
116
|
await this.get(adapterName).open(order);
|
|
111
117
|
} catch (error) {
|
|
112
|
-
|
|
118
|
+
this.logger.error(`unable to open a new order for ${adapterName}`, order, error);
|
|
113
119
|
|
|
114
120
|
throw error;
|
|
115
121
|
}
|
|
@@ -121,12 +127,12 @@ export class AdapterAggregate {
|
|
|
121
127
|
cancel(order: Order): Promise<void> {
|
|
122
128
|
const { adapterName } = order.instrument.base;
|
|
123
129
|
|
|
124
|
-
|
|
130
|
+
this.logger.debug(`canceling a ${order.id} order`);
|
|
125
131
|
|
|
126
132
|
try {
|
|
127
133
|
return this.get(adapterName).cancel(order);
|
|
128
134
|
} catch (error) {
|
|
129
|
-
|
|
135
|
+
this.logger.error(`unable to cancel a order for ${adapterName}`, order, error);
|
|
130
136
|
|
|
131
137
|
throw error;
|
|
132
138
|
}
|
|
@@ -144,7 +150,11 @@ export class AdapterAggregate {
|
|
|
144
150
|
try {
|
|
145
151
|
return this.get(instrument.base.adapterName).history(instrument, timeframe, length);
|
|
146
152
|
} catch (error) {
|
|
147
|
-
|
|
153
|
+
this.logger.error(
|
|
154
|
+
`unable to get history ${instrument.base.adapterName}`,
|
|
155
|
+
{ instrument, timeframe, length },
|
|
156
|
+
error
|
|
157
|
+
);
|
|
148
158
|
|
|
149
159
|
throw error;
|
|
150
160
|
}
|
|
@@ -163,7 +173,11 @@ export class AdapterAggregate {
|
|
|
163
173
|
try {
|
|
164
174
|
return this.get(instrument.base.adapterName).feed(instrument, from, to, callback);
|
|
165
175
|
} catch (error) {
|
|
166
|
-
|
|
176
|
+
this.logger.error(
|
|
177
|
+
`unable to get feed ${instrument.base.adapterName}`,
|
|
178
|
+
{ instrument, from, to },
|
|
179
|
+
error
|
|
180
|
+
);
|
|
167
181
|
|
|
168
182
|
throw error;
|
|
169
183
|
}
|
package/src/adapter/adapter.ts
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { PaperEngine } from './paper/engine/paper-engine';
|
|
1
|
+
import { PaperAdapter, PaperEngine } from '@lib/adapter';
|
|
2
|
+
import { InstrumentSelector, Ohlc, Order } from '@lib/domain';
|
|
3
|
+
import { now, timestamp } from '@lib/shared';
|
|
4
|
+
import { Cache, StorageEvent } from '@lib/storage';
|
|
5
|
+
import { Store } from '@lib/store';
|
|
7
6
|
|
|
8
7
|
export type AdapterTimeProvider = {
|
|
9
8
|
timestamp: () => number;
|
|
@@ -32,7 +31,7 @@ export abstract class Adapter {
|
|
|
32
31
|
return this.timeProvider.timestamp();
|
|
33
32
|
}
|
|
34
33
|
|
|
35
|
-
constructor(private readonly timeProvider: AdapterTimeProvider) {
|
|
34
|
+
constructor(private readonly timeProvider: AdapterTimeProvider) {}
|
|
36
35
|
|
|
37
36
|
/**
|
|
38
37
|
* Setup an adapter.
|
|
@@ -1,11 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
import {
|
|
2
|
+
Adapter,
|
|
3
|
+
AdapterFactory,
|
|
4
|
+
BacktesterStreamer,
|
|
5
|
+
FeedAsyncCallback,
|
|
6
|
+
PaperAdapter,
|
|
7
|
+
PaperEngine,
|
|
8
|
+
PaperOptions
|
|
9
|
+
} from '@lib/adapter';
|
|
10
|
+
import { InstrumentSelector, Ohlc, Order } from '@lib/domain';
|
|
11
|
+
import { timestamp } from '@lib/shared';
|
|
12
|
+
import { InstrumentSubscriptionEvent, Store } from '@lib/store';
|
|
9
13
|
|
|
10
14
|
export interface BacktesterOptions extends PaperOptions {
|
|
11
15
|
from: timestamp;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
1
|
+
import { BacktesterCursor } from '@lib/adapter';
|
|
2
|
+
import { instrumentOf } from '@lib/domain';
|
|
3
|
+
import { d } from '@lib/shared';
|
|
4
|
+
import { Feed, InMemoryStorage } from '@lib/storage';
|
|
5
|
+
import { TradePatchEvent } from '@lib/store';
|
|
6
6
|
|
|
7
|
-
describe(
|
|
7
|
+
describe(BacktesterCursor.name, () => {
|
|
8
8
|
test('should repeat specific events', async () => {
|
|
9
9
|
const instrument = instrumentOf('binance:btc-usdt');
|
|
10
10
|
const feed = new Feed(new InMemoryStorage());
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import { BacktestPageNotEmpty } from '@lib/adapter';
|
|
2
|
+
import { InstrumentSelector } from '@lib/domain';
|
|
3
|
+
import { timestamp } from '@lib/shared';
|
|
4
|
+
import { Feed, StorageEvent } from '@lib/storage';
|
|
5
5
|
|
|
6
6
|
export class BacktesterCursor {
|
|
7
7
|
private page = new Array<StorageEvent>();
|
|
@@ -32,7 +32,7 @@ export class BacktesterCursor {
|
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
if (this.size > 0) {
|
|
35
|
-
throw
|
|
35
|
+
throw new BacktestPageNotEmpty();
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
this.pageIndex = 0;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
1
|
+
import { BacktesterStreamer } from '@lib/adapter';
|
|
2
|
+
import { Asset, Commission, Instrument } from '@lib/domain';
|
|
3
|
+
import { d } from '@lib/shared';
|
|
4
|
+
import { Feed, InMemoryStorage } from '@lib/storage';
|
|
5
|
+
import { Store, TradePatchEvent } from '@lib/store';
|
|
6
6
|
|
|
7
|
-
describe(
|
|
7
|
+
describe(BacktesterStreamer.name, () => {
|
|
8
8
|
const instrument = new Instrument(
|
|
9
9
|
0,
|
|
10
10
|
new Asset('btc', 'binance', 8),
|
|
@@ -1,10 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
AdapterTimeProvider,
|
|
3
|
+
BacktesterCursor,
|
|
4
|
+
InvalidEventSequenceError,
|
|
5
|
+
MissingPeriodParametersError
|
|
6
|
+
} from '@lib/adapter';
|
|
7
|
+
import { InstrumentSelector } from '@lib/domain';
|
|
8
|
+
import { timestamp } from '@lib/shared';
|
|
9
|
+
import { Feed } from '@lib/storage';
|
|
10
|
+
import { Store } from '@lib/store';
|
|
8
11
|
|
|
9
12
|
/**
|
|
10
13
|
* Listen to backtest session events.
|
|
@@ -41,7 +44,7 @@ export class BacktesterStreamer {
|
|
|
41
44
|
private readonly listener?: BacktesterListener
|
|
42
45
|
) {
|
|
43
46
|
if (period.from == undefined || period.to == undefined) {
|
|
44
|
-
throw
|
|
47
|
+
throw new MissingPeriodParametersError();
|
|
45
48
|
}
|
|
46
49
|
|
|
47
50
|
this.timestamp = period.from;
|
|
@@ -131,7 +134,7 @@ export class BacktesterStreamer {
|
|
|
131
134
|
this.store.dispatch(event);
|
|
132
135
|
|
|
133
136
|
if (cursor.dequeue().timestamp != event.timestamp) {
|
|
134
|
-
throw
|
|
137
|
+
throw new InvalidEventSequenceError();
|
|
135
138
|
}
|
|
136
139
|
|
|
137
140
|
return true;
|