mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-04-24 22:59:58 -07:00
516 lines
14 KiB
JavaScript
516 lines
14 KiB
JavaScript
import { Unit } from "../utils/units.js";
|
||
import { priceLine, priceLines } from "./constants.js";
|
||
import { line, baseline } from "./series.js";
|
||
import {
|
||
satsBtcUsd,
|
||
percentileUsdMap,
|
||
percentileMap,
|
||
sdPatterns,
|
||
sdBands,
|
||
} from "./shared.js";
|
||
|
||
/**
|
||
* Create price with ratio options for cointime prices
|
||
* @param {PartialContext} ctx
|
||
* @param {Object} args
|
||
* @param {string} args.title
|
||
* @param {string} args.legend
|
||
* @param {AnyMetricPattern} args.price
|
||
* @param {ActivePriceRatioPattern} args.ratio
|
||
* @param {Color} [args.color]
|
||
* @returns {PartialOptionsTree}
|
||
*/
|
||
function createCointimePriceWithRatioOptions(
|
||
ctx,
|
||
{ title, legend, price, ratio, color },
|
||
) {
|
||
const { colors } = ctx;
|
||
|
||
const pctUsdMap = percentileUsdMap(colors, ratio);
|
||
const pctMap = percentileMap(colors, ratio);
|
||
const sdPats = sdPatterns(ratio);
|
||
|
||
return [
|
||
{
|
||
name: "price",
|
||
title,
|
||
top: [line({ metric: price, name: legend, color, unit: Unit.usd })],
|
||
},
|
||
{
|
||
name: "Ratio",
|
||
title: `${title} Ratio`,
|
||
top: [
|
||
line({ metric: price, name: legend, color, unit: Unit.usd }),
|
||
...pctUsdMap.map(({ name: pctName, prop, color: pctColor }) =>
|
||
line({
|
||
metric: prop,
|
||
name: pctName,
|
||
color: pctColor,
|
||
defaultActive: false,
|
||
unit: Unit.usd,
|
||
options: { lineStyle: 1 },
|
||
}),
|
||
),
|
||
],
|
||
bottom: [
|
||
baseline({
|
||
metric: ratio.ratio,
|
||
name: "Ratio",
|
||
color,
|
||
unit: Unit.ratio,
|
||
}),
|
||
line({
|
||
metric: ratio.ratio1wSma,
|
||
name: "1w SMA",
|
||
color: colors.lime,
|
||
unit: Unit.ratio,
|
||
defaultActive: false,
|
||
}),
|
||
line({
|
||
metric: ratio.ratio1mSma,
|
||
name: "1m SMA",
|
||
color: colors.teal,
|
||
unit: Unit.ratio,
|
||
defaultActive: false,
|
||
}),
|
||
line({
|
||
metric: ratio.ratio1ySd.sma,
|
||
name: "1y SMA",
|
||
color: colors.sky,
|
||
unit: Unit.ratio,
|
||
defaultActive: false,
|
||
}),
|
||
line({
|
||
metric: ratio.ratio2ySd.sma,
|
||
name: "2y SMA",
|
||
color: colors.indigo,
|
||
unit: Unit.ratio,
|
||
defaultActive: false,
|
||
}),
|
||
line({
|
||
metric: ratio.ratio4ySd.sma,
|
||
name: "4y SMA",
|
||
color: colors.purple,
|
||
unit: Unit.ratio,
|
||
defaultActive: false,
|
||
}),
|
||
line({
|
||
metric: ratio.ratioSd.sma,
|
||
name: "All SMA",
|
||
color: colors.rose,
|
||
unit: Unit.ratio,
|
||
defaultActive: false,
|
||
}),
|
||
...pctMap.map(({ name: pctName, prop, color: pctColor }) =>
|
||
line({
|
||
metric: prop,
|
||
name: pctName,
|
||
color: pctColor,
|
||
defaultActive: false,
|
||
unit: Unit.ratio,
|
||
options: { lineStyle: 1 },
|
||
}),
|
||
),
|
||
priceLine({ ctx, unit: Unit.ratio, number: 1 }),
|
||
],
|
||
},
|
||
{
|
||
name: "ZScores",
|
||
tree: [
|
||
// Compare all Z-Scores
|
||
{
|
||
name: "Compare",
|
||
title: `${title} Z-Scores`,
|
||
top: [
|
||
line({ metric: price, name: legend, color, unit: Unit.usd }),
|
||
line({
|
||
metric: ratio.ratio1ySd._0sdUsd,
|
||
name: "1y 0σ",
|
||
color: colors.orange,
|
||
defaultActive: false,
|
||
unit: Unit.usd,
|
||
}),
|
||
line({
|
||
metric: ratio.ratio2ySd._0sdUsd,
|
||
name: "2y 0σ",
|
||
color: colors.yellow,
|
||
defaultActive: false,
|
||
unit: Unit.usd,
|
||
}),
|
||
line({
|
||
metric: ratio.ratio4ySd._0sdUsd,
|
||
name: "4y 0σ",
|
||
color: colors.lime,
|
||
defaultActive: false,
|
||
unit: Unit.usd,
|
||
}),
|
||
line({
|
||
metric: ratio.ratioSd._0sdUsd,
|
||
name: "all 0σ",
|
||
color: colors.blue,
|
||
defaultActive: false,
|
||
unit: Unit.usd,
|
||
}),
|
||
],
|
||
bottom: [
|
||
line({
|
||
metric: ratio.ratioSd.zscore,
|
||
name: "all",
|
||
color: colors.blue,
|
||
unit: Unit.sd,
|
||
}),
|
||
line({
|
||
metric: ratio.ratio4ySd.zscore,
|
||
name: "4y",
|
||
color: colors.lime,
|
||
unit: Unit.sd,
|
||
}),
|
||
line({
|
||
metric: ratio.ratio2ySd.zscore,
|
||
name: "2y",
|
||
color: colors.yellow,
|
||
unit: Unit.sd,
|
||
}),
|
||
line({
|
||
metric: ratio.ratio1ySd.zscore,
|
||
name: "1y",
|
||
color: colors.orange,
|
||
unit: Unit.sd,
|
||
}),
|
||
...priceLines({
|
||
ctx,
|
||
unit: Unit.sd,
|
||
numbers: [0, 1, -1, 2, -2, 3, -3, 4, -4],
|
||
defaultActive: false,
|
||
}),
|
||
],
|
||
},
|
||
// Individual Z-Score charts
|
||
...sdPats.map(({ nameAddon, titleAddon, sd }) => ({
|
||
name: nameAddon,
|
||
title: `${title} ${titleAddon} Z-Score`,
|
||
top: [
|
||
line({ metric: price, name: legend, color, unit: Unit.usd }),
|
||
...sdBands(colors, sd).map(
|
||
({ name: bandName, prop, color: bandColor }) =>
|
||
line({
|
||
metric: prop,
|
||
name: bandName,
|
||
color: bandColor,
|
||
unit: Unit.usd,
|
||
defaultActive: false,
|
||
}),
|
||
),
|
||
],
|
||
bottom: [
|
||
line({ metric: sd.zscore, name: "Z-Score", color, unit: Unit.sd }),
|
||
...priceLines({
|
||
ctx,
|
||
unit: Unit.sd,
|
||
numbers: [0, 1, -1, 2, -2, 3, -3],
|
||
defaultActive: false,
|
||
}),
|
||
],
|
||
})),
|
||
],
|
||
},
|
||
];
|
||
}
|
||
|
||
/**
|
||
* Create Cointime section
|
||
* @param {PartialContext} ctx
|
||
* @returns {PartialOptionsGroup}
|
||
*/
|
||
export function createCointimeSection(ctx) {
|
||
const { colors, brk } = ctx;
|
||
const { cointime, distribution, supply } = brk.metrics;
|
||
const { pricing, cap, activity, supply: cointimeSupply, adjusted } = cointime;
|
||
const { all } = distribution.utxoCohorts;
|
||
|
||
// Cointime prices data
|
||
const cointimePrices = [
|
||
{
|
||
price: pricing.trueMarketMean,
|
||
ratio: pricing.trueMarketMeanRatio,
|
||
name: "True market mean",
|
||
title: "True Market Mean",
|
||
color: colors.blue,
|
||
},
|
||
{
|
||
price: pricing.vaultedPrice,
|
||
ratio: pricing.vaultedPriceRatio,
|
||
name: "Vaulted",
|
||
title: "Vaulted Price",
|
||
color: colors.lime,
|
||
},
|
||
{
|
||
price: pricing.activePrice,
|
||
ratio: pricing.activePriceRatio,
|
||
name: "Active",
|
||
title: "Active Price",
|
||
color: colors.rose,
|
||
},
|
||
{
|
||
price: pricing.cointimePrice,
|
||
ratio: pricing.cointimePriceRatio,
|
||
name: "cointime",
|
||
title: "Cointime Price",
|
||
color: colors.yellow,
|
||
},
|
||
];
|
||
|
||
// Cointime capitalizations data
|
||
const cointimeCapitalizations = [
|
||
{
|
||
metric: cap.vaultedCap,
|
||
name: "vaulted",
|
||
title: "Vaulted Cap",
|
||
color: colors.lime,
|
||
},
|
||
{
|
||
metric: cap.activeCap,
|
||
name: "active",
|
||
title: "Active Cap",
|
||
color: colors.rose,
|
||
},
|
||
{
|
||
metric: cap.cointimeCap,
|
||
name: "cointime",
|
||
title: "Cointime Cap",
|
||
color: colors.yellow,
|
||
},
|
||
{
|
||
metric: cap.investorCap,
|
||
name: "investor",
|
||
title: "Investor Cap",
|
||
color: colors.fuchsia,
|
||
},
|
||
{
|
||
metric: cap.thermoCap,
|
||
name: "thermo",
|
||
title: "Thermo Cap",
|
||
color: colors.emerald,
|
||
},
|
||
];
|
||
|
||
return {
|
||
name: "Cointime",
|
||
tree: [
|
||
// Prices
|
||
{
|
||
name: "Prices",
|
||
tree: [
|
||
{
|
||
name: "Compare",
|
||
title: "Cointime Prices",
|
||
top: cointimePrices.map(({ price, name, color }) =>
|
||
line({ metric: price, name, color, unit: Unit.usd }),
|
||
),
|
||
},
|
||
...cointimePrices.map(({ price, ratio, name, color, title }) => ({
|
||
name,
|
||
tree: createCointimePriceWithRatioOptions(ctx, {
|
||
price,
|
||
ratio,
|
||
legend: name,
|
||
color,
|
||
title,
|
||
}),
|
||
})),
|
||
],
|
||
},
|
||
|
||
// Capitalization
|
||
{
|
||
name: "Capitalization",
|
||
tree: [
|
||
{
|
||
name: "Compare",
|
||
title: "Cointime Caps",
|
||
bottom: [
|
||
line({
|
||
metric: supply.marketCap,
|
||
name: "Market",
|
||
color: colors.default,
|
||
unit: Unit.usd,
|
||
}),
|
||
line({
|
||
metric: all.realized.realizedCap,
|
||
name: "Realized",
|
||
color: colors.orange,
|
||
unit: Unit.usd,
|
||
}),
|
||
...cointimeCapitalizations.map(({ metric, name, color }) =>
|
||
line({ metric, name, color, unit: Unit.usd }),
|
||
),
|
||
],
|
||
},
|
||
...cointimeCapitalizations.map(({ metric, name, color, title }) => ({
|
||
name,
|
||
title,
|
||
bottom: [
|
||
line({ metric, name, color, unit: Unit.usd }),
|
||
line({
|
||
metric: supply.marketCap,
|
||
name: "Market",
|
||
color: colors.default,
|
||
unit: Unit.usd,
|
||
}),
|
||
line({
|
||
metric: all.realized.realizedCap,
|
||
name: "Realized",
|
||
color: colors.orange,
|
||
unit: Unit.usd,
|
||
}),
|
||
],
|
||
})),
|
||
],
|
||
},
|
||
|
||
// Supply
|
||
{
|
||
name: "Supply",
|
||
title: "Cointime Supply",
|
||
bottom: [
|
||
...satsBtcUsd(all.supply.total, "All", colors.orange),
|
||
...satsBtcUsd(cointimeSupply.vaultedSupply, "Vaulted", colors.lime),
|
||
...satsBtcUsd(cointimeSupply.activeSupply, "Active", colors.rose),
|
||
],
|
||
},
|
||
|
||
// Liveliness & Vaultedness
|
||
{
|
||
name: "Liveliness & Vaultedness",
|
||
title: "Liveliness & Vaultedness",
|
||
bottom: [
|
||
line({
|
||
metric: activity.liveliness,
|
||
name: "Liveliness",
|
||
color: colors.rose,
|
||
unit: Unit.ratio,
|
||
}),
|
||
line({
|
||
metric: activity.vaultedness,
|
||
name: "Vaultedness",
|
||
color: colors.lime,
|
||
unit: Unit.ratio,
|
||
}),
|
||
line({
|
||
metric: activity.activityToVaultednessRatio,
|
||
name: "Liveliness / Vaultedness",
|
||
color: colors.purple,
|
||
unit: Unit.ratio,
|
||
}),
|
||
],
|
||
},
|
||
|
||
// Coinblocks
|
||
{
|
||
name: "Coinblocks",
|
||
title: "Coinblocks",
|
||
bottom: [
|
||
// Destroyed comes from the all cohort's activity
|
||
line({
|
||
metric: all.activity.coinblocksDestroyed.sum,
|
||
name: "Destroyed",
|
||
color: colors.red,
|
||
unit: Unit.coinblocks,
|
||
}),
|
||
line({
|
||
metric: all.activity.coinblocksDestroyed.cumulative,
|
||
name: "Cumulative Destroyed",
|
||
color: colors.red,
|
||
defaultActive: false,
|
||
unit: Unit.coinblocks,
|
||
}),
|
||
// Created and stored from cointime
|
||
line({
|
||
metric: activity.coinblocksCreated.sum,
|
||
name: "Created",
|
||
color: colors.orange,
|
||
unit: Unit.coinblocks,
|
||
}),
|
||
line({
|
||
metric: activity.coinblocksCreated.cumulative,
|
||
name: "Cumulative Created",
|
||
color: colors.orange,
|
||
defaultActive: false,
|
||
unit: Unit.coinblocks,
|
||
}),
|
||
line({
|
||
metric: activity.coinblocksStored.sum,
|
||
name: "Stored",
|
||
color: colors.green,
|
||
unit: Unit.coinblocks,
|
||
}),
|
||
line({
|
||
metric: activity.coinblocksStored.cumulative,
|
||
name: "Cumulative Stored",
|
||
color: colors.green,
|
||
defaultActive: false,
|
||
unit: Unit.coinblocks,
|
||
}),
|
||
],
|
||
},
|
||
|
||
// Adjusted metrics
|
||
{
|
||
name: "Adjusted",
|
||
tree: [
|
||
// Inflation
|
||
{
|
||
name: "Inflation",
|
||
title: "Adjusted Inflation",
|
||
bottom: [
|
||
line({
|
||
metric: supply.inflation,
|
||
name: "Base",
|
||
color: colors.orange,
|
||
unit: Unit.percentage,
|
||
}),
|
||
line({
|
||
metric: adjusted.cointimeAdjInflationRate,
|
||
name: "Adjusted",
|
||
color: colors.purple,
|
||
unit: Unit.percentage,
|
||
}),
|
||
],
|
||
},
|
||
// Velocity
|
||
{
|
||
name: "Velocity",
|
||
title: "Adjusted Velocity",
|
||
bottom: [
|
||
line({
|
||
metric: supply.velocity.btc,
|
||
name: "BTC",
|
||
color: colors.orange,
|
||
unit: Unit.ratio,
|
||
}),
|
||
line({
|
||
metric: adjusted.cointimeAdjTxBtcVelocity,
|
||
name: "Adj. BTC",
|
||
color: colors.red,
|
||
unit: Unit.ratio,
|
||
}),
|
||
line({
|
||
metric: supply.velocity.usd,
|
||
name: "USD",
|
||
color: colors.emerald,
|
||
unit: Unit.ratio,
|
||
}),
|
||
line({
|
||
metric: adjusted.cointimeAdjTxUsdVelocity,
|
||
name: "Adj. USD",
|
||
color: colors.lime,
|
||
unit: Unit.ratio,
|
||
}),
|
||
],
|
||
},
|
||
],
|
||
},
|
||
],
|
||
};
|
||
}
|