import { Unit } from "../utils/units.js"; import { priceLine, priceLines } from "./constants.js"; import { line, baseline } from "./series.js"; import { satsBtcUsd, percentileUsdMap, percentileMap, sdPatterns, sdBandsUsd, sdBandsRatio, } 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", unit: Unit.ratio, base: 1, }), 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 }), ...sdBandsUsd(colors, sd).map( ({ name: bandName, prop, color: bandColor }) => line({ metric: prop, name: bandName, color: bandColor, unit: Unit.usd, defaultActive: false, }), ), ], bottom: [ baseline({ metric: sd.zscore, name: "Z-Score", unit: Unit.sd, }), baseline({ metric: ratio.ratio, name: "Ratio", unit: Unit.ratio, base: 1, }), line({ metric: sd.sd, name: "Volatility", color: colors.gray, unit: Unit.percentage, }), ...sdBandsRatio(colors, sd).map( ({ name: bandName, prop, color: bandColor }) => line({ metric: prop, name: bandName, color: bandColor, unit: Unit.ratio, defaultActive: false, }), ), ...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, }), ], }, ], }, ], }; }