global: snapshot

This commit is contained in:
nym21
2026-03-14 14:00:03 +01:00
parent d53e533c9f
commit 7bcc32fea1
31 changed files with 413 additions and 287 deletions

View File

@@ -2,8 +2,7 @@
import { colors } from "../utils/colors.js";
import { brk } from "../client.js";
import { Unit } from "../utils/units.js";
import { baseline, price } from "./series.js";
import { percentRatioBaseline, price } from "./series.js";
import { satsBtcUsd } from "./shared.js";
import { periodIdToName } from "./utils.js";
@@ -31,7 +30,7 @@ const LONG_PERIODS = /** @type {const} */ ([
/**
* Add CAGR to a base entry item
* @param {BaseEntryItem} entry
* @param {AnyMetricPattern} cagr
* @param {PercentRatioPattern} cagr
* @returns {LongEntryItem}
*/
const withCagr = (entry, cagr) => ({ ...entry, cagr });
@@ -47,19 +46,23 @@ const YEARS_2010S = /** @type {const} */ ([2019, 2018, 2017, 2016, 2015]);
/** @param {AllPeriodKey} key */
const periodName = (key) => periodIdToName(key.slice(1), true);
/**
* @typedef {{ percent: AnyMetricPattern, ratio: AnyMetricPattern }} PercentRatioPattern
*/
/**
* Base entry item for compare and single-entry charts
* @typedef {Object} BaseEntryItem
* @property {string} name - Display name
* @property {Color} color - Item color
* @property {AnyPricePattern} costBasis - Cost basis metric
* @property {AnyMetricPattern} returns - Returns metric
* @property {PercentRatioPattern} returns - Returns metric
* @property {AnyValuePattern} stack - Stack pattern
*/
/**
* Long-term entry item with CAGR
* @typedef {BaseEntryItem & { cagr: AnyMetricPattern }} LongEntryItem
* @typedef {BaseEntryItem & { cagr: PercentRatioPattern }} LongEntryItem
*/
const ALL_YEARS = /** @type {const} */ ([...YEARS_2020S, ...YEARS_2010S]);
@@ -77,7 +80,7 @@ function buildYearEntry(dca, year, i) {
name: `${year}`,
color: colors.at(i, ALL_YEARS.length),
costBasis: dca.class.costBasis[key],
returns: dca.class.return[key].ratio,
returns: dca.class.return[key],
stack: dca.class.stack[key],
};
}
@@ -122,12 +125,11 @@ function createCompareFolder(context, items) {
name: "Returns",
title: `Returns: ${context}`,
top: topPane,
bottom: items.map(({ name, color, returns }) =>
baseline({
metric: returns,
bottom: items.flatMap(({ name, color, returns }) =>
percentRatioBaseline({
pattern: returns,
name,
color: [color, color],
unit: Unit.percentage,
}),
),
},
@@ -176,9 +178,7 @@ function createSingleEntryTree(item, returnsBottom) {
* @param {BaseEntryItem & { titlePrefix?: string }} item
*/
function createShortSingleEntry(item) {
return createSingleEntryTree(item, [
baseline({ metric: item.returns, name: "Current", unit: Unit.percentage }),
]);
return createSingleEntryTree(item, percentRatioBaseline({ pattern: item.returns, name: "Current" }));
}
/**
@@ -187,8 +187,8 @@ function createShortSingleEntry(item) {
*/
function createLongSingleEntry(item) {
return createSingleEntryTree(item, [
baseline({ metric: item.returns, name: "Current", unit: Unit.percentage }),
baseline({ metric: item.cagr, name: "CAGR", unit: Unit.cagr }),
...percentRatioBaseline({ pattern: item.returns, name: "Current" }),
...percentRatioBaseline({ pattern: item.cagr, name: "CAGR" }),
]);
}
@@ -223,16 +223,14 @@ export function createDcaVsLumpSumSection({ dca, lookback, returns }) {
title: `Returns: ${name} DCA vs Lump Sum`,
top: topPane(key),
bottom: [
baseline({
metric: dca.period.return[key].ratio,
...percentRatioBaseline({
pattern: dca.period.return[key],
name: "DCA",
unit: Unit.percentage,
}),
baseline({
metric: dca.period.lumpSumReturn[key].ratio,
...percentRatioBaseline({
pattern: dca.period.lumpSumReturn[key],
name: "Lump Sum",
color: colors.bi.p2,
unit: Unit.percentage,
}),
],
});
@@ -243,27 +241,23 @@ export function createDcaVsLumpSumSection({ dca, lookback, returns }) {
title: `Returns: ${name} DCA vs Lump Sum`,
top: topPane(key),
bottom: [
baseline({
metric: dca.period.return[key].ratio,
...percentRatioBaseline({
pattern: dca.period.return[key],
name: "DCA",
unit: Unit.percentage,
}),
baseline({
metric: dca.period.lumpSumReturn[key].ratio,
...percentRatioBaseline({
pattern: dca.period.lumpSumReturn[key],
name: "Lump Sum",
color: colors.bi.p2,
unit: Unit.percentage,
}),
baseline({
metric: dca.period.cagr[key].ratio,
...percentRatioBaseline({
pattern: dca.period.cagr[key],
name: "DCA CAGR",
unit: Unit.cagr,
}),
baseline({
metric: returns.cagr[key].ratio,
...percentRatioBaseline({
pattern: returns.cagr[key],
name: "Lump Sum CAGR",
color: colors.bi.p2,
unit: Unit.cagr,
}),
],
});
@@ -350,8 +344,8 @@ function createPeriodSection({ dca, lookback, returns }) {
color: colors.at(i, allPeriods.length),
costBasis: isLumpSum ? lookback[key] : dca.period.costBasis[key],
returns: isLumpSum
? dca.period.lumpSumReturn[key].ratio
: dca.period.return[key].ratio,
? dca.period.lumpSumReturn[key]
: dca.period.return[key],
stack: isLumpSum
? dca.period.lumpSumStack[key]
: dca.period.stack[key],
@@ -361,7 +355,7 @@ function createPeriodSection({ dca, lookback, returns }) {
const buildLongEntry = (key, i) =>
withCagr(
buildBaseEntry(key, i),
isLumpSum ? returns.cagr[key].ratio : dca.period.cagr[key].ratio,
isLumpSum ? returns.cagr[key] : dca.period.cagr[key],
);
/** @param {BaseEntryItem} entry */

View File

@@ -122,21 +122,18 @@ function returnsSubSection(name, periods) {
{
name: "Compare",
title: `${name} Returns`,
bottom: periods.map((p) =>
baseline({
metric: p.returns,
bottom: periods.flatMap((p) =>
percentRatioBaseline({
pattern: p.returns,
name: p.id,
color: p.color,
unit: Unit.percentage,
}),
),
},
...periods.map((p) => ({
name: periodIdToName(p.id, true),
title: `${periodIdToName(p.id, true)} Returns`,
bottom: [
baseline({ metric: p.returns, name: "Total", unit: Unit.percentage }),
],
bottom: percentRatioBaseline({ pattern: p.returns, name: "Total" }),
})),
],
};
@@ -153,12 +150,11 @@ function returnsSubSectionWithCagr(name, periods) {
{
name: "Compare",
title: `${name} Returns`,
bottom: periods.map((p) =>
baseline({
metric: p.returns,
bottom: periods.flatMap((p) =>
percentRatioBaseline({
pattern: p.returns,
name: p.id,
color: p.color,
unit: Unit.percentage,
}),
),
},
@@ -166,8 +162,8 @@ function returnsSubSectionWithCagr(name, periods) {
name: periodIdToName(p.id, true),
title: `${periodIdToName(p.id, true)} Returns`,
bottom: [
baseline({ metric: p.returns, name: "Total", unit: Unit.percentage }),
baseline({ metric: p.cagr, name: "annual", unit: Unit.cagr }),
...percentRatioBaseline({ pattern: p.returns, name: "Total" }),
...percentRatioBaseline({ pattern: p.cagr, name: "annual" }),
],
})),
],
@@ -216,70 +212,70 @@ export function createMarketSection() {
} = market;
const shortPeriodsBase = [
{ id: "24h", returns: returns.periods._24h.ratio, lookback: lookback._24h },
{ id: "1w", returns: returns.periods._1w.ratio, lookback: lookback._1w },
{ id: "1m", returns: returns.periods._1m.ratio, lookback: lookback._1m },
{ id: "24h", returns: returns.periods._24h, lookback: lookback._24h },
{ id: "1w", returns: returns.periods._1w, lookback: lookback._1w },
{ id: "1m", returns: returns.periods._1m, lookback: lookback._1m },
{
id: "3m",
returns: returns.periods._3m.ratio,
returns: returns.periods._3m,
lookback: lookback._3m,
defaultActive: false,
},
{
id: "6m",
returns: returns.periods._6m.ratio,
returns: returns.periods._6m,
lookback: lookback._6m,
defaultActive: false,
},
{ id: "1y", returns: returns.periods._1y.ratio, lookback: lookback._1y },
{ id: "1y", returns: returns.periods._1y, lookback: lookback._1y },
];
const longPeriodsBase = [
{
id: "2y",
returns: returns.periods._2y.ratio,
cagr: returns.cagr._2y.ratio,
returns: returns.periods._2y,
cagr: returns.cagr._2y,
lookback: lookback._2y,
defaultActive: false,
},
{
id: "3y",
returns: returns.periods._3y.ratio,
cagr: returns.cagr._3y.ratio,
returns: returns.periods._3y,
cagr: returns.cagr._3y,
lookback: lookback._3y,
defaultActive: false,
},
{
id: "4y",
returns: returns.periods._4y.ratio,
cagr: returns.cagr._4y.ratio,
returns: returns.periods._4y,
cagr: returns.cagr._4y,
lookback: lookback._4y,
},
{
id: "5y",
returns: returns.periods._5y.ratio,
cagr: returns.cagr._5y.ratio,
returns: returns.periods._5y,
cagr: returns.cagr._5y,
lookback: lookback._5y,
defaultActive: false,
},
{
id: "6y",
returns: returns.periods._6y.ratio,
cagr: returns.cagr._6y.ratio,
returns: returns.periods._6y,
cagr: returns.cagr._6y,
lookback: lookback._6y,
defaultActive: false,
},
{
id: "8y",
returns: returns.periods._8y.ratio,
cagr: returns.cagr._8y.ratio,
returns: returns.periods._8y,
cagr: returns.cagr._8y,
lookback: lookback._8y,
defaultActive: false,
},
{
id: "10y",
returns: returns.periods._10y.ratio,
cagr: returns.cagr._10y.ratio,
returns: returns.periods._10y,
cagr: returns.cagr._10y,
lookback: lookback._10y,
defaultActive: false,
},
@@ -426,11 +422,10 @@ export function createMarketSection() {
name: "Growth Rate",
title: "Capitalization Growth Rate",
bottom: [
line({
metric: supply.marketCap.delta.rate._24h.percent,
...percentRatio({
pattern: supply.marketCap.delta.rate._24h,
name: "Market Cap (24h)",
color: colors.bitcoin,
unit: Unit.percentage,
}),
baseline({
metric: supply.marketMinusRealizedCapGrowthRate._24h,
@@ -493,12 +488,11 @@ export function createMarketSection() {
{
name: "Compare",
title: "Returns Comparison",
bottom: [...shortPeriods, ...longPeriods].map((p) =>
baseline({
metric: p.returns,
bottom: [...shortPeriods, ...longPeriods].flatMap((p) =>
percentRatioBaseline({
pattern: p.returns,
name: p.id,
color: p.color,
unit: Unit.percentage,
defaultActive: p.defaultActive,
}),
),

View File

@@ -320,7 +320,7 @@ export function createMiningSection() {
title: "Mining Difficulty",
bottom: [
line({
metric: blocks.difficulty.raw,
metric: blocks.difficulty.value,
name: "Difficulty",
unit: Unit.difficulty,
}),

View File

@@ -58,9 +58,9 @@ export function createNetworkSection() {
const nonAddressableTypes = /** @type {const} */ ([
{ key: "p2ms", name: "P2MS", color: st.p2ms, defaultActive: false },
{
key: "opreturn",
key: "opReturn",
name: "OP_RETURN",
color: st.opreturn,
color: st.opReturn,
defaultActive: false,
},
{
@@ -568,7 +568,7 @@ export function createNetworkSection() {
name: "Base",
title: "OP_RETURN Burned",
bottom: satsBtcUsd({
pattern: supply.burned.opreturn.base,
pattern: supply.burned.opReturn.base,
name: "sum",
}),
},
@@ -580,7 +580,7 @@ export function createNetworkSection() {
title: "OP_RETURN Burned Rolling",
bottom: ROLLING_WINDOWS.flatMap((w) =>
satsBtcUsd({
pattern: supply.burned.opreturn.sum[w.key],
pattern: supply.burned.opReturn.sum[w.key],
name: w.name,
color: w.color,
}),
@@ -590,7 +590,7 @@ export function createNetworkSection() {
name: w.name,
title: `OP_RETURN Burned ${w.name}`,
bottom: satsBtcUsd({
pattern: supply.burned.opreturn.sum[w.key],
pattern: supply.burned.opReturn.sum[w.key],
name: w.name,
color: w.color,
}),
@@ -601,7 +601,7 @@ export function createNetworkSection() {
name: "Cumulative",
title: "OP_RETURN Burned (Total)",
bottom: satsBtcUsd({
pattern: supply.burned.opreturn.cumulative,
pattern: supply.burned.opReturn.cumulative,
name: "all-time",
}),
},
@@ -1035,7 +1035,7 @@ export function createNetworkSection() {
title: "Mining Difficulty",
bottom: [
line({
metric: blocks.difficulty.base,
metric: blocks.difficulty.value,
name: "Difficulty",
unit: Unit.count,
}),

View File

@@ -640,7 +640,7 @@ export function percentRatioDots({ pattern, name, color, defaultActive }) {
* @param {Object} args
* @param {{ percent: AnyMetricPattern, ratio: AnyMetricPattern }} args.pattern
* @param {string} args.name
* @param {Color} [args.color]
* @param {Color | [Color, Color]} [args.color]
* @param {boolean} [args.defaultActive]
* @returns {AnyFetchedSeriesBlueprint[]}
*/