@tradejs/node 3.1.29-beta.288 → 3.1.29-beta.289
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/backtest.js +430 -223
- package/dist/backtest.mjs +10 -5
- package/dist/{chunk-F7CLF3PT.mjs → chunk-KYGJBMKE.mjs} +403 -201
- package/dist/diagnostics.js +404 -202
- package/dist/diagnostics.mjs +1 -1
- package/dist/mcp.js +419 -217
- package/dist/mcp.mjs +1 -1
- package/dist/registry.js +404 -202
- package/dist/registry.mjs +1 -1
- package/dist/runtimeDashboard.js +406 -204
- package/dist/runtimeDashboard.mjs +1 -1
- package/dist/runtimeStrategies.js +404 -202
- package/dist/runtimeStrategies.mjs +1 -1
- package/dist/strategies.d.mts +32 -22
- package/dist/strategies.d.ts +32 -22
- package/dist/strategies.js +412 -210
- package/dist/strategies.mjs +1 -1
- package/package.json +5 -5
package/dist/mcp.js
CHANGED
|
@@ -1066,13 +1066,213 @@ var assessSignalWithJev = async ({
|
|
|
1066
1066
|
// src/strategyRuntime.ts
|
|
1067
1067
|
var import_constants5 = require("@tradejs/core/constants");
|
|
1068
1068
|
var import_strategies6 = require("@tradejs/core/strategies");
|
|
1069
|
-
var
|
|
1069
|
+
var import_logger11 = require("@tradejs/infra/logger");
|
|
1070
1070
|
|
|
1071
1071
|
// src/strategyHelpers/runtime.ts
|
|
1072
|
-
var
|
|
1072
|
+
var import_logger9 = require("@tradejs/infra/logger");
|
|
1073
1073
|
var import_constants3 = require("@tradejs/core/constants");
|
|
1074
1074
|
var import_ml2 = require("@tradejs/infra/ml");
|
|
1075
1075
|
|
|
1076
|
+
// src/strategy/entrySubmissionValidation.ts
|
|
1077
|
+
var import_logger = require("@tradejs/infra/logger");
|
|
1078
|
+
|
|
1079
|
+
// src/strategy/entryExecutionValidation.ts
|
|
1080
|
+
var EntrySubmissionValidationError = class extends Error {
|
|
1081
|
+
constructor() {
|
|
1082
|
+
super(...arguments);
|
|
1083
|
+
this.name = "EntrySubmissionValidationError";
|
|
1084
|
+
}
|
|
1085
|
+
};
|
|
1086
|
+
var resolveEntryExecutionLimits = (config, direction) => {
|
|
1087
|
+
const side = config[direction];
|
|
1088
|
+
const minimum = side && typeof side === "object" && "minRiskRatio" in side ? side.minRiskRatio : void 0;
|
|
1089
|
+
const maximum = config.MAX_LOSS_VALUE;
|
|
1090
|
+
if (minimum == null && maximum == null) return void 0;
|
|
1091
|
+
const minimumNetRiskRatio = minimum == null ? void 0 : Number(minimum);
|
|
1092
|
+
const maxLossValue = maximum == null ? void 0 : Number(maximum);
|
|
1093
|
+
const feeRate = Number(config.RISK_FEE_RATE ?? 0);
|
|
1094
|
+
const slippage = Number(config.RISK_SLIPPAGE_BPS ?? 0);
|
|
1095
|
+
const impact = Number(config.RISK_MARKET_IMPACT_BPS ?? 0);
|
|
1096
|
+
const slippageBps = slippage + impact;
|
|
1097
|
+
if (minimumNetRiskRatio != null && (!Number.isFinite(minimumNetRiskRatio) || minimumNetRiskRatio < 0) || maxLossValue != null && (!Number.isFinite(maxLossValue) || maxLossValue <= 0) || !Number.isFinite(feeRate) || feeRate < 0 || feeRate >= 1 || !Number.isFinite(slippage) || slippage < 0 || !Number.isFinite(impact) || impact < 0 || !Number.isFinite(slippageBps) || slippageBps < 0 || slippageBps >= 1e4)
|
|
1098
|
+
throw new Error("INVALID_ENTRY_EXECUTION_LIMITS");
|
|
1099
|
+
return { minimumNetRiskRatio, maxLossValue, feeRate, slippageBps };
|
|
1100
|
+
};
|
|
1101
|
+
var validateEntryExecution = ({
|
|
1102
|
+
direction,
|
|
1103
|
+
price,
|
|
1104
|
+
qty,
|
|
1105
|
+
stopLossPrice,
|
|
1106
|
+
takeProfitPrice,
|
|
1107
|
+
limits
|
|
1108
|
+
}) => {
|
|
1109
|
+
if (!Number.isFinite(price) || price <= 0 || !Number.isFinite(qty) || qty <= 0 || stopLossPrice == null || !Number.isFinite(stopLossPrice) || stopLossPrice <= 0 || !Number.isFinite(takeProfitPrice) || takeProfitPrice <= 0)
|
|
1110
|
+
throw new EntrySubmissionValidationError(
|
|
1111
|
+
"ENTRY_ECONOMICS_INPUTS_UNAVAILABLE"
|
|
1112
|
+
);
|
|
1113
|
+
const side = direction === "LONG" ? 1 : -1;
|
|
1114
|
+
if (side * (price - stopLossPrice) <= 0 || side * (takeProfitPrice - price) <= 0)
|
|
1115
|
+
throw new EntrySubmissionValidationError(
|
|
1116
|
+
"INVALID_ENTRY_PROTECTION_AT_SUBMISSION"
|
|
1117
|
+
);
|
|
1118
|
+
const slippage = limits.slippageBps / 1e4;
|
|
1119
|
+
const cost = (value, sign) => value * slippage + value * (1 + sign * slippage) * limits.feeRate;
|
|
1120
|
+
const entryCost = cost(price, side);
|
|
1121
|
+
const lossPerUnit = Math.abs(price - stopLossPrice) + entryCost + cost(stopLossPrice, -side);
|
|
1122
|
+
const rewardPerUnit = Math.max(
|
|
1123
|
+
0,
|
|
1124
|
+
Math.abs(takeProfitPrice - price) - entryCost - cost(takeProfitPrice, -side)
|
|
1125
|
+
);
|
|
1126
|
+
const netRiskRatio = rewardPerUnit / lossPerUnit;
|
|
1127
|
+
const plannedLossValue = qty * lossPerUnit;
|
|
1128
|
+
if (!Number.isFinite(netRiskRatio) || !Number.isFinite(plannedLossValue))
|
|
1129
|
+
throw new EntrySubmissionValidationError(
|
|
1130
|
+
"ENTRY_ECONOMICS_INPUTS_UNAVAILABLE"
|
|
1131
|
+
);
|
|
1132
|
+
if (limits.minimumNetRiskRatio != null && netRiskRatio <= limits.minimumNetRiskRatio)
|
|
1133
|
+
throw new EntrySubmissionValidationError(
|
|
1134
|
+
"ENTRY_RR_BELOW_MIN_AT_SUBMISSION"
|
|
1135
|
+
);
|
|
1136
|
+
if (limits.maxLossValue != null && plannedLossValue > limits.maxLossValue * (1 + 1e-9))
|
|
1137
|
+
throw new EntrySubmissionValidationError(
|
|
1138
|
+
"ENTRY_RISK_EXCEEDS_MAX_LOSS_AT_SUBMISSION"
|
|
1139
|
+
);
|
|
1140
|
+
return { netRiskRatio, plannedLossValue };
|
|
1141
|
+
};
|
|
1142
|
+
|
|
1143
|
+
// src/strategy/entrySubmissionValidation.ts
|
|
1144
|
+
var MAX_ENTRY_QUOTE_AGE_MS = 5e3;
|
|
1145
|
+
var toFiniteNumberOrNull = (value) => typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
1146
|
+
var getOrderArrivalSnapshot = async ({
|
|
1147
|
+
connector,
|
|
1148
|
+
symbol,
|
|
1149
|
+
requireTimestamp = false
|
|
1150
|
+
}) => {
|
|
1151
|
+
if (typeof connector.getTopOfBookTicker !== "function") {
|
|
1152
|
+
return {
|
|
1153
|
+
arrivalSnapshotTime: Date.now(),
|
|
1154
|
+
arrivalSource: "unavailable",
|
|
1155
|
+
bid: null,
|
|
1156
|
+
ask: null,
|
|
1157
|
+
arrivalMid: null,
|
|
1158
|
+
spreadBps: null
|
|
1159
|
+
};
|
|
1160
|
+
}
|
|
1161
|
+
try {
|
|
1162
|
+
const ticker = await connector.getTopOfBookTicker(symbol);
|
|
1163
|
+
const arrivalSnapshotTime = toFiniteNumberOrNull(ticker?.timestamp);
|
|
1164
|
+
const timestampUnavailable = requireTimestamp && arrivalSnapshotTime == null;
|
|
1165
|
+
const bid = timestampUnavailable ? null : toFiniteNumberOrNull(ticker?.bidPrice);
|
|
1166
|
+
const ask = timestampUnavailable ? null : toFiniteNumberOrNull(ticker?.askPrice);
|
|
1167
|
+
const arrivalMid = bid != null && ask != null ? (bid + ask) / 2 : null;
|
|
1168
|
+
const spreadBps = bid != null && ask != null && arrivalMid != null && arrivalMid > 0 ? (ask - bid) / arrivalMid * 1e4 : null;
|
|
1169
|
+
return {
|
|
1170
|
+
arrivalSnapshotTime: arrivalSnapshotTime ?? Date.now(),
|
|
1171
|
+
arrivalSource: "top_of_book",
|
|
1172
|
+
bid,
|
|
1173
|
+
ask,
|
|
1174
|
+
arrivalMid,
|
|
1175
|
+
spreadBps
|
|
1176
|
+
};
|
|
1177
|
+
} catch (error) {
|
|
1178
|
+
import_logger.logger.warn(
|
|
1179
|
+
"runtime order arrival snapshot failed: %s %s",
|
|
1180
|
+
symbol,
|
|
1181
|
+
error?.message || String(error)
|
|
1182
|
+
);
|
|
1183
|
+
return {
|
|
1184
|
+
arrivalSnapshotTime: Date.now(),
|
|
1185
|
+
arrivalSource: "top_of_book_error",
|
|
1186
|
+
bid: null,
|
|
1187
|
+
ask: null,
|
|
1188
|
+
arrivalMid: null,
|
|
1189
|
+
spreadBps: null
|
|
1190
|
+
};
|
|
1191
|
+
}
|
|
1192
|
+
};
|
|
1193
|
+
var validateEntryProtectionAtArrival = ({
|
|
1194
|
+
direction,
|
|
1195
|
+
signalPrice,
|
|
1196
|
+
bid,
|
|
1197
|
+
ask,
|
|
1198
|
+
arrivalMid,
|
|
1199
|
+
takeProfits,
|
|
1200
|
+
stopLossPrice
|
|
1201
|
+
}) => {
|
|
1202
|
+
const entryReference = direction === "LONG" ? ask ?? arrivalMid ?? signalPrice : bid ?? arrivalMid ?? signalPrice;
|
|
1203
|
+
const stopReference = direction === "LONG" ? bid ?? arrivalMid ?? signalPrice : ask ?? arrivalMid ?? signalPrice;
|
|
1204
|
+
if (!Number.isFinite(entryReference) || entryReference <= 0 || !Number.isFinite(stopReference) || stopReference <= 0) {
|
|
1205
|
+
throw new Error("INVALID_ENTRY_REFERENCE_AT_ARRIVAL");
|
|
1206
|
+
}
|
|
1207
|
+
for (const takeProfit of takeProfits) {
|
|
1208
|
+
if (!Number.isFinite(takeProfit.price) || takeProfit.price <= 0 || (direction === "LONG" ? takeProfit.price <= entryReference : takeProfit.price >= entryReference)) {
|
|
1209
|
+
throw new Error("TAKE_PROFIT_CROSSED_BEFORE_ENTRY");
|
|
1210
|
+
}
|
|
1211
|
+
}
|
|
1212
|
+
if (stopLossPrice != null && (!Number.isFinite(stopLossPrice) || stopLossPrice <= 0 || (direction === "LONG" ? stopLossPrice >= stopReference : stopLossPrice <= stopReference))) {
|
|
1213
|
+
throw new Error("STOP_LOSS_CROSSED_BEFORE_ENTRY");
|
|
1214
|
+
}
|
|
1215
|
+
};
|
|
1216
|
+
var createEntrySubmissionValidation = ({
|
|
1217
|
+
connector,
|
|
1218
|
+
symbol,
|
|
1219
|
+
direction,
|
|
1220
|
+
takeProfits,
|
|
1221
|
+
stopLossPrice,
|
|
1222
|
+
limits,
|
|
1223
|
+
onValidated
|
|
1224
|
+
}) => {
|
|
1225
|
+
if (!limits) return void 0;
|
|
1226
|
+
if (!connector.capabilities?.orderSubmissionValidation)
|
|
1227
|
+
throw new EntrySubmissionValidationError(
|
|
1228
|
+
"ENTRY_SUBMISSION_VALIDATION_UNSUPPORTED"
|
|
1229
|
+
);
|
|
1230
|
+
return async ({ qty, executionPrice }) => {
|
|
1231
|
+
const simulated = Reflect.get(connector, "__tradejsTestConnector") === true;
|
|
1232
|
+
const snapshot2 = simulated && executionPrice != null ? {
|
|
1233
|
+
arrivalSnapshotTime: Date.now(),
|
|
1234
|
+
arrivalSource: "simulation",
|
|
1235
|
+
bid: executionPrice,
|
|
1236
|
+
ask: executionPrice,
|
|
1237
|
+
arrivalMid: executionPrice,
|
|
1238
|
+
spreadBps: 0
|
|
1239
|
+
} : await getOrderArrivalSnapshot({
|
|
1240
|
+
connector,
|
|
1241
|
+
symbol,
|
|
1242
|
+
requireTimestamp: true
|
|
1243
|
+
});
|
|
1244
|
+
const age = Date.now() - snapshot2.arrivalSnapshotTime;
|
|
1245
|
+
if (snapshot2.bid == null || snapshot2.ask == null || !Number.isFinite(snapshot2.bid) || !Number.isFinite(snapshot2.ask) || snapshot2.bid <= 0 || snapshot2.ask < snapshot2.bid)
|
|
1246
|
+
throw new EntrySubmissionValidationError(
|
|
1247
|
+
"ENTRY_QUOTE_UNAVAILABLE_AT_SUBMISSION"
|
|
1248
|
+
);
|
|
1249
|
+
if (!Number.isFinite(age) || age < -MAX_ENTRY_QUOTE_AGE_MS || age > MAX_ENTRY_QUOTE_AGE_MS)
|
|
1250
|
+
throw new EntrySubmissionValidationError(
|
|
1251
|
+
"ENTRY_QUOTE_STALE_AT_SUBMISSION"
|
|
1252
|
+
);
|
|
1253
|
+
const price = direction === "LONG" ? snapshot2.ask : snapshot2.bid;
|
|
1254
|
+
validateEntryProtectionAtArrival({
|
|
1255
|
+
direction,
|
|
1256
|
+
signalPrice: price,
|
|
1257
|
+
bid: snapshot2.bid,
|
|
1258
|
+
ask: snapshot2.ask,
|
|
1259
|
+
arrivalMid: snapshot2.arrivalMid,
|
|
1260
|
+
takeProfits,
|
|
1261
|
+
stopLossPrice
|
|
1262
|
+
});
|
|
1263
|
+
const prices = takeProfits.map((tp) => tp.price);
|
|
1264
|
+
const economics2 = validateEntryExecution({
|
|
1265
|
+
direction,
|
|
1266
|
+
price,
|
|
1267
|
+
qty,
|
|
1268
|
+
stopLossPrice,
|
|
1269
|
+
takeProfitPrice: direction === "LONG" ? Math.max(...prices) : Math.min(...prices),
|
|
1270
|
+
limits
|
|
1271
|
+
});
|
|
1272
|
+
onValidated?.(snapshot2, economics2);
|
|
1273
|
+
};
|
|
1274
|
+
};
|
|
1275
|
+
|
|
1076
1276
|
// src/ai.ts
|
|
1077
1277
|
var import_aiLanguages2 = require("@tradejs/core/aiLanguages");
|
|
1078
1278
|
var import_redis = require("@tradejs/infra/redis");
|
|
@@ -1657,7 +1857,7 @@ var import_fs = __toESM(require("fs"));
|
|
|
1657
1857
|
var import_path = __toESM(require("path"));
|
|
1658
1858
|
var import_url = require("url");
|
|
1659
1859
|
var import_config = require("@tradejs/core/config");
|
|
1660
|
-
var
|
|
1860
|
+
var import_logger2 = require("@tradejs/infra/logger");
|
|
1661
1861
|
var CONFIG_FILE_NAMES = [
|
|
1662
1862
|
"tradejs.config.ts",
|
|
1663
1863
|
"tradejs.config.mts",
|
|
@@ -1924,11 +2124,11 @@ var loadTradejsConfig = async (cwd = getTradejsProjectCwd()) => {
|
|
|
1924
2124
|
cachedByCwd.set(cwd, config);
|
|
1925
2125
|
if (!announcedConfigFile.has(configFilePath)) {
|
|
1926
2126
|
announcedConfigFile.add(configFilePath);
|
|
1927
|
-
|
|
2127
|
+
import_logger2.logger.log("debug", "Loaded TradeJS config: %s", configFilePath);
|
|
1928
2128
|
}
|
|
1929
2129
|
return config;
|
|
1930
2130
|
} catch (error) {
|
|
1931
|
-
|
|
2131
|
+
import_logger2.logger.log(
|
|
1932
2132
|
"warn",
|
|
1933
2133
|
"Failed to load TradeJS config from %s: %s",
|
|
1934
2134
|
configFilePath,
|
|
@@ -2895,7 +3095,7 @@ var import_node_crypto = require("crypto");
|
|
|
2895
3095
|
var import_constants = require("@tradejs/core/constants");
|
|
2896
3096
|
var import_time = require("@tradejs/core/time");
|
|
2897
3097
|
var import_trade = require("@tradejs/core/trade");
|
|
2898
|
-
var
|
|
3098
|
+
var import_logger3 = require("@tradejs/infra/logger");
|
|
2899
3099
|
var import_redis2 = require("@tradejs/infra/redis");
|
|
2900
3100
|
var now = () => Date.now();
|
|
2901
3101
|
var toRandomOrderSuffix = () => (0, import_node_crypto.randomUUID)().replace(/-/g, "").slice(0, 12).toLowerCase();
|
|
@@ -2954,7 +3154,7 @@ var recordRuntimeTradeOpen = async (params) => {
|
|
|
2954
3154
|
)
|
|
2955
3155
|
]);
|
|
2956
3156
|
} catch (error) {
|
|
2957
|
-
|
|
3157
|
+
import_logger3.logger.error(
|
|
2958
3158
|
"runtime trade open journal failed: %s %s",
|
|
2959
3159
|
record.symbol,
|
|
2960
3160
|
error?.message || String(error)
|
|
@@ -3022,7 +3222,7 @@ var recordRuntimeTradeIncrease = async (params) => {
|
|
|
3022
3222
|
)
|
|
3023
3223
|
]);
|
|
3024
3224
|
} catch (error) {
|
|
3025
|
-
|
|
3225
|
+
import_logger3.logger.error(
|
|
3026
3226
|
"runtime trade increase journal failed: %s %s",
|
|
3027
3227
|
symbol,
|
|
3028
3228
|
error?.message || String(error)
|
|
@@ -3129,7 +3329,7 @@ var markRuntimeTradeClosed = async (params) => {
|
|
|
3129
3329
|
)
|
|
3130
3330
|
]);
|
|
3131
3331
|
} catch (error) {
|
|
3132
|
-
|
|
3332
|
+
import_logger3.logger.error(
|
|
3133
3333
|
"runtime trade close journal failed: %s %s",
|
|
3134
3334
|
symbol,
|
|
3135
3335
|
error?.message || String(error)
|
|
@@ -3139,11 +3339,11 @@ var markRuntimeTradeClosed = async (params) => {
|
|
|
3139
3339
|
};
|
|
3140
3340
|
|
|
3141
3341
|
// src/strategyHelpers/marketContextStages.ts
|
|
3142
|
-
var
|
|
3342
|
+
var import_logger8 = require("@tradejs/infra/logger");
|
|
3143
3343
|
|
|
3144
3344
|
// src/strategyHelpers/binanceMarketContext.ts
|
|
3145
3345
|
var import_marketContext = require("@tradejs/infra/timescale/marketContext");
|
|
3146
|
-
var
|
|
3346
|
+
var import_logger4 = require("@tradejs/infra/logger");
|
|
3147
3347
|
var import_strategies = require("@tradejs/core/strategies");
|
|
3148
3348
|
|
|
3149
3349
|
// src/binanceBreadthUniverses.ts
|
|
@@ -3507,7 +3707,7 @@ var parseEnabledFlag = (value, env) => {
|
|
|
3507
3707
|
if (normalized === "live") return env !== "BACKTEST";
|
|
3508
3708
|
return false;
|
|
3509
3709
|
};
|
|
3510
|
-
var
|
|
3710
|
+
var toFiniteNumberOrNull2 = (value) => {
|
|
3511
3711
|
const numeric = typeof value === "number" ? value : Number(value);
|
|
3512
3712
|
return Number.isFinite(numeric) ? numeric : null;
|
|
3513
3713
|
};
|
|
@@ -3632,14 +3832,14 @@ var toTradeFlowContext = (row, interval) => row ? {
|
|
|
3632
3832
|
asOfTs: row.ts.getTime(),
|
|
3633
3833
|
ageMs: row.ageMs,
|
|
3634
3834
|
stale: row.stale,
|
|
3635
|
-
trades:
|
|
3636
|
-
buyPressurePct:
|
|
3637
|
-
buyBaseVolume:
|
|
3638
|
-
sellBaseVolume:
|
|
3639
|
-
buyQuoteVolume:
|
|
3640
|
-
sellQuoteVolume:
|
|
3641
|
-
netBaseDelta:
|
|
3642
|
-
netQuoteDelta:
|
|
3835
|
+
trades: toFiniteNumberOrNull2(row.trades),
|
|
3836
|
+
buyPressurePct: toFiniteNumberOrNull2(row.buyPressurePct),
|
|
3837
|
+
buyBaseVolume: toFiniteNumberOrNull2(row.buyBaseVolume),
|
|
3838
|
+
sellBaseVolume: toFiniteNumberOrNull2(row.sellBaseVolume),
|
|
3839
|
+
buyQuoteVolume: toFiniteNumberOrNull2(row.buyQuoteVolume),
|
|
3840
|
+
sellQuoteVolume: toFiniteNumberOrNull2(row.sellQuoteVolume),
|
|
3841
|
+
netBaseDelta: toFiniteNumberOrNull2(row.netBaseDelta),
|
|
3842
|
+
netQuoteDelta: toFiniteNumberOrNull2(row.netQuoteDelta)
|
|
3643
3843
|
} : null;
|
|
3644
3844
|
var getCachedReferenceRows = ({
|
|
3645
3845
|
referenceSymbols,
|
|
@@ -3728,16 +3928,16 @@ var toMarketBreadthContext = (breadth, interval) => ({
|
|
|
3728
3928
|
asOfTs: breadth.ts.getTime(),
|
|
3729
3929
|
ageMs: breadth.ageMs,
|
|
3730
3930
|
stale: breadth.stale,
|
|
3731
|
-
symbolsCount:
|
|
3732
|
-
advancers:
|
|
3733
|
-
decliners:
|
|
3734
|
-
unchanged:
|
|
3735
|
-
advanceDeclineRatio:
|
|
3736
|
-
pctAboveMa20:
|
|
3737
|
-
pctAboveMa50:
|
|
3738
|
-
equalWeightedReturn:
|
|
3739
|
-
volumeWeightedReturn:
|
|
3740
|
-
dispersion:
|
|
3931
|
+
symbolsCount: toFiniteNumberOrNull2(breadth.symbolsCount),
|
|
3932
|
+
advancers: toFiniteNumberOrNull2(breadth.advancers),
|
|
3933
|
+
decliners: toFiniteNumberOrNull2(breadth.decliners),
|
|
3934
|
+
unchanged: toFiniteNumberOrNull2(breadth.unchanged),
|
|
3935
|
+
advanceDeclineRatio: toFiniteNumberOrNull2(breadth.advanceDeclineRatio),
|
|
3936
|
+
pctAboveMa20: toFiniteNumberOrNull2(breadth.pctAboveMa20),
|
|
3937
|
+
pctAboveMa50: toFiniteNumberOrNull2(breadth.pctAboveMa50),
|
|
3938
|
+
equalWeightedReturn: toFiniteNumberOrNull2(breadth.equalWeightedReturn),
|
|
3939
|
+
volumeWeightedReturn: toFiniteNumberOrNull2(breadth.volumeWeightedReturn),
|
|
3940
|
+
dispersion: toFiniteNumberOrNull2(breadth.dispersion)
|
|
3741
3941
|
});
|
|
3742
3942
|
var enrichSignalWithBinanceMarketContext = async (params) => {
|
|
3743
3943
|
const {
|
|
@@ -3838,46 +4038,46 @@ var enrichSignalWithBinanceMarketContext = async (params) => {
|
|
|
3838
4038
|
asOfTs: primaryBreadth.ts.getTime(),
|
|
3839
4039
|
ageMs: primaryBreadth.ageMs,
|
|
3840
4040
|
stale: primaryBreadth.stale,
|
|
3841
|
-
btcReturn1h:
|
|
4041
|
+
btcReturn1h: toFiniteNumberOrNull2(
|
|
3842
4042
|
primaryBreadth.btcReturn1h
|
|
3843
4043
|
),
|
|
3844
|
-
btcReturn4h:
|
|
4044
|
+
btcReturn4h: toFiniteNumberOrNull2(
|
|
3845
4045
|
primaryBreadth.btcReturn4h
|
|
3846
4046
|
),
|
|
3847
|
-
btcReturn24h:
|
|
4047
|
+
btcReturn24h: toFiniteNumberOrNull2(
|
|
3848
4048
|
primaryBreadth.btcReturn24h
|
|
3849
4049
|
),
|
|
3850
|
-
altBasketReturn1h:
|
|
4050
|
+
altBasketReturn1h: toFiniteNumberOrNull2(
|
|
3851
4051
|
primaryBreadth.altBasketReturn1h
|
|
3852
4052
|
),
|
|
3853
|
-
altBasketReturn4h:
|
|
4053
|
+
altBasketReturn4h: toFiniteNumberOrNull2(
|
|
3854
4054
|
primaryBreadth.altBasketReturn4h
|
|
3855
4055
|
),
|
|
3856
|
-
altBasketReturn24h:
|
|
4056
|
+
altBasketReturn24h: toFiniteNumberOrNull2(
|
|
3857
4057
|
primaryBreadth.altBasketReturn24h
|
|
3858
4058
|
),
|
|
3859
|
-
btcVsAltReturn1h:
|
|
4059
|
+
btcVsAltReturn1h: toFiniteNumberOrNull2(
|
|
3860
4060
|
primaryBreadth.btcVsAltReturn1h
|
|
3861
4061
|
),
|
|
3862
|
-
btcVsAltReturn4h:
|
|
4062
|
+
btcVsAltReturn4h: toFiniteNumberOrNull2(
|
|
3863
4063
|
primaryBreadth.btcVsAltReturn4h
|
|
3864
4064
|
),
|
|
3865
|
-
btcVsAltReturn24h:
|
|
4065
|
+
btcVsAltReturn24h: toFiniteNumberOrNull2(
|
|
3866
4066
|
primaryBreadth.btcVsAltReturn24h
|
|
3867
4067
|
),
|
|
3868
|
-
btcTurnoverShare1h:
|
|
4068
|
+
btcTurnoverShare1h: toFiniteNumberOrNull2(
|
|
3869
4069
|
primaryBreadth.btcTurnoverShare1h
|
|
3870
4070
|
),
|
|
3871
|
-
btcTurnoverShare24h:
|
|
4071
|
+
btcTurnoverShare24h: toFiniteNumberOrNull2(
|
|
3872
4072
|
primaryBreadth.btcTurnoverShare24h
|
|
3873
4073
|
),
|
|
3874
|
-
btcTurnoverShareChange24h:
|
|
4074
|
+
btcTurnoverShareChange24h: toFiniteNumberOrNull2(
|
|
3875
4075
|
primaryBreadth.btcTurnoverShareChange24h
|
|
3876
4076
|
),
|
|
3877
|
-
altVolToBtcVol24h:
|
|
4077
|
+
altVolToBtcVol24h: toFiniteNumberOrNull2(
|
|
3878
4078
|
primaryBreadth.altVolToBtcVol24h
|
|
3879
4079
|
),
|
|
3880
|
-
altDispersion24h:
|
|
4080
|
+
altDispersion24h: toFiniteNumberOrNull2(
|
|
3881
4081
|
primaryBreadth.altDispersion24h
|
|
3882
4082
|
),
|
|
3883
4083
|
regime: primaryBreadth.btcAltRegime ?? "unknown"
|
|
@@ -3894,7 +4094,7 @@ var enrichSignalWithBinanceMarketContext = async (params) => {
|
|
|
3894
4094
|
throw error;
|
|
3895
4095
|
}
|
|
3896
4096
|
binanceMarketContextUnavailable = true;
|
|
3897
|
-
|
|
4097
|
+
import_logger4.logger.warn(
|
|
3898
4098
|
"Binance market context disabled after Timescale read failure: %s",
|
|
3899
4099
|
String(error)
|
|
3900
4100
|
);
|
|
@@ -3904,7 +4104,7 @@ var enrichSignalWithBinanceMarketContext = async (params) => {
|
|
|
3904
4104
|
|
|
3905
4105
|
// src/strategyHelpers/coinMarketCapContext.ts
|
|
3906
4106
|
var import_strategies2 = require("@tradejs/core/strategies");
|
|
3907
|
-
var
|
|
4107
|
+
var import_logger5 = require("@tradejs/infra/logger");
|
|
3908
4108
|
var import_marketContext2 = require("@tradejs/infra/timescale/marketContext");
|
|
3909
4109
|
var DEFAULT_MAX_AGE_MS = 48 * 60 * 6e4;
|
|
3910
4110
|
var SOURCE_GLOBAL_DAILY = "coinmarketcap_global";
|
|
@@ -3942,7 +4142,7 @@ var asInt = (value, fallback) => {
|
|
|
3942
4142
|
const parsed = Number.parseInt(String(value ?? ""), 10);
|
|
3943
4143
|
return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;
|
|
3944
4144
|
};
|
|
3945
|
-
var
|
|
4145
|
+
var toFiniteNumberOrNull3 = (value) => {
|
|
3946
4146
|
const numeric = typeof value === "number" ? value : typeof value === "string" && value.trim() ? Number(value) : Number.NaN;
|
|
3947
4147
|
return Number.isFinite(numeric) ? numeric : null;
|
|
3948
4148
|
};
|
|
@@ -4176,12 +4376,12 @@ var enrichSignalWithCoinMarketCapContext = async (params) => {
|
|
|
4176
4376
|
const ethRow = references.get("ETHUSDT") ?? null;
|
|
4177
4377
|
const previousBtcRow = previousReferences.get("BTCUSDT") ?? null;
|
|
4178
4378
|
const previousEthRow = previousReferences.get("ETHUSDT") ?? null;
|
|
4179
|
-
const btcMarketCapUsd =
|
|
4180
|
-
const ethMarketCapUsd =
|
|
4181
|
-
const previousBtcMarketCapUsd =
|
|
4379
|
+
const btcMarketCapUsd = toFiniteNumberOrNull3(btcRow?.marketCapUsd);
|
|
4380
|
+
const ethMarketCapUsd = toFiniteNumberOrNull3(ethRow?.marketCapUsd);
|
|
4381
|
+
const previousBtcMarketCapUsd = toFiniteNumberOrNull3(
|
|
4182
4382
|
previousBtcRow?.marketCapUsd
|
|
4183
4383
|
);
|
|
4184
|
-
const previousEthMarketCapUsd =
|
|
4384
|
+
const previousEthMarketCapUsd = toFiniteNumberOrNull3(
|
|
4185
4385
|
previousEthRow?.marketCapUsd
|
|
4186
4386
|
);
|
|
4187
4387
|
const ethBtcMarketCapRatio = safeDivide(ethMarketCapUsd, btcMarketCapUsd);
|
|
@@ -4190,16 +4390,16 @@ var enrichSignalWithCoinMarketCapContext = async (params) => {
|
|
|
4190
4390
|
previousBtcMarketCapUsd
|
|
4191
4391
|
);
|
|
4192
4392
|
const ethBtcMarketCapRatioChange24hPct = ethBtcMarketCapRatio != null && previousEthBtcMarketCapRatio != null && previousEthBtcMarketCapRatio > 0 ? (ethBtcMarketCapRatio - previousEthBtcMarketCapRatio) / previousEthBtcMarketCapRatio : null;
|
|
4193
|
-
const btcVolumeUsd =
|
|
4194
|
-
const ethVolumeUsd =
|
|
4393
|
+
const btcVolumeUsd = toFiniteNumberOrNull3(btcRow?.volumeUsd);
|
|
4394
|
+
const ethVolumeUsd = toFiniteNumberOrNull3(ethRow?.volumeUsd);
|
|
4195
4395
|
const referenceStale = btcRow?.stale === true || ethRow?.stale === true || !btcRow || !ethRow;
|
|
4196
|
-
const btcDominanceChange24hPct =
|
|
4396
|
+
const btcDominanceChange24hPct = toFiniteNumberOrNull3(
|
|
4197
4397
|
globalRow?.btcDominanceChange24hPct
|
|
4198
4398
|
);
|
|
4199
|
-
const altMarketCapChange24hPct =
|
|
4399
|
+
const altMarketCapChange24hPct = toFiniteNumberOrNull3(
|
|
4200
4400
|
globalRow?.altMarketCapChange24hPct
|
|
4201
4401
|
);
|
|
4202
|
-
const altVolumeChange24hPct =
|
|
4402
|
+
const altVolumeChange24hPct = toFiniteNumberOrNull3(
|
|
4203
4403
|
globalRow?.altVolumeChange24hPct
|
|
4204
4404
|
);
|
|
4205
4405
|
const altLiquidityRegime = globalRow ? toAltLiquidityRegime({
|
|
@@ -4210,19 +4410,19 @@ var enrichSignalWithCoinMarketCapContext = async (params) => {
|
|
|
4210
4410
|
}) : "unknown";
|
|
4211
4411
|
const exchangeLiquidityRegime = exchangeLiquidityRow ? toExchangeLiquidityRegime({
|
|
4212
4412
|
stale: exchangeLiquidityRow.stale,
|
|
4213
|
-
totalVolumeChange24hPct:
|
|
4413
|
+
totalVolumeChange24hPct: toFiniteNumberOrNull3(
|
|
4214
4414
|
exchangeLiquidityRow.totalVolumeChange24hPct
|
|
4215
4415
|
),
|
|
4216
4416
|
fallback: exchangeLiquidityRow.liquidityRegime ?? "unknown"
|
|
4217
4417
|
}) : "unknown";
|
|
4218
4418
|
const cmc100Row = indexRows.get("cmc100") ?? null;
|
|
4219
4419
|
const cmc20Row = indexRows.get("cmc20") ?? null;
|
|
4220
|
-
const cmc100Value =
|
|
4221
|
-
const cmc20Value =
|
|
4222
|
-
const cmc100Change24hPct =
|
|
4420
|
+
const cmc100Value = toFiniteNumberOrNull3(cmc100Row?.value);
|
|
4421
|
+
const cmc20Value = toFiniteNumberOrNull3(cmc20Row?.value);
|
|
4422
|
+
const cmc100Change24hPct = toFiniteNumberOrNull3(
|
|
4223
4423
|
cmc100Row?.valueChange24hPct
|
|
4224
4424
|
);
|
|
4225
|
-
const cmc20Change24hPct =
|
|
4425
|
+
const cmc20Change24hPct = toFiniteNumberOrNull3(cmc20Row?.valueChange24hPct);
|
|
4226
4426
|
const cmc20ToCmc100Ratio = safeDivide(cmc20Value, cmc100Value);
|
|
4227
4427
|
const cmc20ToCmc100RatioChange24hPct = cmc20Change24hPct != null && cmc100Change24hPct != null ? (1 + cmc20Change24hPct) / (1 + cmc100Change24hPct) - 1 : null;
|
|
4228
4428
|
const indexStale = cmc100Row?.stale === true || cmc20Row?.stale === true || !cmc100Row || !cmc20Row;
|
|
@@ -4246,41 +4446,41 @@ var enrichSignalWithCoinMarketCapContext = async (params) => {
|
|
|
4246
4446
|
asOfTs: globalRow.ts.getTime(),
|
|
4247
4447
|
ageMs: globalRow.ageMs,
|
|
4248
4448
|
stale: globalRow.stale,
|
|
4249
|
-
totalMarketCapUsd:
|
|
4449
|
+
totalMarketCapUsd: toFiniteNumberOrNull3(
|
|
4250
4450
|
globalRow.totalMarketCapUsd
|
|
4251
4451
|
),
|
|
4252
|
-
totalVolumeUsd:
|
|
4452
|
+
totalVolumeUsd: toFiniteNumberOrNull3(
|
|
4253
4453
|
globalRow.totalVolumeUsd
|
|
4254
4454
|
),
|
|
4255
|
-
totalVolumeReportedUsd:
|
|
4455
|
+
totalVolumeReportedUsd: toFiniteNumberOrNull3(
|
|
4256
4456
|
globalRow.totalVolumeReportedUsd
|
|
4257
4457
|
),
|
|
4258
|
-
altMarketCapUsd:
|
|
4458
|
+
altMarketCapUsd: toFiniteNumberOrNull3(
|
|
4259
4459
|
globalRow.altMarketCapUsd
|
|
4260
4460
|
),
|
|
4261
|
-
altVolumeUsd:
|
|
4262
|
-
altVolumeReportedUsd:
|
|
4461
|
+
altVolumeUsd: toFiniteNumberOrNull3(globalRow.altVolumeUsd),
|
|
4462
|
+
altVolumeReportedUsd: toFiniteNumberOrNull3(
|
|
4263
4463
|
globalRow.altVolumeReportedUsd
|
|
4264
4464
|
),
|
|
4265
|
-
btcDominancePct:
|
|
4465
|
+
btcDominancePct: toFiniteNumberOrNull3(
|
|
4266
4466
|
globalRow.btcDominancePct
|
|
4267
4467
|
),
|
|
4268
|
-
ethDominancePct:
|
|
4468
|
+
ethDominancePct: toFiniteNumberOrNull3(
|
|
4269
4469
|
globalRow.ethDominancePct
|
|
4270
4470
|
),
|
|
4271
4471
|
btcDominanceChange24hPct,
|
|
4272
|
-
ethDominanceChange24hPct:
|
|
4472
|
+
ethDominanceChange24hPct: toFiniteNumberOrNull3(
|
|
4273
4473
|
globalRow.ethDominanceChange24hPct
|
|
4274
4474
|
),
|
|
4275
4475
|
altMarketCapChange24hPct,
|
|
4276
4476
|
altVolumeChange24hPct,
|
|
4277
|
-
activeCryptocurrencies:
|
|
4477
|
+
activeCryptocurrencies: toFiniteNumberOrNull3(
|
|
4278
4478
|
globalRow.activeCryptocurrencies
|
|
4279
4479
|
),
|
|
4280
|
-
activeExchanges:
|
|
4480
|
+
activeExchanges: toFiniteNumberOrNull3(
|
|
4281
4481
|
globalRow.activeExchanges
|
|
4282
4482
|
),
|
|
4283
|
-
activeMarketPairs:
|
|
4483
|
+
activeMarketPairs: toFiniteNumberOrNull3(
|
|
4284
4484
|
globalRow.activeMarketPairs
|
|
4285
4485
|
),
|
|
4286
4486
|
altLiquidityRegime
|
|
@@ -4325,22 +4525,22 @@ var enrichSignalWithCoinMarketCapContext = async (params) => {
|
|
|
4325
4525
|
asOfTs: exchangeLiquidityRow.ts.getTime(),
|
|
4326
4526
|
ageMs: exchangeLiquidityRow.ageMs,
|
|
4327
4527
|
stale: exchangeLiquidityRow.stale,
|
|
4328
|
-
exchangesCount:
|
|
4528
|
+
exchangesCount: toFiniteNumberOrNull3(
|
|
4329
4529
|
exchangeLiquidityRow.exchangesCount
|
|
4330
4530
|
),
|
|
4331
|
-
totalVolumeUsd:
|
|
4531
|
+
totalVolumeUsd: toFiniteNumberOrNull3(
|
|
4332
4532
|
exchangeLiquidityRow.totalVolumeUsd
|
|
4333
4533
|
),
|
|
4334
|
-
totalVolumeChange24hPct:
|
|
4534
|
+
totalVolumeChange24hPct: toFiniteNumberOrNull3(
|
|
4335
4535
|
exchangeLiquidityRow.totalVolumeChange24hPct
|
|
4336
4536
|
),
|
|
4337
|
-
binanceVolumeUsd:
|
|
4537
|
+
binanceVolumeUsd: toFiniteNumberOrNull3(
|
|
4338
4538
|
exchangeLiquidityRow.binanceVolumeUsd
|
|
4339
4539
|
),
|
|
4340
|
-
binanceVolumeShare:
|
|
4540
|
+
binanceVolumeShare: toFiniteNumberOrNull3(
|
|
4341
4541
|
exchangeLiquidityRow.binanceVolumeShare
|
|
4342
4542
|
),
|
|
4343
|
-
topExchangeVolumeShare:
|
|
4543
|
+
topExchangeVolumeShare: toFiniteNumberOrNull3(
|
|
4344
4544
|
exchangeLiquidityRow.topExchangeVolumeShare
|
|
4345
4545
|
),
|
|
4346
4546
|
liquidityRegime: exchangeLiquidityRegime
|
|
@@ -4353,11 +4553,11 @@ var enrichSignalWithCoinMarketCapContext = async (params) => {
|
|
|
4353
4553
|
asOfTs: fearGreedRow.ts.getTime(),
|
|
4354
4554
|
ageMs: fearGreedRow.ageMs,
|
|
4355
4555
|
stale: fearGreedRow.stale,
|
|
4356
|
-
value:
|
|
4357
|
-
valueChange24h:
|
|
4556
|
+
value: toFiniteNumberOrNull3(fearGreedRow.value),
|
|
4557
|
+
valueChange24h: toFiniteNumberOrNull3(
|
|
4358
4558
|
fearGreedRow.valueChange24h
|
|
4359
4559
|
),
|
|
4360
|
-
valueChange7d:
|
|
4560
|
+
valueChange7d: toFiniteNumberOrNull3(
|
|
4361
4561
|
fearGreedRow.valueChange7d
|
|
4362
4562
|
),
|
|
4363
4563
|
classification: fearGreedRow.classification ?? "Unknown",
|
|
@@ -4377,13 +4577,13 @@ var enrichSignalWithCoinMarketCapContext = async (params) => {
|
|
|
4377
4577
|
cmc100Value,
|
|
4378
4578
|
cmc100Change24hPct,
|
|
4379
4579
|
cmc100TopConstituentSymbol: cmc100Row?.topConstituentSymbol ?? null,
|
|
4380
|
-
cmc100TopConstituentWeightPct:
|
|
4580
|
+
cmc100TopConstituentWeightPct: toFiniteNumberOrNull3(
|
|
4381
4581
|
cmc100Row?.topConstituentWeightPct
|
|
4382
4582
|
),
|
|
4383
4583
|
cmc20Value,
|
|
4384
4584
|
cmc20Change24hPct,
|
|
4385
4585
|
cmc20TopConstituentSymbol: cmc20Row?.topConstituentSymbol ?? null,
|
|
4386
|
-
cmc20TopConstituentWeightPct:
|
|
4586
|
+
cmc20TopConstituentWeightPct: toFiniteNumberOrNull3(
|
|
4387
4587
|
cmc20Row?.topConstituentWeightPct
|
|
4388
4588
|
),
|
|
4389
4589
|
cmc20ToCmc100Ratio,
|
|
@@ -4401,7 +4601,7 @@ var enrichSignalWithCoinMarketCapContext = async (params) => {
|
|
|
4401
4601
|
throw error;
|
|
4402
4602
|
}
|
|
4403
4603
|
coinMarketCapContextUnavailable = true;
|
|
4404
|
-
|
|
4604
|
+
import_logger5.logger.warn(
|
|
4405
4605
|
"CoinMarketCap context disabled after Timescale read failure: %s",
|
|
4406
4606
|
String(error)
|
|
4407
4607
|
);
|
|
@@ -4415,7 +4615,7 @@ var import_data2 = require("@tradejs/core/data");
|
|
|
4415
4615
|
var import_strategies3 = require("@tradejs/core/strategies");
|
|
4416
4616
|
var import_constants2 = require("@tradejs/core/constants");
|
|
4417
4617
|
var import_derivatives = require("@tradejs/infra/timescale/derivatives");
|
|
4418
|
-
var
|
|
4618
|
+
var import_logger6 = require("@tradejs/infra/logger");
|
|
4419
4619
|
var STORED_INTERVALS = ["15m", "1h"];
|
|
4420
4620
|
var CONTEXT_INTERVALS = ["15m", "1h"];
|
|
4421
4621
|
var DEFAULT_LOOKBACK_HOURS = 48;
|
|
@@ -4470,7 +4670,7 @@ var resolvePrimaryReferenceSymbol2 = () => PRIMARY_DERIVATIVES_REFERENCE_SYMBOL;
|
|
|
4470
4670
|
var resolveSecondaryReferenceSymbol = () => SECONDARY_DERIVATIVES_REFERENCE_SYMBOL;
|
|
4471
4671
|
var getPrimaryIntervalContext = (context) => context?.intervals["15m"] ?? context?.intervals["1h"] ?? null;
|
|
4472
4672
|
var hasDerivativesSymbolData = (context) => Object.keys(context.intervals).length > 0 && !context.summary.riskFlags.includes("missing_derivatives");
|
|
4473
|
-
var
|
|
4673
|
+
var toFiniteNumberOrNull4 = (value) => {
|
|
4474
4674
|
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
4475
4675
|
if (typeof value === "string" && value.trim()) {
|
|
4476
4676
|
const parsed = Number(value);
|
|
@@ -4484,8 +4684,8 @@ var roundNullable = (value, digits = 4) => {
|
|
|
4484
4684
|
return Math.round(value * multiplier) / multiplier;
|
|
4485
4685
|
};
|
|
4486
4686
|
var deltaNullable = (targetValue, referenceValue) => {
|
|
4487
|
-
const target =
|
|
4488
|
-
const reference =
|
|
4687
|
+
const target = toFiniteNumberOrNull4(targetValue);
|
|
4688
|
+
const reference = toFiniteNumberOrNull4(referenceValue);
|
|
4489
4689
|
return target == null || reference == null ? null : roundNullable(target - reference);
|
|
4490
4690
|
};
|
|
4491
4691
|
var buildTargetDerivedContext = (params) => {
|
|
@@ -4647,7 +4847,7 @@ var enrichSignalWithDerivativesContext = async (params) => {
|
|
|
4647
4847
|
throw error;
|
|
4648
4848
|
}
|
|
4649
4849
|
derivativesContextUnavailable = true;
|
|
4650
|
-
|
|
4850
|
+
import_logger6.logger.warn(
|
|
4651
4851
|
"Derivatives context disabled after Timescale read failure: %s",
|
|
4652
4852
|
String(error)
|
|
4653
4853
|
);
|
|
@@ -4659,7 +4859,7 @@ var enrichSignalWithDerivativesContext = async (params) => {
|
|
|
4659
4859
|
var import_data3 = require("@tradejs/core/data");
|
|
4660
4860
|
var import_strategies4 = require("@tradejs/core/strategies");
|
|
4661
4861
|
var import_hyperliquidWhales2 = require("@tradejs/infra/timescale/hyperliquidWhales");
|
|
4662
|
-
var
|
|
4862
|
+
var import_logger7 = require("@tradejs/infra/logger");
|
|
4663
4863
|
|
|
4664
4864
|
// src/hyperliquidWhaleUniverse.ts
|
|
4665
4865
|
var import_node_crypto3 = require("crypto");
|
|
@@ -5179,7 +5379,7 @@ var loadHyperliquidWhaleFlowContext = async (params) => {
|
|
|
5179
5379
|
throw error;
|
|
5180
5380
|
}
|
|
5181
5381
|
hyperliquidWhaleContextUnavailable = true;
|
|
5182
|
-
|
|
5382
|
+
import_logger7.logger.warn(
|
|
5183
5383
|
"Hyperliquid whale context disabled after Timescale read failure: %s",
|
|
5184
5384
|
String(error)
|
|
5185
5385
|
);
|
|
@@ -5262,7 +5462,7 @@ var runMarketContextStage = async ({
|
|
|
5262
5462
|
elapsedMs: Date.now() - startedAt
|
|
5263
5463
|
};
|
|
5264
5464
|
if (status === "timed_out") {
|
|
5265
|
-
|
|
5465
|
+
import_logger8.logger.warn(
|
|
5266
5466
|
"Market context stage timed out: %s after %sms",
|
|
5267
5467
|
stage,
|
|
5268
5468
|
result.elapsedMs
|
|
@@ -5452,79 +5652,10 @@ var enrichSignalWithAi = async ({
|
|
|
5452
5652
|
signal.aiAnalysis = analysis;
|
|
5453
5653
|
return resolveAiQuality(analysis, direction);
|
|
5454
5654
|
} catch (err) {
|
|
5455
|
-
|
|
5655
|
+
import_logger9.logger.error("AI analysis error: %s %s", symbol, formatAiError(err));
|
|
5456
5656
|
}
|
|
5457
5657
|
return void 0;
|
|
5458
5658
|
};
|
|
5459
|
-
var toFiniteNumberOrNull4 = (value) => typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
5460
|
-
var getOrderArrivalSnapshot = async ({
|
|
5461
|
-
connector,
|
|
5462
|
-
symbol
|
|
5463
|
-
}) => {
|
|
5464
|
-
if (typeof connector.getTopOfBookTicker !== "function") {
|
|
5465
|
-
return {
|
|
5466
|
-
arrivalSnapshotTime: Date.now(),
|
|
5467
|
-
arrivalSource: "unavailable",
|
|
5468
|
-
bid: null,
|
|
5469
|
-
ask: null,
|
|
5470
|
-
arrivalMid: null,
|
|
5471
|
-
spreadBps: null
|
|
5472
|
-
};
|
|
5473
|
-
}
|
|
5474
|
-
try {
|
|
5475
|
-
const ticker = await connector.getTopOfBookTicker(symbol);
|
|
5476
|
-
const arrivalSnapshotTime = toFiniteNumberOrNull4(ticker?.timestamp);
|
|
5477
|
-
const bid = toFiniteNumberOrNull4(ticker?.bidPrice);
|
|
5478
|
-
const ask = toFiniteNumberOrNull4(ticker?.askPrice);
|
|
5479
|
-
const arrivalMid = bid != null && ask != null ? (bid + ask) / 2 : null;
|
|
5480
|
-
const spreadBps = bid != null && ask != null && arrivalMid != null && arrivalMid > 0 ? (ask - bid) / arrivalMid * 1e4 : null;
|
|
5481
|
-
return {
|
|
5482
|
-
arrivalSnapshotTime: arrivalSnapshotTime ?? Date.now(),
|
|
5483
|
-
arrivalSource: "top_of_book",
|
|
5484
|
-
bid,
|
|
5485
|
-
ask,
|
|
5486
|
-
arrivalMid,
|
|
5487
|
-
spreadBps
|
|
5488
|
-
};
|
|
5489
|
-
} catch (error) {
|
|
5490
|
-
import_logger8.logger.warn(
|
|
5491
|
-
"runtime order arrival snapshot failed: %s %s",
|
|
5492
|
-
symbol,
|
|
5493
|
-
error?.message || String(error)
|
|
5494
|
-
);
|
|
5495
|
-
return {
|
|
5496
|
-
arrivalSnapshotTime: Date.now(),
|
|
5497
|
-
arrivalSource: "top_of_book_error",
|
|
5498
|
-
bid: null,
|
|
5499
|
-
ask: null,
|
|
5500
|
-
arrivalMid: null,
|
|
5501
|
-
spreadBps: null
|
|
5502
|
-
};
|
|
5503
|
-
}
|
|
5504
|
-
};
|
|
5505
|
-
var validateEntryProtectionAtArrival = ({
|
|
5506
|
-
direction,
|
|
5507
|
-
signalPrice,
|
|
5508
|
-
bid,
|
|
5509
|
-
ask,
|
|
5510
|
-
arrivalMid,
|
|
5511
|
-
takeProfits,
|
|
5512
|
-
stopLossPrice
|
|
5513
|
-
}) => {
|
|
5514
|
-
const entryReference = direction === "LONG" ? ask ?? arrivalMid ?? signalPrice : bid ?? arrivalMid ?? signalPrice;
|
|
5515
|
-
const stopReference = direction === "LONG" ? bid ?? arrivalMid ?? signalPrice : ask ?? arrivalMid ?? signalPrice;
|
|
5516
|
-
if (!Number.isFinite(entryReference) || entryReference <= 0 || !Number.isFinite(stopReference) || stopReference <= 0) {
|
|
5517
|
-
throw new Error("INVALID_ENTRY_REFERENCE_AT_ARRIVAL");
|
|
5518
|
-
}
|
|
5519
|
-
for (const takeProfit of takeProfits) {
|
|
5520
|
-
if (!Number.isFinite(takeProfit.price) || takeProfit.price <= 0 || (direction === "LONG" ? takeProfit.price <= entryReference : takeProfit.price >= entryReference)) {
|
|
5521
|
-
throw new Error("TAKE_PROFIT_CROSSED_BEFORE_ENTRY");
|
|
5522
|
-
}
|
|
5523
|
-
}
|
|
5524
|
-
if (stopLossPrice != null && (!Number.isFinite(stopLossPrice) || stopLossPrice <= 0 || (direction === "LONG" ? stopLossPrice >= stopReference : stopLossPrice <= stopReference))) {
|
|
5525
|
-
throw new Error("STOP_LOSS_CROSSED_BEFORE_ENTRY");
|
|
5526
|
-
}
|
|
5527
|
-
};
|
|
5528
5659
|
var resolveRuntimeTelemetryQuality = ({
|
|
5529
5660
|
signalClosePrice,
|
|
5530
5661
|
arrivalMid,
|
|
@@ -5601,7 +5732,8 @@ var executeEntryOrder = async ({
|
|
|
5601
5732
|
signal,
|
|
5602
5733
|
beforePlaceOrder,
|
|
5603
5734
|
recordRuntimeTrade = true,
|
|
5604
|
-
leverage
|
|
5735
|
+
leverage,
|
|
5736
|
+
executionLimits
|
|
5605
5737
|
}) => {
|
|
5606
5738
|
await beforePlaceOrder?.();
|
|
5607
5739
|
const previousPosition = positionIntent === "increase" ? await connector.getPosition(symbol) : null;
|
|
@@ -5612,23 +5744,57 @@ var executeEntryOrder = async ({
|
|
|
5612
5744
|
signal.orderQty = qty;
|
|
5613
5745
|
signal.orderValue = qty * currentPrice;
|
|
5614
5746
|
signal.orderFailureReason = void 0;
|
|
5615
|
-
|
|
5616
|
-
|
|
5617
|
-
|
|
5618
|
-
|
|
5619
|
-
|
|
5620
|
-
|
|
5621
|
-
|
|
5622
|
-
|
|
5623
|
-
|
|
5624
|
-
|
|
5625
|
-
|
|
5626
|
-
|
|
5627
|
-
|
|
5628
|
-
|
|
5629
|
-
|
|
5747
|
+
let arrivalSnapshot = {
|
|
5748
|
+
arrivalSnapshotTime: Date.now(),
|
|
5749
|
+
arrivalSource: "unavailable",
|
|
5750
|
+
bid: null,
|
|
5751
|
+
ask: null,
|
|
5752
|
+
arrivalMid: null,
|
|
5753
|
+
spreadBps: null
|
|
5754
|
+
};
|
|
5755
|
+
let orderSubmitTime = Date.now();
|
|
5756
|
+
const beforeSubmit = createEntrySubmissionValidation({
|
|
5757
|
+
connector,
|
|
5758
|
+
symbol,
|
|
5759
|
+
direction,
|
|
5760
|
+
takeProfits,
|
|
5761
|
+
stopLossPrice,
|
|
5762
|
+
limits: executionLimits,
|
|
5763
|
+
onValidated: (snapshot2, economics2) => {
|
|
5764
|
+
arrivalSnapshot = snapshot2;
|
|
5765
|
+
orderSubmitTime = Date.now();
|
|
5766
|
+
if (executionLimits?.maxLossValue != null) {
|
|
5767
|
+
signal.riskDecision = {
|
|
5768
|
+
stage: "order_plan",
|
|
5769
|
+
status: "approved",
|
|
5770
|
+
reason: "PLANNED_LOSS_WITHIN_MAX_LOSS_VALUE",
|
|
5771
|
+
plannedLossValue: economics2.plannedLossValue,
|
|
5772
|
+
maxLossValue: executionLimits.maxLossValue,
|
|
5773
|
+
limitUtilization: economics2.plannedLossValue / executionLimits.maxLossValue,
|
|
5774
|
+
enforced: true
|
|
5775
|
+
};
|
|
5776
|
+
}
|
|
5777
|
+
}
|
|
5778
|
+
});
|
|
5779
|
+
if (!beforeSubmit) {
|
|
5780
|
+
arrivalSnapshot = await getOrderArrivalSnapshot({ connector, symbol });
|
|
5781
|
+
try {
|
|
5782
|
+
validateEntryProtectionAtArrival({
|
|
5783
|
+
direction,
|
|
5784
|
+
signalPrice: currentPrice,
|
|
5785
|
+
bid: arrivalSnapshot.bid,
|
|
5786
|
+
ask: arrivalSnapshot.ask,
|
|
5787
|
+
arrivalMid: arrivalSnapshot.arrivalMid,
|
|
5788
|
+
takeProfits,
|
|
5789
|
+
stopLossPrice
|
|
5790
|
+
});
|
|
5791
|
+
} catch (error) {
|
|
5792
|
+
signal.orderStatus = "failed";
|
|
5793
|
+
signal.orderFailureReason = error.message;
|
|
5794
|
+
throw error;
|
|
5795
|
+
}
|
|
5796
|
+
orderSubmitTime = Date.now();
|
|
5630
5797
|
}
|
|
5631
|
-
const orderSubmitTime = Date.now();
|
|
5632
5798
|
const orderPlaced = await connector.placeOrder({
|
|
5633
5799
|
symbol,
|
|
5634
5800
|
qty,
|
|
@@ -5639,7 +5805,8 @@ var executeEntryOrder = async ({
|
|
|
5639
5805
|
direction,
|
|
5640
5806
|
...typeof leverage === "number" && Number.isFinite(leverage) ? { leverage } : {},
|
|
5641
5807
|
orderId,
|
|
5642
|
-
signal
|
|
5808
|
+
signal,
|
|
5809
|
+
...beforeSubmit ? { beforeSubmit } : {}
|
|
5643
5810
|
});
|
|
5644
5811
|
const orderAckTime = Date.now();
|
|
5645
5812
|
const placedQty = typeof signal.orderQty === "number" && Number.isFinite(signal.orderQty) && signal.orderQty > 0 ? signal.orderQty : qty;
|
|
@@ -6468,7 +6635,7 @@ var canUseSharedReplayState = ({
|
|
|
6468
6635
|
}) => (env === "BACKTEST" || env === "PARITY") && Boolean(sharedReplayKey);
|
|
6469
6636
|
|
|
6470
6637
|
// src/strategy/runtimeExecution.ts
|
|
6471
|
-
var
|
|
6638
|
+
var import_logger10 = require("@tradejs/infra/logger");
|
|
6472
6639
|
var import_types = require("@tradejs/types");
|
|
6473
6640
|
var buildExitOrderSignal = ({
|
|
6474
6641
|
strategyName,
|
|
@@ -6520,7 +6687,7 @@ var handleExitDecision = async ({
|
|
|
6520
6687
|
deploymentId: connector.deploymentId
|
|
6521
6688
|
});
|
|
6522
6689
|
if (!activeTrade) {
|
|
6523
|
-
|
|
6690
|
+
import_logger10.logger.warn(
|
|
6524
6691
|
"[%s] blocked closePosition for untracked runtime position: %s",
|
|
6525
6692
|
strategyName ?? "unknown",
|
|
6526
6693
|
symbol
|
|
@@ -6528,7 +6695,7 @@ var handleExitDecision = async ({
|
|
|
6528
6695
|
return "CLOSE_BLOCKED_BY_UNTRACKED_POSITION";
|
|
6529
6696
|
}
|
|
6530
6697
|
if (!strategyName || activeTrade.strategy !== strategyName) {
|
|
6531
|
-
|
|
6698
|
+
import_logger10.logger.warn(
|
|
6532
6699
|
"[%s] blocked closePosition for foreign runtime position: %s ownedBy=%s",
|
|
6533
6700
|
strategyName ?? "unknown",
|
|
6534
6701
|
symbol,
|
|
@@ -6581,7 +6748,7 @@ var handleExitDecision = async ({
|
|
|
6581
6748
|
exitType: closedTrade?.exitType ?? "exit"
|
|
6582
6749
|
});
|
|
6583
6750
|
} catch (notificationError) {
|
|
6584
|
-
|
|
6751
|
+
import_logger10.logger.error(
|
|
6585
6752
|
"runtime close notification error: %s %s",
|
|
6586
6753
|
symbol,
|
|
6587
6754
|
notificationError
|
|
@@ -6595,7 +6762,7 @@ var handleExitDecision = async ({
|
|
|
6595
6762
|
decision,
|
|
6596
6763
|
market
|
|
6597
6764
|
});
|
|
6598
|
-
|
|
6765
|
+
import_logger10.logger.error("close order error: %s %s", symbol, err);
|
|
6599
6766
|
return "ORDER_ERROR";
|
|
6600
6767
|
}
|
|
6601
6768
|
return decision.code;
|
|
@@ -6622,7 +6789,7 @@ var handleProtectDecision = async ({
|
|
|
6622
6789
|
decision,
|
|
6623
6790
|
market
|
|
6624
6791
|
});
|
|
6625
|
-
|
|
6792
|
+
import_logger10.logger.error("protect position error: %s %s", symbol, err);
|
|
6626
6793
|
return "ORDER_ERROR";
|
|
6627
6794
|
}
|
|
6628
6795
|
return decision.code;
|
|
@@ -6688,7 +6855,11 @@ var executeEntryDecision = async ({
|
|
|
6688
6855
|
...Number.isFinite(Number(hookCtx.strategyConfig.LEVERAGE)) ? { leverage: Number(hookCtx.strategyConfig.LEVERAGE) } : {},
|
|
6689
6856
|
signal,
|
|
6690
6857
|
beforePlaceOrder,
|
|
6691
|
-
recordRuntimeTrade: recordRuntimeJournal
|
|
6858
|
+
recordRuntimeTrade: recordRuntimeJournal,
|
|
6859
|
+
executionLimits: resolveEntryExecutionLimits(
|
|
6860
|
+
hookCtx.strategyConfig,
|
|
6861
|
+
decision.entryContext.direction
|
|
6862
|
+
)
|
|
6692
6863
|
});
|
|
6693
6864
|
await invokeStageHooks(
|
|
6694
6865
|
"afterPlaceOrder",
|
|
@@ -6710,19 +6881,32 @@ var executeEntryDecision = async ({
|
|
|
6710
6881
|
return signal;
|
|
6711
6882
|
}
|
|
6712
6883
|
await beforePlaceOrder();
|
|
6713
|
-
const
|
|
6884
|
+
const beforeSubmit = createEntrySubmissionValidation({
|
|
6714
6885
|
connector,
|
|
6715
|
-
symbol
|
|
6716
|
-
});
|
|
6717
|
-
validateEntryProtectionAtArrival({
|
|
6886
|
+
symbol,
|
|
6718
6887
|
direction: decision.entryContext.direction,
|
|
6719
|
-
signalPrice: decision.entryContext.prices.currentPrice,
|
|
6720
|
-
bid: arrivalSnapshot.bid,
|
|
6721
|
-
ask: arrivalSnapshot.ask,
|
|
6722
|
-
arrivalMid: arrivalSnapshot.arrivalMid,
|
|
6723
6888
|
takeProfits: decision.orderPlan.takeProfits,
|
|
6724
|
-
stopLossPrice: decision.orderPlan.stopLossPrice
|
|
6889
|
+
stopLossPrice: decision.orderPlan.stopLossPrice,
|
|
6890
|
+
limits: resolveEntryExecutionLimits(
|
|
6891
|
+
hookCtx.strategyConfig,
|
|
6892
|
+
decision.entryContext.direction
|
|
6893
|
+
)
|
|
6725
6894
|
});
|
|
6895
|
+
if (!beforeSubmit) {
|
|
6896
|
+
const arrivalSnapshot = await getOrderArrivalSnapshot({
|
|
6897
|
+
connector,
|
|
6898
|
+
symbol
|
|
6899
|
+
});
|
|
6900
|
+
validateEntryProtectionAtArrival({
|
|
6901
|
+
direction: decision.entryContext.direction,
|
|
6902
|
+
signalPrice: decision.entryContext.prices.currentPrice,
|
|
6903
|
+
bid: arrivalSnapshot.bid,
|
|
6904
|
+
ask: arrivalSnapshot.ask,
|
|
6905
|
+
arrivalMid: arrivalSnapshot.arrivalMid,
|
|
6906
|
+
takeProfits: decision.orderPlan.takeProfits,
|
|
6907
|
+
stopLossPrice: decision.orderPlan.stopLossPrice
|
|
6908
|
+
});
|
|
6909
|
+
}
|
|
6726
6910
|
const orderPlaced = await connector.placeOrder({
|
|
6727
6911
|
symbol,
|
|
6728
6912
|
qty: decision.orderPlan.qty,
|
|
@@ -6730,6 +6914,7 @@ var executeEntryDecision = async ({
|
|
|
6730
6914
|
timestamp: decision.entryContext.timestamp,
|
|
6731
6915
|
direction: decision.entryContext.direction,
|
|
6732
6916
|
positionIntent: decision.orderPlan.positionIntent,
|
|
6917
|
+
...beforeSubmit ? { beforeSubmit } : {},
|
|
6733
6918
|
...Number.isFinite(Number(hookCtx.strategyConfig.LEVERAGE)) ? { leverage: Number(hookCtx.strategyConfig.LEVERAGE) } : {}
|
|
6734
6919
|
});
|
|
6735
6920
|
if (!orderPlaced) {
|
|
@@ -6771,6 +6956,23 @@ var executeEntryDecision = async ({
|
|
|
6771
6956
|
{ decision, entry, market }
|
|
6772
6957
|
);
|
|
6773
6958
|
} catch (err) {
|
|
6959
|
+
if (err instanceof EntrySubmissionValidationError) {
|
|
6960
|
+
if (signal) {
|
|
6961
|
+
signal.orderStatus = "skipped";
|
|
6962
|
+
signal.orderSkipReason = err.message;
|
|
6963
|
+
signal.allocatorDecision = {
|
|
6964
|
+
stage: "runtime_admission",
|
|
6965
|
+
status: "rejected",
|
|
6966
|
+
reason: err.message
|
|
6967
|
+
};
|
|
6968
|
+
}
|
|
6969
|
+
import_logger10.logger.warn(
|
|
6970
|
+
"entry rejected before submission: %s %s",
|
|
6971
|
+
symbol,
|
|
6972
|
+
err.message
|
|
6973
|
+
);
|
|
6974
|
+
return signal ?? err.message;
|
|
6975
|
+
}
|
|
6774
6976
|
if (signal) {
|
|
6775
6977
|
signal.orderStatus = "failed";
|
|
6776
6978
|
if (typeof signal.orderFailureReason !== "string" || !signal.orderFailureReason.trim()) {
|
|
@@ -6785,9 +6987,9 @@ var executeEntryDecision = async ({
|
|
|
6785
6987
|
market
|
|
6786
6988
|
});
|
|
6787
6989
|
if (err?.message === import_types.BACKTEST_WARNING_CODES.TAKE_PROFIT_CROSSED_BEFORE_ENTRY) {
|
|
6788
|
-
|
|
6990
|
+
import_logger10.logger.warn("order warning: %s %s", symbol, err);
|
|
6789
6991
|
} else {
|
|
6790
|
-
|
|
6992
|
+
import_logger10.logger.error("order error: %s %s", symbol, err);
|
|
6791
6993
|
}
|
|
6792
6994
|
return signal ?? "ORDER_ERROR";
|
|
6793
6995
|
}
|
|
@@ -6952,7 +7154,7 @@ var createStrategyRuntime = ({
|
|
|
6952
7154
|
try {
|
|
6953
7155
|
await projectHook(errorParams);
|
|
6954
7156
|
} catch (hookError) {
|
|
6955
|
-
|
|
7157
|
+
import_logger11.logger.error(
|
|
6956
7158
|
"project hook onRuntimeError failed: %s %s",
|
|
6957
7159
|
strategyName,
|
|
6958
7160
|
hookError
|
|
@@ -6966,7 +7168,7 @@ var createStrategyRuntime = ({
|
|
|
6966
7168
|
try {
|
|
6967
7169
|
await onRuntimeError(errorParams);
|
|
6968
7170
|
} catch (hookError) {
|
|
6969
|
-
|
|
7171
|
+
import_logger11.logger.error(
|
|
6970
7172
|
"runtime hook onRuntimeError failed: %s %s",
|
|
6971
7173
|
strategyName,
|
|
6972
7174
|
hookError
|
|
@@ -6980,7 +7182,7 @@ var createStrategyRuntime = ({
|
|
|
6980
7182
|
try {
|
|
6981
7183
|
return await hook(params);
|
|
6982
7184
|
} catch (error) {
|
|
6983
|
-
|
|
7185
|
+
import_logger11.logger.error(
|
|
6984
7186
|
'strategy hook "%s" failed for %s: %s',
|
|
6985
7187
|
stage,
|
|
6986
7188
|
strategyName,
|
|
@@ -7802,10 +8004,10 @@ var createStrategyRuntime = ({
|
|
|
7802
8004
|
setStrategyRuntimeFactory(createStrategyRuntime);
|
|
7803
8005
|
|
|
7804
8006
|
// src/connectorsRegistry.ts
|
|
7805
|
-
var
|
|
8007
|
+
var import_logger14 = require("@tradejs/infra/logger");
|
|
7806
8008
|
|
|
7807
8009
|
// src/connectorRuntime.ts
|
|
7808
|
-
var
|
|
8010
|
+
var import_logger13 = require("@tradejs/infra/logger");
|
|
7809
8011
|
var import_tradingAccounts = require("@tradejs/infra/tradingAccounts");
|
|
7810
8012
|
|
|
7811
8013
|
// src/timescaleCachedKline.ts
|
|
@@ -7813,7 +8015,7 @@ var import_constants6 = require("@tradejs/core/constants");
|
|
|
7813
8015
|
var import_data5 = require("@tradejs/core/data");
|
|
7814
8016
|
var import_time2 = require("@tradejs/core/time");
|
|
7815
8017
|
var import_async = require("@tradejs/core/async");
|
|
7816
|
-
var
|
|
8018
|
+
var import_logger12 = require("@tradejs/infra/logger");
|
|
7817
8019
|
var import_candles = require("@tradejs/infra/timescale/candles");
|
|
7818
8020
|
var DEFAULT_LIMIT = 1e3;
|
|
7819
8021
|
var DEFAULT_CACHE_FALLBACK_WINDOW = 1e3;
|
|
@@ -7923,7 +8125,7 @@ var createTimescaleCachedKline = ({
|
|
|
7923
8125
|
}) => {
|
|
7924
8126
|
const intMinutes = intervalToMinutes(interval);
|
|
7925
8127
|
if (!intMinutes) {
|
|
7926
|
-
|
|
8128
|
+
import_logger12.logger.log("error", "refreshTail: invalid interval %s", interval);
|
|
7927
8129
|
return;
|
|
7928
8130
|
}
|
|
7929
8131
|
const intervalMs = intervalMsOf(intMinutes);
|
|
@@ -7954,7 +8156,7 @@ var createTimescaleCachedKline = ({
|
|
|
7954
8156
|
}) => {
|
|
7955
8157
|
const intMinutes = intervalToMinutes(interval);
|
|
7956
8158
|
if (!intMinutes) {
|
|
7957
|
-
|
|
8159
|
+
import_logger12.logger.log("error", "kline: invalid interval %s", interval);
|
|
7958
8160
|
return [];
|
|
7959
8161
|
}
|
|
7960
8162
|
if (defaultStart !== void 0 && defaultEnd !== void 0 && defaultEnd <= defaultStart) {
|
|
@@ -8063,7 +8265,7 @@ var createTimescaleCachedKline = ({
|
|
|
8063
8265
|
if (warmOnly) {
|
|
8064
8266
|
if (isTimescaleFallbackMode) {
|
|
8065
8267
|
isTimescaleFallbackMode = false;
|
|
8066
|
-
|
|
8268
|
+
import_logger12.logger.log("info", "TimescaleDB connection restored for kline cache");
|
|
8067
8269
|
}
|
|
8068
8270
|
return [];
|
|
8069
8271
|
}
|
|
@@ -8081,13 +8283,13 @@ var createTimescaleCachedKline = ({
|
|
|
8081
8283
|
);
|
|
8082
8284
|
if (isTimescaleFallbackMode) {
|
|
8083
8285
|
isTimescaleFallbackMode = false;
|
|
8084
|
-
|
|
8286
|
+
import_logger12.logger.log("info", "TimescaleDB connection restored for kline cache");
|
|
8085
8287
|
}
|
|
8086
8288
|
return dbData;
|
|
8087
8289
|
} catch (error) {
|
|
8088
8290
|
if (!isTimescaleFallbackMode) {
|
|
8089
8291
|
isTimescaleFallbackMode = true;
|
|
8090
|
-
|
|
8292
|
+
import_logger12.logger.log(
|
|
8091
8293
|
"warn",
|
|
8092
8294
|
"TimescaleDB unavailable for %s %s: %s. Falling back to exchange API.",
|
|
8093
8295
|
symbol,
|
|
@@ -8111,7 +8313,7 @@ var createTimescaleCachedKline = ({
|
|
|
8111
8313
|
|
|
8112
8314
|
// src/connectorRuntime.ts
|
|
8113
8315
|
var connectorRuntime = {
|
|
8114
|
-
logger:
|
|
8316
|
+
logger: import_logger13.logger,
|
|
8115
8317
|
resolveTradingAccount: import_tradingAccounts.resolveTradingAccount,
|
|
8116
8318
|
createCachedKline: createTimescaleCachedKline
|
|
8117
8319
|
};
|
|
@@ -8172,7 +8374,7 @@ var normalizeProviders = (providers, connectorName) => {
|
|
|
8172
8374
|
var registerProvider = (provider, connectorName, source, providerToConnectorName) => {
|
|
8173
8375
|
const existing = providerToConnectorName.get(provider);
|
|
8174
8376
|
if (existing && existing !== connectorName) {
|
|
8175
|
-
|
|
8377
|
+
import_logger14.logger.warn(
|
|
8176
8378
|
'Skip duplicate connector provider "%s" from %s: already mapped to %s',
|
|
8177
8379
|
provider,
|
|
8178
8380
|
source,
|
|
@@ -8185,11 +8387,11 @@ var registerProvider = (provider, connectorName, source, providerToConnectorName
|
|
|
8185
8387
|
var registerEntry = (entry, source, state) => {
|
|
8186
8388
|
const connectorName = String(entry?.name ?? "").trim();
|
|
8187
8389
|
if (!connectorName) {
|
|
8188
|
-
|
|
8390
|
+
import_logger14.logger.warn("Skip connector entry without name from %s", source);
|
|
8189
8391
|
return;
|
|
8190
8392
|
}
|
|
8191
8393
|
if (typeof entry.creator !== "function") {
|
|
8192
|
-
|
|
8394
|
+
import_logger14.logger.warn(
|
|
8193
8395
|
'Skip connector entry "%s" from %s: creator must be a function',
|
|
8194
8396
|
connectorName,
|
|
8195
8397
|
source
|
|
@@ -8201,7 +8403,7 @@ var registerEntry = (entry, source, state) => {
|
|
|
8201
8403
|
state.connectorCreators
|
|
8202
8404
|
);
|
|
8203
8405
|
if (existingByName) {
|
|
8204
|
-
|
|
8406
|
+
import_logger14.logger.warn(
|
|
8205
8407
|
'Skip duplicate connector "%s" from %s: already registered as %s',
|
|
8206
8408
|
connectorName,
|
|
8207
8409
|
source,
|
|
@@ -8276,7 +8478,7 @@ var ensureConnectorPluginsLoaded = async (cwd = getTradejsProjectCwd()) => {
|
|
|
8276
8478
|
);
|
|
8277
8479
|
const pluginDefinition = extractConnectorPluginDefinition(moduleExport);
|
|
8278
8480
|
if (!pluginDefinition) {
|
|
8279
|
-
|
|
8481
|
+
import_logger14.logger.warn(
|
|
8280
8482
|
'Skip connector plugin "%s": export { connectorEntries } is missing',
|
|
8281
8483
|
moduleName
|
|
8282
8484
|
);
|
|
@@ -8284,7 +8486,7 @@ var ensureConnectorPluginsLoaded = async (cwd = getTradejsProjectCwd()) => {
|
|
|
8284
8486
|
}
|
|
8285
8487
|
registerEntries2(pluginDefinition.connectorEntries, moduleName, state);
|
|
8286
8488
|
} catch (error) {
|
|
8287
|
-
|
|
8489
|
+
import_logger14.logger.warn(
|
|
8288
8490
|
'Failed to load connector plugin "%s": %s',
|
|
8289
8491
|
moduleName,
|
|
8290
8492
|
String(error)
|