@quantform/core 0.6.4 → 0.6.6
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 +1 -2
- package/dist/adapter/adapter.d.ts +2 -2
- package/dist/adapter/adapter.d.ts.map +1 -1
- package/dist/adapter/backtester/backtester-adapter.d.ts +2 -2
- package/dist/adapter/backtester/backtester-adapter.d.ts.map +1 -1
- package/dist/adapter/paper/paper-adapter.d.ts +2 -2
- package/dist/adapter/paper/paper-adapter.d.ts.map +1 -1
- package/dist/cli/dev.js +2 -2
- package/dist/cli/pull.js +2 -2
- package/dist/cli/run.js +2 -2
- package/dist/cli/test.js +2 -2
- package/dist/domain/asset.d.ts +0 -4
- package/dist/domain/asset.d.ts.map +1 -1
- package/dist/domain/asset.js +0 -6
- package/dist/domain/balance.d.ts +0 -2
- package/dist/domain/balance.d.ts.map +1 -1
- package/dist/domain/balance.js +0 -4
- package/dist/domain/component.d.ts +0 -1
- package/dist/domain/component.d.ts.map +1 -1
- package/dist/domain/index.d.ts +2 -2
- package/dist/domain/index.d.ts.map +1 -1
- package/dist/domain/index.js +2 -2
- package/dist/domain/instrument.d.ts +0 -2
- package/dist/domain/instrument.d.ts.map +1 -1
- package/dist/domain/instrument.js +0 -4
- package/dist/domain/ohlc-operator.d.ts +11 -0
- package/dist/domain/ohlc-operator.d.ts.map +1 -0
- package/dist/domain/{candle-operator.js → ohlc-operator.js} +11 -11
- package/dist/domain/{candle.d.ts → ohlc.d.ts} +2 -2
- package/dist/domain/ohlc.d.ts.map +1 -0
- package/dist/domain/{candle.js → ohlc.js} +3 -3
- package/dist/domain/order.d.ts +0 -2
- package/dist/domain/order.d.ts.map +1 -1
- package/dist/domain/order.js +0 -4
- package/dist/domain/orderbook.d.ts +0 -2
- package/dist/domain/orderbook.d.ts.map +1 -1
- package/dist/domain/orderbook.js +0 -4
- package/dist/domain/position.d.ts +0 -2
- package/dist/domain/position.d.ts.map +1 -1
- package/dist/domain/position.js +0 -4
- package/dist/domain/session-builder.d.ts +1 -1
- package/dist/domain/session-builder.d.ts.map +1 -1
- package/dist/domain/session-builder.js +3 -2
- package/dist/domain/session.d.ts +2 -2
- package/dist/domain/session.d.ts.map +1 -1
- package/dist/domain/trade.d.ts +0 -2
- package/dist/domain/trade.d.ts.map +1 -1
- package/dist/domain/trade.js +0 -4
- package/dist/index.d.ts +24 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +63 -1
- package/dist/shared/logger.d.ts +1 -0
- package/dist/shared/logger.d.ts.map +1 -1
- package/dist/shared/logger.js +7 -4
- package/package.json +1 -1
- package/src/adapter/adapter-aggregate.ts +4 -6
- package/src/adapter/adapter.ts +3 -3
- package/src/adapter/backtester/backtester-adapter.ts +2 -2
- package/src/adapter/backtester/backtester-cursor.ts +1 -1
- package/src/adapter/paper/paper-adapter.ts +2 -2
- package/src/cli/dev.ts +2 -2
- package/src/cli/pull.ts +2 -2
- package/src/cli/run.ts +2 -2
- package/src/cli/test.ts +2 -2
- package/src/domain/asset.ts +0 -7
- package/src/domain/balance.ts +0 -5
- package/src/domain/component.ts +0 -1
- package/src/domain/index.ts +2 -2
- package/src/domain/instrument.ts +0 -5
- package/src/domain/ohlc-operator.spec.ts +126 -0
- package/src/domain/{candle-operator.ts → ohlc-operator.ts} +15 -15
- package/src/domain/{candle.spec.ts → ohlc.spec.ts} +6 -6
- package/src/domain/{candle.ts → ohlc.ts} +2 -2
- package/src/domain/order.ts +0 -5
- package/src/domain/orderbook.ts +0 -5
- package/src/domain/position.ts +0 -5
- package/src/domain/session-builder.ts +3 -3
- package/src/domain/session.ts +3 -3
- package/src/domain/trade.ts +0 -5
- package/src/index.ts +75 -1
- package/src/shared/logger.ts +6 -4
- package/dist/domain/candle-operator.d.ts +0 -11
- package/dist/domain/candle-operator.d.ts.map +0 -1
- package/dist/domain/candle.d.ts.map +0 -1
- package/dist/strategy.d.ts +0 -8
- package/dist/strategy.d.ts.map +0 -1
- package/dist/strategy.js +0 -44
- package/src/domain/candle-operator.spec.ts +0 -126
- package/src/strategy.ts +0 -47
|
@@ -12,11 +12,11 @@ import {
|
|
|
12
12
|
} from 'rxjs';
|
|
13
13
|
|
|
14
14
|
import { decimal } from '../shared';
|
|
15
|
-
import {
|
|
15
|
+
import { Ohlc } from './ohlc';
|
|
16
16
|
import { tf } from './timeframe';
|
|
17
17
|
|
|
18
18
|
function aggregate(
|
|
19
|
-
candle:
|
|
19
|
+
candle: Ohlc | undefined,
|
|
20
20
|
timeframe: number,
|
|
21
21
|
value: decimal,
|
|
22
22
|
timestamp: number
|
|
@@ -24,23 +24,23 @@ function aggregate(
|
|
|
24
24
|
const frame = tf(timestamp, timeframe);
|
|
25
25
|
|
|
26
26
|
if (!candle) {
|
|
27
|
-
return new
|
|
27
|
+
return new Ohlc(frame, value, value, value, value);
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
if (candle.timestamp === frame) {
|
|
31
31
|
candle.apply(value);
|
|
32
32
|
return undefined;
|
|
33
33
|
} else {
|
|
34
|
-
return new
|
|
34
|
+
return new Ohlc(frame, candle.close, value, value, value);
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
export function
|
|
38
|
+
export function ohlc<T extends { timestamp: number }>(
|
|
39
39
|
timeframe: number,
|
|
40
40
|
fn: (x: T) => decimal,
|
|
41
|
-
candleToStartWith?:
|
|
41
|
+
candleToStartWith?: Ohlc
|
|
42
42
|
) {
|
|
43
|
-
return function (source: Observable<T>): Observable<
|
|
43
|
+
return function (source: Observable<T>): Observable<Ohlc> {
|
|
44
44
|
let candle = candleToStartWith;
|
|
45
45
|
|
|
46
46
|
return source.pipe(
|
|
@@ -77,18 +77,18 @@ export function candle<T extends { timestamp: number }>(
|
|
|
77
77
|
};
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
-
export function
|
|
80
|
+
export function mergeOhlc<T extends { timestamp: number }>(
|
|
81
81
|
timeframe: number,
|
|
82
82
|
fn: (x: T) => decimal,
|
|
83
|
-
history$: Observable<
|
|
83
|
+
history$: Observable<Ohlc>
|
|
84
84
|
) {
|
|
85
|
-
return function (source$: Observable<T>): Observable<
|
|
85
|
+
return function (source$: Observable<T>): Observable<Ohlc> {
|
|
86
86
|
return concat(
|
|
87
87
|
history$.pipe(skipLast(1)),
|
|
88
88
|
history$.pipe(
|
|
89
89
|
last(),
|
|
90
90
|
switchMap(lastHistoricalCandle =>
|
|
91
|
-
source$.pipe(
|
|
91
|
+
source$.pipe(ohlc(timeframe, fn, lastHistoricalCandle))
|
|
92
92
|
),
|
|
93
93
|
share()
|
|
94
94
|
)
|
|
@@ -96,10 +96,10 @@ export function mergeCandle<T extends { timestamp: number }>(
|
|
|
96
96
|
};
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
-
export function
|
|
100
|
-
let currCandle:
|
|
99
|
+
export function ohlcCompleted(): (source: Observable<Ohlc>) => Observable<Ohlc> {
|
|
100
|
+
let currCandle: Ohlc;
|
|
101
101
|
|
|
102
|
-
return (source: Observable<
|
|
102
|
+
return (source: Observable<Ohlc>) =>
|
|
103
103
|
source.pipe(
|
|
104
104
|
map(it => {
|
|
105
105
|
if (!currCandle) {
|
|
@@ -117,7 +117,7 @@ export function candleCompleted(): (source: Observable<Candle>) => Observable<Ca
|
|
|
117
117
|
return undefined;
|
|
118
118
|
}
|
|
119
119
|
}),
|
|
120
|
-
filter(it => it !== undefined) as OperatorFunction<
|
|
120
|
+
filter(it => it !== undefined) as OperatorFunction<Ohlc | undefined, Ohlc>,
|
|
121
121
|
share()
|
|
122
122
|
);
|
|
123
123
|
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { d, now } from '../shared';
|
|
2
|
-
import {
|
|
2
|
+
import { Ohlc } from './ohlc';
|
|
3
3
|
|
|
4
|
-
describe('
|
|
5
|
-
test('should construct a
|
|
4
|
+
describe('Ohlc', () => {
|
|
5
|
+
test('should construct a ohlc', () => {
|
|
6
6
|
const timestamp = now();
|
|
7
7
|
|
|
8
|
-
const sut = new
|
|
8
|
+
const sut = new Ohlc(timestamp, d(2), d(4), d(1), d(3));
|
|
9
9
|
|
|
10
10
|
expect(sut.timestamp).toEqual(timestamp);
|
|
11
11
|
expect(sut.open).toEqual(d(2));
|
|
@@ -14,10 +14,10 @@ describe('Candle', () => {
|
|
|
14
14
|
expect(sut.close).toEqual(d(3));
|
|
15
15
|
});
|
|
16
16
|
|
|
17
|
-
test('should modify a
|
|
17
|
+
test('should modify a ohlc', () => {
|
|
18
18
|
const timestamp = now();
|
|
19
19
|
|
|
20
|
-
const sut = new
|
|
20
|
+
const sut = new Ohlc(timestamp, d(2), d(4), d(1), d(3));
|
|
21
21
|
|
|
22
22
|
sut.apply(d(10));
|
|
23
23
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { decimal, timestamp } from '../shared';
|
|
2
2
|
|
|
3
|
-
export class
|
|
3
|
+
export class Ohlc {
|
|
4
4
|
constructor(
|
|
5
5
|
public timestamp: timestamp,
|
|
6
6
|
public open: decimal,
|
|
@@ -8,7 +8,7 @@ export class Candle {
|
|
|
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);
|
package/src/domain/order.ts
CHANGED
|
@@ -13,7 +13,6 @@ export type OrderState =
|
|
|
13
13
|
| 'REJECTED';
|
|
14
14
|
|
|
15
15
|
export class Order implements Component {
|
|
16
|
-
readonly kind = 'order';
|
|
17
16
|
state: OrderState = 'NEW';
|
|
18
17
|
quantityExecuted = d.Zero;
|
|
19
18
|
averageExecutionRate?: decimal;
|
|
@@ -37,10 +36,6 @@ export class Order implements Component {
|
|
|
37
36
|
}
|
|
38
37
|
}
|
|
39
38
|
|
|
40
|
-
toString() {
|
|
41
|
-
return this.id;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
39
|
calculateBalanceToLock(
|
|
45
40
|
base: Balance,
|
|
46
41
|
quote: Balance
|
package/src/domain/orderbook.ts
CHANGED
|
@@ -18,7 +18,6 @@ export const LiquidityBidComparer = (lhs: { rate: decimal }, rhs: { rate: decima
|
|
|
18
18
|
*/
|
|
19
19
|
export class Orderbook implements Component {
|
|
20
20
|
readonly id: string;
|
|
21
|
-
readonly kind = 'orderbook';
|
|
22
21
|
|
|
23
22
|
constructor(
|
|
24
23
|
public timestamp: number,
|
|
@@ -28,8 +27,4 @@ export class Orderbook implements Component {
|
|
|
28
27
|
) {
|
|
29
28
|
this.id = instrument.id;
|
|
30
29
|
}
|
|
31
|
-
|
|
32
|
-
toString() {
|
|
33
|
-
return this.instrument.toString();
|
|
34
|
-
}
|
|
35
30
|
}
|
package/src/domain/position.ts
CHANGED
|
@@ -5,7 +5,6 @@ import { Component } from './component';
|
|
|
5
5
|
export type PositionMode = 'CROSS' | 'ISOLATED';
|
|
6
6
|
|
|
7
7
|
export class Position implements Component {
|
|
8
|
-
readonly kind = 'position';
|
|
9
8
|
estimatedUnrealizedPnL?: decimal;
|
|
10
9
|
|
|
11
10
|
get margin(): decimal {
|
|
@@ -29,8 +28,4 @@ export class Position implements Component {
|
|
|
29
28
|
|
|
30
29
|
return this.estimatedUnrealizedPnL;
|
|
31
30
|
}
|
|
32
|
-
|
|
33
|
-
toString() {
|
|
34
|
-
return this.id;
|
|
35
|
-
}
|
|
36
31
|
}
|
|
@@ -27,9 +27,9 @@ export function deposit(selector: AssetSelector, amount: decimal): SessionFeatur
|
|
|
27
27
|
};
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
export function period(from: Date, to
|
|
30
|
+
export function period(from: Date, to?: Date): SessionFeature {
|
|
31
31
|
return (builder: SessionBuilder) => {
|
|
32
|
-
builder.usePeriod(from.getTime(), to
|
|
32
|
+
builder.usePeriod(from.getTime(), to?.getTime() ?? now());
|
|
33
33
|
};
|
|
34
34
|
}
|
|
35
35
|
|
|
@@ -76,7 +76,7 @@ export class SessionBuilder {
|
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
useBalance(selector: AssetSelector, amount: decimal): SessionBuilder {
|
|
79
|
-
this.balance[selector.
|
|
79
|
+
this.balance[selector.id] = amount;
|
|
80
80
|
|
|
81
81
|
return this;
|
|
82
82
|
}
|
package/src/domain/session.ts
CHANGED
|
@@ -20,10 +20,10 @@ import { AdapterAggregate } from '../adapter/adapter-aggregate';
|
|
|
20
20
|
import {
|
|
21
21
|
AssetSelector,
|
|
22
22
|
Balance,
|
|
23
|
-
Candle,
|
|
24
23
|
Instrument,
|
|
25
24
|
InstrumentSelector,
|
|
26
25
|
invalidInstrumentSelectorError,
|
|
26
|
+
Ohlc,
|
|
27
27
|
Order,
|
|
28
28
|
Orderbook,
|
|
29
29
|
Position,
|
|
@@ -53,7 +53,7 @@ export class Session {
|
|
|
53
53
|
readonly store: Store,
|
|
54
54
|
readonly aggregate: AdapterAggregate,
|
|
55
55
|
readonly measurement: Measurement | undefined
|
|
56
|
-
) {
|
|
56
|
+
) {}
|
|
57
57
|
|
|
58
58
|
async awake(): Promise<void> {
|
|
59
59
|
if (this.initialized) {
|
|
@@ -203,7 +203,7 @@ export class Session {
|
|
|
203
203
|
selector: InstrumentSelector,
|
|
204
204
|
timeframe: number,
|
|
205
205
|
length: number
|
|
206
|
-
): Observable<Readonly<
|
|
206
|
+
): Observable<Readonly<Ohlc>> {
|
|
207
207
|
return this.store.changes$.pipe(
|
|
208
208
|
startWith(this.store.snapshot.universe.instrument.get(selector.id)),
|
|
209
209
|
filter(it => it instanceof Instrument && it.id == selector.id),
|
package/src/domain/trade.ts
CHANGED
|
@@ -8,7 +8,6 @@ import { Component } from './component';
|
|
|
8
8
|
*/
|
|
9
9
|
export class Trade implements Component {
|
|
10
10
|
readonly id: string;
|
|
11
|
-
readonly kind = 'trade';
|
|
12
11
|
|
|
13
12
|
constructor(
|
|
14
13
|
public timestamp: number,
|
|
@@ -18,8 +17,4 @@ export class Trade implements Component {
|
|
|
18
17
|
) {
|
|
19
18
|
this.id = instrument.id;
|
|
20
19
|
}
|
|
21
|
-
|
|
22
|
-
toString() {
|
|
23
|
-
return this.instrument.toString();
|
|
24
|
-
}
|
|
25
20
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,6 +1,80 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { finalize, forkJoin, Observable, of, switchMap } from 'rxjs';
|
|
3
|
+
|
|
4
|
+
import { Session, SessionBuilder, SessionFeature } from './domain';
|
|
1
5
|
export * from './adapter';
|
|
2
6
|
export * from './domain';
|
|
3
7
|
export * from './shared';
|
|
4
8
|
export * from './storage';
|
|
5
9
|
export * from './store';
|
|
6
|
-
|
|
10
|
+
|
|
11
|
+
import { Logger } from './shared';
|
|
12
|
+
|
|
13
|
+
const registry: Record<string, () => Array<SessionFeature>> = {};
|
|
14
|
+
|
|
15
|
+
export type SessionHook = (session: Session) => Observable<any>;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Describes a single strategy logic
|
|
19
|
+
*/
|
|
20
|
+
export let rule: (name: string | undefined, describe: SessionHook) => void;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
*
|
|
24
|
+
*/
|
|
25
|
+
export let beforeAll: (describe: SessionHook) => void;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
*
|
|
29
|
+
* @param name
|
|
30
|
+
* @param describe
|
|
31
|
+
*/
|
|
32
|
+
export function describe(name: string, describe: () => Array<SessionFeature>) {
|
|
33
|
+
registry[name] = describe;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
*
|
|
38
|
+
* @param name
|
|
39
|
+
* @param builder
|
|
40
|
+
* @returns
|
|
41
|
+
*/
|
|
42
|
+
export async function spawn(name: string, builder: SessionBuilder) {
|
|
43
|
+
const describe = registry[name];
|
|
44
|
+
if (!describe) {
|
|
45
|
+
throw new Error(`missing strategy: ${name}`);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const ruleHooks = new Array<SessionHook>();
|
|
49
|
+
const beforeAllHooks = new Array<SessionHook>();
|
|
50
|
+
|
|
51
|
+
beforeAll = (describe: SessionHook) => {
|
|
52
|
+
beforeAllHooks.push(describe);
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
rule = (ruleName: string | undefined, describe: SessionHook) => {
|
|
56
|
+
if (ruleName) {
|
|
57
|
+
Logger.info(name, `${chalk.italic(ruleName)} rule found`);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
ruleHooks.push(describe);
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
for (const feature of describe()) {
|
|
64
|
+
feature(builder);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return (session: Session) => {
|
|
68
|
+
const beforeAll$ = beforeAllHooks.map(it => it(session));
|
|
69
|
+
const rule$ = ruleHooks.map(it => it(session));
|
|
70
|
+
|
|
71
|
+
if (!beforeAll$.length) {
|
|
72
|
+
beforeAll$.push(of(true));
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return forkJoin(beforeAll$).pipe(
|
|
76
|
+
switchMap(() => forkJoin(rule$)),
|
|
77
|
+
finalize(() => session.dispose())
|
|
78
|
+
);
|
|
79
|
+
};
|
|
80
|
+
}
|
package/src/shared/logger.ts
CHANGED
|
@@ -17,13 +17,13 @@ const time = () => chalk.gray(new Date(now()).toISOString());
|
|
|
17
17
|
|
|
18
18
|
export class Logger {
|
|
19
19
|
public static info = (context: string, message: string) =>
|
|
20
|
-
console.info(`${
|
|
20
|
+
console.info(`${this.prefix(context)}: ${message}`);
|
|
21
21
|
|
|
22
22
|
public static debug = (context: string, message: string) =>
|
|
23
|
-
console.debug(`${
|
|
23
|
+
console.debug(`${this.prefix(context)}: ${message}`);
|
|
24
24
|
|
|
25
25
|
public static warn = (context: string, message: string) =>
|
|
26
|
-
console.warn(`${
|
|
26
|
+
console.warn(`${this.prefix(context)}: ${message}`);
|
|
27
27
|
|
|
28
28
|
public static error = (context: string, error: unknown) => {
|
|
29
29
|
let message = 'Unknown Error';
|
|
@@ -32,6 +32,8 @@ export class Logger {
|
|
|
32
32
|
message = error.message;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
console.error(`${
|
|
35
|
+
console.error(`${this.prefix(context)}: ${message}`);
|
|
36
36
|
};
|
|
37
|
+
|
|
38
|
+
public static prefix = (context: string) => `${time()} ${colorize(context)}`;
|
|
37
39
|
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { Observable } from 'rxjs';
|
|
2
|
-
import { decimal } from '../shared';
|
|
3
|
-
import { Candle } from './candle';
|
|
4
|
-
export declare function candle<T extends {
|
|
5
|
-
timestamp: number;
|
|
6
|
-
}>(timeframe: number, fn: (x: T) => decimal, candleToStartWith?: Candle): (source: Observable<T>) => Observable<Candle>;
|
|
7
|
-
export declare function mergeCandle<T extends {
|
|
8
|
-
timestamp: number;
|
|
9
|
-
}>(timeframe: number, fn: (x: T) => decimal, history$: Observable<Candle>): (source$: Observable<T>) => Observable<Candle>;
|
|
10
|
-
export declare function candleCompleted(): (source: Observable<Candle>) => Observable<Candle>;
|
|
11
|
-
//# sourceMappingURL=candle-operator.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"candle-operator.d.ts","sourceRoot":"","sources":["../../src/domain/candle-operator.ts"],"names":[],"mappings":"AAAA,OAAO,EAML,UAAU,EAKX,MAAM,MAAM,CAAC;AAEd,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAuBlC,wBAAgB,MAAM,CAAC,CAAC,SAAS;IAAE,SAAS,EAAE,MAAM,CAAA;CAAE,EACpD,SAAS,EAAE,MAAM,EACjB,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,OAAO,EACrB,iBAAiB,CAAC,EAAE,MAAM,YAED,WAAW,CAAC,CAAC,KAAG,WAAW,MAAM,CAAC,CAmC5D;AAED,wBAAgB,WAAW,CAAC,CAAC,SAAS;IAAE,SAAS,EAAE,MAAM,CAAA;CAAE,EACzD,SAAS,EAAE,MAAM,EACjB,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,OAAO,EACrB,QAAQ,EAAE,UAAU,CAAC,MAAM,CAAC,aAEF,WAAW,CAAC,CAAC,KAAG,WAAW,MAAM,CAAC,CAY7D;AAED,wBAAgB,eAAe,IAAI,CAAC,MAAM,EAAE,UAAU,CAAC,MAAM,CAAC,KAAK,UAAU,CAAC,MAAM,CAAC,CAwBpF"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"candle.d.ts","sourceRoot":"","sources":["../../src/domain/candle.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAE/C,qBAAa,MAAM;IAER,SAAS,EAAE,SAAS;IACpB,IAAI,EAAE,OAAO;IACb,IAAI,EAAE,OAAO;IACb,GAAG,EAAE,OAAO;IACZ,KAAK,EAAE,OAAO;IACd,MAAM,CAAC;gBALP,SAAS,EAAE,SAAS,EACpB,IAAI,EAAE,OAAO,EACb,IAAI,EAAE,OAAO,EACb,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,OAAO,EACd,MAAM,CAAC,qBAAS;IAGzB,KAAK,CAAC,KAAK,EAAE,OAAO;CAKrB"}
|
package/dist/strategy.d.ts
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { Observable } from 'rxjs';
|
|
2
|
-
import { Session, SessionBuilder, SessionFeature } from './domain';
|
|
3
|
-
export declare type SessionAction = (session: Session) => Observable<any>;
|
|
4
|
-
export declare let rule: (name: string | undefined, describe: SessionAction) => void;
|
|
5
|
-
export declare let beforeAll: (describe: SessionAction) => void;
|
|
6
|
-
export declare function describe(name: string, describe: () => Array<SessionFeature>): void;
|
|
7
|
-
export declare function prepare(name: string, builder: SessionBuilder): Promise<(session: Session) => Observable<any[]>>;
|
|
8
|
-
//# sourceMappingURL=strategy.d.ts.map
|
package/dist/strategy.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"strategy.d.ts","sourceRoot":"","sources":["../src/strategy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,UAAU,EAAa,MAAM,MAAM,CAAC;AAEjE,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAKnE,oBAAY,aAAa,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,UAAU,CAAC,GAAG,CAAC,CAAC;AAElE,eAAO,IAAI,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,EAAE,QAAQ,EAAE,aAAa,KAAK,IAAI,CAAC;AAC7E,eAAO,IAAI,SAAS,EAAE,CAAC,QAAQ,EAAE,aAAa,KAAK,IAAI,CAAC;AAExD,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,CAAC,cAAc,CAAC,QAE3E;AAED,wBAAsB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,qBAqBhD,OAAO,wBASzB"}
|
package/dist/strategy.js
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.prepare = exports.describe = exports.beforeAll = exports.rule = void 0;
|
|
13
|
-
const rxjs_1 = require("rxjs");
|
|
14
|
-
const shared_1 = require("./shared");
|
|
15
|
-
const registry = {};
|
|
16
|
-
function describe(name, describe) {
|
|
17
|
-
registry[name] = describe;
|
|
18
|
-
}
|
|
19
|
-
exports.describe = describe;
|
|
20
|
-
function prepare(name, builder) {
|
|
21
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
22
|
-
const describe = registry[name];
|
|
23
|
-
const rules = new Array();
|
|
24
|
-
const beforeAlls = new Array();
|
|
25
|
-
exports.beforeAll = (describe) => {
|
|
26
|
-
beforeAlls.push(describe);
|
|
27
|
-
};
|
|
28
|
-
exports.rule = (ruleName, describe) => {
|
|
29
|
-
if (ruleName) {
|
|
30
|
-
shared_1.Logger.info(name, ruleName);
|
|
31
|
-
}
|
|
32
|
-
rules.push(describe);
|
|
33
|
-
};
|
|
34
|
-
for (const plugin of describe()) {
|
|
35
|
-
plugin(builder);
|
|
36
|
-
}
|
|
37
|
-
return (session) => {
|
|
38
|
-
const toBeforeAll = beforeAlls.map(it => it(session));
|
|
39
|
-
const toRules = rules.map(it => it(session));
|
|
40
|
-
return (0, rxjs_1.forkJoin)(toBeforeAll).pipe((0, rxjs_1.switchMap)(() => (0, rxjs_1.forkJoin)(toRules)), (0, rxjs_1.finalize)(() => session.dispose()));
|
|
41
|
-
};
|
|
42
|
-
});
|
|
43
|
-
}
|
|
44
|
-
exports.prepare = prepare;
|
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
import { from } from 'rxjs';
|
|
2
|
-
|
|
3
|
-
import { d } from '../shared';
|
|
4
|
-
import { Candle } from './candle';
|
|
5
|
-
import { candle, candleCompleted, mergeCandle } from './candle-operator';
|
|
6
|
-
|
|
7
|
-
describe('candle', () => {
|
|
8
|
-
test('should aggregate and pipe candle updates', done => {
|
|
9
|
-
const input$ = from([
|
|
10
|
-
{ timestamp: 1, rate: d(1) },
|
|
11
|
-
{ timestamp: 2, rate: d(2) },
|
|
12
|
-
{ timestamp: 3, rate: d(3) },
|
|
13
|
-
{ timestamp: 4, rate: d.Zero },
|
|
14
|
-
{ timestamp: 5, rate: d(7) },
|
|
15
|
-
{ timestamp: 6, rate: d(8) }
|
|
16
|
-
]);
|
|
17
|
-
|
|
18
|
-
const output = [
|
|
19
|
-
new Candle(0, d(1), d(1), d(1), d(1)),
|
|
20
|
-
new Candle(0, d(1), d(2), d(1), d(2)),
|
|
21
|
-
new Candle(0, d(1), d(3), d(1), d(3)),
|
|
22
|
-
new Candle(0, d(1), d(3), d.Zero, d.Zero),
|
|
23
|
-
new Candle(5, d.Zero, d(7), d(7), d(7)),
|
|
24
|
-
new Candle(5, d.Zero, d(8), d(7), d(8))
|
|
25
|
-
].reverse();
|
|
26
|
-
|
|
27
|
-
input$.pipe(candle(5, it => it.rate)).subscribe({
|
|
28
|
-
next: it => {
|
|
29
|
-
expect(it).toEqual(output.pop());
|
|
30
|
-
if (output.length === 0) {
|
|
31
|
-
done();
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
});
|
|
35
|
-
});
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
describe('candleCompleted', () => {
|
|
39
|
-
test('should aggregate and pipe distinct completed candles', done => {
|
|
40
|
-
const input$ = from([
|
|
41
|
-
{ timestamp: 1, rate: d(1) },
|
|
42
|
-
{ timestamp: 2, rate: d(2) },
|
|
43
|
-
{ timestamp: 3, rate: d(3) },
|
|
44
|
-
{ timestamp: 4, rate: d.Zero },
|
|
45
|
-
{ timestamp: 5, rate: d(7) },
|
|
46
|
-
{ timestamp: 6, rate: d(8) }
|
|
47
|
-
]);
|
|
48
|
-
|
|
49
|
-
input$
|
|
50
|
-
.pipe(
|
|
51
|
-
candle(5, it => it.rate),
|
|
52
|
-
candleCompleted()
|
|
53
|
-
)
|
|
54
|
-
.subscribe({
|
|
55
|
-
next: it => {
|
|
56
|
-
expect(it).toEqual(new Candle(0, d(1), d(3), d.Zero, d.Zero));
|
|
57
|
-
done();
|
|
58
|
-
}
|
|
59
|
-
});
|
|
60
|
-
});
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
describe('mergeCandle', () => {
|
|
64
|
-
test('should pipe and merge candle from history', done => {
|
|
65
|
-
const history$ = from([
|
|
66
|
-
new Candle(1, d(1), d(1.5), d(0.5), d(2)),
|
|
67
|
-
new Candle(2, d(2), d(2.5), d(1.5), d(3)),
|
|
68
|
-
new Candle(3, d(3), d(3.5), d(2.5), d(4))
|
|
69
|
-
]);
|
|
70
|
-
|
|
71
|
-
const input$ = from([
|
|
72
|
-
{ timestamp: 3, rate: d(5) },
|
|
73
|
-
{ timestamp: 4, rate: d(3) },
|
|
74
|
-
{ timestamp: 5, rate: d(4) }
|
|
75
|
-
]);
|
|
76
|
-
|
|
77
|
-
const output = [
|
|
78
|
-
new Candle(1, d(1), d(1.5), d(0.5), d(2)),
|
|
79
|
-
new Candle(2, d(2), d(2.5), d(1.5), d(3)),
|
|
80
|
-
new Candle(3, d(3), d(5), d(2.5), d(5)),
|
|
81
|
-
new Candle(4, d(5), d(3), d(3), d(3)),
|
|
82
|
-
new Candle(5, d(3), d(4), d(4), d(4))
|
|
83
|
-
].reverse();
|
|
84
|
-
|
|
85
|
-
input$.pipe(mergeCandle(1, it => it.rate, history$)).subscribe({
|
|
86
|
-
next: it => {
|
|
87
|
-
expect(it).toEqual(output.pop());
|
|
88
|
-
if (output.length === 0) {
|
|
89
|
-
done();
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
});
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
test('should pipe and not merge candle from history', done => {
|
|
96
|
-
const history$ = from([
|
|
97
|
-
new Candle(1, d(1), d(1.5), d(0.5), d(2)),
|
|
98
|
-
new Candle(2, d(2), d(2.5), d(1.5), d(3)),
|
|
99
|
-
new Candle(3, d(3), d(3.5), d(2.5), d(4))
|
|
100
|
-
]);
|
|
101
|
-
|
|
102
|
-
const input$ = from([
|
|
103
|
-
{ timestamp: 4, rate: d(5) },
|
|
104
|
-
{ timestamp: 5, rate: d(3) },
|
|
105
|
-
{ timestamp: 6, rate: d(4) }
|
|
106
|
-
]);
|
|
107
|
-
|
|
108
|
-
const output = [
|
|
109
|
-
new Candle(1, d(1), d(1.5), d(0.5), d(2)),
|
|
110
|
-
new Candle(2, d(2), d(2.5), d(1.5), d(3)),
|
|
111
|
-
new Candle(3, d(3), d(3.5), d(2.5), d(4)),
|
|
112
|
-
new Candle(4, d(4), d(5), d(5), d(5)),
|
|
113
|
-
new Candle(5, d(5), d(3), d(3), d(3)),
|
|
114
|
-
new Candle(6, d(3), d(4), d(4), d(4))
|
|
115
|
-
].reverse();
|
|
116
|
-
|
|
117
|
-
input$.pipe(mergeCandle(1, it => it.rate, history$)).subscribe({
|
|
118
|
-
next: it => {
|
|
119
|
-
expect(it).toEqual(output.pop());
|
|
120
|
-
if (output.length === 0) {
|
|
121
|
-
done();
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
});
|
|
125
|
-
});
|
|
126
|
-
});
|
package/src/strategy.ts
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import { finalize, forkJoin, Observable, switchMap } from 'rxjs';
|
|
2
|
-
|
|
3
|
-
import { Session, SessionBuilder, SessionFeature } from './domain';
|
|
4
|
-
import { Logger } from './shared';
|
|
5
|
-
|
|
6
|
-
const registry: Record<string, () => Array<SessionFeature>> = {};
|
|
7
|
-
|
|
8
|
-
export type SessionAction = (session: Session) => Observable<any>;
|
|
9
|
-
|
|
10
|
-
export let rule: (name: string | undefined, describe: SessionAction) => void;
|
|
11
|
-
export let beforeAll: (describe: SessionAction) => void;
|
|
12
|
-
|
|
13
|
-
export function describe(name: string, describe: () => Array<SessionFeature>) {
|
|
14
|
-
registry[name] = describe;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export async function prepare(name: string, builder: SessionBuilder) {
|
|
18
|
-
const describe = registry[name];
|
|
19
|
-
const rules = new Array<SessionAction>();
|
|
20
|
-
const beforeAlls = new Array<SessionAction>();
|
|
21
|
-
|
|
22
|
-
beforeAll = (describe: SessionAction) => {
|
|
23
|
-
beforeAlls.push(describe);
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
rule = (ruleName: string | undefined, describe: SessionAction) => {
|
|
27
|
-
if (ruleName) {
|
|
28
|
-
Logger.info(name, ruleName);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
rules.push(describe);
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
for (const plugin of describe()) {
|
|
35
|
-
plugin(builder);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
return (session: Session) => {
|
|
39
|
-
const toBeforeAll = beforeAlls.map(it => it(session));
|
|
40
|
-
const toRules = rules.map(it => it(session));
|
|
41
|
-
|
|
42
|
-
return forkJoin(toBeforeAll).pipe(
|
|
43
|
-
switchMap(() => forkJoin(toRules)),
|
|
44
|
-
finalize(() => session.dispose())
|
|
45
|
-
);
|
|
46
|
-
};
|
|
47
|
-
}
|