@tradejs/cli 1.0.0
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/README.md +65 -0
- package/dist/cli.js +10727 -0
- package/dist/lib/runBot.js +157 -0
- package/dist/scripts/backtest.js +2044 -0
- package/dist/scripts/bot.js +153 -0
- package/dist/scripts/cleanDir.js +40 -0
- package/dist/scripts/cleanRedis.js +40 -0
- package/dist/scripts/cleanTests.js +81 -0
- package/dist/scripts/continuity.js +183 -0
- package/dist/scripts/derivativesIngest.js +107 -0
- package/dist/scripts/derivativesIngestCoinalyzeAll.js +391 -0
- package/dist/scripts/doctor.js +5143 -0
- package/dist/scripts/findMlSignalsByTestSuite.js +83 -0
- package/dist/scripts/infraCommon.js +135 -0
- package/dist/scripts/infraDown.js +82 -0
- package/dist/scripts/infraInit.js +107 -0
- package/dist/scripts/infraUp.js +82 -0
- package/dist/scripts/migration.js +67 -0
- package/dist/scripts/mlExport.js +95 -0
- package/dist/scripts/mlExportSelect.js +100 -0
- package/dist/scripts/mlInspect.js +553 -0
- package/dist/scripts/mlTrainLatestSelect.js +1056 -0
- package/dist/scripts/results.js +1909 -0
- package/dist/scripts/selectStrategy.js +99 -0
- package/dist/scripts/signals.js +300 -0
- package/dist/scripts/test-ml.js +133 -0
- package/dist/scripts/test.js +16 -0
- package/dist/scripts/user-add.js +64 -0
- package/dist/workers/testerWorker.js +54 -0
- package/package.json +75 -0
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __copyProps = (to, from, except, desc) => {
|
|
9
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
10
|
+
for (let key of __getOwnPropNames(from))
|
|
11
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
12
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
13
|
+
}
|
|
14
|
+
return to;
|
|
15
|
+
};
|
|
16
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
17
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
18
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
19
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
20
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
21
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
22
|
+
mod
|
|
23
|
+
));
|
|
24
|
+
|
|
25
|
+
// src/scripts/findMlSignalsByTestSuite.ts
|
|
26
|
+
var import_args = __toESM(require("args"));
|
|
27
|
+
var import_ioredis = __toESM(require("ioredis"));
|
|
28
|
+
import_args.default.example(
|
|
29
|
+
'yarn ts-node ./src/scripts/findMlSignalsByTestSuite --testSuiteId 861d9d --pattern "ml:*:signals:*"',
|
|
30
|
+
"Find ML signal keys by context.testSuiteId"
|
|
31
|
+
);
|
|
32
|
+
import_args.default.option(["p", "pattern"], "Redis key pattern", "ml:signals:*");
|
|
33
|
+
import_args.default.option(["t", "testSuiteId"], "context.testSuiteId value", "861d9d");
|
|
34
|
+
import_args.default.option(["c", "count"], "SCAN COUNT", 500);
|
|
35
|
+
var flags = import_args.default.parse(process.argv);
|
|
36
|
+
var redis = new import_ioredis.default({
|
|
37
|
+
host: process.env.REDIS_HOST ?? "127.0.0.1",
|
|
38
|
+
port: Number(process.env.REDIS_PORT ?? 6379)
|
|
39
|
+
});
|
|
40
|
+
var findKeys = async () => {
|
|
41
|
+
const pattern = String(flags.pattern || "ml:signals:*");
|
|
42
|
+
const testSuiteId = String(flags.testSuiteId || "861d9d");
|
|
43
|
+
const scanCount = Number(flags.count || 500);
|
|
44
|
+
let cursor = "0";
|
|
45
|
+
const matchedKeys = [];
|
|
46
|
+
let scanned = 0;
|
|
47
|
+
do {
|
|
48
|
+
const [nextCursor, keys] = await redis.scan(
|
|
49
|
+
cursor,
|
|
50
|
+
"MATCH",
|
|
51
|
+
pattern,
|
|
52
|
+
"COUNT",
|
|
53
|
+
scanCount
|
|
54
|
+
);
|
|
55
|
+
cursor = nextCursor;
|
|
56
|
+
for (const key of keys) {
|
|
57
|
+
scanned++;
|
|
58
|
+
const raw = await redis.call("JSON.GET", key, "$.context.testSuiteId");
|
|
59
|
+
if (raw === `["${testSuiteId}"]`) {
|
|
60
|
+
matchedKeys.push(key);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
} while (cursor !== "0");
|
|
64
|
+
console.log(
|
|
65
|
+
JSON.stringify(
|
|
66
|
+
{
|
|
67
|
+
pattern,
|
|
68
|
+
testSuiteId,
|
|
69
|
+
scanned,
|
|
70
|
+
matched: matchedKeys.length,
|
|
71
|
+
keys: matchedKeys
|
|
72
|
+
},
|
|
73
|
+
null,
|
|
74
|
+
2
|
|
75
|
+
)
|
|
76
|
+
);
|
|
77
|
+
};
|
|
78
|
+
findKeys().catch((error) => {
|
|
79
|
+
console.error(error);
|
|
80
|
+
process.exitCode = 1;
|
|
81
|
+
}).finally(() => {
|
|
82
|
+
redis.disconnect();
|
|
83
|
+
});
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/scripts/infraCommon.ts
|
|
31
|
+
var infraCommon_exports = {};
|
|
32
|
+
__export(infraCommon_exports, {
|
|
33
|
+
DEV_COMPOSE_FILE: () => DEV_COMPOSE_FILE,
|
|
34
|
+
initDevComposeFile: () => initDevComposeFile,
|
|
35
|
+
requireDevComposeFile: () => requireDevComposeFile,
|
|
36
|
+
runDockerCompose: () => runDockerCompose
|
|
37
|
+
});
|
|
38
|
+
module.exports = __toCommonJS(infraCommon_exports);
|
|
39
|
+
var import_chalk = __toESM(require("chalk"));
|
|
40
|
+
var import_node_child_process = require("child_process");
|
|
41
|
+
var import_node_fs = require("fs");
|
|
42
|
+
var import_node_path = __toESM(require("path"));
|
|
43
|
+
var DEV_COMPOSE_FILE = "docker-compose.dev.yml";
|
|
44
|
+
var resolveProjectRoot = () => {
|
|
45
|
+
const cwd = process.cwd();
|
|
46
|
+
const composeInCwd = import_node_path.default.resolve(cwd, DEV_COMPOSE_FILE);
|
|
47
|
+
if ((0, import_node_fs.existsSync)(composeInCwd)) {
|
|
48
|
+
return cwd;
|
|
49
|
+
}
|
|
50
|
+
const fromEnv = String(process.env.PROJECT_CWD || "").trim();
|
|
51
|
+
if (fromEnv) {
|
|
52
|
+
const normalized = import_node_path.default.resolve(fromEnv);
|
|
53
|
+
const composeFromEnv = import_node_path.default.resolve(normalized, DEV_COMPOSE_FILE);
|
|
54
|
+
if ((0, import_node_fs.existsSync)(composeFromEnv)) {
|
|
55
|
+
return normalized;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return cwd;
|
|
59
|
+
};
|
|
60
|
+
var DEV_COMPOSE_TEMPLATE = `services:
|
|
61
|
+
timescale:
|
|
62
|
+
image: timescale/timescaledb:latest-pg16
|
|
63
|
+
container_name: tradejs-timescale
|
|
64
|
+
environment:
|
|
65
|
+
POSTGRES_USER: \${PG_USER:-app}
|
|
66
|
+
POSTGRES_PASSWORD: \${PG_PASSWORD:-app}
|
|
67
|
+
POSTGRES_DB: \${PG_DB:-app}
|
|
68
|
+
ports:
|
|
69
|
+
- "5432:5432"
|
|
70
|
+
volumes:
|
|
71
|
+
- tradejs_pgdata:/var/lib/postgresql/data
|
|
72
|
+
healthcheck:
|
|
73
|
+
test: ["CMD-SHELL", "pg_isready -U \${PG_USER:-app} -d \${PG_DB:-app}"]
|
|
74
|
+
interval: 5s
|
|
75
|
+
timeout: 3s
|
|
76
|
+
retries: 10
|
|
77
|
+
restart: unless-stopped
|
|
78
|
+
|
|
79
|
+
redis:
|
|
80
|
+
image: redis/redis-stack:latest
|
|
81
|
+
container_name: tradejs-redis
|
|
82
|
+
ports:
|
|
83
|
+
- "6379:6379"
|
|
84
|
+
- "5540:8001"
|
|
85
|
+
volumes:
|
|
86
|
+
- tradejs_redisdata:/data
|
|
87
|
+
restart: unless-stopped
|
|
88
|
+
|
|
89
|
+
volumes:
|
|
90
|
+
tradejs_pgdata:
|
|
91
|
+
tradejs_redisdata:
|
|
92
|
+
`;
|
|
93
|
+
var getDevComposePath = () => import_node_path.default.resolve(resolveProjectRoot(), DEV_COMPOSE_FILE);
|
|
94
|
+
var initDevComposeFile = () => {
|
|
95
|
+
const composePath = getDevComposePath();
|
|
96
|
+
if ((0, import_node_fs.existsSync)(composePath)) {
|
|
97
|
+
console.log(
|
|
98
|
+
import_chalk.default.yellow(
|
|
99
|
+
`${DEV_COMPOSE_FILE} already exists. Keeping user-defined file as is.`
|
|
100
|
+
)
|
|
101
|
+
);
|
|
102
|
+
return composePath;
|
|
103
|
+
}
|
|
104
|
+
(0, import_node_fs.writeFileSync)(composePath, DEV_COMPOSE_TEMPLATE, "utf8");
|
|
105
|
+
console.log(import_chalk.default.green(`Created ${DEV_COMPOSE_FILE} in project root`));
|
|
106
|
+
return composePath;
|
|
107
|
+
};
|
|
108
|
+
var requireDevComposeFile = () => {
|
|
109
|
+
const composePath = import_node_path.default.resolve(resolveProjectRoot(), DEV_COMPOSE_FILE);
|
|
110
|
+
if ((0, import_node_fs.existsSync)(composePath)) {
|
|
111
|
+
console.log(import_chalk.default.gray(`Using existing ${DEV_COMPOSE_FILE}`));
|
|
112
|
+
return composePath;
|
|
113
|
+
}
|
|
114
|
+
throw new Error(
|
|
115
|
+
`${DEV_COMPOSE_FILE} not found in project root. Run "npx @tradejs/cli infra-init" first.`
|
|
116
|
+
);
|
|
117
|
+
};
|
|
118
|
+
var runDockerCompose = (composePath, args) => {
|
|
119
|
+
const result = (0, import_node_child_process.spawnSync)("docker", ["compose", "-f", composePath, ...args], {
|
|
120
|
+
stdio: "inherit"
|
|
121
|
+
});
|
|
122
|
+
if (result.error) {
|
|
123
|
+
throw result.error;
|
|
124
|
+
}
|
|
125
|
+
if ((result.status ?? 0) !== 0) {
|
|
126
|
+
process.exit(result.status ?? 1);
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
130
|
+
0 && (module.exports = {
|
|
131
|
+
DEV_COMPOSE_FILE,
|
|
132
|
+
initDevComposeFile,
|
|
133
|
+
requireDevComposeFile,
|
|
134
|
+
runDockerCompose
|
|
135
|
+
});
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __copyProps = (to, from, except, desc) => {
|
|
9
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
10
|
+
for (let key of __getOwnPropNames(from))
|
|
11
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
12
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
13
|
+
}
|
|
14
|
+
return to;
|
|
15
|
+
};
|
|
16
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
17
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
18
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
19
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
20
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
21
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
22
|
+
mod
|
|
23
|
+
));
|
|
24
|
+
|
|
25
|
+
// src/scripts/infraDown.ts
|
|
26
|
+
var import_chalk2 = __toESM(require("chalk"));
|
|
27
|
+
|
|
28
|
+
// src/scripts/infraCommon.ts
|
|
29
|
+
var import_chalk = __toESM(require("chalk"));
|
|
30
|
+
var import_node_child_process = require("child_process");
|
|
31
|
+
var import_node_fs = require("fs");
|
|
32
|
+
var import_node_path = __toESM(require("path"));
|
|
33
|
+
var DEV_COMPOSE_FILE = "docker-compose.dev.yml";
|
|
34
|
+
var resolveProjectRoot = () => {
|
|
35
|
+
const cwd = process.cwd();
|
|
36
|
+
const composeInCwd = import_node_path.default.resolve(cwd, DEV_COMPOSE_FILE);
|
|
37
|
+
if ((0, import_node_fs.existsSync)(composeInCwd)) {
|
|
38
|
+
return cwd;
|
|
39
|
+
}
|
|
40
|
+
const fromEnv = String(process.env.PROJECT_CWD || "").trim();
|
|
41
|
+
if (fromEnv) {
|
|
42
|
+
const normalized = import_node_path.default.resolve(fromEnv);
|
|
43
|
+
const composeFromEnv = import_node_path.default.resolve(normalized, DEV_COMPOSE_FILE);
|
|
44
|
+
if ((0, import_node_fs.existsSync)(composeFromEnv)) {
|
|
45
|
+
return normalized;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return cwd;
|
|
49
|
+
};
|
|
50
|
+
var requireDevComposeFile = () => {
|
|
51
|
+
const composePath = import_node_path.default.resolve(resolveProjectRoot(), DEV_COMPOSE_FILE);
|
|
52
|
+
if ((0, import_node_fs.existsSync)(composePath)) {
|
|
53
|
+
console.log(import_chalk.default.gray(`Using existing ${DEV_COMPOSE_FILE}`));
|
|
54
|
+
return composePath;
|
|
55
|
+
}
|
|
56
|
+
throw new Error(
|
|
57
|
+
`${DEV_COMPOSE_FILE} not found in project root. Run "npx @tradejs/cli infra-init" first.`
|
|
58
|
+
);
|
|
59
|
+
};
|
|
60
|
+
var runDockerCompose = (composePath, args) => {
|
|
61
|
+
const result = (0, import_node_child_process.spawnSync)("docker", ["compose", "-f", composePath, ...args], {
|
|
62
|
+
stdio: "inherit"
|
|
63
|
+
});
|
|
64
|
+
if (result.error) {
|
|
65
|
+
throw result.error;
|
|
66
|
+
}
|
|
67
|
+
if ((result.status ?? 0) !== 0) {
|
|
68
|
+
process.exit(result.status ?? 1);
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
// src/scripts/infraDown.ts
|
|
73
|
+
var run = async () => {
|
|
74
|
+
const composePath = requireDevComposeFile();
|
|
75
|
+
console.log(import_chalk2.default.cyan("Stopping dev infra (timescale, redis)..."));
|
|
76
|
+
runDockerCompose(composePath, ["stop", "timescale", "redis"]);
|
|
77
|
+
console.log(import_chalk2.default.green("Dev infra is stopped."));
|
|
78
|
+
};
|
|
79
|
+
run().catch((error) => {
|
|
80
|
+
console.error(import_chalk2.default.red(`infra-down failed: ${String(error)}`));
|
|
81
|
+
process.exit(1);
|
|
82
|
+
});
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __copyProps = (to, from, except, desc) => {
|
|
9
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
10
|
+
for (let key of __getOwnPropNames(from))
|
|
11
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
12
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
13
|
+
}
|
|
14
|
+
return to;
|
|
15
|
+
};
|
|
16
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
17
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
18
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
19
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
20
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
21
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
22
|
+
mod
|
|
23
|
+
));
|
|
24
|
+
|
|
25
|
+
// src/scripts/infraInit.ts
|
|
26
|
+
var import_chalk2 = __toESM(require("chalk"));
|
|
27
|
+
|
|
28
|
+
// src/scripts/infraCommon.ts
|
|
29
|
+
var import_chalk = __toESM(require("chalk"));
|
|
30
|
+
var import_node_child_process = require("child_process");
|
|
31
|
+
var import_node_fs = require("fs");
|
|
32
|
+
var import_node_path = __toESM(require("path"));
|
|
33
|
+
var DEV_COMPOSE_FILE = "docker-compose.dev.yml";
|
|
34
|
+
var resolveProjectRoot = () => {
|
|
35
|
+
const cwd = process.cwd();
|
|
36
|
+
const composeInCwd = import_node_path.default.resolve(cwd, DEV_COMPOSE_FILE);
|
|
37
|
+
if ((0, import_node_fs.existsSync)(composeInCwd)) {
|
|
38
|
+
return cwd;
|
|
39
|
+
}
|
|
40
|
+
const fromEnv = String(process.env.PROJECT_CWD || "").trim();
|
|
41
|
+
if (fromEnv) {
|
|
42
|
+
const normalized = import_node_path.default.resolve(fromEnv);
|
|
43
|
+
const composeFromEnv = import_node_path.default.resolve(normalized, DEV_COMPOSE_FILE);
|
|
44
|
+
if ((0, import_node_fs.existsSync)(composeFromEnv)) {
|
|
45
|
+
return normalized;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return cwd;
|
|
49
|
+
};
|
|
50
|
+
var DEV_COMPOSE_TEMPLATE = `services:
|
|
51
|
+
timescale:
|
|
52
|
+
image: timescale/timescaledb:latest-pg16
|
|
53
|
+
container_name: tradejs-timescale
|
|
54
|
+
environment:
|
|
55
|
+
POSTGRES_USER: \${PG_USER:-app}
|
|
56
|
+
POSTGRES_PASSWORD: \${PG_PASSWORD:-app}
|
|
57
|
+
POSTGRES_DB: \${PG_DB:-app}
|
|
58
|
+
ports:
|
|
59
|
+
- "5432:5432"
|
|
60
|
+
volumes:
|
|
61
|
+
- tradejs_pgdata:/var/lib/postgresql/data
|
|
62
|
+
healthcheck:
|
|
63
|
+
test: ["CMD-SHELL", "pg_isready -U \${PG_USER:-app} -d \${PG_DB:-app}"]
|
|
64
|
+
interval: 5s
|
|
65
|
+
timeout: 3s
|
|
66
|
+
retries: 10
|
|
67
|
+
restart: unless-stopped
|
|
68
|
+
|
|
69
|
+
redis:
|
|
70
|
+
image: redis/redis-stack:latest
|
|
71
|
+
container_name: tradejs-redis
|
|
72
|
+
ports:
|
|
73
|
+
- "6379:6379"
|
|
74
|
+
- "5540:8001"
|
|
75
|
+
volumes:
|
|
76
|
+
- tradejs_redisdata:/data
|
|
77
|
+
restart: unless-stopped
|
|
78
|
+
|
|
79
|
+
volumes:
|
|
80
|
+
tradejs_pgdata:
|
|
81
|
+
tradejs_redisdata:
|
|
82
|
+
`;
|
|
83
|
+
var getDevComposePath = () => import_node_path.default.resolve(resolveProjectRoot(), DEV_COMPOSE_FILE);
|
|
84
|
+
var initDevComposeFile = () => {
|
|
85
|
+
const composePath = getDevComposePath();
|
|
86
|
+
if ((0, import_node_fs.existsSync)(composePath)) {
|
|
87
|
+
console.log(
|
|
88
|
+
import_chalk.default.yellow(
|
|
89
|
+
`${DEV_COMPOSE_FILE} already exists. Keeping user-defined file as is.`
|
|
90
|
+
)
|
|
91
|
+
);
|
|
92
|
+
return composePath;
|
|
93
|
+
}
|
|
94
|
+
(0, import_node_fs.writeFileSync)(composePath, DEV_COMPOSE_TEMPLATE, "utf8");
|
|
95
|
+
console.log(import_chalk.default.green(`Created ${DEV_COMPOSE_FILE} in project root`));
|
|
96
|
+
return composePath;
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
// src/scripts/infraInit.ts
|
|
100
|
+
var run = async () => {
|
|
101
|
+
initDevComposeFile();
|
|
102
|
+
console.log(import_chalk2.default.green("Dev infra files are initialized."));
|
|
103
|
+
};
|
|
104
|
+
run().catch((error) => {
|
|
105
|
+
console.error(import_chalk2.default.red(`infra-init failed: ${String(error)}`));
|
|
106
|
+
process.exit(1);
|
|
107
|
+
});
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __copyProps = (to, from, except, desc) => {
|
|
9
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
10
|
+
for (let key of __getOwnPropNames(from))
|
|
11
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
12
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
13
|
+
}
|
|
14
|
+
return to;
|
|
15
|
+
};
|
|
16
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
17
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
18
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
19
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
20
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
21
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
22
|
+
mod
|
|
23
|
+
));
|
|
24
|
+
|
|
25
|
+
// src/scripts/infraUp.ts
|
|
26
|
+
var import_chalk2 = __toESM(require("chalk"));
|
|
27
|
+
|
|
28
|
+
// src/scripts/infraCommon.ts
|
|
29
|
+
var import_chalk = __toESM(require("chalk"));
|
|
30
|
+
var import_node_child_process = require("child_process");
|
|
31
|
+
var import_node_fs = require("fs");
|
|
32
|
+
var import_node_path = __toESM(require("path"));
|
|
33
|
+
var DEV_COMPOSE_FILE = "docker-compose.dev.yml";
|
|
34
|
+
var resolveProjectRoot = () => {
|
|
35
|
+
const cwd = process.cwd();
|
|
36
|
+
const composeInCwd = import_node_path.default.resolve(cwd, DEV_COMPOSE_FILE);
|
|
37
|
+
if ((0, import_node_fs.existsSync)(composeInCwd)) {
|
|
38
|
+
return cwd;
|
|
39
|
+
}
|
|
40
|
+
const fromEnv = String(process.env.PROJECT_CWD || "").trim();
|
|
41
|
+
if (fromEnv) {
|
|
42
|
+
const normalized = import_node_path.default.resolve(fromEnv);
|
|
43
|
+
const composeFromEnv = import_node_path.default.resolve(normalized, DEV_COMPOSE_FILE);
|
|
44
|
+
if ((0, import_node_fs.existsSync)(composeFromEnv)) {
|
|
45
|
+
return normalized;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return cwd;
|
|
49
|
+
};
|
|
50
|
+
var requireDevComposeFile = () => {
|
|
51
|
+
const composePath = import_node_path.default.resolve(resolveProjectRoot(), DEV_COMPOSE_FILE);
|
|
52
|
+
if ((0, import_node_fs.existsSync)(composePath)) {
|
|
53
|
+
console.log(import_chalk.default.gray(`Using existing ${DEV_COMPOSE_FILE}`));
|
|
54
|
+
return composePath;
|
|
55
|
+
}
|
|
56
|
+
throw new Error(
|
|
57
|
+
`${DEV_COMPOSE_FILE} not found in project root. Run "npx @tradejs/cli infra-init" first.`
|
|
58
|
+
);
|
|
59
|
+
};
|
|
60
|
+
var runDockerCompose = (composePath, args) => {
|
|
61
|
+
const result = (0, import_node_child_process.spawnSync)("docker", ["compose", "-f", composePath, ...args], {
|
|
62
|
+
stdio: "inherit"
|
|
63
|
+
});
|
|
64
|
+
if (result.error) {
|
|
65
|
+
throw result.error;
|
|
66
|
+
}
|
|
67
|
+
if ((result.status ?? 0) !== 0) {
|
|
68
|
+
process.exit(result.status ?? 1);
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
// src/scripts/infraUp.ts
|
|
73
|
+
var run = async () => {
|
|
74
|
+
const composePath = requireDevComposeFile();
|
|
75
|
+
console.log(import_chalk2.default.cyan("Starting dev infra (timescale, redis)..."));
|
|
76
|
+
runDockerCompose(composePath, ["up", "-d", "timescale", "redis"]);
|
|
77
|
+
console.log(import_chalk2.default.green("Dev infra is up."));
|
|
78
|
+
};
|
|
79
|
+
run().catch((error) => {
|
|
80
|
+
console.error(import_chalk2.default.red(`infra-up failed: ${String(error)}`));
|
|
81
|
+
process.exit(1);
|
|
82
|
+
});
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __copyProps = (to, from, except, desc) => {
|
|
9
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
10
|
+
for (let key of __getOwnPropNames(from))
|
|
11
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
12
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
13
|
+
}
|
|
14
|
+
return to;
|
|
15
|
+
};
|
|
16
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
17
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
18
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
19
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
20
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
21
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
22
|
+
mod
|
|
23
|
+
));
|
|
24
|
+
|
|
25
|
+
// src/scripts/migration.ts
|
|
26
|
+
var import_progress = __toESM(require("progress"));
|
|
27
|
+
var import_chalk = __toESM(require("chalk"));
|
|
28
|
+
var import_logger = require("@tradejs/infra/logger");
|
|
29
|
+
var import_files = require("@tradejs/infra/files");
|
|
30
|
+
var import_timescale = require("@tradejs/infra/timescale");
|
|
31
|
+
var DIR = "data/history";
|
|
32
|
+
var re = /^(.+?)_(\d+)\.json$/;
|
|
33
|
+
var BATCH = 2e3;
|
|
34
|
+
var migrateFile = async (file) => {
|
|
35
|
+
const m = re.exec(file);
|
|
36
|
+
if (!m) return;
|
|
37
|
+
const symbol = m[1];
|
|
38
|
+
const interval = Number(m[2]);
|
|
39
|
+
const data = await (0, import_files.getFile)(DIR, `${symbol}_${interval}`);
|
|
40
|
+
const rows = (0, import_timescale.toRows)(symbol, interval, data);
|
|
41
|
+
for (let i = 0; i < rows.length; i += BATCH) {
|
|
42
|
+
await (0, import_timescale.upsertCandles)(rows.slice(i, i + BATCH));
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
var migration = async () => {
|
|
46
|
+
const files = await (0, import_files.getFiles)(DIR);
|
|
47
|
+
const bar = new import_progress.default(
|
|
48
|
+
":current/:total [:bar][:percent] :eta(s) :file",
|
|
49
|
+
{
|
|
50
|
+
total: files.length,
|
|
51
|
+
width: 30
|
|
52
|
+
}
|
|
53
|
+
);
|
|
54
|
+
for await (const file of files) {
|
|
55
|
+
try {
|
|
56
|
+
await migrateFile(file);
|
|
57
|
+
} catch (e) {
|
|
58
|
+
import_logger.logger.error("Failed: %s %s", file, e);
|
|
59
|
+
} finally {
|
|
60
|
+
bar.tick(1, {
|
|
61
|
+
file: import_chalk.default.gray(file)
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
process.exit();
|
|
66
|
+
};
|
|
67
|
+
migration();
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __copyProps = (to, from, except, desc) => {
|
|
9
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
10
|
+
for (let key of __getOwnPropNames(from))
|
|
11
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
12
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
13
|
+
}
|
|
14
|
+
return to;
|
|
15
|
+
};
|
|
16
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
17
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
18
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
19
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
20
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
21
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
22
|
+
mod
|
|
23
|
+
));
|
|
24
|
+
|
|
25
|
+
// src/scripts/mlExport.ts
|
|
26
|
+
var import_args = __toESM(require("args"));
|
|
27
|
+
var import_chalk = __toESM(require("chalk"));
|
|
28
|
+
var import_promises = __toESM(require("fs/promises"));
|
|
29
|
+
var import_path = __toESM(require("path"));
|
|
30
|
+
var import_ml = require("@tradejs/infra/ml");
|
|
31
|
+
import_args.default.example(
|
|
32
|
+
"yarn ts-node ./src/scripts/mlExport --strategy trendline",
|
|
33
|
+
"Merge per-worker ML chunks into one dataset JSONL"
|
|
34
|
+
);
|
|
35
|
+
import_args.default.option(["o", "outDir"], "Dataset directory", "data/ml/export");
|
|
36
|
+
import_args.default.option(["s", "strategy"], "Strategy name", "");
|
|
37
|
+
import_args.default.option(
|
|
38
|
+
["k", "keepChunks"],
|
|
39
|
+
"Keep source chunk files after successful merge",
|
|
40
|
+
false
|
|
41
|
+
);
|
|
42
|
+
var flags = import_args.default.parse(process.argv);
|
|
43
|
+
var listChunkFiles = async (outDir, strategyName) => {
|
|
44
|
+
const prefix = `ml-dataset-${(0, import_ml.toFileToken)(strategyName)}-chunk-`;
|
|
45
|
+
const entries = await import_promises.default.readdir(outDir, { withFileTypes: true });
|
|
46
|
+
return entries.filter((entry) => entry.isFile()).map((entry) => entry.name).filter((name) => name.startsWith(prefix) && name.endsWith(".jsonl")).map((name) => import_path.default.join(outDir, name)).sort();
|
|
47
|
+
};
|
|
48
|
+
var resolveStrategyName = async () => {
|
|
49
|
+
const raw = String(flags.strategy || "").trim();
|
|
50
|
+
if (raw) {
|
|
51
|
+
return raw;
|
|
52
|
+
}
|
|
53
|
+
throw new Error("Missing --strategy. Use mlExportSelect or pass --strategy.");
|
|
54
|
+
};
|
|
55
|
+
var main = async () => {
|
|
56
|
+
const outDir = String(flags.outDir || "data/ml/export");
|
|
57
|
+
const strategyName = await resolveStrategyName();
|
|
58
|
+
await import_promises.default.mkdir(outDir, { recursive: true });
|
|
59
|
+
const chunkFiles = await listChunkFiles(outDir, strategyName);
|
|
60
|
+
if (!chunkFiles.length) {
|
|
61
|
+
console.log(
|
|
62
|
+
import_chalk.default.yellow(
|
|
63
|
+
`No chunk files found for strategy "${strategyName}" in ${outDir}`
|
|
64
|
+
)
|
|
65
|
+
);
|
|
66
|
+
process.exit(0);
|
|
67
|
+
}
|
|
68
|
+
const mergedPath = import_path.default.join(
|
|
69
|
+
outDir,
|
|
70
|
+
`ml-dataset-${(0, import_ml.toFileToken)(strategyName)}-merged-${Date.now()}.jsonl`
|
|
71
|
+
);
|
|
72
|
+
await (0, import_ml.mergeJsonlFiles)({
|
|
73
|
+
filePaths: chunkFiles,
|
|
74
|
+
outPath: mergedPath
|
|
75
|
+
});
|
|
76
|
+
const shouldDeleteChunks = !Boolean(flags.keepChunks);
|
|
77
|
+
if (shouldDeleteChunks) {
|
|
78
|
+
for (const filePath of chunkFiles) {
|
|
79
|
+
await import_promises.default.rm(filePath, { force: true });
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
console.log(import_chalk.default.green(`Merged dataset saved: ${mergedPath}`));
|
|
83
|
+
console.log(
|
|
84
|
+
import_chalk.default.gray(
|
|
85
|
+
`strategy=${strategyName}, source_chunks=${chunkFiles.length}, deleteChunks=${Boolean(
|
|
86
|
+
shouldDeleteChunks
|
|
87
|
+
)}`
|
|
88
|
+
)
|
|
89
|
+
);
|
|
90
|
+
process.exit(0);
|
|
91
|
+
};
|
|
92
|
+
main().catch((error) => {
|
|
93
|
+
console.error(import_chalk.default.red(error?.message || String(error)));
|
|
94
|
+
process.exit(1);
|
|
95
|
+
});
|