next: ai part 11

This commit is contained in:
nym21
2026-07-29 10:50:14 +02:00
parent eccbda34ee
commit 1cdee36f2e
56 changed files with 2269 additions and 1037 deletions
+136
View File
@@ -0,0 +1,136 @@
import { brk } from "../../utils/client.js";
import { colors } from "../../utils/colors.js";
import { Unit } from "../../utils/units.js";
import { line } from "../series.js";
const FLOOR_PERCENTILES = /** @type {const} */ ([
{ key: "pct95", name: "P95" },
{ key: "pct98", name: "P98" },
{ key: "pct99", name: "P99" },
{ key: "pct995", name: "P99.5" },
{ key: "pct999", name: "P99.9" },
]);
const LEVEL_PERCENTILES = /** @type {const} */ ([
{ key: "pct10", name: "P10" },
{ key: "pct20", name: "P20" },
{ key: "pct30", name: "P30" },
{ key: "pct40", name: "P40" },
{ key: "pct50", name: "P50" },
{ key: "pct60", name: "P60" },
{ key: "pct70", name: "P70" },
{ key: "pct80", name: "P80" },
{ key: "pct90", name: "P90" },
]);
/**
* @typedef {Object} BedrockMode
* @property {string} name
* @property {AnySeriesPattern} inLoss
* @property {{
* floor: Record<string, AnySeriesPattern>,
* level: Record<string, AnySeriesPattern>,
* lossThreshold: Record<string, AnySeriesPattern>,
* }} tree
*/
/**
* @param {BedrockMode} mode
* @param {AnySeriesPattern} ath
* @returns {PartialChartOption}
*/
function modeChart(mode, ath) {
return {
name: mode.name,
title: `Bitcoin Bedrock Model: ${mode.name}`,
top: [
...FLOOR_PERCENTILES.map((percentile, index) =>
line({
series: mode.tree.floor[percentile.key],
name: percentile.name,
color: colors.bedrock.percentiles[index],
unit: Unit.usd,
}),
),
...LEVEL_PERCENTILES.map((percentile, index) =>
line({
series: mode.tree.level[percentile.key],
name: `L${percentile.name.slice(1)}`,
color: colors.bedrock.levels[index],
unit: Unit.usd,
style: 1,
}),
),
line({
series: ath,
name: "L100",
color: colors.bedrock.levels[9],
unit: Unit.usd,
style: 1,
}),
],
bottom: [
line({
series: mode.inLoss,
name: "Loss",
color: colors.default,
defaultActive: false,
unit: Unit.ratio,
}),
...FLOOR_PERCENTILES.map((percentile, index) =>
line({
series: mode.tree.lossThreshold[percentile.key],
name: percentile.name,
color: colors.bedrock.percentiles[index],
defaultActive: false,
unit: Unit.ratio,
}),
),
],
};
}
/**
* Create Bedrock model section.
* @returns {PartialOptionsGroup}
*/
export function createBedrockSection() {
const { bedrock, market, cohorts, cointime, coinflow } = brk.series;
const horizonModes = /** @type {const} */ ([
{ key: "coinflow8y", horizon: "_8y", name: "Coinflow 8Y" },
{ key: "coinflow4y", horizon: "_4y", name: "Coinflow 4Y" },
{ key: "coinflow2y", horizon: "_2y", name: "Coinflow 2Y" },
{ key: "coinflow1y", horizon: "_1y", name: "Coinflow 1Y" },
{ key: "coinflow6m", horizon: "_6m", name: "Coinflow 6M" },
{ key: "coinflow3m", horizon: "_3m", name: "Coinflow 3M" },
{ key: "coinflow1m", horizon: "_1m", name: "Coinflow 1M" },
]).map((mode) => ({
name: mode.name,
tree: bedrock[mode.key],
inLoss: coinflow.horizon[mode.horizon].supply.inLoss.share,
}));
const modes = /** @type {readonly BedrockMode[]} */ ([
{
name: "Raw",
tree: bedrock.raw,
inLoss: cohorts.utxo.all.supply.inLoss.share.ratio,
},
{
name: "Cointime",
tree: bedrock.cointime,
inLoss: cointime.supply.active.inLoss.share,
},
{
name: "Coinflow",
tree: bedrock.coinflow,
inLoss: coinflow.supply.mobile.inLoss.share,
},
...horizonModes,
]);
return {
name: "Bedrock",
tree: modes.map((mode) => modeChart(mode, market.ath.high.usd)),
};
}
@@ -0,0 +1,118 @@
import { brk } from "../../utils/client.js";
import { colors } from "../../utils/colors.js";
import { Unit } from "../../utils/units.js";
import { baseline, histogram } from "../series.js";
import {
percentileBands,
priceBands,
priceRatioPercentilesTree,
} from "../shared.js";
/**
* Create Rarity Meter model section.
* @returns {PartialOptionsGroup}
*/
export function createRarityMeterSection() {
const { rarityMeter } = brk.series.indicators;
const { all, sth, lth } = brk.series.cohorts.utxo;
return {
name: "Rarity Meter",
tree: [
.../** @type {const} */ ([
{ key: "full", name: "Full", title: "Bitcoin Rarity Meter: Full" },
{ key: "local", name: "Local", title: "Bitcoin Rarity Meter: Local" },
{ key: "cycle", name: "Cycle", title: "Bitcoin Rarity Meter: Cycle" },
]).map((variant) => {
const meter = rarityMeter[variant.key];
return {
name: variant.name,
title: variant.title,
top: priceBands(percentileBands(meter), { defaultActive: true }),
bottom: [
histogram({
series: meter.index,
name: "Index",
unit: Unit.count,
colorFn: (value) =>
/** @type {const} */ ([
colors.ratioPct._0_5,
colors.ratioPct._1,
colors.ratioPct._2,
colors.ratioPct._5,
colors.transparent,
colors.ratioPct._95,
colors.ratioPct._98,
colors.ratioPct._99,
colors.ratioPct._99_5,
])[value + 4],
}),
baseline({
series: meter.score,
name: "Score",
unit: Unit.count,
color: [colors.ratioPct._99, colors.ratioPct._1],
defaultActive: false,
}),
],
};
}),
{
name: "Components",
tree: [
{
name: "Realized Price",
title: "Realized Price",
pattern: all.realized.price,
legend: "Realized",
color: colors.realized,
},
{
name: "Capitalized Price",
title: "Capitalized Price",
pattern: all.realized.capitalized.price,
legend: "Capitalized",
color: colors.capitalized,
},
{
name: "STH RP",
title: "STH Realized Price",
pattern: sth.realized.price,
legend: "Realized",
color: colors.realized,
},
{
name: "STH CP",
title: "STH Capitalized Price",
pattern: sth.realized.capitalized.price,
legend: "Capitalized",
color: colors.capitalized,
},
{
name: "LTH RP",
title: "LTH Realized Price",
pattern: lth.realized.price,
legend: "Realized",
color: colors.realized,
},
{
name: "LTH CP",
title: "LTH Capitalized Price",
pattern: lth.realized.capitalized.price,
legend: "Capitalized",
color: colors.capitalized,
},
].map((component) => {
const [, ratioChart] = priceRatioPercentilesTree({
pattern: component.pattern,
title: component.title,
legend: component.legend,
color: component.color,
defaultActivePercentiles: true,
});
return { ...ratioChart, name: component.name };
}),
},
],
};
}