mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-04-24 06:39:58 -07:00
546 lines
15 KiB
JavaScript
546 lines
15 KiB
JavaScript
import { colors } from "../utils/colors.js";
|
|
import { brk } from "../client.js";
|
|
import { Unit } from "../utils/units.js";
|
|
import { dots, line, baseline, price, rollingWindowsTree, percentRatioDots } from "./series.js";
|
|
import { satsBtcUsd, priceRatioPercentilesTree } from "./shared.js";
|
|
|
|
/**
|
|
* Create Cointime section
|
|
* @returns {PartialOptionsGroup}
|
|
*/
|
|
export function createCointimeSection() {
|
|
const { cointime, cohorts, supply } = brk.metrics;
|
|
const {
|
|
prices: cointimePrices,
|
|
cap,
|
|
activity,
|
|
supply: cointimeSupply,
|
|
adjusted,
|
|
reserveRisk,
|
|
value,
|
|
coinblocksDestroyed,
|
|
} = cointime;
|
|
const { all } = cohorts.utxo;
|
|
|
|
// Reference lines for cap comparisons
|
|
const capReferenceLines = /** @type {const} */ ([
|
|
{ metric: supply.marketCap.usd, name: "Market", color: colors.default },
|
|
{
|
|
metric: all.realized.cap.usd,
|
|
name: "Realized",
|
|
color: colors.realized,
|
|
},
|
|
]);
|
|
|
|
const prices = /** @type {const} */ ([
|
|
{
|
|
pattern: cointimePrices.trueMarketMean,
|
|
name: "True Market Mean",
|
|
color: colors.trueMarketMean,
|
|
},
|
|
{
|
|
pattern: cointimePrices.vaulted,
|
|
name: "Vaulted",
|
|
color: colors.vaulted,
|
|
},
|
|
{
|
|
pattern: cointimePrices.active,
|
|
name: "Active",
|
|
color: colors.active,
|
|
},
|
|
{
|
|
pattern: cointimePrices.cointime,
|
|
name: "Cointime",
|
|
color: colors.cointime,
|
|
},
|
|
{
|
|
pattern: cointimePrices.transfer,
|
|
name: "Transfer",
|
|
color: colors.transfer,
|
|
},
|
|
{
|
|
pattern: cointimePrices.balanced,
|
|
name: "Balanced",
|
|
color: colors.balanced,
|
|
},
|
|
{
|
|
pattern: cointimePrices.terminal,
|
|
name: "Terminal",
|
|
color: colors.terminal,
|
|
},
|
|
{
|
|
pattern: cointimePrices.delta,
|
|
name: "Delta",
|
|
color: colors.delta,
|
|
},
|
|
]);
|
|
|
|
const caps = /** @type {const} */ ([
|
|
{ metric: cap.vaulted.usd, name: "Vaulted", color: colors.vaulted },
|
|
{ metric: cap.active.usd, name: "Active", color: colors.active },
|
|
{ metric: cap.cointime.usd, name: "Cointime", color: colors.cointime },
|
|
{ metric: cap.investor.usd, name: "Investor", color: colors.investor },
|
|
{ metric: cap.thermo.usd, name: "Thermo", color: colors.thermo },
|
|
]);
|
|
|
|
const supplyBreakdown = /** @type {const} */ ([
|
|
{ pattern: all.supply.total, name: "Total", color: colors.bitcoin },
|
|
{
|
|
pattern: cointimeSupply.vaulted,
|
|
name: "Vaulted",
|
|
color: colors.vaulted,
|
|
},
|
|
{
|
|
pattern: cointimeSupply.active,
|
|
name: "Active",
|
|
color: colors.active,
|
|
},
|
|
]);
|
|
|
|
const coinblocks = /** @type {const} */ ([
|
|
{
|
|
pattern: coinblocksDestroyed,
|
|
name: "Destroyed",
|
|
title: "Coinblocks Destroyed",
|
|
color: colors.destroyed,
|
|
},
|
|
{
|
|
pattern: activity.coinblocksCreated,
|
|
name: "Created",
|
|
title: "Coinblocks Created",
|
|
color: colors.created,
|
|
},
|
|
{
|
|
pattern: activity.coinblocksStored,
|
|
name: "Stored",
|
|
title: "Coinblocks Stored",
|
|
color: colors.stored,
|
|
},
|
|
]);
|
|
|
|
// Colors aligned with coinblocks: Destroyed=red, Created=orange, Stored=green
|
|
const cointimeValues = /** @type {const} */ ([
|
|
{
|
|
pattern: value.created,
|
|
name: "Created",
|
|
title: "Cointime Value Created",
|
|
color: colors.created,
|
|
},
|
|
{
|
|
pattern: value.destroyed,
|
|
name: "Destroyed",
|
|
title: "Cointime Value Destroyed",
|
|
color: colors.destroyed,
|
|
},
|
|
{
|
|
pattern: value.stored,
|
|
name: "Stored",
|
|
title: "Cointime Value Stored",
|
|
color: colors.stored,
|
|
},
|
|
]);
|
|
|
|
const vocdd = /** @type {const} */ ({
|
|
pattern: value.vocdd,
|
|
name: "VOCDD",
|
|
title: "Value of Coin Days Destroyed",
|
|
color: colors.vocdd,
|
|
});
|
|
|
|
return {
|
|
name: "Cointime",
|
|
tree: [
|
|
// Prices - the core pricing models
|
|
{
|
|
name: "Prices",
|
|
tree: [
|
|
{
|
|
name: "Compare",
|
|
title: "Cointime Prices",
|
|
top: [
|
|
price({
|
|
metric: all.realized.price,
|
|
name: "Realized",
|
|
color: colors.realized,
|
|
}),
|
|
price({
|
|
metric: all.realized.investor.price,
|
|
name: "Investor",
|
|
color: colors.investor,
|
|
}),
|
|
...prices.map(({ pattern, name, color }) =>
|
|
price({ metric: pattern, name, color }),
|
|
),
|
|
],
|
|
},
|
|
...prices.map(({ pattern, name, color }) => ({
|
|
name,
|
|
tree: priceRatioPercentilesTree({
|
|
pattern,
|
|
title: `${name} Price`,
|
|
legend: name,
|
|
color,
|
|
priceReferences: [
|
|
price({ metric: all.realized.price, name: "Realized", color: colors.realized, defaultActive: false }),
|
|
],
|
|
}),
|
|
})),
|
|
],
|
|
},
|
|
|
|
// Caps - market capitalizations from different models
|
|
{
|
|
name: "Caps",
|
|
tree: [
|
|
{
|
|
name: "Compare",
|
|
title: "Cointime Caps",
|
|
bottom: [
|
|
...capReferenceLines.map(({ metric, name, color }) =>
|
|
line({ metric, name, color, unit: Unit.usd }),
|
|
),
|
|
...caps.map(({ metric, name, color }) =>
|
|
line({ metric, name, color, unit: Unit.usd }),
|
|
),
|
|
],
|
|
},
|
|
...caps.map(({ metric, name, color }) => ({
|
|
name,
|
|
title: `${name} Cap`,
|
|
bottom: [
|
|
line({ metric, name, color, unit: Unit.usd }),
|
|
...capReferenceLines.map((ref) =>
|
|
line({
|
|
metric: ref.metric,
|
|
name: ref.name,
|
|
color: ref.color,
|
|
unit: Unit.usd,
|
|
}),
|
|
),
|
|
],
|
|
})),
|
|
],
|
|
},
|
|
|
|
// Supply - active vs vaulted breakdown
|
|
{
|
|
name: "Supply",
|
|
title: "Active vs Vaulted Supply",
|
|
bottom: supplyBreakdown.flatMap(({ pattern, name, color }) =>
|
|
satsBtcUsd({ pattern, name, color }),
|
|
),
|
|
},
|
|
|
|
// Liveliness - the foundational cointime ratios
|
|
{
|
|
name: "Activity",
|
|
title: "Liveliness & Vaultedness",
|
|
bottom: [
|
|
line({
|
|
metric: activity.liveliness,
|
|
name: "Liveliness",
|
|
color: colors.liveliness,
|
|
unit: Unit.ratio,
|
|
}),
|
|
line({
|
|
metric: activity.vaultedness,
|
|
name: "Vaultedness",
|
|
color: colors.vaulted,
|
|
unit: Unit.ratio,
|
|
}),
|
|
line({
|
|
metric: activity.ratio,
|
|
name: "L/V Ratio",
|
|
color: colors.activity,
|
|
unit: Unit.ratio,
|
|
defaultActive: false,
|
|
}),
|
|
],
|
|
},
|
|
|
|
// Coinblocks - created, destroyed, stored
|
|
{
|
|
name: "Coinblocks",
|
|
tree: [
|
|
{
|
|
name: "Compare",
|
|
tree: [
|
|
{
|
|
name: "Base",
|
|
title: "Coinblocks",
|
|
bottom: coinblocks.map(({ pattern, name, color }) =>
|
|
line({
|
|
metric: pattern.base,
|
|
name,
|
|
color,
|
|
unit: Unit.coinblocks,
|
|
}),
|
|
),
|
|
},
|
|
{
|
|
name: "Cumulative",
|
|
title: "Coinblocks (Total)",
|
|
bottom: coinblocks.map(({ pattern, name, color }) =>
|
|
line({
|
|
metric: pattern.cumulative,
|
|
name,
|
|
color,
|
|
unit: Unit.coinblocks,
|
|
}),
|
|
),
|
|
},
|
|
],
|
|
},
|
|
...coinblocks.map(({ pattern, name, title, color }) => ({
|
|
name,
|
|
tree: [
|
|
{
|
|
name: "Base",
|
|
title,
|
|
bottom: [
|
|
line({
|
|
metric: pattern.base,
|
|
name,
|
|
color,
|
|
unit: Unit.coinblocks,
|
|
}),
|
|
],
|
|
},
|
|
rollingWindowsTree({ windows: pattern.sum, title, unit: Unit.coinblocks }),
|
|
{
|
|
name: "Cumulative",
|
|
title: `${title} (Total)`,
|
|
bottom: [
|
|
line({
|
|
metric: pattern.cumulative,
|
|
name,
|
|
color,
|
|
unit: Unit.coinblocks,
|
|
}),
|
|
],
|
|
},
|
|
],
|
|
})),
|
|
],
|
|
},
|
|
|
|
// Value - cointime value flows
|
|
{
|
|
name: "Value",
|
|
tree: [
|
|
{
|
|
name: "Compare",
|
|
tree: [
|
|
{
|
|
name: "Base",
|
|
title: "Cointime Value",
|
|
bottom: [
|
|
...cointimeValues.map(({ pattern, name, color }) =>
|
|
line({ metric: pattern.base, name, color, unit: Unit.usd }),
|
|
),
|
|
line({
|
|
metric: vocdd.pattern.base,
|
|
name: vocdd.name,
|
|
color: vocdd.color,
|
|
unit: Unit.usd,
|
|
}),
|
|
],
|
|
},
|
|
{
|
|
name: "Cumulative",
|
|
title: "Cointime Value (Total)",
|
|
bottom: [
|
|
...cointimeValues.map(({ pattern, name, color }) =>
|
|
line({
|
|
metric: pattern.cumulative,
|
|
name,
|
|
color,
|
|
unit: Unit.usd,
|
|
}),
|
|
),
|
|
line({
|
|
metric: vocdd.pattern.cumulative,
|
|
name: vocdd.name,
|
|
color: vocdd.color,
|
|
unit: Unit.usd,
|
|
}),
|
|
],
|
|
},
|
|
],
|
|
},
|
|
...cointimeValues.map(({ pattern, name, title, color }) => ({
|
|
name,
|
|
tree: [
|
|
{
|
|
name: "Base",
|
|
title,
|
|
bottom: [
|
|
line({ metric: pattern.base, name, color, unit: Unit.usd }),
|
|
],
|
|
},
|
|
rollingWindowsTree({ windows: pattern.sum, title, unit: Unit.usd }),
|
|
{
|
|
name: "Cumulative",
|
|
title: `${title} (Total)`,
|
|
bottom: [
|
|
line({
|
|
metric: pattern.cumulative,
|
|
name,
|
|
color,
|
|
unit: Unit.usd,
|
|
}),
|
|
],
|
|
},
|
|
],
|
|
})),
|
|
{
|
|
name: vocdd.name,
|
|
tree: [
|
|
{
|
|
name: "Base",
|
|
title: vocdd.title,
|
|
bottom: [
|
|
line({
|
|
metric: vocdd.pattern.base,
|
|
name: vocdd.name,
|
|
color: vocdd.color,
|
|
unit: Unit.usd,
|
|
}),
|
|
line({
|
|
metric: reserveRisk.vocddMedian1y,
|
|
name: "365d Median",
|
|
color: colors.time._1y,
|
|
unit: Unit.usd,
|
|
}),
|
|
],
|
|
},
|
|
rollingWindowsTree({ windows: vocdd.pattern.sum, title: vocdd.title, unit: Unit.usd }),
|
|
{
|
|
name: "Cumulative",
|
|
title: `${vocdd.title} (Total)`,
|
|
bottom: [
|
|
line({
|
|
metric: vocdd.pattern.cumulative,
|
|
name: vocdd.name,
|
|
color: vocdd.color,
|
|
unit: Unit.usd,
|
|
}),
|
|
],
|
|
},
|
|
],
|
|
},
|
|
],
|
|
},
|
|
|
|
// Indicators - derived decision metrics
|
|
{
|
|
name: "Indicators",
|
|
tree: [
|
|
{
|
|
name: "Reserve Risk",
|
|
title: "Reserve Risk",
|
|
bottom: [
|
|
line({
|
|
metric: reserveRisk.value,
|
|
name: "Ratio",
|
|
color: colors.reserveRisk,
|
|
unit: Unit.ratio,
|
|
}),
|
|
],
|
|
},
|
|
{
|
|
name: "AVIV",
|
|
title: "AVIV Ratio",
|
|
bottom: [
|
|
baseline({
|
|
metric: cap.aviv.ratio,
|
|
name: "Ratio",
|
|
color: colors.reserveRisk,
|
|
unit: Unit.ratio,
|
|
base: 1,
|
|
}),
|
|
],
|
|
},
|
|
{
|
|
name: "HODL Bank",
|
|
title: "HODL Bank",
|
|
bottom: [
|
|
line({
|
|
metric: reserveRisk.hodlBank,
|
|
name: "Value",
|
|
color: colors.hodlBank,
|
|
unit: Unit.usd,
|
|
}),
|
|
],
|
|
},
|
|
],
|
|
},
|
|
|
|
// Cointime-Adjusted - comparing base vs adjusted metrics
|
|
{
|
|
name: "Cointime-Adjusted",
|
|
tree: [
|
|
{
|
|
name: "Inflation",
|
|
title: "Cointime-Adjusted Inflation",
|
|
bottom: [
|
|
dots({
|
|
metric: supply.inflationRate.percent,
|
|
name: "Base",
|
|
color: colors.base,
|
|
unit: Unit.percentage,
|
|
}),
|
|
...percentRatioDots({
|
|
pattern: adjusted.inflationRate,
|
|
name: "Cointime-Adjusted",
|
|
color: colors.adjusted,
|
|
}),
|
|
],
|
|
},
|
|
{
|
|
name: "Velocity",
|
|
tree: [
|
|
{
|
|
name: "BTC",
|
|
title: "Cointime-Adjusted BTC Velocity",
|
|
bottom: [
|
|
line({
|
|
metric: supply.velocity.native,
|
|
name: "Base",
|
|
color: colors.base,
|
|
unit: Unit.ratio,
|
|
}),
|
|
line({
|
|
metric: adjusted.txVelocityNative,
|
|
name: "Cointime-Adjusted",
|
|
color: colors.adjusted,
|
|
unit: Unit.ratio,
|
|
}),
|
|
],
|
|
},
|
|
{
|
|
name: "USD",
|
|
title: "Cointime-Adjusted USD Velocity",
|
|
bottom: [
|
|
line({
|
|
metric: supply.velocity.fiat,
|
|
name: "Base",
|
|
color: colors.thermo,
|
|
unit: Unit.ratio,
|
|
}),
|
|
line({
|
|
metric: adjusted.txVelocityFiat,
|
|
name: "Cointime-Adjusted",
|
|
color: colors.vaulted,
|
|
unit: Unit.ratio,
|
|
}),
|
|
],
|
|
},
|
|
],
|
|
},
|
|
],
|
|
},
|
|
],
|
|
};
|
|
}
|