mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-07-09 10:08:13 -07:00
global: snapshot
This commit is contained in:
@@ -7,6 +7,7 @@ import { Unit } from "../utils/units.js";
|
||||
import { priceLine, priceLines } from "./constants.js";
|
||||
import {
|
||||
baseline,
|
||||
deltaTree,
|
||||
histogram,
|
||||
line,
|
||||
price,
|
||||
@@ -522,58 +523,12 @@ export function createMarketSection() {
|
||||
}),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Change",
|
||||
tree: [
|
||||
{
|
||||
name: "Compare",
|
||||
title: "Market Cap Change",
|
||||
bottom: ROLLING_WINDOWS.map((w) =>
|
||||
baseline({
|
||||
series: supply.marketCap.delta.absolute[w.key].usd,
|
||||
name: w.name,
|
||||
color: w.color,
|
||||
unit: Unit.usd,
|
||||
}),
|
||||
),
|
||||
},
|
||||
...ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: `Market Cap Change ${w.name}`,
|
||||
bottom: [
|
||||
baseline({
|
||||
series: supply.marketCap.delta.absolute[w.key].usd,
|
||||
name: w.name,
|
||||
unit: Unit.usd,
|
||||
}),
|
||||
],
|
||||
})),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Growth Rate",
|
||||
tree: [
|
||||
{
|
||||
name: "Compare",
|
||||
title: "Market Cap Growth Rate",
|
||||
bottom: ROLLING_WINDOWS.flatMap((w) =>
|
||||
percentRatio({
|
||||
pattern: supply.marketCap.delta.rate[w.key],
|
||||
name: w.name,
|
||||
color: w.color,
|
||||
}),
|
||||
),
|
||||
},
|
||||
...ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: `Market Cap Growth Rate ${w.name}`,
|
||||
bottom: percentRatioBaseline({
|
||||
pattern: supply.marketCap.delta.rate[w.key],
|
||||
name: w.name,
|
||||
}),
|
||||
})),
|
||||
],
|
||||
},
|
||||
...deltaTree({
|
||||
delta: supply.marketCap.delta,
|
||||
title: "Market Cap",
|
||||
unit: Unit.usd,
|
||||
extract: (v) => v.usd,
|
||||
}),
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -591,58 +546,12 @@ export function createMarketSection() {
|
||||
}),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Change",
|
||||
tree: [
|
||||
{
|
||||
name: "Compare",
|
||||
title: "Realized Cap Change",
|
||||
bottom: ROLLING_WINDOWS.map((w) =>
|
||||
baseline({
|
||||
series: cohorts.utxo.all.realized.cap.delta.absolute[w.key].usd,
|
||||
name: w.name,
|
||||
color: w.color,
|
||||
unit: Unit.usd,
|
||||
}),
|
||||
),
|
||||
},
|
||||
...ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: `Realized Cap Change ${w.name}`,
|
||||
bottom: [
|
||||
baseline({
|
||||
series: cohorts.utxo.all.realized.cap.delta.absolute[w.key].usd,
|
||||
name: w.name,
|
||||
unit: Unit.usd,
|
||||
}),
|
||||
],
|
||||
})),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Growth Rate",
|
||||
tree: [
|
||||
{
|
||||
name: "Compare",
|
||||
title: "Realized Cap Growth Rate",
|
||||
bottom: ROLLING_WINDOWS.flatMap((w) =>
|
||||
percentRatio({
|
||||
pattern: cohorts.utxo.all.realized.cap.delta.rate[w.key],
|
||||
name: w.name,
|
||||
color: w.color,
|
||||
}),
|
||||
),
|
||||
},
|
||||
...ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: `Realized Cap Growth Rate ${w.name}`,
|
||||
bottom: percentRatioBaseline({
|
||||
pattern: cohorts.utxo.all.realized.cap.delta.rate[w.key],
|
||||
name: w.name,
|
||||
}),
|
||||
})),
|
||||
],
|
||||
},
|
||||
...deltaTree({
|
||||
delta: cohorts.utxo.all.realized.cap.delta,
|
||||
title: "Realized Cap",
|
||||
unit: Unit.usd,
|
||||
extract: (v) => v.usd,
|
||||
}),
|
||||
],
|
||||
},
|
||||
{
|
||||
|
||||
+137
-362
@@ -12,18 +12,18 @@ import {
|
||||
fromSupplyPattern,
|
||||
chartsFromFullPerBlock,
|
||||
chartsFromCount,
|
||||
chartsFromCountEntries,
|
||||
chartsFromSumPerBlock,
|
||||
rollingWindowsTree,
|
||||
distributionWindowsTree,
|
||||
|
||||
ROLLING_WINDOWS,
|
||||
chartsFromBlockAnd6b,
|
||||
fromStatsPattern,
|
||||
simpleDeltaTree,
|
||||
percentRatio,
|
||||
percentRatioDots,
|
||||
rollingPercentRatioTree,
|
||||
} from "./series.js";
|
||||
import { satsBtcUsd, satsBtcUsdFrom } from "./shared.js";
|
||||
import { satsBtcUsd, satsBtcUsdFrom, satsBtcUsdFullTree } from "./shared.js";
|
||||
|
||||
/**
|
||||
* Create Network section
|
||||
@@ -512,202 +512,97 @@ export function createNetworkSection() {
|
||||
unit: Unit.count,
|
||||
}),
|
||||
},
|
||||
{
|
||||
name: "Volume",
|
||||
tree: satsBtcUsdFullTree({
|
||||
pattern: transactions.volume.transferVolume,
|
||||
name: "base",
|
||||
title: "Transaction Volume",
|
||||
}),
|
||||
},
|
||||
{
|
||||
name: "Fee Rate",
|
||||
title: "Fee Rate Distribution (6 Blocks)",
|
||||
bottom: fromStatsPattern({ pattern: transactions.fees.feeRate._6b, unit: Unit.feeRate }),
|
||||
tree: chartsFromBlockAnd6b({
|
||||
pattern: transactions.fees.feeRate,
|
||||
title: "Transaction Fee Rate",
|
||||
unit: Unit.feeRate,
|
||||
}),
|
||||
},
|
||||
{
|
||||
name: "Fee",
|
||||
title: "Fee Distribution (6 Blocks)",
|
||||
bottom: fromStatsPattern({ pattern: transactions.fees.fee._6b, unit: Unit.sats }),
|
||||
tree: chartsFromBlockAnd6b({
|
||||
pattern: transactions.fees.fee,
|
||||
title: "Transaction Fee",
|
||||
unit: Unit.sats,
|
||||
}),
|
||||
},
|
||||
{
|
||||
name: "Volume",
|
||||
tree: [
|
||||
{
|
||||
name: "Transferred",
|
||||
title: "Transaction Volume",
|
||||
bottom: [
|
||||
...satsBtcUsd({
|
||||
pattern: transactions.volume.transferVolume.base,
|
||||
name: "Sent",
|
||||
}),
|
||||
...satsBtcUsd({
|
||||
pattern: transactions.volume.outputVolume.base,
|
||||
name: "Received",
|
||||
color: colors.entity.output,
|
||||
}),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Sent Rolling",
|
||||
tree: [
|
||||
{
|
||||
name: "Compare",
|
||||
title: "Sent Volume Rolling",
|
||||
bottom: ROLLING_WINDOWS.flatMap((w) =>
|
||||
satsBtcUsd({
|
||||
pattern: transactions.volume.transferVolume.sum[w.key],
|
||||
name: w.name,
|
||||
color: w.color,
|
||||
}),
|
||||
),
|
||||
},
|
||||
...ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: `Sent Volume ${w.name}`,
|
||||
bottom: satsBtcUsd({
|
||||
pattern: transactions.volume.transferVolume.sum[w.key],
|
||||
name: w.name,
|
||||
color: w.color,
|
||||
}),
|
||||
})),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Sent Cumulative",
|
||||
title: "Sent Volume (Total)",
|
||||
bottom: satsBtcUsd({
|
||||
pattern: transactions.volume.transferVolume.cumulative,
|
||||
name: "all-time",
|
||||
}),
|
||||
},
|
||||
{
|
||||
name: "Received Rolling",
|
||||
tree: [
|
||||
{
|
||||
name: "Compare",
|
||||
title: "Received Volume Rolling",
|
||||
bottom: ROLLING_WINDOWS.flatMap((w) =>
|
||||
satsBtcUsd({
|
||||
pattern: transactions.volume.outputVolume.sum[w.key],
|
||||
name: w.name,
|
||||
color: w.color,
|
||||
}),
|
||||
),
|
||||
},
|
||||
...ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: `Received Volume ${w.name}`,
|
||||
bottom: satsBtcUsd({
|
||||
pattern: transactions.volume.outputVolume.sum[w.key],
|
||||
name: w.name,
|
||||
color: w.color,
|
||||
}),
|
||||
})),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Received Cumulative",
|
||||
title: "Received Volume (Total)",
|
||||
bottom: satsBtcUsd({
|
||||
pattern: transactions.volume.outputVolume.cumulative,
|
||||
name: "all-time",
|
||||
}),
|
||||
},
|
||||
],
|
||||
name: "Weight",
|
||||
tree: chartsFromBlockAnd6b({
|
||||
pattern: transactions.size.weight,
|
||||
title: "Transaction Weight",
|
||||
unit: Unit.wu,
|
||||
}),
|
||||
},
|
||||
{
|
||||
name: "Size",
|
||||
tree: [
|
||||
{
|
||||
name: "Weight",
|
||||
tree: chartsFromBlockAnd6b({
|
||||
pattern: transactions.size.weight,
|
||||
title: "Transaction Weight",
|
||||
unit: Unit.wu,
|
||||
}),
|
||||
},
|
||||
{
|
||||
name: "vSize",
|
||||
tree: chartsFromBlockAnd6b({
|
||||
pattern: transactions.size.vsize,
|
||||
title: "Transaction vSize",
|
||||
unit: Unit.vb,
|
||||
}),
|
||||
},
|
||||
],
|
||||
name: "vSize",
|
||||
tree: chartsFromBlockAnd6b({
|
||||
pattern: transactions.size.vsize,
|
||||
title: "Transaction vSize",
|
||||
unit: Unit.vb,
|
||||
}),
|
||||
},
|
||||
{
|
||||
name: "Versions",
|
||||
tree: [
|
||||
{
|
||||
name: "Base",
|
||||
title: "Transaction Versions",
|
||||
bottom: entries(transactions.versions).map(
|
||||
([v, data], i, arr) =>
|
||||
line({
|
||||
series: data.base,
|
||||
name: v,
|
||||
color: colors.at(i, arr.length),
|
||||
unit: Unit.count,
|
||||
}),
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "Rolling",
|
||||
tree: [
|
||||
{
|
||||
name: "Compare",
|
||||
title: "Transaction Versions Rolling",
|
||||
bottom: entries(transactions.versions).flatMap(
|
||||
([v, data], i, arr) =>
|
||||
ROLLING_WINDOWS.map((w) =>
|
||||
line({
|
||||
series: data.sum[w.key],
|
||||
name: `${v} ${w.name}`,
|
||||
color: colors.at(i, arr.length),
|
||||
unit: Unit.count,
|
||||
}),
|
||||
),
|
||||
),
|
||||
},
|
||||
...ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: `Transaction Versions (${w.name})`,
|
||||
bottom: entries(transactions.versions).map(
|
||||
([v, data], i, arr) =>
|
||||
line({
|
||||
series: data.sum[w.key],
|
||||
name: v,
|
||||
color: colors.at(i, arr.length),
|
||||
unit: Unit.count,
|
||||
}),
|
||||
),
|
||||
})),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Cumulative",
|
||||
title: "Transaction Versions (Total)",
|
||||
bottom: entries(transactions.versions).map(
|
||||
([v, data], i, arr) =>
|
||||
line({
|
||||
series: data.cumulative,
|
||||
name: v,
|
||||
color: colors.at(i, arr.length),
|
||||
unit: Unit.count,
|
||||
}),
|
||||
),
|
||||
},
|
||||
],
|
||||
tree: chartsFromCountEntries({
|
||||
entries: entries(transactions.versions),
|
||||
title: "Transaction Versions",
|
||||
unit: Unit.count,
|
||||
}),
|
||||
},
|
||||
{
|
||||
name: "Velocity",
|
||||
title: "Transaction Velocity",
|
||||
bottom: [
|
||||
line({
|
||||
series: supply.velocity.native,
|
||||
name: "BTC",
|
||||
unit: Unit.ratio,
|
||||
}),
|
||||
line({
|
||||
series: supply.velocity.fiat,
|
||||
name: "USD",
|
||||
color: colors.usd,
|
||||
unit: Unit.ratio,
|
||||
}),
|
||||
tree: [
|
||||
{
|
||||
name: "Compare",
|
||||
title: "Transaction Velocity",
|
||||
bottom: [
|
||||
line({
|
||||
series: supply.velocity.native,
|
||||
name: "BTC",
|
||||
unit: Unit.ratio,
|
||||
}),
|
||||
line({
|
||||
series: supply.velocity.fiat,
|
||||
name: "USD",
|
||||
color: colors.usd,
|
||||
unit: Unit.ratio,
|
||||
}),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Native",
|
||||
title: "Transaction Velocity (BTC)",
|
||||
bottom: [
|
||||
line({
|
||||
series: supply.velocity.native,
|
||||
name: "BTC",
|
||||
unit: Unit.ratio,
|
||||
}),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Fiat",
|
||||
title: "Transaction Velocity (USD)",
|
||||
bottom: [
|
||||
line({
|
||||
series: supply.velocity.fiat,
|
||||
name: "USD",
|
||||
color: colors.usd,
|
||||
unit: Unit.ratio,
|
||||
}),
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
@@ -721,37 +616,45 @@ export function createNetworkSection() {
|
||||
name: "Count",
|
||||
tree: [
|
||||
{
|
||||
name: "Base",
|
||||
title: "Block Count",
|
||||
bottom: [
|
||||
line({
|
||||
series: blocks.count.total.base,
|
||||
name: "base",
|
||||
unit: Unit.count,
|
||||
}),
|
||||
line({
|
||||
series: blocks.count.target,
|
||||
name: "Target",
|
||||
color: colors.gray,
|
||||
unit: Unit.count,
|
||||
options: { lineStyle: 4 },
|
||||
}),
|
||||
name: "Sums",
|
||||
tree: [
|
||||
{
|
||||
name: "Compare",
|
||||
title: "Block Count Rolling",
|
||||
bottom: ROLLING_WINDOWS.map((w) =>
|
||||
line({
|
||||
series: blocks.count.total.sum[w.key],
|
||||
name: w.name,
|
||||
color: w.color,
|
||||
unit: Unit.count,
|
||||
}),
|
||||
),
|
||||
},
|
||||
...ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: `Block Count ${w.name}`,
|
||||
bottom: [
|
||||
line({
|
||||
series: blocks.count.total.sum[w.key],
|
||||
name: "Actual",
|
||||
unit: Unit.count,
|
||||
}),
|
||||
line({
|
||||
series: blocks.count.target[w.key],
|
||||
name: "Target",
|
||||
color: colors.gray,
|
||||
unit: Unit.count,
|
||||
options: { lineStyle: 4 },
|
||||
}),
|
||||
],
|
||||
})),
|
||||
],
|
||||
},
|
||||
rollingWindowsTree({
|
||||
windows: blocks.count.total.sum,
|
||||
title: "Block Count",
|
||||
unit: Unit.count,
|
||||
}),
|
||||
{
|
||||
name: "Cumulative",
|
||||
title: "Block Count (Total)",
|
||||
bottom: [
|
||||
line({
|
||||
series: blocks.count.total.cumulative,
|
||||
name: "all-time",
|
||||
unit: Unit.count,
|
||||
}),
|
||||
{ series: blocks.count.total.cumulative, title: "all-time", unit: Unit.count },
|
||||
],
|
||||
},
|
||||
],
|
||||
@@ -760,7 +663,7 @@ export function createNetworkSection() {
|
||||
name: "Interval",
|
||||
tree: [
|
||||
{
|
||||
name: "Base",
|
||||
name: "Per Block",
|
||||
title: "Block Interval",
|
||||
bottom: [
|
||||
dots({
|
||||
@@ -780,155 +683,34 @@ export function createNetworkSection() {
|
||||
rollingWindowsTree({
|
||||
windows: blocks.interval,
|
||||
title: "Block Interval",
|
||||
name: "Averages",
|
||||
unit: Unit.secs,
|
||||
}),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Size",
|
||||
tree: [
|
||||
{
|
||||
name: "Base",
|
||||
title: "Block Size",
|
||||
bottom: [
|
||||
line({
|
||||
series: blocks.size.base,
|
||||
name: "base",
|
||||
unit: Unit.bytes,
|
||||
}),
|
||||
],
|
||||
},
|
||||
rollingWindowsTree({
|
||||
windows: blocks.size.sum,
|
||||
title: "Block Size",
|
||||
unit: Unit.bytes,
|
||||
}),
|
||||
distributionWindowsTree({
|
||||
pattern: blocks.size,
|
||||
base: blocks.size.base,
|
||||
title: "Block Size",
|
||||
unit: Unit.bytes,
|
||||
}),
|
||||
{
|
||||
name: "Cumulative",
|
||||
title: "Block Size (Total)",
|
||||
bottom: [
|
||||
line({
|
||||
series: blocks.size.cumulative,
|
||||
name: "all-time",
|
||||
unit: Unit.bytes,
|
||||
}),
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Weight",
|
||||
tree: [
|
||||
{
|
||||
name: "Base",
|
||||
title: "Block Weight",
|
||||
bottom: [
|
||||
line({
|
||||
series: blocks.weight.base,
|
||||
name: "base",
|
||||
unit: Unit.wu,
|
||||
}),
|
||||
],
|
||||
},
|
||||
rollingWindowsTree({
|
||||
windows: blocks.weight.sum,
|
||||
title: "Block Weight",
|
||||
unit: Unit.wu,
|
||||
}),
|
||||
distributionWindowsTree({
|
||||
pattern: blocks.weight,
|
||||
base: blocks.weight.base,
|
||||
title: "Block Weight",
|
||||
unit: Unit.wu,
|
||||
}),
|
||||
{
|
||||
name: "Cumulative",
|
||||
title: "Block Weight (Total)",
|
||||
bottom: [
|
||||
line({
|
||||
series: blocks.weight.cumulative,
|
||||
name: "all-time",
|
||||
unit: Unit.wu,
|
||||
}),
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "vBytes",
|
||||
tree: [
|
||||
{
|
||||
name: "Base",
|
||||
title: "Block vBytes",
|
||||
bottom: [
|
||||
line({
|
||||
series: blocks.vbytes.base,
|
||||
name: "base",
|
||||
unit: Unit.vb,
|
||||
}),
|
||||
],
|
||||
},
|
||||
rollingWindowsTree({
|
||||
windows: blocks.vbytes.sum,
|
||||
title: "Block vBytes",
|
||||
unit: Unit.vb,
|
||||
}),
|
||||
distributionWindowsTree({
|
||||
pattern: blocks.vbytes,
|
||||
base: blocks.vbytes.base,
|
||||
title: "Block vBytes",
|
||||
unit: Unit.vb,
|
||||
}),
|
||||
{
|
||||
name: "Cumulative",
|
||||
title: "Block vBytes (Total)",
|
||||
bottom: [
|
||||
line({
|
||||
series: blocks.vbytes.cumulative,
|
||||
name: "all-time",
|
||||
unit: Unit.vb,
|
||||
}),
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Fullness",
|
||||
title: "Block Fullness",
|
||||
bottom: percentRatioDots({
|
||||
pattern: blocks.fullness,
|
||||
name: "base",
|
||||
tree: chartsFromFullPerBlock({
|
||||
pattern: blocks.size,
|
||||
title: "Block Size",
|
||||
unit: Unit.bytes,
|
||||
}),
|
||||
},
|
||||
{
|
||||
name: "Difficulty",
|
||||
tree: [
|
||||
{
|
||||
name: "Base",
|
||||
title: "Mining Difficulty",
|
||||
bottom: [
|
||||
line({
|
||||
series: blocks.difficulty.value,
|
||||
name: "Difficulty",
|
||||
unit: Unit.count,
|
||||
}),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Adjustment",
|
||||
title: "Difficulty Adjustment",
|
||||
bottom: percentRatioDots({
|
||||
pattern: blocks.difficulty.adjustment,
|
||||
name: "Adjustment",
|
||||
}),
|
||||
},
|
||||
],
|
||||
name: "Weight",
|
||||
tree: chartsFromFullPerBlock({
|
||||
pattern: blocks.weight,
|
||||
title: "Block Weight",
|
||||
unit: Unit.wu,
|
||||
}),
|
||||
},
|
||||
{
|
||||
name: "vBytes",
|
||||
tree: chartsFromFullPerBlock({
|
||||
pattern: blocks.vbytes,
|
||||
title: "Block vBytes",
|
||||
unit: Unit.vb,
|
||||
}),
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -948,18 +730,11 @@ export function createNetworkSection() {
|
||||
}),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "30d Change",
|
||||
title: "UTXO Count 30d Change",
|
||||
bottom: [
|
||||
baseline({
|
||||
series:
|
||||
cohorts.utxo.all.outputs.unspentCount.delta.absolute._1m,
|
||||
name: "30d Change",
|
||||
unit: Unit.count,
|
||||
}),
|
||||
],
|
||||
},
|
||||
...simpleDeltaTree({
|
||||
delta: cohorts.utxo.all.outputs.unspentCount.delta,
|
||||
title: "UTXO Count",
|
||||
unit: Unit.count,
|
||||
}),
|
||||
{
|
||||
name: "Flow",
|
||||
title: "UTXO Flow",
|
||||
|
||||
@@ -476,12 +476,13 @@ export function statsAtWindow(pattern, window) {
|
||||
* @param {{ _24h: AnySeriesPattern, _1w: AnySeriesPattern, _1m: AnySeriesPattern, _1y: AnySeriesPattern }} args.windows
|
||||
* @param {string} args.title
|
||||
* @param {Unit} args.unit
|
||||
* @param {string} [args.name]
|
||||
* @param {(args: {series: AnySeriesPattern, name: string, color: Color, unit: Unit}) => AnyFetchedSeriesBlueprint} [args.series]
|
||||
* @returns {PartialOptionsGroup}
|
||||
*/
|
||||
export function rollingWindowsTree({ windows, title, unit, series = line }) {
|
||||
export function rollingWindowsTree({ windows, title, unit, name = "Sums", series = line }) {
|
||||
return {
|
||||
name: "Sums",
|
||||
name,
|
||||
tree: [
|
||||
{
|
||||
name: "Compare",
|
||||
@@ -523,17 +524,26 @@ export function rollingWindowsTree({ windows, title, unit, series = line }) {
|
||||
export function distributionWindowsTree({ pattern, base, title, unit }) {
|
||||
return {
|
||||
name: "Distributions",
|
||||
tree: ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: `${title} Distribution (${w.name})`,
|
||||
bottom: [
|
||||
...(base ? [line({ series: base, name: "base", unit })] : []),
|
||||
...fromStatsPattern({
|
||||
pattern: statsAtWindow(pattern, w.key),
|
||||
unit,
|
||||
}),
|
||||
],
|
||||
})),
|
||||
tree: [
|
||||
{
|
||||
name: "Compare",
|
||||
title: `${title} Average`,
|
||||
bottom: ROLLING_WINDOWS.map((w) =>
|
||||
line({ series: pattern.average[w.key], name: w.name, color: w.color, unit }),
|
||||
),
|
||||
},
|
||||
...ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: `${title} Distribution (${w.name})`,
|
||||
bottom: [
|
||||
...(base ? [line({ series: base, name: "base", unit })] : []),
|
||||
...fromStatsPattern({
|
||||
pattern: statsAtWindow(pattern, w.key),
|
||||
unit,
|
||||
}),
|
||||
],
|
||||
})),
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
@@ -651,10 +661,10 @@ export function percentRatioDots({ pattern, name, color, defaultActive }) {
|
||||
* @param {boolean} [args.defaultActive]
|
||||
* @returns {AnyFetchedSeriesBlueprint[]}
|
||||
*/
|
||||
export function percentRatioBaseline({ pattern, name, color, defaultActive }) {
|
||||
export function percentRatioBaseline({ pattern, name, defaultActive }) {
|
||||
return [
|
||||
baseline({ series: pattern.percent, name, color, defaultActive, unit: Unit.percentage }),
|
||||
baseline({ series: pattern.ratio, name, color, defaultActive, unit: Unit.ratio }),
|
||||
baseline({ series: pattern.percent, name, defaultActive, unit: Unit.percentage }),
|
||||
baseline({ series: pattern.ratio, name, defaultActive, unit: Unit.ratio }),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -663,29 +673,86 @@ export function percentRatioBaseline({ pattern, name, color, defaultActive }) {
|
||||
* @param {Object} args
|
||||
* @param {{ _24h: { percent: AnySeriesPattern, ratio: AnySeriesPattern }, _1w: { percent: AnySeriesPattern, ratio: AnySeriesPattern }, _1m: { percent: AnySeriesPattern, ratio: AnySeriesPattern }, _1y: { percent: AnySeriesPattern, ratio: AnySeriesPattern } }} args.windows
|
||||
* @param {string} args.title
|
||||
* @param {(args: {pattern: { percent: AnySeriesPattern, ratio: AnySeriesPattern }, name: string, color: Color}) => AnyFetchedSeriesBlueprint[]} [args.series]
|
||||
* @param {string} [args.name]
|
||||
* @param {(args: {pattern: { percent: AnySeriesPattern, ratio: AnySeriesPattern }, name: string, color?: Color}) => AnyFetchedSeriesBlueprint[]} [args.series]
|
||||
* @returns {PartialOptionsGroup}
|
||||
*/
|
||||
export function rollingPercentRatioTree({ windows, title, series = percentRatio }) {
|
||||
export function rollingPercentRatioTree({ windows, title, name = "Sums", series = percentRatio }) {
|
||||
return {
|
||||
name: "Sums",
|
||||
name,
|
||||
tree: [
|
||||
{
|
||||
name: "Compare",
|
||||
title: `${title} Rolling`,
|
||||
bottom: ROLLING_WINDOWS.flatMap((w) =>
|
||||
series({ pattern: windows[w.key], name: w.name, color: w.color }),
|
||||
percentRatio({ pattern: windows[w.key], name: w.name, color: w.color }),
|
||||
),
|
||||
},
|
||||
...ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: `${title} ${w.name}`,
|
||||
bottom: series({ pattern: windows[w.key], name: w.name, color: w.color }),
|
||||
bottom: series({ pattern: windows[w.key], name: w.name }),
|
||||
})),
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Change + Growth Rate tree from a delta pattern (absolute + rate)
|
||||
* @template T
|
||||
* @param {Object} args
|
||||
* @param {{ absolute: { _24h: T, _1w: T, _1m: T, _1y: T }, rate: { _24h: { percent: AnySeriesPattern, ratio: AnySeriesPattern }, _1w: { percent: AnySeriesPattern, ratio: AnySeriesPattern }, _1m: { percent: AnySeriesPattern, ratio: AnySeriesPattern }, _1y: { percent: AnySeriesPattern, ratio: AnySeriesPattern } } }} args.delta
|
||||
* @param {string} args.title
|
||||
* @param {Unit} args.unit
|
||||
* @param {(v: T) => AnySeriesPattern} args.extract
|
||||
* @returns {PartialOptionsTree}
|
||||
*/
|
||||
export function deltaTree({ delta, title, unit, extract }) {
|
||||
return [
|
||||
{
|
||||
name: "Change",
|
||||
tree: [
|
||||
{
|
||||
name: "Compare",
|
||||
title: `${title} Change`,
|
||||
bottom: ROLLING_WINDOWS.map((w) =>
|
||||
baseline({
|
||||
series: extract(delta.absolute[w.key]),
|
||||
name: w.name,
|
||||
color: w.color,
|
||||
unit,
|
||||
}),
|
||||
),
|
||||
},
|
||||
...ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: `${title} Change ${w.name}`,
|
||||
bottom: [
|
||||
baseline({
|
||||
series: extract(delta.absolute[w.key]),
|
||||
name: w.name,
|
||||
unit,
|
||||
}),
|
||||
],
|
||||
})),
|
||||
],
|
||||
},
|
||||
rollingPercentRatioTree({ windows: delta.rate, title: `${title} Growth Rate`, name: "Growth Rate", series: percentRatioBaseline }),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* deltaTree where absolute windows are directly AnySeriesPattern (no extract needed)
|
||||
* @param {Object} args
|
||||
* @param {{ absolute: { _24h: AnySeriesPattern, _1w: AnySeriesPattern, _1m: AnySeriesPattern, _1y: AnySeriesPattern }, rate: { _24h: { percent: AnySeriesPattern, ratio: AnySeriesPattern }, _1w: { percent: AnySeriesPattern, ratio: AnySeriesPattern }, _1m: { percent: AnySeriesPattern, ratio: AnySeriesPattern }, _1y: { percent: AnySeriesPattern, ratio: AnySeriesPattern } } }} args.delta
|
||||
* @param {string} args.title
|
||||
* @param {Unit} args.unit
|
||||
* @returns {PartialOptionsTree}
|
||||
*/
|
||||
export function simpleDeltaTree({ delta, title, unit }) {
|
||||
return deltaTree({ delta, title, unit, extract: (v) => v });
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Chart-generating helpers (return PartialOptionsTree for folder structures)
|
||||
// ============================================================================
|
||||
@@ -896,20 +963,40 @@ export const chartsFromSumPerBlock = (args) =>
|
||||
export function chartsFromBlockAnd6b({ pattern, title, unit }) {
|
||||
return [
|
||||
{
|
||||
name: "Per Block",
|
||||
title: `${title} per Block`,
|
||||
name: "Block",
|
||||
title: `${title} (Block)`,
|
||||
bottom: fromStatsPattern({ pattern: pattern.block, unit }),
|
||||
},
|
||||
{
|
||||
name: "Per 6 Blocks",
|
||||
title: `${title} per 6 Blocks`,
|
||||
name: "Hourly",
|
||||
title: `${title} (Hourly)`,
|
||||
bottom: fromStatsPattern({ pattern: pattern._6b, unit }),
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Split pattern with rolling sum windows + cumulative into charts
|
||||
* Sums + Cumulative charts (no Per Block)
|
||||
* @param {Object} args
|
||||
* @param {{ sum: { _24h: AnySeriesPattern, _1w: AnySeriesPattern, _1m: AnySeriesPattern, _1y: AnySeriesPattern }, cumulative: AnySeriesPattern }} args.pattern
|
||||
* @param {string} args.title
|
||||
* @param {Unit} args.unit
|
||||
* @param {Color} [args.color]
|
||||
* @returns {PartialOptionsTree}
|
||||
*/
|
||||
export function chartsFromSumsCumulative({ pattern, title, unit, color }) {
|
||||
return [
|
||||
rollingWindowsTree({ windows: pattern.sum, title, unit }),
|
||||
{
|
||||
name: "Cumulative",
|
||||
title: `${title} (Total)`,
|
||||
bottom: [{ series: pattern.cumulative, title: "all-time", color, unit }],
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Per Block + Sums + Cumulative charts
|
||||
* @param {Object} args
|
||||
* @param {CountPattern<any>} args.pattern
|
||||
* @param {string} args.title
|
||||
@@ -920,15 +1007,47 @@ export function chartsFromBlockAnd6b({ pattern, title, unit }) {
|
||||
export function chartsFromCount({ pattern, title, unit, color }) {
|
||||
return [
|
||||
{
|
||||
name: "Base",
|
||||
name: "Per Block",
|
||||
title,
|
||||
bottom: [{ series: pattern.base, title: "base", color, unit }],
|
||||
},
|
||||
rollingWindowsTree({ windows: pattern.sum, title, unit }),
|
||||
...chartsFromSumsCumulative({ pattern, title, unit, color }),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Split multiple named entries (each with base/sum/cumulative) into Per Block/Sums/Cumulative charts
|
||||
* @param {Object} args
|
||||
* @param {Array<[string, CountPattern<any>]>} args.entries
|
||||
* @param {string} args.title
|
||||
* @param {Unit} args.unit
|
||||
* @returns {PartialOptionsTree}
|
||||
*/
|
||||
export function chartsFromCountEntries({ entries, title, unit }) {
|
||||
return [
|
||||
{
|
||||
name: "Per Block",
|
||||
title,
|
||||
bottom: entries.map(([name, data], i, arr) =>
|
||||
line({ series: data.base, name, color: colors.at(i, arr.length), unit }),
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "Sums",
|
||||
tree: ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: `${title} (${w.name})`,
|
||||
bottom: entries.map(([name, data], i, arr) =>
|
||||
line({ series: data.sum[w.key], name, color: colors.at(i, arr.length), unit }),
|
||||
),
|
||||
})),
|
||||
},
|
||||
{
|
||||
name: "Cumulative",
|
||||
title: `${title} (Total)`,
|
||||
bottom: [{ series: pattern.cumulative, title: "all-time", color, unit }],
|
||||
bottom: entries.map(([name, data], i, arr) =>
|
||||
line({ series: data.cumulative, name, color: colors.at(i, arr.length), unit }),
|
||||
),
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
@@ -227,16 +227,16 @@ export function satsBtcUsdRolling({ pattern, name, color, defaultActive }) {
|
||||
export function satsBtcUsdFullTree({ pattern, name, title, color }) {
|
||||
return [
|
||||
{
|
||||
name: "Sum",
|
||||
name: "Per Block",
|
||||
title,
|
||||
bottom: satsBtcUsd({ pattern: pattern.base, name, color }),
|
||||
},
|
||||
{
|
||||
name: "Rolling",
|
||||
name: "Sums",
|
||||
tree: [
|
||||
{
|
||||
name: "Compare",
|
||||
title: `${title} Rolling Sum`,
|
||||
title: `${title} Rolling`,
|
||||
bottom: ROLLING_WINDOWS.flatMap((w) =>
|
||||
satsBtcUsd({
|
||||
pattern: pattern.sum[w.key],
|
||||
@@ -247,7 +247,7 @@ export function satsBtcUsdFullTree({ pattern, name, title, color }) {
|
||||
},
|
||||
...ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: `${title} ${w.name} Rolling Sum`,
|
||||
title: `${title} (${w.name})`,
|
||||
bottom: satsBtcUsd({
|
||||
pattern: pattern.sum[w.key],
|
||||
name: w.name,
|
||||
|
||||
Reference in New Issue
Block a user