@vizzor/cli 0.15.1 → 0.15.2
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/index.js +249 -205
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -47499,6 +47499,124 @@ var init_horizon_packs = __esm({
|
|
|
47499
47499
|
}
|
|
47500
47500
|
});
|
|
47501
47501
|
|
|
47502
|
+
// src/notifications/scheduler-state.ts
|
|
47503
|
+
var scheduler_state_exports = {};
|
|
47504
|
+
__export(scheduler_state_exports, {
|
|
47505
|
+
applySchedulerStateOverlay: () => applySchedulerStateOverlay,
|
|
47506
|
+
isSchedulerRunningPersisted: () => isSchedulerRunningPersisted,
|
|
47507
|
+
persistDefaultSymbols: () => persistDefaultSymbols,
|
|
47508
|
+
persistSchedulerRunning: () => persistSchedulerRunning,
|
|
47509
|
+
persistSlotEnabled: () => persistSlotEnabled,
|
|
47510
|
+
persistSlotFiringTimesUtc: () => persistSlotFiringTimesUtc,
|
|
47511
|
+
persistSlotHorizons: () => persistSlotHorizons,
|
|
47512
|
+
persistSlotInterval: () => persistSlotInterval,
|
|
47513
|
+
persistSlotSymbols: () => persistSlotSymbols
|
|
47514
|
+
});
|
|
47515
|
+
function ensureTable6() {
|
|
47516
|
+
getDb().exec(`
|
|
47517
|
+
CREATE TABLE IF NOT EXISTS scheduler_state (
|
|
47518
|
+
key TEXT PRIMARY KEY,
|
|
47519
|
+
value TEXT NOT NULL,
|
|
47520
|
+
updated_at INTEGER NOT NULL
|
|
47521
|
+
)
|
|
47522
|
+
`);
|
|
47523
|
+
}
|
|
47524
|
+
function setKey(key, value) {
|
|
47525
|
+
ensureTable6();
|
|
47526
|
+
getDb().prepare(
|
|
47527
|
+
`INSERT INTO scheduler_state (key, value, updated_at) VALUES (?, ?, ?)
|
|
47528
|
+
ON CONFLICT(key) DO UPDATE SET value = excluded.value, updated_at = excluded.updated_at`
|
|
47529
|
+
).run(key, JSON.stringify(value), Date.now());
|
|
47530
|
+
}
|
|
47531
|
+
function getKey(key) {
|
|
47532
|
+
ensureTable6();
|
|
47533
|
+
const row2 = getDb().prepare(`SELECT value FROM scheduler_state WHERE key = ?`).get(key);
|
|
47534
|
+
if (!row2) return null;
|
|
47535
|
+
try {
|
|
47536
|
+
return JSON.parse(row2.value);
|
|
47537
|
+
} catch {
|
|
47538
|
+
return null;
|
|
47539
|
+
}
|
|
47540
|
+
}
|
|
47541
|
+
function persistDefaultSymbols(symbols) {
|
|
47542
|
+
setKey("defaultSymbols", symbols);
|
|
47543
|
+
}
|
|
47544
|
+
function persistSchedulerRunning(running6) {
|
|
47545
|
+
setKey("running", running6);
|
|
47546
|
+
}
|
|
47547
|
+
function isSchedulerRunningPersisted() {
|
|
47548
|
+
return getKey("running");
|
|
47549
|
+
}
|
|
47550
|
+
function persistSlotEnabled(slotName, enabled) {
|
|
47551
|
+
const current = getKey("slotsEnabled") ?? {};
|
|
47552
|
+
current[slotName] = enabled;
|
|
47553
|
+
setKey("slotsEnabled", current);
|
|
47554
|
+
}
|
|
47555
|
+
function persistSlotSymbols(slotName, symbols) {
|
|
47556
|
+
const current = getKey("slotSymbols") ?? {};
|
|
47557
|
+
current[slotName] = symbols;
|
|
47558
|
+
setKey("slotSymbols", current);
|
|
47559
|
+
}
|
|
47560
|
+
function persistSlotHorizons(slotName, horizons) {
|
|
47561
|
+
const current = getKey("slotHorizons") ?? {};
|
|
47562
|
+
current[slotName] = horizons;
|
|
47563
|
+
setKey("slotHorizons", current);
|
|
47564
|
+
}
|
|
47565
|
+
function persistSlotInterval(slotName, intervalMinutes) {
|
|
47566
|
+
const current = getKey("slotIntervals") ?? {};
|
|
47567
|
+
current[slotName] = intervalMinutes;
|
|
47568
|
+
setKey("slotIntervals", current);
|
|
47569
|
+
}
|
|
47570
|
+
function persistSlotFiringTimesUtc(slotName, firingTimesUtc) {
|
|
47571
|
+
const current = getKey("slotFiringTimesUtc") ?? {};
|
|
47572
|
+
current[slotName] = firingTimesUtc === void 0 ? null : firingTimesUtc;
|
|
47573
|
+
setKey("slotFiringTimesUtc", current);
|
|
47574
|
+
}
|
|
47575
|
+
function applySchedulerStateOverlay(cfg) {
|
|
47576
|
+
try {
|
|
47577
|
+
const defaultSymbols = getKey("defaultSymbols");
|
|
47578
|
+
if (Array.isArray(defaultSymbols)) {
|
|
47579
|
+
cfg.defaultSymbols = defaultSymbols;
|
|
47580
|
+
}
|
|
47581
|
+
const slotsEnabled = getKey("slotsEnabled") ?? {};
|
|
47582
|
+
const slotSymbols = getKey("slotSymbols") ?? {};
|
|
47583
|
+
const slotHorizons = getKey("slotHorizons") ?? {};
|
|
47584
|
+
const slotIntervals = getKey("slotIntervals") ?? {};
|
|
47585
|
+
const slotFiringTimesUtc = getKey("slotFiringTimesUtc") ?? {};
|
|
47586
|
+
cfg.slots = cfg.slots.map((slot) => {
|
|
47587
|
+
const next = { ...slot };
|
|
47588
|
+
if (slotsEnabled[slot.name] !== void 0) next.enabled = slotsEnabled[slot.name];
|
|
47589
|
+
if (slotSymbols[slot.name] !== void 0) next.symbols = slotSymbols[slot.name];
|
|
47590
|
+
if (slotHorizons[slot.name] !== void 0) next.horizons = slotHorizons[slot.name];
|
|
47591
|
+
if (slotIntervals[slot.name] !== void 0) next.intervalMinutes = slotIntervals[slot.name];
|
|
47592
|
+
if (slotFiringTimesUtc[slot.name] !== void 0) {
|
|
47593
|
+
const v = slotFiringTimesUtc[slot.name];
|
|
47594
|
+
if (v === null) {
|
|
47595
|
+
delete next.firingTimesUtc;
|
|
47596
|
+
} else {
|
|
47597
|
+
next.firingTimesUtc = v;
|
|
47598
|
+
}
|
|
47599
|
+
}
|
|
47600
|
+
return next;
|
|
47601
|
+
});
|
|
47602
|
+
return cfg;
|
|
47603
|
+
} catch (err) {
|
|
47604
|
+
log111.debug(
|
|
47605
|
+
`applySchedulerStateOverlay failed: ${err instanceof Error ? err.message : String(err)}`
|
|
47606
|
+
);
|
|
47607
|
+
return cfg;
|
|
47608
|
+
}
|
|
47609
|
+
}
|
|
47610
|
+
var log111;
|
|
47611
|
+
var init_scheduler_state = __esm({
|
|
47612
|
+
"src/notifications/scheduler-state.ts"() {
|
|
47613
|
+
"use strict";
|
|
47614
|
+
init_cache();
|
|
47615
|
+
init_logger();
|
|
47616
|
+
log111 = createLogger("notifications:scheduler-state");
|
|
47617
|
+
}
|
|
47618
|
+
});
|
|
47619
|
+
|
|
47502
47620
|
// src/notifications/bridges/prediction-scheduler.ts
|
|
47503
47621
|
var prediction_scheduler_exports = {};
|
|
47504
47622
|
__export(prediction_scheduler_exports, {
|
|
@@ -47690,7 +47808,7 @@ async function runPredictionSlot(slot, defaultSymbols, resolveFirst, maxConcurre
|
|
|
47690
47808
|
if (slot.activeHoursStart !== void 0 && slot.activeHoursEnd !== void 0) {
|
|
47691
47809
|
const hour = getHourInTimezone(slot.activeHoursTimezone);
|
|
47692
47810
|
if (hour < slot.activeHoursStart || hour >= slot.activeHoursEnd) {
|
|
47693
|
-
|
|
47811
|
+
log112.debug(
|
|
47694
47812
|
`Slot "${slot.name}" outside active hours (${slot.activeHoursStart}-${slot.activeHoursEnd}${slot.activeHoursTimezone ? `, tz=${slot.activeHoursTimezone}` : ""}), skipping`
|
|
47695
47813
|
);
|
|
47696
47814
|
return;
|
|
@@ -47698,18 +47816,20 @@ async function runPredictionSlot(slot, defaultSymbols, resolveFirst, maxConcurre
|
|
|
47698
47816
|
}
|
|
47699
47817
|
const symbols = slot.symbols.length > 0 ? slot.symbols : defaultSymbols;
|
|
47700
47818
|
if (symbols.length === 0) {
|
|
47701
|
-
|
|
47819
|
+
log112.warn(
|
|
47820
|
+
`[${slot.name}] No symbols configured for this slot and no defaults available \u2014 cycle skipped. Set defaults via /scheduler defaults BTC,ETH,SOL or override per-slot.`
|
|
47821
|
+
);
|
|
47702
47822
|
return;
|
|
47703
47823
|
}
|
|
47704
47824
|
const horizonsStr = slot.horizons.join(",");
|
|
47705
|
-
|
|
47825
|
+
log112.info(`[${slot.name}] Running predictions for ${symbols.join(",")} @ ${horizonsStr}`);
|
|
47706
47826
|
if (resolveFirst) {
|
|
47707
47827
|
try {
|
|
47708
47828
|
const { handleTool: handleTool2 } = await Promise.resolve().then(() => (init_tool_handler(), tool_handler_exports));
|
|
47709
47829
|
await handleTool2("resolve_predictions", {});
|
|
47710
|
-
|
|
47830
|
+
log112.debug(`[${slot.name}] Resolved pending predictions`);
|
|
47711
47831
|
} catch (err) {
|
|
47712
|
-
|
|
47832
|
+
log112.debug(
|
|
47713
47833
|
`[${slot.name}] Resolve failed: ${err instanceof Error ? err.message : String(err)}`
|
|
47714
47834
|
);
|
|
47715
47835
|
}
|
|
@@ -47767,7 +47887,7 @@ ${SUMMARY_DIVIDER}
|
|
|
47767
47887
|
});
|
|
47768
47888
|
}
|
|
47769
47889
|
} catch (err) {
|
|
47770
|
-
|
|
47890
|
+
log112.debug(
|
|
47771
47891
|
`Admin fan-out skipped for scheduler summary: ${err instanceof Error ? err.message : String(err)}`
|
|
47772
47892
|
);
|
|
47773
47893
|
}
|
|
@@ -47789,12 +47909,12 @@ ${SUMMARY_DIVIDER}
|
|
|
47789
47909
|
}
|
|
47790
47910
|
}
|
|
47791
47911
|
} catch (err) {
|
|
47792
|
-
|
|
47912
|
+
log112.debug(
|
|
47793
47913
|
`Channel fan-out skipped for scheduler summary: ${err instanceof Error ? err.message : String(err)}`
|
|
47794
47914
|
);
|
|
47795
47915
|
}
|
|
47796
47916
|
}
|
|
47797
|
-
|
|
47917
|
+
log112.info(`[${slot.name}] Completed ${allResults.length}/${symbols.length} predictions`);
|
|
47798
47918
|
}
|
|
47799
47919
|
async function runSinglePrediction(symbol, horizons, slot) {
|
|
47800
47920
|
try {
|
|
@@ -47810,7 +47930,7 @@ async function runSinglePrediction(symbol, horizons, slot) {
|
|
|
47810
47930
|
tracker.tagPredictionsBySlot(symbol.toUpperCase(), h.trim(), slot.name, preEmitSec);
|
|
47811
47931
|
}
|
|
47812
47932
|
} catch (tagErr) {
|
|
47813
|
-
|
|
47933
|
+
log112.debug(
|
|
47814
47934
|
`Slot-tag failed for ${slot.name}: ${tagErr instanceof Error ? tagErr.message : String(tagErr)}`
|
|
47815
47935
|
);
|
|
47816
47936
|
}
|
|
@@ -47843,11 +47963,19 @@ async function runSinglePrediction(symbol, horizons, slot) {
|
|
|
47843
47963
|
if (slot.autoAlerts) {
|
|
47844
47964
|
const isShort = (d) => d === "down";
|
|
47845
47965
|
const isLong2 = (d) => d === "up";
|
|
47966
|
+
let armed = 0;
|
|
47967
|
+
let skippedSideways = 0;
|
|
47968
|
+
let skippedAlreadyPast = 0;
|
|
47969
|
+
let skippedInvalid = 0;
|
|
47970
|
+
let skippedFailed = 0;
|
|
47846
47971
|
for (const pred of predictions) {
|
|
47847
47972
|
if (!pred.forecast) continue;
|
|
47848
47973
|
const fc = pred.forecast;
|
|
47849
47974
|
const dir = pred.direction;
|
|
47850
|
-
if (!isShort(dir) && !isLong2(dir))
|
|
47975
|
+
if (!isShort(dir) && !isLong2(dir)) {
|
|
47976
|
+
skippedSideways++;
|
|
47977
|
+
continue;
|
|
47978
|
+
}
|
|
47851
47979
|
const tpAbove = isLong2(dir);
|
|
47852
47980
|
const slAbove = isShort(dir);
|
|
47853
47981
|
const spot = pred.forecast.entry ?? 0;
|
|
@@ -47857,11 +47985,20 @@ async function runSinglePrediction(symbol, horizons, slot) {
|
|
|
47857
47985
|
{ price: fc.sl, label: `${pred.horizon} SL`, above: slAbove }
|
|
47858
47986
|
];
|
|
47859
47987
|
for (const alert of candidates) {
|
|
47860
|
-
if (!alert.price || !isFinite(alert.price) || alert.price <= 0)
|
|
47988
|
+
if (!alert.price || !isFinite(alert.price) || alert.price <= 0) {
|
|
47989
|
+
skippedInvalid++;
|
|
47990
|
+
continue;
|
|
47991
|
+
}
|
|
47861
47992
|
if (spot > 0) {
|
|
47862
47993
|
const pad2 = spot * 2e-4;
|
|
47863
|
-
if (alert.above && alert.price <= spot + pad2)
|
|
47864
|
-
|
|
47994
|
+
if (alert.above && alert.price <= spot + pad2) {
|
|
47995
|
+
skippedAlreadyPast++;
|
|
47996
|
+
continue;
|
|
47997
|
+
}
|
|
47998
|
+
if (!alert.above && alert.price >= spot - pad2) {
|
|
47999
|
+
skippedAlreadyPast++;
|
|
48000
|
+
continue;
|
|
48001
|
+
}
|
|
47865
48002
|
}
|
|
47866
48003
|
try {
|
|
47867
48004
|
await handleTool2("set_price_alert", {
|
|
@@ -47869,10 +48006,17 @@ async function runSinglePrediction(symbol, horizons, slot) {
|
|
|
47869
48006
|
[alert.above ? "above" : "below"]: alert.price,
|
|
47870
48007
|
label: alert.label
|
|
47871
48008
|
});
|
|
48009
|
+
armed++;
|
|
47872
48010
|
} catch {
|
|
48011
|
+
skippedFailed++;
|
|
47873
48012
|
}
|
|
47874
48013
|
}
|
|
47875
48014
|
}
|
|
48015
|
+
if (armed > 0 || skippedAlreadyPast > 0 || skippedFailed > 0 || skippedSideways > 0) {
|
|
48016
|
+
log112.info(
|
|
48017
|
+
`[${slot.name}] ${symbol} auto-alerts: armed=${armed}, skipped(sideways)=${skippedSideways}, skipped(already-past-spot)=${skippedAlreadyPast}, skipped(invalid)=${skippedInvalid}, skipped(failed)=${skippedFailed}`
|
|
48018
|
+
);
|
|
48019
|
+
}
|
|
47876
48020
|
}
|
|
47877
48021
|
return {
|
|
47878
48022
|
symbol,
|
|
@@ -47882,7 +48026,7 @@ async function runSinglePrediction(symbol, horizons, slot) {
|
|
|
47882
48026
|
predictions
|
|
47883
48027
|
};
|
|
47884
48028
|
} catch (err) {
|
|
47885
|
-
|
|
48029
|
+
log112.warn(
|
|
47886
48030
|
`[${slot.name}] Prediction failed for ${symbol}: ${err instanceof Error ? err.message : String(err)}`
|
|
47887
48031
|
);
|
|
47888
48032
|
return null;
|
|
@@ -47890,24 +48034,24 @@ async function runSinglePrediction(symbol, horizons, slot) {
|
|
|
47890
48034
|
}
|
|
47891
48035
|
function startPredictionScheduler(config3) {
|
|
47892
48036
|
if (!config3.enabled) {
|
|
47893
|
-
|
|
48037
|
+
log112.debug("Prediction scheduler disabled");
|
|
47894
48038
|
return () => {
|
|
47895
48039
|
};
|
|
47896
48040
|
}
|
|
47897
48041
|
if (process.env["BACKGROUND_TASKS"] === "false") {
|
|
47898
|
-
|
|
48042
|
+
log112.info("prediction-scheduler: BACKGROUND_TASKS=false \u2014 staying idle");
|
|
47899
48043
|
return () => {
|
|
47900
48044
|
};
|
|
47901
48045
|
}
|
|
47902
48046
|
if (running2) {
|
|
47903
|
-
|
|
48047
|
+
log112.warn("Prediction scheduler already running");
|
|
47904
48048
|
return () => stopPredictionScheduler();
|
|
47905
48049
|
}
|
|
47906
48050
|
running2 = true;
|
|
47907
48051
|
onShutdown("prediction-scheduler", () => stopPredictionScheduler(), "timers");
|
|
47908
48052
|
const activeSlots = config3.slots.filter((s) => s.enabled);
|
|
47909
48053
|
if (activeSlots.length === 0) {
|
|
47910
|
-
|
|
48054
|
+
log112.debug("No active schedule slots configured");
|
|
47911
48055
|
return () => {
|
|
47912
48056
|
};
|
|
47913
48057
|
}
|
|
@@ -47917,7 +48061,7 @@ function startPredictionScheduler(config3) {
|
|
|
47917
48061
|
const firingSlots = activeSlots.filter(
|
|
47918
48062
|
(s) => Array.isArray(s.firingTimesUtc) && s.firingTimesUtc.length > 0
|
|
47919
48063
|
);
|
|
47920
|
-
|
|
48064
|
+
log112.info(
|
|
47921
48065
|
`Starting prediction scheduler with ${activeSlots.length} slot(s): ` + [
|
|
47922
48066
|
...intervalSlots.map((s) => `${s.name}(${s.intervalMinutes ?? "?"}m)`),
|
|
47923
48067
|
...firingSlots.map((s) => `${s.name}(utc=${(s.firingTimesUtc ?? []).join(",")})`)
|
|
@@ -47926,14 +48070,16 @@ function startPredictionScheduler(config3) {
|
|
|
47926
48070
|
for (const slot of intervalSlots) {
|
|
47927
48071
|
const minutes = slot.intervalMinutes;
|
|
47928
48072
|
if (!minutes || minutes <= 0) {
|
|
47929
|
-
|
|
48073
|
+
log112.warn(`Slot "${slot.name}" has no intervalMinutes or firingTimesUtc \u2014 skipping`);
|
|
47930
48074
|
continue;
|
|
47931
48075
|
}
|
|
47932
48076
|
const intervalMs = minutes * 6e4;
|
|
47933
48077
|
const initialDelay = setTimeout(() => {
|
|
47934
48078
|
if (!running2) return;
|
|
48079
|
+
applySchedulerStateOverlay(config3);
|
|
48080
|
+
const liveSlot = config3.slots.find((s) => s.name === slot.name) ?? slot;
|
|
47935
48081
|
void runPredictionSlot(
|
|
47936
|
-
|
|
48082
|
+
liveSlot,
|
|
47937
48083
|
config3.defaultSymbols,
|
|
47938
48084
|
config3.resolveBeforePredict,
|
|
47939
48085
|
config3.maxConcurrent
|
|
@@ -47941,8 +48087,10 @@ function startPredictionScheduler(config3) {
|
|
|
47941
48087
|
}, 15e3);
|
|
47942
48088
|
const interval = setInterval(() => {
|
|
47943
48089
|
if (!running2) return;
|
|
48090
|
+
applySchedulerStateOverlay(config3);
|
|
48091
|
+
const liveSlot = config3.slots.find((s) => s.name === slot.name) ?? slot;
|
|
47944
48092
|
void runPredictionSlot(
|
|
47945
|
-
|
|
48093
|
+
liveSlot,
|
|
47946
48094
|
config3.defaultSymbols,
|
|
47947
48095
|
config3.resolveBeforePredict,
|
|
47948
48096
|
config3.maxConcurrent
|
|
@@ -47956,17 +48104,19 @@ function startPredictionScheduler(config3) {
|
|
|
47956
48104
|
const heartbeat = setInterval(() => {
|
|
47957
48105
|
if (!running2) return;
|
|
47958
48106
|
if (!tryAcquireBackgroundLeader()) return;
|
|
48107
|
+
applySchedulerStateOverlay(config3);
|
|
47959
48108
|
const now = /* @__PURE__ */ new Date();
|
|
47960
48109
|
const hhmm = getCurrentUtcHhmm(now);
|
|
47961
48110
|
const minuteEpoch = Math.floor(now.getTime() / 6e4);
|
|
47962
48111
|
for (const slot of firingSlots) {
|
|
47963
|
-
|
|
47964
|
-
|
|
48112
|
+
const liveSlot = config3.slots.find((s) => s.name === slot.name) ?? slot;
|
|
48113
|
+
if (!liveSlot.firingTimesUtc?.includes(hhmm)) continue;
|
|
48114
|
+
const key = `${liveSlot.name}:${minuteEpoch}`;
|
|
47965
48115
|
if (firedThisMinute.has(key)) continue;
|
|
47966
48116
|
firedThisMinute.set(key, minuteEpoch);
|
|
47967
|
-
|
|
48117
|
+
log112.info(`[${liveSlot.name}] Firing at ${hhmm} UTC (premarket window)`);
|
|
47968
48118
|
void runPredictionSlot(
|
|
47969
|
-
|
|
48119
|
+
liveSlot,
|
|
47970
48120
|
config3.defaultSymbols,
|
|
47971
48121
|
config3.resolveBeforePredict,
|
|
47972
48122
|
config3.maxConcurrent
|
|
@@ -47990,7 +48140,7 @@ function stopPredictionScheduler() {
|
|
|
47990
48140
|
clearTimeout(timer5);
|
|
47991
48141
|
}
|
|
47992
48142
|
timers.length = 0;
|
|
47993
|
-
|
|
48143
|
+
log112.info("Prediction scheduler stopped");
|
|
47994
48144
|
}
|
|
47995
48145
|
async function triggerPredictionCycle(config3, slotName) {
|
|
47996
48146
|
const slots = slotName ? config3.slots.filter((s) => s.name === slotName && s.enabled) : config3.slots.filter((s) => s.enabled);
|
|
@@ -48003,7 +48153,7 @@ async function triggerPredictionCycle(config3, slotName) {
|
|
|
48003
48153
|
);
|
|
48004
48154
|
}
|
|
48005
48155
|
}
|
|
48006
|
-
var
|
|
48156
|
+
var log112, DEFAULT_PREDICTION_SCHEDULER, timers, running2;
|
|
48007
48157
|
var init_prediction_scheduler = __esm({
|
|
48008
48158
|
"src/notifications/bridges/prediction-scheduler.ts"() {
|
|
48009
48159
|
"use strict";
|
|
@@ -48012,7 +48162,8 @@ var init_prediction_scheduler = __esm({
|
|
|
48012
48162
|
init_leader_lock();
|
|
48013
48163
|
init_engine_config();
|
|
48014
48164
|
init_graceful_shutdown();
|
|
48015
|
-
|
|
48165
|
+
init_scheduler_state();
|
|
48166
|
+
log112 = createLogger("prediction-scheduler");
|
|
48016
48167
|
DEFAULT_PREDICTION_SCHEDULER = {
|
|
48017
48168
|
enabled: false,
|
|
48018
48169
|
defaultSymbols: [],
|
|
@@ -48076,21 +48227,21 @@ var engine_exports2 = {};
|
|
|
48076
48227
|
__export(engine_exports2, {
|
|
48077
48228
|
BacktestEngine: () => BacktestEngine
|
|
48078
48229
|
});
|
|
48079
|
-
var
|
|
48230
|
+
var log113, BacktestEngine;
|
|
48080
48231
|
var init_engine3 = __esm({
|
|
48081
48232
|
"src/core/backtest/engine.ts"() {
|
|
48082
48233
|
"use strict";
|
|
48083
48234
|
init_binance();
|
|
48084
48235
|
init_manager();
|
|
48085
48236
|
init_logger();
|
|
48086
|
-
|
|
48237
|
+
log113 = createLogger("backtest");
|
|
48087
48238
|
BacktestEngine = class {
|
|
48088
48239
|
config;
|
|
48089
48240
|
constructor(config3) {
|
|
48090
48241
|
this.config = config3;
|
|
48091
48242
|
}
|
|
48092
48243
|
async run() {
|
|
48093
|
-
|
|
48244
|
+
log113.info(
|
|
48094
48245
|
`Backtest: ${this.config.strategy} on ${this.config.pair} (${this.config.from} \u2192 ${this.config.to})`
|
|
48095
48246
|
);
|
|
48096
48247
|
const strategy = getStrategy(this.config.strategy);
|
|
@@ -48471,7 +48622,7 @@ async function fetchDexScreener(path2) {
|
|
|
48471
48622
|
function resolveChain(chain) {
|
|
48472
48623
|
return CHAIN_MAP3[chain.toLowerCase()] ?? chain.toLowerCase();
|
|
48473
48624
|
}
|
|
48474
|
-
function
|
|
48625
|
+
function ensureTable7() {
|
|
48475
48626
|
if (tableInitialized6) return;
|
|
48476
48627
|
const db2 = getDb();
|
|
48477
48628
|
db2.exec(`
|
|
@@ -48495,13 +48646,13 @@ function ensureTable6() {
|
|
|
48495
48646
|
`);
|
|
48496
48647
|
tableInitialized6 = true;
|
|
48497
48648
|
}
|
|
48498
|
-
var
|
|
48649
|
+
var log114, DEXSCREENER_BASE, CHAIN_MAP3, tableInitialized6, DexPairTracker;
|
|
48499
48650
|
var init_dex_pair_tracker = __esm({
|
|
48500
48651
|
"src/data/sources/dex-pair-tracker.ts"() {
|
|
48501
48652
|
"use strict";
|
|
48502
48653
|
init_logger();
|
|
48503
48654
|
init_cache();
|
|
48504
|
-
|
|
48655
|
+
log114 = createLogger("dex-pair-tracker");
|
|
48505
48656
|
DEXSCREENER_BASE = "https://api.dexscreener.com";
|
|
48506
48657
|
CHAIN_MAP3 = {
|
|
48507
48658
|
ethereum: "ethereum",
|
|
@@ -48516,7 +48667,7 @@ var init_dex_pair_tracker = __esm({
|
|
|
48516
48667
|
tableInitialized6 = false;
|
|
48517
48668
|
DexPairTracker = class {
|
|
48518
48669
|
constructor() {
|
|
48519
|
-
|
|
48670
|
+
ensureTable7();
|
|
48520
48671
|
}
|
|
48521
48672
|
/**
|
|
48522
48673
|
* Detect new pairs on a specific chain within the given time window.
|
|
@@ -48541,10 +48692,10 @@ var init_dex_pair_tracker = __esm({
|
|
|
48541
48692
|
for (const pair of newPairs) {
|
|
48542
48693
|
this.cachePair(pair);
|
|
48543
48694
|
}
|
|
48544
|
-
|
|
48695
|
+
log114.info(`Detected ${newPairs.length} new pairs on ${resolvedChain} in last ${sinceMins}min`);
|
|
48545
48696
|
return newPairs;
|
|
48546
48697
|
} catch (err) {
|
|
48547
|
-
|
|
48698
|
+
log114.error(
|
|
48548
48699
|
`Failed to detect new pairs on ${resolvedChain}: ${err instanceof Error ? err.message : String(err)}`
|
|
48549
48700
|
);
|
|
48550
48701
|
return [];
|
|
@@ -48578,7 +48729,7 @@ var init_dex_pair_tracker = __esm({
|
|
|
48578
48729
|
timestamp: Date.now()
|
|
48579
48730
|
};
|
|
48580
48731
|
} catch (err) {
|
|
48581
|
-
|
|
48732
|
+
log114.error(
|
|
48582
48733
|
`Failed to track pair ${pairAddress}: ${err instanceof Error ? err.message : String(err)}`
|
|
48583
48734
|
);
|
|
48584
48735
|
return {
|
|
@@ -48651,7 +48802,7 @@ var init_dex_pair_tracker = __esm({
|
|
|
48651
48802
|
pair.createdAt
|
|
48652
48803
|
);
|
|
48653
48804
|
} catch (err) {
|
|
48654
|
-
|
|
48805
|
+
log114.debug(
|
|
48655
48806
|
`Failed to cache pair ${pair.pairAddress}: ${err instanceof Error ? err.message : String(err)}`
|
|
48656
48807
|
);
|
|
48657
48808
|
}
|
|
@@ -48881,7 +49032,7 @@ async function computeCorrelationMatrix(symbols, interval = "4h", limit = 100) {
|
|
|
48881
49032
|
const closes2 = result.value.map((k) => k.close);
|
|
48882
49033
|
returnsBySymbol[symbols[i]] = logReturns4(closes2);
|
|
48883
49034
|
} else {
|
|
48884
|
-
|
|
49035
|
+
log115.debug(`Kline fetch failed for ${symbols[i]}`);
|
|
48885
49036
|
}
|
|
48886
49037
|
}
|
|
48887
49038
|
const validSymbols = Object.keys(returnsBySymbol);
|
|
@@ -48909,13 +49060,13 @@ async function computeCorrelationMatrix(symbols, interval = "4h", limit = 100) {
|
|
|
48909
49060
|
strongNegative: sorted.filter((p) => p.correlation < cfg.strongNegativeThreshold).slice(0, 5)
|
|
48910
49061
|
};
|
|
48911
49062
|
}
|
|
48912
|
-
var
|
|
49063
|
+
var log115;
|
|
48913
49064
|
var init_correlation = __esm({
|
|
48914
49065
|
"src/data/sources/correlation.ts"() {
|
|
48915
49066
|
"use strict";
|
|
48916
49067
|
init_engine_config();
|
|
48917
49068
|
init_logger();
|
|
48918
|
-
|
|
49069
|
+
log115 = createLogger("correlation");
|
|
48919
49070
|
}
|
|
48920
49071
|
});
|
|
48921
49072
|
|
|
@@ -49008,7 +49159,7 @@ function persistSkippedTrackingNotification(symbol, trackingSummary) {
|
|
|
49008
49159
|
createdAt: Date.now()
|
|
49009
49160
|
});
|
|
49010
49161
|
} catch (err) {
|
|
49011
|
-
|
|
49162
|
+
log116.debug(
|
|
49012
49163
|
`persistSkippedTrackingNotification failed for ${symbol}: ${err instanceof Error ? err.message : String(err)}`
|
|
49013
49164
|
);
|
|
49014
49165
|
}
|
|
@@ -49091,7 +49242,7 @@ async function handleToolUnsafe(name, input, userId) {
|
|
|
49091
49242
|
_meta: buildMeta(metaSources)
|
|
49092
49243
|
};
|
|
49093
49244
|
} catch (err) {
|
|
49094
|
-
|
|
49245
|
+
log116.debug(
|
|
49095
49246
|
`get_market_data Binance fetch failed for ${symbol}, falling back to CoinGecko: ${err instanceof Error ? err.message : String(err)}`
|
|
49096
49247
|
);
|
|
49097
49248
|
const data = await fetchMarketData(symbol);
|
|
@@ -49609,7 +49760,7 @@ async function handleToolUnsafe(name, input, userId) {
|
|
|
49609
49760
|
};
|
|
49610
49761
|
}
|
|
49611
49762
|
} catch (err) {
|
|
49612
|
-
|
|
49763
|
+
log116.debug(
|
|
49613
49764
|
`get_prediction ChronoVisor engine failed for ${symbol}, using legacy predictor: ${err instanceof Error ? err.message : String(err)}`
|
|
49614
49765
|
);
|
|
49615
49766
|
}
|
|
@@ -49626,7 +49777,7 @@ async function handleToolUnsafe(name, input, userId) {
|
|
|
49626
49777
|
const ticker = await fetchAggregatedPrice(symbol);
|
|
49627
49778
|
initialPrice = ticker.price;
|
|
49628
49779
|
} catch (err) {
|
|
49629
|
-
|
|
49780
|
+
log116.debug(
|
|
49630
49781
|
`get_prediction legacy price fetch failed for ${symbol}: ${err instanceof Error ? err.message : String(err)}`
|
|
49631
49782
|
);
|
|
49632
49783
|
}
|
|
@@ -49656,7 +49807,7 @@ async function handleToolUnsafe(name, input, userId) {
|
|
|
49656
49807
|
});
|
|
49657
49808
|
}
|
|
49658
49809
|
} catch (err) {
|
|
49659
|
-
|
|
49810
|
+
log116.debug(
|
|
49660
49811
|
`get_prediction legacy accuracy tracking failed for ${symbol}: ${err instanceof Error ? err.message : String(err)}`
|
|
49661
49812
|
);
|
|
49662
49813
|
}
|
|
@@ -49683,7 +49834,7 @@ async function handleToolUnsafe(name, input, userId) {
|
|
|
49683
49834
|
mlClient2 = initMLClient(cfg.ml.engineUrl);
|
|
49684
49835
|
}
|
|
49685
49836
|
} catch (err) {
|
|
49686
|
-
|
|
49837
|
+
log116.debug(
|
|
49687
49838
|
`get_ml_prediction config load failed: ${err instanceof Error ? err.message : String(err)}`
|
|
49688
49839
|
);
|
|
49689
49840
|
}
|
|
@@ -49758,7 +49909,7 @@ async function handleToolUnsafe(name, input, userId) {
|
|
|
49758
49909
|
try {
|
|
49759
49910
|
goplus = await checkTokenSecurity(address, chain);
|
|
49760
49911
|
} catch (err) {
|
|
49761
|
-
|
|
49912
|
+
log116.debug(
|
|
49762
49913
|
`get_rug_ml_analysis GoPlus security check failed: ${err instanceof Error ? err.message : String(err)}`
|
|
49763
49914
|
);
|
|
49764
49915
|
}
|
|
@@ -49770,7 +49921,7 @@ async function handleToolUnsafe(name, input, userId) {
|
|
|
49770
49921
|
mlClient2 = initMLClient(cfg.ml.engineUrl);
|
|
49771
49922
|
}
|
|
49772
49923
|
} catch (err) {
|
|
49773
|
-
|
|
49924
|
+
log116.debug(
|
|
49774
49925
|
`get_rug_ml_analysis ML config load failed: ${err instanceof Error ? err.message : String(err)}`
|
|
49775
49926
|
);
|
|
49776
49927
|
}
|
|
@@ -49844,7 +49995,7 @@ async function handleToolUnsafe(name, input, userId) {
|
|
|
49844
49995
|
mlClient2 = initMLClient(cfg.ml.engineUrl);
|
|
49845
49996
|
}
|
|
49846
49997
|
} catch (err) {
|
|
49847
|
-
|
|
49998
|
+
log116.debug(
|
|
49848
49999
|
`analyze_news_sentiment ML config load failed: ${err instanceof Error ? err.message : String(err)}`
|
|
49849
50000
|
);
|
|
49850
50001
|
}
|
|
@@ -50017,7 +50168,7 @@ async function handleToolUnsafe(name, input, userId) {
|
|
|
50017
50168
|
mlClient2 = initMLClient(cfg.ml.engineUrl);
|
|
50018
50169
|
}
|
|
50019
50170
|
} catch (err) {
|
|
50020
|
-
|
|
50171
|
+
log116.debug(
|
|
50021
50172
|
`get_portfolio_forecast ML config load failed: ${err instanceof Error ? err.message : String(err)}`
|
|
50022
50173
|
);
|
|
50023
50174
|
}
|
|
@@ -50165,7 +50316,7 @@ async function handleToolUnsafe(name, input, userId) {
|
|
|
50165
50316
|
try {
|
|
50166
50317
|
balance = await getWalletBalance(agent.walletAddress);
|
|
50167
50318
|
} catch (err) {
|
|
50168
|
-
|
|
50319
|
+
log116.debug(
|
|
50169
50320
|
`get_agent_wallet balance fetch failed for ${agent.name}: ${err instanceof Error ? err.message : String(err)}`
|
|
50170
50321
|
);
|
|
50171
50322
|
balance = "0";
|
|
@@ -50317,7 +50468,7 @@ async function handleToolUnsafe(name, input, userId) {
|
|
|
50317
50468
|
mlClient2 = initMLClient(cfg.ml.engineUrl);
|
|
50318
50469
|
}
|
|
50319
50470
|
} catch (err) {
|
|
50320
|
-
|
|
50471
|
+
log116.debug(
|
|
50321
50472
|
`get_ml_model_health ML config load failed: ${err instanceof Error ? err.message : String(err)}`
|
|
50322
50473
|
);
|
|
50323
50474
|
}
|
|
@@ -50351,7 +50502,7 @@ async function handleToolUnsafe(name, input, userId) {
|
|
|
50351
50502
|
mlClient2 = initMLClient(cfg.ml.engineUrl);
|
|
50352
50503
|
}
|
|
50353
50504
|
} catch (err) {
|
|
50354
|
-
|
|
50505
|
+
log116.debug(
|
|
50355
50506
|
`classify_user_intent ML config load failed: ${err instanceof Error ? err.message : String(err)}`
|
|
50356
50507
|
);
|
|
50357
50508
|
}
|
|
@@ -50894,7 +51045,7 @@ async function handleToolUnsafe(name, input, userId) {
|
|
|
50894
51045
|
const ticker = await fetchAggregatedPrice2(symbol);
|
|
50895
51046
|
priceAtCreation = ticker.price;
|
|
50896
51047
|
} catch (err) {
|
|
50897
|
-
|
|
51048
|
+
log116.debug(
|
|
50898
51049
|
`set_price_alert price fetch failed for ${symbol}: ${err instanceof Error ? err.message : String(err)}`
|
|
50899
51050
|
);
|
|
50900
51051
|
}
|
|
@@ -50954,7 +51105,7 @@ async function handleToolUnsafe(name, input, userId) {
|
|
|
50954
51105
|
const engine = getChronoVisor2();
|
|
50955
51106
|
engineResult = await engine.predict(symbol, ["4h"], { userId });
|
|
50956
51107
|
} catch (err) {
|
|
50957
|
-
|
|
51108
|
+
log116.debug(
|
|
50958
51109
|
`set_price_alert ChronoVisor engine unavailable for ${symbol}: ${err instanceof Error ? err.message : String(err)}`
|
|
50959
51110
|
);
|
|
50960
51111
|
}
|
|
@@ -51064,7 +51215,7 @@ async function handleToolUnsafe(name, input, userId) {
|
|
|
51064
51215
|
});
|
|
51065
51216
|
}
|
|
51066
51217
|
} catch (err) {
|
|
51067
|
-
|
|
51218
|
+
log116.debug(
|
|
51068
51219
|
`set_price_alert prediction mirroring failed for ${symbol}: ${err instanceof Error ? err.message : String(err)}`
|
|
51069
51220
|
);
|
|
51070
51221
|
}
|
|
@@ -51639,7 +51790,7 @@ async function handleToolUnsafe(name, input, userId) {
|
|
|
51639
51790
|
const signalKeys = Object.keys(breakdown);
|
|
51640
51791
|
sigCount = signalKeys.filter((k) => breakdown[k].score !== 0).length;
|
|
51641
51792
|
} catch (err) {
|
|
51642
|
-
|
|
51793
|
+
log116.debug(
|
|
51643
51794
|
`get_position_sizing ChronoVisor meta-score fetch failed for ${symbol}: ${err instanceof Error ? err.message : String(err)}`
|
|
51644
51795
|
);
|
|
51645
51796
|
}
|
|
@@ -51965,7 +52116,7 @@ async function handleToolUnsafe(name, input, userId) {
|
|
|
51965
52116
|
return { error: `Unknown tool: ${name}` };
|
|
51966
52117
|
}
|
|
51967
52118
|
}
|
|
51968
|
-
var
|
|
52119
|
+
var log116;
|
|
51969
52120
|
var init_tool_handler = __esm({
|
|
51970
52121
|
"src/ai/tool-handler.ts"() {
|
|
51971
52122
|
"use strict";
|
|
@@ -51998,7 +52149,7 @@ var init_tool_handler = __esm({
|
|
|
51998
52149
|
init_store();
|
|
51999
52150
|
init_sanitize();
|
|
52000
52151
|
init_logger();
|
|
52001
|
-
|
|
52152
|
+
log116 = createLogger("tool-handler");
|
|
52002
52153
|
}
|
|
52003
52154
|
});
|
|
52004
52155
|
|
|
@@ -54707,7 +54858,7 @@ function instrumentAck(ctx) {
|
|
|
54707
54858
|
try {
|
|
54708
54859
|
return await original(...args2);
|
|
54709
54860
|
} catch (err) {
|
|
54710
|
-
|
|
54861
|
+
log117.debug(`answerCallbackQuery failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
54711
54862
|
return true;
|
|
54712
54863
|
}
|
|
54713
54864
|
});
|
|
@@ -54734,7 +54885,7 @@ function mountCallbackRouter(bot) {
|
|
|
54734
54885
|
const key = `${userId}:${data}`;
|
|
54735
54886
|
const existing = dedup.get(key);
|
|
54736
54887
|
if (existing && (existing.inFlight || existing.until > now)) {
|
|
54737
|
-
|
|
54888
|
+
log117.debug(`Dedup'd callback "${data}" for user ${userId}`);
|
|
54738
54889
|
await ctx.answerCallbackQuery();
|
|
54739
54890
|
return;
|
|
54740
54891
|
}
|
|
@@ -54759,7 +54910,7 @@ function mountCallbackRouter(bot) {
|
|
|
54759
54910
|
}
|
|
54760
54911
|
} catch (err) {
|
|
54761
54912
|
const msg = err instanceof Error ? err.message : String(err);
|
|
54762
|
-
|
|
54913
|
+
log117.warn(`Callback "${prefix}" failed: ${msg}`);
|
|
54763
54914
|
if (userId) {
|
|
54764
54915
|
recordDebugLine(userId, `callback:${prefix} ERROR ${msg}`);
|
|
54765
54916
|
}
|
|
@@ -54774,13 +54925,13 @@ function mountCallbackRouter(bot) {
|
|
|
54774
54925
|
}
|
|
54775
54926
|
});
|
|
54776
54927
|
}
|
|
54777
|
-
var
|
|
54928
|
+
var log117, handlers, DEDUP_WINDOW_MS, EARLY_ACK_MS, dedup, mounted;
|
|
54778
54929
|
var init_callbacks = __esm({
|
|
54779
54930
|
"src/telegram/callbacks.ts"() {
|
|
54780
54931
|
"use strict";
|
|
54781
54932
|
init_logger();
|
|
54782
54933
|
init_debug_log();
|
|
54783
|
-
|
|
54934
|
+
log117 = createLogger("telegram:callbacks");
|
|
54784
54935
|
handlers = /* @__PURE__ */ new Map();
|
|
54785
54936
|
DEDUP_WINDOW_MS = 1500;
|
|
54786
54937
|
EARLY_ACK_MS = 600;
|
|
@@ -55032,11 +55183,13 @@ async function deliverPredictions(ctx, symbolArg, filter, editPrevious) {
|
|
|
55032
55183
|
await ctx.reply("Login required \u2014 send /start first.");
|
|
55033
55184
|
return;
|
|
55034
55185
|
}
|
|
55186
|
+
const isAdmin3 = ctx.state?.user?.role === "admin";
|
|
55035
55187
|
const { getUserWatchlist: getUserWatchlist2 } = await Promise.resolve().then(() => (init_users(), users_exports));
|
|
55036
|
-
const subscribedSymbols = getUserWatchlist2(userId).map((w) => w.symbol);
|
|
55188
|
+
const subscribedSymbols = isAdmin3 ? [] : getUserWatchlist2(userId).map((w) => w.symbol);
|
|
55037
55189
|
const tracker = new AccuracyTracker();
|
|
55038
|
-
const
|
|
55039
|
-
const
|
|
55190
|
+
const queryUserId = isAdmin3 ? void 0 : userId;
|
|
55191
|
+
const pending = tracker.getPendingPredictions(queryUserId, subscribedSymbols);
|
|
55192
|
+
const recentResolved = tracker.getAllRecentPredictions(100, queryUserId, subscribedSymbols).filter((p) => p.wasCorrect !== null);
|
|
55040
55193
|
let rows;
|
|
55041
55194
|
if (filter === "pending") rows = pending;
|
|
55042
55195
|
else if (filter === "resolved") rows = recentResolved;
|
|
@@ -55240,22 +55393,24 @@ async function renderPrecisions(ctx, symbol, horizon, editPrevious) {
|
|
|
55240
55393
|
await ctx.reply("Login required \u2014 send /start first.");
|
|
55241
55394
|
return;
|
|
55242
55395
|
}
|
|
55396
|
+
const isAdmin3 = ctx.state?.user?.role === "admin";
|
|
55243
55397
|
const { getUserWatchlist: getUserWatchlist2 } = await Promise.resolve().then(() => (init_users(), users_exports));
|
|
55244
|
-
const subscribedSymbols = getUserWatchlist2(userId).map((w) => w.symbol);
|
|
55398
|
+
const subscribedSymbols = isAdmin3 ? [] : getUserWatchlist2(userId).map((w) => w.symbol);
|
|
55399
|
+
const queryUserId = isAdmin3 ? void 0 : userId;
|
|
55245
55400
|
const tracker = new AccuracyTracker();
|
|
55246
55401
|
const trackedMetrics = tracker.getAccuracyMetrics(
|
|
55247
55402
|
symbol,
|
|
55248
55403
|
horizon,
|
|
55249
55404
|
void 0,
|
|
55250
55405
|
void 0,
|
|
55251
|
-
|
|
55406
|
+
queryUserId,
|
|
55252
55407
|
subscribedSymbols
|
|
55253
55408
|
);
|
|
55254
55409
|
const displayMetrics = tracker.getDisplayAccuracyMetrics(
|
|
55255
55410
|
symbol,
|
|
55256
55411
|
horizon,
|
|
55257
55412
|
void 0,
|
|
55258
|
-
|
|
55413
|
+
queryUserId,
|
|
55259
55414
|
subscribedSymbols
|
|
55260
55415
|
);
|
|
55261
55416
|
const status = getPredictionControlStatus();
|
|
@@ -55328,7 +55483,7 @@ async function renderPrecisions(ctx, symbol, horizon, editPrevious) {
|
|
|
55328
55483
|
)
|
|
55329
55484
|
);
|
|
55330
55485
|
}
|
|
55331
|
-
const slotAccuracy = tracker.getAccuracyBySlot(
|
|
55486
|
+
const slotAccuracy = tracker.getAccuracyBySlot(queryUserId, subscribedSymbols);
|
|
55332
55487
|
const slotRows = [];
|
|
55333
55488
|
if (slotAccuracy.length > 0) {
|
|
55334
55489
|
slotRows.push(section("\u{1F4C5}", "Per Scheduler"));
|
|
@@ -55447,7 +55602,7 @@ function trainLogisticRegression(rows, opts = {}) {
|
|
|
55447
55602
|
const l2 = opts.l2 ?? 0.01;
|
|
55448
55603
|
const holdoutFrac = opts.holdoutFrac ?? 0.2;
|
|
55449
55604
|
if (rows.length < 30) {
|
|
55450
|
-
|
|
55605
|
+
log118.info(`trainLogisticRegression: only ${rows.length} rows, need \u226530 \u2014 skipping fit`);
|
|
55451
55606
|
return null;
|
|
55452
55607
|
}
|
|
55453
55608
|
const allFeatures = rows.map(extractFeatures2);
|
|
@@ -55505,7 +55660,7 @@ function trainLogisticRegression(rows, opts = {}) {
|
|
|
55505
55660
|
if ((p >= 0.5 ? 1 : 0) === valY[i]) correct++;
|
|
55506
55661
|
}
|
|
55507
55662
|
const holdoutAccuracy = valX.length > 0 ? correct / valX.length : null;
|
|
55508
|
-
|
|
55663
|
+
log118.info(
|
|
55509
55664
|
`Trained logistic regression: n=${rows.length} (${trainX.length} train, ${valX.length} val) holdoutAcc=${holdoutAccuracy !== null ? (holdoutAccuracy * 100).toFixed(1) + "%" : "n/a"} bias=${bias.toFixed(3)}`
|
|
55510
55665
|
);
|
|
55511
55666
|
return {
|
|
@@ -55539,9 +55694,9 @@ async function persistModel(state) {
|
|
|
55539
55694
|
try {
|
|
55540
55695
|
await fs.mkdir(path.dirname(target), { recursive: true });
|
|
55541
55696
|
await fs.writeFile(target, JSON.stringify(state, null, 2));
|
|
55542
|
-
|
|
55697
|
+
log118.info(`Persisted trained model to ${target}`);
|
|
55543
55698
|
} catch (err) {
|
|
55544
|
-
|
|
55699
|
+
log118.warn(`Failed to persist model: ${err instanceof Error ? err.message : String(err)}`);
|
|
55545
55700
|
}
|
|
55546
55701
|
}
|
|
55547
55702
|
async function loadPersistedModel() {
|
|
@@ -55550,7 +55705,7 @@ async function loadPersistedModel() {
|
|
|
55550
55705
|
const raw = await fs.readFile(target, "utf-8");
|
|
55551
55706
|
const parsed = JSON.parse(raw);
|
|
55552
55707
|
if (parsed.version !== 1) {
|
|
55553
|
-
|
|
55708
|
+
log118.info(`Persisted model version ${parsed.version} != 1, ignoring`);
|
|
55554
55709
|
return null;
|
|
55555
55710
|
}
|
|
55556
55711
|
return parsed;
|
|
@@ -55564,12 +55719,12 @@ function getCachedModel() {
|
|
|
55564
55719
|
function setCachedModel(state) {
|
|
55565
55720
|
cachedModel = state;
|
|
55566
55721
|
}
|
|
55567
|
-
var
|
|
55722
|
+
var log118, SIGNAL_NAMES, cachedModel;
|
|
55568
55723
|
var init_trainer = __esm({
|
|
55569
55724
|
"src/ml/native/trainer.ts"() {
|
|
55570
55725
|
"use strict";
|
|
55571
55726
|
init_logger();
|
|
55572
|
-
|
|
55727
|
+
log118 = createLogger("ml:native:trainer");
|
|
55573
55728
|
SIGNAL_NAMES = [
|
|
55574
55729
|
"onChain",
|
|
55575
55730
|
"mlEnsemble",
|
|
@@ -56266,124 +56421,6 @@ var init_chronovisor = __esm({
|
|
|
56266
56421
|
}
|
|
56267
56422
|
});
|
|
56268
56423
|
|
|
56269
|
-
// src/notifications/scheduler-state.ts
|
|
56270
|
-
var scheduler_state_exports = {};
|
|
56271
|
-
__export(scheduler_state_exports, {
|
|
56272
|
-
applySchedulerStateOverlay: () => applySchedulerStateOverlay,
|
|
56273
|
-
isSchedulerRunningPersisted: () => isSchedulerRunningPersisted,
|
|
56274
|
-
persistDefaultSymbols: () => persistDefaultSymbols,
|
|
56275
|
-
persistSchedulerRunning: () => persistSchedulerRunning,
|
|
56276
|
-
persistSlotEnabled: () => persistSlotEnabled,
|
|
56277
|
-
persistSlotFiringTimesUtc: () => persistSlotFiringTimesUtc,
|
|
56278
|
-
persistSlotHorizons: () => persistSlotHorizons,
|
|
56279
|
-
persistSlotInterval: () => persistSlotInterval,
|
|
56280
|
-
persistSlotSymbols: () => persistSlotSymbols
|
|
56281
|
-
});
|
|
56282
|
-
function ensureTable7() {
|
|
56283
|
-
getDb().exec(`
|
|
56284
|
-
CREATE TABLE IF NOT EXISTS scheduler_state (
|
|
56285
|
-
key TEXT PRIMARY KEY,
|
|
56286
|
-
value TEXT NOT NULL,
|
|
56287
|
-
updated_at INTEGER NOT NULL
|
|
56288
|
-
)
|
|
56289
|
-
`);
|
|
56290
|
-
}
|
|
56291
|
-
function setKey(key, value) {
|
|
56292
|
-
ensureTable7();
|
|
56293
|
-
getDb().prepare(
|
|
56294
|
-
`INSERT INTO scheduler_state (key, value, updated_at) VALUES (?, ?, ?)
|
|
56295
|
-
ON CONFLICT(key) DO UPDATE SET value = excluded.value, updated_at = excluded.updated_at`
|
|
56296
|
-
).run(key, JSON.stringify(value), Date.now());
|
|
56297
|
-
}
|
|
56298
|
-
function getKey(key) {
|
|
56299
|
-
ensureTable7();
|
|
56300
|
-
const row2 = getDb().prepare(`SELECT value FROM scheduler_state WHERE key = ?`).get(key);
|
|
56301
|
-
if (!row2) return null;
|
|
56302
|
-
try {
|
|
56303
|
-
return JSON.parse(row2.value);
|
|
56304
|
-
} catch {
|
|
56305
|
-
return null;
|
|
56306
|
-
}
|
|
56307
|
-
}
|
|
56308
|
-
function persistDefaultSymbols(symbols) {
|
|
56309
|
-
setKey("defaultSymbols", symbols);
|
|
56310
|
-
}
|
|
56311
|
-
function persistSchedulerRunning(running6) {
|
|
56312
|
-
setKey("running", running6);
|
|
56313
|
-
}
|
|
56314
|
-
function isSchedulerRunningPersisted() {
|
|
56315
|
-
return getKey("running");
|
|
56316
|
-
}
|
|
56317
|
-
function persistSlotEnabled(slotName, enabled) {
|
|
56318
|
-
const current = getKey("slotsEnabled") ?? {};
|
|
56319
|
-
current[slotName] = enabled;
|
|
56320
|
-
setKey("slotsEnabled", current);
|
|
56321
|
-
}
|
|
56322
|
-
function persistSlotSymbols(slotName, symbols) {
|
|
56323
|
-
const current = getKey("slotSymbols") ?? {};
|
|
56324
|
-
current[slotName] = symbols;
|
|
56325
|
-
setKey("slotSymbols", current);
|
|
56326
|
-
}
|
|
56327
|
-
function persistSlotHorizons(slotName, horizons) {
|
|
56328
|
-
const current = getKey("slotHorizons") ?? {};
|
|
56329
|
-
current[slotName] = horizons;
|
|
56330
|
-
setKey("slotHorizons", current);
|
|
56331
|
-
}
|
|
56332
|
-
function persistSlotInterval(slotName, intervalMinutes) {
|
|
56333
|
-
const current = getKey("slotIntervals") ?? {};
|
|
56334
|
-
current[slotName] = intervalMinutes;
|
|
56335
|
-
setKey("slotIntervals", current);
|
|
56336
|
-
}
|
|
56337
|
-
function persistSlotFiringTimesUtc(slotName, firingTimesUtc) {
|
|
56338
|
-
const current = getKey("slotFiringTimesUtc") ?? {};
|
|
56339
|
-
current[slotName] = firingTimesUtc === void 0 ? null : firingTimesUtc;
|
|
56340
|
-
setKey("slotFiringTimesUtc", current);
|
|
56341
|
-
}
|
|
56342
|
-
function applySchedulerStateOverlay(cfg) {
|
|
56343
|
-
try {
|
|
56344
|
-
const defaultSymbols = getKey("defaultSymbols");
|
|
56345
|
-
if (Array.isArray(defaultSymbols)) {
|
|
56346
|
-
cfg.defaultSymbols = defaultSymbols;
|
|
56347
|
-
}
|
|
56348
|
-
const slotsEnabled = getKey("slotsEnabled") ?? {};
|
|
56349
|
-
const slotSymbols = getKey("slotSymbols") ?? {};
|
|
56350
|
-
const slotHorizons = getKey("slotHorizons") ?? {};
|
|
56351
|
-
const slotIntervals = getKey("slotIntervals") ?? {};
|
|
56352
|
-
const slotFiringTimesUtc = getKey("slotFiringTimesUtc") ?? {};
|
|
56353
|
-
cfg.slots = cfg.slots.map((slot) => {
|
|
56354
|
-
const next = { ...slot };
|
|
56355
|
-
if (slotsEnabled[slot.name] !== void 0) next.enabled = slotsEnabled[slot.name];
|
|
56356
|
-
if (slotSymbols[slot.name] !== void 0) next.symbols = slotSymbols[slot.name];
|
|
56357
|
-
if (slotHorizons[slot.name] !== void 0) next.horizons = slotHorizons[slot.name];
|
|
56358
|
-
if (slotIntervals[slot.name] !== void 0) next.intervalMinutes = slotIntervals[slot.name];
|
|
56359
|
-
if (slotFiringTimesUtc[slot.name] !== void 0) {
|
|
56360
|
-
const v = slotFiringTimesUtc[slot.name];
|
|
56361
|
-
if (v === null) {
|
|
56362
|
-
delete next.firingTimesUtc;
|
|
56363
|
-
} else {
|
|
56364
|
-
next.firingTimesUtc = v;
|
|
56365
|
-
}
|
|
56366
|
-
}
|
|
56367
|
-
return next;
|
|
56368
|
-
});
|
|
56369
|
-
return cfg;
|
|
56370
|
-
} catch (err) {
|
|
56371
|
-
log118.debug(
|
|
56372
|
-
`applySchedulerStateOverlay failed: ${err instanceof Error ? err.message : String(err)}`
|
|
56373
|
-
);
|
|
56374
|
-
return cfg;
|
|
56375
|
-
}
|
|
56376
|
-
}
|
|
56377
|
-
var log118;
|
|
56378
|
-
var init_scheduler_state = __esm({
|
|
56379
|
-
"src/notifications/scheduler-state.ts"() {
|
|
56380
|
-
"use strict";
|
|
56381
|
-
init_cache();
|
|
56382
|
-
init_logger();
|
|
56383
|
-
log118 = createLogger("notifications:scheduler-state");
|
|
56384
|
-
}
|
|
56385
|
-
});
|
|
56386
|
-
|
|
56387
56424
|
// src/telegram/commands/scheduler.ts
|
|
56388
56425
|
var scheduler_exports = {};
|
|
56389
56426
|
__export(scheduler_exports, {
|
|
@@ -56462,6 +56499,9 @@ async function handleScheduler(ctx) {
|
|
|
56462
56499
|
await doToggleSlot(ctx, schedCfg, args2[1], sub === "enable");
|
|
56463
56500
|
return;
|
|
56464
56501
|
case "symbols":
|
|
56502
|
+
case "defaults":
|
|
56503
|
+
case "default-symbols":
|
|
56504
|
+
case "defaultsymbols":
|
|
56465
56505
|
await doSetSymbols(ctx, schedCfg, args2.slice(1).join(" "));
|
|
56466
56506
|
return;
|
|
56467
56507
|
case "interval":
|
|
@@ -56501,7 +56541,9 @@ async function handleScheduler(ctx) {
|
|
|
56501
56541
|
}
|
|
56502
56542
|
async function renderStatus3(ctx, schedCfg) {
|
|
56503
56543
|
if (!schedCfg) return;
|
|
56504
|
-
const
|
|
56544
|
+
const persisted = isSchedulerRunningPersisted();
|
|
56545
|
+
const running6 = persisted ?? isPredictionSchedulerRunning();
|
|
56546
|
+
applySchedulerStateOverlay(schedCfg);
|
|
56505
56547
|
const slots = schedCfg.slots ?? [];
|
|
56506
56548
|
const defaultCount = schedCfg.defaultSymbols.length;
|
|
56507
56549
|
const slotLines = slots.map((s) => {
|
|
@@ -56564,7 +56606,7 @@ function helpText() {
|
|
|
56564
56606
|
"*Edit \\(admin\\)*",
|
|
56565
56607
|
"`/scheduler enable <slot>`",
|
|
56566
56608
|
"`/scheduler disable <slot>`",
|
|
56567
|
-
"`/scheduler symbols BTC,ETH,SOL`",
|
|
56609
|
+
"`/scheduler symbols BTC,ETH,SOL` \u2014 replace default symbols \\(alias: `defaults`\\)",
|
|
56568
56610
|
"`/scheduler interval <slot> <minutes>`",
|
|
56569
56611
|
"`/scheduler firing <slot> 08:30,09:00` \u2014 fixed UTC firing times",
|
|
56570
56612
|
"`/scheduler firing <slot> clear` \u2014 back to interval cadence",
|
|
@@ -57807,15 +57849,17 @@ async function renderWr(ctx, symbol) {
|
|
|
57807
57849
|
await ctx.reply("Login required \u2014 send /start first.");
|
|
57808
57850
|
return;
|
|
57809
57851
|
}
|
|
57852
|
+
const isAdmin3 = ctx.state?.user?.role === "admin";
|
|
57810
57853
|
const { getUserWatchlist: getUserWatchlist2 } = await Promise.resolve().then(() => (init_users(), users_exports));
|
|
57811
|
-
const subscribedSymbols = getUserWatchlist2(userId).map((w) => w.symbol);
|
|
57854
|
+
const subscribedSymbols = isAdmin3 ? [] : getUserWatchlist2(userId).map((w) => w.symbol);
|
|
57855
|
+
const queryUserId = isAdmin3 ? void 0 : userId;
|
|
57812
57856
|
const tracker = new AccuracyTracker();
|
|
57813
57857
|
const tracked = tracker.getAccuracyMetrics(
|
|
57814
57858
|
symbol,
|
|
57815
57859
|
void 0,
|
|
57816
57860
|
void 0,
|
|
57817
57861
|
{ excludeWarmup: true },
|
|
57818
|
-
|
|
57862
|
+
queryUserId,
|
|
57819
57863
|
subscribedSymbols
|
|
57820
57864
|
);
|
|
57821
57865
|
const trackedIncl = tracker.getAccuracyMetrics(
|
|
@@ -57823,14 +57867,14 @@ async function renderWr(ctx, symbol) {
|
|
|
57823
57867
|
void 0,
|
|
57824
57868
|
void 0,
|
|
57825
57869
|
void 0,
|
|
57826
|
-
|
|
57870
|
+
queryUserId,
|
|
57827
57871
|
subscribedSymbols
|
|
57828
57872
|
);
|
|
57829
57873
|
const display = tracker.getDisplayAccuracyMetrics(
|
|
57830
57874
|
symbol,
|
|
57831
57875
|
void 0,
|
|
57832
57876
|
void 0,
|
|
57833
|
-
|
|
57877
|
+
queryUserId,
|
|
57834
57878
|
subscribedSymbols
|
|
57835
57879
|
);
|
|
57836
57880
|
const warmup = tracker.getWarmupStats(symbol);
|