@quantform/core 0.6.6 → 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
package/src/domain/balance.ts
CHANGED
|
@@ -1,24 +1,27 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
import { Asset, Component, Position, PositionMode } from '@lib/domain';
|
|
2
|
+
import { d, decimal, hash } from '@lib/shared';
|
|
3
|
+
|
|
4
|
+
export interface Fundable {
|
|
5
|
+
id: string;
|
|
6
|
+
getFundingAmount(balance: Balance): decimal;
|
|
7
|
+
}
|
|
6
8
|
|
|
7
9
|
/**
|
|
8
10
|
* Represents single asset balance in your wallet.
|
|
9
11
|
*/
|
|
10
12
|
export class Balance implements Component {
|
|
13
|
+
static type = hash(Balance.name);
|
|
14
|
+
readonly type = Balance.type;
|
|
15
|
+
|
|
11
16
|
id: string;
|
|
12
17
|
|
|
13
|
-
private
|
|
14
|
-
private available = d.Zero;
|
|
15
|
-
private unavailable = d.Zero;
|
|
18
|
+
private transientFunding: Record<string, Fundable> = {};
|
|
16
19
|
|
|
17
20
|
/**
|
|
18
21
|
* Returns available amount to trade.
|
|
19
22
|
*/
|
|
20
23
|
get free(): decimal {
|
|
21
|
-
return this.
|
|
24
|
+
return this.available.add(this.getEstimatedUnrealizedPnL('CROSS'));
|
|
22
25
|
}
|
|
23
26
|
|
|
24
27
|
/**
|
|
@@ -33,9 +36,7 @@ export class Balance implements Component {
|
|
|
33
36
|
* Represents a sum of free, locked and opened positions.
|
|
34
37
|
*/
|
|
35
38
|
get total(): decimal {
|
|
36
|
-
return this.
|
|
37
|
-
.floor(this.available.add(this.unavailable))
|
|
38
|
-
.add(this.getEstimatedUnrealizedPnL());
|
|
39
|
+
return this.available.plus(this.unavailable).plus(this.getEstimatedUnrealizedPnL());
|
|
39
40
|
}
|
|
40
41
|
|
|
41
42
|
/**
|
|
@@ -43,61 +44,15 @@ export class Balance implements Component {
|
|
|
43
44
|
*/
|
|
44
45
|
readonly position: Record<string, Position> = {};
|
|
45
46
|
|
|
46
|
-
constructor(
|
|
47
|
+
constructor(
|
|
48
|
+
public timestamp: number,
|
|
49
|
+
public readonly asset: Asset,
|
|
50
|
+
public available: decimal = d.Zero,
|
|
51
|
+
public unavailable: decimal = d.Zero
|
|
52
|
+
) {
|
|
47
53
|
this.id = asset.id;
|
|
48
54
|
}
|
|
49
55
|
|
|
50
|
-
account(amount: decimal) {
|
|
51
|
-
if (this.available.add(amount).lessThan(0)) {
|
|
52
|
-
throw insufficientFundsError(this.id, amount, this.available);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
this.available = this.available.add(amount);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
set(free: decimal, locked: decimal) {
|
|
59
|
-
this.available = free;
|
|
60
|
-
this.unavailable = locked;
|
|
61
|
-
this.locker = {};
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Lock specific amount of asset.
|
|
66
|
-
* If you place new pending order, you will lock your balance to fund order.
|
|
67
|
-
*/
|
|
68
|
-
lock(id: string, amount: decimal) {
|
|
69
|
-
if (this.available.lessThan(amount)) {
|
|
70
|
-
throw insufficientFundsError(this.id, amount, this.available);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
if (this.locker[id]) {
|
|
74
|
-
throw invalidArgumentError(id);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
this.locker[id] = amount;
|
|
78
|
-
this.available = this.available.minus(amount);
|
|
79
|
-
this.unavailable = this.unavailable.plus(amount);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
tryUnlock(id: string): boolean {
|
|
83
|
-
if (!this.locker[id]) {
|
|
84
|
-
return false;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
const amount = this.locker[id];
|
|
88
|
-
|
|
89
|
-
delete this.locker[id];
|
|
90
|
-
|
|
91
|
-
if (this.unavailable < amount) {
|
|
92
|
-
throw insufficientFundsError(this.id, amount, this.unavailable);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
this.available = this.available.add(amount);
|
|
96
|
-
this.unavailable = this.unavailable.minus(amount);
|
|
97
|
-
|
|
98
|
-
return true;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
56
|
/**
|
|
102
57
|
* Returns unrealized profit and loss for all positions backed by this balance.
|
|
103
58
|
*/
|
|
@@ -120,4 +75,36 @@ export class Balance implements Component {
|
|
|
120
75
|
d.Zero
|
|
121
76
|
);
|
|
122
77
|
}
|
|
78
|
+
|
|
79
|
+
tryAddTransientFunding(fundable: Fundable) {
|
|
80
|
+
if (fundable.id in this.transientFunding) {
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
this.transientFunding[fundable.id] = fundable;
|
|
85
|
+
|
|
86
|
+
const funding = fundable.getFundingAmount(this);
|
|
87
|
+
|
|
88
|
+
this.available = this.available.minus(funding);
|
|
89
|
+
this.unavailable = this.unavailable.plus(funding);
|
|
90
|
+
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
tryRemoveTransientFunding(fundable: Fundable) {
|
|
95
|
+
if (!(fundable.id in this.transientFunding)) {
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const funding = fundable.getFundingAmount(this);
|
|
100
|
+
|
|
101
|
+
this.available = this.available.plus(funding);
|
|
102
|
+
this.unavailable = this.unavailable.minus(funding);
|
|
103
|
+
|
|
104
|
+
return true;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
clearTransientFunding() {
|
|
108
|
+
this.transientFunding = {};
|
|
109
|
+
}
|
|
123
110
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { Commission, commissionPercentOf } from '@lib/domain';
|
|
2
|
+
import { d } from '@lib/shared';
|
|
3
3
|
|
|
4
|
-
describe(
|
|
4
|
+
describe(Commission.name, () => {
|
|
5
5
|
test('should construct a Commission', () => {
|
|
6
6
|
const sut = commissionPercentOf({
|
|
7
7
|
maker: d(0.1),
|
package/src/domain/commission.ts
CHANGED
package/src/domain/component.ts
CHANGED
package/src/domain/error.ts
CHANGED
|
@@ -1,27 +1,32 @@
|
|
|
1
|
-
import { decimal } from '
|
|
1
|
+
import { decimal } from '@lib/shared';
|
|
2
2
|
|
|
3
|
-
export
|
|
4
|
-
assetName: string,
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
)
|
|
8
|
-
|
|
9
|
-
`insufficient funds of ${assetName} has: ${availableAmount.toString()} requires: ${requiredAmount.toString()}`
|
|
10
|
-
);
|
|
3
|
+
export class InsufficientFundsError extends Error {
|
|
4
|
+
constructor(assetName: string, requiredAmount: decimal, availableAmount: decimal) {
|
|
5
|
+
super(
|
|
6
|
+
`insufficient funds of ${assetName} has: ${availableAmount.toString()} requires: ${requiredAmount.toString()}`
|
|
7
|
+
);
|
|
8
|
+
}
|
|
11
9
|
}
|
|
12
10
|
|
|
13
|
-
export
|
|
14
|
-
|
|
11
|
+
export class InvalidArgumentsError extends Error {
|
|
12
|
+
constructor(argName: Record<any, unknown>) {
|
|
13
|
+
super(`invalid arguments: ${argName}`);
|
|
14
|
+
}
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
export
|
|
18
|
-
|
|
17
|
+
export class InvalidAssetSelectorError extends Error {
|
|
18
|
+
constructor(selector: string) {
|
|
19
|
+
super(`invalid asset selector: ${selector}`);
|
|
20
|
+
}
|
|
19
21
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
22
|
+
export class InvalidInstrumentSelectorError extends Error {
|
|
23
|
+
constructor(selector: string) {
|
|
24
|
+
super(`invalid instrument selector: ${selector}`);
|
|
25
|
+
}
|
|
23
26
|
}
|
|
24
27
|
|
|
25
|
-
export
|
|
26
|
-
|
|
28
|
+
export class AdapterMismatchError extends Error {
|
|
29
|
+
constructor() {
|
|
30
|
+
super('adapters must be the same');
|
|
31
|
+
}
|
|
27
32
|
}
|
package/src/domain/index.ts
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
export * from '
|
|
2
|
-
export * from '
|
|
3
|
-
export * from '
|
|
4
|
-
export * from '
|
|
5
|
-
export * from '
|
|
6
|
-
export * from '
|
|
7
|
-
export * from '
|
|
8
|
-
export * from '
|
|
9
|
-
export * from '
|
|
10
|
-
export * from '
|
|
11
|
-
export * from '
|
|
12
|
-
export * from '
|
|
13
|
-
export * from '
|
|
14
|
-
export * from '
|
|
15
|
-
export * from '
|
|
16
|
-
export * from '
|
|
17
|
-
export * from '
|
|
18
|
-
export * from '
|
|
19
|
-
export * from '
|
|
20
|
-
export * from '
|
|
21
|
-
export * from '
|
|
1
|
+
export * from '@lib/domain/asset';
|
|
2
|
+
export * from '@lib/domain/balance';
|
|
3
|
+
export * from '@lib/domain/balance-operator';
|
|
4
|
+
export * from '@lib/domain/error';
|
|
5
|
+
export * from '@lib/domain/ohlc';
|
|
6
|
+
export * from '@lib/domain/ohlc-operator';
|
|
7
|
+
export * from '@lib/domain/commission';
|
|
8
|
+
export * from '@lib/domain/component';
|
|
9
|
+
export * from '@lib/domain/instrument';
|
|
10
|
+
export * from '@lib/domain/instrument-operator';
|
|
11
|
+
export * from '@lib/domain/order';
|
|
12
|
+
export * from '@lib/domain/order-operator';
|
|
13
|
+
export * from '@lib/domain/orderbook';
|
|
14
|
+
export * from '@lib/domain/orderbook-operator';
|
|
15
|
+
export * from '@lib/domain/position';
|
|
16
|
+
export * from '@lib/domain/position-operator';
|
|
17
|
+
export * from '@lib/domain/session';
|
|
18
|
+
export * from '@lib/domain/session-builder';
|
|
19
|
+
export * from '@lib/domain/timeframe';
|
|
20
|
+
export * from '@lib/domain/trade';
|
|
21
|
+
export * from '@lib/domain/trade-operator';
|
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
import { Subject } from 'rxjs';
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
3
|
+
import {
|
|
4
|
+
Asset,
|
|
5
|
+
Commission,
|
|
6
|
+
Component,
|
|
7
|
+
Instrument,
|
|
8
|
+
instrument,
|
|
9
|
+
instrumentOf
|
|
10
|
+
} from '@lib/domain';
|
|
11
|
+
import { State } from '@lib/store';
|
|
9
12
|
|
|
10
|
-
describe(
|
|
13
|
+
describe(instrument.name, () => {
|
|
11
14
|
const state = new State();
|
|
12
15
|
|
|
13
16
|
beforeEach(() => {
|
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
import { distinctUntilChanged, filter, map, Observable, startWith } from 'rxjs';
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { Instrument, InstrumentSelector } from './instrument';
|
|
3
|
+
import { Component, Instrument, InstrumentSelector } from '@lib/domain';
|
|
4
|
+
import { State } from '@lib/store';
|
|
6
5
|
|
|
7
6
|
export function instrument(selector: InstrumentSelector, state: State) {
|
|
8
7
|
return (source$: Observable<Component>) =>
|
|
9
8
|
source$.pipe(
|
|
10
9
|
startWith(state.universe.instrument.get(selector.id)),
|
|
11
|
-
filter(it => it
|
|
12
|
-
map(it => it as Instrument)
|
|
10
|
+
filter(it => it !== undefined && it.type === Instrument.type),
|
|
11
|
+
map(it => it as Instrument),
|
|
12
|
+
filter(it => it.id == selector.id)
|
|
13
13
|
);
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
export function instruments(state: State) {
|
|
17
17
|
return (source$: Observable<Component>) =>
|
|
18
18
|
source$.pipe(
|
|
19
|
-
filter(it => it
|
|
19
|
+
filter(it => it.type === Instrument.type),
|
|
20
20
|
map(() => state.universe.instrument.asReadonlyArray()),
|
|
21
21
|
startWith(state.universe.instrument.asReadonlyArray()),
|
|
22
22
|
filter(it => it.length > 0),
|
|
@@ -1,9 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import {
|
|
2
|
+
Asset,
|
|
3
|
+
assetOf,
|
|
4
|
+
commissionPercentOf,
|
|
5
|
+
Instrument,
|
|
6
|
+
instrumentOf,
|
|
7
|
+
InstrumentSelector
|
|
8
|
+
} from '@lib/domain';
|
|
9
|
+
import { d } from '@lib/shared';
|
|
5
10
|
|
|
6
|
-
describe(
|
|
11
|
+
describe(Instrument.name, () => {
|
|
7
12
|
test('should construct a instrument', () => {
|
|
8
13
|
const sut = new Instrument(
|
|
9
14
|
0,
|
|
@@ -24,7 +29,7 @@ describe('Instrument', () => {
|
|
|
24
29
|
});
|
|
25
30
|
});
|
|
26
31
|
|
|
27
|
-
describe(
|
|
32
|
+
describe(InstrumentSelector.name, () => {
|
|
28
33
|
test('should construct a instrument selector', () => {
|
|
29
34
|
const sut = instrumentOf('xyz:abc-def');
|
|
30
35
|
|
package/src/domain/instrument.ts
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import {
|
|
2
|
+
AdapterMismatchError,
|
|
3
|
+
Asset,
|
|
4
|
+
AssetSelector,
|
|
5
|
+
AssetSelectorSeparator,
|
|
6
|
+
Commission,
|
|
7
|
+
Component,
|
|
8
|
+
InvalidInstrumentSelectorError
|
|
9
|
+
} from '@lib/domain';
|
|
10
|
+
import { hash } from '@lib/shared';
|
|
5
11
|
|
|
6
12
|
export const InstrumentSelectorSeparator = '-';
|
|
7
13
|
|
|
@@ -22,6 +28,9 @@ export class InstrumentSelector {
|
|
|
22
28
|
* Represents trading market which is made up by two trading assets (base and quoted).
|
|
23
29
|
*/
|
|
24
30
|
export class Instrument extends InstrumentSelector implements Component {
|
|
31
|
+
static type = hash(Instrument.name);
|
|
32
|
+
readonly type = Instrument.type;
|
|
33
|
+
|
|
25
34
|
readonly cross: Instrument | undefined;
|
|
26
35
|
leverage: number | undefined = undefined;
|
|
27
36
|
|
|
@@ -35,7 +44,7 @@ export class Instrument extends InstrumentSelector implements Component {
|
|
|
35
44
|
super(base.name, quote.name, base.adapterName);
|
|
36
45
|
|
|
37
46
|
if (base.adapterName != quote.adapterName) {
|
|
38
|
-
throw
|
|
47
|
+
throw new AdapterMismatchError();
|
|
39
48
|
}
|
|
40
49
|
}
|
|
41
50
|
}
|
|
@@ -43,12 +52,12 @@ export class Instrument extends InstrumentSelector implements Component {
|
|
|
43
52
|
export function instrumentOf(selector: string): InstrumentSelector {
|
|
44
53
|
const [adapterName, asset, ...rest] = selector.split(AssetSelectorSeparator);
|
|
45
54
|
if (!adapterName || !asset || rest.length) {
|
|
46
|
-
throw
|
|
55
|
+
throw new InvalidInstrumentSelectorError(selector);
|
|
47
56
|
}
|
|
48
57
|
|
|
49
58
|
const [baseAssetName, quoteAssetName] = asset.split(InstrumentSelectorSeparator);
|
|
50
59
|
if (!baseAssetName || !quoteAssetName) {
|
|
51
|
-
throw
|
|
60
|
+
throw new InvalidInstrumentSelectorError(selector);
|
|
52
61
|
}
|
|
53
62
|
|
|
54
63
|
return new InstrumentSelector(baseAssetName, quoteAssetName, adapterName);
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { from } from 'rxjs';
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { mergeOhlc, ohlc, ohlcCompleted } from './ohlc-operator';
|
|
3
|
+
import { mergeOhlc, Ohlc, ohlc, ohlcCompleted } from '@lib/domain';
|
|
4
|
+
import { d } from '@lib/shared';
|
|
6
5
|
|
|
7
|
-
describe(
|
|
6
|
+
describe(ohlc.name, () => {
|
|
8
7
|
test('should aggregate and pipe ohlc updates', done => {
|
|
9
8
|
const input$ = from([
|
|
10
9
|
{ timestamp: 1, rate: d(1) },
|
|
@@ -35,7 +34,7 @@ describe('ohlc', () => {
|
|
|
35
34
|
});
|
|
36
35
|
});
|
|
37
36
|
|
|
38
|
-
describe(
|
|
37
|
+
describe(ohlcCompleted.name, () => {
|
|
39
38
|
test('should aggregate and pipe distinct completed ohlc', done => {
|
|
40
39
|
const input$ = from([
|
|
41
40
|
{ timestamp: 1, rate: d(1) },
|
|
@@ -60,7 +59,7 @@ describe('ohlcCompleted', () => {
|
|
|
60
59
|
});
|
|
61
60
|
});
|
|
62
61
|
|
|
63
|
-
describe(
|
|
62
|
+
describe(mergeOhlc.name, () => {
|
|
64
63
|
test('should pipe and merge ohlc from history', done => {
|
|
65
64
|
const history$ = from([
|
|
66
65
|
new Ohlc(1, d(1), d(1.5), d(0.5), d(2)),
|
|
@@ -11,9 +11,8 @@ import {
|
|
|
11
11
|
switchMap
|
|
12
12
|
} from 'rxjs';
|
|
13
13
|
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import { tf } from './timeframe';
|
|
14
|
+
import { Ohlc, tf } from '@lib/domain';
|
|
15
|
+
import { decimal } from '@lib/shared';
|
|
17
16
|
|
|
18
17
|
function aggregate(
|
|
19
18
|
candle: Ohlc | undefined,
|
package/src/domain/ohlc.spec.ts
CHANGED
package/src/domain/ohlc.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { decimal, timestamp } from '
|
|
1
|
+
import { decimal, timestamp } from '@lib/shared';
|
|
2
2
|
|
|
3
3
|
export class Ohlc {
|
|
4
4
|
constructor(
|
|
@@ -8,7 +8,7 @@ export class Ohlc {
|
|
|
8
8
|
public low: decimal,
|
|
9
9
|
public close: decimal,
|
|
10
10
|
public volume?: decimal
|
|
11
|
-
) {
|
|
11
|
+
) {}
|
|
12
12
|
|
|
13
13
|
apply(value: decimal) {
|
|
14
14
|
this.high = decimal.max(this.high, value);
|
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
import { BehaviorSubject, map, Subject } from 'rxjs';
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
3
|
+
import {
|
|
4
|
+
Asset,
|
|
5
|
+
Commission,
|
|
6
|
+
Component,
|
|
7
|
+
Instrument,
|
|
8
|
+
Order,
|
|
9
|
+
order,
|
|
10
|
+
orders,
|
|
11
|
+
positions
|
|
12
|
+
} from '@lib/domain';
|
|
13
|
+
import { d } from '@lib/shared';
|
|
14
|
+
import { InnerSet, State } from '@lib/store';
|
|
11
15
|
|
|
12
16
|
const instrument = new Instrument(
|
|
13
17
|
0,
|
|
@@ -17,7 +21,7 @@ const instrument = new Instrument(
|
|
|
17
21
|
Commission.Zero
|
|
18
22
|
);
|
|
19
23
|
|
|
20
|
-
describe(
|
|
24
|
+
describe(order.name, () => {
|
|
21
25
|
test('should pipe an order', done => {
|
|
22
26
|
new BehaviorSubject<Component>(new Order(0, '1', instrument, d(-100), 0))
|
|
23
27
|
.pipe(order(instrument))
|
|
@@ -38,7 +42,7 @@ describe('order', () => {
|
|
|
38
42
|
});
|
|
39
43
|
});
|
|
40
44
|
|
|
41
|
-
describe(
|
|
45
|
+
describe(positions.name, () => {
|
|
42
46
|
let state: State;
|
|
43
47
|
let order1: Order, order2: Order, order3: Order;
|
|
44
48
|
|
|
@@ -1,22 +1,23 @@
|
|
|
1
1
|
import { filter, map, Observable, startWith } from 'rxjs';
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { InstrumentSelector } from './instrument';
|
|
6
|
-
import { Order } from './order';
|
|
3
|
+
import { Component, InstrumentSelector, Order } from '@lib/domain';
|
|
4
|
+
import { State } from '@lib/store';
|
|
7
5
|
|
|
8
6
|
export function order(selector: InstrumentSelector) {
|
|
9
7
|
return (source$: Observable<Component>) =>
|
|
10
8
|
source$.pipe(
|
|
11
|
-
filter(it => it
|
|
12
|
-
map(it => it as Order)
|
|
9
|
+
filter(it => it !== undefined && it.type === Order.type),
|
|
10
|
+
map(it => it as Order),
|
|
11
|
+
filter(it => it.instrument.id === selector.id)
|
|
13
12
|
);
|
|
14
13
|
}
|
|
15
14
|
|
|
16
15
|
export function orders(selector: InstrumentSelector, state: State) {
|
|
17
16
|
return (source$: Observable<Component>) =>
|
|
18
17
|
source$.pipe(
|
|
19
|
-
filter(it => it
|
|
18
|
+
filter(it => it.type === Order.type),
|
|
19
|
+
map(it => it as Order),
|
|
20
|
+
filter(it => it.instrument.id === selector.id),
|
|
20
21
|
map(() => state.order.get(selector.id)?.asReadonlyArray() ?? []),
|
|
21
22
|
startWith(state.order.get(selector.id)?.asReadonlyArray() ?? [])
|
|
22
23
|
);
|
package/src/domain/order.spec.ts
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { Commission } from './commission';
|
|
4
|
-
import { Instrument } from './instrument';
|
|
5
|
-
import { Order } from './order';
|
|
1
|
+
import { Asset, Commission, Instrument, Order } from '@lib/domain';
|
|
2
|
+
import { d } from '@lib/shared';
|
|
6
3
|
|
|
7
|
-
describe(
|
|
4
|
+
describe(Order.name, () => {
|
|
8
5
|
const instrument = new Instrument(
|
|
9
6
|
0,
|
|
10
7
|
new Asset('abc', 'xyz', 4),
|
package/src/domain/order.ts
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
import {
|
|
2
|
+
Balance,
|
|
3
|
+
Component,
|
|
4
|
+
Fundable,
|
|
5
|
+
Instrument,
|
|
6
|
+
InvalidArgumentsError
|
|
7
|
+
} from '@lib/domain';
|
|
8
|
+
import { d, decimal, hash } from '@lib/shared';
|
|
6
9
|
|
|
7
10
|
export type OrderState =
|
|
8
11
|
| 'NEW'
|
|
@@ -12,7 +15,10 @@ export type OrderState =
|
|
|
12
15
|
| 'CANCELED'
|
|
13
16
|
| 'REJECTED';
|
|
14
17
|
|
|
15
|
-
export class Order implements Component {
|
|
18
|
+
export class Order implements Fundable, Component {
|
|
19
|
+
static type = hash(Order.name);
|
|
20
|
+
readonly type = Order.type;
|
|
21
|
+
|
|
16
22
|
state: OrderState = 'NEW';
|
|
17
23
|
quantityExecuted = d.Zero;
|
|
18
24
|
averageExecutionRate?: decimal;
|
|
@@ -28,41 +34,32 @@ export class Order implements Component {
|
|
|
28
34
|
readonly stopRate?: decimal
|
|
29
35
|
) {
|
|
30
36
|
if (!quantity || Number.isNaN(quantity)) {
|
|
31
|
-
throw
|
|
37
|
+
throw new InvalidArgumentsError({ quantity });
|
|
32
38
|
}
|
|
33
39
|
|
|
34
40
|
if (rate && rate.lessThanOrEqualTo(0)) {
|
|
35
|
-
throw
|
|
41
|
+
throw new InvalidArgumentsError({ rate });
|
|
36
42
|
}
|
|
37
43
|
}
|
|
38
44
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
quote: Balance
|
|
42
|
-
): { base?: decimal; quote?: decimal } {
|
|
43
|
-
const qty = this.quantity.abs();
|
|
45
|
+
getFundingAmount(balance: Balance): decimal {
|
|
46
|
+
const quantityLeft = this.quantity.abs().minus(this.quantityExecuted);
|
|
44
47
|
|
|
45
|
-
if (
|
|
48
|
+
if (
|
|
49
|
+
this.instrument.quote.id === balance.asset.id &&
|
|
50
|
+
this.quantity.greaterThan(d.Zero)
|
|
51
|
+
) {
|
|
46
52
|
if (this.rate) {
|
|
47
|
-
return
|
|
48
|
-
base: d.Zero,
|
|
49
|
-
quote: quote.asset.ceil(this.rate.mul(qty))
|
|
50
|
-
};
|
|
51
|
-
} else {
|
|
52
|
-
return {
|
|
53
|
-
base: d.Zero,
|
|
54
|
-
quote: quote.free
|
|
55
|
-
};
|
|
53
|
+
return quantityLeft.mul(this.rate).abs();
|
|
56
54
|
}
|
|
55
|
+
|
|
56
|
+
return balance.free;
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
if (this.quantity.lessThan(
|
|
60
|
-
return
|
|
61
|
-
base: qty,
|
|
62
|
-
quote: d.Zero
|
|
63
|
-
};
|
|
59
|
+
if (this.instrument.base.id === balance.asset.id && this.quantity.lessThan(d.Zero)) {
|
|
60
|
+
return quantityLeft;
|
|
64
61
|
}
|
|
65
62
|
|
|
66
|
-
return
|
|
63
|
+
return d.Zero;
|
|
67
64
|
}
|
|
68
65
|
}
|