mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-04-24 06:39:58 -07:00
global: snapshot part 18
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -1,13 +1,15 @@
|
||||
use std::{cmp::Reverse, collections::BinaryHeap, fs, path::Path};
|
||||
|
||||
use brk_cohort::{Filtered, PROFITABILITY_RANGE_COUNT, PROFIT_COUNT, TERM_NAMES};
|
||||
use brk_cohort::{Filtered, PROFIT_COUNT, PROFITABILITY_RANGE_COUNT, TERM_NAMES};
|
||||
use brk_error::Result;
|
||||
use brk_types::{BasisPoints16, Cents, CentsCompact, CostBasisDistribution, Date, Dollars, Sats};
|
||||
|
||||
use crate::distribution::metrics::{CostBasis, ProfitabilityMetrics};
|
||||
|
||||
use super::fenwick::{PercentileResult, ProfitabilityRangeResult};
|
||||
use super::groups::UTXOCohorts;
|
||||
use super::{
|
||||
fenwick::{PercentileResult, ProfitabilityRangeResult},
|
||||
groups::UTXOCohorts,
|
||||
};
|
||||
|
||||
use super::COST_BASIS_PRICE_DIGITS;
|
||||
|
||||
@@ -48,7 +50,7 @@ impl UTXOCohorts {
|
||||
push_cost_basis(<h, lth_d, &mut self.lth.metrics.cost_basis);
|
||||
|
||||
let prof = self.fenwick.profitability(spot_price);
|
||||
push_profitability(&prof, &mut self.profitability);
|
||||
push_profitability(&prof, spot_price, &mut self.profitability);
|
||||
}
|
||||
|
||||
/// K-way merge only for writing daily cost basis distributions to disk.
|
||||
@@ -92,11 +94,7 @@ impl UTXOCohorts {
|
||||
|
||||
/// Push percentiles + density to cost basis vecs.
|
||||
#[inline(always)]
|
||||
fn push_cost_basis(
|
||||
percentiles: &PercentileResult,
|
||||
density_bps: u16,
|
||||
cost_basis: &mut CostBasis,
|
||||
) {
|
||||
fn push_cost_basis(percentiles: &PercentileResult, density_bps: u16, cost_basis: &mut CostBasis) {
|
||||
cost_basis.push_minmax(percentiles.min_price, percentiles.max_price);
|
||||
cost_basis.push_percentiles(&percentiles.sat_prices, &percentiles.usd_prices);
|
||||
cost_basis.push_density(BasisPoints16::from(density_bps));
|
||||
@@ -108,19 +106,41 @@ fn raw_usd_to_dollars(raw: u128) -> Dollars {
|
||||
Dollars::from(raw as f64 / 1e10)
|
||||
}
|
||||
|
||||
/// Number of profit ranges (0..=14 are profit, 15..=24 are loss).
|
||||
const PROFIT_RANGE_COUNT: usize = 15;
|
||||
|
||||
/// Compute unrealized P&L from raw sats/usd for a given range.
|
||||
/// Profit ranges: market_value - cost_basis. Loss ranges: cost_basis - market_value.
|
||||
#[inline(always)]
|
||||
fn compute_unrealized_pnl(spot_cents: u128, sats: u64, usd: u128, is_profit: bool) -> Dollars {
|
||||
let market_value = spot_cents * sats as u128;
|
||||
let raw = if is_profit {
|
||||
market_value.saturating_sub(usd)
|
||||
} else {
|
||||
usd.saturating_sub(market_value)
|
||||
};
|
||||
raw_usd_to_dollars(raw)
|
||||
}
|
||||
|
||||
/// Push profitability range + profit/loss aggregate values to vecs.
|
||||
fn push_profitability(
|
||||
buckets: &[ProfitabilityRangeResult; PROFITABILITY_RANGE_COUNT],
|
||||
spot_price: Cents,
|
||||
metrics: &mut ProfitabilityMetrics,
|
||||
) {
|
||||
let spot_cents = spot_price.as_u128();
|
||||
|
||||
// Push 25 range buckets
|
||||
for (i, bucket) in metrics.range.as_array_mut().into_iter().enumerate() {
|
||||
let r = &buckets[i];
|
||||
let is_profit = i < PROFIT_RANGE_COUNT;
|
||||
bucket.push(
|
||||
Sats::from(r.all_sats),
|
||||
Sats::from(r.sth_sats),
|
||||
raw_usd_to_dollars(r.all_usd),
|
||||
raw_usd_to_dollars(r.sth_usd),
|
||||
compute_unrealized_pnl(spot_cents, r.all_sats, r.all_usd, is_profit),
|
||||
compute_unrealized_pnl(spot_cents, r.sth_sats, r.sth_usd, is_profit),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -141,6 +161,8 @@ fn push_profitability(
|
||||
Sats::from(cum_sth_sats),
|
||||
raw_usd_to_dollars(cum_usd),
|
||||
raw_usd_to_dollars(cum_sth_usd),
|
||||
compute_unrealized_pnl(spot_cents, cum_sats, cum_usd, true),
|
||||
compute_unrealized_pnl(spot_cents, cum_sth_sats, cum_sth_usd, true),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -163,6 +185,8 @@ fn push_profitability(
|
||||
Sats::from(cum_sth_sats),
|
||||
raw_usd_to_dollars(cum_usd),
|
||||
raw_usd_to_dollars(cum_sth_usd),
|
||||
compute_unrealized_pnl(spot_cents, cum_sats, cum_usd, false),
|
||||
compute_unrealized_pnl(spot_cents, cum_sth_sats, cum_sth_usd, false),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
use brk_cohort::Filter;
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{
|
||||
Dollars, Height, Indexes, Sats, StoredU64, Version,
|
||||
};
|
||||
use brk_types::{Dollars, Height, Indexes, Sats, StoredU64, Version};
|
||||
use vecdb::AnyStoredVec;
|
||||
use vecdb::{Exit, ReadableVec, Rw, StorageMode};
|
||||
|
||||
@@ -87,6 +85,7 @@ impl ExtendedCohortMetrics {
|
||||
})
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub(crate) fn compute_rest_part2(
|
||||
&mut self,
|
||||
blocks: &blocks::Vecs,
|
||||
@@ -126,11 +125,8 @@ impl ExtendedCohortMetrics {
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.unrealized.compute_sentiment(
|
||||
starting_indexes,
|
||||
&prices.spot.cents.height,
|
||||
exit,
|
||||
)?;
|
||||
self.unrealized
|
||||
.compute_sentiment(starting_indexes, &prices.spot.cents.height, exit)?;
|
||||
|
||||
self.relative.compute(
|
||||
starting_indexes.height,
|
||||
@@ -142,9 +138,9 @@ impl ExtendedCohortMetrics {
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.outputs.compute_part2(starting_indexes.height, all_utxo_count, exit)?;
|
||||
self.outputs
|
||||
.compute_part2(starting_indexes.height, all_utxo_count, exit)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ pub struct WithSth<All, Sth = All> {
|
||||
pub struct ProfitabilityBucket<M: StorageMode = Rw> {
|
||||
pub supply: WithSth<AmountPerBlockWithDeltas<M>, AmountPerBlock<M>>,
|
||||
pub realized_cap: WithSth<PerBlock<Dollars, M>>,
|
||||
pub unrealized_pnl: WithSth<PerBlock<Dollars, M>>,
|
||||
pub nupl: RatioPerBlock<BasisPointsSigned32, M>,
|
||||
}
|
||||
|
||||
@@ -31,6 +32,7 @@ impl<M: StorageMode> ProfitabilityBucket<M> {
|
||||
.height
|
||||
.len()
|
||||
.min(self.realized_cap.all.height.len())
|
||||
.min(self.unrealized_pnl.all.height.len())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,6 +74,20 @@ impl ProfitabilityBucket {
|
||||
indexes,
|
||||
)?,
|
||||
},
|
||||
unrealized_pnl: WithSth {
|
||||
all: PerBlock::forced_import(
|
||||
db,
|
||||
&format!("{name}_unrealized_pnl"),
|
||||
version,
|
||||
indexes,
|
||||
)?,
|
||||
sth: PerBlock::forced_import(
|
||||
db,
|
||||
&format!("{name}_sth_unrealized_pnl"),
|
||||
version,
|
||||
indexes,
|
||||
)?,
|
||||
},
|
||||
nupl: RatioPerBlock::forced_import_raw(
|
||||
db,
|
||||
&format!("{name}_nupl"),
|
||||
@@ -88,11 +104,15 @@ impl ProfitabilityBucket {
|
||||
sth_supply: Sats,
|
||||
realized_cap: Dollars,
|
||||
sth_realized_cap: Dollars,
|
||||
unrealized_pnl: Dollars,
|
||||
sth_unrealized_pnl: Dollars,
|
||||
) {
|
||||
self.supply.all.sats.height.push(supply);
|
||||
self.supply.sth.sats.height.push(sth_supply);
|
||||
self.realized_cap.all.height.push(realized_cap);
|
||||
self.realized_cap.sth.height.push(sth_realized_cap);
|
||||
self.unrealized_pnl.all.height.push(unrealized_pnl);
|
||||
self.unrealized_pnl.sth.height.push(sth_unrealized_pnl);
|
||||
}
|
||||
|
||||
pub(crate) fn compute(
|
||||
@@ -138,6 +158,8 @@ impl ProfitabilityBucket {
|
||||
&mut self.supply.sth.cents.height,
|
||||
&mut self.realized_cap.all.height,
|
||||
&mut self.realized_cap.sth.height,
|
||||
&mut self.unrealized_pnl.all.height,
|
||||
&mut self.unrealized_pnl.sth.height,
|
||||
&mut self.nupl.bps.height,
|
||||
]
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
1
website/.gitignore
vendored
1
website/.gitignore
vendored
@@ -2,3 +2,4 @@
|
||||
!scripts/**/_*.js
|
||||
*_old.js
|
||||
_*.js
|
||||
dump-*
|
||||
|
||||
@@ -50,7 +50,7 @@ function volumeTree(tv, color, title) {
|
||||
tree: [
|
||||
...ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: title(`Transfer Volume Profitability (${w.title})`),
|
||||
title: title(`${w.title} Transfer Volume Profitability`),
|
||||
bottom: [
|
||||
...satsBtcUsd({
|
||||
pattern: tv.inProfit.sum[w.key],
|
||||
@@ -157,7 +157,7 @@ function singleRollingSoprTree(ratio, title, prefix = "") {
|
||||
},
|
||||
...ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: title(`${prefix}SOPR (${w.title})`),
|
||||
title: title(`${w.title} ${prefix}SOPR`.trim()),
|
||||
bottom: [
|
||||
baseline({
|
||||
series: ratio[w.key],
|
||||
@@ -228,7 +228,7 @@ function singleSellSideRiskTree(sellSideRisk, title) {
|
||||
},
|
||||
...ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: title(`Sell Side Risk (${w.title})`),
|
||||
title: title(`${w.title} Sell Side Risk`),
|
||||
bottom: percentRatio({
|
||||
pattern: sellSideRisk[w.key],
|
||||
name: "Risk",
|
||||
@@ -509,7 +509,7 @@ function groupedVolumeFolderWithAdjusted(list, all, title, getTransferVolume, ge
|
||||
function groupedSoprCharts(list, all, getRatio, title, prefix = "") {
|
||||
return ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: title(`${prefix}SOPR (${w.title})`),
|
||||
title: title(`${w.title} ${prefix}SOPR`.trim()),
|
||||
bottom: mapCohortsWithAll(list, all, (c) =>
|
||||
baseline({
|
||||
series: getRatio(c)[w.key],
|
||||
@@ -653,7 +653,7 @@ function groupedActivitySharedItems(list, all, title) {
|
||||
name: "Dormancy",
|
||||
tree: ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: title(`Dormancy (${w.title})`),
|
||||
title: title(`${w.title} Dormancy`),
|
||||
bottom: mapCohortsWithAll(list, all, ({ name, color, tree }) =>
|
||||
line({
|
||||
series: tree.activity.dormancy[w.key],
|
||||
@@ -668,7 +668,7 @@ function groupedActivitySharedItems(list, all, title) {
|
||||
name: "Sell Side Risk",
|
||||
tree: ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: title(`Sell Side Risk (${w.title})`),
|
||||
title: title(`${w.title} Sell Side Risk`),
|
||||
bottom: mapCohortsWithAll(list, all, ({ name, color, tree }) =>
|
||||
line({
|
||||
series: tree.realized.sellSideRiskRatio[w.key].ratio,
|
||||
@@ -711,7 +711,7 @@ export function createGroupedActivitySectionWithActivity({ list, all, title }) {
|
||||
tree: [
|
||||
...ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: title(`Coindays Destroyed (${w.title})`),
|
||||
title: title(`${w.title} Coindays Destroyed`),
|
||||
bottom: mapCohortsWithAll(list, all, ({ name, color, tree }) =>
|
||||
line({
|
||||
series: tree.activity.coindaysDestroyed.sum[w.key],
|
||||
|
||||
@@ -108,7 +108,7 @@ function groupedDeltaItems(list, all, getDelta, unit, title, name) {
|
||||
name: "Change",
|
||||
tree: ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: title(`${name} Change (${w.title})`),
|
||||
title: title(`${w.title} ${name} Change`),
|
||||
bottom: mapCohortsWithAll(list, all, (c) =>
|
||||
baseline({
|
||||
series: getDelta(c).absolute[w.key],
|
||||
@@ -123,7 +123,7 @@ function groupedDeltaItems(list, all, getDelta, unit, title, name) {
|
||||
name: "Growth Rate",
|
||||
tree: ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: title(`${name} Growth Rate (${w.title})`),
|
||||
title: title(`${w.title} ${name} Growth Rate`),
|
||||
bottom: flatMapCohortsWithAll(list, all, (c) =>
|
||||
percentRatioBaseline({
|
||||
pattern: getDelta(c).rate[w.key],
|
||||
|
||||
@@ -403,7 +403,7 @@ export function createGroupedCohortFolderAgeRangeWithMatured({
|
||||
name: "Matured",
|
||||
tree: ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: title(`Matured Supply (${w.title})`),
|
||||
title: title(`${w.title} Matured Supply`),
|
||||
bottom: list.flatMap((cohort) =>
|
||||
satsBtcUsd({
|
||||
pattern: cohort.matured.sum[w.key],
|
||||
@@ -617,7 +617,7 @@ function groupedBucketCharts(list, groupTitle) {
|
||||
},
|
||||
...ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: title(`Supply Change (${w.title})`),
|
||||
title: title(`${w.title} Supply Change`),
|
||||
bottom: list.map(({ name, color, pattern }) =>
|
||||
baseline({
|
||||
series: pattern.supply.all.delta.absolute[w.key],
|
||||
@@ -647,7 +647,7 @@ function groupedBucketCharts(list, groupTitle) {
|
||||
},
|
||||
...ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: title(`Supply Growth Rate (${w.title})`),
|
||||
title: title(`${w.title} Supply Growth Rate`),
|
||||
bottom: list.flatMap(({ name, color, pattern }) =>
|
||||
percentRatio({
|
||||
pattern: pattern.supply.all.delta.rate[w.key],
|
||||
|
||||
@@ -315,7 +315,7 @@ function realizedMetricFolder({ pattern, metricTitle, color, title }) {
|
||||
},
|
||||
...ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: title(`Realized ${metricTitle} (${w.title})`),
|
||||
title: title(`${w.title} Realized ${metricTitle}`),
|
||||
bottom: [
|
||||
line({
|
||||
series: pattern.sum[w.key].usd,
|
||||
@@ -366,7 +366,7 @@ function realizedNetFolder({ netPnl, title, extraChange = [] }) {
|
||||
},
|
||||
...ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: title(`Net Realized P&L (${w.title})`),
|
||||
title: title(`${w.title} Net Realized P&L`),
|
||||
bottom: [
|
||||
baseline({
|
||||
series: netPnl.sum[w.key].usd,
|
||||
@@ -433,7 +433,7 @@ function realizedOverviewFolder({
|
||||
name: "Overview",
|
||||
tree: ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: title(`Realized P&L (${w.title})`),
|
||||
title: title(`${w.title} Realized P&L`),
|
||||
bottom: [
|
||||
baseline({
|
||||
series: netPnl.sum[w.key].usd,
|
||||
@@ -576,7 +576,7 @@ function realizedSubfolderFull(r, title) {
|
||||
},
|
||||
...ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: title(`Realized P/L Ratio (${w.title})`),
|
||||
title: title(`${w.title} Realized P/L Ratio`),
|
||||
bottom: [
|
||||
baseline({
|
||||
series: r.profitToLossRatio[w.key],
|
||||
@@ -605,7 +605,7 @@ function realizedSubfolderFull(r, title) {
|
||||
},
|
||||
...ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: title(`Peak Regret (${w.title})`),
|
||||
title: title(`${w.title} Peak Regret`),
|
||||
bottom: [
|
||||
line({
|
||||
series: r.peakRegret.sum[w.key].usd,
|
||||
@@ -937,7 +937,7 @@ function groupedRealizedNetPnlDeltaItems(list, all, title) {
|
||||
name: "Change",
|
||||
tree: ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: title(`Net Realized P&L Change (${w.title})`),
|
||||
title: title(`${w.title} Net Realized P&L Change`),
|
||||
bottom: mapCohortsWithAll(list, all, ({ name, color, tree }) =>
|
||||
baseline({
|
||||
series: tree.realized.netPnl.delta.absolute[w.key].usd,
|
||||
@@ -952,7 +952,7 @@ function groupedRealizedNetPnlDeltaItems(list, all, title) {
|
||||
name: "Growth Rate",
|
||||
tree: ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: title(`Net Realized P&L Growth Rate (${w.title})`),
|
||||
title: title(`${w.title} Net Realized P&L Growth Rate`),
|
||||
bottom: flatMapCohortsWithAll(list, all, ({ name, color, tree }) =>
|
||||
percentRatioBaseline({
|
||||
pattern: tree.realized.netPnl.delta.rate[w.key],
|
||||
@@ -1005,7 +1005,7 @@ function groupedRealizedSubfolderFull(list, all, title) {
|
||||
name: "P/L Ratio",
|
||||
tree: ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: title(`Realized P/L Ratio (${w.title})`),
|
||||
title: title(`${w.title} Realized P/L Ratio`),
|
||||
bottom: mapCohortsWithAll(list, all, (c) =>
|
||||
baseline({
|
||||
series: c.tree.realized.profitToLossRatio[w.key],
|
||||
|
||||
@@ -44,7 +44,7 @@ function groupedDeltaAndMvrv(list, all, title) {
|
||||
name: "Change",
|
||||
tree: ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: title(`Realized Cap Change (${w.title})`),
|
||||
title: title(`${w.title} Realized Cap Change`),
|
||||
bottom: mapCohortsWithAll(list, all, ({ name, color, tree }) =>
|
||||
baseline({ series: tree.realized.cap.delta.absolute[w.key].usd, name, color, unit: Unit.usd }),
|
||||
),
|
||||
@@ -54,7 +54,7 @@ function groupedDeltaAndMvrv(list, all, title) {
|
||||
name: "Growth Rate",
|
||||
tree: ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: title(`Realized Cap Growth Rate (${w.title})`),
|
||||
title: title(`${w.title} Realized Cap Growth Rate`),
|
||||
bottom: flatMapCohortsWithAll(list, all, ({ name, color, tree }) =>
|
||||
percentRatioBaseline({ pattern: tree.realized.cap.delta.rate[w.key], name, color }),
|
||||
),
|
||||
|
||||
@@ -588,7 +588,7 @@ export function createMarketSection() {
|
||||
},
|
||||
...ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: `Capitalization Growth Rate Spread (${w.title})`,
|
||||
title: `${w.title} Capitalization Growth Rate Spread`,
|
||||
bottom: [
|
||||
baseline({
|
||||
series: supply.marketMinusRealizedCapGrowthRate[w.key],
|
||||
@@ -676,7 +676,7 @@ export function createMarketSection() {
|
||||
const rsi = technical.rsi[w.key];
|
||||
return {
|
||||
name: w.name,
|
||||
title: `RSI (${w.title})`,
|
||||
title: `${w.title} RSI`,
|
||||
bottom: [
|
||||
...indexRatio({
|
||||
pattern: rsi.rsi,
|
||||
@@ -699,7 +699,7 @@ export function createMarketSection() {
|
||||
const rsi = technical.rsi[w.key];
|
||||
return {
|
||||
name: w.name,
|
||||
title: `Stochastic RSI (${w.title})`,
|
||||
title: `${w.title} Stochastic RSI`,
|
||||
bottom: [
|
||||
...indexRatio({
|
||||
pattern: rsi.stochRsiK,
|
||||
@@ -738,7 +738,7 @@ export function createMarketSection() {
|
||||
},
|
||||
...ROLLING_WINDOWS_TO_1M.map((w) => ({
|
||||
name: w.name,
|
||||
title: `MACD (${w.title})`,
|
||||
title: `${w.title} MACD`,
|
||||
bottom: [
|
||||
line({
|
||||
series: technical.macd[w.key].line,
|
||||
@@ -785,7 +785,7 @@ export function createMarketSection() {
|
||||
},
|
||||
...ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: `Volatility Index (${w.title})`,
|
||||
title: `${w.title} Volatility Index`,
|
||||
bottom: [
|
||||
line({
|
||||
series: volatility[w.key],
|
||||
|
||||
@@ -97,7 +97,7 @@ export function createMiningSection() {
|
||||
},
|
||||
...ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: title(`${w.name} ${metric}`),
|
||||
title: title(`${w.title} ${metric}`),
|
||||
bottom: percentRatio({ pattern: dominance[w.key], name: w.name, color: w.color }),
|
||||
})),
|
||||
{
|
||||
@@ -177,7 +177,7 @@ export function createMiningSection() {
|
||||
name: "Dominance",
|
||||
tree: ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: `Dominance: ${groupTitle} ${w.title}`,
|
||||
title: formatCohortTitle(groupTitle)(`${w.title} Dominance`),
|
||||
bottom: poolList.flatMap((p, i) =>
|
||||
percentRatio({
|
||||
pattern: p.pool.dominance[w.key],
|
||||
@@ -191,7 +191,7 @@ export function createMiningSection() {
|
||||
name: "Blocks Mined",
|
||||
tree: ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: `Blocks Mined: ${groupTitle} ${w.title} Sum`,
|
||||
title: formatCohortTitle(groupTitle)(`${w.title} Blocks Mined`),
|
||||
bottom: poolList.map((p, i) =>
|
||||
line({
|
||||
series: p.pool.blocksMined.sum[w.key],
|
||||
@@ -299,7 +299,7 @@ export function createMiningSection() {
|
||||
tree: [
|
||||
...ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: `Revenue ${w.title} Averages`,
|
||||
title: `${w.title} Revenue`,
|
||||
bottom: revenueRollingBtcSatsUsd({
|
||||
coinbase: mining.rewards.coinbase.average[w.key],
|
||||
subsidy: mining.rewards.subsidy.average[w.key],
|
||||
@@ -341,7 +341,7 @@ export function createMiningSection() {
|
||||
name: "Distributions",
|
||||
tree: ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: `Fee Revenue per Block ${w.title} Distribution`,
|
||||
title: `${w.title} Fee Revenue per Block Distribution`,
|
||||
bottom: distributionBtcSatsUsd(statsAtWindow(mining.rewards.fees, w.key)),
|
||||
})),
|
||||
},
|
||||
@@ -352,7 +352,7 @@ export function createMiningSection() {
|
||||
tree: [
|
||||
...ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: `Revenue Dominance ${w.title}`,
|
||||
title: `${w.title} Revenue Dominance`,
|
||||
bottom: [
|
||||
...percentRatio({ pattern: mining.rewards.subsidy.dominance[w.key], name: "Subsidy", color: colors.mining.subsidy }),
|
||||
...percentRatio({ pattern: mining.rewards.fees.dominance[w.key], name: "Fees", color: colors.mining.fee }),
|
||||
@@ -372,7 +372,7 @@ export function createMiningSection() {
|
||||
name: "Fee Multiple",
|
||||
tree: ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: `Fee-to-Subsidy Ratio ${w.title}`,
|
||||
title: `${w.title} Fee-to-Subsidy Ratio`,
|
||||
bottom: [line({ series: mining.rewards.fees.toSubsidyRatio[w.key].ratio, name: "Ratio", color: colors.mining.fee, unit: Unit.ratio })],
|
||||
})),
|
||||
},
|
||||
|
||||
@@ -162,7 +162,7 @@ export function createNetworkSection() {
|
||||
name: "Compare",
|
||||
tree: ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: `${titlePrefix}Active Addresses ${w.title} Average`,
|
||||
title: `${w.title} ${titlePrefix}Active Addresses`,
|
||||
bottom: activityTypes.map((t, i) =>
|
||||
line({
|
||||
series: addrs.activity[key][t.key][w.key],
|
||||
@@ -213,7 +213,7 @@ export function createNetworkSection() {
|
||||
tree: [
|
||||
...ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: `${groupName} Output Count ${w.title} Sum`,
|
||||
title: `${w.title} ${groupName} Output Count`,
|
||||
bottom: types.map((t) =>
|
||||
line({
|
||||
series: /** @type {CountPattern<number>} */ (
|
||||
@@ -402,7 +402,7 @@ export function createNetworkSection() {
|
||||
},
|
||||
...ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: `Block Count ${w.title}`,
|
||||
title: `${w.title} Block Count`,
|
||||
bottom: [
|
||||
line({
|
||||
series: blocks.count.total.sum[w.key],
|
||||
@@ -531,7 +531,7 @@ export function createNetworkSection() {
|
||||
name: "Throughput",
|
||||
tree: ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: `Throughput ${w.title} Average`,
|
||||
title: `${w.title} Throughput`,
|
||||
bottom: [
|
||||
line({
|
||||
series: transactions.volume.txPerSec[w.key],
|
||||
@@ -597,7 +597,7 @@ export function createNetworkSection() {
|
||||
tree: [
|
||||
...ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: `Output Count by Script Type ${w.title} Sum`,
|
||||
title: `${w.title} Output Count by Script Type`,
|
||||
bottom: scriptTypes.map((t) =>
|
||||
line({
|
||||
series: /** @type {CountPattern<number>} */ (
|
||||
|
||||
@@ -519,7 +519,7 @@ export function sumsAndAveragesCumulativeWith({
|
||||
},
|
||||
...ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: title(`${w.name} ${metric}`),
|
||||
title: title(`${w.title} ${metric}`),
|
||||
bottom: [
|
||||
...series({ pattern: sum[w.key], name: "Sum", color: w.color }),
|
||||
...series({
|
||||
@@ -551,7 +551,7 @@ export function sumsAndAveragesCumulativeWith({
|
||||
export function sumsAndAveragesArray({ sum, average, title = (s) => s, metric, unit }) {
|
||||
return ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: title(`${w.name} ${metric}`),
|
||||
title: title(`${w.title} ${metric}`),
|
||||
bottom: [
|
||||
line({ series: sum[w.key], name: "Sum", color: w.color, unit }),
|
||||
line({
|
||||
@@ -611,7 +611,7 @@ export function sumsTreeBaseline({ windows, title = (s) => s, metric, unit }) {
|
||||
return rollingWindowsTreeBaseline({
|
||||
windows,
|
||||
title: title(metric),
|
||||
windowTitle: (w) => title(`${w.name} ${metric}`),
|
||||
windowTitle: (w) => title(`${w.title} ${metric}`),
|
||||
unit,
|
||||
name: "Sums",
|
||||
});
|
||||
@@ -637,7 +637,7 @@ export function averagesArray({ windows, title = (s) => s, metric, unit }) {
|
||||
},
|
||||
...ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: title(`${w.name} ${metric}`),
|
||||
title: title(`${w.title} ${metric}`),
|
||||
bottom: [
|
||||
line({ series: windows[w.key], name: w.name, color: w.color, unit }),
|
||||
],
|
||||
@@ -673,7 +673,7 @@ export function distributionWindowsTree({ pattern, base, title = (s) => s, metri
|
||||
},
|
||||
...ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: title(`${w.name} ${metric} Distribution`),
|
||||
title: title(`${w.title} ${metric} Distribution`),
|
||||
bottom: [
|
||||
...(base ? [line({ series: base, name: "base", unit })] : []),
|
||||
...percentileSeries({ pattern: statsAtWindow(pattern, w.key), unit }),
|
||||
@@ -870,7 +870,7 @@ export function rollingPercentRatioTree({
|
||||
},
|
||||
...ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: title(`${w.name} ${metric}`),
|
||||
title: title(`${w.title} ${metric}`),
|
||||
bottom: percentRatioBaseline({ pattern: windows[w.key], name: w.name }),
|
||||
})),
|
||||
],
|
||||
@@ -907,7 +907,7 @@ export function deltaTree({ delta, title = (s) => s, metric, unit, extract }) {
|
||||
},
|
||||
...ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: title(`${w.name} ${metric} Change`),
|
||||
title: title(`${w.title} ${metric} Change`),
|
||||
bottom: [
|
||||
baseline({
|
||||
series: extract(delta.absolute[w.key]),
|
||||
@@ -1106,7 +1106,7 @@ export function chartsFromCountEntries({ entries, title = (s) => s, metric, unit
|
||||
return [
|
||||
...ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: title(`${w.name} ${metric}`),
|
||||
title: title(`${w.title} ${metric}`),
|
||||
bottom: items.map((e) =>
|
||||
line({ series: e.sum[w.key], name: e.name, color: e.color, unit }),
|
||||
),
|
||||
@@ -1134,7 +1134,7 @@ export function multiSeriesTree({ entries, title = (s) => s, metric, unit }) {
|
||||
return [
|
||||
...ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: title(`${w.name} ${metric}`),
|
||||
title: title(`${w.title} ${metric}`),
|
||||
bottom: entries.map((e) =>
|
||||
line({ series: e.average[w.key], name: e.name, color: e.color, unit }),
|
||||
),
|
||||
|
||||
@@ -775,7 +775,7 @@ export function groupedWindowsCumulative({ list, all, title, metricTitle, getWin
|
||||
return [
|
||||
...ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: title(`${metricTitle} (${w.title})`),
|
||||
title: title(`${w.title} ${metricTitle}`),
|
||||
bottom: mapCohortsWithAll(list, all, (c) =>
|
||||
seriesFn({ series: getWindowSeries(c, w.key), name: c.name, color: c.color, unit }),
|
||||
),
|
||||
@@ -827,7 +827,7 @@ export function groupedWindowsCumulativeSatsBtcUsd({ list, all, title, metricTit
|
||||
return [
|
||||
...ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: title(`${metricTitle} (${w.title})`),
|
||||
title: title(`${w.title} ${metricTitle}`),
|
||||
bottom: flatMapCohortsWithAll(list, all, (c) =>
|
||||
satsBtcUsd({ pattern: getMetric(c).sum[w.key], name: c.name, color: c.color }),
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user