mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-04-29 09:09:58 -07:00
global: snapshot
This commit is contained in:
@@ -165,7 +165,6 @@ export function createCointimeSection() {
|
||||
return {
|
||||
name: "Cointime",
|
||||
tree: [
|
||||
// Prices - the core pricing models
|
||||
{
|
||||
name: "Prices",
|
||||
tree: [
|
||||
@@ -208,7 +207,6 @@ export function createCointimeSection() {
|
||||
],
|
||||
},
|
||||
|
||||
// Caps - market capitalizations from different models
|
||||
{
|
||||
name: "Caps",
|
||||
tree: [
|
||||
@@ -242,7 +240,6 @@ export function createCointimeSection() {
|
||||
],
|
||||
},
|
||||
|
||||
// Supply - active vs vaulted breakdown
|
||||
{
|
||||
name: "Supply",
|
||||
title: "Active vs Vaulted Supply",
|
||||
@@ -251,7 +248,6 @@ export function createCointimeSection() {
|
||||
),
|
||||
},
|
||||
|
||||
// Liveliness - the foundational cointime ratios
|
||||
{
|
||||
name: "Activity",
|
||||
title: "Liveliness & Vaultedness",
|
||||
@@ -278,7 +274,6 @@ export function createCointimeSection() {
|
||||
],
|
||||
},
|
||||
|
||||
// Coinblocks - created, destroyed, stored
|
||||
{
|
||||
name: "Coinblocks",
|
||||
tree: [
|
||||
@@ -300,7 +295,7 @@ export function createCointimeSection() {
|
||||
name,
|
||||
tree: [
|
||||
{
|
||||
name: "Base",
|
||||
name: "Per Block",
|
||||
title,
|
||||
bottom: [
|
||||
line({
|
||||
@@ -329,7 +324,6 @@ export function createCointimeSection() {
|
||||
],
|
||||
},
|
||||
|
||||
// Value - cointime value flows
|
||||
{
|
||||
name: "Value",
|
||||
tree: [
|
||||
@@ -360,7 +354,7 @@ export function createCointimeSection() {
|
||||
name,
|
||||
tree: [
|
||||
{
|
||||
name: "Base",
|
||||
name: "Per Block",
|
||||
title,
|
||||
bottom: [
|
||||
line({ series: pattern.base, name, color, unit: Unit.usd }),
|
||||
@@ -385,7 +379,7 @@ export function createCointimeSection() {
|
||||
name: vocdd.name,
|
||||
tree: [
|
||||
{
|
||||
name: "Base",
|
||||
name: "Per Block",
|
||||
title: vocdd.title,
|
||||
bottom: [
|
||||
line({
|
||||
@@ -424,7 +418,6 @@ export function createCointimeSection() {
|
||||
],
|
||||
},
|
||||
|
||||
// Indicators - derived decision series
|
||||
{
|
||||
name: "Indicators",
|
||||
tree: [
|
||||
@@ -446,7 +439,7 @@ export function createCointimeSection() {
|
||||
bottom: [
|
||||
line({
|
||||
series: cap.aviv.ratio,
|
||||
name: "aviv",
|
||||
name: "AVIV",
|
||||
unit: Unit.ratio,
|
||||
}),
|
||||
],
|
||||
@@ -454,7 +447,6 @@ export function createCointimeSection() {
|
||||
],
|
||||
},
|
||||
|
||||
// Cointime-Adjusted - comparing base vs adjusted series
|
||||
{
|
||||
name: "Cointime-Adjusted",
|
||||
tree: [
|
||||
@@ -476,44 +468,39 @@ export function createCointimeSection() {
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Velocity",
|
||||
tree: [
|
||||
{
|
||||
name: "BTC",
|
||||
title: "Cointime-Adjusted BTC Velocity",
|
||||
bottom: [
|
||||
line({
|
||||
series: supply.velocity.native,
|
||||
name: "Base",
|
||||
color: colors.base,
|
||||
unit: Unit.ratio,
|
||||
}),
|
||||
line({
|
||||
series: adjusted.txVelocityNative,
|
||||
name: "Cointime-Adjusted",
|
||||
color: colors.adjusted,
|
||||
unit: Unit.ratio,
|
||||
}),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "USD",
|
||||
title: "Cointime-Adjusted USD Velocity",
|
||||
bottom: [
|
||||
line({
|
||||
series: supply.velocity.fiat,
|
||||
name: "Base",
|
||||
color: colors.thermo,
|
||||
unit: Unit.ratio,
|
||||
}),
|
||||
line({
|
||||
series: adjusted.txVelocityFiat,
|
||||
name: "Cointime-Adjusted",
|
||||
color: colors.vaulted,
|
||||
unit: Unit.ratio,
|
||||
}),
|
||||
],
|
||||
},
|
||||
name: "BTC Velocity",
|
||||
title: "Cointime-Adjusted BTC Velocity",
|
||||
bottom: [
|
||||
line({
|
||||
series: supply.velocity.native,
|
||||
name: "Base",
|
||||
color: colors.base,
|
||||
unit: Unit.ratio,
|
||||
}),
|
||||
line({
|
||||
series: adjusted.txVelocityNative,
|
||||
name: "Cointime-Adjusted",
|
||||
color: colors.adjusted,
|
||||
unit: Unit.ratio,
|
||||
}),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "USD Velocity",
|
||||
title: "Cointime-Adjusted USD Velocity",
|
||||
bottom: [
|
||||
line({
|
||||
series: supply.velocity.fiat,
|
||||
name: "Base",
|
||||
color: colors.thermo,
|
||||
unit: Unit.ratio,
|
||||
}),
|
||||
line({
|
||||
series: adjusted.txVelocityFiat,
|
||||
name: "Cointime-Adjusted",
|
||||
color: colors.vaulted,
|
||||
unit: Unit.ratio,
|
||||
}),
|
||||
],
|
||||
},
|
||||
],
|
||||
|
||||
@@ -32,7 +32,7 @@ function volumeAndCoinsTree(activity, color, title) {
|
||||
name: "Volume",
|
||||
tree: [
|
||||
{
|
||||
name: "Sum",
|
||||
name: "Per Block",
|
||||
title: title("Sent Volume"),
|
||||
bottom: [
|
||||
line({ series: activity.transferVolume.base.sats, name: "Sum", color, unit: Unit.sats }),
|
||||
@@ -52,10 +52,10 @@ function volumeAndCoinsTree(activity, color, title) {
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Coins Destroyed",
|
||||
name: "Coindays Destroyed",
|
||||
tree: [
|
||||
{
|
||||
name: "Base",
|
||||
name: "Per Block",
|
||||
title: title("Coindays Destroyed"),
|
||||
bottom: [
|
||||
line({ series: activity.coindaysDestroyed.base, name: "Base", color, unit: Unit.coindays }),
|
||||
@@ -675,7 +675,7 @@ function groupedRollingSoprCharts(list, all, get24h, get7d, get30d, get1y, title
|
||||
* @template {{ color: Color, name: string }} A
|
||||
* @param {readonly T[]} list
|
||||
* @param {A} all
|
||||
* @param {readonly { name: string, getCreated: (item: T | A) => AnySeriesPattern, getDestroyed: (item: T | A) => AnySeriesPattern }[]} windows
|
||||
* @param {readonly { name: string, title: string, getCreated: (item: T | A) => AnySeriesPattern, getDestroyed: (item: T | A) => AnySeriesPattern }[]} windows
|
||||
* @param {(name: string) => string} title
|
||||
* @param {string} [prefix]
|
||||
* @returns {PartialOptionsTree}
|
||||
@@ -686,7 +686,7 @@ function groupedRollingValueCharts(list, all, windows, title, prefix = "") {
|
||||
name: "Created",
|
||||
tree: windows.map((w) => ({
|
||||
name: w.name,
|
||||
title: title(`${prefix}Value Created (${w.name})`),
|
||||
title: title(`${prefix}Value Created (${w.title})`),
|
||||
bottom: mapCohortsWithAll(list, all, (item) =>
|
||||
line({ series: w.getCreated(item), name: item.name, color: item.color, unit: Unit.usd }),
|
||||
),
|
||||
@@ -696,7 +696,7 @@ function groupedRollingValueCharts(list, all, windows, title, prefix = "") {
|
||||
name: "Destroyed",
|
||||
tree: windows.map((w) => ({
|
||||
name: w.name,
|
||||
title: title(`${prefix}Value Destroyed (${w.name})`),
|
||||
title: title(`${prefix}Value Destroyed (${w.title})`),
|
||||
bottom: mapCohortsWithAll(list, all, (item) =>
|
||||
line({ series: w.getDestroyed(item), name: item.name, color: item.color, unit: Unit.usd }),
|
||||
),
|
||||
@@ -711,10 +711,10 @@ function groupedRollingValueCharts(list, all, windows, title, prefix = "") {
|
||||
*/
|
||||
function valueWindows(list, all) {
|
||||
return [
|
||||
{ name: "24h", getCreated: (/** @type {typeof list[number] | typeof all} */ c) => c.tree.realized.sopr.valueCreated.sum._24h, getDestroyed: (/** @type {typeof list[number] | typeof all} */ c) => c.tree.realized.sopr.valueDestroyed.sum._24h },
|
||||
{ name: "7d", getCreated: (/** @type {typeof list[number] | typeof all} */ c) => c.tree.realized.sopr.valueCreated.sum._1w, getDestroyed: (/** @type {typeof list[number] | typeof all} */ c) => c.tree.realized.sopr.valueDestroyed.sum._1w },
|
||||
{ name: "30d", getCreated: (/** @type {typeof list[number] | typeof all} */ c) => c.tree.realized.sopr.valueCreated.sum._1m, getDestroyed: (/** @type {typeof list[number] | typeof all} */ c) => c.tree.realized.sopr.valueDestroyed.sum._1m },
|
||||
{ name: "1y", getCreated: (/** @type {typeof list[number] | typeof all} */ c) => c.tree.realized.sopr.valueCreated.sum._1y, getDestroyed: (/** @type {typeof list[number] | typeof all} */ c) => c.tree.realized.sopr.valueDestroyed.sum._1y },
|
||||
{ name: "24h", title: "Daily", getCreated: (/** @type {typeof list[number] | typeof all} */ c) => c.tree.realized.sopr.valueCreated.sum._24h, getDestroyed: (/** @type {typeof list[number] | typeof all} */ c) => c.tree.realized.sopr.valueDestroyed.sum._24h },
|
||||
{ name: "7d", title: "Weekly", getCreated: (/** @type {typeof list[number] | typeof all} */ c) => c.tree.realized.sopr.valueCreated.sum._1w, getDestroyed: (/** @type {typeof list[number] | typeof all} */ c) => c.tree.realized.sopr.valueDestroyed.sum._1w },
|
||||
{ name: "30d", title: "Monthly", getCreated: (/** @type {typeof list[number] | typeof all} */ c) => c.tree.realized.sopr.valueCreated.sum._1m, getDestroyed: (/** @type {typeof list[number] | typeof all} */ c) => c.tree.realized.sopr.valueDestroyed.sum._1m },
|
||||
{ name: "1y", title: "Yearly", getCreated: (/** @type {typeof list[number] | typeof all} */ c) => c.tree.realized.sopr.valueCreated.sum._1y, getDestroyed: (/** @type {typeof list[number] | typeof all} */ c) => c.tree.realized.sopr.valueDestroyed.sum._1y },
|
||||
];
|
||||
}
|
||||
|
||||
@@ -823,10 +823,10 @@ export function createGroupedActivitySectionWithAdjusted({ list, all, title }) {
|
||||
tree: groupedRollingValueCharts(
|
||||
list, all,
|
||||
[
|
||||
{ name: "24h", getCreated: (c) => c.tree.realized.sopr.adjusted.valueCreated.sum._24h, getDestroyed: (c) => c.tree.realized.sopr.adjusted.valueDestroyed.sum._24h },
|
||||
{ name: "7d", getCreated: (c) => c.tree.realized.sopr.adjusted.valueCreated.sum._1w, getDestroyed: (c) => c.tree.realized.sopr.adjusted.valueDestroyed.sum._1w },
|
||||
{ name: "30d", getCreated: (c) => c.tree.realized.sopr.adjusted.valueCreated.sum._1m, getDestroyed: (c) => c.tree.realized.sopr.adjusted.valueDestroyed.sum._1m },
|
||||
{ name: "1y", getCreated: (c) => c.tree.realized.sopr.adjusted.valueCreated.sum._1y, getDestroyed: (c) => c.tree.realized.sopr.adjusted.valueDestroyed.sum._1y },
|
||||
{ name: "24h", title: "Daily", getCreated: (c) => c.tree.realized.sopr.adjusted.valueCreated.sum._24h, getDestroyed: (c) => c.tree.realized.sopr.adjusted.valueDestroyed.sum._24h },
|
||||
{ name: "7d", title: "Weekly", getCreated: (c) => c.tree.realized.sopr.adjusted.valueCreated.sum._1w, getDestroyed: (c) => c.tree.realized.sopr.adjusted.valueDestroyed.sum._1w },
|
||||
{ name: "30d", title: "Monthly", getCreated: (c) => c.tree.realized.sopr.adjusted.valueCreated.sum._1m, getDestroyed: (c) => c.tree.realized.sopr.adjusted.valueDestroyed.sum._1m },
|
||||
{ name: "1y", title: "Yearly", getCreated: (c) => c.tree.realized.sopr.adjusted.valueCreated.sum._1y, getDestroyed: (c) => c.tree.realized.sopr.adjusted.valueDestroyed.sum._1y },
|
||||
],
|
||||
title,
|
||||
"Adjusted ",
|
||||
@@ -837,7 +837,7 @@ export function createGroupedActivitySectionWithAdjusted({ list, all, title }) {
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Coins Destroyed",
|
||||
name: "Coindays Destroyed",
|
||||
title: title("Coindays Destroyed"),
|
||||
bottom: flatMapCohortsWithAll(list, all, ({ name, color, tree }) => [
|
||||
line({ series: tree.activity.coindaysDestroyed.sum._24h, name, color, unit: Unit.coindays }),
|
||||
@@ -914,7 +914,7 @@ export function createGroupedActivitySection({ list, all, title }) {
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Coins Destroyed",
|
||||
name: "Coindays Destroyed",
|
||||
title: title("Coindays Destroyed"),
|
||||
bottom: flatMapCohortsWithAll(list, all, ({ name, color, tree }) => [
|
||||
line({ series: tree.activity.coindaysDestroyed.sum._24h, name, color, unit: Unit.coindays }),
|
||||
@@ -955,7 +955,7 @@ export function createGroupedActivitySectionWithActivity({ list, all, title }) {
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Coins Destroyed",
|
||||
name: "Coindays Destroyed",
|
||||
title: title("Coindays Destroyed"),
|
||||
bottom: flatMapCohortsWithAll(list, all, ({ name, color, tree }) => [
|
||||
line({ series: tree.activity.coindaysDestroyed.sum._24h, name, color, unit: Unit.coindays }),
|
||||
|
||||
@@ -199,7 +199,7 @@ function groupedDeltaTree(list, all, getDelta, unit, title, name) {
|
||||
name: "Absolute",
|
||||
tree: ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: title(`${name} Change (${w.name})`),
|
||||
title: title(`${name} Change (${w.title})`),
|
||||
bottom: mapCohortsWithAll(list, all, (c) =>
|
||||
baseline({ series: getDelta(c).absolute[w.key], name: c.name, color: c.color, unit }),
|
||||
),
|
||||
@@ -209,7 +209,7 @@ function groupedDeltaTree(list, all, getDelta, unit, title, name) {
|
||||
name: "Rate",
|
||||
tree: ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: title(`${name} Rate (${w.name})`),
|
||||
title: title(`${name} Rate (${w.title})`),
|
||||
bottom: flatMapCohortsWithAll(list, all, (c) =>
|
||||
percentRatio({ pattern: getDelta(c).rate[w.key], name: c.name, color: c.color }),
|
||||
),
|
||||
|
||||
@@ -677,7 +677,7 @@ function groupedBucketCharts(list, titlePrefix) {
|
||||
},
|
||||
...ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: `${titlePrefix}: Supply Change ${w.name}`,
|
||||
title: `${titlePrefix}: Supply Change (${w.title})`,
|
||||
bottom: list.map(({ name, color, pattern }) =>
|
||||
baseline({ series: pattern.supply.all.delta.absolute[w.key], name, color, unit: Unit.sats }),
|
||||
),
|
||||
@@ -698,7 +698,7 @@ function groupedBucketCharts(list, titlePrefix) {
|
||||
},
|
||||
...ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: `${titlePrefix}: Supply Rate ${w.name}`,
|
||||
title: `${titlePrefix}: Supply Rate (${w.title})`,
|
||||
bottom: list.flatMap(({ name, color, pattern }) =>
|
||||
percentRatio({ pattern: pattern.supply.all.delta.rate[w.key], name, color }),
|
||||
),
|
||||
|
||||
@@ -45,7 +45,7 @@ function pnlLines(m, unit) {
|
||||
if (m.gross) {
|
||||
series.push(line({ series: m.gross, name: "Total", color: colors.default, unit }));
|
||||
}
|
||||
series.push(line({ series: m.negLoss, name: "Negative Loss", color: colors.loss, unit, defaultActive: false }));
|
||||
series.push(line({ series: m.negLoss, name: "Loss (Inverted)", color: colors.loss, unit, defaultActive: false }));
|
||||
return series;
|
||||
}
|
||||
|
||||
@@ -63,13 +63,13 @@ function netBaseline(s, unit) {
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* @param {{ profit: { base: { usd: AnySeriesPattern } }, loss: { base: { usd: AnySeriesPattern }, negative: AnySeriesPattern }, grossPnl: { usd: AnySeriesPattern } }} u
|
||||
* @param {{ profit: { usd: AnySeriesPattern }, loss: { usd: AnySeriesPattern, negative: AnySeriesPattern }, grossPnl: { usd: AnySeriesPattern } }} u
|
||||
* @returns {AnyFetchedSeriesBlueprint[]}
|
||||
*/
|
||||
function unrealizedUsdSeries(u) {
|
||||
return [
|
||||
...pnlLines(
|
||||
{ profit: u.profit.base.usd, loss: u.loss.base.usd, negLoss: u.loss.negative, gross: u.grossPnl.usd },
|
||||
{ profit: u.profit.usd, loss: u.loss.usd, negLoss: u.loss.negative, gross: u.grossPnl.usd },
|
||||
Unit.usd,
|
||||
),
|
||||
priceLine({ unit: Unit.usd, defaultActive: false }),
|
||||
@@ -105,7 +105,6 @@ function unrealizedPnlTreeAll(u, title) {
|
||||
{ name: "USD", title: title("Unrealized P&L"), bottom: unrealizedUsdSeries(u) },
|
||||
relPnlChart(u.profit.toMcap, u.loss.toMcap, "% of Mcap", title),
|
||||
relPnlChart(u.profit.toOwnGrossPnl, u.loss.toOwnGrossPnl, "% of Own P&L", title),
|
||||
...unrealizedCumulativeRollingTree(u.profit, u.loss, title),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -121,7 +120,6 @@ function unrealizedPnlTreeFull(u, title) {
|
||||
relPnlChart(u.profit.toMcap, u.loss.toMcap, "% of Mcap", title),
|
||||
relPnlChart(u.profit.toOwnMcap, u.loss.toOwnMcap, "% of Own Mcap", title),
|
||||
relPnlChart(u.profit.toOwnGrossPnl, u.loss.toOwnGrossPnl, "% of Own P&L", title),
|
||||
...unrealizedCumulativeRollingTree(u.profit, u.loss, title),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -141,7 +139,6 @@ function unrealizedPnlTreeLongTerm(u, title) {
|
||||
},
|
||||
relPnlChart(u.profit.toOwnMcap, u.loss.toOwnMcap, "% of Own Mcap", title),
|
||||
relPnlChart(u.profit.toOwnGrossPnl, u.loss.toOwnGrossPnl, "% of Own P&L", title),
|
||||
...unrealizedCumulativeRollingTree(u.profit, u.loss, title),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -158,72 +155,12 @@ function unrealizedPnlTreeMid(u, title) {
|
||||
title: title("Unrealized P&L"),
|
||||
bottom: [
|
||||
...pnlLines(
|
||||
{ profit: u.profit.base.usd, loss: u.loss.base.usd, negLoss: u.loss.negative },
|
||||
{ profit: u.profit.usd, loss: u.loss.usd, negLoss: u.loss.negative },
|
||||
Unit.usd,
|
||||
),
|
||||
priceLine({ unit: Unit.usd, defaultActive: false }),
|
||||
],
|
||||
},
|
||||
...unrealizedCumulativeRollingTree(u.profit, u.loss, title),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Unrealized cumulative + rolling P&L tree (profit and loss have cumulative.usd + sum[w].usd)
|
||||
* @param {{ cumulative: { usd: AnySeriesPattern }, sum: { _24h: { usd: AnySeriesPattern }, _1w: { usd: AnySeriesPattern }, _1m: { usd: AnySeriesPattern }, _1y: { usd: AnySeriesPattern } } }} profit
|
||||
* @param {{ cumulative: { usd: AnySeriesPattern }, sum: { _24h: { usd: AnySeriesPattern }, _1w: { usd: AnySeriesPattern }, _1m: { usd: AnySeriesPattern }, _1y: { usd: AnySeriesPattern } } }} loss
|
||||
* @param {(name: string) => string} title
|
||||
* @returns {PartialOptionsTree}
|
||||
*/
|
||||
function unrealizedCumulativeRollingTree(profit, loss, title) {
|
||||
return [
|
||||
{
|
||||
name: "Cumulative",
|
||||
title: title("Cumulative Unrealized P&L"),
|
||||
bottom: [
|
||||
line({ series: profit.cumulative.usd, name: "Profit", color: colors.profit, unit: Unit.usd }),
|
||||
line({ series: loss.cumulative.usd, name: "Loss", color: colors.loss, unit: Unit.usd }),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Rolling",
|
||||
tree: [
|
||||
{
|
||||
name: "Profit",
|
||||
tree: [
|
||||
{
|
||||
name: "Compare",
|
||||
title: title("Rolling Unrealized Profit"),
|
||||
bottom: ROLLING_WINDOWS.map((w) =>
|
||||
line({ series: profit.sum[w.key].usd, name: w.name, color: w.color, unit: Unit.usd }),
|
||||
),
|
||||
},
|
||||
...ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: title(`Unrealized Profit (${w.name})`),
|
||||
bottom: [line({ series: profit.sum[w.key].usd, name: "Profit", color: colors.profit, unit: Unit.usd })],
|
||||
})),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Loss",
|
||||
tree: [
|
||||
{
|
||||
name: "Compare",
|
||||
title: title("Rolling Unrealized Loss"),
|
||||
bottom: ROLLING_WINDOWS.map((w) =>
|
||||
line({ series: loss.sum[w.key].usd, name: w.name, color: w.color, unit: Unit.usd }),
|
||||
),
|
||||
},
|
||||
...ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: title(`Unrealized Loss (${w.name})`),
|
||||
bottom: [line({ series: loss.sum[w.key].usd, name: "Loss", color: colors.loss, unit: Unit.usd })],
|
||||
})),
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
@@ -331,12 +268,12 @@ function realizedPnlSumTreeFull(r, title) {
|
||||
title: title("Realized P&L"),
|
||||
bottom: [
|
||||
dots({ series: r.profit.base.usd, name: "Profit", color: colors.profit, unit: Unit.usd }),
|
||||
dots({ series: r.loss.negative, name: "Negative Loss", color: colors.loss, unit: Unit.usd, defaultActive: false }),
|
||||
dots({ series: r.loss.negative, name: "Loss (Inverted)", color: colors.loss, unit: Unit.usd, defaultActive: false }),
|
||||
dots({ series: r.loss.base.usd, name: "Loss", color: colors.loss, unit: Unit.usd, defaultActive: false }),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "% of Rcap",
|
||||
name: "% of Realized Cap",
|
||||
title: title("Realized P&L (% of Realized Cap)"),
|
||||
bottom: [
|
||||
...percentRatioBaseline({ pattern: r.profit.toRcap, name: "Profit", color: colors.profit }),
|
||||
@@ -355,7 +292,7 @@ function realizedNetPnlSumTreeFull(r, title) {
|
||||
return [
|
||||
{ name: "USD", title: title("Net Realized P&L"), bottom: [dotsBaseline({ series: r.netPnl.base.usd, name: "Net", unit: Unit.usd })] },
|
||||
{
|
||||
name: "% of Rcap",
|
||||
name: "% of Realized Cap",
|
||||
title: title("Net Realized P&L (% of Realized Cap)"),
|
||||
bottom: percentRatioBaseline({ pattern: r.netPnl.toRcap, name: "Net" }),
|
||||
},
|
||||
@@ -375,11 +312,11 @@ function realizedPnlCumulativeTreeFull(r, title) {
|
||||
bottom: [
|
||||
line({ series: r.profit.cumulative.usd, name: "Profit", color: colors.profit, unit: Unit.usd }),
|
||||
line({ series: r.loss.cumulative.usd, name: "Loss", color: colors.loss, unit: Unit.usd }),
|
||||
line({ series: r.loss.negative, name: "Negative Loss", color: colors.loss, unit: Unit.usd, defaultActive: false }),
|
||||
line({ series: r.loss.negative, name: "Loss (Inverted)", color: colors.loss, unit: Unit.usd, defaultActive: false }),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "% of Rcap",
|
||||
name: "% of Realized Cap",
|
||||
title: title("Cumulative Realized P&L (% of Realized Cap)"),
|
||||
bottom: [
|
||||
...percentRatioBaseline({ pattern: r.profit.toRcap, name: "Profit", color: colors.profit }),
|
||||
@@ -411,7 +348,7 @@ function realizedNetPnlDeltaTree(netPnl, title) {
|
||||
},
|
||||
...ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: title(`Net Realized P&L Change (${w.name})`),
|
||||
title: title(`Net Realized P&L Change (${w.title})`),
|
||||
bottom: [baseline({ series: netPnl.delta.absolute[w.key].usd, name: "Change", unit: Unit.usd })],
|
||||
})),
|
||||
],
|
||||
@@ -428,7 +365,7 @@ function realizedNetPnlDeltaTree(netPnl, title) {
|
||||
},
|
||||
...ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: title(`Net Realized P&L Rate (${w.name})`),
|
||||
title: title(`Net Realized P&L Rate (${w.title})`),
|
||||
bottom: percentRatioBaseline({ pattern: netPnl.delta.rate[w.key], name: "Rate" }),
|
||||
})),
|
||||
],
|
||||
@@ -455,8 +392,8 @@ function realizedNetPnlDeltaTreeFull(r, title) {
|
||||
bottom: percentRatioBaseline({ pattern: r.netPnl.change1m.toMcap, name: "30d Change" }),
|
||||
},
|
||||
{
|
||||
name: "% of Rcap",
|
||||
title: title("Net Realized P&L Change (% of Rcap)"),
|
||||
name: "% of Realized Cap",
|
||||
title: title("Net Realized P&L Change (% of Realized Cap)"),
|
||||
bottom: percentRatioBaseline({ pattern: r.netPnl.change1m.toRcap, name: "30d Change" }),
|
||||
},
|
||||
],
|
||||
@@ -482,7 +419,7 @@ function rollingNetRealizedTree(netPnl, title) {
|
||||
},
|
||||
...ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: title(`Net Realized P&L (${w.name})`),
|
||||
title: title(`Net Realized P&L (${w.title})`),
|
||||
bottom: [baseline({ series: netPnl.sum[w.key].usd, name: "Net", unit: Unit.usd })],
|
||||
})),
|
||||
],
|
||||
@@ -509,7 +446,7 @@ function singleRollingRealizedTreeFull(r, title) {
|
||||
},
|
||||
...ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: title(`Realized Profit (${w.name})`),
|
||||
title: title(`Realized Profit (${w.title})`),
|
||||
bottom: [line({ series: r.profit.sum[w.key].usd, name: "Profit", color: colors.profit, unit: Unit.usd })],
|
||||
})),
|
||||
],
|
||||
@@ -526,7 +463,7 @@ function singleRollingRealizedTreeFull(r, title) {
|
||||
},
|
||||
...ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: title(`Realized Loss (${w.name})`),
|
||||
title: title(`Realized Loss (${w.title})`),
|
||||
bottom: [line({ series: r.loss.sum[w.key].usd, name: "Loss", color: colors.loss, unit: Unit.usd })],
|
||||
})),
|
||||
],
|
||||
@@ -544,7 +481,7 @@ function singleRollingRealizedTreeFull(r, title) {
|
||||
},
|
||||
...ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: title(`Realized P/L Ratio (${w.name})`),
|
||||
title: title(`Realized P/L Ratio (${w.title})`),
|
||||
bottom: [baseline({ series: r.profitToLossRatio[w.key], name: "P/L Ratio", unit: Unit.ratio, base: 1 })],
|
||||
})),
|
||||
],
|
||||
@@ -565,7 +502,7 @@ function singleRollingRealizedTreeBasic(profit, loss, title) {
|
||||
name: "Profit",
|
||||
tree: ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: title(`Realized Profit (${w.name})`),
|
||||
title: title(`Realized Profit (${w.title})`),
|
||||
bottom: [line({ series: profit.sum[w.key].usd, name: "Profit", color: colors.profit, unit: Unit.usd })],
|
||||
})),
|
||||
},
|
||||
@@ -573,7 +510,7 @@ function singleRollingRealizedTreeBasic(profit, loss, title) {
|
||||
name: "Loss",
|
||||
tree: ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: title(`Realized Loss (${w.name})`),
|
||||
title: title(`Realized Loss (${w.title})`),
|
||||
bottom: [line({ series: loss.sum[w.key].usd, name: "Loss", color: colors.loss, unit: Unit.usd })],
|
||||
})),
|
||||
},
|
||||
@@ -609,7 +546,7 @@ function realizedValueTree(valueCreated, valueDestroyed, label, title) {
|
||||
},
|
||||
...ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: title(`${label} Value (${w.name})`),
|
||||
title: title(`${label} Value (${w.title})`),
|
||||
bottom: [
|
||||
line({ series: valueCreated.sum[w.key], name: "Created", color: colors.profit, unit: Unit.usd }),
|
||||
line({ series: valueDestroyed.sum[w.key], name: "Destroyed", color: colors.loss, unit: Unit.usd }),
|
||||
@@ -690,7 +627,7 @@ function realizedSubfolderFull(r, title) {
|
||||
{
|
||||
name: "Gross P&L",
|
||||
tree: [
|
||||
{ name: "Base", title: title("Gross Realized P&L"), bottom: [dots({ series: r.grossPnl.base.usd, name: "Gross P&L", color: colors.bitcoin, unit: Unit.usd })] },
|
||||
{ name: "Per Block", title: title("Gross Realized P&L"), bottom: [dots({ series: r.grossPnl.base.usd, name: "Gross P&L", color: colors.bitcoin, unit: Unit.usd })] },
|
||||
{
|
||||
name: "Rolling",
|
||||
tree: [
|
||||
@@ -703,7 +640,7 @@ function realizedSubfolderFull(r, title) {
|
||||
},
|
||||
...ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: title(`Gross Realized P&L (${w.name})`),
|
||||
title: title(`Gross Realized P&L (${w.title})`),
|
||||
bottom: [line({ series: r.grossPnl.sum[w.key].usd, name: "Gross P&L", color: colors.bitcoin, unit: Unit.usd })],
|
||||
})),
|
||||
],
|
||||
@@ -744,7 +681,7 @@ function realizedSubfolderFull(r, title) {
|
||||
tree: [
|
||||
{ name: "USD", title: title("Cumulative Net Realized P&L"), bottom: [baseline({ series: r.netPnl.cumulative.usd, name: "Net", unit: Unit.usd })] },
|
||||
{
|
||||
name: "% of Rcap",
|
||||
name: "% of Realized Cap",
|
||||
title: title("Cumulative Net P&L (% of Realized Cap)"),
|
||||
bottom: percentRatioBaseline({ pattern: r.netPnl.toRcap, name: "Net" }),
|
||||
},
|
||||
@@ -755,7 +692,7 @@ function realizedSubfolderFull(r, title) {
|
||||
tree: [
|
||||
{ name: "USD", title: title("Cumulative Peak Regret"), bottom: [line({ series: r.peakRegret.cumulative, name: "Peak Regret", unit: Unit.usd })] },
|
||||
{
|
||||
name: "% of Rcap",
|
||||
name: "% of Realized Cap",
|
||||
title: title("Cumulative Peak Regret (% of Realized Cap)"),
|
||||
bottom: percentRatioBaseline({ pattern: r.peakRegret.toRcap, name: "Peak Regret" }),
|
||||
},
|
||||
@@ -782,7 +719,7 @@ function realizedSubfolderMid(r, title) {
|
||||
title: title("Realized P&L"),
|
||||
bottom: [
|
||||
dots({ series: r.profit.base.usd, name: "Profit", color: colors.profit, unit: Unit.usd }),
|
||||
dots({ series: r.loss.negative, name: "Negative Loss", color: colors.loss, unit: Unit.usd, defaultActive: false }),
|
||||
dots({ series: r.loss.negative, name: "Loss (Inverted)", color: colors.loss, unit: Unit.usd, defaultActive: false }),
|
||||
dots({ series: r.loss.base.usd, name: "Loss", color: colors.loss, unit: Unit.usd, defaultActive: false }),
|
||||
],
|
||||
},
|
||||
@@ -898,12 +835,11 @@ export function createProfitabilitySectionWithProfitLoss({ cohort, title }) {
|
||||
name: "USD",
|
||||
title: title("Unrealized P&L"),
|
||||
bottom: [
|
||||
...pnlLines({ profit: u.profit.base.usd, loss: u.loss.base.usd, negLoss: u.loss.negative }, Unit.usd),
|
||||
...pnlLines({ profit: u.profit.usd, loss: u.loss.usd, negLoss: u.loss.negative }, Unit.usd),
|
||||
priceLine({ unit: Unit.usd, defaultActive: false }),
|
||||
],
|
||||
},
|
||||
...unrealizedCumulativeRollingTree(u.profit, u.loss, title),
|
||||
],
|
||||
],
|
||||
},
|
||||
{ name: "NUPL", title: title("NUPL"), bottom: nuplSeries(u.nupl) },
|
||||
],
|
||||
@@ -1089,12 +1025,11 @@ export function createProfitabilitySectionAddress({ cohort, title }) {
|
||||
name: "USD",
|
||||
title: title("Unrealized P&L"),
|
||||
bottom: [
|
||||
...pnlLines({ profit: u.profit.base.usd, loss: u.loss.base.usd, negLoss: u.loss.negative }, Unit.usd),
|
||||
...pnlLines({ profit: u.profit.usd, loss: u.loss.usd, negLoss: u.loss.negative }, Unit.usd),
|
||||
priceLine({ unit: Unit.usd, defaultActive: false }),
|
||||
],
|
||||
},
|
||||
...unrealizedCumulativeRollingTree(u.profit, u.loss, title),
|
||||
],
|
||||
],
|
||||
},
|
||||
{ name: "NUPL", title: title("NUPL"), bottom: nuplSeries(u.nupl) },
|
||||
],
|
||||
@@ -1178,7 +1113,7 @@ function groupedRollingRealizedCharts(list, all, title) {
|
||||
name: "Profit",
|
||||
tree: ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: title(`Realized Profit (${w.name})`),
|
||||
title: title(`Realized Profit (${w.title})`),
|
||||
bottom: mapCohortsWithAll(list, all, ({ name, color, tree }) => line({ series: tree.realized.profit.sum[w.key].usd, name, color, unit: Unit.usd })),
|
||||
})),
|
||||
},
|
||||
@@ -1186,7 +1121,7 @@ function groupedRollingRealizedCharts(list, all, title) {
|
||||
name: "Loss",
|
||||
tree: ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: title(`Realized Loss (${w.name})`),
|
||||
title: title(`Realized Loss (${w.title})`),
|
||||
bottom: mapCohortsWithAll(list, all, ({ name, color, tree }) => line({ series: tree.realized.loss.sum[w.key].usd, name, color, unit: Unit.usd })),
|
||||
})),
|
||||
},
|
||||
@@ -1207,7 +1142,7 @@ function groupedRollingRealizedChartsFull(list, all, title) {
|
||||
name: "P/L Ratio",
|
||||
tree: ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: title(`Realized P/L Ratio (${w.name})`),
|
||||
title: title(`Realized P/L Ratio (${w.title})`),
|
||||
bottom: mapCohortsWithAll(list, all, ({ name, color, tree }) =>
|
||||
baseline({ series: tree.realized.profitToLossRatio[w.key], name, color, unit: Unit.ratio, base: 1 }),
|
||||
),
|
||||
@@ -1279,7 +1214,7 @@ function groupedRealizedNetPnlDeltaTree(list, all, title) {
|
||||
},
|
||||
...ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: title(`Net Realized P&L Change (${w.name})`),
|
||||
title: title(`Net Realized P&L Change (${w.title})`),
|
||||
bottom: mapCohortsWithAll(list, all, ({ name, color, tree }) =>
|
||||
baseline({ series: tree.realized.netPnl.delta.absolute[w.key].usd, name, color, unit: Unit.usd }),
|
||||
),
|
||||
@@ -1300,7 +1235,7 @@ function groupedRealizedNetPnlDeltaTree(list, all, title) {
|
||||
},
|
||||
...ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: title(`Net Realized P&L Rate (${w.name})`),
|
||||
title: title(`Net Realized P&L Rate (${w.title})`),
|
||||
bottom: flatMapCohortsWithAll(list, all, ({ name, color, tree }) =>
|
||||
percentRatio({ pattern: tree.realized.netPnl.delta.rate[w.key], name, color }),
|
||||
),
|
||||
@@ -1399,7 +1334,7 @@ function groupedPnlChartsWithMarketCap(list, all, title) {
|
||||
name: "USD",
|
||||
title: title("Unrealized Profit"),
|
||||
bottom: mapCohortsWithAll(list, all, ({ name, color, tree }) =>
|
||||
line({ series: tree.unrealized.profit.base.usd, name, color, unit: Unit.usd }),
|
||||
line({ series: tree.unrealized.profit.usd, name, color, unit: Unit.usd }),
|
||||
),
|
||||
},
|
||||
{
|
||||
@@ -1418,7 +1353,7 @@ function groupedPnlChartsWithMarketCap(list, all, title) {
|
||||
name: "USD",
|
||||
title: title("Unrealized Loss"),
|
||||
bottom: mapCohortsWithAll(list, all, ({ name, color, tree }) =>
|
||||
line({ series: tree.unrealized.loss.base.usd, name, color, unit: Unit.usd }),
|
||||
line({ series: tree.unrealized.loss.usd, name, color, unit: Unit.usd }),
|
||||
),
|
||||
},
|
||||
{
|
||||
@@ -1453,14 +1388,14 @@ function groupedPnlChartsWithOwnMarketCap(list, all, title) {
|
||||
name: "Profit",
|
||||
title: title("Unrealized Profit"),
|
||||
bottom: mapCohortsWithAll(list, all, ({ name, color, tree }) =>
|
||||
line({ series: tree.unrealized.profit.base.usd, name, color, unit: Unit.usd }),
|
||||
line({ series: tree.unrealized.profit.usd, name, color, unit: Unit.usd }),
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "Loss",
|
||||
title: title("Unrealized Loss"),
|
||||
bottom: mapCohortsWithAll(list, all, ({ name, color, tree }) =>
|
||||
line({ series: tree.unrealized.loss.base.usd, name, color, unit: Unit.usd }),
|
||||
line({ series: tree.unrealized.loss.usd, name, color, unit: Unit.usd }),
|
||||
),
|
||||
},
|
||||
{
|
||||
@@ -1489,7 +1424,7 @@ function groupedPnlChartsLongTerm(list, all, title) {
|
||||
name: "USD",
|
||||
title: title("Unrealized Profit"),
|
||||
bottom: mapCohortsWithAll(list, all, ({ name, color, tree }) =>
|
||||
line({ series: tree.unrealized.profit.base.usd, name, color, unit: Unit.usd }),
|
||||
line({ series: tree.unrealized.profit.usd, name, color, unit: Unit.usd }),
|
||||
),
|
||||
},
|
||||
{
|
||||
@@ -1515,7 +1450,7 @@ function groupedPnlChartsLongTerm(list, all, title) {
|
||||
name: "USD",
|
||||
title: title("Unrealized Loss"),
|
||||
bottom: mapCohortsWithAll(list, all, ({ name, color, tree }) =>
|
||||
line({ series: tree.unrealized.loss.base.usd, name, color, unit: Unit.usd }),
|
||||
line({ series: tree.unrealized.loss.usd, name, color, unit: Unit.usd }),
|
||||
),
|
||||
},
|
||||
{
|
||||
@@ -1642,14 +1577,14 @@ export function createGroupedProfitabilitySectionWithProfitLoss({ list, all, tit
|
||||
name: "Profit",
|
||||
title: title("Unrealized Profit"),
|
||||
bottom: mapCohortsWithAll(list, all, ({ name, color, tree }) =>
|
||||
line({ series: tree.unrealized.profit.base.usd, name, color, unit: Unit.usd }),
|
||||
line({ series: tree.unrealized.profit.usd, name, color, unit: Unit.usd }),
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "Loss",
|
||||
title: title("Unrealized Loss"),
|
||||
bottom: mapCohortsWithAll(list, all, ({ name, color, tree }) =>
|
||||
line({ series: tree.unrealized.loss.base.usd, name, color, unit: Unit.usd }),
|
||||
line({ series: tree.unrealized.loss.usd, name, color, unit: Unit.usd }),
|
||||
),
|
||||
},
|
||||
...groupedNuplCharts(list, all, title),
|
||||
|
||||
@@ -50,9 +50,9 @@ export function createValuationSectionFull({ cohort, title }) {
|
||||
bottom: createSingleRealizedCapSeries(cohort),
|
||||
},
|
||||
{
|
||||
name: "% of Own Mcap",
|
||||
title: title("Realized Cap (% of Own Mcap)"),
|
||||
bottom: percentRatioBaseline({ pattern: tree.realized.cap.toOwnMcap, name: "Rel. to Own M.Cap", color }),
|
||||
name: "% of Own Market Cap",
|
||||
title: title("Realized Cap (% of Own Market Cap)"),
|
||||
bottom: percentRatioBaseline({ pattern: tree.realized.cap.toOwnMcap, name: "Rel. to Own Market Cap", color }),
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -140,7 +140,7 @@ export function createGroupedValuationSection({ list, all, title }) {
|
||||
name: "Absolute",
|
||||
tree: ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: title(`Realized Cap Change (${w.name})`),
|
||||
title: title(`Realized Cap Change (${w.title})`),
|
||||
bottom: mapCohortsWithAll(list, all, ({ name, color, tree }) =>
|
||||
baseline({ series: tree.realized.cap.delta.absolute[w.key].usd, name, color, unit: Unit.usd }),
|
||||
),
|
||||
@@ -150,7 +150,7 @@ export function createGroupedValuationSection({ list, all, title }) {
|
||||
name: "Rate",
|
||||
tree: ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: title(`Realized Cap Rate (${w.name})`),
|
||||
title: title(`Realized Cap Rate (${w.title})`),
|
||||
bottom: flatMapCohortsWithAll(list, all, ({ name, color, tree }) =>
|
||||
percentRatio({ pattern: tree.realized.cap.delta.rate[w.key], name, color }),
|
||||
),
|
||||
@@ -198,8 +198,8 @@ export function createGroupedValuationSectionWithOwnMarketCap({
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "% of Own Mcap",
|
||||
title: title("Realized Cap (% of Own Mcap)"),
|
||||
name: "% of Own Market Cap",
|
||||
title: title("Realized Cap (% of Own Market Cap)"),
|
||||
bottom: flatMapCohortsWithAll(list, all, ({ name, color, tree }) =>
|
||||
percentRatio({ pattern: tree.realized.cap.toOwnMcap, name, color }),
|
||||
),
|
||||
@@ -213,7 +213,7 @@ export function createGroupedValuationSectionWithOwnMarketCap({
|
||||
name: "Absolute",
|
||||
tree: ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: title(`Realized Cap Change (${w.name})`),
|
||||
title: title(`Realized Cap Change (${w.title})`),
|
||||
bottom: mapCohortsWithAll(list, all, ({ name, color, tree }) =>
|
||||
baseline({ series: tree.realized.cap.delta.absolute[w.key].usd, name, color, unit: Unit.usd }),
|
||||
),
|
||||
@@ -223,7 +223,7 @@ export function createGroupedValuationSectionWithOwnMarketCap({
|
||||
name: "Rate",
|
||||
tree: ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: title(`Realized Cap Rate (${w.name})`),
|
||||
title: title(`Realized Cap Rate (${w.title})`),
|
||||
bottom: flatMapCohortsWithAll(list, all, ({ name, color, tree }) =>
|
||||
percentRatio({ pattern: tree.realized.cap.delta.rate[w.key], name, color }),
|
||||
),
|
||||
|
||||
@@ -292,26 +292,8 @@ export function createDcaVsLumpSumSection({ dca, lookback, returns }) {
|
||||
top: topPane(key),
|
||||
});
|
||||
|
||||
/** @param {string} name @param {ShortPeriodKey} key */
|
||||
const shortReturnsChart = (name, key) => ({
|
||||
name: "Returns",
|
||||
title: `Returns: ${name} DCA vs Lump Sum`,
|
||||
top: topPane(key),
|
||||
bottom: [
|
||||
...percentRatioBaseline({
|
||||
pattern: dca.period.return[key],
|
||||
name: "DCA",
|
||||
}),
|
||||
...percentRatioBaseline({
|
||||
pattern: dca.period.lumpSumReturn[key],
|
||||
name: "Lump Sum",
|
||||
color: colors.bi.p2,
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
/** @param {string} name @param {LongPeriodKey} key */
|
||||
const longReturnsChart = (name, key) => ({
|
||||
/** @param {string} name @param {AllPeriodKey} key */
|
||||
const returnsChart = (name, key) => ({
|
||||
name: "Returns",
|
||||
title: `Returns: ${name} DCA vs Lump Sum`,
|
||||
top: topPane(key),
|
||||
@@ -372,7 +354,7 @@ export function createDcaVsLumpSumSection({ dca, lookback, returns }) {
|
||||
name,
|
||||
tree: [
|
||||
costBasisChart(name, key),
|
||||
shortReturnsChart(name, key),
|
||||
returnsChart(name, key),
|
||||
stackChart(name, key),
|
||||
],
|
||||
};
|
||||
@@ -385,7 +367,7 @@ export function createDcaVsLumpSumSection({ dca, lookback, returns }) {
|
||||
name,
|
||||
tree: [
|
||||
costBasisChart(name, key),
|
||||
longReturnsChart(name, key),
|
||||
returnsChart(name, key),
|
||||
longCagrChart(name, key),
|
||||
stackChart(name, key),
|
||||
],
|
||||
|
||||
@@ -576,7 +576,7 @@ export function createMarketSection() {
|
||||
},
|
||||
...ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: `Capitalization Growth Rate Spread ${w.name}`,
|
||||
title: `Capitalization Growth Rate Spread (${w.title})`,
|
||||
bottom: [
|
||||
baseline({
|
||||
series: supply.marketMinusRealizedCapGrowthRate[w.key],
|
||||
@@ -660,7 +660,7 @@ export function createMarketSection() {
|
||||
const rsi = technical.rsi[w.key];
|
||||
return {
|
||||
name: w.name,
|
||||
title: `RSI (${w.name})`,
|
||||
title: `RSI (${w.title})`,
|
||||
bottom: [
|
||||
...indexRatio({ pattern: rsi.rsi, name: "RSI", color: colors.indicator.main }),
|
||||
priceLine({ unit: Unit.index, number: 70 }),
|
||||
@@ -675,7 +675,7 @@ export function createMarketSection() {
|
||||
const rsi = technical.rsi[w.key];
|
||||
return {
|
||||
name: w.name,
|
||||
title: `Stochastic RSI (${w.name})`,
|
||||
title: `Stochastic RSI (${w.title})`,
|
||||
bottom: [
|
||||
...indexRatio({ pattern: rsi.stochRsiK, name: "K", color: colors.indicator.fast }),
|
||||
...indexRatio({ pattern: rsi.stochRsiD, name: "D", color: colors.indicator.slow }),
|
||||
@@ -698,7 +698,7 @@ export function createMarketSection() {
|
||||
},
|
||||
...ROLLING_WINDOWS_TO_1M.map((w) => ({
|
||||
name: w.name,
|
||||
title: `MACD (${w.name})`,
|
||||
title: `MACD (${w.title})`,
|
||||
bottom: [
|
||||
line({ series: technical.macd[w.key].line, name: "MACD", color: colors.indicator.fast, unit: Unit.usd }),
|
||||
line({ series: technical.macd[w.key].signal, name: "Signal", color: colors.indicator.slow, unit: Unit.usd }),
|
||||
@@ -726,7 +726,7 @@ export function createMarketSection() {
|
||||
},
|
||||
...ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: `Volatility Index (${w.name})`,
|
||||
title: `Volatility Index (${w.title})`,
|
||||
bottom: [line({ series: volatility[w.key], name: w.name, color: w.color, unit: Unit.percentage })],
|
||||
})),
|
||||
],
|
||||
|
||||
@@ -59,27 +59,20 @@ export function createPartialOptions() {
|
||||
} = buildCohortData();
|
||||
|
||||
return [
|
||||
// Charts section
|
||||
{
|
||||
name: "Charts",
|
||||
tree: [
|
||||
// Market section
|
||||
createMarketSection(),
|
||||
|
||||
// Network section (on-chain activity)
|
||||
createNetworkSection(),
|
||||
|
||||
// Mining section (security & economics)
|
||||
createMiningSection(),
|
||||
|
||||
// Cohorts section
|
||||
{
|
||||
name: "Distribution",
|
||||
tree: [
|
||||
// Overview - All UTXOs
|
||||
createCohortFolderAll({ ...cohortAll, name: "Overview" }),
|
||||
|
||||
// STH vs LTH - Direct comparison
|
||||
createGroupedCohortFolderWithNupl({
|
||||
name: "STH vs LTH",
|
||||
title: "STH vs LTH",
|
||||
@@ -87,17 +80,13 @@ export function createPartialOptions() {
|
||||
all: cohortAll,
|
||||
}),
|
||||
|
||||
// STH - Short term holder cohort
|
||||
createCohortFolderFull(termShort),
|
||||
|
||||
// LTH - Long term holder cohort
|
||||
createCohortFolderLongTerm(termLong),
|
||||
|
||||
// Ages cohorts
|
||||
{
|
||||
name: "UTXO Age",
|
||||
tree: [
|
||||
// Younger Than (< X old)
|
||||
{
|
||||
name: "Younger Than",
|
||||
tree: [
|
||||
@@ -110,7 +99,6 @@ export function createPartialOptions() {
|
||||
...underAge.map(createCohortFolderWithAdjusted),
|
||||
],
|
||||
},
|
||||
// Older Than (≥ X old)
|
||||
{
|
||||
name: "Older Than",
|
||||
tree: [
|
||||
@@ -123,7 +111,6 @@ export function createPartialOptions() {
|
||||
...overAge.map(createCohortFolderWithAdjusted),
|
||||
],
|
||||
},
|
||||
// Range
|
||||
{
|
||||
name: "Range",
|
||||
tree: [
|
||||
@@ -139,17 +126,15 @@ export function createPartialOptions() {
|
||||
],
|
||||
},
|
||||
|
||||
// Sizes cohorts (UTXO size)
|
||||
{
|
||||
name: "UTXO Size",
|
||||
tree: [
|
||||
// Less Than (< X sats)
|
||||
{
|
||||
name: "Less Than",
|
||||
tree: [
|
||||
createGroupedCohortFolderBasicWithMarketCap({
|
||||
name: "Compare",
|
||||
title: "Over Amount",
|
||||
title: "Under Amount",
|
||||
list: utxosUnderAmount,
|
||||
all: cohortAll,
|
||||
}),
|
||||
@@ -158,13 +143,12 @@ export function createPartialOptions() {
|
||||
),
|
||||
],
|
||||
},
|
||||
// More Than (≥ X sats)
|
||||
{
|
||||
name: "More Than",
|
||||
tree: [
|
||||
createGroupedCohortFolderBasicWithMarketCap({
|
||||
name: "Compare",
|
||||
title: "Under Amount",
|
||||
title: "Over Amount",
|
||||
list: utxosOverAmount,
|
||||
all: cohortAll,
|
||||
}),
|
||||
@@ -173,7 +157,6 @@ export function createPartialOptions() {
|
||||
),
|
||||
],
|
||||
},
|
||||
// Range
|
||||
{
|
||||
name: "Range",
|
||||
tree: [
|
||||
@@ -191,37 +174,39 @@ export function createPartialOptions() {
|
||||
],
|
||||
},
|
||||
|
||||
// Balances cohorts (Address balance)
|
||||
createUtxoProfitabilitySection({
|
||||
range: profitabilityRange,
|
||||
profit: profitabilityProfit,
|
||||
loss: profitabilityLoss,
|
||||
}),
|
||||
|
||||
{
|
||||
name: "Address Balance",
|
||||
tree: [
|
||||
// Less Than (< X sats)
|
||||
{
|
||||
name: "Less Than",
|
||||
tree: [
|
||||
createGroupedAddressCohortFolder({
|
||||
name: "Compare",
|
||||
title: "Over Balance",
|
||||
title: "Under Balance",
|
||||
list: addressesUnderAmount,
|
||||
all: cohortAll,
|
||||
}),
|
||||
...addressesUnderAmount.map(createAddressCohortFolder),
|
||||
],
|
||||
},
|
||||
// More Than (≥ X sats)
|
||||
{
|
||||
name: "More Than",
|
||||
tree: [
|
||||
createGroupedAddressCohortFolder({
|
||||
name: "Compare",
|
||||
title: "Under Balance",
|
||||
title: "Over Balance",
|
||||
list: addressesOverAmount,
|
||||
all: cohortAll,
|
||||
}),
|
||||
...addressesOverAmount.map(createAddressCohortFolder),
|
||||
],
|
||||
},
|
||||
// Range
|
||||
{
|
||||
name: "Range",
|
||||
tree: [
|
||||
@@ -237,7 +222,6 @@ export function createPartialOptions() {
|
||||
],
|
||||
},
|
||||
|
||||
// Script Types - addressable types have addrCount, others don't
|
||||
{
|
||||
name: "Script Type",
|
||||
tree: [
|
||||
@@ -252,7 +236,6 @@ export function createPartialOptions() {
|
||||
],
|
||||
},
|
||||
|
||||
// Epochs
|
||||
{
|
||||
name: "Epoch",
|
||||
tree: [
|
||||
@@ -266,7 +249,6 @@ export function createPartialOptions() {
|
||||
],
|
||||
},
|
||||
|
||||
// Classes
|
||||
{
|
||||
name: "Class",
|
||||
tree: [
|
||||
@@ -279,20 +261,11 @@ export function createPartialOptions() {
|
||||
...class_.map(createCohortFolderWithAdjusted),
|
||||
],
|
||||
},
|
||||
|
||||
// UTXO Profitability bands
|
||||
createUtxoProfitabilitySection({
|
||||
range: profitabilityRange,
|
||||
profit: profitabilityProfit,
|
||||
loss: profitabilityLoss,
|
||||
}),
|
||||
],
|
||||
},
|
||||
|
||||
// Investing section
|
||||
createInvestingSection(),
|
||||
|
||||
// Frameworks section
|
||||
{
|
||||
name: "Frameworks",
|
||||
tree: [createCointimeSection()],
|
||||
@@ -300,14 +273,12 @@ export function createPartialOptions() {
|
||||
],
|
||||
},
|
||||
|
||||
// API documentation
|
||||
{
|
||||
name: "API",
|
||||
url: () => "/api",
|
||||
title: "API documentation",
|
||||
},
|
||||
|
||||
// Project link
|
||||
{
|
||||
name: "Source",
|
||||
url: () => "https://bitcoinresearchkit.org",
|
||||
|
||||
@@ -17,11 +17,11 @@ export const ROLLING_WINDOWS = [
|
||||
{ key: "_1y", name: "1y", title: "Yearly", color: colors.time._1y },
|
||||
];
|
||||
|
||||
/** @type {ReadonlyArray<{key: '_24h' | '_1w' | '_1m', name: string, color: Color}>} */
|
||||
/** @type {ReadonlyArray<{key: '_24h' | '_1w' | '_1m', name: string, title: string, color: Color}>} */
|
||||
export const ROLLING_WINDOWS_TO_1M = [
|
||||
{ key: "_24h", name: "24h", color: colors.time._24h },
|
||||
{ key: "_1w", name: "1w", color: colors.time._1w },
|
||||
{ key: "_1m", name: "1m", color: colors.time._1m },
|
||||
{ key: "_24h", name: "24h", title: "Daily", color: colors.time._24h },
|
||||
{ key: "_1w", name: "1w", title: "Weekly", color: colors.time._1w },
|
||||
{ key: "_1m", name: "1m", title: "Monthly", color: colors.time._1m },
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -604,7 +604,7 @@ export function distributionWindowsTree({ pattern, base, title, unit }) {
|
||||
},
|
||||
...ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: `${title} Distribution (${w.name})`,
|
||||
title: `${title} Distribution (${w.title})`,
|
||||
bottom: [
|
||||
...(base ? [line({ series: base, name: "base", unit })] : []),
|
||||
...fromStatsPattern({
|
||||
@@ -755,15 +755,22 @@ export function percentRatioDots({ pattern, name, color, defaultActive }) {
|
||||
* @param {boolean} [args.defaultActive]
|
||||
* @returns {AnyFetchedSeriesBlueprint[]}
|
||||
*/
|
||||
export function percentRatioBaseline({ pattern, name, defaultActive }) {
|
||||
export function percentRatioBaseline({ pattern, name, color, defaultActive }) {
|
||||
return [
|
||||
baseline({
|
||||
series: pattern.percent,
|
||||
name,
|
||||
color,
|
||||
defaultActive,
|
||||
unit: Unit.percentage,
|
||||
}),
|
||||
baseline({ series: pattern.ratio, name, defaultActive, unit: Unit.ratio }),
|
||||
baseline({
|
||||
series: pattern.ratio,
|
||||
name,
|
||||
color,
|
||||
defaultActive,
|
||||
unit: Unit.ratio,
|
||||
}),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -798,7 +805,7 @@ export function rollingPercentRatioTree({
|
||||
},
|
||||
...ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: `${title} ${w.name}`,
|
||||
title: `${title} (${w.title})`,
|
||||
bottom: series({ pattern: windows[w.key], name: w.name }),
|
||||
})),
|
||||
],
|
||||
@@ -834,7 +841,7 @@ export function deltaTree({ delta, title, unit, extract }) {
|
||||
},
|
||||
...ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: `${title} Change ${w.name}`,
|
||||
title: `${title} Change (${w.title})`,
|
||||
bottom: [
|
||||
baseline({
|
||||
series: extract(delta.absolute[w.key]),
|
||||
|
||||
Reference in New Issue
Block a user