computer: fixes

This commit is contained in:
nym21
2026-03-23 00:39:15 +01:00
parent 514b0513de
commit fef7a24951
4 changed files with 189 additions and 36 deletions
Generated
+40 -34
View File
@@ -307,7 +307,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aedd23ae0fd321affb4bbbc36126c6f49a32818dc6b979395d24da8c9d4e80ee"
dependencies = [
"bitcoincore-rpc-json",
"jsonrpc 0.18.0",
"jsonrpc",
"log",
"serde",
"serde_json",
@@ -361,6 +361,42 @@ dependencies = [
"brk_types",
]
[[package]]
name = "brk-corepc-client"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c15bc86010adb0c3118d88a531a7d2633b726fe97a6c2888ce200946d198e7b"
dependencies = [
"bitcoin",
"brk-corepc-jsonrpc",
"brk-corepc-types",
"log",
"serde",
"serde_json",
]
[[package]]
name = "brk-corepc-jsonrpc"
version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cbb72c73b4c3aafd6ab3d0a0ad07b2961543929452d7c5d8f11b88e7a1ca7725"
dependencies = [
"base64 0.22.1",
"serde",
"serde_json",
]
[[package]]
name = "brk-corepc-types"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca4662e4e22838c09a6f80d1677f6177295eddbb524515be9156a8f8412c4147"
dependencies = [
"bitcoin",
"serde",
"serde_json",
]
[[package]]
name = "brk_alloc"
version = "0.1.9"
@@ -484,7 +520,7 @@ version = "0.1.9"
dependencies = [
"bitcoin",
"bitcoincore-rpc",
"corepc-client",
"brk-corepc-client",
"fjall",
"jiff",
"pco",
@@ -623,11 +659,11 @@ version = "0.1.9"
dependencies = [
"bitcoin",
"bitcoincore-rpc",
"brk-corepc-client",
"brk-corepc-jsonrpc",
"brk_error",
"brk_logger",
"brk_types",
"corepc-client",
"jsonrpc 0.19.0",
"parking_lot",
"serde",
"serde_json",
@@ -997,27 +1033,6 @@ dependencies = [
"libc",
]
[[package]]
name = "corepc-client"
version = "0.11.0"
dependencies = [
"bitcoin",
"corepc-types",
"jsonrpc 0.19.0",
"log",
"serde",
"serde_json",
]
[[package]]
name = "corepc-types"
version = "0.11.0"
dependencies = [
"bitcoin",
"serde",
"serde_json",
]
[[package]]
name = "crc32fast"
version = "1.5.0"
@@ -1971,15 +1986,6 @@ dependencies = [
"serde_json",
]
[[package]]
name = "jsonrpc"
version = "0.19.0"
dependencies = [
"base64 0.22.1",
"serde",
"serde_json",
]
[[package]]
name = "lazy_static"
version = "1.5.0"
+2 -2
View File
@@ -65,8 +65,8 @@ brk_types = { version = "0.1.9", path = "crates/brk_types" }
brk_website = { version = "0.1.9", path = "crates/brk_website" }
byteview = "0.10.1"
color-eyre = "0.6.5"
corepc-client = { path = "/Users/k/Developer/corepc/client", features = ["client-sync"] }
corepc-jsonrpc = { package = "jsonrpc", path = "/Users/k/Developer/corepc/jsonrpc", features = ["simple_http"], default-features = false }
corepc-client = { package = "brk-corepc-client", version = "0.11.0", features = ["client-sync"] }
corepc-jsonrpc = { package = "brk-corepc-jsonrpc", version = "0.19.0", features = ["simple_http"], default-features = false }
derive_more = { version = "2.1.1", features = ["deref", "deref_mut"] }
fjall = "3.1.2"
indexmap = { version = "2.13.0", features = ["serde"] }
@@ -60,6 +60,11 @@ impl Vecs {
)?;
}
// DCA by period - stack cents (sats × price)
for stack in self.period.stack.iter_mut() {
stack.compute(prices, starting_indexes.height, exit)?;
}
// DCA by period - average price (derived from stack)
let starting_height = starting_indexes.height.to_usize();
for (average_price, stack, days) in
@@ -146,6 +151,11 @@ impl Vecs {
)?;
}
// Lump sum by period - stack cents (sats × price)
for stack in self.period.lump_sum_stack.iter_mut() {
stack.compute(prices, starting_indexes.height, exit)?;
}
// Lump sum by period - returns (compute from lookback price)
for (returns, (lookback_price, _)) in self
.period
@@ -213,6 +223,11 @@ impl Vecs {
)?;
}
// DCA by year class - stack cents (sats × price)
for stack in self.class.stack.iter_mut() {
stack.compute(prices, starting_indexes.height, exit)?;
}
// DCA by year class - average price (derived from stack)
let start_days = super::ByDcaClass::<()>::start_days();
for ((average_price, stack), from) in self
+132
View File
@@ -0,0 +1,132 @@
/**
* Consistency test: verifies that all series sharing the same index have the same length.
* Useful for catching stale/inconsistent state after a reorg rollback.
*/
import { BrkClient } from "../index.js";
/**
* @typedef {import('../index.js').AnySeriesPattern} AnyMetricPattern
*/
/**
* @param {any} obj
* @returns {obj is AnyMetricPattern}
*/
function isMetricPattern(obj) {
return (
obj &&
typeof obj === "object" &&
typeof obj.indexes === "function" &&
obj.by &&
typeof obj.by === "object"
);
}
/**
* Recursively collect all metric patterns from the tree.
* @param {Record<string, any>} obj
* @param {string} path
* @returns {Array<{path: string, metric: AnyMetricPattern}>}
*/
function getAllMetrics(obj, path = "") {
/** @type {Array<{path: string, metric: AnyMetricPattern}>} */
const metrics = [];
for (const key of Object.keys(obj)) {
const attr = obj[key];
if (!attr || typeof attr !== "object") continue;
const currentPath = path ? `${path}.${key}` : key;
if (isMetricPattern(attr)) {
metrics.push({ path: currentPath, metric: attr });
}
if (typeof attr === "object" && !Array.isArray(attr)) {
metrics.push(...getAllMetrics(attr, currentPath));
}
}
return metrics;
}
async function testConsistency() {
const client = new BrkClient({
baseUrl: "http://localhost:3110",
timeout: 15000,
});
const metrics = getAllMetrics(client.series);
console.log(`\nFound ${metrics.length} metrics`);
/** @type {Map<string, Array<{path: string, total: number}>>} */
const byIndex = new Map();
for (const { path, metric } of metrics) {
const indexes = metric.indexes();
for (const idxName of indexes) {
const fullPath = `${path}.by.${idxName}`;
const endpoint = metric.by[idxName];
if (!endpoint) {
console.log(`SKIP: ${fullPath} (undefined endpoint)`);
continue;
}
try {
const result = await endpoint.last(0);
const total = result.total;
if (!byIndex.has(idxName)) {
byIndex.set(idxName, []);
}
byIndex.get(idxName).push({ path: fullPath, total });
} catch (e) {
console.log(
`FAIL: ${fullPath} -> ${e instanceof Error ? e.message : e}`,
);
return;
}
}
}
let failed = false;
for (const [index, entries] of byIndex) {
const totals = new Set(entries.map((e) => e.total));
if (totals.size === 1) {
const [total] = totals;
console.log(`OK: ${index}${entries.length} series, all length ${total}`);
continue;
}
failed = true;
console.log(`\nMISMATCH: ${index}${entries.length} series with ${totals.size} different lengths:`);
/** @type {Map<number, string[]>} */
const grouped = new Map();
for (const { path, total } of entries) {
if (!grouped.has(total)) grouped.set(total, []);
grouped.get(total).push(path);
}
for (const [total, paths] of [...grouped].sort((a, b) => b[0] - a[0])) {
console.log(` length ${total}: (${paths.length} series)`);
for (const p of paths) {
console.log(` ${p}`);
}
}
}
if (failed) {
console.log("\nFAILED: length mismatches detected");
process.exit(1);
} else {
console.log("\nPASSED: all indexes consistent");
}
}
testConsistency();