@tradejs/infra 1.0.9 → 1.0.10
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/ai.d.mts +39 -3
- package/dist/ai.d.ts +39 -3
- package/dist/ai.js +404 -28
- package/dist/ai.mjs +372 -24
- package/dist/backtestArtifacts.d.mts +57 -0
- package/dist/backtestArtifacts.d.ts +57 -0
- package/dist/backtestArtifacts.js +255 -0
- package/dist/backtestArtifacts.mjs +211 -0
- package/dist/{chunk-MLVWC2I2.mjs → chunk-DXG2UDNA.mjs} +60 -5
- package/dist/{chunk-KVEZORMS.mjs → chunk-RQP5VSTH.mjs} +54 -3
- package/dist/ml.d.mts +1 -1
- package/dist/ml.d.ts +1 -1
- package/dist/ml.js +55 -3
- package/dist/ml.mjs +3 -1
- package/dist/{mlDatasetFile-sRGWgR_o.d.mts → mlDatasetFile-Czx__g9M.d.mts} +7 -1
- package/dist/{mlDatasetFile-sRGWgR_o.d.ts → mlDatasetFile-Czx__g9M.d.ts} +7 -1
- package/dist/redis.d.mts +21 -3
- package/dist/redis.d.ts +21 -3
- package/dist/redis.js +63 -5
- package/dist/redis.mjs +7 -1
- package/dist/timescale.d.mts +220 -5
- package/dist/timescale.d.ts +220 -5
- package/dist/timescale.js +1983 -93
- package/dist/timescale.mjs +1955 -93
- package/dist/tradingAccounts.d.mts +20 -0
- package/dist/tradingAccounts.d.ts +20 -0
- package/dist/tradingAccounts.js +556 -0
- package/dist/tradingAccounts.mjs +190 -0
- package/dist/userSettings.d.mts +2 -0
- package/dist/userSettings.d.ts +2 -0
- package/dist/userSettings.js +24 -5
- package/dist/userSettings.mjs +2 -1
- package/package.json +13 -3
|
@@ -0,0 +1,255 @@
|
|
|
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/backtestArtifacts.ts
|
|
31
|
+
var backtestArtifacts_exports = {};
|
|
32
|
+
__export(backtestArtifacts_exports, {
|
|
33
|
+
deleteCachedBacktestArtifacts: () => deleteCachedBacktestArtifacts,
|
|
34
|
+
deletePersistedBacktestOrderLog: () => deletePersistedBacktestOrderLog,
|
|
35
|
+
getBacktestArtifactsRootDir: () => getBacktestArtifactsRootDir,
|
|
36
|
+
getBacktestCacheArtifactsDirForUser: () => getBacktestCacheArtifactsDirForUser,
|
|
37
|
+
getPersistedBacktestArtifactsDirForUser: () => getPersistedBacktestArtifactsDirForUser,
|
|
38
|
+
parseBacktestArtifactRef: () => parseBacktestArtifactRef,
|
|
39
|
+
readCachedBacktestArtifacts: () => readCachedBacktestArtifacts,
|
|
40
|
+
readPersistedBacktestOrderLog: () => readPersistedBacktestOrderLog,
|
|
41
|
+
writeCachedBacktestArtifacts: () => writeCachedBacktestArtifacts,
|
|
42
|
+
writePersistedBacktestOrderLog: () => writePersistedBacktestOrderLog
|
|
43
|
+
});
|
|
44
|
+
module.exports = __toCommonJS(backtestArtifacts_exports);
|
|
45
|
+
var import_promises = __toESM(require("fs/promises"));
|
|
46
|
+
var import_path = __toESM(require("path"));
|
|
47
|
+
var BACKTEST_ARTIFACTS_DIR = import_path.default.join("data", "backtests");
|
|
48
|
+
var resolveProjectRoot = (projectRoot) => {
|
|
49
|
+
const explicit = String(projectRoot || "").trim();
|
|
50
|
+
if (explicit) {
|
|
51
|
+
return import_path.default.resolve(explicit);
|
|
52
|
+
}
|
|
53
|
+
const fromEnv = String(process.env.PROJECT_CWD || "").trim();
|
|
54
|
+
if (fromEnv) {
|
|
55
|
+
return import_path.default.resolve(fromEnv);
|
|
56
|
+
}
|
|
57
|
+
return process.cwd();
|
|
58
|
+
};
|
|
59
|
+
var encodeSegment = (value) => encodeURIComponent(String(value));
|
|
60
|
+
var toProjectRelativePath = (projectRoot, absolutePath) => import_path.default.relative(projectRoot, absolutePath);
|
|
61
|
+
var resolveArtifactPath = (relativePath, projectRoot) => {
|
|
62
|
+
const root = resolveProjectRoot(projectRoot);
|
|
63
|
+
return import_path.default.isAbsolute(relativePath) ? relativePath : import_path.default.resolve(root, relativePath);
|
|
64
|
+
};
|
|
65
|
+
var isEnoentError = (error) => error?.code === "ENOENT";
|
|
66
|
+
var createRef = (absolutePath, projectRoot) => ({
|
|
67
|
+
kind: "file",
|
|
68
|
+
version: 1,
|
|
69
|
+
path: toProjectRelativePath(resolveProjectRoot(projectRoot), absolutePath)
|
|
70
|
+
});
|
|
71
|
+
var isBacktestArtifactRef = (value) => Boolean(
|
|
72
|
+
value && typeof value === "object" && value.kind === "file" && value.version === 1 && typeof value.path === "string"
|
|
73
|
+
);
|
|
74
|
+
var getCachedArtifactPath = (userName, orderLogId, artifactName, projectRoot) => import_path.default.join(
|
|
75
|
+
resolveProjectRoot(projectRoot),
|
|
76
|
+
BACKTEST_ARTIFACTS_DIR,
|
|
77
|
+
"cache",
|
|
78
|
+
encodeSegment(userName),
|
|
79
|
+
artifactName,
|
|
80
|
+
`${encodeSegment(orderLogId)}.json`
|
|
81
|
+
);
|
|
82
|
+
var getPersistedOrderLogPath = (userName, strategyName, testName, projectRoot) => import_path.default.join(
|
|
83
|
+
resolveProjectRoot(projectRoot),
|
|
84
|
+
BACKTEST_ARTIFACTS_DIR,
|
|
85
|
+
"tests",
|
|
86
|
+
encodeSegment(userName),
|
|
87
|
+
encodeSegment(strategyName),
|
|
88
|
+
`${encodeSegment(testName)}.json`
|
|
89
|
+
);
|
|
90
|
+
var readJsonFile = async (absolutePath, fallback) => {
|
|
91
|
+
try {
|
|
92
|
+
const raw = await import_promises.default.readFile(absolutePath, "utf8");
|
|
93
|
+
return JSON.parse(raw);
|
|
94
|
+
} catch (error) {
|
|
95
|
+
if (isEnoentError(error)) {
|
|
96
|
+
return fallback;
|
|
97
|
+
}
|
|
98
|
+
throw error;
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
var writeJsonFile = async (absolutePath, value) => {
|
|
102
|
+
await import_promises.default.mkdir(import_path.default.dirname(absolutePath), { recursive: true });
|
|
103
|
+
await import_promises.default.writeFile(absolutePath, JSON.stringify(value), "utf8");
|
|
104
|
+
};
|
|
105
|
+
var removeFileIfExists = async (absolutePath) => {
|
|
106
|
+
try {
|
|
107
|
+
await import_promises.default.rm(absolutePath, { force: true });
|
|
108
|
+
return true;
|
|
109
|
+
} catch (error) {
|
|
110
|
+
if (isEnoentError(error)) {
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
throw error;
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
var writeCachedBacktestArtifacts = async ({
|
|
117
|
+
orderLog,
|
|
118
|
+
orderLogId,
|
|
119
|
+
positionLog,
|
|
120
|
+
projectRoot,
|
|
121
|
+
userName
|
|
122
|
+
}) => {
|
|
123
|
+
const orderPath = getCachedArtifactPath(
|
|
124
|
+
userName,
|
|
125
|
+
orderLogId,
|
|
126
|
+
"orders",
|
|
127
|
+
projectRoot
|
|
128
|
+
);
|
|
129
|
+
const positionPath = getCachedArtifactPath(
|
|
130
|
+
userName,
|
|
131
|
+
orderLogId,
|
|
132
|
+
"positions",
|
|
133
|
+
projectRoot
|
|
134
|
+
);
|
|
135
|
+
await Promise.all([
|
|
136
|
+
writeJsonFile(orderPath, orderLog),
|
|
137
|
+
writeJsonFile(positionPath, positionLog)
|
|
138
|
+
]);
|
|
139
|
+
return {
|
|
140
|
+
orderLog: createRef(orderPath, projectRoot),
|
|
141
|
+
positionLog: createRef(positionPath, projectRoot)
|
|
142
|
+
};
|
|
143
|
+
};
|
|
144
|
+
var readCachedBacktestArtifacts = async ({
|
|
145
|
+
orderLogId,
|
|
146
|
+
projectRoot,
|
|
147
|
+
userName
|
|
148
|
+
}) => {
|
|
149
|
+
const orderPath = getCachedArtifactPath(
|
|
150
|
+
userName,
|
|
151
|
+
orderLogId,
|
|
152
|
+
"orders",
|
|
153
|
+
projectRoot
|
|
154
|
+
);
|
|
155
|
+
const positionPath = getCachedArtifactPath(
|
|
156
|
+
userName,
|
|
157
|
+
orderLogId,
|
|
158
|
+
"positions",
|
|
159
|
+
projectRoot
|
|
160
|
+
);
|
|
161
|
+
const [orderLog, positionLog] = await Promise.all([
|
|
162
|
+
readJsonFile(orderPath, null),
|
|
163
|
+
readJsonFile(positionPath, null)
|
|
164
|
+
]);
|
|
165
|
+
return { orderLog, positionLog };
|
|
166
|
+
};
|
|
167
|
+
var deleteCachedBacktestArtifacts = async ({
|
|
168
|
+
orderLogId,
|
|
169
|
+
projectRoot,
|
|
170
|
+
userName
|
|
171
|
+
}) => {
|
|
172
|
+
const orderPath = getCachedArtifactPath(
|
|
173
|
+
userName,
|
|
174
|
+
orderLogId,
|
|
175
|
+
"orders",
|
|
176
|
+
projectRoot
|
|
177
|
+
);
|
|
178
|
+
const positionPath = getCachedArtifactPath(
|
|
179
|
+
userName,
|
|
180
|
+
orderLogId,
|
|
181
|
+
"positions",
|
|
182
|
+
projectRoot
|
|
183
|
+
);
|
|
184
|
+
const [removedOrderLog, removedPositionLog] = await Promise.all([
|
|
185
|
+
removeFileIfExists(orderPath),
|
|
186
|
+
removeFileIfExists(positionPath)
|
|
187
|
+
]);
|
|
188
|
+
return removedOrderLog || removedPositionLog;
|
|
189
|
+
};
|
|
190
|
+
var writePersistedBacktestOrderLog = async ({
|
|
191
|
+
orderLog,
|
|
192
|
+
projectRoot,
|
|
193
|
+
strategyName,
|
|
194
|
+
testName,
|
|
195
|
+
userName
|
|
196
|
+
}) => {
|
|
197
|
+
const absolutePath = getPersistedOrderLogPath(
|
|
198
|
+
userName,
|
|
199
|
+
strategyName,
|
|
200
|
+
testName,
|
|
201
|
+
projectRoot
|
|
202
|
+
);
|
|
203
|
+
await writeJsonFile(absolutePath, orderLog);
|
|
204
|
+
return createRef(absolutePath, projectRoot);
|
|
205
|
+
};
|
|
206
|
+
var readPersistedBacktestOrderLog = async ({
|
|
207
|
+
projectRoot,
|
|
208
|
+
ref,
|
|
209
|
+
strategyName,
|
|
210
|
+
testName,
|
|
211
|
+
userName
|
|
212
|
+
}) => {
|
|
213
|
+
const absolutePath = ref ? resolveArtifactPath(ref.path, projectRoot) : getPersistedOrderLogPath(userName, strategyName, testName, projectRoot);
|
|
214
|
+
return readJsonFile(absolutePath, null);
|
|
215
|
+
};
|
|
216
|
+
var deletePersistedBacktestOrderLog = async ({
|
|
217
|
+
projectRoot,
|
|
218
|
+
ref,
|
|
219
|
+
strategyName,
|
|
220
|
+
testName,
|
|
221
|
+
userName
|
|
222
|
+
}) => {
|
|
223
|
+
const absolutePath = ref ? resolveArtifactPath(ref.path, projectRoot) : getPersistedOrderLogPath(userName, strategyName, testName, projectRoot);
|
|
224
|
+
return removeFileIfExists(absolutePath);
|
|
225
|
+
};
|
|
226
|
+
var parseBacktestArtifactRef = (value) => {
|
|
227
|
+
if (isBacktestArtifactRef(value)) {
|
|
228
|
+
return value;
|
|
229
|
+
}
|
|
230
|
+
return null;
|
|
231
|
+
};
|
|
232
|
+
var getBacktestArtifactsRootDir = (projectRoot) => import_path.default.join(resolveProjectRoot(projectRoot), BACKTEST_ARTIFACTS_DIR);
|
|
233
|
+
var getBacktestCacheArtifactsDirForUser = (userName, projectRoot) => import_path.default.join(
|
|
234
|
+
getBacktestArtifactsRootDir(projectRoot),
|
|
235
|
+
"cache",
|
|
236
|
+
encodeSegment(userName)
|
|
237
|
+
);
|
|
238
|
+
var getPersistedBacktestArtifactsDirForUser = (userName, projectRoot) => import_path.default.join(
|
|
239
|
+
getBacktestArtifactsRootDir(projectRoot),
|
|
240
|
+
"tests",
|
|
241
|
+
encodeSegment(userName)
|
|
242
|
+
);
|
|
243
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
244
|
+
0 && (module.exports = {
|
|
245
|
+
deleteCachedBacktestArtifacts,
|
|
246
|
+
deletePersistedBacktestOrderLog,
|
|
247
|
+
getBacktestArtifactsRootDir,
|
|
248
|
+
getBacktestCacheArtifactsDirForUser,
|
|
249
|
+
getPersistedBacktestArtifactsDirForUser,
|
|
250
|
+
parseBacktestArtifactRef,
|
|
251
|
+
readCachedBacktestArtifacts,
|
|
252
|
+
readPersistedBacktestOrderLog,
|
|
253
|
+
writeCachedBacktestArtifacts,
|
|
254
|
+
writePersistedBacktestOrderLog
|
|
255
|
+
});
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
// src/backtestArtifacts.ts
|
|
2
|
+
import fs from "fs/promises";
|
|
3
|
+
import path from "path";
|
|
4
|
+
var BACKTEST_ARTIFACTS_DIR = path.join("data", "backtests");
|
|
5
|
+
var resolveProjectRoot = (projectRoot) => {
|
|
6
|
+
const explicit = String(projectRoot || "").trim();
|
|
7
|
+
if (explicit) {
|
|
8
|
+
return path.resolve(explicit);
|
|
9
|
+
}
|
|
10
|
+
const fromEnv = String(process.env.PROJECT_CWD || "").trim();
|
|
11
|
+
if (fromEnv) {
|
|
12
|
+
return path.resolve(fromEnv);
|
|
13
|
+
}
|
|
14
|
+
return process.cwd();
|
|
15
|
+
};
|
|
16
|
+
var encodeSegment = (value) => encodeURIComponent(String(value));
|
|
17
|
+
var toProjectRelativePath = (projectRoot, absolutePath) => path.relative(projectRoot, absolutePath);
|
|
18
|
+
var resolveArtifactPath = (relativePath, projectRoot) => {
|
|
19
|
+
const root = resolveProjectRoot(projectRoot);
|
|
20
|
+
return path.isAbsolute(relativePath) ? relativePath : path.resolve(root, relativePath);
|
|
21
|
+
};
|
|
22
|
+
var isEnoentError = (error) => error?.code === "ENOENT";
|
|
23
|
+
var createRef = (absolutePath, projectRoot) => ({
|
|
24
|
+
kind: "file",
|
|
25
|
+
version: 1,
|
|
26
|
+
path: toProjectRelativePath(resolveProjectRoot(projectRoot), absolutePath)
|
|
27
|
+
});
|
|
28
|
+
var isBacktestArtifactRef = (value) => Boolean(
|
|
29
|
+
value && typeof value === "object" && value.kind === "file" && value.version === 1 && typeof value.path === "string"
|
|
30
|
+
);
|
|
31
|
+
var getCachedArtifactPath = (userName, orderLogId, artifactName, projectRoot) => path.join(
|
|
32
|
+
resolveProjectRoot(projectRoot),
|
|
33
|
+
BACKTEST_ARTIFACTS_DIR,
|
|
34
|
+
"cache",
|
|
35
|
+
encodeSegment(userName),
|
|
36
|
+
artifactName,
|
|
37
|
+
`${encodeSegment(orderLogId)}.json`
|
|
38
|
+
);
|
|
39
|
+
var getPersistedOrderLogPath = (userName, strategyName, testName, projectRoot) => path.join(
|
|
40
|
+
resolveProjectRoot(projectRoot),
|
|
41
|
+
BACKTEST_ARTIFACTS_DIR,
|
|
42
|
+
"tests",
|
|
43
|
+
encodeSegment(userName),
|
|
44
|
+
encodeSegment(strategyName),
|
|
45
|
+
`${encodeSegment(testName)}.json`
|
|
46
|
+
);
|
|
47
|
+
var readJsonFile = async (absolutePath, fallback) => {
|
|
48
|
+
try {
|
|
49
|
+
const raw = await fs.readFile(absolutePath, "utf8");
|
|
50
|
+
return JSON.parse(raw);
|
|
51
|
+
} catch (error) {
|
|
52
|
+
if (isEnoentError(error)) {
|
|
53
|
+
return fallback;
|
|
54
|
+
}
|
|
55
|
+
throw error;
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
var writeJsonFile = async (absolutePath, value) => {
|
|
59
|
+
await fs.mkdir(path.dirname(absolutePath), { recursive: true });
|
|
60
|
+
await fs.writeFile(absolutePath, JSON.stringify(value), "utf8");
|
|
61
|
+
};
|
|
62
|
+
var removeFileIfExists = async (absolutePath) => {
|
|
63
|
+
try {
|
|
64
|
+
await fs.rm(absolutePath, { force: true });
|
|
65
|
+
return true;
|
|
66
|
+
} catch (error) {
|
|
67
|
+
if (isEnoentError(error)) {
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
throw error;
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
var writeCachedBacktestArtifacts = async ({
|
|
74
|
+
orderLog,
|
|
75
|
+
orderLogId,
|
|
76
|
+
positionLog,
|
|
77
|
+
projectRoot,
|
|
78
|
+
userName
|
|
79
|
+
}) => {
|
|
80
|
+
const orderPath = getCachedArtifactPath(
|
|
81
|
+
userName,
|
|
82
|
+
orderLogId,
|
|
83
|
+
"orders",
|
|
84
|
+
projectRoot
|
|
85
|
+
);
|
|
86
|
+
const positionPath = getCachedArtifactPath(
|
|
87
|
+
userName,
|
|
88
|
+
orderLogId,
|
|
89
|
+
"positions",
|
|
90
|
+
projectRoot
|
|
91
|
+
);
|
|
92
|
+
await Promise.all([
|
|
93
|
+
writeJsonFile(orderPath, orderLog),
|
|
94
|
+
writeJsonFile(positionPath, positionLog)
|
|
95
|
+
]);
|
|
96
|
+
return {
|
|
97
|
+
orderLog: createRef(orderPath, projectRoot),
|
|
98
|
+
positionLog: createRef(positionPath, projectRoot)
|
|
99
|
+
};
|
|
100
|
+
};
|
|
101
|
+
var readCachedBacktestArtifacts = async ({
|
|
102
|
+
orderLogId,
|
|
103
|
+
projectRoot,
|
|
104
|
+
userName
|
|
105
|
+
}) => {
|
|
106
|
+
const orderPath = getCachedArtifactPath(
|
|
107
|
+
userName,
|
|
108
|
+
orderLogId,
|
|
109
|
+
"orders",
|
|
110
|
+
projectRoot
|
|
111
|
+
);
|
|
112
|
+
const positionPath = getCachedArtifactPath(
|
|
113
|
+
userName,
|
|
114
|
+
orderLogId,
|
|
115
|
+
"positions",
|
|
116
|
+
projectRoot
|
|
117
|
+
);
|
|
118
|
+
const [orderLog, positionLog] = await Promise.all([
|
|
119
|
+
readJsonFile(orderPath, null),
|
|
120
|
+
readJsonFile(positionPath, null)
|
|
121
|
+
]);
|
|
122
|
+
return { orderLog, positionLog };
|
|
123
|
+
};
|
|
124
|
+
var deleteCachedBacktestArtifacts = async ({
|
|
125
|
+
orderLogId,
|
|
126
|
+
projectRoot,
|
|
127
|
+
userName
|
|
128
|
+
}) => {
|
|
129
|
+
const orderPath = getCachedArtifactPath(
|
|
130
|
+
userName,
|
|
131
|
+
orderLogId,
|
|
132
|
+
"orders",
|
|
133
|
+
projectRoot
|
|
134
|
+
);
|
|
135
|
+
const positionPath = getCachedArtifactPath(
|
|
136
|
+
userName,
|
|
137
|
+
orderLogId,
|
|
138
|
+
"positions",
|
|
139
|
+
projectRoot
|
|
140
|
+
);
|
|
141
|
+
const [removedOrderLog, removedPositionLog] = await Promise.all([
|
|
142
|
+
removeFileIfExists(orderPath),
|
|
143
|
+
removeFileIfExists(positionPath)
|
|
144
|
+
]);
|
|
145
|
+
return removedOrderLog || removedPositionLog;
|
|
146
|
+
};
|
|
147
|
+
var writePersistedBacktestOrderLog = async ({
|
|
148
|
+
orderLog,
|
|
149
|
+
projectRoot,
|
|
150
|
+
strategyName,
|
|
151
|
+
testName,
|
|
152
|
+
userName
|
|
153
|
+
}) => {
|
|
154
|
+
const absolutePath = getPersistedOrderLogPath(
|
|
155
|
+
userName,
|
|
156
|
+
strategyName,
|
|
157
|
+
testName,
|
|
158
|
+
projectRoot
|
|
159
|
+
);
|
|
160
|
+
await writeJsonFile(absolutePath, orderLog);
|
|
161
|
+
return createRef(absolutePath, projectRoot);
|
|
162
|
+
};
|
|
163
|
+
var readPersistedBacktestOrderLog = async ({
|
|
164
|
+
projectRoot,
|
|
165
|
+
ref,
|
|
166
|
+
strategyName,
|
|
167
|
+
testName,
|
|
168
|
+
userName
|
|
169
|
+
}) => {
|
|
170
|
+
const absolutePath = ref ? resolveArtifactPath(ref.path, projectRoot) : getPersistedOrderLogPath(userName, strategyName, testName, projectRoot);
|
|
171
|
+
return readJsonFile(absolutePath, null);
|
|
172
|
+
};
|
|
173
|
+
var deletePersistedBacktestOrderLog = async ({
|
|
174
|
+
projectRoot,
|
|
175
|
+
ref,
|
|
176
|
+
strategyName,
|
|
177
|
+
testName,
|
|
178
|
+
userName
|
|
179
|
+
}) => {
|
|
180
|
+
const absolutePath = ref ? resolveArtifactPath(ref.path, projectRoot) : getPersistedOrderLogPath(userName, strategyName, testName, projectRoot);
|
|
181
|
+
return removeFileIfExists(absolutePath);
|
|
182
|
+
};
|
|
183
|
+
var parseBacktestArtifactRef = (value) => {
|
|
184
|
+
if (isBacktestArtifactRef(value)) {
|
|
185
|
+
return value;
|
|
186
|
+
}
|
|
187
|
+
return null;
|
|
188
|
+
};
|
|
189
|
+
var getBacktestArtifactsRootDir = (projectRoot) => path.join(resolveProjectRoot(projectRoot), BACKTEST_ARTIFACTS_DIR);
|
|
190
|
+
var getBacktestCacheArtifactsDirForUser = (userName, projectRoot) => path.join(
|
|
191
|
+
getBacktestArtifactsRootDir(projectRoot),
|
|
192
|
+
"cache",
|
|
193
|
+
encodeSegment(userName)
|
|
194
|
+
);
|
|
195
|
+
var getPersistedBacktestArtifactsDirForUser = (userName, projectRoot) => path.join(
|
|
196
|
+
getBacktestArtifactsRootDir(projectRoot),
|
|
197
|
+
"tests",
|
|
198
|
+
encodeSegment(userName)
|
|
199
|
+
);
|
|
200
|
+
export {
|
|
201
|
+
deleteCachedBacktestArtifacts,
|
|
202
|
+
deletePersistedBacktestOrderLog,
|
|
203
|
+
getBacktestArtifactsRootDir,
|
|
204
|
+
getBacktestCacheArtifactsDirForUser,
|
|
205
|
+
getPersistedBacktestArtifactsDirForUser,
|
|
206
|
+
parseBacktestArtifactRef,
|
|
207
|
+
readCachedBacktestArtifacts,
|
|
208
|
+
readPersistedBacktestOrderLog,
|
|
209
|
+
writeCachedBacktestArtifacts,
|
|
210
|
+
writePersistedBacktestOrderLog
|
|
211
|
+
};
|
|
@@ -12,9 +12,12 @@ var logger = {
|
|
|
12
12
|
};
|
|
13
13
|
var redisConnectionWarningShown = false;
|
|
14
14
|
var redisUnavailable = false;
|
|
15
|
-
var isRedisConnectivityError = (error) =>
|
|
16
|
-
error.message
|
|
17
|
-
|
|
15
|
+
var isRedisConnectivityError = (error) => {
|
|
16
|
+
const errorText = [error.name, error.message, String(error)].join(" ");
|
|
17
|
+
return /ECONNREFUSED|ECONNRESET|ECONNABORTED|EPIPE|ENOTFOUND|EAI_AGAIN|ETIMEDOUT|MaxRetriesPerRequestError|Connection is closed|Stream isn't writeable/i.test(
|
|
18
|
+
errorText
|
|
19
|
+
);
|
|
20
|
+
};
|
|
18
21
|
var toNonNegativeInt = (value, fallback) => {
|
|
19
22
|
const parsed = Number.parseInt(String(value ?? ""), 10);
|
|
20
23
|
return Number.isFinite(parsed) && parsed >= 0 ? parsed : fallback;
|
|
@@ -70,6 +73,16 @@ var getRedis = () => {
|
|
|
70
73
|
}
|
|
71
74
|
return global.__redis__;
|
|
72
75
|
};
|
|
76
|
+
var closeRedisConnection = async () => {
|
|
77
|
+
const redis = global.__redis__;
|
|
78
|
+
if (!redis) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
global.__redis__ = void 0;
|
|
82
|
+
redisUnavailable = false;
|
|
83
|
+
redisConnectionWarningShown = false;
|
|
84
|
+
redis.disconnect();
|
|
85
|
+
};
|
|
73
86
|
var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
74
87
|
var getRedisStatus = (redis) => String(redis.status ?? "ready");
|
|
75
88
|
var waitForRedisReady = async (redis) => {
|
|
@@ -110,6 +123,11 @@ var toResultString = (result) => {
|
|
|
110
123
|
if (Buffer.isBuffer(result)) return result.toString("utf8");
|
|
111
124
|
return String(result);
|
|
112
125
|
};
|
|
126
|
+
var publishData = async (channel, value) => {
|
|
127
|
+
const redis = await getReadyRedis();
|
|
128
|
+
if (!redis) return 0;
|
|
129
|
+
return redis.publish(channel, toJson(value));
|
|
130
|
+
};
|
|
113
131
|
var DEFAULT_OPTIONS = {
|
|
114
132
|
expire: TTL_1D
|
|
115
133
|
};
|
|
@@ -301,6 +319,25 @@ var setHashJsonField = async (key, field, data, options = {}) => {
|
|
|
301
319
|
logger.log("error", "failed HSET %s[%s]: %s", key, field, String(e));
|
|
302
320
|
}
|
|
303
321
|
};
|
|
322
|
+
var getHashJsonField = async (key, field, fallback = null) => {
|
|
323
|
+
if (redisUnavailable) return fallback;
|
|
324
|
+
const redis = await getReadyRedis();
|
|
325
|
+
if (!redis) return fallback;
|
|
326
|
+
try {
|
|
327
|
+
const value = await redis.call("HGET", key, field);
|
|
328
|
+
if (typeof value !== "string" || !value) {
|
|
329
|
+
return fallback;
|
|
330
|
+
}
|
|
331
|
+
return JSON.parse(value);
|
|
332
|
+
} catch (e) {
|
|
333
|
+
if (e instanceof Error && isRedisConnectivityError(e)) {
|
|
334
|
+
markRedisUnavailable(e);
|
|
335
|
+
return fallback;
|
|
336
|
+
}
|
|
337
|
+
logger.log("error", "failed HGET %s[%s]: %s", key, field, String(e));
|
|
338
|
+
return fallback;
|
|
339
|
+
}
|
|
340
|
+
};
|
|
304
341
|
var getHashJsonValues = async (key) => {
|
|
305
342
|
if (redisUnavailable) return [];
|
|
306
343
|
const redis = await getReadyRedis();
|
|
@@ -406,13 +443,21 @@ var consumeScreenshotSessionToken = async (token) => {
|
|
|
406
443
|
var redisKeys = {
|
|
407
444
|
users: () => "users:index:",
|
|
408
445
|
user: (userName) => `users:index:${userName}`,
|
|
446
|
+
tradingAccounts: (userName) => `users:${userName}:trading-accounts:`,
|
|
447
|
+
tradingAccount: (userName, accountId) => `users:${userName}:trading-accounts:${accountId}`,
|
|
448
|
+
runtimeDeployments: (userName) => `users:${userName}:runtime:deployments:`,
|
|
449
|
+
runtimeDeployment: (userName, deploymentId) => `users:${userName}:runtime:deployments:${deploymentId}`,
|
|
450
|
+
runtimeDeploymentHeartbeat: (userName, deploymentId) => `users:${userName}:runtime:deployments:${deploymentId}:heartbeat`,
|
|
409
451
|
bots: (userName) => `users:${userName}:bots`,
|
|
410
452
|
botsPrefix: () => "users:",
|
|
411
453
|
bot: (userName, botId) => `users:${userName}:bots:${botId}`,
|
|
412
454
|
backtestConfig: (userName, config) => `users:${userName}:backtests:configs:${config}`,
|
|
413
455
|
strategies: (userName) => `users:${userName}:strategies`,
|
|
414
|
-
strategyConfig: (userName, strategyName) => `users:${userName}:strategies:${strategyName}
|
|
456
|
+
strategyConfig: (userName, strategyName, configId = "config") => `users:${userName}:strategies:${strategyName}:${configId}`,
|
|
415
457
|
strategyResults: (userName, strategyName) => `users:${userName}:strategies:${strategyName}:results`,
|
|
458
|
+
strategyCharts: (userName, mode) => `users:${userName}:strategies:charts:${mode}`,
|
|
459
|
+
strategyChartCards: (userName, mode) => `users:${userName}:strategies:charts:${mode}:cards:`,
|
|
460
|
+
strategyChartCard: (userName, mode, cardId) => `users:${userName}:strategies:charts:${mode}:cards:${cardId}`,
|
|
416
461
|
tests: (userName, strategyName) => strategyName ? `users:${userName}:tests:${strategyName}` : `users:${userName}:tests:`,
|
|
417
462
|
testOrders: (userName, strategyName, testName) => `users:${userName}:tests:${strategyName}:${testName}:orders`,
|
|
418
463
|
testConfig: (userName, strategyName, testName) => `users:${userName}:tests:${strategyName}:${testName}:config`,
|
|
@@ -421,6 +466,7 @@ var redisKeys = {
|
|
|
421
466
|
cacheChunk: (userName, chunkId) => `users:${userName}:cache:tests:chunks:${chunkId}`,
|
|
422
467
|
cacheOrders: (userName, orderLogId) => `users:${userName}:cache:tests:orders:${orderLogId}`,
|
|
423
468
|
cachePositions: (userName, orderLogId) => `users:${userName}:cache:tests:positions:${orderLogId}`,
|
|
469
|
+
tickerUniverse: (userName, connectorName, universe, accountId) => universe || accountId ? `users:${userName}:cache:tickers:${connectorName}:${universe ?? "crypto"}:${accountId ?? "default"}` : `users:${userName}:cache:tickers:${connectorName}`,
|
|
424
470
|
signal: (symbol, signalId) => `signals:${symbol}:${signalId}`,
|
|
425
471
|
signalsBySymbol: (symbol) => `signals:${symbol}:`,
|
|
426
472
|
storeSignal: (symbol, signalId) => `store:signals:${symbol}:${signalId}`,
|
|
@@ -436,12 +482,18 @@ var redisKeys = {
|
|
|
436
482
|
runtimeSignalEvaluationStatsBucket: (userName, dayKey, strategyName) => `users:${userName}:runtime:signal-evaluation-stats:days:${dayKey}:${strategyName}`,
|
|
437
483
|
runtimeTrades: (userName) => `users:${userName}:runtime:trade-records:`,
|
|
438
484
|
runtimeTrade: (userName, orderId) => `users:${userName}:runtime:trade-records:${orderId}`,
|
|
485
|
+
runtimeTradeBuckets: (userName) => `users:${userName}:runtime:trade-records:days:`,
|
|
486
|
+
runtimeTradeBucket: (userName, dayKey) => `users:${userName}:runtime:trade-records:days:${dayKey}`,
|
|
439
487
|
runtimeActiveTrades: (userName) => `users:${userName}:runtime:active-trades:`,
|
|
440
|
-
runtimeActiveTrade: (userName, symbol) => `users:${userName}:runtime:active-trades:${symbol}`,
|
|
488
|
+
runtimeActiveTrade: (userName, symbol, scopeId) => scopeId ? `users:${userName}:runtime:active-trades:${scopeId}:${symbol}` : `users:${userName}:runtime:active-trades:${symbol}`,
|
|
441
489
|
aiChatHistory: (userName, symbolKey) => `users:${userName}:ai:chats:${symbolKey}`,
|
|
442
490
|
analysis: (symbol, signalId) => `analysis:${symbol}:${signalId}`,
|
|
443
491
|
screenshotSessionToken: (token) => `auth:screenshot:${token}`,
|
|
444
492
|
backtestResults: (userName, config, timestamp) => `users:${userName}:backtests:results:${config}:${timestamp}`,
|
|
493
|
+
backtestRuns: (userName) => `users:${userName}:backtests:runs:`,
|
|
494
|
+
backtestRun: (userName, runId) => `users:${userName}:backtests:runs:${runId}`,
|
|
495
|
+
backtestRunResults: (userName, runId) => `users:${userName}:backtests:runs:${runId}:results`,
|
|
496
|
+
backtestLatestRun: (userName, config) => `users:${userName}:backtests:latest:${config}`,
|
|
445
497
|
researchRuns: (userName) => `users:${userName}:research:runs:`,
|
|
446
498
|
researchRun: (userName, runId) => `users:${userName}:research:runs:${runId}`,
|
|
447
499
|
researchLatestRun: (userName, strategyName) => `users:${userName}:research:latest:${strategyName}`,
|
|
@@ -454,6 +506,8 @@ var redisKeys = {
|
|
|
454
506
|
};
|
|
455
507
|
|
|
456
508
|
export {
|
|
509
|
+
closeRedisConnection,
|
|
510
|
+
publishData,
|
|
457
511
|
getKeys,
|
|
458
512
|
getData,
|
|
459
513
|
delKey,
|
|
@@ -461,6 +515,7 @@ export {
|
|
|
461
515
|
delKeyWithOptions,
|
|
462
516
|
setData,
|
|
463
517
|
setHashJsonField,
|
|
518
|
+
getHashJsonField,
|
|
464
519
|
getHashJsonValues,
|
|
465
520
|
incrHashFields,
|
|
466
521
|
getHashData,
|