global: snapshot

This commit is contained in:
nym21
2026-02-12 22:52:57 +01:00
parent 3bc20a0a46
commit b779edc0d6
60 changed files with 8720 additions and 1504 deletions

View File

@@ -367,21 +367,21 @@ export function createActivitySection({
line({
metric: tree.activity.sent14dEma.sats,
name: "14d EMA",
color: colors.ma._14d,
color: colors.indicator.main,
unit: Unit.sats,
defaultActive: false,
}),
line({
metric: tree.activity.sent14dEma.bitcoin,
name: "14d EMA",
color: colors.ma._14d,
color: colors.indicator.main,
unit: Unit.btc,
defaultActive: false,
}),
line({
metric: tree.activity.sent14dEma.dollars,
name: "14d EMA",
color: colors.ma._14d,
color: colors.indicator.main,
unit: Unit.usd,
defaultActive: false,
}),
@@ -814,13 +814,13 @@ function createSingleSellSideRiskSeries(tree) {
line({
metric: tree.realized.sellSideRiskRatio30dEma,
name: "30d EMA",
color: colors.ma._1m,
color: colors.time._1m,
unit: Unit.ratio,
}),
line({
metric: tree.realized.sellSideRiskRatio7dEma,
name: "7d EMA",
color: colors.ma._1w,
color: colors.time._1w,
unit: Unit.ratio,
}),
dots({

View File

@@ -11,118 +11,30 @@
*/
import { colors } from "../../utils/colors.js";
import { entries } from "../../utils/array.js";
import { Unit } from "../../utils/units.js";
import { priceLines } from "../constants.js";
import { line, price } from "../series.js";
import { mapCohortsWithAll } from "../shared.js";
const ACTIVE_PCTS = new Set(["pct75", "pct50", "pct25"]);
/**
* @param {PercentilesPattern} p
* @param {(name: string) => string} [n]
* @returns {FetchedPriceSeriesBlueprint[]}
*/
function createCorePercentileSeries(p, n = (x) => x) {
return [
price({
metric: p.pct95,
name: n("p95"),
color: colors.pct._95,
defaultActive: false,
}),
price({
metric: p.pct90,
name: n("p90"),
color: colors.pct._90,
defaultActive: false,
}),
price({
metric: p.pct85,
name: n("p85"),
color: colors.pct._85,
defaultActive: false,
}),
price({
metric: p.pct80,
name: n("p80"),
color: colors.pct._80,
defaultActive: false,
}),
price({ metric: p.pct75, name: n("p75"), color: colors.pct._75 }),
price({
metric: p.pct70,
name: n("p70"),
color: colors.pct._70,
defaultActive: false,
}),
price({
metric: p.pct65,
name: n("p65"),
color: colors.pct._65,
defaultActive: false,
}),
price({
metric: p.pct60,
name: n("p60"),
color: colors.pct._60,
defaultActive: false,
}),
price({
metric: p.pct55,
name: n("p55"),
color: colors.pct._55,
defaultActive: false,
}),
price({ metric: p.pct50, name: n("p50"), color: colors.pct._50 }),
price({
metric: p.pct45,
name: n("p45"),
color: colors.pct._45,
defaultActive: false,
}),
price({
metric: p.pct40,
name: n("p40"),
color: colors.pct._40,
defaultActive: false,
}),
price({
metric: p.pct35,
name: n("p35"),
color: colors.pct._35,
defaultActive: false,
}),
price({
metric: p.pct30,
name: n("p30"),
color: colors.pct._30,
defaultActive: false,
}),
price({ metric: p.pct25, name: n("p25"), color: colors.pct._25 }),
price({
metric: p.pct20,
name: n("p20"),
color: colors.pct._20,
defaultActive: false,
}),
price({
metric: p.pct15,
name: n("p15"),
color: colors.pct._15,
defaultActive: false,
}),
price({
metric: p.pct10,
name: n("p10"),
color: colors.pct._10,
defaultActive: false,
}),
price({
metric: p.pct05,
name: n("p05"),
color: colors.pct._05,
defaultActive: false,
}),
];
return entries(p)
.reverse()
.map(([key, metric], i, arr) =>
price({
metric,
name: n(key.replace("pct", "p")),
color: colors.at(i, arr.length),
...(ACTIVE_PCTS.has(key) ? {} : { defaultActive: false }),
}),
);
}
/**
@@ -136,13 +48,13 @@ function createSingleSummarySeriesBasic(cohort) {
price({
metric: tree.costBasis.max,
name: "Max",
color: colors.pct._100,
color: colors.stat.max,
defaultActive: false,
}),
price({
metric: tree.costBasis.min,
name: "Min",
color: colors.pct._0,
color: colors.stat.min,
defaultActive: false,
}),
];
@@ -160,26 +72,26 @@ function createSingleSummarySeriesWithPercentiles(cohort) {
price({
metric: tree.costBasis.max,
name: "Max (p100)",
color: colors.pct._100,
color: colors.stat.max,
defaultActive: false,
}),
price({
metric: p.pct75,
name: "Q3 (p75)",
color: colors.pct._75,
color: colors.stat.pct75,
defaultActive: false,
}),
price({ metric: p.pct50, name: "Median (p50)", color: colors.pct._50 }),
price({ metric: p.pct50, name: "Median (p50)", color: colors.stat.median }),
price({
metric: p.pct25,
name: "Q1 (p25)",
color: colors.pct._25,
color: colors.stat.pct25,
defaultActive: false,
}),
price({
metric: tree.costBasis.min,
name: "Min (p0)",
color: colors.pct._0,
color: colors.stat.min,
defaultActive: false,
}),
];
@@ -208,14 +120,14 @@ function createSingleByCoinSeries(cohort) {
price({
metric: cb.max,
name: "p100",
color: colors.pct._100,
color: colors.stat.max,
defaultActive: false,
}),
...createCorePercentileSeries(cb.percentiles),
price({
metric: cb.min,
name: "p0",
color: colors.pct._0,
color: colors.stat.min,
defaultActive: false,
}),
];

View File

@@ -67,68 +67,72 @@ export function buildCohortData() {
};
// Max age cohorts (up to X time)
const upToDate = entries(utxoCohorts.maxAge).map(([key, tree]) => {
const upToDate = entries(utxoCohorts.maxAge).map(([key, tree], i, arr) => {
const names = MAX_AGE_NAMES[key];
return {
name: names.short,
title: `UTXOs ${names.long}`,
color: colors.age[key],
color: colors.at(i, arr.length),
tree,
};
});
// Min age cohorts (from X time)
const fromDate = entries(utxoCohorts.minAge).map(([key, tree]) => {
const fromDate = entries(utxoCohorts.minAge).map(([key, tree], i, arr) => {
const names = MIN_AGE_NAMES[key];
return {
name: names.short,
title: `UTXOs ${names.long}`,
color: colors.age[key],
color: colors.at(i, arr.length),
tree,
};
});
// Age range cohorts
const dateRange = entries(utxoCohorts.ageRange).map(([key, tree]) => {
const names = AGE_RANGE_NAMES[key];
return {
name: names.short,
title: `UTXOs ${names.long}`,
color: colors.ageRange[key],
tree,
};
});
const dateRange = entries(utxoCohorts.ageRange).map(
([key, tree], i, arr) => {
const names = AGE_RANGE_NAMES[key];
return {
name: names.short,
title: `UTXOs ${names.long}`,
color: colors.at(i, arr.length),
tree,
};
},
);
// Epoch cohorts
const epoch = entries(utxoCohorts.epoch).map(([key, tree]) => {
const epoch = entries(utxoCohorts.epoch).map(([key, tree], i, arr) => {
const names = EPOCH_NAMES[key];
return {
name: names.short,
title: names.long,
color: colors.epoch[key],
color: colors.at(i, arr.length),
tree,
};
});
// UTXOs above amount
const utxosAboveAmount = entries(utxoCohorts.geAmount).map(([key, tree]) => {
const names = GE_AMOUNT_NAMES[key];
return {
name: names.short,
title: `UTXOs ${names.long}`,
color: colors.amount[key],
tree,
};
});
const utxosAboveAmount = entries(utxoCohorts.geAmount).map(
([key, tree], i, arr) => {
const names = GE_AMOUNT_NAMES[key];
return {
name: names.short,
title: `UTXOs ${names.long}`,
color: colors.at(i, arr.length),
tree,
};
},
);
// Addresses above amount
const addressesAboveAmount = entries(addressCohorts.geAmount).map(
([key, cohort]) => {
([key, cohort], i, arr) => {
const names = GE_AMOUNT_NAMES[key];
return {
name: names.short,
title: `Addresses ${names.long}`,
color: colors.amount[key],
color: colors.at(i, arr.length),
tree: cohort,
addrCount: {
count: cohort.addrCount,
@@ -139,24 +143,26 @@ export function buildCohortData() {
);
// UTXOs under amount
const utxosUnderAmount = entries(utxoCohorts.ltAmount).map(([key, tree]) => {
const names = LT_AMOUNT_NAMES[key];
return {
name: names.short,
title: `UTXOs ${names.long}`,
color: colors.amount[key],
tree,
};
});
const utxosUnderAmount = entries(utxoCohorts.ltAmount).map(
([key, tree], i, arr) => {
const names = LT_AMOUNT_NAMES[key];
return {
name: names.short,
title: `UTXOs ${names.long}`,
color: colors.at(i, arr.length),
tree,
};
},
);
// Addresses under amount
const addressesUnderAmount = entries(addressCohorts.ltAmount).map(
([key, cohort]) => {
([key, cohort], i, arr) => {
const names = LT_AMOUNT_NAMES[key];
return {
name: names.short,
title: `Addresses ${names.long}`,
color: colors.amount[key],
color: colors.at(i, arr.length),
tree: cohort,
addrCount: {
count: cohort.addrCount,
@@ -168,12 +174,12 @@ export function buildCohortData() {
// UTXOs amount ranges
const utxosAmountRanges = entries(utxoCohorts.amountRange).map(
([key, tree]) => {
([key, tree], i, arr) => {
const names = AMOUNT_RANGE_NAMES[key];
return {
name: names.short,
title: `UTXOs ${names.long}`,
color: colors.amountRange[key],
color: colors.at(i, arr.length),
tree,
};
},
@@ -181,12 +187,12 @@ export function buildCohortData() {
// Addresses amount ranges
const addressesAmountRanges = entries(addressCohorts.amountRange).map(
([key, cohort]) => {
([key, cohort], i, arr) => {
const names = AMOUNT_RANGE_NAMES[key];
return {
name: names.short,
title: `Addresses ${names.long}`,
color: colors.amountRange[key],
color: colors.at(i, arr.length),
tree: cohort,
addrCount: {
count: cohort.addrCount,
@@ -197,12 +203,12 @@ export function buildCohortData() {
);
// Spendable type cohorts - split by addressability
const typeAddressable = ADDRESSABLE_TYPES.map((key) => {
const typeAddressable = ADDRESSABLE_TYPES.map((key, i, arr) => {
const names = SPENDABLE_TYPE_NAMES[key];
return {
name: names.short,
title: names.short,
color: colors.scriptType[key],
color: colors.at(i, arr.length),
tree: utxoCohorts.type[key],
addrCount: addrCount[key],
};
@@ -210,26 +216,28 @@ export function buildCohortData() {
const typeOther = entries(utxoCohorts.type)
.filter(([key]) => !isAddressable(key))
.map(([key, tree]) => {
.map(([key, tree], i, arr) => {
const names = SPENDABLE_TYPE_NAMES[key];
return {
name: names.short,
title: names.short,
color: colors.scriptType[key],
color: colors.at(i, arr.length),
tree,
};
});
// Year cohorts
const year = entries(utxoCohorts.year).map(([key, tree]) => {
const names = YEAR_NAMES[key];
return {
name: names.short,
title: names.long,
color: colors.year[key],
tree,
};
});
const year = entries(utxoCohorts.year)
.reverse()
.map(([key, tree], i, arr) => {
const names = YEAR_NAMES[key];
return {
name: names.short,
title: names.long,
color: colors.at(i, arr.length),
tree,
};
});
return {
cohortAll,

View File

@@ -91,7 +91,7 @@ export function createValuationSectionFull({ cohort, title }) {
* @returns {PartialOptionsGroup}
*/
export function createValuationSection({ cohort, title }) {
const { tree, color } = cohort;
const { tree } = cohort;
return {
name: "Valuation",
tree: [