@quantform/core 0.4.11 → 0.5.13
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 +4 -2
- package/dist/adapter/adapter-aggregate.js +4 -3
- package/dist/adapter/adapter-aggregate.js.map +1 -1
- package/dist/adapter/adapter.d.ts +3 -2
- package/dist/adapter/adapter.js +5 -2
- package/dist/adapter/adapter.js.map +1 -1
- package/dist/adapter/backtester/backtester-adapter.d.ts +1 -1
- package/dist/adapter/backtester/backtester-adapter.js +2 -1
- package/dist/adapter/backtester/backtester-adapter.js.map +1 -1
- package/dist/adapter/backtester/index.js +5 -1
- package/dist/adapter/backtester/index.js.map +1 -1
- package/dist/adapter/index.js +5 -1
- package/dist/adapter/index.js.map +1 -1
- package/dist/adapter/paper/index.js +5 -1
- package/dist/adapter/paper/index.js.map +1 -1
- package/dist/adapter/paper/paper-adapter.d.ts +1 -1
- package/dist/adapter/paper/paper-adapter.js +1 -1
- package/dist/adapter/paper/paper-adapter.js.map +1 -1
- package/dist/adapter/paper/paper-adapter.spec.js +5 -3
- package/dist/adapter/paper/paper-adapter.spec.js.map +1 -1
- package/dist/adapter/paper/simulator/paper-margin-simulator.d.ts +1 -1
- package/dist/adapter/paper/simulator/paper-margin-simulator.js.map +1 -1
- package/dist/adapter/paper/simulator/paper-simulator.d.ts +1 -1
- package/dist/adapter/paper/simulator/paper-simulator.js.map +1 -1
- package/dist/adapter/paper/simulator/paper-spot-simulator.d.ts +1 -1
- package/dist/adapter/paper/simulator/paper-spot-simulator.js +1 -1
- package/dist/adapter/paper/simulator/paper-spot-simulator.js.map +1 -1
- package/dist/bootstrap.js +31 -15
- package/dist/bootstrap.js.map +1 -1
- package/dist/cli/build.d.ts +1 -0
- package/dist/cli/build.js +16 -0
- package/dist/cli/build.js.map +1 -0
- package/dist/cli/dev.d.ts +1 -0
- package/dist/cli/dev.js +17 -0
- package/dist/cli/dev.js.map +1 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +72 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/internal/workspace.d.ts +8 -0
- package/dist/cli/internal/workspace.js +14 -0
- package/dist/cli/internal/workspace.js.map +1 -0
- package/dist/cli/pull.d.ts +1 -0
- package/dist/cli/pull.js +50 -0
- package/dist/cli/pull.js.map +1 -0
- package/dist/cli/run.d.ts +1 -0
- package/dist/cli/run.js +19 -0
- package/dist/cli/run.js.map +1 -0
- package/dist/cli/test.d.ts +1 -0
- package/dist/cli/test.js +37 -0
- package/dist/cli/test.js.map +1 -0
- package/dist/domain/balance.d.ts +4 -3
- package/dist/domain/balance.js +20 -19
- package/dist/domain/balance.js.map +1 -1
- package/dist/domain/balance.spec.js +2 -2
- package/dist/domain/balance.spec.js.map +1 -1
- package/dist/domain/candle.d.ts +4 -2
- package/dist/domain/candle.js +13 -9
- package/dist/domain/candle.js.map +1 -1
- package/dist/domain/candle.spec.js.map +1 -1
- package/dist/domain/component.d.ts +1 -0
- package/dist/domain/index.js +5 -1
- package/dist/domain/index.js.map +1 -1
- package/dist/domain/instrument.d.ts +1 -0
- package/dist/domain/instrument.js +1 -0
- package/dist/domain/instrument.js.map +1 -1
- package/dist/domain/order.d.ts +3 -2
- package/dist/domain/order.js +2 -0
- package/dist/domain/order.js.map +1 -1
- package/dist/domain/orderbook.d.ts +1 -0
- package/dist/domain/orderbook.js +1 -0
- package/dist/domain/orderbook.js.map +1 -1
- package/dist/domain/position.d.ts +1 -0
- package/dist/domain/position.js +1 -0
- package/dist/domain/position.js.map +1 -1
- package/dist/domain/session.d.ts +4 -18
- package/dist/domain/session.js +7 -23
- package/dist/domain/session.js.map +1 -1
- package/dist/domain/statement.js +11 -11
- package/dist/domain/statement.js.map +1 -1
- package/dist/domain/trade.d.ts +2 -1
- package/dist/domain/trade.js +1 -0
- package/dist/domain/trade.js.map +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js +5 -2
- package/dist/index.js.map +1 -1
- package/dist/indicator/atr.js.map +1 -1
- package/dist/indicator/cross.spec.js.map +1 -1
- package/dist/indicator/donchian.js.map +1 -1
- package/dist/indicator/ema.js.map +1 -1
- package/dist/indicator/ema.spec.js.map +1 -1
- package/dist/indicator/envelope.js.map +1 -1
- package/dist/indicator/index.js +5 -1
- package/dist/indicator/index.js.map +1 -1
- package/dist/indicator/macd.js.map +1 -1
- package/dist/indicator/min-max.js.map +1 -1
- package/dist/indicator/rma.js.map +1 -1
- package/dist/indicator/sma.js.map +1 -1
- package/dist/indicator/sma.spec.js.map +1 -1
- package/dist/indicator/swma.js.map +1 -1
- package/dist/indicator/tma.js.map +1 -1
- package/dist/indicator/tma.spec.js.map +1 -1
- package/dist/indicator/trailing.spec.js.map +1 -1
- package/dist/indicator/truerange.js.map +1 -1
- package/dist/indicator/truerange.spec.js.map +1 -1
- package/dist/indicator/window.js.map +1 -1
- package/dist/indicator/wma.js.map +1 -1
- package/dist/indicator/wma.spec.js.map +1 -1
- package/dist/shared/index.d.ts +0 -2
- package/dist/shared/index.js +5 -3
- package/dist/shared/index.js.map +1 -1
- package/dist/shared/policy.spec.js +2 -6
- package/dist/shared/policy.spec.js.map +1 -1
- package/dist/storage/cache.d.ts +9 -0
- package/dist/storage/cache.js +32 -0
- package/dist/storage/cache.js.map +1 -0
- package/dist/storage/index.d.ts +1 -0
- package/dist/storage/index.js +6 -1
- package/dist/storage/index.js.map +1 -1
- package/dist/storage/storage.d.ts +7 -0
- package/dist/storage/storage.js +11 -1
- package/dist/storage/storage.js.map +1 -1
- package/dist/store/event/index.js +5 -1
- package/dist/store/event/index.js.map +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 +1 -1
- package/dist/store/event/store-candle.event.js.map +1 -1
- package/dist/store/event/store-candle.event.spec.js +1 -1
- package/dist/store/event/store-candle.event.spec.js.map +1 -1
- package/dist/store/event/store-instrument.event.spec.js +1 -1
- package/dist/store/event/store-instrument.event.spec.js.map +1 -1
- package/dist/store/event/store-trade.event.spec.js +2 -2
- package/dist/store/event/store-trade.event.spec.js.map +1 -1
- package/dist/store/index.js +5 -1
- package/dist/store/index.js.map +1 -1
- package/dist/store/store.js.map +1 -1
- package/dist/tests/backtester-adapter.spec.js +2 -1
- package/dist/tests/backtester-adapter.spec.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +24 -16
- package/src/adapter/adapter-aggregate.ts +8 -3
- package/src/adapter/adapter.ts +9 -3
- package/src/adapter/backtester/backtester-adapter.ts +3 -1
- package/src/adapter/paper/paper-adapter.spec.ts +5 -3
- package/src/adapter/paper/paper-adapter.ts +1 -1
- package/src/adapter/paper/simulator/paper-margin-simulator.ts +1 -1
- package/src/adapter/paper/simulator/paper-simulator.ts +2 -1
- package/src/adapter/paper/simulator/paper-spot-simulator.ts +2 -2
- package/src/bootstrap.ts +47 -18
- package/src/cli/build.ts +15 -0
- package/src/cli/dev.ts +18 -0
- package/src/cli/index.ts +81 -0
- package/src/cli/internal/workspace.ts +18 -0
- package/src/cli/pull.ts +67 -0
- package/src/cli/run.ts +22 -0
- package/src/cli/test.ts +50 -0
- package/src/domain/balance.spec.ts +2 -2
- package/src/domain/balance.ts +20 -19
- package/src/domain/candle.spec.ts +1 -0
- package/src/domain/candle.ts +20 -10
- package/src/domain/component.ts +1 -0
- package/src/domain/instrument.ts +1 -0
- package/src/domain/order.ts +3 -1
- package/src/domain/orderbook.ts +1 -0
- package/src/domain/position.ts +2 -0
- package/src/domain/session.ts +17 -67
- package/src/domain/statement.ts +13 -12
- package/src/domain/trade.ts +2 -1
- package/src/index.ts +0 -1
- package/src/indicator/atr.ts +1 -0
- package/src/indicator/cross.spec.ts +1 -0
- package/src/indicator/donchian.ts +1 -0
- package/src/indicator/ema.spec.ts +1 -0
- package/src/indicator/ema.ts +1 -0
- package/src/indicator/envelope.ts +1 -0
- package/src/indicator/macd.ts +1 -0
- package/src/indicator/min-max.ts +1 -0
- package/src/indicator/rma.ts +1 -0
- package/src/indicator/sma.spec.ts +1 -0
- package/src/indicator/sma.ts +1 -0
- package/src/indicator/swma.ts +1 -0
- package/src/indicator/tma.spec.ts +1 -0
- package/src/indicator/tma.ts +1 -0
- package/src/indicator/trailing.spec.ts +1 -0
- package/src/indicator/truerange.spec.ts +1 -0
- package/src/indicator/truerange.ts +1 -0
- package/src/indicator/window.ts +1 -0
- package/src/indicator/wma.spec.ts +1 -0
- package/src/indicator/wma.ts +1 -0
- package/src/shared/index.ts +0 -2
- package/src/shared/policy.spec.ts +2 -6
- package/src/storage/cache.ts +35 -0
- package/src/storage/index.ts +1 -0
- package/src/storage/storage.ts +15 -0
- package/src/store/event/store-balance.event.spec.ts +3 -3
- package/src/store/event/store-candle.event.spec.ts +1 -1
- package/src/store/event/store-candle.event.ts +2 -2
- package/src/store/event/store-instrument.event.spec.ts +1 -1
- package/src/store/event/store-trade.event.spec.ts +2 -2
- package/src/store/store.ts +1 -0
- package/src/tests/backtester-adapter.spec.ts +3 -2
- package/tsconfig.json +2 -2
- package/dist/ipc.d.ts +0 -33
- package/dist/ipc.js +0 -244
- package/dist/ipc.js.map +0 -1
- package/dist/ipc.spec.d.ts +0 -1
- package/dist/ipc.spec.js +0 -57
- package/dist/ipc.spec.js.map +0 -1
- package/dist/shared/task.d.ts +0 -6
- package/dist/shared/task.js +0 -25
- package/dist/shared/task.js.map +0 -1
- package/dist/shared/worker.d.ts +0 -10
- package/dist/shared/worker.js +0 -46
- package/dist/shared/worker.js.map +0 -1
- package/dist/shared/worker.spec.d.ts +0 -1
- package/dist/shared/worker.spec.js +0 -18
- package/dist/shared/worker.spec.js.map +0 -1
- package/src/ipc.spec.ts +0 -73
- package/src/ipc.ts +0 -321
- package/src/shared/task.ts +0 -30
- package/src/shared/worker.spec.ts +0 -25
- package/src/shared/worker.ts +0 -55
package/src/domain/candle.ts
CHANGED
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
skipLast,
|
|
10
10
|
withLatestFrom
|
|
11
11
|
} from 'rxjs';
|
|
12
|
+
|
|
12
13
|
import { timestamp } from '../shared';
|
|
13
14
|
import { tf } from './timeframe';
|
|
14
15
|
|
|
@@ -29,10 +30,10 @@ export class Candle {
|
|
|
29
30
|
}
|
|
30
31
|
|
|
31
32
|
export class CandleBuilder {
|
|
32
|
-
private
|
|
33
|
+
private current: Candle;
|
|
33
34
|
|
|
34
35
|
get candle(): Candle {
|
|
35
|
-
return this.
|
|
36
|
+
return this.current;
|
|
36
37
|
}
|
|
37
38
|
|
|
38
39
|
constructor(readonly timeframe: number) {}
|
|
@@ -40,8 +41,8 @@ export class CandleBuilder {
|
|
|
40
41
|
append(value: number, timestamp: timestamp): Candle {
|
|
41
42
|
const frame = tf(timestamp, this.timeframe);
|
|
42
43
|
|
|
43
|
-
if (!this.
|
|
44
|
-
this.
|
|
44
|
+
if (!this.current) {
|
|
45
|
+
this.current = new Candle(frame, value, value, value, value);
|
|
45
46
|
|
|
46
47
|
return null;
|
|
47
48
|
}
|
|
@@ -52,25 +53,34 @@ export class CandleBuilder {
|
|
|
52
53
|
return null;
|
|
53
54
|
}
|
|
54
55
|
|
|
55
|
-
const previous = this.
|
|
56
|
+
const previous = this.current;
|
|
56
57
|
|
|
57
|
-
this.
|
|
58
|
+
this.current = new Candle(frame, value, value, value, value);
|
|
58
59
|
return previous;
|
|
59
60
|
}
|
|
60
61
|
}
|
|
61
62
|
|
|
62
63
|
export function candle<T extends { timestamp: number }>(
|
|
63
64
|
timeframe: number,
|
|
64
|
-
fn: (x: T) => number
|
|
65
|
+
fn: (x: T) => number,
|
|
66
|
+
options: { passThru: boolean } = { passThru: false }
|
|
65
67
|
) {
|
|
66
68
|
return function (source: Observable<T>): Observable<Candle> {
|
|
67
69
|
const builder = new CandleBuilder(timeframe);
|
|
68
70
|
let candle: Candle;
|
|
69
71
|
|
|
72
|
+
if (options.passThru) {
|
|
73
|
+
return source.pipe(
|
|
74
|
+
map(it => {
|
|
75
|
+
builder.append(fn(it), it.timestamp);
|
|
76
|
+
return builder.candle;
|
|
77
|
+
}),
|
|
78
|
+
share()
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
70
82
|
return source.pipe(
|
|
71
|
-
filter(it =>
|
|
72
|
-
return (candle = builder.append(fn(it), it.timestamp)) != null;
|
|
73
|
-
}),
|
|
83
|
+
filter(it => (candle = builder.append(fn(it), it.timestamp)) != null),
|
|
74
84
|
map(_ => candle),
|
|
75
85
|
share()
|
|
76
86
|
);
|
package/src/domain/component.ts
CHANGED
package/src/domain/instrument.ts
CHANGED
|
@@ -25,6 +25,7 @@ export class InstrumentSelector {
|
|
|
25
25
|
* Represents trading market which is made up by two trading assets (base and quoted).
|
|
26
26
|
*/
|
|
27
27
|
export class Instrument extends InstrumentSelector implements Component {
|
|
28
|
+
kind = 'instrument';
|
|
28
29
|
timestamp: timestamp;
|
|
29
30
|
commission: Commission;
|
|
30
31
|
cross: Instrument;
|
package/src/domain/order.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { v4 } from 'uuid';
|
|
2
|
+
|
|
2
3
|
import { timestamp } from '../shared';
|
|
3
4
|
import { Component } from './component';
|
|
4
5
|
import { InstrumentSelector } from './instrument';
|
|
@@ -14,12 +15,13 @@ export type OrderState =
|
|
|
14
15
|
| 'REJECTED';
|
|
15
16
|
|
|
16
17
|
export class Order implements Component {
|
|
18
|
+
kind = 'order';
|
|
17
19
|
timestamp: timestamp;
|
|
18
20
|
id = v4();
|
|
19
21
|
externalId: string;
|
|
20
22
|
state: OrderState = 'NEW';
|
|
21
23
|
|
|
22
|
-
quantityExecuted
|
|
24
|
+
quantityExecuted = 0;
|
|
23
25
|
averageExecutionRate: number;
|
|
24
26
|
createdAt: timestamp;
|
|
25
27
|
comment: string;
|
package/src/domain/orderbook.ts
CHANGED
|
@@ -6,6 +6,7 @@ import { Component } from './component';
|
|
|
6
6
|
* Provides an access to pending buy and sell orders on the specific market.
|
|
7
7
|
*/
|
|
8
8
|
export class Orderbook implements Component {
|
|
9
|
+
kind = 'orderbook';
|
|
9
10
|
timestamp: timestamp;
|
|
10
11
|
bestAskRate: number;
|
|
11
12
|
bestAskQuantity: number;
|
package/src/domain/position.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { map, Observable, share } from 'rxjs';
|
|
2
|
+
|
|
2
3
|
import { Instrument } from '../domain';
|
|
3
4
|
import { pnl, timestamp, weightedMean } from '../shared';
|
|
4
5
|
import { Component } from './component';
|
|
@@ -6,6 +7,7 @@ import { Component } from './component';
|
|
|
6
7
|
export type PositionMode = 'CROSS' | 'ISOLATED';
|
|
7
8
|
|
|
8
9
|
export class Position implements Component {
|
|
10
|
+
kind = 'position';
|
|
9
11
|
timestamp: timestamp;
|
|
10
12
|
averageExecutionRate: number;
|
|
11
13
|
size: number;
|
package/src/domain/session.ts
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
|
-
concat,
|
|
3
2
|
defer,
|
|
4
3
|
distinctUntilChanged,
|
|
5
4
|
filter,
|
|
5
|
+
finalize,
|
|
6
6
|
from,
|
|
7
7
|
map,
|
|
8
8
|
merge,
|
|
9
9
|
mergeMap,
|
|
10
10
|
Observable,
|
|
11
|
-
share,
|
|
12
11
|
shareReplay,
|
|
13
12
|
startWith,
|
|
14
13
|
Subject,
|
|
@@ -16,6 +15,7 @@ import {
|
|
|
16
15
|
switchMap,
|
|
17
16
|
take
|
|
18
17
|
} from 'rxjs';
|
|
18
|
+
|
|
19
19
|
import { Adapter, BacktesterOptions, PaperOptions } from '../adapter';
|
|
20
20
|
import { AdapterAggregate } from '../adapter/adapter-aggregate';
|
|
21
21
|
import {
|
|
@@ -27,15 +27,13 @@ import {
|
|
|
27
27
|
Order,
|
|
28
28
|
Orderbook,
|
|
29
29
|
OrderState,
|
|
30
|
-
Position
|
|
30
|
+
Position,
|
|
31
|
+
Trade
|
|
31
32
|
} from '../domain';
|
|
32
|
-
import {
|
|
33
|
-
import {
|
|
34
|
-
import { Feed, Measurement } from '../storage';
|
|
33
|
+
import { now } from '../shared';
|
|
34
|
+
import { StorageFactory } from '../storage';
|
|
35
35
|
import { Store } from '../store';
|
|
36
36
|
|
|
37
|
-
type Optional<T, K extends keyof T> = Omit<T, K> & Partial<T>;
|
|
38
|
-
|
|
39
37
|
/**
|
|
40
38
|
* Describes a single session.
|
|
41
39
|
* You can use @run function to start a new session managed by CLI.
|
|
@@ -65,29 +63,20 @@ export interface SessionDescriptor {
|
|
|
65
63
|
|
|
66
64
|
/**
|
|
67
65
|
* Provides historical data for backtest, it's not required for live and paper
|
|
68
|
-
* sessions.
|
|
69
|
-
*/
|
|
70
|
-
feed?: Feed;
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* Stores session variables i.e. indicators, orders, or any other type of time
|
|
66
|
+
* sessions. Stores session variables i.e. indicators, orders, or any other type of time
|
|
74
67
|
* series data. You can install @quantform/editor to render this data in your browser.
|
|
75
68
|
*/
|
|
76
|
-
|
|
69
|
+
storage?: StorageFactory;
|
|
77
70
|
|
|
78
71
|
/**
|
|
79
72
|
* Session additional options.
|
|
80
73
|
*/
|
|
81
|
-
|
|
82
|
-
backtester?: BacktesterOptions;
|
|
83
|
-
paper?: PaperOptions;
|
|
84
|
-
};
|
|
74
|
+
simulation?: PaperOptions & BacktesterOptions;
|
|
85
75
|
}
|
|
86
76
|
|
|
87
77
|
export class Session {
|
|
88
78
|
private initialized = false;
|
|
89
79
|
private subscription: Subscription;
|
|
90
|
-
private worker = new Worker();
|
|
91
80
|
|
|
92
81
|
get timestamp(): number {
|
|
93
82
|
return this.store.snapshot.timestamp;
|
|
@@ -117,7 +106,9 @@ export class Session {
|
|
|
117
106
|
await this.aggregate.awake();
|
|
118
107
|
|
|
119
108
|
if (describe) {
|
|
120
|
-
this.subscription = describe(this)
|
|
109
|
+
this.subscription = describe(this)
|
|
110
|
+
.pipe(finalize(() => this.dispose()))
|
|
111
|
+
.subscribe();
|
|
121
112
|
}
|
|
122
113
|
}
|
|
123
114
|
|
|
@@ -126,63 +117,22 @@ export class Session {
|
|
|
126
117
|
return;
|
|
127
118
|
}
|
|
128
119
|
|
|
129
|
-
this.store.dispose();
|
|
130
|
-
|
|
131
120
|
if (this.subscription) {
|
|
132
121
|
this.subscription.unsubscribe();
|
|
122
|
+
this.subscription = undefined;
|
|
133
123
|
}
|
|
134
124
|
|
|
125
|
+
this.store.dispose();
|
|
126
|
+
|
|
135
127
|
await this.aggregate.dispose();
|
|
136
|
-
|
|
128
|
+
|
|
129
|
+
this.initialized = false;
|
|
137
130
|
}
|
|
138
131
|
|
|
139
132
|
useStatement(section: string): Record<string, any> {
|
|
140
133
|
return this.statement[section] ?? (this.statement[section] = {});
|
|
141
134
|
}
|
|
142
135
|
|
|
143
|
-
/**
|
|
144
|
-
* Returns last stored measurement and setter for it in session.
|
|
145
|
-
* For example you can save and restore variables in same session between runs.
|
|
146
|
-
* Example usage:
|
|
147
|
-
* const [order$, setOrder] = session.measurement<Order>('order');
|
|
148
|
-
*
|
|
149
|
-
* order.pipe(tap(it => console.log(`your last order was: ${it}`)));
|
|
150
|
-
*
|
|
151
|
-
* setOrder(order);
|
|
152
|
-
*/
|
|
153
|
-
useMeasure<T extends { timestamp: number }>(
|
|
154
|
-
params: { kind: string; timestamp?: number },
|
|
155
|
-
defaultValue: T = undefined
|
|
156
|
-
): [Observable<T>, (value: Optional<T, 'timestamp'>) => void] {
|
|
157
|
-
const stored$ = from(
|
|
158
|
-
this.descriptor.measurement.query(this.descriptor.id, {
|
|
159
|
-
to: params.timestamp ?? this.timestamp,
|
|
160
|
-
kind: params.kind,
|
|
161
|
-
count: 1
|
|
162
|
-
})
|
|
163
|
-
).pipe(
|
|
164
|
-
map(it =>
|
|
165
|
-
it.length ? { timestamp: it[0].timestamp, ...it[0].payload } : defaultValue
|
|
166
|
-
),
|
|
167
|
-
share()
|
|
168
|
-
);
|
|
169
|
-
|
|
170
|
-
const subject$ = new Subject<T>();
|
|
171
|
-
|
|
172
|
-
const setter = (value: T) => {
|
|
173
|
-
const timestamp = value.timestamp ?? this.timestamp;
|
|
174
|
-
const measure = { timestamp, kind: params.kind, payload: value };
|
|
175
|
-
|
|
176
|
-
this.worker.enqueue(() =>
|
|
177
|
-
this.descriptor.measurement.save(this.descriptor.id, [measure])
|
|
178
|
-
);
|
|
179
|
-
|
|
180
|
-
subject$.next({ ...value, timestamp });
|
|
181
|
-
};
|
|
182
|
-
|
|
183
|
-
return [concat(stored$, subject$.asObservable()), setter];
|
|
184
|
-
}
|
|
185
|
-
|
|
186
136
|
/**
|
|
187
137
|
* Return values for patch provided in optimization file.
|
|
188
138
|
* Example usage:
|
package/src/domain/statement.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { combineLatest, finalize, map, take, tap } from 'rxjs';
|
|
2
|
-
|
|
2
|
+
|
|
3
3
|
import { drawdown } from '../indicator';
|
|
4
4
|
import { floor, precision } from '../shared';
|
|
5
|
+
import { InstrumentSelector, Session } from '.';
|
|
5
6
|
|
|
6
7
|
export function period() {
|
|
7
8
|
return (session: Session) => {
|
|
@@ -46,11 +47,11 @@ export function benchmark(instrument: InstrumentSelector) {
|
|
|
46
47
|
finalize(() => {
|
|
47
48
|
const pnl = exit / entry - 1;
|
|
48
49
|
|
|
49
|
-
statement
|
|
50
|
-
statement
|
|
51
|
-
statement
|
|
52
|
-
statement
|
|
53
|
-
statement
|
|
50
|
+
statement.benchmark_entry = entry;
|
|
51
|
+
statement.benchmark_exit = exit;
|
|
52
|
+
statement.benchmark_pnl = floor(balance * pnl, precision(entry));
|
|
53
|
+
statement.benchmark_pnl_pp = floor(pnl * 100, 2);
|
|
54
|
+
statement.benchmark_drawdown_pp = floor(dd * 100, 2);
|
|
54
55
|
})
|
|
55
56
|
);
|
|
56
57
|
};
|
|
@@ -106,12 +107,12 @@ export function equity(instrument: InstrumentSelector) {
|
|
|
106
107
|
const pnl = equity / balance - 1;
|
|
107
108
|
const scale = precision(equity);
|
|
108
109
|
|
|
109
|
-
statement
|
|
110
|
-
statement
|
|
111
|
-
statement
|
|
112
|
-
statement
|
|
113
|
-
statement
|
|
114
|
-
statement
|
|
110
|
+
statement.equity = equity;
|
|
111
|
+
statement.equity_min = min;
|
|
112
|
+
statement.equity_max = max;
|
|
113
|
+
statement.equity_pnl = floor(balance * pnl, scale);
|
|
114
|
+
statement.equity_pnl_pp = floor(pnl * 100, 2);
|
|
115
|
+
statement.equity_drawdown_pp = floor(dd * 100, 2);
|
|
115
116
|
})
|
|
116
117
|
);
|
|
117
118
|
};
|
package/src/domain/trade.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Instrument } from '.';
|
|
2
1
|
import { timestamp } from '../shared';
|
|
2
|
+
import { Instrument } from '.';
|
|
3
3
|
import { Component } from './component';
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -7,6 +7,7 @@ import { Component } from './component';
|
|
|
7
7
|
* and seller of the same asset.
|
|
8
8
|
*/
|
|
9
9
|
export class Trade implements Component {
|
|
10
|
+
kind = 'trade';
|
|
10
11
|
timestamp: timestamp;
|
|
11
12
|
rate: number;
|
|
12
13
|
quantity: number;
|
package/src/index.ts
CHANGED
package/src/indicator/atr.ts
CHANGED
package/src/indicator/ema.ts
CHANGED
package/src/indicator/macd.ts
CHANGED
package/src/indicator/min-max.ts
CHANGED
package/src/indicator/rma.ts
CHANGED
package/src/indicator/sma.ts
CHANGED
package/src/indicator/swma.ts
CHANGED
package/src/indicator/tma.ts
CHANGED
package/src/indicator/window.ts
CHANGED
package/src/indicator/wma.ts
CHANGED
package/src/shared/index.ts
CHANGED
|
@@ -4,9 +4,7 @@ describe('cache policy tests', () => {
|
|
|
4
4
|
test('string as key cache', async () => {
|
|
5
5
|
let counter = 0;
|
|
6
6
|
|
|
7
|
-
const request = async () =>
|
|
8
|
-
return ++counter;
|
|
9
|
-
};
|
|
7
|
+
const request = async () => ++counter;
|
|
10
8
|
|
|
11
9
|
expect(await cache('abc', request)).toBe(1);
|
|
12
10
|
expect(await cache('abc', request)).toBe(1);
|
|
@@ -17,9 +15,7 @@ describe('cache policy tests', () => {
|
|
|
17
15
|
test('object as key cache', async () => {
|
|
18
16
|
let counter = 0;
|
|
19
17
|
|
|
20
|
-
const request = async () =>
|
|
21
|
-
return ++counter;
|
|
22
|
-
};
|
|
18
|
+
const request = async () => ++counter;
|
|
23
19
|
|
|
24
20
|
expect(await cache({ from: 1, to: 2, content: 'abc' }, request)).toBe(1);
|
|
25
21
|
expect(await cache({ from: 1, to: 2, content: 'abc' }, request)).toBe(1);
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { now } from '../shared';
|
|
2
|
+
import { Storage } from './storage';
|
|
3
|
+
|
|
4
|
+
export class Cache {
|
|
5
|
+
constructor(private readonly storage: Storage) {}
|
|
6
|
+
|
|
7
|
+
async tryGet<T>(
|
|
8
|
+
getter: () => Promise<T>,
|
|
9
|
+
options: { key: string; ttl?: number }
|
|
10
|
+
): Promise<T> {
|
|
11
|
+
const time = now();
|
|
12
|
+
|
|
13
|
+
const payload = await this.storage.query(options.key, {
|
|
14
|
+
kind: 'cache',
|
|
15
|
+
count: 1,
|
|
16
|
+
to: time
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
if ((!payload.length || payload[0].timestamp < time - options.ttl) ?? 60 * 60 * 24) {
|
|
20
|
+
const value = await getter();
|
|
21
|
+
|
|
22
|
+
await this.storage.save(options.key, [
|
|
23
|
+
{
|
|
24
|
+
timestamp: time,
|
|
25
|
+
kind: 'cache',
|
|
26
|
+
json: JSON.stringify(value)
|
|
27
|
+
}
|
|
28
|
+
]);
|
|
29
|
+
|
|
30
|
+
return value;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return JSON.parse(payload[0].json);
|
|
34
|
+
}
|
|
35
|
+
}
|
package/src/storage/index.ts
CHANGED
package/src/storage/storage.ts
CHANGED
|
@@ -35,6 +35,13 @@ export interface Storage {
|
|
|
35
35
|
query(library: string, options: StorageQueryOptions): Promise<StorageDocument[]>;
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
+
/**
|
|
39
|
+
*
|
|
40
|
+
*/
|
|
41
|
+
export interface StorageFactory {
|
|
42
|
+
create(type: string): Storage;
|
|
43
|
+
}
|
|
44
|
+
|
|
38
45
|
/**
|
|
39
46
|
*
|
|
40
47
|
*/
|
|
@@ -111,3 +118,11 @@ export class InMemoryStorage implements Storage {
|
|
|
111
118
|
this.tables = {};
|
|
112
119
|
}
|
|
113
120
|
}
|
|
121
|
+
|
|
122
|
+
export class InMemoryStorageFactory implements StorageFactory {
|
|
123
|
+
private readonly storage: Record<string, Storage> = {};
|
|
124
|
+
|
|
125
|
+
create(type: string): Storage {
|
|
126
|
+
return this.storage[type] ?? (this.storage[type] = new InMemoryStorage());
|
|
127
|
+
}
|
|
128
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { BalancePatchEvent } from '.';
|
|
2
|
-
import { Store } from '..';
|
|
3
1
|
import { Asset, Commission } from '../../domain';
|
|
4
2
|
import { now } from '../../shared';
|
|
3
|
+
import { Store } from '..';
|
|
4
|
+
import { BalancePatchEvent } from '.';
|
|
5
5
|
import { InstrumentPatchEvent } from './store-instrument.event';
|
|
6
6
|
|
|
7
7
|
describe('balance event tests', () => {
|
|
@@ -23,7 +23,7 @@ describe('balance event tests', () => {
|
|
|
23
23
|
|
|
24
24
|
expect(balance).toEqual(component);
|
|
25
25
|
expect(balance.free).toEqual(100);
|
|
26
|
-
expect(balance.
|
|
26
|
+
expect(balance.locked).toEqual(0);
|
|
27
27
|
expect(balance.timestamp).toEqual(timestamp);
|
|
28
28
|
expect(store.snapshot.timestamp).toEqual(timestamp);
|
|
29
29
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { CandleEvent } from '.';
|
|
2
1
|
import { Asset, Instrument } from '../../domain';
|
|
3
2
|
import { now } from '../../shared';
|
|
4
3
|
import { Store } from '../store';
|
|
4
|
+
import { CandleEvent } from '.';
|
|
5
5
|
|
|
6
6
|
const instrument = new Instrument(
|
|
7
7
|
new Asset('btc', 'binance', 8),
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { StateChangeTracker } from '..';
|
|
2
1
|
import { InstrumentSelector } from '../../domain';
|
|
3
2
|
import { timestamp } from '../../shared/datetime';
|
|
4
3
|
import { event } from '../../shared/topic';
|
|
4
|
+
import { StateChangeTracker } from '..';
|
|
5
5
|
import { State } from '../store.state';
|
|
6
|
+
import { StoreEvent } from './store.event';
|
|
6
7
|
import { OrderbookPatchEventHandler } from './store-orderbook.event';
|
|
7
8
|
import { TradePatchEventHandler } from './store-trade.event';
|
|
8
|
-
import { StoreEvent } from './store.event';
|
|
9
9
|
|
|
10
10
|
@event
|
|
11
11
|
export class CandleEvent implements StoreEvent {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { TradePatchEvent } from '.';
|
|
2
|
-
import { Store } from '..';
|
|
3
1
|
import { Asset, Instrument } from '../../domain';
|
|
4
2
|
import { now } from '../../shared';
|
|
3
|
+
import { Store } from '..';
|
|
4
|
+
import { TradePatchEvent } from '.';
|
|
5
5
|
|
|
6
6
|
const instrument = new Instrument(
|
|
7
7
|
new Asset('btc', 'binance', 8),
|