@quantform/core 0.7.0-beta.48 → 0.7.0-beta.49
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/cli/internal/script.d.ts +2 -2
- package/dist/cli/internal/script.d.ts.map +1 -1
- package/dist/cli/internal/script.js +9 -6
- package/dist/replay/index.d.ts +2 -2
- package/dist/replay/index.d.ts.map +1 -1
- package/dist/replay/index.js +2 -2
- package/dist/replay/{use-replay-storage-buffer.d.ts → storage/use-replay-storage-buffer.d.ts} +2 -2
- package/dist/replay/storage/use-replay-storage-buffer.d.ts.map +1 -0
- package/dist/replay/{use-replay-storage-buffer.js → storage/use-replay-storage-buffer.js} +10 -4
- package/dist/replay/storage/use-replay-storage-cursor.d.ts +30 -0
- package/dist/replay/storage/use-replay-storage-cursor.d.ts.map +1 -0
- package/dist/replay/storage/use-replay-storage-cursor.js +49 -0
- package/dist/replay/{use-replay-storage.d.ts → storage/use-replay-storage.d.ts} +2 -2
- package/dist/replay/storage/use-replay-storage.d.ts.map +1 -0
- package/dist/replay/{use-replay-storage.js → storage/use-replay-storage.js} +2 -2
- package/dist/replay/storage/use-replay-storage.spec.d.ts.map +1 -0
- package/dist/replay/{use-replay-storage.spec.js → storage/use-replay-storage.spec.js} +2 -2
- package/dist/replay/use-replay-breakpoint.js +3 -3
- package/dist/replay/use-replay-manager.d.ts +2 -2
- package/dist/replay/use-replay-manager.d.ts.map +1 -1
- package/dist/replay/use-replay-manager.js +9 -30
- package/dist/replay/use-replay.js +3 -3
- package/dist/shared/decimals.d.ts +0 -16
- package/dist/shared/decimals.d.ts.map +1 -1
- package/dist/shared/decimals.js +1 -44
- package/dist/strategy.d.ts.map +1 -1
- package/dist/strategy.js +7 -0
- package/dist/use-execution-mode.js +7 -7
- package/dist/use-socket.d.ts +19 -0
- package/dist/use-socket.d.ts.map +1 -0
- package/dist/use-socket.js +69 -0
- package/package.json +1 -1
- package/src/cli/internal/script.ts +14 -7
- package/src/replay/index.ts +2 -2
- package/src/replay/{use-replay-storage-buffer.ts → storage/use-replay-storage-buffer.ts} +9 -2
- package/src/replay/storage/use-replay-storage-cursor.ts +44 -0
- package/src/replay/{use-replay-storage.spec.ts → storage/use-replay-storage.spec.ts} +0 -1
- package/src/replay/use-replay-breakpoint.ts +3 -3
- package/src/replay/use-replay-manager.ts +11 -35
- package/src/replay/use-replay.ts +3 -3
- package/src/shared/decimals.ts +0 -45
- package/src/strategy.ts +9 -1
- package/src/use-execution-mode.ts +7 -7
- package/src/use-socket.ts +78 -0
- package/dist/replay/use-replay-storage-buffer.d.ts.map +0 -1
- package/dist/replay/use-replay-storage.d.ts.map +0 -1
- package/dist/replay/use-replay-storage.spec.d.ts.map +0 -1
- /package/dist/replay/{use-replay-storage.spec.d.ts → storage/use-replay-storage.spec.d.ts} +0 -0
- /package/src/replay/{use-replay-storage.ts → storage/use-replay-storage.ts} +0 -0
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Dependency } from '../../module';
|
|
2
2
|
export declare class Script {
|
|
3
|
-
private readonly
|
|
3
|
+
private readonly filename;
|
|
4
4
|
private readonly dependencies;
|
|
5
|
-
constructor(
|
|
5
|
+
constructor(filename: string, dependencies: Dependency[]);
|
|
6
6
|
run(): Promise<unknown[]>;
|
|
7
7
|
}
|
|
8
8
|
//# sourceMappingURL=script.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"script.d.ts","sourceRoot":"","sources":["../../../src/cli/internal/script.ts"],"names":[],"mappings":"AAeA,OAAO,EAAE,UAAU,EAAU,MAAM,aAAa,CAAC;AAMjD,qBAAa,MAAM;IAEf,OAAO,CAAC,QAAQ,CAAC,
|
|
1
|
+
{"version":3,"file":"script.d.ts","sourceRoot":"","sources":["../../../src/cli/internal/script.ts"],"names":[],"mappings":"AAeA,OAAO,EAAE,UAAU,EAAU,MAAM,aAAa,CAAC;AAMjD,qBAAa,MAAM;IAEf,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,YAAY;gBADZ,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,UAAU,EAAE;IAGvC,GAAG;CA0CV"}
|
|
@@ -40,21 +40,24 @@ const module_1 = require("../../module");
|
|
|
40
40
|
const replay_1 = require("../../replay");
|
|
41
41
|
const workspace_1 = require("./workspace");
|
|
42
42
|
class Script {
|
|
43
|
-
constructor(
|
|
44
|
-
this.
|
|
43
|
+
constructor(filename, dependencies) {
|
|
44
|
+
this.filename = filename;
|
|
45
45
|
this.dependencies = dependencies;
|
|
46
46
|
}
|
|
47
47
|
run() {
|
|
48
48
|
return __awaiter(this, void 0, void 0, function* () {
|
|
49
|
-
const script = yield Promise.resolve(`${(0, path_1.join)((0, workspace_1.buildDirectory)(), this.
|
|
49
|
+
const script = yield Promise.resolve(`${(0, path_1.join)((0, workspace_1.buildDirectory)(), this.filename)}`).then(s => __importStar(require(s)));
|
|
50
50
|
const { dependencies, description } = script.default;
|
|
51
51
|
const module = new module_1.Module([...(0, core_1.core)(), ...dependencies, ...this.dependencies]);
|
|
52
52
|
const { act } = yield module.awake();
|
|
53
53
|
return yield act(() => {
|
|
54
54
|
process.stdin.resume();
|
|
55
|
-
return (0, rxjs_1.firstValueFrom)((0, rxjs_1.merge)((0, rxjs_1.forkJoin)(description.before.map(
|
|
56
|
-
.pipe((0, rxjs_1.switchMap)(() => (0, rxjs_1.forkJoin)(description.behavior.map(
|
|
57
|
-
.pipe((0, rxjs_1.last)()), (0, replay_1.whenReplayFinished)().pipe((0, rxjs_1.last)()), (0, rxjs_1.fromEvent)(process, 'exit'), (0, rxjs_1.fromEvent)(process, 'SIGINT'), (0, rxjs_1.fromEvent)(process, 'SIGUSR1'), (0, rxjs_1.fromEvent)(process, 'SIGUSR2'), (0, rxjs_1.fromEvent)(process, 'uncaughtException')).pipe((0, rxjs_1.
|
|
55
|
+
return (0, rxjs_1.firstValueFrom)((0, rxjs_1.merge)((0, rxjs_1.forkJoin)(description.before.map(before => before()))
|
|
56
|
+
.pipe((0, rxjs_1.switchMap)(() => (0, rxjs_1.forkJoin)(description.behavior.map(behavior => behavior())).pipe((0, rxjs_1.last)())))
|
|
57
|
+
.pipe((0, rxjs_1.last)()), (0, replay_1.whenReplayFinished)().pipe((0, rxjs_1.last)()), (0, rxjs_1.fromEvent)(process, 'exit'), (0, rxjs_1.fromEvent)(process, 'SIGINT'), (0, rxjs_1.fromEvent)(process, 'SIGUSR1'), (0, rxjs_1.fromEvent)(process, 'SIGUSR2'), (0, rxjs_1.fromEvent)(process, 'uncaughtException')).pipe((0, rxjs_1.catchError)(e => {
|
|
58
|
+
console.error(e);
|
|
59
|
+
return (0, rxjs_1.of)(e);
|
|
60
|
+
}), (0, rxjs_1.take)(1), (0, rxjs_1.switchMap)(it => { var _a; return (_a = (0, rxjs_1.forkJoin)(description.after.map(after => after())).pipe((0, rxjs_1.last)())) !== null && _a !== void 0 ? _a : (0, rxjs_1.of)(it); }), (0, rxjs_1.finalize)(() => process.exit(0))));
|
|
58
61
|
});
|
|
59
62
|
});
|
|
60
63
|
}
|
package/dist/replay/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
export * from './use-replay';
|
|
2
2
|
export * from './use-replay-breakpoint';
|
|
3
3
|
export * from './use-replay-options';
|
|
4
|
-
export * from './use-replay-storage';
|
|
5
|
-
export * from './use-replay-storage-buffer';
|
|
4
|
+
export * from './storage/use-replay-storage';
|
|
5
|
+
export * from './storage/use-replay-storage-buffer';
|
|
6
6
|
export * from './use-replay-manager';
|
|
7
7
|
export * from './when-replay-finished';
|
|
8
8
|
export * from './replay';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/replay/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,yBAAyB,CAAC;AACxC,cAAc,sBAAsB,CAAC;AACrC,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/replay/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,yBAAyB,CAAC;AACxC,cAAc,sBAAsB,CAAC;AACrC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,qCAAqC,CAAC;AACpD,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,UAAU,CAAC;AACzB,cAAc,gBAAgB,CAAC"}
|
package/dist/replay/index.js
CHANGED
|
@@ -17,8 +17,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
17
17
|
__exportStar(require("./use-replay"), exports);
|
|
18
18
|
__exportStar(require("./use-replay-breakpoint"), exports);
|
|
19
19
|
__exportStar(require("./use-replay-options"), exports);
|
|
20
|
-
__exportStar(require("./use-replay-storage"), exports);
|
|
21
|
-
__exportStar(require("./use-replay-storage-buffer"), exports);
|
|
20
|
+
__exportStar(require("./storage/use-replay-storage"), exports);
|
|
21
|
+
__exportStar(require("./storage/use-replay-storage-buffer"), exports);
|
|
22
22
|
__exportStar(require("./use-replay-manager"), exports);
|
|
23
23
|
__exportStar(require("./when-replay-finished"), exports);
|
|
24
24
|
__exportStar(require("./replay"), exports);
|
package/dist/replay/{use-replay-storage-buffer.d.ts → storage/use-replay-storage-buffer.d.ts}
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { dependency } from '
|
|
1
|
+
import { dependency } from '../../use-hash';
|
|
2
2
|
export declare const useReplayStorageBuffer: <T>(dependencies: dependency[]) => {
|
|
3
3
|
size(): number;
|
|
4
4
|
peek(): {
|
|
@@ -10,6 +10,6 @@ export declare const useReplayStorageBuffer: <T>(dependencies: dependency[]) =>
|
|
|
10
10
|
payload: T;
|
|
11
11
|
};
|
|
12
12
|
completed(): boolean;
|
|
13
|
-
fetchNextPage(
|
|
13
|
+
fetchNextPage(): Promise<void>;
|
|
14
14
|
};
|
|
15
15
|
//# sourceMappingURL=use-replay-storage-buffer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-replay-storage-buffer.d.ts","sourceRoot":"","sources":["../../../src/replay/storage/use-replay-storage-buffer.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAK3C,eAAO,MAAM,sBAAsB;;;mBAIC,MAAM;;;;mBAAN,MAAM;;;;;CAsCxC,CAAC"}
|
|
@@ -10,14 +10,17 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.useReplayStorageBuffer = void 0;
|
|
13
|
-
const
|
|
14
|
-
const
|
|
13
|
+
const use_replay_options_1 = require("../../replay/use-replay-options");
|
|
14
|
+
const storage_1 = require("../../storage");
|
|
15
|
+
const with_memo_1 = require("../../with-memo");
|
|
15
16
|
const use_replay_storage_1 = require("./use-replay-storage");
|
|
16
17
|
exports.useReplayStorageBuffer = (0, with_memo_1.withMemo)((dependencies) => {
|
|
17
18
|
const { query } = (0, use_replay_storage_1.useReplayStorage)(dependencies);
|
|
19
|
+
const { from, to } = (0, use_replay_options_1.useReplayOptions)();
|
|
18
20
|
let page = new Array();
|
|
19
21
|
let index = 0;
|
|
20
22
|
let completed = false;
|
|
23
|
+
let count = 0;
|
|
21
24
|
return {
|
|
22
25
|
size() {
|
|
23
26
|
return page.length - index;
|
|
@@ -31,7 +34,7 @@ exports.useReplayStorageBuffer = (0, with_memo_1.withMemo)((dependencies) => {
|
|
|
31
34
|
completed() {
|
|
32
35
|
return completed;
|
|
33
36
|
},
|
|
34
|
-
fetchNextPage(
|
|
37
|
+
fetchNextPage() {
|
|
35
38
|
return __awaiter(this, void 0, void 0, function* () {
|
|
36
39
|
if (completed) {
|
|
37
40
|
return;
|
|
@@ -41,8 +44,11 @@ exports.useReplayStorageBuffer = (0, with_memo_1.withMemo)((dependencies) => {
|
|
|
41
44
|
where: {
|
|
42
45
|
timestamp: (0, storage_1.between)(from, to)
|
|
43
46
|
},
|
|
44
|
-
limit: 10000
|
|
47
|
+
limit: 10000,
|
|
48
|
+
offset: count,
|
|
49
|
+
orderBy: 'ASC'
|
|
45
50
|
});
|
|
51
|
+
count += page.length;
|
|
46
52
|
completed = page.length == 0;
|
|
47
53
|
});
|
|
48
54
|
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { dependency } from '../../use-hash';
|
|
2
|
+
export declare const useReplayStorageCursor: () => {
|
|
3
|
+
get<T>(dependencies: dependency[]): {
|
|
4
|
+
size(): number;
|
|
5
|
+
peek(): {
|
|
6
|
+
timestamp: number;
|
|
7
|
+
payload: T;
|
|
8
|
+
};
|
|
9
|
+
dequeue(): {
|
|
10
|
+
timestamp: number;
|
|
11
|
+
payload: T;
|
|
12
|
+
};
|
|
13
|
+
completed(): boolean;
|
|
14
|
+
fetchNextPage(): Promise<void>;
|
|
15
|
+
};
|
|
16
|
+
cursor(): Promise<{
|
|
17
|
+
size(): number;
|
|
18
|
+
peek(): {
|
|
19
|
+
timestamp: number;
|
|
20
|
+
payload: any;
|
|
21
|
+
};
|
|
22
|
+
dequeue(): {
|
|
23
|
+
timestamp: number;
|
|
24
|
+
payload: any;
|
|
25
|
+
};
|
|
26
|
+
completed(): boolean;
|
|
27
|
+
fetchNextPage(): Promise<void>;
|
|
28
|
+
} | undefined>;
|
|
29
|
+
};
|
|
30
|
+
//# sourceMappingURL=use-replay-storage-cursor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-replay-storage-cursor.d.ts","sourceRoot":"","sources":["../../../src/replay/storage/use-replay-storage-cursor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAW,MAAM,eAAe,CAAC;AAMpD,eAAO,MAAM,sBAAsB;yBAKV,UAAU,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;CAgCnC,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
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.useReplayStorageCursor = void 0;
|
|
13
|
+
const use_hash_1 = require("../../use-hash");
|
|
14
|
+
const use_logger_1 = require("../../use-logger");
|
|
15
|
+
const with_memo_1 = require("../../with-memo");
|
|
16
|
+
const use_replay_storage_buffer_1 = require("./use-replay-storage-buffer");
|
|
17
|
+
exports.useReplayStorageCursor = (0, with_memo_1.withMemo)(() => {
|
|
18
|
+
const { info } = (0, use_logger_1.useLogger)('useReplayStorageCursor');
|
|
19
|
+
const storages = Array.of();
|
|
20
|
+
return {
|
|
21
|
+
get(dependencies) {
|
|
22
|
+
const storage = (0, use_replay_storage_buffer_1.useReplayStorageBuffer)(dependencies);
|
|
23
|
+
if (!storages.includes(storage)) {
|
|
24
|
+
info('opening a new replay buffer', (0, use_hash_1.useHash)(dependencies));
|
|
25
|
+
storages.push(storage);
|
|
26
|
+
}
|
|
27
|
+
return storage;
|
|
28
|
+
},
|
|
29
|
+
cursor() {
|
|
30
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
31
|
+
let current;
|
|
32
|
+
for (const storage of storages) {
|
|
33
|
+
if (storage.completed()) {
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
if (storage.size() == 0) {
|
|
37
|
+
yield storage.fetchNextPage();
|
|
38
|
+
}
|
|
39
|
+
if (storage.peek()) {
|
|
40
|
+
if (!current || current.peek().timestamp > storage.peek().timestamp) {
|
|
41
|
+
current = storage;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return current;
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Query, QueryObject } from '
|
|
2
|
-
import { dependency } from '
|
|
1
|
+
import { Query, QueryObject } from '../../storage';
|
|
2
|
+
import { dependency } from '../../use-hash';
|
|
3
3
|
export declare function useReplayStorage<T>(dependencies: dependency[]): {
|
|
4
4
|
query(query: Query<QueryObject>): Promise<{
|
|
5
5
|
timestamp: number;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-replay-storage.d.ts","sourceRoot":"","sources":["../../../src/replay/storage/use-replay-storage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,WAAW,EAAuB,MAAM,cAAc,CAAC;AACvE,OAAO,EAAE,UAAU,EAAW,MAAM,eAAe,CAAC;AAEpD,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,YAAY,EAAE,UAAU,EAAE;iBASvC,MAAM,WAAW,CAAC;;;;kBAMvB;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,CAAC,CAAA;KAAE,EAAE;EAUpD"}
|
|
@@ -10,8 +10,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.useReplayStorage = void 0;
|
|
13
|
-
const storage_1 = require("
|
|
14
|
-
const use_hash_1 = require("
|
|
13
|
+
const storage_1 = require("../../storage");
|
|
14
|
+
const use_hash_1 = require("../../use-hash");
|
|
15
15
|
function useReplayStorage(dependencies) {
|
|
16
16
|
const storage = (0, storage_1.useStorage)(['replay']);
|
|
17
17
|
const storageObjectKey = (0, use_hash_1.useHash)(dependencies);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-replay-storage.spec.d.ts","sourceRoot":"","sources":["../../../src/replay/storage/use-replay-storage.spec.ts"],"names":[],"mappings":""}
|
|
@@ -9,8 +9,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
const make_test_module_1 = require("
|
|
13
|
-
const storage_1 = require("
|
|
12
|
+
const make_test_module_1 = require("../../make-test-module");
|
|
13
|
+
const storage_1 = require("../../storage");
|
|
14
14
|
const use_replay_storage_1 = require("./use-replay-storage");
|
|
15
15
|
jest.mock('@lib/storage', () => (Object.assign(Object.assign({}, jest.requireActual('@lib/storage')), { useStorage: jest.fn() })));
|
|
16
16
|
describe(use_replay_storage_1.useReplayStorage.name, () => {
|
|
@@ -10,12 +10,12 @@ function useReplayBreakpoint(input) {
|
|
|
10
10
|
if (!isReplay) {
|
|
11
11
|
return input;
|
|
12
12
|
}
|
|
13
|
-
const { info } = (0, use_logger_1.useLogger)('
|
|
13
|
+
const { info } = (0, use_logger_1.useLogger)('replay');
|
|
14
14
|
const { stop, tryContinue } = (0, use_replay_manager_1.useReplayManager)();
|
|
15
|
-
info('
|
|
15
|
+
info('breakpoint acquired');
|
|
16
16
|
stop();
|
|
17
17
|
return input.pipe((0, rxjs_1.finalize)(() => {
|
|
18
|
-
info('
|
|
18
|
+
info('breakpoint released');
|
|
19
19
|
tryContinue();
|
|
20
20
|
}));
|
|
21
21
|
}
|
|
@@ -12,7 +12,7 @@ export declare const useReplayManager: () => {
|
|
|
12
12
|
payload: any;
|
|
13
13
|
};
|
|
14
14
|
completed(): boolean;
|
|
15
|
-
fetchNextPage(
|
|
15
|
+
fetchNextPage(): Promise<void>;
|
|
16
16
|
}, {
|
|
17
17
|
timestamp: number;
|
|
18
18
|
payload: any;
|
|
@@ -20,7 +20,7 @@ export declare const useReplayManager: () => {
|
|
|
20
20
|
timestamp(): number;
|
|
21
21
|
stop(): void;
|
|
22
22
|
tryContinue: () => void;
|
|
23
|
-
|
|
23
|
+
watch<T>(dependencies: dependency[]): Observable<{
|
|
24
24
|
timestamp: number;
|
|
25
25
|
payload: T;
|
|
26
26
|
}>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-replay-manager.d.ts","sourceRoot":"","sources":["../../src/replay/use-replay-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,UAAU,EAAW,MAAM,MAAM,CAAC;AAE/D,OAAO,EAAE,UAAU,
|
|
1
|
+
{"version":3,"file":"use-replay-manager.d.ts","sourceRoot":"","sources":["../../src/replay/use-replay-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,UAAU,EAAW,MAAM,MAAM,CAAC;AAE/D,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAO3C,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;mBAQqC,MAAM;iBAAW,GAAG;;;;;2BAoD3D,UAAU,EAAE;mBAA2B,MAAM;;;CAatE,CAAC"}
|
|
@@ -11,41 +11,24 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.useReplayManager = void 0;
|
|
13
13
|
const rxjs_1 = require("rxjs");
|
|
14
|
-
const use_hash_1 = require("../use-hash");
|
|
15
|
-
const use_logger_1 = require("../use-logger");
|
|
16
14
|
const with_memo_1 = require("../with-memo");
|
|
15
|
+
const use_replay_storage_cursor_1 = require("./storage/use-replay-storage-cursor");
|
|
17
16
|
const use_replay_options_1 = require("./use-replay-options");
|
|
18
|
-
const use_replay_storage_buffer_1 = require("./use-replay-storage-buffer");
|
|
19
17
|
exports.useReplayManager = (0, with_memo_1.withMemo)(() => {
|
|
20
|
-
const { from
|
|
21
|
-
const {
|
|
18
|
+
const { from } = (0, use_replay_options_1.useReplayOptions)();
|
|
19
|
+
const { get, cursor } = (0, use_replay_storage_cursor_1.useReplayStorageCursor)();
|
|
22
20
|
let timestamp = from;
|
|
23
21
|
let stopAcquire = 1;
|
|
24
|
-
const subscriptions = Array.of();
|
|
25
22
|
const stream$ = new rxjs_1.Subject();
|
|
26
|
-
const getNextStorage = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
27
|
-
let next;
|
|
28
|
-
for (const cursor of subscriptions) {
|
|
29
|
-
if (cursor.size() == 0 && !cursor.completed()) {
|
|
30
|
-
yield cursor.fetchNextPage(timestamp, to + 1);
|
|
31
|
-
}
|
|
32
|
-
if (cursor.peek()) {
|
|
33
|
-
if (!next || next.peek().timestamp > cursor.peek().timestamp) {
|
|
34
|
-
next = cursor;
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
return next;
|
|
39
|
-
});
|
|
40
23
|
const processNext = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
41
|
-
const
|
|
42
|
-
if (!
|
|
24
|
+
const storage = yield cursor();
|
|
25
|
+
if (!storage || !storage.peek()) {
|
|
43
26
|
stream$.complete();
|
|
44
27
|
return false;
|
|
45
28
|
}
|
|
46
|
-
const sample =
|
|
29
|
+
const sample = storage.dequeue();
|
|
47
30
|
timestamp = sample.timestamp;
|
|
48
|
-
stream$.next([
|
|
31
|
+
stream$.next([storage, sample]);
|
|
49
32
|
return true;
|
|
50
33
|
});
|
|
51
34
|
const next = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
@@ -74,12 +57,8 @@ exports.useReplayManager = (0, with_memo_1.withMemo)(() => {
|
|
|
74
57
|
stopAcquire++;
|
|
75
58
|
},
|
|
76
59
|
tryContinue,
|
|
77
|
-
|
|
78
|
-
const storage = (
|
|
79
|
-
if (!subscriptions.includes(storage)) {
|
|
80
|
-
info('subscribing to replay', (0, use_hash_1.useHash)(dependencies));
|
|
81
|
-
subscriptions.push(storage);
|
|
82
|
-
}
|
|
60
|
+
watch(dependencies) {
|
|
61
|
+
const storage = get(dependencies);
|
|
83
62
|
return (0, rxjs_1.defer)(() => {
|
|
84
63
|
tryContinue();
|
|
85
64
|
return stream$.pipe((0, rxjs_1.filter)(([cur]) => cur === storage), (0, rxjs_1.map)(([, it]) => ({ timestamp: it.timestamp, payload: it.payload })));
|
|
@@ -3,13 +3,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.useReplay = void 0;
|
|
4
4
|
const rxjs_1 = require("rxjs");
|
|
5
5
|
const use_execution_mode_1 = require("../use-execution-mode");
|
|
6
|
+
const use_replay_storage_1 = require("./storage/use-replay-storage");
|
|
6
7
|
const use_replay_manager_1 = require("./use-replay-manager");
|
|
7
|
-
const use_replay_storage_1 = require("./use-replay-storage");
|
|
8
8
|
function useReplay(input, dependencies) {
|
|
9
9
|
const { isReplay, recording } = (0, use_execution_mode_1.useExecutionMode)();
|
|
10
10
|
if (isReplay) {
|
|
11
|
-
const {
|
|
12
|
-
return
|
|
11
|
+
const { watch } = (0, use_replay_manager_1.useReplayManager)();
|
|
12
|
+
return watch(dependencies);
|
|
13
13
|
}
|
|
14
14
|
if (recording) {
|
|
15
15
|
const { save } = (0, use_replay_storage_1.useReplayStorage)(dependencies);
|
|
@@ -11,20 +11,4 @@ export declare function d(value: Decimal.Value): decimal;
|
|
|
11
11
|
export declare namespace d {
|
|
12
12
|
var Zero: decimal;
|
|
13
13
|
}
|
|
14
|
-
export declare function weightedMean(values: decimal[], weights: decimal[]): decimal;
|
|
15
|
-
export declare function pnl(entryRate: decimal, exitRate: decimal, amount: decimal): Decimal;
|
|
16
|
-
/**
|
|
17
|
-
*
|
|
18
|
-
* @param timestamp
|
|
19
|
-
* @param timeframe
|
|
20
|
-
* @returns nearest timestamp to the given timeframe
|
|
21
|
-
*/
|
|
22
|
-
export declare function candledown(timestamp: number, timeframe: number): number;
|
|
23
|
-
/**
|
|
24
|
-
*
|
|
25
|
-
* @param timestamp
|
|
26
|
-
* @param timeframe
|
|
27
|
-
* @returns nearest timestamp to the given timeframe
|
|
28
|
-
*/
|
|
29
|
-
export declare function candleup(timestamp: number, timeframe: number): number;
|
|
30
14
|
//# sourceMappingURL=decimals.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"decimals.d.ts","sourceRoot":"","sources":["../../src/shared/decimals.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAErC,OAAO,QAAQ,YAAY,CAAC;IAC1B,UAAU,OAAO;QACf,OAAO,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC;QACxC,MAAM,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC;KACxC;CACF;AAUD,qBAAa,OAAQ,SAAQ,OAAO;CAAG;
|
|
1
|
+
{"version":3,"file":"decimals.d.ts","sourceRoot":"","sources":["../../src/shared/decimals.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAErC,OAAO,QAAQ,YAAY,CAAC;IAC1B,UAAU,OAAO;QACf,OAAO,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC;QACxC,MAAM,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC;KACxC;CACF;AAUD,qBAAa,OAAQ,SAAQ,OAAO;CAAG;AAEvC,wBAAgB,CAAC,CAAC,KAAK,EAAE,OAAO,CAAC,KAAK,WAErC;yBAFe,CAAC"}
|
package/dist/shared/decimals.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.d = exports.decimal = void 0;
|
|
4
4
|
const decimal_js_1 = require("decimal.js");
|
|
5
5
|
decimal_js_1.Decimal.prototype.toFloor = function (decimalPlaces) {
|
|
6
6
|
return this.toDecimalPlaces(decimalPlaces, decimal_js_1.Decimal.ROUND_FLOOR);
|
|
@@ -11,51 +11,8 @@ decimal_js_1.Decimal.prototype.toCeil = function (decimalPlaces) {
|
|
|
11
11
|
class decimal extends decimal_js_1.Decimal {
|
|
12
12
|
}
|
|
13
13
|
exports.decimal = decimal;
|
|
14
|
-
/*
|
|
15
|
-
decimal.prototype.toJSON = function () {
|
|
16
|
-
return '444';
|
|
17
|
-
};
|
|
18
|
-
*/
|
|
19
14
|
function d(value) {
|
|
20
15
|
return new decimal(value);
|
|
21
16
|
}
|
|
22
17
|
exports.d = d;
|
|
23
18
|
d.Zero = new decimal(0);
|
|
24
|
-
function weightedMean(values, weights) {
|
|
25
|
-
const result = values
|
|
26
|
-
.map((value, i) => {
|
|
27
|
-
const weight = weights[i];
|
|
28
|
-
const sum = value.mul(weight);
|
|
29
|
-
return [sum, weight];
|
|
30
|
-
})
|
|
31
|
-
.reduce((p, c) => [p[0].add(c[0]), p[1].add(c[1])], [d.Zero, d.Zero]);
|
|
32
|
-
if (!result[1]) {
|
|
33
|
-
return d.Zero;
|
|
34
|
-
}
|
|
35
|
-
return result[0].div(result[1]);
|
|
36
|
-
}
|
|
37
|
-
exports.weightedMean = weightedMean;
|
|
38
|
-
function pnl(entryRate, exitRate, amount) {
|
|
39
|
-
return exitRate.div(entryRate).minus(1).mul(amount);
|
|
40
|
-
}
|
|
41
|
-
exports.pnl = pnl;
|
|
42
|
-
/**
|
|
43
|
-
*
|
|
44
|
-
* @param timestamp
|
|
45
|
-
* @param timeframe
|
|
46
|
-
* @returns nearest timestamp to the given timeframe
|
|
47
|
-
*/
|
|
48
|
-
function candledown(timestamp, timeframe) {
|
|
49
|
-
return timestamp - (timestamp % timeframe);
|
|
50
|
-
}
|
|
51
|
-
exports.candledown = candledown;
|
|
52
|
-
/**
|
|
53
|
-
*
|
|
54
|
-
* @param timestamp
|
|
55
|
-
* @param timeframe
|
|
56
|
-
* @returns nearest timestamp to the given timeframe
|
|
57
|
-
*/
|
|
58
|
-
function candleup(timestamp, timeframe) {
|
|
59
|
-
return candledown(timestamp, timeframe) + timeframe;
|
|
60
|
-
}
|
|
61
|
-
exports.candleup = candleup;
|
package/dist/strategy.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"strategy.d.ts","sourceRoot":"","sources":["../src/strategy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,
|
|
1
|
+
{"version":3,"file":"strategy.d.ts","sourceRoot":"","sources":["../src/strategy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAM,MAAM,MAAM,CAAC;AAEtC,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAEtC,MAAM,MAAM,UAAU,GAAG,MAAM,UAAU,CAAC,OAAO,CAAC,CAAC;AAEnD,eAAO,IAAI,MAAM,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,CAAC;AACpD,eAAO,IAAI,QAAQ,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,CAAC;AACtD,eAAO,IAAI,KAAK,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,CAAC;AAEnD,wBAAgB,QAAQ,CAAC,UAAU,EAAE,MAAM,UAAU,EAAE;;;;;;;EAyBtD"}
|
package/dist/strategy.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.strategy = exports.after = exports.behavior = exports.before = void 0;
|
|
4
|
+
const rxjs_1 = require("rxjs");
|
|
4
5
|
function strategy(descriptor) {
|
|
5
6
|
const description = {
|
|
6
7
|
before: Array.of(),
|
|
@@ -11,6 +12,12 @@ function strategy(descriptor) {
|
|
|
11
12
|
exports.behavior = descriptor => description.behavior.push(descriptor);
|
|
12
13
|
exports.after = descriptor => description.after.push(descriptor);
|
|
13
14
|
const dependencies = descriptor();
|
|
15
|
+
if (!description.before.length) {
|
|
16
|
+
description.before.push(() => (0, rxjs_1.of)(true));
|
|
17
|
+
}
|
|
18
|
+
if (!description.after.length) {
|
|
19
|
+
description.after.push(() => (0, rxjs_1.of)(true));
|
|
20
|
+
}
|
|
14
21
|
return {
|
|
15
22
|
dependencies,
|
|
16
23
|
description
|
|
@@ -32,14 +32,14 @@ function idleExecutionMode() {
|
|
|
32
32
|
}
|
|
33
33
|
exports.idleExecutionMode = idleExecutionMode;
|
|
34
34
|
const useExecutionMode = () => {
|
|
35
|
-
const mode = (0, module_1.useContext)(injectionToken);
|
|
35
|
+
const { mode, recording } = (0, module_1.useContext)(injectionToken);
|
|
36
36
|
return {
|
|
37
|
-
isReplay: mode
|
|
38
|
-
isPaper: mode
|
|
39
|
-
isLive: mode
|
|
40
|
-
isIdle: mode
|
|
41
|
-
isSimulation: mode
|
|
42
|
-
recording
|
|
37
|
+
isReplay: mode === 'replay',
|
|
38
|
+
isPaper: mode === 'paper',
|
|
39
|
+
isLive: mode === 'live',
|
|
40
|
+
isIdle: mode === 'idle',
|
|
41
|
+
isSimulation: mode !== 'live',
|
|
42
|
+
recording
|
|
43
43
|
};
|
|
44
44
|
};
|
|
45
45
|
exports.useExecutionMode = useExecutionMode;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Observable } from 'rxjs';
|
|
2
|
+
export declare function useSocket(url: string, options?: {
|
|
3
|
+
pingInterval?: number;
|
|
4
|
+
}): {
|
|
5
|
+
/**
|
|
6
|
+
* Observes socket events and handles connection health monitoring via ping/pong
|
|
7
|
+
* @returns observable emitting message events with timestamps and parsed payloads
|
|
8
|
+
*/
|
|
9
|
+
watch(): Observable<{
|
|
10
|
+
timestamp: number;
|
|
11
|
+
payload: unknown;
|
|
12
|
+
}>;
|
|
13
|
+
send(message: {
|
|
14
|
+
payload: unknown;
|
|
15
|
+
}): Observable<{
|
|
16
|
+
timestamp: number;
|
|
17
|
+
}>;
|
|
18
|
+
};
|
|
19
|
+
//# sourceMappingURL=use-socket.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-socket.d.ts","sourceRoot":"","sources":["../src/use-socket.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,UAAU,EAAM,MAAM,MAAM,CAAC;AAM7C,wBAAgB,SAAS,CACvB,GAAG,EAAE,MAAM,EACX,OAAO,GAAE;IAAE,YAAY,CAAC,EAAE,MAAM,CAAA;CAA2B;IAMzD;;;OAGG;aACM,WAAW;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;kBAmD9C;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,GAAG,WAAW;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;EAQzE"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useSocket = void 0;
|
|
4
|
+
const rxjs_1 = require("rxjs");
|
|
5
|
+
const ws_1 = require("ws");
|
|
6
|
+
const use_logger_1 = require("./use-logger");
|
|
7
|
+
const use_timestamp_1 = require("./use-timestamp");
|
|
8
|
+
function useSocket(url, options = { pingInterval: 5000 }) {
|
|
9
|
+
const { debug } = (0, use_logger_1.useLogger)('useSocket');
|
|
10
|
+
const socket = new ws_1.WebSocket(url);
|
|
11
|
+
return {
|
|
12
|
+
/**
|
|
13
|
+
* Observes socket events and handles connection health monitoring via ping/pong
|
|
14
|
+
* @returns observable emitting message events with timestamps and parsed payloads
|
|
15
|
+
*/
|
|
16
|
+
watch() {
|
|
17
|
+
let isAlive = false;
|
|
18
|
+
let interval;
|
|
19
|
+
return new rxjs_1.Observable(stream => {
|
|
20
|
+
socket.onmessage = it => stream.next({
|
|
21
|
+
timestamp: (0, use_timestamp_1.useTimestamp)(),
|
|
22
|
+
payload: JSON.parse(it.data)
|
|
23
|
+
});
|
|
24
|
+
socket.onerror = it => {
|
|
25
|
+
clearInterval(interval);
|
|
26
|
+
debug('errored', url);
|
|
27
|
+
stream.error(it);
|
|
28
|
+
};
|
|
29
|
+
socket.onclose = () => {
|
|
30
|
+
debug('closed', url);
|
|
31
|
+
clearInterval(interval);
|
|
32
|
+
stream.error();
|
|
33
|
+
};
|
|
34
|
+
socket.onopen = () => {
|
|
35
|
+
debug('opened', url);
|
|
36
|
+
isAlive = true;
|
|
37
|
+
interval = setInterval(() => {
|
|
38
|
+
if (isAlive) {
|
|
39
|
+
isAlive = false;
|
|
40
|
+
socket.ping();
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
socket.terminate();
|
|
44
|
+
clearInterval(interval);
|
|
45
|
+
}
|
|
46
|
+
}, options.pingInterval);
|
|
47
|
+
socket.on('pong', () => {
|
|
48
|
+
isAlive = true;
|
|
49
|
+
});
|
|
50
|
+
socket.on('ping', () => {
|
|
51
|
+
isAlive = true;
|
|
52
|
+
socket.pong();
|
|
53
|
+
});
|
|
54
|
+
};
|
|
55
|
+
return () => {
|
|
56
|
+
clearInterval(interval);
|
|
57
|
+
socket.terminate();
|
|
58
|
+
};
|
|
59
|
+
});
|
|
60
|
+
},
|
|
61
|
+
send(message) {
|
|
62
|
+
return (0, rxjs_1.defer)(() => {
|
|
63
|
+
socket.send(JSON.stringify(message.payload));
|
|
64
|
+
return (0, rxjs_1.of)({ timestamp: (0, use_timestamp_1.useTimestamp)() });
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
exports.useSocket = useSocket;
|
package/package.json
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { join } from 'path';
|
|
2
2
|
import {
|
|
3
|
+
catchError,
|
|
3
4
|
finalize,
|
|
4
5
|
firstValueFrom,
|
|
5
6
|
forkJoin,
|
|
@@ -8,8 +9,7 @@ import {
|
|
|
8
9
|
merge,
|
|
9
10
|
of,
|
|
10
11
|
switchMap,
|
|
11
|
-
take
|
|
12
|
-
tap
|
|
12
|
+
take
|
|
13
13
|
} from 'rxjs';
|
|
14
14
|
|
|
15
15
|
import { core } from '@lib/core';
|
|
@@ -21,12 +21,12 @@ import { buildDirectory } from './workspace';
|
|
|
21
21
|
|
|
22
22
|
export class Script {
|
|
23
23
|
constructor(
|
|
24
|
-
private readonly
|
|
24
|
+
private readonly filename: string,
|
|
25
25
|
private readonly dependencies: Dependency[]
|
|
26
26
|
) {}
|
|
27
27
|
|
|
28
28
|
async run() {
|
|
29
|
-
const script = await import(join(buildDirectory(), this.
|
|
29
|
+
const script = await import(join(buildDirectory(), this.filename));
|
|
30
30
|
|
|
31
31
|
const { dependencies, description } = script.default as ReturnType<typeof strategy>;
|
|
32
32
|
|
|
@@ -39,9 +39,11 @@ export class Script {
|
|
|
39
39
|
|
|
40
40
|
return firstValueFrom(
|
|
41
41
|
merge(
|
|
42
|
-
forkJoin(description.before.map(
|
|
42
|
+
forkJoin(description.before.map(before => before()))
|
|
43
43
|
.pipe(
|
|
44
|
-
switchMap(() =>
|
|
44
|
+
switchMap(() =>
|
|
45
|
+
forkJoin(description.behavior.map(behavior => behavior())).pipe(last())
|
|
46
|
+
)
|
|
45
47
|
)
|
|
46
48
|
.pipe(last()),
|
|
47
49
|
whenReplayFinished().pipe(last()),
|
|
@@ -51,9 +53,14 @@ export class Script {
|
|
|
51
53
|
fromEvent(process, 'SIGUSR2'),
|
|
52
54
|
fromEvent(process, 'uncaughtException')
|
|
53
55
|
).pipe(
|
|
56
|
+
catchError(e => {
|
|
57
|
+
console.error(e);
|
|
58
|
+
|
|
59
|
+
return of(e);
|
|
60
|
+
}),
|
|
54
61
|
take(1),
|
|
55
62
|
switchMap(
|
|
56
|
-
it => forkJoin(description.after.map(
|
|
63
|
+
it => forkJoin(description.after.map(after => after())).pipe(last()) ?? of(it)
|
|
57
64
|
),
|
|
58
65
|
finalize(() => process.exit(0))
|
|
59
66
|
)
|
package/src/replay/index.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
export * from './use-replay';
|
|
2
2
|
export * from './use-replay-breakpoint';
|
|
3
3
|
export * from './use-replay-options';
|
|
4
|
-
export * from './use-replay-storage';
|
|
5
|
-
export * from './use-replay-storage-buffer';
|
|
4
|
+
export * from './storage/use-replay-storage';
|
|
5
|
+
export * from './storage/use-replay-storage-buffer';
|
|
6
6
|
export * from './use-replay-manager';
|
|
7
7
|
export * from './when-replay-finished';
|
|
8
8
|
export * from './replay';
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { useReplayOptions } from '@lib/replay/use-replay-options';
|
|
1
2
|
import { between } from '@lib/storage';
|
|
2
3
|
import { dependency } from '@lib/use-hash';
|
|
3
4
|
import { withMemo } from '@lib/with-memo';
|
|
@@ -6,10 +7,12 @@ import { useReplayStorage } from './use-replay-storage';
|
|
|
6
7
|
|
|
7
8
|
export const useReplayStorageBuffer = withMemo(<T>(dependencies: dependency[]) => {
|
|
8
9
|
const { query } = useReplayStorage<T>(dependencies);
|
|
10
|
+
const { from, to } = useReplayOptions();
|
|
9
11
|
|
|
10
12
|
let page = new Array<{ timestamp: number; payload: T }>();
|
|
11
13
|
let index = 0;
|
|
12
14
|
let completed = false;
|
|
15
|
+
let count = 0;
|
|
13
16
|
|
|
14
17
|
return {
|
|
15
18
|
size() {
|
|
@@ -24,7 +27,7 @@ export const useReplayStorageBuffer = withMemo(<T>(dependencies: dependency[]) =
|
|
|
24
27
|
completed() {
|
|
25
28
|
return completed;
|
|
26
29
|
},
|
|
27
|
-
async fetchNextPage(
|
|
30
|
+
async fetchNextPage() {
|
|
28
31
|
if (completed) {
|
|
29
32
|
return;
|
|
30
33
|
}
|
|
@@ -35,8 +38,12 @@ export const useReplayStorageBuffer = withMemo(<T>(dependencies: dependency[]) =
|
|
|
35
38
|
where: {
|
|
36
39
|
timestamp: between(from, to)
|
|
37
40
|
},
|
|
38
|
-
limit: 10000
|
|
41
|
+
limit: 10000,
|
|
42
|
+
offset: count,
|
|
43
|
+
orderBy: 'ASC'
|
|
39
44
|
});
|
|
45
|
+
|
|
46
|
+
count += page.length;
|
|
40
47
|
completed = page.length == 0;
|
|
41
48
|
}
|
|
42
49
|
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { dependency, useHash } from '@lib/use-hash';
|
|
2
|
+
import { useLogger } from '@lib/use-logger';
|
|
3
|
+
import { withMemo } from '@lib/with-memo';
|
|
4
|
+
|
|
5
|
+
import { useReplayStorageBuffer } from './use-replay-storage-buffer';
|
|
6
|
+
|
|
7
|
+
export const useReplayStorageCursor = withMemo(() => {
|
|
8
|
+
const { info } = useLogger('useReplayStorageCursor');
|
|
9
|
+
const storages = Array.of<ReturnType<typeof useReplayStorageBuffer<any>>>();
|
|
10
|
+
|
|
11
|
+
return {
|
|
12
|
+
get<T>(dependencies: dependency[]) {
|
|
13
|
+
const storage = useReplayStorageBuffer<T>(dependencies);
|
|
14
|
+
|
|
15
|
+
if (!storages.includes(storage)) {
|
|
16
|
+
info('opening a new replay buffer', useHash(dependencies));
|
|
17
|
+
storages.push(storage);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return storage;
|
|
21
|
+
},
|
|
22
|
+
async cursor() {
|
|
23
|
+
let current: ReturnType<typeof useReplayStorageBuffer<any>> | undefined;
|
|
24
|
+
|
|
25
|
+
for (const storage of storages) {
|
|
26
|
+
if (storage.completed()) {
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (storage.size() == 0) {
|
|
31
|
+
await storage.fetchNextPage();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (storage.peek()) {
|
|
35
|
+
if (!current || current.peek().timestamp > storage.peek().timestamp) {
|
|
36
|
+
current = storage;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return current;
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
});
|
|
@@ -12,16 +12,16 @@ export function useReplayBreakpoint<T>(input: Observable<T>): Observable<T> {
|
|
|
12
12
|
return input;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
const { info } = useLogger('
|
|
15
|
+
const { info } = useLogger('replay');
|
|
16
16
|
const { stop, tryContinue } = useReplayManager();
|
|
17
17
|
|
|
18
|
-
info('
|
|
18
|
+
info('breakpoint acquired');
|
|
19
19
|
|
|
20
20
|
stop();
|
|
21
21
|
|
|
22
22
|
return input.pipe(
|
|
23
23
|
finalize(() => {
|
|
24
|
-
info('
|
|
24
|
+
info('breakpoint released');
|
|
25
25
|
|
|
26
26
|
tryContinue();
|
|
27
27
|
})
|
|
@@ -1,56 +1,37 @@
|
|
|
1
1
|
import { defer, filter, map, Observable, Subject } from 'rxjs';
|
|
2
2
|
|
|
3
|
-
import { dependency
|
|
4
|
-
import { useLogger } from '@lib/use-logger';
|
|
3
|
+
import { dependency } from '@lib/use-hash';
|
|
5
4
|
import { withMemo } from '@lib/with-memo';
|
|
6
5
|
|
|
6
|
+
import { useReplayStorageBuffer } from './storage/use-replay-storage-buffer';
|
|
7
|
+
import { useReplayStorageCursor } from './storage/use-replay-storage-cursor';
|
|
7
8
|
import { useReplayOptions } from './use-replay-options';
|
|
8
|
-
import { useReplayStorageBuffer } from './use-replay-storage-buffer';
|
|
9
9
|
|
|
10
10
|
export const useReplayManager = withMemo(() => {
|
|
11
|
-
const { from
|
|
12
|
-
const {
|
|
11
|
+
const { from } = useReplayOptions();
|
|
12
|
+
const { get, cursor } = useReplayStorageCursor();
|
|
13
13
|
|
|
14
14
|
let timestamp = from;
|
|
15
15
|
let stopAcquire = 1;
|
|
16
|
-
const subscriptions = Array.of<ReturnType<typeof useReplayStorageBuffer<any>>>();
|
|
17
16
|
|
|
18
17
|
const stream$ = new Subject<
|
|
19
18
|
[ReturnType<typeof useReplayStorageBuffer<any>>, { timestamp: number; payload: any }]
|
|
20
19
|
>();
|
|
21
20
|
|
|
22
|
-
const getNextStorage = async () => {
|
|
23
|
-
let next: ReturnType<typeof useReplayStorageBuffer<any>> | undefined;
|
|
24
|
-
|
|
25
|
-
for (const cursor of subscriptions) {
|
|
26
|
-
if (cursor.size() == 0 && !cursor.completed()) {
|
|
27
|
-
await cursor.fetchNextPage(timestamp, to + 1);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
if (cursor.peek()) {
|
|
31
|
-
if (!next || next.peek().timestamp > cursor.peek().timestamp) {
|
|
32
|
-
next = cursor;
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
return next;
|
|
38
|
-
};
|
|
39
|
-
|
|
40
21
|
const processNext = async () => {
|
|
41
|
-
const
|
|
22
|
+
const storage = await cursor();
|
|
42
23
|
|
|
43
|
-
if (!
|
|
24
|
+
if (!storage || !storage.peek()) {
|
|
44
25
|
stream$.complete();
|
|
45
26
|
|
|
46
27
|
return false;
|
|
47
28
|
}
|
|
48
29
|
|
|
49
|
-
const sample =
|
|
30
|
+
const sample = storage.dequeue();
|
|
50
31
|
|
|
51
32
|
timestamp = sample.timestamp;
|
|
52
33
|
|
|
53
|
-
stream$.next([
|
|
34
|
+
stream$.next([storage, sample]);
|
|
54
35
|
|
|
55
36
|
return true;
|
|
56
37
|
};
|
|
@@ -86,13 +67,8 @@ export const useReplayManager = withMemo(() => {
|
|
|
86
67
|
stopAcquire++;
|
|
87
68
|
},
|
|
88
69
|
tryContinue,
|
|
89
|
-
|
|
90
|
-
const storage =
|
|
91
|
-
|
|
92
|
-
if (!subscriptions.includes(storage)) {
|
|
93
|
-
info('subscribing to replay', useHash(dependencies));
|
|
94
|
-
subscriptions.push(storage);
|
|
95
|
-
}
|
|
70
|
+
watch<T>(dependencies: dependency[]): Observable<{ timestamp: number; payload: T }> {
|
|
71
|
+
const storage = get<T>(dependencies);
|
|
96
72
|
|
|
97
73
|
return defer(() => {
|
|
98
74
|
tryContinue();
|
package/src/replay/use-replay.ts
CHANGED
|
@@ -3,8 +3,8 @@ import { Observable, tap } from 'rxjs';
|
|
|
3
3
|
import { useExecutionMode } from '@lib/use-execution-mode';
|
|
4
4
|
import { dependency } from '@lib/use-hash';
|
|
5
5
|
|
|
6
|
+
import { useReplayStorage } from './storage/use-replay-storage';
|
|
6
7
|
import { useReplayManager } from './use-replay-manager';
|
|
7
|
-
import { useReplayStorage } from './use-replay-storage';
|
|
8
8
|
|
|
9
9
|
export function useReplay<T>(
|
|
10
10
|
input: Observable<{ timestamp: number; payload: T }>,
|
|
@@ -13,9 +13,9 @@ export function useReplay<T>(
|
|
|
13
13
|
const { isReplay, recording } = useExecutionMode();
|
|
14
14
|
|
|
15
15
|
if (isReplay) {
|
|
16
|
-
const {
|
|
16
|
+
const { watch } = useReplayManager();
|
|
17
17
|
|
|
18
|
-
return
|
|
18
|
+
return watch<T>(dependencies);
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
if (recording) {
|
package/src/shared/decimals.ts
CHANGED
|
@@ -16,54 +16,9 @@ Decimal.prototype.toCeil = function (decimalPlaces: number) {
|
|
|
16
16
|
};
|
|
17
17
|
|
|
18
18
|
export class decimal extends Decimal {}
|
|
19
|
-
/*
|
|
20
|
-
decimal.prototype.toJSON = function () {
|
|
21
|
-
return '444';
|
|
22
|
-
};
|
|
23
|
-
*/
|
|
24
19
|
|
|
25
20
|
export function d(value: Decimal.Value) {
|
|
26
21
|
return new decimal(value);
|
|
27
22
|
}
|
|
28
23
|
|
|
29
24
|
d.Zero = new decimal(0);
|
|
30
|
-
|
|
31
|
-
export function weightedMean(values: decimal[], weights: decimal[]): decimal {
|
|
32
|
-
const result = values
|
|
33
|
-
.map((value, i) => {
|
|
34
|
-
const weight = weights[i];
|
|
35
|
-
const sum = value.mul(weight);
|
|
36
|
-
return [sum, weight];
|
|
37
|
-
})
|
|
38
|
-
.reduce((p, c) => [p[0].add(c[0]), p[1].add(c[1])], [d.Zero, d.Zero]);
|
|
39
|
-
|
|
40
|
-
if (!result[1]) {
|
|
41
|
-
return d.Zero;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
return result[0].div(result[1]);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export function pnl(entryRate: decimal, exitRate: decimal, amount: decimal) {
|
|
48
|
-
return exitRate.div(entryRate).minus(1).mul(amount);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
*
|
|
53
|
-
* @param timestamp
|
|
54
|
-
* @param timeframe
|
|
55
|
-
* @returns nearest timestamp to the given timeframe
|
|
56
|
-
*/
|
|
57
|
-
export function candledown(timestamp: number, timeframe: number): number {
|
|
58
|
-
return timestamp - (timestamp % timeframe);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
*
|
|
63
|
-
* @param timestamp
|
|
64
|
-
* @param timeframe
|
|
65
|
-
* @returns nearest timestamp to the given timeframe
|
|
66
|
-
*/
|
|
67
|
-
export function candleup(timestamp: number, timeframe: number): number {
|
|
68
|
-
return candledown(timestamp, timeframe) + timeframe;
|
|
69
|
-
}
|
package/src/strategy.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Observable } from 'rxjs';
|
|
1
|
+
import { Observable, of } from 'rxjs';
|
|
2
2
|
|
|
3
3
|
import { Dependency } from './module';
|
|
4
4
|
|
|
@@ -21,6 +21,14 @@ export function strategy(descriptor: () => Dependency[]) {
|
|
|
21
21
|
|
|
22
22
|
const dependencies = descriptor();
|
|
23
23
|
|
|
24
|
+
if (!description.before.length) {
|
|
25
|
+
description.before.push(() => of(true));
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (!description.after.length) {
|
|
29
|
+
description.after.push(() => of(true));
|
|
30
|
+
}
|
|
31
|
+
|
|
24
32
|
return {
|
|
25
33
|
dependencies,
|
|
26
34
|
description
|
|
@@ -36,14 +36,14 @@ export function idleExecutionMode() {
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
export const useExecutionMode = () => {
|
|
39
|
-
const mode = useContext<ExecutionMode>(injectionToken);
|
|
39
|
+
const { mode, recording } = useContext<ExecutionMode>(injectionToken);
|
|
40
40
|
|
|
41
41
|
return {
|
|
42
|
-
isReplay: mode
|
|
43
|
-
isPaper: mode
|
|
44
|
-
isLive: mode
|
|
45
|
-
isIdle: mode
|
|
46
|
-
isSimulation: mode
|
|
47
|
-
recording
|
|
42
|
+
isReplay: mode === 'replay',
|
|
43
|
+
isPaper: mode === 'paper',
|
|
44
|
+
isLive: mode === 'live',
|
|
45
|
+
isIdle: mode === 'idle',
|
|
46
|
+
isSimulation: mode !== 'live',
|
|
47
|
+
recording
|
|
48
48
|
};
|
|
49
49
|
};
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { defer, Observable, of } from 'rxjs';
|
|
2
|
+
import { WebSocket } from 'ws';
|
|
3
|
+
|
|
4
|
+
import { useLogger } from './use-logger';
|
|
5
|
+
import { useTimestamp } from './use-timestamp';
|
|
6
|
+
|
|
7
|
+
export function useSocket(
|
|
8
|
+
url: string,
|
|
9
|
+
options: { pingInterval?: number } = { pingInterval: 5000 }
|
|
10
|
+
) {
|
|
11
|
+
const { debug } = useLogger('useSocket');
|
|
12
|
+
const socket = new WebSocket(url);
|
|
13
|
+
|
|
14
|
+
return {
|
|
15
|
+
/**
|
|
16
|
+
* Observes socket events and handles connection health monitoring via ping/pong
|
|
17
|
+
* @returns observable emitting message events with timestamps and parsed payloads
|
|
18
|
+
*/
|
|
19
|
+
watch(): Observable<{ timestamp: number; payload: unknown }> {
|
|
20
|
+
let isAlive = false;
|
|
21
|
+
let interval: NodeJS.Timeout | undefined;
|
|
22
|
+
|
|
23
|
+
return new Observable(stream => {
|
|
24
|
+
socket.onmessage = it =>
|
|
25
|
+
stream.next({
|
|
26
|
+
timestamp: useTimestamp(),
|
|
27
|
+
payload: JSON.parse(it.data as string)
|
|
28
|
+
});
|
|
29
|
+
socket.onerror = it => {
|
|
30
|
+
clearInterval(interval);
|
|
31
|
+
debug('errored', url);
|
|
32
|
+
stream.error(it);
|
|
33
|
+
};
|
|
34
|
+
socket.onclose = () => {
|
|
35
|
+
debug('closed', url);
|
|
36
|
+
clearInterval(interval);
|
|
37
|
+
stream.error();
|
|
38
|
+
};
|
|
39
|
+
socket.onopen = () => {
|
|
40
|
+
debug('opened', url);
|
|
41
|
+
isAlive = true;
|
|
42
|
+
interval = setInterval(() => {
|
|
43
|
+
if (isAlive) {
|
|
44
|
+
isAlive = false;
|
|
45
|
+
|
|
46
|
+
socket.ping();
|
|
47
|
+
} else {
|
|
48
|
+
socket.terminate();
|
|
49
|
+
clearInterval(interval);
|
|
50
|
+
}
|
|
51
|
+
}, options.pingInterval);
|
|
52
|
+
|
|
53
|
+
socket.on('pong', () => {
|
|
54
|
+
isAlive = true;
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
socket.on('ping', () => {
|
|
58
|
+
isAlive = true;
|
|
59
|
+
socket.pong();
|
|
60
|
+
});
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
return () => {
|
|
64
|
+
clearInterval(interval);
|
|
65
|
+
socket.terminate();
|
|
66
|
+
};
|
|
67
|
+
});
|
|
68
|
+
},
|
|
69
|
+
|
|
70
|
+
send(message: { payload: unknown }): Observable<{ timestamp: number }> {
|
|
71
|
+
return defer(() => {
|
|
72
|
+
socket.send(JSON.stringify(message.payload));
|
|
73
|
+
|
|
74
|
+
return of({ timestamp: useTimestamp() });
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"use-replay-storage-buffer.d.ts","sourceRoot":"","sources":["../../src/replay/use-replay-storage-buffer.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAK3C,eAAO,MAAM,sBAAsB;;;mBAGC,MAAM;;;;mBAAN,MAAM;;;;wBAiBZ,MAAM,MAAM,MAAM;CAgB9C,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"use-replay-storage.d.ts","sourceRoot":"","sources":["../../src/replay/use-replay-storage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,WAAW,EAAuB,MAAM,cAAc,CAAC;AACvE,OAAO,EAAE,UAAU,EAAW,MAAM,eAAe,CAAC;AAEpD,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,YAAY,EAAE,UAAU,EAAE;iBASvC,MAAM,WAAW,CAAC;;;;kBAMvB;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,CAAC,CAAA;KAAE,EAAE;EAUpD"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"use-replay-storage.spec.d.ts","sourceRoot":"","sources":["../../src/replay/use-replay-storage.spec.ts"],"names":[],"mappings":""}
|
|
File without changes
|
|
File without changes
|