mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-04-24 14:49:58 -07:00
global: v0.2 incoming
This commit is contained in:
@@ -66,7 +66,7 @@ function volumeTree(tv, color, title) {
|
||||
})),
|
||||
{
|
||||
name: "Cumulative",
|
||||
title: title("Cumulative Transfer Volume"),
|
||||
title: title("Cumulative Transfer Volume Profitability"),
|
||||
bottom: [
|
||||
...satsBtcUsd({
|
||||
pattern: tv.inProfit.cumulative,
|
||||
@@ -231,7 +231,7 @@ function singleSellSideRiskTree(sellSideRisk, title) {
|
||||
title: title(`${w.title} Sell Side Risk`),
|
||||
bottom: percentRatio({
|
||||
pattern: sellSideRisk[w.key],
|
||||
name: "Risk",
|
||||
name: "Sell Side Risk",
|
||||
color: w.color,
|
||||
}),
|
||||
})),
|
||||
@@ -381,7 +381,7 @@ export function createGroupedActivitySectionMinimal({ list, all, title }) {
|
||||
return {
|
||||
name: "Activity",
|
||||
tree: groupedWindowsCumulativeSatsBtcUsd({
|
||||
list, all, title, metricTitle: "Volume",
|
||||
list, all, title, metricTitle: "Transfer Volume",
|
||||
getMetric: (c) => c.tree.activity.transferVolume,
|
||||
}),
|
||||
};
|
||||
|
||||
@@ -28,7 +28,7 @@ function percentileSeries(p, n = (x) => x) {
|
||||
.map(([key, s], i, arr) =>
|
||||
price({
|
||||
series: s,
|
||||
name: n(key.replace("pct", "p")),
|
||||
name: n(key.replace("pct", "P")),
|
||||
color: colors.at(i, arr.length),
|
||||
...(ACTIVE_PCTS.has(key) ? {} : { defaultActive: false }),
|
||||
}),
|
||||
@@ -70,9 +70,9 @@ function singleWeightFolder({ avgPrice, avgName, inProfit, inLoss, percentiles,
|
||||
title: title(`Cost Basis Distribution (${weightLabel})`),
|
||||
top: [
|
||||
price({ series: avgPrice, name: avgName, color }),
|
||||
...(max ? [price({ series: max, name: "p100", color: colors.stat.max, defaultActive: false })] : []),
|
||||
...(max ? [price({ series: max, name: "P100", color: colors.stat.max, defaultActive: false })] : []),
|
||||
...percentileSeries(percentiles),
|
||||
...(min ? [price({ series: min, name: "p0", color: colors.stat.min, defaultActive: false })] : []),
|
||||
...(min ? [price({ series: min, name: "P0", color: colors.stat.min, defaultActive: false })] : []),
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
@@ -18,12 +18,14 @@ import {
|
||||
rollingPercentRatioTree,
|
||||
percentRatio,
|
||||
percentRatioBaseline,
|
||||
chartsFromCount,
|
||||
} from "../series.js";
|
||||
import {
|
||||
satsBtcUsd,
|
||||
flatMapCohorts,
|
||||
mapCohortsWithAll,
|
||||
flatMapCohortsWithAll,
|
||||
groupedWindowsCumulative,
|
||||
} from "../shared.js";
|
||||
import { colors } from "../../utils/colors.js";
|
||||
import { priceLines } from "../constants.js";
|
||||
@@ -46,18 +48,39 @@ function simpleSupplySeries(supply) {
|
||||
* @param {CohortAll} all
|
||||
* @param {(name: string) => string} title
|
||||
*/
|
||||
function groupedUtxoCountFolder(list, all, title) {
|
||||
function groupedOutputsFolder(list, all, title) {
|
||||
return {
|
||||
name: "UTXOs",
|
||||
name: "Outputs",
|
||||
tree: [
|
||||
{
|
||||
name: "Count",
|
||||
title: title("UTXO Count"),
|
||||
name: "Unspent",
|
||||
tree: [
|
||||
{
|
||||
name: "Count",
|
||||
title: title("UTXO Count"),
|
||||
bottom: mapCohortsWithAll(list, all, ({ name, color, tree }) =>
|
||||
line({ series: tree.outputs.unspentCount.base, name, color, unit: Unit.count }),
|
||||
),
|
||||
},
|
||||
...groupedDeltaItems(list, all, (c) => c.tree.outputs.unspentCount.delta, Unit.count, title, "UTXO Count"),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Spent",
|
||||
tree: groupedWindowsCumulative({
|
||||
list, all, title, metricTitle: "Spent UTXO Count",
|
||||
getWindowSeries: (c, key) => c.tree.outputs.spentCount.sum[key],
|
||||
getCumulativeSeries: (c) => c.tree.outputs.spentCount.cumulative,
|
||||
seriesFn: line, unit: Unit.count,
|
||||
}),
|
||||
},
|
||||
{
|
||||
name: "Spending Rate",
|
||||
title: title("Spending Rate"),
|
||||
bottom: mapCohortsWithAll(list, all, ({ name, color, tree }) =>
|
||||
line({ series: tree.outputs.unspentCount.base, name, color, unit: Unit.count }),
|
||||
line({ series: tree.outputs.spendingRate, name, color, unit: Unit.ratio }),
|
||||
),
|
||||
},
|
||||
...groupedDeltaItems(list, all, (c) => c.tree.outputs.unspentCount.delta, Unit.count, title, "UTXO Count"),
|
||||
],
|
||||
};
|
||||
}
|
||||
@@ -211,7 +234,32 @@ function ownSupplyChart(supply, title) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Count folder (UTXO or Address) with value + change
|
||||
* @param {OutputsPattern} outputs
|
||||
* @param {Color} color
|
||||
* @param {(name: string) => string} title
|
||||
* @returns {PartialOptionsGroup}
|
||||
*/
|
||||
function outputsFolder(outputs, color, title) {
|
||||
return {
|
||||
name: "Outputs",
|
||||
tree: [
|
||||
countFolder(outputs.unspentCount, "Unspent", "UTXO Count", color, title),
|
||||
{
|
||||
name: "Spent",
|
||||
tree: chartsFromCount({ pattern: outputs.spentCount, title, metric: "Spent UTXO Count", unit: Unit.count, color }),
|
||||
},
|
||||
{
|
||||
name: "Spending Rate",
|
||||
title: title("Spending Rate"),
|
||||
bottom: [
|
||||
line({ series: outputs.spendingRate, name: "Rate", color, unit: Unit.ratio }),
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {{ base: AnySeriesPattern, delta: DeltaPattern }} pattern
|
||||
* @param {string} name
|
||||
* @param {string} chartTitle
|
||||
@@ -262,7 +310,7 @@ export function createHoldingsSection({ cohort, title }) {
|
||||
...singleDeltaItems(supply.delta, Unit.sats, title, "Supply"),
|
||||
],
|
||||
},
|
||||
countFolder(cohort.tree.outputs.unspentCount, "UTXOs", "UTXO Count", cohort.color, title),
|
||||
outputsFolder(cohort.tree.outputs, cohort.color, title),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -286,7 +334,7 @@ export function createHoldingsSectionAll({ cohort, title }) {
|
||||
...singleDeltaItems(supply.delta, Unit.sats, title, "Supply"),
|
||||
],
|
||||
},
|
||||
countFolder(cohort.tree.outputs.unspentCount, "UTXOs", "UTXO Count", cohort.color, title),
|
||||
outputsFolder(cohort.tree.outputs, cohort.color, title),
|
||||
countFolder(cohort.addressCount, "Addresses", "Address Count", cohort.color, title),
|
||||
];
|
||||
}
|
||||
@@ -312,7 +360,7 @@ export function createHoldingsSectionWithRelative({ cohort, title }) {
|
||||
...singleDeltaItems(supply.delta, Unit.sats, title, "Supply"),
|
||||
],
|
||||
},
|
||||
countFolder(cohort.tree.outputs.unspentCount, "UTXOs", "UTXO Count", cohort.color, title),
|
||||
outputsFolder(cohort.tree.outputs, cohort.color, title),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -336,7 +384,7 @@ export function createHoldingsSectionWithOwnSupply({ cohort, title }) {
|
||||
...singleDeltaItems(supply.delta, Unit.sats, title, "Supply"),
|
||||
],
|
||||
},
|
||||
countFolder(cohort.tree.outputs.unspentCount, "UTXOs", "UTXO Count", cohort.color, title),
|
||||
outputsFolder(cohort.tree.outputs, cohort.color, title),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -359,7 +407,7 @@ export function createHoldingsSectionWithProfitLoss({ cohort, title }) {
|
||||
...singleDeltaItems(supply.delta, Unit.sats, title, "Supply"),
|
||||
],
|
||||
},
|
||||
countFolder(cohort.tree.outputs.unspentCount, "UTXOs", "UTXO Count", cohort.color, title),
|
||||
outputsFolder(cohort.tree.outputs, cohort.color, title),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -382,7 +430,7 @@ export function createHoldingsSectionAddress({ cohort, title }) {
|
||||
...singleDeltaItems(supply.delta, Unit.sats, title, "Supply"),
|
||||
],
|
||||
},
|
||||
countFolder(cohort.tree.outputs.unspentCount, "UTXOs", "UTXO Count", cohort.color, title),
|
||||
outputsFolder(cohort.tree.outputs, cohort.color, title),
|
||||
countFolder(cohort.addressCount, "Addresses", "Address Count", cohort.color, title),
|
||||
];
|
||||
}
|
||||
@@ -405,7 +453,7 @@ export function createHoldingsSectionAddressAmount({ cohort, title }) {
|
||||
...singleDeltaItems(supply.delta, Unit.sats, title, "Supply"),
|
||||
],
|
||||
},
|
||||
countFolder(cohort.tree.outputs.unspentCount, "UTXOs", "UTXO Count", cohort.color, title),
|
||||
outputsFolder(cohort.tree.outputs, cohort.color, title),
|
||||
countFolder(cohort.addressCount, "Addresses", "Address Count", cohort.color, title),
|
||||
];
|
||||
}
|
||||
@@ -457,7 +505,7 @@ export function createGroupedHoldingsSectionAddress({ list, all, title }) {
|
||||
...groupedDeltaItems(list, all, (c) => c.tree.supply.delta, Unit.sats, title, "Supply"),
|
||||
],
|
||||
},
|
||||
groupedUtxoCountFolder(list, all, title),
|
||||
groupedOutputsFolder(list, all, title),
|
||||
{
|
||||
name: "Addresses",
|
||||
tree: [
|
||||
@@ -488,7 +536,7 @@ export function createGroupedHoldingsSectionAddressAmount({ list, all, title })
|
||||
...groupedDeltaItems(list, all, (c) => c.tree.supply.delta, Unit.sats, title, "Supply"),
|
||||
],
|
||||
},
|
||||
groupedUtxoCountFolder(list, all, title),
|
||||
groupedOutputsFolder(list, all, title),
|
||||
{
|
||||
name: "Addresses",
|
||||
tree: [
|
||||
@@ -515,7 +563,7 @@ export function createGroupedHoldingsSection({ list, all, title }) {
|
||||
...groupedDeltaItems(list, all, (c) => c.tree.supply.delta, Unit.sats, title, "Supply"),
|
||||
],
|
||||
},
|
||||
groupedUtxoCountFolder(list, all, title),
|
||||
groupedOutputsFolder(list, all, title),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -530,7 +578,7 @@ export function createGroupedHoldingsSectionWithProfitLoss({ list, all, title })
|
||||
...groupedDeltaItems(list, all, (c) => c.tree.supply.delta, Unit.sats, title, "Supply"),
|
||||
],
|
||||
},
|
||||
groupedUtxoCountFolder(list, all, title),
|
||||
groupedOutputsFolder(list, all, title),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -546,7 +594,7 @@ export function createGroupedHoldingsSectionWithOwnSupply({ list, all, title })
|
||||
...groupedDeltaItems(list, all, (c) => c.tree.supply.delta, Unit.sats, title, "Supply"),
|
||||
],
|
||||
},
|
||||
groupedUtxoCountFolder(list, all, title),
|
||||
groupedOutputsFolder(list, all, title),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -568,6 +616,6 @@ export function createGroupedHoldingsSectionWithRelative({ list, all, title }) {
|
||||
...groupedDeltaItems(list, all, (c) => c.tree.supply.delta, Unit.sats, title, "Supply"),
|
||||
],
|
||||
},
|
||||
groupedUtxoCountFolder(list, all, title),
|
||||
groupedOutputsFolder(list, all, title),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -496,10 +496,11 @@ export function createGroupedAddressCohortFolder({
|
||||
|
||||
/**
|
||||
* @param {{ name: string, color: Color, pattern: RealizedSupplyPattern }} bucket
|
||||
* @param {string} [parentName]
|
||||
* @returns {PartialOptionsGroup}
|
||||
*/
|
||||
function singleBucketFolder({ name, color, pattern }) {
|
||||
const title = formatCohortTitle(name);
|
||||
function singleBucketFolder({ name, color, pattern }, parentName) {
|
||||
const title = formatCohortTitle(parentName ? `${parentName} ${name}` : name);
|
||||
return {
|
||||
name,
|
||||
tree: [
|
||||
@@ -507,7 +508,7 @@ function singleBucketFolder({ name, color, pattern }) {
|
||||
name: "Supply",
|
||||
tree: [
|
||||
{
|
||||
name: "Value",
|
||||
name: "Total",
|
||||
title: title("Supply"),
|
||||
bottom: [
|
||||
...satsBtcUsd({ pattern: pattern.supply.all, name: "Total" }),
|
||||
@@ -519,26 +520,21 @@ function singleBucketFolder({ name, color, pattern }) {
|
||||
],
|
||||
},
|
||||
{
|
||||
...sumsTreeBaseline({
|
||||
windows: pattern.supply.all.delta.absolute,
|
||||
title,
|
||||
metric: "Supply Change",
|
||||
unit: Unit.sats,
|
||||
}),
|
||||
name: "Change",
|
||||
tree: [
|
||||
{
|
||||
...sumsTreeBaseline({
|
||||
windows: pattern.supply.all.delta.absolute,
|
||||
title,
|
||||
metric: "Supply Change",
|
||||
unit: Unit.sats,
|
||||
}),
|
||||
name: "Change",
|
||||
},
|
||||
{
|
||||
...rollingPercentRatioTree({
|
||||
windows: pattern.supply.all.delta.rate,
|
||||
title,
|
||||
metric: "Supply Growth Rate",
|
||||
}),
|
||||
name: "Growth Rate",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
...rollingPercentRatioTree({
|
||||
windows: pattern.supply.all.delta.rate,
|
||||
title,
|
||||
metric: "Supply Growth Rate",
|
||||
}),
|
||||
name: "Growth Rate",
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -559,6 +555,23 @@ function singleBucketFolder({ name, color, pattern }) {
|
||||
}),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Unrealized PnL",
|
||||
title: title("Unrealized PnL"),
|
||||
bottom: [
|
||||
line({
|
||||
series: pattern.unrealizedPnl.all,
|
||||
name: "Total",
|
||||
unit: Unit.usd,
|
||||
}),
|
||||
line({
|
||||
series: pattern.unrealizedPnl.sth,
|
||||
name: "STH",
|
||||
color: colors.term.short,
|
||||
unit: Unit.usd,
|
||||
}),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "NUPL",
|
||||
title: title("NUPL"),
|
||||
@@ -599,65 +612,60 @@ function groupedBucketCharts(list, groupTitle) {
|
||||
name: "Change",
|
||||
tree: [
|
||||
{
|
||||
name: "Change",
|
||||
tree: [
|
||||
{
|
||||
name: "Compare",
|
||||
title: title("Supply Change"),
|
||||
bottom: ROLLING_WINDOWS.flatMap((w) =>
|
||||
list.map(({ name, color, pattern }) =>
|
||||
baseline({
|
||||
series: pattern.supply.all.delta.absolute[w.key],
|
||||
name: `${name} ${w.name}`,
|
||||
color,
|
||||
unit: Unit.sats,
|
||||
}),
|
||||
),
|
||||
),
|
||||
},
|
||||
...ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: title(`${w.title} Supply Change`),
|
||||
bottom: list.map(({ name, color, pattern }) =>
|
||||
baseline({
|
||||
series: pattern.supply.all.delta.absolute[w.key],
|
||||
name,
|
||||
color,
|
||||
unit: Unit.sats,
|
||||
}),
|
||||
),
|
||||
})),
|
||||
],
|
||||
name: "Compare",
|
||||
title: title("Supply Change"),
|
||||
bottom: ROLLING_WINDOWS.flatMap((w) =>
|
||||
list.map(({ name, color, pattern }) =>
|
||||
baseline({
|
||||
series: pattern.supply.all.delta.absolute[w.key],
|
||||
name: `${name} ${w.name}`,
|
||||
color,
|
||||
unit: Unit.sats,
|
||||
}),
|
||||
),
|
||||
),
|
||||
},
|
||||
...ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: title(`${w.title} Supply Change`),
|
||||
bottom: list.map(({ name, color, pattern }) =>
|
||||
baseline({
|
||||
series: pattern.supply.all.delta.absolute[w.key],
|
||||
name,
|
||||
color,
|
||||
unit: Unit.sats,
|
||||
}),
|
||||
),
|
||||
})),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Growth Rate",
|
||||
tree: [
|
||||
{
|
||||
name: "Growth Rate",
|
||||
tree: [
|
||||
{
|
||||
name: "Compare",
|
||||
title: title("Supply Growth Rate"),
|
||||
bottom: ROLLING_WINDOWS.flatMap((w) =>
|
||||
list.flatMap(({ name, color, pattern }) =>
|
||||
percentRatio({
|
||||
pattern: pattern.supply.all.delta.rate[w.key],
|
||||
name: `${name} ${w.name}`,
|
||||
color,
|
||||
}),
|
||||
),
|
||||
),
|
||||
},
|
||||
...ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: title(`${w.title} Supply Growth Rate`),
|
||||
bottom: list.flatMap(({ name, color, pattern }) =>
|
||||
percentRatio({
|
||||
pattern: pattern.supply.all.delta.rate[w.key],
|
||||
name,
|
||||
color,
|
||||
}),
|
||||
),
|
||||
})),
|
||||
],
|
||||
name: "Compare",
|
||||
title: title("Supply Growth Rate"),
|
||||
bottom: ROLLING_WINDOWS.flatMap((w) =>
|
||||
list.flatMap(({ name, color, pattern }) =>
|
||||
percentRatio({
|
||||
pattern: pattern.supply.all.delta.rate[w.key],
|
||||
name: `${name} ${w.name}`,
|
||||
color,
|
||||
}),
|
||||
),
|
||||
),
|
||||
},
|
||||
...ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: title(`${w.title} Supply Growth Rate`),
|
||||
bottom: list.flatMap(({ name, color, pattern }) =>
|
||||
percentRatio({
|
||||
pattern: pattern.supply.all.delta.rate[w.key],
|
||||
name,
|
||||
color,
|
||||
}),
|
||||
),
|
||||
})),
|
||||
],
|
||||
},
|
||||
],
|
||||
@@ -691,6 +699,35 @@ function groupedBucketCharts(list, groupTitle) {
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Unrealized PnL",
|
||||
tree: [
|
||||
{
|
||||
name: "All",
|
||||
title: title("Unrealized PnL"),
|
||||
bottom: list.map(({ name, color, pattern }) =>
|
||||
line({
|
||||
series: pattern.unrealizedPnl.all,
|
||||
name,
|
||||
color,
|
||||
unit: Unit.usd,
|
||||
}),
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "STH",
|
||||
title: title("STH Unrealized PnL"),
|
||||
bottom: list.map(({ name, color, pattern }) =>
|
||||
line({
|
||||
series: pattern.unrealizedPnl.sth,
|
||||
name,
|
||||
color,
|
||||
unit: Unit.usd,
|
||||
}),
|
||||
),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "NUPL",
|
||||
title: title("NUPL"),
|
||||
@@ -716,21 +753,21 @@ export function createUtxoProfitabilitySection({ range, profit, loss }) {
|
||||
name: "Compare",
|
||||
tree: groupedBucketCharts(range, "Profitability Range"),
|
||||
},
|
||||
...range.map(singleBucketFolder),
|
||||
...range.map((bucket) => singleBucketFolder(bucket)),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "In Profit",
|
||||
tree: [
|
||||
{ name: "Compare", tree: groupedBucketCharts(profit, "In Profit") },
|
||||
...profit.map(singleBucketFolder),
|
||||
...profit.map((bucket) => singleBucketFolder(bucket, "In Profit")),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "In Loss",
|
||||
tree: [
|
||||
{ name: "Compare", tree: groupedBucketCharts(loss, "In Loss") },
|
||||
...loss.map(singleBucketFolder),
|
||||
...loss.map((bucket) => singleBucketFolder(bucket, "In Loss")),
|
||||
],
|
||||
},
|
||||
],
|
||||
|
||||
@@ -40,7 +40,7 @@ export function createPricesSectionFull({ cohort, title }) {
|
||||
{
|
||||
name: "Realized",
|
||||
tree: createPriceRatioCharts({
|
||||
context: cohort.name,
|
||||
context: cohort.title,
|
||||
legend: "Realized",
|
||||
pricePattern: tree.realized.price,
|
||||
ratio: tree.realized.price,
|
||||
@@ -54,6 +54,7 @@ export function createPricesSectionFull({ cohort, title }) {
|
||||
tree: priceRatioPercentilesTree({
|
||||
pattern: tree.realized.investor.price,
|
||||
title: title("Investor Price"),
|
||||
ratioTitle: title("Investor Price Ratio"),
|
||||
legend: "Investor",
|
||||
color,
|
||||
}),
|
||||
@@ -82,24 +83,12 @@ export function createPricesSectionBasic({ cohort, title }) {
|
||||
top: [price({ series: tree.realized.price, name: "Realized", color })],
|
||||
},
|
||||
{
|
||||
name: "MVRV",
|
||||
title: title("MVRV"),
|
||||
bottom: [
|
||||
baseline({
|
||||
series: tree.realized.mvrv,
|
||||
name: "MVRV",
|
||||
unit: Unit.ratio,
|
||||
base: 1,
|
||||
}),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Price Ratio",
|
||||
name: "Ratio",
|
||||
title: title("Realized Price Ratio"),
|
||||
bottom: [
|
||||
baseline({
|
||||
series: tree.realized.price.ratio,
|
||||
name: "Price Ratio",
|
||||
name: "Ratio",
|
||||
unit: Unit.ratio,
|
||||
base: 1,
|
||||
}),
|
||||
@@ -136,7 +125,7 @@ function groupedRealizedPriceItems(list, all, title) {
|
||||
},
|
||||
{
|
||||
name: "Ratio",
|
||||
title: title("MVRV"),
|
||||
title: title("Realized Price Ratio"),
|
||||
bottom: mapCohortsWithAll(list, all, ({ name, color, tree }) =>
|
||||
baseline({ series: tree.realized.mvrv, name, color, unit: Unit.ratio, base: 1 }),
|
||||
),
|
||||
|
||||
@@ -61,7 +61,7 @@ function unrealizedOverview(profit, loss, netPnlUsd, title) {
|
||||
}),
|
||||
dotted({
|
||||
series: loss.negative,
|
||||
name: "Neg. Loss",
|
||||
name: "Negated Loss",
|
||||
color: colors.loss,
|
||||
unit: Unit.usd,
|
||||
}),
|
||||
@@ -233,12 +233,19 @@ function unrealizedTreeLongTerm(u, title) {
|
||||
ownPnlChart(u, title),
|
||||
{
|
||||
name: "% of Market Cap",
|
||||
title: title("Unrealized Loss (% of Market Cap)"),
|
||||
bottom: percentRatio({
|
||||
pattern: u.loss.toMcap,
|
||||
name: "Loss",
|
||||
color: colors.loss,
|
||||
}),
|
||||
title: title("Unrealized P&L (% of Market Cap)"),
|
||||
bottom: [
|
||||
...percentRatio({
|
||||
pattern: u.profit.toMcap,
|
||||
name: "Profit",
|
||||
color: colors.profit,
|
||||
}),
|
||||
...percentRatio({
|
||||
pattern: u.loss.toMcap,
|
||||
name: "Loss",
|
||||
color: colors.loss,
|
||||
}),
|
||||
],
|
||||
},
|
||||
relPnlChartWithNet(u.netPnl.toOwnMcap, u.profit.toOwnMcap, u.loss.toOwnMcap, "% of Own Market Cap", title),
|
||||
];
|
||||
@@ -448,7 +455,7 @@ function realizedOverviewFolder({
|
||||
}),
|
||||
dotted({
|
||||
series: loss.negative.sum[w.key],
|
||||
name: "Neg. Loss",
|
||||
name: "Negated Loss",
|
||||
color: colors.loss,
|
||||
unit: Unit.usd,
|
||||
}),
|
||||
@@ -518,7 +525,7 @@ function realizedSubfolderFull(r, title) {
|
||||
title: title("Net Realized P&L Change (% of Market Cap)"),
|
||||
bottom: percentRatioBaseline({
|
||||
pattern: r.netPnl.change1m.toMcap,
|
||||
name: "30d Change",
|
||||
name: "1m Change",
|
||||
}),
|
||||
},
|
||||
{
|
||||
@@ -526,7 +533,7 @@ function realizedSubfolderFull(r, title) {
|
||||
title: title("Net Realized P&L Change (% of Realized Cap)"),
|
||||
bottom: percentRatioBaseline({
|
||||
pattern: r.netPnl.change1m.toRcap,
|
||||
name: "30d Change",
|
||||
name: "1m Change",
|
||||
}),
|
||||
},
|
||||
],
|
||||
@@ -740,7 +747,7 @@ export function createProfitabilitySectionWithProfitLoss({ cohort, title }) {
|
||||
title: title("Unrealized P&L"),
|
||||
bottom: [
|
||||
line({ series: u.profit.usd, name: "Profit", color: colors.profit, unit: Unit.usd }),
|
||||
line({ series: u.loss.negative, name: "Neg. Loss", color: colors.loss, unit: Unit.usd }),
|
||||
line({ series: u.loss.negative, name: "Negated Loss", color: colors.loss, unit: Unit.usd }),
|
||||
line({ series: u.loss.usd, name: "Loss", color: colors.loss, unit: Unit.usd, defaultActive: false }),
|
||||
priceLine({ unit: Unit.usd }),
|
||||
],
|
||||
@@ -997,7 +1004,7 @@ function groupedRealizedSubfolderFull(list, all, title) {
|
||||
list,
|
||||
all,
|
||||
title,
|
||||
metricTitle: "Gross Realized P&L",
|
||||
metricTitle: "Realized Gross P&L",
|
||||
getMetric: (c) => c.tree.realized.grossPnl,
|
||||
}),
|
||||
},
|
||||
|
||||
@@ -89,7 +89,7 @@ export function createValuationSectionFull({ cohort, title }) {
|
||||
},
|
||||
{ name: "MVRV", title: title("MVRV"), bottom: ratioBottomSeries(tree.realized.price) },
|
||||
...singleDeltaItems(tree, title),
|
||||
{ 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 }) },
|
||||
{ name: "% of Own Market Cap", title: title("Realized Cap (% of Own Market Cap)"), bottom: percentRatioBaseline({ pattern: tree.realized.cap.toOwnMcap, name: "% of Own Market Cap", color }) },
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user