mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-08-05 07:03:06 -07:00
279 lines
7.5 KiB
JavaScript
279 lines
7.5 KiB
JavaScript
import { brk } from "../../utils/client.js";
|
|
import { colors } from "../../utils/colors.js";
|
|
import { Unit } from "../../utils/units.js";
|
|
import { ageRanges } from "../age-ranges.js";
|
|
import { line, price } from "../series.js";
|
|
import { satsBtcUsd, simplePriceRatioTree } from "../shared.js";
|
|
|
|
/**
|
|
* @typedef {Object} CoinflowAgeRange
|
|
* @property {string} name
|
|
* @property {Color} color
|
|
* @property {{
|
|
* mobility: AnySeriesPattern,
|
|
* spendingRate: AnySeriesPattern,
|
|
* spendingExposure: AnySeriesPattern,
|
|
* supply: { mobile: AnyValuePattern, immobile: AnyValuePattern },
|
|
* }} tree
|
|
*/
|
|
|
|
/**
|
|
* @param {readonly CoinflowAgeRange[]} ranges
|
|
* @param {"mobility" | "spendingRate" | "spendingExposure"} key
|
|
* @param {string} name
|
|
* @returns {PartialChartOption}
|
|
*/
|
|
function ageRangeRatioChart(ranges, key, name) {
|
|
return {
|
|
name,
|
|
title: `${name} by UTXO Age`,
|
|
bottom: ranges.map((range) =>
|
|
line({
|
|
series: range.tree[key],
|
|
name: range.name,
|
|
color: range.color,
|
|
unit: Unit.ratio,
|
|
}),
|
|
),
|
|
};
|
|
}
|
|
|
|
/**
|
|
* @param {readonly CoinflowAgeRange[]} ranges
|
|
* @param {"mobile" | "immobile"} key
|
|
* @param {string} name
|
|
* @returns {PartialChartOption}
|
|
*/
|
|
function ageRangeSupplyChart(ranges, key, name) {
|
|
return {
|
|
name,
|
|
title: `${name} Supply by UTXO Age`,
|
|
bottom: ranges.flatMap((range) =>
|
|
satsBtcUsd({
|
|
pattern: range.tree.supply[key],
|
|
name: range.name,
|
|
color: range.color,
|
|
}),
|
|
),
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Create Coinflow section.
|
|
* @returns {PartialOptionsGroup}
|
|
*/
|
|
export function createCoinflowSection() {
|
|
const { coinflow } = brk.series.frameworks;
|
|
const ranges = ageRanges.map(({ key, ...range }) => ({
|
|
...range,
|
|
tree: coinflow.ageRange[key],
|
|
}));
|
|
const terms = [
|
|
{ name: "STH", color: colors.term.short, tree: coinflow.sth },
|
|
{ name: "LTH", color: colors.term.long, tree: coinflow.lth },
|
|
];
|
|
const cohorts = [
|
|
{ name: "All", color: colors.loss, tree: coinflow },
|
|
...terms,
|
|
];
|
|
const frameworkCohorts = [
|
|
{ name: "All", color: colors.coinflow, tree: coinflow },
|
|
...terms,
|
|
];
|
|
|
|
const horizons = /** @type {const} */ ([
|
|
{ key: "_8y", name: "8Y" },
|
|
{ key: "_4y", name: "4Y" },
|
|
{ key: "_2y", name: "2Y" },
|
|
{ key: "_1y", name: "1Y" },
|
|
{ key: "_6m", name: "6M" },
|
|
{ key: "_3m", name: "3M" },
|
|
{ key: "_1m", name: "1M" },
|
|
]).map((horizon, index, all) => ({
|
|
...horizon,
|
|
color: colors.at(index, all.length),
|
|
}));
|
|
|
|
return {
|
|
name: "Coinflow",
|
|
tree: [
|
|
{
|
|
name: "Price",
|
|
tree: [
|
|
{
|
|
name: "Compare",
|
|
title: "Coinflow Price by Holder Term",
|
|
top: frameworkCohorts.map(({ name, color, tree }) =>
|
|
price({
|
|
series: tree.price,
|
|
name,
|
|
color,
|
|
}),
|
|
),
|
|
bottom: frameworkCohorts.map(({ name, color, tree }) =>
|
|
line({
|
|
series: tree.price.ratio,
|
|
name: `Spot / ${name}`,
|
|
color,
|
|
unit: Unit.ratio,
|
|
}),
|
|
),
|
|
},
|
|
...frameworkCohorts.map(({ name, color, tree }) => {
|
|
const title =
|
|
name === "All" ? "Coinflow Price" : `${name} Coinflow Price`;
|
|
const [chart] = simplePriceRatioTree({
|
|
pattern: tree.price,
|
|
title,
|
|
legend: name,
|
|
color,
|
|
});
|
|
return { ...chart, name };
|
|
}),
|
|
],
|
|
},
|
|
{
|
|
name: "Capitalization",
|
|
tree: [
|
|
{
|
|
name: "Compare",
|
|
title: "Coinflow Cap by Holder Term",
|
|
bottom: frameworkCohorts.map(({ name, color, tree }) =>
|
|
line({
|
|
series: tree.cap.usd,
|
|
name,
|
|
color,
|
|
unit: Unit.usd,
|
|
}),
|
|
),
|
|
},
|
|
...frameworkCohorts.map(({ name, color, tree }) => ({
|
|
name,
|
|
title: name === "All" ? "Coinflow Cap" : `${name} Coinflow Cap`,
|
|
bottom: [
|
|
line({
|
|
series: tree.cap.usd,
|
|
name,
|
|
color,
|
|
unit: Unit.usd,
|
|
}),
|
|
],
|
|
})),
|
|
],
|
|
},
|
|
{
|
|
name: "Supply",
|
|
tree: [
|
|
{
|
|
name: "Overview",
|
|
title: "Mobile vs Immobile Supply",
|
|
bottom: [
|
|
...satsBtcUsd({
|
|
pattern: coinflow.supply.mobile,
|
|
name: "Mobile",
|
|
color: colors.mobile,
|
|
}),
|
|
...satsBtcUsd({
|
|
pattern: coinflow.supply.immobile,
|
|
name: "Immobile",
|
|
color: colors.immobile,
|
|
}),
|
|
],
|
|
},
|
|
{
|
|
name: "By Holder Term",
|
|
tree: [
|
|
{
|
|
name: "Mobile",
|
|
title: "Mobile Supply by Holder Term",
|
|
bottom: terms.flatMap(({ name, color, tree }) =>
|
|
satsBtcUsd({
|
|
pattern: tree.supply.mobile,
|
|
name,
|
|
color,
|
|
}),
|
|
),
|
|
},
|
|
{
|
|
name: "Immobile",
|
|
title: "Immobile Supply by Holder Term",
|
|
bottom: terms.flatMap(({ name, color, tree }) =>
|
|
satsBtcUsd({
|
|
pattern: tree.supply.immobile,
|
|
name,
|
|
color,
|
|
}),
|
|
),
|
|
},
|
|
],
|
|
},
|
|
{
|
|
name: "By UTXO Age",
|
|
tree: [
|
|
ageRangeSupplyChart(ranges, "mobile", "Mobile"),
|
|
ageRangeSupplyChart(ranges, "immobile", "Immobile"),
|
|
],
|
|
},
|
|
{
|
|
name: "In Loss",
|
|
tree: [
|
|
{
|
|
name: "By Holder Term",
|
|
title: "Mobile Supply in Loss by Holder Term",
|
|
bottom: cohorts.map(({ name, color, tree }) =>
|
|
line({
|
|
series: tree.supply.mobile.inLoss.share,
|
|
name,
|
|
color,
|
|
unit: Unit.ratio,
|
|
}),
|
|
),
|
|
},
|
|
{
|
|
name: "By Horizon",
|
|
tree: cohorts.map(({ name, tree }) => ({
|
|
name,
|
|
title:
|
|
name === "All"
|
|
? "Mobile Supply in Loss by Horizon"
|
|
: `${name} Mobile Supply in Loss by Horizon`,
|
|
bottom: horizons.map((horizon) =>
|
|
line({
|
|
series:
|
|
tree.horizon[horizon.key].supply.inLoss.share,
|
|
name: horizon.name,
|
|
color: horizon.color,
|
|
unit: Unit.ratio,
|
|
}),
|
|
),
|
|
})),
|
|
},
|
|
],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
name: "Activity",
|
|
tree: [
|
|
{
|
|
name: "By UTXO Age",
|
|
tree: [
|
|
ageRangeRatioChart(ranges, "mobility", "Mobility"),
|
|
ageRangeRatioChart(
|
|
ranges,
|
|
"spendingRate",
|
|
"Spending Rate",
|
|
),
|
|
ageRangeRatioChart(
|
|
ranges,
|
|
"spendingExposure",
|
|
"Spending Exposure",
|
|
),
|
|
],
|
|
},
|
|
],
|
|
},
|
|
],
|
|
};
|
|
}
|