mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-07-14 12:38:13 -07:00
git: reset
This commit is contained in:
@@ -0,0 +1,218 @@
|
||||
import {
|
||||
addressCohortsBySize,
|
||||
addressCohortsByType,
|
||||
} from "../../datasets/consts/address";
|
||||
import { liquidities } from "../../datasets/consts/liquidities";
|
||||
import { colors } from "../../utils/colors";
|
||||
import { createCohortPresetList } from "../templates/cohort";
|
||||
import { applyMultipleSeries, SeriesType } from "../templates/multiple";
|
||||
|
||||
export function createPresets({
|
||||
scale,
|
||||
datasets,
|
||||
}: {
|
||||
scale: ResourceScale;
|
||||
datasets: Datasets;
|
||||
}): PartialPresetFolder {
|
||||
return {
|
||||
name: "Addresses",
|
||||
tree: [
|
||||
{
|
||||
scale,
|
||||
name: `Total Non Empty Addresses`,
|
||||
title: `Total Non Empty Address`,
|
||||
description: "",
|
||||
icon: IconTablerWallet,
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: `Total Non Empty Address`,
|
||||
color: colors.bitcoin,
|
||||
seriesType: SeriesType.Area,
|
||||
dataset: params.datasets[scale].address_count,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
scale,
|
||||
name: `New Addresses`,
|
||||
title: `New Addresses`,
|
||||
description: "",
|
||||
icon: IconTablerSparkles,
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: `New Addresses`,
|
||||
color: colors.white,
|
||||
dataset: params.datasets[scale].created_addresses,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
scale,
|
||||
name: `Total Addresses Created`,
|
||||
title: `Total Addresses Created`,
|
||||
description: "",
|
||||
icon: IconTablerArchive,
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: `Total Addresses Created`,
|
||||
color: colors.bitcoin,
|
||||
seriesType: SeriesType.Area,
|
||||
dataset: params.datasets[scale].created_addresses,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
scale,
|
||||
name: `Total Empty Addresses`,
|
||||
title: `Total Empty Addresses`,
|
||||
description: "",
|
||||
icon: IconTablerTrash,
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: `Total Empty Addresses`,
|
||||
color: colors.darkWhite,
|
||||
seriesType: SeriesType.Area,
|
||||
dataset: params.datasets[scale].empty_addresses,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "By Size",
|
||||
tree: addressCohortsBySize.map(({ key, name }) =>
|
||||
createAddressPresetFolder({
|
||||
datasets,
|
||||
scale,
|
||||
color: colors[key],
|
||||
name,
|
||||
datasetKey: key,
|
||||
}),
|
||||
),
|
||||
},
|
||||
{
|
||||
scale,
|
||||
name: "By Type",
|
||||
tree: addressCohortsByType.map(({ key, name }) =>
|
||||
createAddressPresetFolder({
|
||||
datasets,
|
||||
scale,
|
||||
color: colors[key],
|
||||
name,
|
||||
datasetKey: key,
|
||||
}),
|
||||
),
|
||||
},
|
||||
],
|
||||
} satisfies PartialPresetFolder;
|
||||
}
|
||||
|
||||
function createAddressPresetFolder<Scale extends ResourceScale>({
|
||||
datasets,
|
||||
scale,
|
||||
color,
|
||||
name,
|
||||
datasetKey,
|
||||
}: {
|
||||
datasets: Datasets;
|
||||
scale: Scale;
|
||||
name: string;
|
||||
datasetKey: AddressCohortKey;
|
||||
color: string;
|
||||
}): PartialPresetFolder {
|
||||
return {
|
||||
name,
|
||||
tree: [
|
||||
createAddressCountPreset({ scale, name, datasetKey, color }),
|
||||
...createCohortPresetList({
|
||||
title: name,
|
||||
datasets,
|
||||
scale,
|
||||
name,
|
||||
color,
|
||||
datasetKey,
|
||||
}),
|
||||
{
|
||||
name: `Split By Liquidity`,
|
||||
tree: liquidities.map(
|
||||
(liquidity): PartialPresetFolder => ({
|
||||
name: liquidity.name,
|
||||
tree: createCohortPresetList({
|
||||
title: `${liquidity.name} ${name}`,
|
||||
name: `${liquidity.name} ${name}`,
|
||||
datasets,
|
||||
scale,
|
||||
color,
|
||||
datasetKey: `${liquidity.key}_${datasetKey}`,
|
||||
}),
|
||||
}),
|
||||
),
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
export function createAddressCountPreset<Scale extends ResourceScale>({
|
||||
scale,
|
||||
color,
|
||||
name,
|
||||
datasetKey,
|
||||
}: {
|
||||
scale: Scale;
|
||||
name: string;
|
||||
datasetKey: AddressCohortKey;
|
||||
color: string;
|
||||
}): PartialPreset {
|
||||
return {
|
||||
scale,
|
||||
name: `Address Count`,
|
||||
title: `${name} Address Count`,
|
||||
icon: IconTablerAddressBook,
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "Address Count",
|
||||
color,
|
||||
dataset: params.datasets[scale][`${datasetKey}_address_count`],
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
description: "",
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,221 @@
|
||||
import { colors } from "../../utils/colors";
|
||||
import { applyMultipleSeries, SeriesType } from "../templates/multiple";
|
||||
|
||||
export function createPresets() {
|
||||
const scale: ResourceScale = "date";
|
||||
|
||||
return {
|
||||
name: "Blocks",
|
||||
tree: [
|
||||
{
|
||||
scale,
|
||||
icon: IconTablerWall,
|
||||
name: "Height",
|
||||
title: "Block Height",
|
||||
description: "",
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "Height",
|
||||
color: colors.bitcoin,
|
||||
dataset: params.datasets.date.last_height,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
scale,
|
||||
name: "Mined",
|
||||
tree: [
|
||||
{
|
||||
scale,
|
||||
icon: IconTablerCube,
|
||||
name: "Daily Sum",
|
||||
title: "Daily Sum Of Blocks Mined",
|
||||
description: "",
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "Target",
|
||||
color: colors.white,
|
||||
dataset: params.datasets.date.blocks_mined_1d_target,
|
||||
options: {
|
||||
lineStyle: 3,
|
||||
// lineStyle: LineStyle.LargeDashed,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "1W Avg.",
|
||||
color: colors.momentumYellow,
|
||||
dataset: params.datasets.date.blocks_mined_1w_sma,
|
||||
defaultVisible: false,
|
||||
},
|
||||
{
|
||||
title: "1M Avg.",
|
||||
color: colors.bitcoin,
|
||||
dataset: params.datasets.date.blocks_mined_1m_sma,
|
||||
},
|
||||
{
|
||||
title: "Mined",
|
||||
color: colors.darkBitcoin,
|
||||
dataset: params.datasets.date.blocks_mined,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
scale,
|
||||
icon: IconTablerLetterW,
|
||||
name: "Weekly Sum",
|
||||
title: "Weekly Sum Of Blocks Mined",
|
||||
description: "",
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "Target",
|
||||
color: colors.white,
|
||||
dataset: params.datasets.date.blocks_mined_1w_target,
|
||||
options: {
|
||||
lineStyle: 3,
|
||||
// lineStyle: LineStyle.LargeDashed,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "Sum Mined",
|
||||
color: colors.bitcoin,
|
||||
dataset: params.datasets.date.blocks_mined_1w_sum,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
scale,
|
||||
icon: IconTablerLetterM,
|
||||
name: "Monthly Sum",
|
||||
title: "Monthly Sum Of Blocks Mined",
|
||||
description: "",
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "Target",
|
||||
color: colors.white,
|
||||
dataset: params.datasets.date.blocks_mined_1m_target,
|
||||
options: {
|
||||
// lineStyle: LineStyle.LargeDashed,
|
||||
lineStyle: 3,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "Sum Mined",
|
||||
color: colors.bitcoin,
|
||||
dataset: params.datasets.date.blocks_mined_1m_sum,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
scale,
|
||||
icon: IconTablerLetterY,
|
||||
name: "Yearly Sum",
|
||||
title: "Yearly Sum Of Blocks Mined",
|
||||
description: "",
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "Target",
|
||||
color: colors.white,
|
||||
dataset: params.datasets.date.blocks_mined_1y_target,
|
||||
options: {
|
||||
lineStyle: 3,
|
||||
// lineStyle: LineStyle.LargeDashed,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "Sum Mined",
|
||||
color: colors.bitcoin,
|
||||
dataset: params.datasets.date.blocks_mined_1y_sum,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
scale,
|
||||
icon: IconTablerWall,
|
||||
name: "Total",
|
||||
title: "Total Blocks Mined",
|
||||
description: "",
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "Mined",
|
||||
color: colors.bitcoin,
|
||||
seriesType: SeriesType.Area,
|
||||
dataset: params.datasets.date.total_blocks_mined,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
scale,
|
||||
icon: IconTablerStack3,
|
||||
name: "Cumulative Size",
|
||||
title: "Cumulative Block Size",
|
||||
description: "",
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "Size (MB)",
|
||||
color: colors.darkWhite,
|
||||
seriesType: SeriesType.Area,
|
||||
dataset: params.datasets.date.cumulative_block_size,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
],
|
||||
} satisfies PartialPresetFolder;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,127 @@
|
||||
import {
|
||||
fromXCohorts,
|
||||
fromXToYCohorts,
|
||||
upToCohorts,
|
||||
xthCohorts,
|
||||
yearCohorts,
|
||||
} from "../../datasets/consts/age";
|
||||
import { colors } from "../../utils/colors";
|
||||
import { createCohortPresetFolder } from "../templates/cohort";
|
||||
import { applyMultipleSeries } from "../templates/multiple";
|
||||
|
||||
export function createPresets({
|
||||
scale,
|
||||
datasets,
|
||||
}: {
|
||||
scale: ResourceScale;
|
||||
datasets: Datasets;
|
||||
}) {
|
||||
return {
|
||||
name: "Hodlers",
|
||||
tree: [
|
||||
{
|
||||
scale,
|
||||
name: `Hodl Supply`,
|
||||
title: `Hodl Supply`,
|
||||
description: "",
|
||||
icon: IconTablerRipple,
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: `24h`,
|
||||
color: colors.up_to_1d,
|
||||
dataset:
|
||||
params.datasets.date
|
||||
.up_to_1d_supply_to_circulating_supply_ratio,
|
||||
},
|
||||
|
||||
...fromXToYCohorts.map(({ key, name, legend }) => ({
|
||||
title: legend,
|
||||
color: colors[key],
|
||||
dataset:
|
||||
params.datasets.date[
|
||||
`${key}_supply_to_circulating_supply_ratio`
|
||||
],
|
||||
})),
|
||||
|
||||
{
|
||||
title: `15y+`,
|
||||
color: colors.from_15y,
|
||||
dataset:
|
||||
params.datasets.date
|
||||
.from_15y_supply_to_circulating_supply_ratio,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
...xthCohorts.map(({ key, name, legend }) =>
|
||||
createCohortPresetFolder({
|
||||
datasets,
|
||||
scale,
|
||||
color: colors[key],
|
||||
name: legend,
|
||||
datasetKey: key,
|
||||
title: name,
|
||||
}),
|
||||
),
|
||||
{
|
||||
name: "Up To X",
|
||||
tree: upToCohorts.map(({ key, name }) =>
|
||||
createCohortPresetFolder({
|
||||
datasets,
|
||||
scale,
|
||||
color: colors[key],
|
||||
name,
|
||||
datasetKey: key,
|
||||
title: name,
|
||||
}),
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "From X To Y",
|
||||
tree: fromXToYCohorts.map(({ key, name }) =>
|
||||
createCohortPresetFolder({
|
||||
datasets,
|
||||
scale,
|
||||
color: colors[key],
|
||||
name,
|
||||
datasetKey: key,
|
||||
title: name,
|
||||
}),
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "From X",
|
||||
tree: fromXCohorts.map(({ key, name }) =>
|
||||
createCohortPresetFolder({
|
||||
datasets,
|
||||
scale,
|
||||
color: colors[key],
|
||||
name,
|
||||
datasetKey: key,
|
||||
title: name,
|
||||
}),
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "Years",
|
||||
tree: yearCohorts.map(({ key, name }) =>
|
||||
createCohortPresetFolder({
|
||||
datasets,
|
||||
scale,
|
||||
color: colors[key],
|
||||
name,
|
||||
datasetKey: key,
|
||||
title: name,
|
||||
}),
|
||||
),
|
||||
},
|
||||
],
|
||||
} satisfies PartialPresetFolder;
|
||||
}
|
||||
@@ -0,0 +1,296 @@
|
||||
import { createRWS } from "/src/solid/rws";
|
||||
|
||||
import { colors } from "../utils/colors";
|
||||
import { replaceHistory } from "../utils/history";
|
||||
import { stringToId } from "../utils/id";
|
||||
import { resetURLParams } from "../utils/urlParams";
|
||||
import { createPresets as createAddressesPresets } from "./addresses";
|
||||
import { createPresets as createBlocksPresets } from "./blocks";
|
||||
import { createPresets as createCoinblocksPresets } from "./coinblocks";
|
||||
import { createPresets as createHodlersPresets } from "./hodlers";
|
||||
import { createPresets as createMarketPresets } from "./market";
|
||||
import { createPresets as createMinersPresets } from "./miners";
|
||||
import { createCohortPresetList } from "./templates/cohort";
|
||||
import { createPresets as createTransactionsPresets } from "./transactions";
|
||||
|
||||
export const LOCAL_STORAGE_FAVORITES_KEY = "favorites";
|
||||
export const LOCAL_STORAGE_FOLDERS_KEY = "folders";
|
||||
export const LOCAL_STORAGE_HISTORY_KEY = "history";
|
||||
export const LOCAL_STORAGE_SELECTED_KEY = "preset";
|
||||
export const LOCAL_STORAGE_VISITED_KEY = "visited";
|
||||
|
||||
export function createPresets(datasets: Datasets): Presets {
|
||||
const partialTree = [
|
||||
{
|
||||
name: "Dashboards (Coming soon)",
|
||||
tree: [],
|
||||
},
|
||||
{
|
||||
name: "Charts",
|
||||
tree: [
|
||||
{
|
||||
name: "By Date",
|
||||
tree: [
|
||||
createMarketPresets({ scale: "date", datasets }),
|
||||
createBlocksPresets(),
|
||||
createMinersPresets("date"),
|
||||
createTransactionsPresets("date"),
|
||||
...createCohortPresetList({
|
||||
datasets,
|
||||
scale: "date",
|
||||
color: colors.bitcoin,
|
||||
datasetKey: "",
|
||||
name: "",
|
||||
title: "",
|
||||
}),
|
||||
createHodlersPresets({ scale: "date", datasets }),
|
||||
createAddressesPresets({ scale: "date", datasets }),
|
||||
createCoinblocksPresets({ scale: "date", datasets }),
|
||||
],
|
||||
} satisfies PartialPresetFolder,
|
||||
{
|
||||
name: "By Height (Coming soon)",
|
||||
tree: [
|
||||
// createMarketPresets({ scale: "height", datasets }),
|
||||
// createMinersPresets("height"),
|
||||
// createTransactionsPresets("height"),
|
||||
// ...createCohortPresetList({
|
||||
// datasets,
|
||||
// scale: "height",
|
||||
// color: colors.bitcoin,
|
||||
// name: "",
|
||||
// datasetKey: "",
|
||||
// title: "",
|
||||
// }),
|
||||
// createHodlersPresets({ scale: "height", datasets }),
|
||||
// createAddressesPresets({ scale: "height", datasets }),
|
||||
// createCoinblocksPresets({ scale: "height", datasets }),
|
||||
],
|
||||
} satisfies PartialPresetFolder,
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
const { list, ids, tree } = flatten(partialTree);
|
||||
|
||||
checkIfDuplicateIds(ids);
|
||||
|
||||
setIsFavorites(list);
|
||||
|
||||
setVisited(list);
|
||||
|
||||
const favorites = createMemo(() =>
|
||||
list.filter((preset) => preset.isFavorite()),
|
||||
);
|
||||
|
||||
createEffect(() => {
|
||||
localStorage.setItem(
|
||||
LOCAL_STORAGE_FAVORITES_KEY,
|
||||
JSON.stringify(favorites().map((p) => p.id)),
|
||||
);
|
||||
});
|
||||
|
||||
const visited = createMemo(() => list.filter((preset) => preset.visited()));
|
||||
|
||||
createEffect(() => {
|
||||
localStorage.setItem(
|
||||
LOCAL_STORAGE_VISITED_KEY,
|
||||
JSON.stringify(visited().map((p) => p.id)),
|
||||
);
|
||||
});
|
||||
|
||||
createEffect(() => {
|
||||
const serializedHistory: SerializedPresetsHistory = history().map(
|
||||
({ preset, date }) => ({
|
||||
p: preset.id,
|
||||
d: date.valueOf(),
|
||||
}),
|
||||
);
|
||||
|
||||
localStorage.setItem(
|
||||
LOCAL_STORAGE_HISTORY_KEY,
|
||||
JSON.stringify(serializedHistory),
|
||||
);
|
||||
});
|
||||
|
||||
const history: PresetsHistorySignal = createRWS(getHistory(list), {
|
||||
equals: false,
|
||||
});
|
||||
|
||||
const selected = createRWS(findInitialPreset(list), {
|
||||
equals: false,
|
||||
});
|
||||
|
||||
createEffect((previousPreset: Preset) => {
|
||||
if (previousPreset && previousPreset !== selected()) {
|
||||
resetURLParams();
|
||||
}
|
||||
return selected();
|
||||
}, selected());
|
||||
|
||||
createEffect(() => selected().visited.set(true));
|
||||
|
||||
const select = (preset: Preset) => {
|
||||
if (selected().id === preset.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
history.set((l) => {
|
||||
l.unshift({
|
||||
date: new Date(),
|
||||
preset,
|
||||
});
|
||||
return l;
|
||||
});
|
||||
|
||||
_select(preset, selected.set);
|
||||
};
|
||||
|
||||
const openedFolders = createRWS(
|
||||
new Set(
|
||||
JSON.parse(
|
||||
localStorage.getItem(LOCAL_STORAGE_FOLDERS_KEY) || "[]",
|
||||
) as string[],
|
||||
),
|
||||
{
|
||||
equals: false,
|
||||
},
|
||||
);
|
||||
|
||||
createEffect(() => {
|
||||
localStorage.setItem(
|
||||
LOCAL_STORAGE_FOLDERS_KEY,
|
||||
JSON.stringify(Array.from(openedFolders())),
|
||||
);
|
||||
});
|
||||
|
||||
return {
|
||||
tree,
|
||||
list,
|
||||
selected,
|
||||
favorites,
|
||||
history,
|
||||
select,
|
||||
openedFolders,
|
||||
};
|
||||
}
|
||||
|
||||
function _select(preset: Preset, set: Setter<Preset>) {
|
||||
const key = LOCAL_STORAGE_SELECTED_KEY;
|
||||
const value = preset.id;
|
||||
|
||||
localStorage.setItem(key, value);
|
||||
|
||||
replaceHistory({ pathname: `/${value}` });
|
||||
|
||||
set(preset);
|
||||
}
|
||||
|
||||
function flatten(partialTree: PartialPresetTree) {
|
||||
const result: { list: Preset[]; ids: string[] } = { list: [], ids: [] };
|
||||
|
||||
const _flatten = (partialTree: PartialPresetTree, path?: FilePath) => {
|
||||
partialTree.forEach((anyPreset) => {
|
||||
if ("tree" in anyPreset) {
|
||||
const id = stringToId(
|
||||
`${(path || [])?.map(({ name }) => name).join(" ")} ${anyPreset.name} folder`,
|
||||
);
|
||||
|
||||
const presetFolder: PresetFolder = {
|
||||
...anyPreset,
|
||||
tree: anyPreset.tree as PresetTree,
|
||||
id,
|
||||
};
|
||||
|
||||
Object.assign(anyPreset, presetFolder);
|
||||
|
||||
result.ids.push(presetFolder.id);
|
||||
|
||||
return _flatten(presetFolder.tree, [
|
||||
...(path || []),
|
||||
{
|
||||
name: presetFolder.name,
|
||||
id: presetFolder.id,
|
||||
},
|
||||
]);
|
||||
} else {
|
||||
const preset = {
|
||||
...anyPreset,
|
||||
path: path || [],
|
||||
isFavorite: createRWS(false),
|
||||
visited: createRWS(false),
|
||||
id: `${anyPreset.scale}-to-${stringToId(anyPreset.title)}`,
|
||||
} satisfies Preset;
|
||||
|
||||
result.list.push(Object.assign(anyPreset, preset));
|
||||
result.ids.push(preset.id);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
_flatten(partialTree);
|
||||
|
||||
return { ...result, tree: partialTree as PresetTree };
|
||||
}
|
||||
|
||||
function checkIfDuplicateIds(ids: string[]) {
|
||||
if (ids.length !== new Set(ids).size) {
|
||||
const m = new Map<string, number>();
|
||||
|
||||
ids.forEach((id) => {
|
||||
m.set(id, (m.get(id) || 0) + 1);
|
||||
});
|
||||
|
||||
console.log(
|
||||
[...m.entries()].filter(([_, value]) => value > 1).map(([key, _]) => key),
|
||||
);
|
||||
|
||||
throw Error("ID duplicate");
|
||||
}
|
||||
}
|
||||
|
||||
function findInitialPreset(presets: Preset[]): Preset {
|
||||
const urlPreset = document.location.pathname.substring(1);
|
||||
|
||||
return (
|
||||
(urlPreset &&
|
||||
(presets.find((preset) => preset.id === urlPreset) ||
|
||||
presets.find(
|
||||
(preset) =>
|
||||
preset.id === localStorage.getItem(LOCAL_STORAGE_SELECTED_KEY),
|
||||
))) ||
|
||||
presets[0]
|
||||
);
|
||||
}
|
||||
|
||||
function setIsFavorites(list: Preset[]) {
|
||||
(
|
||||
JSON.parse(
|
||||
localStorage.getItem(LOCAL_STORAGE_FAVORITES_KEY) || "[]",
|
||||
) as string[]
|
||||
).forEach((id) => {
|
||||
list.find((preset) => preset.id === id)?.isFavorite.set(true);
|
||||
});
|
||||
}
|
||||
|
||||
function setVisited(list: Preset[]) {
|
||||
(
|
||||
JSON.parse(
|
||||
localStorage.getItem(LOCAL_STORAGE_VISITED_KEY) || "[]",
|
||||
) as string[]
|
||||
).forEach((id) => {
|
||||
list.find((preset) => preset.id === id)?.visited.set(true);
|
||||
});
|
||||
}
|
||||
|
||||
function getHistory(list: Preset[]): PresetsHistory {
|
||||
return (
|
||||
JSON.parse(
|
||||
localStorage.getItem(LOCAL_STORAGE_HISTORY_KEY) || "[]",
|
||||
) as SerializedPresetsHistory
|
||||
).flatMap(({ p, d }) => {
|
||||
const preset = list.find((preset) => preset.id === p);
|
||||
|
||||
return preset ? [{ preset, date: new Date(d) }] : [];
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
import { averages } from "/src/scripts/datasets/date";
|
||||
import { colors } from "/src/scripts/utils/colors";
|
||||
|
||||
import { applyMultipleSeries } from "../../templates/multiple";
|
||||
|
||||
export function createPresets(datasets: Datasets): PartialPresetFolder {
|
||||
const scale: ResourceScale = "date";
|
||||
|
||||
return {
|
||||
name: "Averages",
|
||||
tree: [
|
||||
{
|
||||
scale,
|
||||
icon: IconTablerMathAvg,
|
||||
name: "All",
|
||||
title: "All Averages",
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
list: averages.map((average) => ({
|
||||
title: average.key.toUpperCase(),
|
||||
color: colors[`_${average.key}`],
|
||||
dataset: params.datasets.date[`price_${average.key}_sma`],
|
||||
})),
|
||||
});
|
||||
},
|
||||
description: "",
|
||||
},
|
||||
...averages.map(({ name, key }) =>
|
||||
createPresetFolder({
|
||||
datasets,
|
||||
scale,
|
||||
color: colors[`_${key}`],
|
||||
name,
|
||||
key,
|
||||
}),
|
||||
),
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
function createPresetFolder({
|
||||
scale,
|
||||
datasets,
|
||||
color,
|
||||
name,
|
||||
key,
|
||||
}: {
|
||||
datasets: Datasets;
|
||||
scale: ResourceScale;
|
||||
color: string;
|
||||
name: string;
|
||||
key: AverageName;
|
||||
}) {
|
||||
return {
|
||||
// id,
|
||||
// name,
|
||||
// tree: [
|
||||
// {
|
||||
scale,
|
||||
name,
|
||||
description: "",
|
||||
icon: IconTablerMathAvg,
|
||||
title: `${name} Moving Average`,
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
list: [
|
||||
{
|
||||
title: `SMA`,
|
||||
color,
|
||||
dataset: datasets.date[`price_${key}_sma`],
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
} satisfies PartialPreset;
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
import { colors } from "../../utils/colors";
|
||||
import { applyMultipleSeries } from "../templates/multiple";
|
||||
import { createPresets as createAveragesPresets } from "./averages";
|
||||
import { createPresets as createIndicatorsPresets } from "./indicators";
|
||||
import { createPresets as createReturnsPresets } from "./returns";
|
||||
|
||||
export function createPresets({
|
||||
scale,
|
||||
datasets,
|
||||
}: {
|
||||
scale: ResourceScale;
|
||||
datasets: Datasets;
|
||||
}) {
|
||||
return {
|
||||
name: "Market",
|
||||
tree: [
|
||||
{
|
||||
scale,
|
||||
icon: IconTablerCurrencyDollar,
|
||||
name: "Price",
|
||||
title: "Market Price",
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({ ...params });
|
||||
},
|
||||
description: "",
|
||||
},
|
||||
{
|
||||
scale,
|
||||
icon: IconTablerPercentage,
|
||||
name: "Performance",
|
||||
title: "Market Performance",
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceOptions: {
|
||||
id: "performance",
|
||||
title: "Performance",
|
||||
priceScaleOptions: {
|
||||
mode: 2,
|
||||
},
|
||||
},
|
||||
});
|
||||
},
|
||||
description: "",
|
||||
},
|
||||
{
|
||||
scale,
|
||||
icon: IconTablerInfinity,
|
||||
name: "Capitalization",
|
||||
title: "Market Capitalization",
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "Market Cap.",
|
||||
dataset: params.datasets[scale].market_cap,
|
||||
color: colors.bitcoin,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
description: "",
|
||||
},
|
||||
...(scale === "date"
|
||||
? ([
|
||||
createAveragesPresets(datasets),
|
||||
createReturnsPresets(datasets),
|
||||
createIndicatorsPresets(datasets),
|
||||
] satisfies PartialPresetTree)
|
||||
: []),
|
||||
],
|
||||
} satisfies PartialPresetFolder;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
export function createPresets(datasets: Datasets) {
|
||||
return {
|
||||
name: "Indicators",
|
||||
tree: [],
|
||||
} satisfies PartialPresetFolder;
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
import {
|
||||
compoundReturns,
|
||||
totalReturns,
|
||||
} from "/src/scripts/datasets/consts/returns";
|
||||
|
||||
import { applyMultipleSeries, SeriesType } from "../../templates/multiple";
|
||||
|
||||
export function createPresets(datasets: Datasets) {
|
||||
return {
|
||||
name: "Returns",
|
||||
tree: [
|
||||
{
|
||||
name: "Total",
|
||||
tree: [
|
||||
...totalReturns.map(({ name, key }) =>
|
||||
createPreset({
|
||||
scale: "date",
|
||||
datasets,
|
||||
name,
|
||||
title: `${name} Total`,
|
||||
key: `${key}_total`,
|
||||
}),
|
||||
),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Compound",
|
||||
tree: [
|
||||
...compoundReturns.map(({ name, key }) =>
|
||||
createPreset({
|
||||
scale: "date",
|
||||
datasets,
|
||||
name,
|
||||
title: `${name} Compound`,
|
||||
key: `${key}_compound`,
|
||||
}),
|
||||
),
|
||||
],
|
||||
},
|
||||
],
|
||||
} satisfies PartialPresetFolder;
|
||||
}
|
||||
|
||||
function createPreset({
|
||||
scale,
|
||||
datasets,
|
||||
name,
|
||||
title,
|
||||
key,
|
||||
}: {
|
||||
scale: ResourceScale;
|
||||
datasets: Datasets;
|
||||
name: string;
|
||||
title: string;
|
||||
key: `${TotalReturnKey}_total` | `${CompoundReturnKey}_compound`;
|
||||
}): PartialPreset {
|
||||
return {
|
||||
scale,
|
||||
name,
|
||||
description: "",
|
||||
icon: IconTablerReceiptTax,
|
||||
title: `${title} Return`,
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: `Return (%)`,
|
||||
seriesType: SeriesType.Based,
|
||||
dataset: datasets.date[`price_${key}_return`],
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,902 @@
|
||||
import { colors } from "../../utils/colors";
|
||||
import { applyMultipleSeries, SeriesType } from "../templates/multiple";
|
||||
|
||||
export function createPresets(scale: ResourceScale) {
|
||||
return {
|
||||
name: "Miners",
|
||||
tree: [
|
||||
{
|
||||
name: "Coinbases",
|
||||
tree: [
|
||||
...(scale === "date"
|
||||
? ([
|
||||
{
|
||||
name: "Last",
|
||||
tree: [
|
||||
{
|
||||
scale,
|
||||
icon: IconTablerCoinBitcoin,
|
||||
name: "In Bitcoin",
|
||||
title: "Last Coinbase (In Bitcoin)",
|
||||
description: "",
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "Last",
|
||||
color: colors.bitcoin,
|
||||
dataset: params.datasets[scale].last_coinbase,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
scale,
|
||||
icon: IconTablerCoin,
|
||||
name: "In Dollars",
|
||||
title: "Last Coinbase (In Dollars)",
|
||||
description: "",
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "Last",
|
||||
color: colors.dollars,
|
||||
dataset:
|
||||
params.datasets[scale].last_coinbase_in_dollars,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
scale,
|
||||
name: "Daily Sum",
|
||||
tree: [
|
||||
{
|
||||
scale,
|
||||
icon: IconTablerMoneybag,
|
||||
name: "In Bitcoin",
|
||||
title: "Daily Sum Of Bitcoin Coinbases",
|
||||
description: "",
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "Coinbases (Bitcoin)",
|
||||
color: colors.bitcoin,
|
||||
dataset: params.datasets[scale].coinbase,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
scale,
|
||||
icon: IconTablerCash,
|
||||
name: "In Dollars",
|
||||
title: "Daily Sum Of Dollar Coinbases",
|
||||
description: "",
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "Coinbases (Dollars)",
|
||||
color: colors.dollars,
|
||||
dataset:
|
||||
params.datasets[scale].coinbase_in_dollars,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
scale,
|
||||
name: "Yearly Sum",
|
||||
tree: [
|
||||
{
|
||||
scale,
|
||||
icon: IconTablerMoneybag,
|
||||
name: "In Bitcoin",
|
||||
title: "Yearly Sum Of Bitcoin Coinbases",
|
||||
description: "",
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "Coinbases (Bitcoin)",
|
||||
color: colors.bitcoin,
|
||||
dataset: params.datasets[scale].coinbase_1y_sum,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
scale,
|
||||
icon: IconTablerCash,
|
||||
name: "In Dollars",
|
||||
title: "Yearly Sum Of Dollar Coinbases",
|
||||
description: "",
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "Coinbases (Dollars)",
|
||||
color: colors.dollars,
|
||||
dataset:
|
||||
params.datasets[scale]
|
||||
.coinbase_in_dollars_1y_sum,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
scale,
|
||||
name: "Cumulative",
|
||||
tree: [
|
||||
{
|
||||
scale,
|
||||
icon: IconTablerMoneybag,
|
||||
name: "In Bitcoin",
|
||||
title: "Cumulative Bitcoin Coinbases",
|
||||
description: "",
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "Coinbases (Bitcoin)",
|
||||
color: colors.bitcoin,
|
||||
dataset:
|
||||
params.datasets[scale].cumulative_coinbase,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
scale,
|
||||
icon: IconTablerCash,
|
||||
name: "In Dollars",
|
||||
title: "Cumulative Dollar Coinbases",
|
||||
description: "",
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "Coinbases (Dollars)",
|
||||
color: colors.dollars,
|
||||
dataset:
|
||||
params.datasets[scale]
|
||||
.cumulative_coinbase_in_dollars,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
] satisfies PartialPresetTree)
|
||||
: []),
|
||||
],
|
||||
},
|
||||
|
||||
{
|
||||
name: "Subsidies",
|
||||
tree: [
|
||||
...(scale === "date"
|
||||
? ([
|
||||
{
|
||||
name: "Last",
|
||||
tree: [
|
||||
{
|
||||
scale,
|
||||
icon: IconTablerCoinBitcoin,
|
||||
name: "In Bitcoin",
|
||||
title: "Last Subsidy (In Bitcoin)",
|
||||
description: "",
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "Last",
|
||||
color: colors.bitcoin,
|
||||
dataset: params.datasets[scale].last_subsidy,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
scale,
|
||||
icon: IconTablerCoin,
|
||||
name: "In Dollars",
|
||||
title: "Last Subsidy (In Dollars)",
|
||||
description: "",
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "Last",
|
||||
color: colors.dollars,
|
||||
dataset:
|
||||
params.datasets[scale].last_subsidy_in_dollars,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
scale,
|
||||
name: "Daily Sum",
|
||||
tree: [
|
||||
{
|
||||
scale,
|
||||
icon: IconTablerMoneybag,
|
||||
name: "In Bitcoin",
|
||||
title: "Daily Sum Of Bitcoin Subsidies",
|
||||
description: "",
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "Subsidies (Bitcoin)",
|
||||
color: colors.bitcoin,
|
||||
dataset: params.datasets[scale].subsidy,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
scale,
|
||||
icon: IconTablerCash,
|
||||
name: "In Dollars",
|
||||
title: "Daily Sum Of Dollar Subsidies",
|
||||
description: "",
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "Subsidies (Dollars)",
|
||||
color: colors.dollars,
|
||||
dataset:
|
||||
params.datasets[scale].subsidy_in_dollars,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
scale,
|
||||
name: "Yearly Sum",
|
||||
tree: [
|
||||
{
|
||||
scale,
|
||||
icon: IconTablerMoneybag,
|
||||
name: "In Bitcoin",
|
||||
title: "Yearly Sum Of Bitcoin Subsidies",
|
||||
description: "",
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "Subsidies (Bitcoin)",
|
||||
color: colors.bitcoin,
|
||||
dataset: params.datasets[scale].subsidy_1y_sum,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
scale,
|
||||
icon: IconTablerCash,
|
||||
name: "In Dollars",
|
||||
title: "Yearly Sum Of Dollar Subsidies",
|
||||
description: "",
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "Subsidies (Dollars)",
|
||||
color: colors.dollars,
|
||||
dataset:
|
||||
params.datasets[scale]
|
||||
.subsidy_in_dollars_1y_sum,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
scale,
|
||||
name: "Cumulative",
|
||||
tree: [
|
||||
{
|
||||
scale,
|
||||
icon: IconTablerMoneybag,
|
||||
name: "In Bitcoin",
|
||||
title: "Cumulative Bitcoin Subsidies",
|
||||
description: "",
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "Subsidies (Bitcoin)",
|
||||
color: colors.bitcoin,
|
||||
dataset:
|
||||
params.datasets[scale].cumulative_subsidy,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
scale,
|
||||
icon: IconTablerCash,
|
||||
name: "In Dollars",
|
||||
title: "Cumulative Dollar Subsidies",
|
||||
description: "",
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "Subsidies (Dollars)",
|
||||
color: colors.dollars,
|
||||
dataset:
|
||||
params.datasets[scale]
|
||||
.cumulative_subsidy_in_dollars,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
] satisfies PartialPresetTree)
|
||||
: []),
|
||||
],
|
||||
},
|
||||
|
||||
{
|
||||
name: "Fees",
|
||||
tree: [
|
||||
...(scale === "date"
|
||||
? ([
|
||||
{
|
||||
name: "Last",
|
||||
tree: [
|
||||
{
|
||||
scale,
|
||||
icon: IconTablerCoinBitcoin,
|
||||
name: "In Bitcoin",
|
||||
title: "Last Fees (In Bitcoin)",
|
||||
description: "",
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "Last",
|
||||
color: colors.bitcoin,
|
||||
dataset: params.datasets[scale].last_fees,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
scale,
|
||||
icon: IconTablerCoin,
|
||||
name: "In Dollars",
|
||||
title: "Last Fees (In Dollars)",
|
||||
description: "",
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "Last",
|
||||
color: colors.dollars,
|
||||
dataset:
|
||||
params.datasets[scale].last_fees_in_dollars,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
scale,
|
||||
name: "Daily Sum",
|
||||
tree: [
|
||||
{
|
||||
scale,
|
||||
icon: IconTablerMoneybag,
|
||||
name: "In Bitcoin",
|
||||
title: "Daily Sum Of Bitcoin Fees",
|
||||
description: "",
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "Fees (Bitcoin)",
|
||||
color: colors.bitcoin,
|
||||
dataset: params.datasets[scale].fees,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
scale,
|
||||
icon: IconTablerCash,
|
||||
name: "In Dollars",
|
||||
title: "Daily Sum Of Dollar Fees",
|
||||
description: "",
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "Fees (Dollars)",
|
||||
color: colors.dollars,
|
||||
dataset: params.datasets[scale].fees_in_dollars,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
scale,
|
||||
name: "Yearly Sum",
|
||||
tree: [
|
||||
{
|
||||
scale,
|
||||
icon: IconTablerMoneybag,
|
||||
name: "In Bitcoin",
|
||||
title: "Yearly Sum Of Bitcoin Fees",
|
||||
description: "",
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "Fees (Bitcoin)",
|
||||
color: colors.bitcoin,
|
||||
dataset: params.datasets[scale].fees_1y_sum,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
scale,
|
||||
icon: IconTablerCash,
|
||||
name: "In Dollars",
|
||||
title: "Yearly Sum Of Dollar Fees",
|
||||
description: "",
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "Fees (Dollars)",
|
||||
color: colors.dollars,
|
||||
dataset:
|
||||
params.datasets[scale].fees_in_dollars_1y_sum,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
scale,
|
||||
name: "Cumulative",
|
||||
tree: [
|
||||
{
|
||||
scale,
|
||||
icon: IconTablerMoneybag,
|
||||
name: "In Bitcoin",
|
||||
title: "Cumulative Bitcoin Fees",
|
||||
description: "",
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "Fees (Bitcoin)",
|
||||
color: colors.bitcoin,
|
||||
dataset: params.datasets[scale].cumulative_fees,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
scale,
|
||||
icon: IconTablerCash,
|
||||
name: "In Dollars",
|
||||
title: "Cumulative Dollar Fees",
|
||||
description: "",
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "Fees (Dollars)",
|
||||
color: colors.dollars,
|
||||
dataset:
|
||||
params.datasets[scale]
|
||||
.cumulative_fees_in_dollars,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
] satisfies PartialPresetTree)
|
||||
: []),
|
||||
],
|
||||
},
|
||||
|
||||
{
|
||||
scale,
|
||||
icon: IconTablerSwords,
|
||||
name: "Subsidy V. Fees",
|
||||
title: "Subsidy V. Fees",
|
||||
description: "",
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "Subsidy (%)",
|
||||
color: colors.bitcoin,
|
||||
dataset: params.datasets[scale].subsidy_to_coinbase_ratio,
|
||||
},
|
||||
{
|
||||
title: "Fees (%)",
|
||||
color: colors.darkBitcoin,
|
||||
dataset: params.datasets[scale].fees_to_coinbase_ratio,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
|
||||
...(scale === "date"
|
||||
? ([
|
||||
{
|
||||
scale,
|
||||
icon: IconTablerCalculator,
|
||||
name: "Puell Multiple",
|
||||
title: "Puell Multiple",
|
||||
description: "",
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
mode: 1,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "Multiple",
|
||||
color: colors.bitcoin,
|
||||
dataset: params.datasets.date.puell_multiple,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
scale,
|
||||
icon: IconTablerPick,
|
||||
name: "Hash Rate",
|
||||
title: "Hash Rate (EH/s)",
|
||||
description: "",
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
mode: 1,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "1M SMA",
|
||||
color: colors.momentumYellow,
|
||||
dataset: params.datasets.date.hash_rate_1m_sma,
|
||||
},
|
||||
{
|
||||
title: "1W SMA",
|
||||
color: colors.bitcoin,
|
||||
dataset: params.datasets.date.hash_rate_1w_sma,
|
||||
},
|
||||
{
|
||||
title: "Rate",
|
||||
color: colors.darkBitcoin,
|
||||
dataset: params.datasets.date.hash_rate,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
scale,
|
||||
icon: IconTablerRibbonHealth,
|
||||
name: "Hash Ribbon",
|
||||
title: "Hash Ribbon (EH/s)",
|
||||
description: "",
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
mode: 1,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "1M SMA",
|
||||
color: colors.profit,
|
||||
dataset: params.datasets.date.hash_rate_1m_sma,
|
||||
},
|
||||
{
|
||||
title: "2M SMA",
|
||||
color: colors.loss,
|
||||
dataset: params.datasets.date.hash_rate_2m_sma,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
scale,
|
||||
icon: IconTablerTag,
|
||||
name: "Hash Price",
|
||||
title: "Hash Price",
|
||||
description: "",
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "Price ($/PH/s)",
|
||||
color: colors.dollars,
|
||||
dataset: params.datasets.date.hash_price,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
] satisfies PartialPreset[])
|
||||
: []),
|
||||
|
||||
{
|
||||
scale,
|
||||
icon: IconTablerWeight,
|
||||
name: "Difficulty",
|
||||
title: "Difficulty",
|
||||
description: "",
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
mode: 1,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "Difficulty",
|
||||
color: colors.bitcoin,
|
||||
dataset: params.datasets[scale].difficulty,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
|
||||
...(scale === "date"
|
||||
? ([
|
||||
{
|
||||
scale,
|
||||
icon: IconTablerAdjustments,
|
||||
name: "Difficulty Adjustment",
|
||||
title: "Difficulty Adjustment",
|
||||
description: "",
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "Adjustment (%)",
|
||||
// color: colors.bitcoin,
|
||||
seriesType: SeriesType.Based,
|
||||
dataset: params.datasets[scale].difficulty_adjustment,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
] satisfies PartialPreset[])
|
||||
: []),
|
||||
|
||||
{
|
||||
scale,
|
||||
icon: IconTablerBuildingFactory,
|
||||
name: "Annualized Issuance",
|
||||
title: "Annualized Issuance",
|
||||
description: "",
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
mode: 1,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "Issuance",
|
||||
color: colors.bitcoin,
|
||||
dataset: params.datasets[scale].annualized_issuance,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
scale,
|
||||
icon: IconTablerBuildingFactory2,
|
||||
name: "Yearly Inflation Rate",
|
||||
title: "Yearly Inflation Rate",
|
||||
description: "",
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
mode: 1,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "Rate (%)",
|
||||
color: colors.bitcoin,
|
||||
dataset: params.datasets[scale].yearly_inflation_rate,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
|
||||
// For scale === "height"
|
||||
// block_size,
|
||||
// block_weight,
|
||||
// block_vbytes,
|
||||
// block_interval,
|
||||
],
|
||||
} satisfies PartialPresetFolder;
|
||||
}
|
||||
@@ -0,0 +1,985 @@
|
||||
import { percentiles } from "../../datasets/consts/percentiles";
|
||||
import { colors } from "../../utils/colors";
|
||||
import { applyMultipleSeries, SeriesType } from "./multiple";
|
||||
|
||||
export function createCohortPresetFolder<Scale extends ResourceScale>({
|
||||
datasets,
|
||||
scale,
|
||||
color,
|
||||
name,
|
||||
datasetKey,
|
||||
title,
|
||||
}: {
|
||||
datasets: Datasets;
|
||||
scale: Scale;
|
||||
name: string;
|
||||
datasetKey: AnyPossibleCohortKey;
|
||||
color: string;
|
||||
title: string;
|
||||
}) {
|
||||
return {
|
||||
name,
|
||||
tree: createCohortPresetList({
|
||||
title,
|
||||
datasets,
|
||||
name,
|
||||
scale,
|
||||
color,
|
||||
datasetKey,
|
||||
}),
|
||||
} satisfies PartialPresetFolder;
|
||||
}
|
||||
|
||||
export function createCohortPresetList<Scale extends ResourceScale>({
|
||||
name,
|
||||
datasets,
|
||||
scale,
|
||||
color,
|
||||
datasetKey,
|
||||
title,
|
||||
}: {
|
||||
name: string;
|
||||
datasets: Datasets;
|
||||
scale: Scale;
|
||||
datasetKey: AnyPossibleCohortKey;
|
||||
title: string;
|
||||
color: string;
|
||||
}) {
|
||||
const datasetPrefix = datasetKey
|
||||
? (`${datasetKey}_` as const)
|
||||
: ("" as const);
|
||||
|
||||
return [
|
||||
{
|
||||
name: "UTXOs",
|
||||
tree: [
|
||||
{
|
||||
scale,
|
||||
name: `Count`,
|
||||
title: `${title} Unspent Transaction Outputs Count`,
|
||||
icon: () => IconTablerTicket,
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "Count",
|
||||
color,
|
||||
seriesType: SeriesType.Area,
|
||||
dataset: params.datasets[scale][`${datasetPrefix}utxo_count`],
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
description: "",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Realized",
|
||||
tree: [
|
||||
{
|
||||
scale,
|
||||
name: `Price`,
|
||||
title: `${title} Realized Price`,
|
||||
description: "",
|
||||
icon: () => IconTablerTag,
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
list: [
|
||||
{
|
||||
title: "Realized Price",
|
||||
color,
|
||||
dataset:
|
||||
params.datasets[scale][`${datasetPrefix}realized_price`],
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
scale,
|
||||
name: `Capitalization`,
|
||||
title: `${title} Realized Capitalization`,
|
||||
icon: () => IconTablerPigMoney,
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: `${name} Realized Cap.`,
|
||||
color,
|
||||
seriesType: SeriesType.Area,
|
||||
dataset:
|
||||
params.datasets[scale][`${datasetPrefix}realized_cap`],
|
||||
},
|
||||
...(datasetKey
|
||||
? [
|
||||
{
|
||||
title: "Realized Cap.",
|
||||
color: colors.bitcoin,
|
||||
dataset: params.datasets[scale].realized_cap,
|
||||
defaultVisible: false,
|
||||
},
|
||||
]
|
||||
: []),
|
||||
],
|
||||
});
|
||||
},
|
||||
description: "",
|
||||
},
|
||||
{
|
||||
scale,
|
||||
name: `Capitalization 1M Net Change`,
|
||||
title: `${title} Realized Capitalization 1 Month Net Change`,
|
||||
icon: () => IconTablerStatusChange,
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: `Net Change`,
|
||||
seriesType: SeriesType.Based,
|
||||
dataset:
|
||||
params.datasets[scale][
|
||||
`${datasetPrefix}realized_cap_1m_net_change`
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
description: "",
|
||||
},
|
||||
{
|
||||
scale,
|
||||
name: `Profit`,
|
||||
title: `${title} Realized Profit`,
|
||||
icon: () => IconTablerCash,
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "Realized Profit",
|
||||
dataset:
|
||||
params.datasets[scale][`${datasetPrefix}realized_profit`],
|
||||
color: colors.profit,
|
||||
seriesType: SeriesType.Area,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
description: "",
|
||||
},
|
||||
{
|
||||
scale,
|
||||
name: "Loss",
|
||||
title: `${title} Realized Loss`,
|
||||
icon: () => IconTablerCoffin,
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "Realized Loss",
|
||||
dataset:
|
||||
params.datasets[scale][`${datasetPrefix}realized_loss`],
|
||||
color: colors.loss,
|
||||
seriesType: SeriesType.Area,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
description: "",
|
||||
},
|
||||
{
|
||||
scale,
|
||||
name: `PNL`,
|
||||
title: `${title} Realized Profit And Loss`,
|
||||
icon: () => IconTablerArrowsVertical,
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "Profit",
|
||||
color: colors.profit,
|
||||
dataset:
|
||||
params.datasets[scale][`${datasetPrefix}realized_profit`],
|
||||
seriesType: SeriesType.Based,
|
||||
},
|
||||
{
|
||||
title: "Loss",
|
||||
color: colors.loss,
|
||||
dataset:
|
||||
params.datasets[scale][
|
||||
`${datasetPrefix}negative_realized_loss`
|
||||
],
|
||||
seriesType: SeriesType.Based,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
description: "",
|
||||
},
|
||||
{
|
||||
scale,
|
||||
name: `Net PNL`,
|
||||
title: `${title} Net Realized Profit And Loss`,
|
||||
icon: () => IconTablerScale,
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "Net PNL",
|
||||
seriesType: SeriesType.Based,
|
||||
dataset:
|
||||
params.datasets[scale][
|
||||
`${datasetPrefix}net_realized_profit_and_loss`
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
description: "",
|
||||
},
|
||||
{
|
||||
scale,
|
||||
name: `Net PNL Relative To Market Cap`,
|
||||
title: `${title} Net Realized Profit And Loss Relative To Market Capitalization`,
|
||||
icon: () => IconTablerDivide,
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "Net",
|
||||
seriesType: SeriesType.Based,
|
||||
dataset:
|
||||
params.datasets[scale][
|
||||
`${datasetPrefix}net_realized_profit_and_loss_to_market_cap_ratio`
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
description: "",
|
||||
},
|
||||
{
|
||||
scale,
|
||||
name: `Cumulative Profit`,
|
||||
title: `${title} Cumulative Realized Profit`,
|
||||
icon: () => IconTablerSum,
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "Cumulative Realized Profit",
|
||||
color: colors.profit,
|
||||
seriesType: SeriesType.Area,
|
||||
dataset:
|
||||
params.datasets[scale][
|
||||
`${datasetPrefix}cumulative_realized_profit`
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
description: "",
|
||||
},
|
||||
{
|
||||
scale,
|
||||
name: "Cumulative Loss",
|
||||
title: `${title} Cumulative Realized Loss`,
|
||||
icon: () => IconTablerSum,
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "Cumulative Realized Loss",
|
||||
color: colors.loss,
|
||||
seriesType: SeriesType.Area,
|
||||
dataset:
|
||||
params.datasets[scale][
|
||||
`${datasetPrefix}cumulative_realized_loss`
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
description: "",
|
||||
},
|
||||
{
|
||||
scale,
|
||||
name: `Cumulative Net PNL`,
|
||||
title: `${title} Cumulative Net Realized Profit And Loss`,
|
||||
icon: () => IconTablerSum,
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "Cumulative Net Realized PNL",
|
||||
seriesType: SeriesType.Based,
|
||||
dataset:
|
||||
params.datasets[scale][
|
||||
`${datasetPrefix}cumulative_net_realized_profit_and_loss`
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
description: "",
|
||||
},
|
||||
{
|
||||
scale,
|
||||
name: `Cumulative Net PNL 30 Day Change`,
|
||||
title: `${title} Cumulative Net Realized Profit And Loss 30 Day Change`,
|
||||
icon: () => IconTablerTimeDuration30,
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "Cumulative Net Realized PNL 30d Change",
|
||||
dataset:
|
||||
params.datasets[scale][
|
||||
`${datasetPrefix}cumulative_net_realized_profit_and_loss_1m_net_change`
|
||||
],
|
||||
seriesType: SeriesType.Based,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
description: "",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Unrealized",
|
||||
tree: [
|
||||
{
|
||||
scale,
|
||||
name: `Profit`,
|
||||
title: `${title} Unrealized Profit`,
|
||||
icon: () => IconTablerMoodDollar,
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "Profit",
|
||||
dataset:
|
||||
params.datasets[scale][`${datasetPrefix}unrealized_profit`],
|
||||
color: colors.profit,
|
||||
seriesType: SeriesType.Area,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
description: "",
|
||||
},
|
||||
|
||||
{
|
||||
scale,
|
||||
name: "Loss",
|
||||
title: `${title} Unrealized Loss`,
|
||||
icon: () => IconTablerMoodSadDizzy,
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "Loss",
|
||||
dataset:
|
||||
params.datasets[scale][`${datasetPrefix}unrealized_loss`],
|
||||
color: colors.loss,
|
||||
seriesType: SeriesType.Area,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
description: "",
|
||||
},
|
||||
{
|
||||
scale,
|
||||
name: `PNL`,
|
||||
title: `${title} Unrealized Profit And Loss`,
|
||||
icon: () => IconTablerArrowsVertical,
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "Profit",
|
||||
color: colors.profit,
|
||||
dataset:
|
||||
params.datasets[scale][`${datasetPrefix}unrealized_profit`],
|
||||
seriesType: SeriesType.Based,
|
||||
},
|
||||
{
|
||||
title: "Loss",
|
||||
color: colors.loss,
|
||||
dataset:
|
||||
params.datasets[scale][
|
||||
`${datasetPrefix}negative_unrealized_loss`
|
||||
],
|
||||
seriesType: SeriesType.Based,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
description: "",
|
||||
},
|
||||
{
|
||||
scale,
|
||||
name: `Net PNL`,
|
||||
title: `${title} Net Unrealized Profit And Loss`,
|
||||
icon: () => IconTablerScale,
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "Net Unrealized PNL",
|
||||
dataset:
|
||||
params.datasets[scale][
|
||||
`${datasetPrefix}net_unrealized_profit_and_loss`
|
||||
],
|
||||
seriesType: SeriesType.Based,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
description: "",
|
||||
},
|
||||
{
|
||||
scale,
|
||||
name: `Net PNL Relative To Market Cap`,
|
||||
title: `${title} Net Unrealized Profit And Loss Relative To Total Market Capitalization`,
|
||||
icon: () => IconTablerDivide,
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "Relative Net Unrealized PNL",
|
||||
dataset:
|
||||
params.datasets[scale][
|
||||
`${datasetPrefix}net_unrealized_profit_and_loss_to_market_cap_ratio`
|
||||
],
|
||||
seriesType: SeriesType.Based,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
description: "",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Supply",
|
||||
tree: [
|
||||
{
|
||||
name: "Absolute",
|
||||
tree: [
|
||||
{
|
||||
scale,
|
||||
name: "All",
|
||||
title: `${title} Profit And Loss`,
|
||||
icon: () => IconTablerArrowsCross,
|
||||
description: "",
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "In Profit",
|
||||
color: colors.profit,
|
||||
dataset:
|
||||
params.datasets[scale][
|
||||
`${datasetPrefix}supply_in_profit`
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "In Loss",
|
||||
color: colors.loss,
|
||||
dataset:
|
||||
params.datasets[scale][
|
||||
`${datasetPrefix}supply_in_loss`
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Total",
|
||||
color: colors.white,
|
||||
dataset: params.datasets[scale][`${datasetPrefix}supply`],
|
||||
},
|
||||
{
|
||||
title: "Halved Total",
|
||||
color: colors.gray,
|
||||
dataset:
|
||||
params.datasets[scale][`${datasetPrefix}halved_supply`],
|
||||
options: {
|
||||
lineStyle: 4,
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
scale,
|
||||
name: `Total`,
|
||||
title: `${title} Total supply`,
|
||||
icon: () => IconTablerSum,
|
||||
description: "",
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "Supply",
|
||||
color,
|
||||
seriesType: SeriesType.Area,
|
||||
dataset: params.datasets[scale][`${datasetPrefix}supply`],
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
scale,
|
||||
name: "In Profit",
|
||||
title: `${title} Supply In Profit`,
|
||||
icon: () => IconTablerTrendingUp,
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "Supply",
|
||||
color: colors.profit,
|
||||
seriesType: SeriesType.Area,
|
||||
dataset:
|
||||
params.datasets[scale][
|
||||
`${datasetPrefix}supply_in_profit`
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
description: "",
|
||||
},
|
||||
{
|
||||
scale,
|
||||
name: "In Loss",
|
||||
title: `${title} Supply In Loss`,
|
||||
icon: () => IconTablerTrendingDown,
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "Supply",
|
||||
color: colors.loss,
|
||||
seriesType: SeriesType.Area,
|
||||
dataset:
|
||||
params.datasets[scale][
|
||||
`${datasetPrefix}supply_in_loss`
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
description: "",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Relative To Circulating",
|
||||
tree: [
|
||||
{
|
||||
scale,
|
||||
name: "All",
|
||||
title: `${title} Profit And Loss Relative To Circulating Supply`,
|
||||
icon: () => IconTablerArrowsCross,
|
||||
description: "",
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "In Profit",
|
||||
color: colors.profit,
|
||||
dataset:
|
||||
params.datasets[scale][
|
||||
`${datasetPrefix}supply_in_profit_to_circulating_supply_ratio`
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "In Loss",
|
||||
color: colors.loss,
|
||||
dataset:
|
||||
params.datasets[scale][
|
||||
`${datasetPrefix}supply_in_loss_to_circulating_supply_ratio`
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "100%",
|
||||
color: colors.white,
|
||||
dataset:
|
||||
params.datasets[scale][
|
||||
`${datasetPrefix}supply_to_circulating_supply_ratio`
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "50%",
|
||||
color: colors.gray,
|
||||
dataset:
|
||||
params.datasets[scale][
|
||||
`${datasetPrefix}halved_supply_to_circulating_supply_ratio`
|
||||
],
|
||||
options: {
|
||||
lineStyle: 4,
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
scale,
|
||||
name: `Total`,
|
||||
title: `${title} Total supply Relative To Circulating Supply`,
|
||||
icon: () => IconTablerSum,
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "Supply",
|
||||
color,
|
||||
seriesType: SeriesType.Area,
|
||||
dataset:
|
||||
params.datasets[scale][
|
||||
`${datasetPrefix}supply_to_circulating_supply_ratio`
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
description: "",
|
||||
},
|
||||
{
|
||||
scale,
|
||||
name: "In Profit",
|
||||
title: `${title} Supply In Profit Relative To Circulating Supply`,
|
||||
icon: () => IconTablerTrendingUp,
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "Supply",
|
||||
color: colors.profit,
|
||||
seriesType: SeriesType.Area,
|
||||
dataset:
|
||||
params.datasets[scale][
|
||||
`${datasetPrefix}supply_in_profit_to_circulating_supply_ratio`
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
description: "",
|
||||
},
|
||||
{
|
||||
scale,
|
||||
name: "In Loss",
|
||||
title: `${title} Supply In Loss Relative To Circulating Supply`,
|
||||
icon: () => IconTablerTrendingDown,
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "Supply",
|
||||
seriesType: SeriesType.Area,
|
||||
color: colors.loss,
|
||||
dataset:
|
||||
params.datasets[scale][
|
||||
`${datasetPrefix}supply_in_loss_to_circulating_supply_ratio`
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
description: "",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Relative To Own",
|
||||
tree: [
|
||||
{
|
||||
scale,
|
||||
name: "All",
|
||||
title: `${title} Supply In Profit And Loss Relative To Own Supply`,
|
||||
icon: () => IconTablerArrowsCross,
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "In profit",
|
||||
dataset:
|
||||
params.datasets[scale][
|
||||
`${datasetPrefix}supply_in_profit_to_own_supply_ratio`
|
||||
],
|
||||
color: colors.profit,
|
||||
},
|
||||
{
|
||||
title: "In loss",
|
||||
color: colors.loss,
|
||||
dataset:
|
||||
params.datasets[scale][
|
||||
`${datasetPrefix}supply_in_loss_to_own_supply_ratio`
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "100%",
|
||||
color: colors.white,
|
||||
dataset: params.datasets[scale][100],
|
||||
options: {
|
||||
lastValueVisible: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "50%",
|
||||
color: colors.gray,
|
||||
dataset: params.datasets[scale][50],
|
||||
options: {
|
||||
lineStyle: 4,
|
||||
lastValueVisible: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
description: "",
|
||||
},
|
||||
{
|
||||
scale,
|
||||
name: "In Profit",
|
||||
title: `${title} Supply In Profit Relative To Own Supply`,
|
||||
icon: () => IconTablerTrendingUp,
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "Supply",
|
||||
color: colors.profit,
|
||||
seriesType: SeriesType.Area,
|
||||
dataset:
|
||||
params.datasets[scale][
|
||||
`${datasetPrefix}supply_in_profit_to_own_supply_ratio`
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
description: "",
|
||||
},
|
||||
{
|
||||
scale,
|
||||
name: "In Loss",
|
||||
title: `${title} Supply In Loss Relative To Own Supply`,
|
||||
icon: () => IconTablerTrendingDown,
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "Supply",
|
||||
seriesType: SeriesType.Area,
|
||||
color: colors.loss,
|
||||
dataset:
|
||||
params.datasets[scale][
|
||||
`${datasetPrefix}supply_in_loss_to_own_supply_ratio`
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
description: "",
|
||||
},
|
||||
],
|
||||
},
|
||||
// createMomentumPresetFolder({
|
||||
// datasets: datasets[scale],
|
||||
// scale,
|
||||
// id: `${scale}-${id}-supply-in-profit-and-loss-percentage-self`,
|
||||
// title: `${title} Supply In Profit And Loss (% Self)`,
|
||||
// datasetKey: `${datasetKey}SupplyPNL%Self`,
|
||||
// }),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Prices Paid",
|
||||
tree: [
|
||||
{
|
||||
scale,
|
||||
name: `Average`,
|
||||
title: `${title} Average Price Paid - Realized Price`,
|
||||
icon: () => IconTablerMathAvg,
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
list: [
|
||||
{
|
||||
title: "Average",
|
||||
color,
|
||||
dataset:
|
||||
params.datasets[scale][`${datasetPrefix}realized_price`],
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
description: "",
|
||||
},
|
||||
{
|
||||
scale,
|
||||
name: `Deciles`,
|
||||
title: `${title} deciles`,
|
||||
icon: () => IconTablerSquareHalf,
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
list: percentiles
|
||||
.filter(({ value }) => Number(value) % 10 === 0)
|
||||
.map(({ name, key }) => ({
|
||||
dataset: params.datasets[scale][`${datasetPrefix}${key}`],
|
||||
color,
|
||||
title: name,
|
||||
})),
|
||||
});
|
||||
},
|
||||
description: "",
|
||||
},
|
||||
...percentiles.map(
|
||||
(percentile): PartialPreset => ({
|
||||
scale,
|
||||
name: percentile.name,
|
||||
title: `${title} ${percentile.title}`,
|
||||
icon: () => IconTablerSquareHalf,
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
list: [
|
||||
{
|
||||
title: percentile.name,
|
||||
color,
|
||||
dataset:
|
||||
params.datasets[scale][
|
||||
`${datasetPrefix}${percentile.key}`
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
description: "",
|
||||
}),
|
||||
),
|
||||
],
|
||||
},
|
||||
] satisfies PartialPresetTree;
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
// import { PriceScaleMode } from "lightweight-charts";
|
||||
|
||||
// import {
|
||||
// applyMultipleSeries,
|
||||
// colors,
|
||||
// PRICE_SCALE_MOMENTUM_ID,
|
||||
// SeriesType,
|
||||
// } from "/src/scripts";
|
||||
|
||||
// // type HeightMomentumKey =
|
||||
// // | `${AnyPossibleCohortKey}SupplyPNL%Self`
|
||||
// // | `${AnyPossibleCohortKey}RealizedPriceRatio`
|
||||
// // | "activePriceRatio"
|
||||
// // | "vaultedPriceRatio"
|
||||
// // | "trueMarketMeanRatio";
|
||||
|
||||
// // type DateMomentumKey = HeightMomentumKey | `price${AverageName}MARatio`;
|
||||
|
||||
// export function createMomentumPresetFolder<
|
||||
// Scale extends ResourceScale,
|
||||
// Key extends string,
|
||||
// >({
|
||||
// datasets,
|
||||
// scale,
|
||||
// id,
|
||||
// title,
|
||||
// datasetKey,
|
||||
// }: {
|
||||
// datasets: Record<`${Key}${MomentumKey}`, Dataset<ResourceScale>>;
|
||||
// scale: Scale;
|
||||
// id: string;
|
||||
// title: string;
|
||||
// datasetKey: Key;
|
||||
// }): PartialPresetFolder {
|
||||
// return {
|
||||
// id: `${scale}-${id}-momentum`,
|
||||
// name: "Momentum",
|
||||
// tree: [
|
||||
// {
|
||||
// id: `${scale}-${id}-momentum-value`,
|
||||
// name: "Value",
|
||||
// title: `${title} Momentum`,
|
||||
// icon: () => IconTablerRollercoaster,
|
||||
// applyPreset(params) {
|
||||
// return applyMultipleSeries({
|
||||
// scale,
|
||||
// ...params,
|
||||
// list: [
|
||||
// {
|
||||
// title: "Momentum",
|
||||
// colors: colors.momentum,
|
||||
// seriesType: SeriesType.Histogram,
|
||||
// dataset: datasets[`${datasetKey}Momentum`],
|
||||
// options: {
|
||||
// priceScaleId: PRICE_SCALE_MOMENTUM_ID,
|
||||
// lastValueVisible: false,
|
||||
// },
|
||||
// },
|
||||
// ],
|
||||
// });
|
||||
// },
|
||||
// description: "",
|
||||
// },
|
||||
// {
|
||||
// id: `${scale}-${id}-momentum-buy-low-sell-high`,
|
||||
// name: "BLSH - Buy Low Sell High",
|
||||
// tree: [
|
||||
// {
|
||||
// id: `${scale}-${id}-buy-low-sell-high-bitcoin-returns`,
|
||||
// name: "Bitcoin Returns",
|
||||
// title: `${title} Momentum Based Buy Low Sell High Bitcoin Returns`,
|
||||
// icon: () => IconTablerReceiptBitcoin,
|
||||
// applyPreset(params) {
|
||||
// return applyMultipleSeries({
|
||||
// scale,
|
||||
// ...params,
|
||||
// priceScaleOptions: {
|
||||
// halved: true,
|
||||
// mode: PriceScaleMode.Percentage,
|
||||
// },
|
||||
// list: [
|
||||
// {
|
||||
// title: "Bitcoin Returns",
|
||||
// dataset:
|
||||
// datasets[`${datasetKey}MomentumBLSHBitcoinReturns`],
|
||||
// color: colors.bitcoin,
|
||||
// },
|
||||
// ],
|
||||
// });
|
||||
// },
|
||||
// description: "",
|
||||
// },
|
||||
// {
|
||||
// id: `${scale}-${id}-momentum-buy-low-sell-high-dollar-returns`,
|
||||
// name: "Dollar Returns",
|
||||
// title: `${title} Momentum Based Buy Low Sell High Dollar Returns`,
|
||||
// icon: () => IconTablerReceiptDollar,
|
||||
// applyPreset(params) {
|
||||
// return applyMultipleSeries({
|
||||
// scale,
|
||||
// ...params,
|
||||
// priceScaleOptions: {
|
||||
// halved: true,
|
||||
// mode: PriceScaleMode.Percentage,
|
||||
// },
|
||||
// list: [
|
||||
// {
|
||||
// title: "Dollar Returns",
|
||||
// dataset: datasets[`${datasetKey}MomentumBLSHDollarReturns`],
|
||||
// color: colors.dollars,
|
||||
// },
|
||||
// ],
|
||||
// });
|
||||
// },
|
||||
// description: "",
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
// ],
|
||||
// };
|
||||
// }
|
||||
@@ -0,0 +1,183 @@
|
||||
import { applyPriceSeries } from "../../lightweightCharts/chart/price";
|
||||
import { chartState } from "../../lightweightCharts/chart/state";
|
||||
import { setTimeScale } from "../../lightweightCharts/chart/time";
|
||||
import { createAreaSeries } from "../../lightweightCharts/series/creators/area";
|
||||
import {
|
||||
createBaseLineSeries,
|
||||
DEFAULT_BASELINE_COLORS,
|
||||
} from "../../lightweightCharts/series/creators/baseLine";
|
||||
import { createHistogramSeries } from "../../lightweightCharts/series/creators/histogram";
|
||||
import { createSeriesLegend } from "../../lightweightCharts/series/creators/legend";
|
||||
import { createLineSeries } from "../../lightweightCharts/series/creators/line";
|
||||
import { resetRightPriceScale } from "../../lightweightCharts/series/options/priceScale";
|
||||
import { stringToId } from "../../utils/id";
|
||||
|
||||
export enum SeriesType {
|
||||
Normal,
|
||||
Based,
|
||||
Area,
|
||||
Histogram,
|
||||
}
|
||||
|
||||
export function applyMultipleSeries<
|
||||
Scale extends ResourceScale,
|
||||
DS extends Dataset<Scale> & Partial<ResourceDataset<Scale>>,
|
||||
>({
|
||||
chart,
|
||||
list = [],
|
||||
preset,
|
||||
priceScaleOptions,
|
||||
datasets,
|
||||
priceDataset,
|
||||
priceOptions,
|
||||
activeResources,
|
||||
}: {
|
||||
chart: IChartApi;
|
||||
preset: Preset;
|
||||
priceDataset?: DS;
|
||||
priceOptions?: PriceSeriesOptions;
|
||||
priceScaleOptions?: FullPriceScaleOptions;
|
||||
list?: (
|
||||
| {
|
||||
dataset: DS;
|
||||
color?: string;
|
||||
colors?: undefined;
|
||||
seriesType: SeriesType.Based;
|
||||
title: string;
|
||||
options?: BaselineSeriesOptions;
|
||||
defaultVisible?: boolean;
|
||||
}
|
||||
| {
|
||||
dataset: DS;
|
||||
color?: string;
|
||||
colors?: string[];
|
||||
seriesType: SeriesType.Histogram;
|
||||
title: string;
|
||||
options?: DeepPartialHistogramOptions;
|
||||
defaultVisible?: boolean;
|
||||
}
|
||||
| {
|
||||
dataset: DS;
|
||||
color: string;
|
||||
colors?: undefined;
|
||||
seriesType?: SeriesType.Normal | SeriesType.Area;
|
||||
title: string;
|
||||
options?: DeepPartialLineOptions;
|
||||
defaultVisible?: boolean;
|
||||
}
|
||||
)[];
|
||||
datasets: Datasets;
|
||||
activeResources: Accessor<Set<ResourceDataset<any, any>>>;
|
||||
}): PresetLegend {
|
||||
const { halved } = priceScaleOptions || {};
|
||||
|
||||
const price = applyPriceSeries({
|
||||
chart,
|
||||
datasets,
|
||||
preset,
|
||||
dataset: priceDataset,
|
||||
activeResources,
|
||||
options: {
|
||||
...priceOptions,
|
||||
halved,
|
||||
},
|
||||
});
|
||||
|
||||
const legendList: PresetLegend = [price.lineLegend, price.ohlcLegend];
|
||||
|
||||
const isAnyArea = list.find(
|
||||
(config) => config.seriesType === SeriesType.Area,
|
||||
);
|
||||
|
||||
const rightPriceScaleOptions = resetRightPriceScale(chart, {
|
||||
...priceScaleOptions,
|
||||
...(isAnyArea
|
||||
? {
|
||||
scaleMargins: {
|
||||
bottom: 0,
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
});
|
||||
|
||||
[...list]
|
||||
.reverse()
|
||||
.forEach(
|
||||
({
|
||||
dataset,
|
||||
color,
|
||||
colors,
|
||||
seriesType: type,
|
||||
title,
|
||||
options,
|
||||
defaultVisible,
|
||||
}) => {
|
||||
let series: ISeriesApi<"Baseline" | "Line" | "Area" | "Histogram">;
|
||||
|
||||
if (type === SeriesType.Based) {
|
||||
series = createBaseLineSeries(chart, {
|
||||
color,
|
||||
...options,
|
||||
});
|
||||
} else if (type === SeriesType.Area) {
|
||||
series = createAreaSeries(chart, {
|
||||
color,
|
||||
autoscaleInfoProvider: (getInfo: () => AutoscaleInfo | null) => {
|
||||
const info = getInfo();
|
||||
if (info) {
|
||||
info.priceRange.minValue = 0;
|
||||
}
|
||||
return info;
|
||||
},
|
||||
...options,
|
||||
});
|
||||
} else if (type === SeriesType.Histogram) {
|
||||
series = createHistogramSeries(chart, {
|
||||
color,
|
||||
...options,
|
||||
});
|
||||
} else {
|
||||
series = createLineSeries(chart, {
|
||||
color,
|
||||
...options,
|
||||
});
|
||||
}
|
||||
|
||||
legendList.splice(
|
||||
0,
|
||||
0,
|
||||
createSeriesLegend({
|
||||
id: stringToId(title),
|
||||
presetId: preset.id,
|
||||
title,
|
||||
series,
|
||||
color: () => colors || color || DEFAULT_BASELINE_COLORS,
|
||||
defaultVisible,
|
||||
url: dataset.url,
|
||||
}),
|
||||
);
|
||||
|
||||
createEffect(() => {
|
||||
series.setData(dataset?.values() || []);
|
||||
|
||||
setTimeScale(chartState.range);
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
createEffect(() => {
|
||||
const options = {
|
||||
scaleMargins: {
|
||||
top:
|
||||
price.lineLegend.visible() || price.ohlcLegend.visible()
|
||||
? rightPriceScaleOptions.scaleMargins.top
|
||||
: rightPriceScaleOptions.scaleMargins.bottom,
|
||||
bottom: rightPriceScaleOptions.scaleMargins.bottom,
|
||||
},
|
||||
};
|
||||
|
||||
chart.priceScale("right").applyOptions(options);
|
||||
});
|
||||
|
||||
return legendList;
|
||||
}
|
||||
@@ -0,0 +1,289 @@
|
||||
// import {
|
||||
// applyMultipleSeries,
|
||||
// colors,
|
||||
// createMomentumPresetFolder,
|
||||
// SeriesType,
|
||||
// } from "/src/scripts";
|
||||
|
||||
// // type HeightRatioKey =
|
||||
// // | `${AnyPossibleCohortKey}RealizedPrice`
|
||||
// // | "activePrice"
|
||||
// // | "vaultedPrice"
|
||||
// // | "trueMarketMean";
|
||||
|
||||
// // // type DateRatioKey = HeightRatioKey;
|
||||
// // type DateRatioKey = HeightRatioKey | `price${AverageName}MA`;
|
||||
|
||||
// export function createRatioPresetFolder<
|
||||
// Scale extends ResourceScale,
|
||||
// Key extends string,
|
||||
// >({
|
||||
// datasets,
|
||||
// scale,
|
||||
// id,
|
||||
// title,
|
||||
// datasetKey,
|
||||
// color,
|
||||
// }: {
|
||||
// datasets: Record<`${Key}${RatioKey}`, Dataset<ResourceScale>>;
|
||||
// scale: Scale;
|
||||
// id: string;
|
||||
// title: string;
|
||||
// color: string;
|
||||
// datasetKey: Key;
|
||||
// }): PartialPresetFolder {
|
||||
// return {
|
||||
// id: `${scale}-${id}-ratio`,
|
||||
// name: "Ratio",
|
||||
// tree: [
|
||||
// {
|
||||
// id: `${scale}-${id}-ratio-value`,
|
||||
// name: `Value`,
|
||||
// title: `Bitcoin Price to ${title} Ratio`,
|
||||
// icon: () => IconTablerDivide,
|
||||
// applyPreset(params) {
|
||||
// return applyMultipleSeries({
|
||||
// scale,
|
||||
// ...params,
|
||||
// priceScaleOptions: {
|
||||
// halved: true,
|
||||
// },
|
||||
// list: [
|
||||
// {
|
||||
// title: "Ratio",
|
||||
// seriesType: SeriesType.Based,
|
||||
// dataset: datasets[`${datasetKey}Ratio`],
|
||||
// options: {
|
||||
// base: 1,
|
||||
// },
|
||||
// },
|
||||
// ],
|
||||
// });
|
||||
// },
|
||||
// description: "",
|
||||
// },
|
||||
// {
|
||||
// id: `${scale}-${id}-ratio-1y-average`,
|
||||
// name: "Averages",
|
||||
// tree: [
|
||||
// {
|
||||
// id: `${scale}-${id}-ratio-averages`,
|
||||
// name: `7 Day VS. 1 Year`,
|
||||
// title: `Bitcoin Price to ${title} Ratio Moving Averages`,
|
||||
// icon: () => IconTablerSwords,
|
||||
// applyPreset(params) {
|
||||
// return applyMultipleSeries({
|
||||
// scale,
|
||||
// ...params,
|
||||
// priceScaleOptions: {
|
||||
// halved: true,
|
||||
// },
|
||||
// list: [
|
||||
// {
|
||||
// title: "Ratio",
|
||||
// seriesType: SeriesType.Based,
|
||||
// color: colors.gray,
|
||||
// dataset: datasets[`${datasetKey}Ratio`],
|
||||
// options: {
|
||||
// base: 1,
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// title: "7 Day Moving Average",
|
||||
// color: colors.closes7DMA,
|
||||
// dataset: datasets[`${datasetKey}Ratio7DayMovingAverage`],
|
||||
// },
|
||||
// {
|
||||
// title: "1 Year Moving Average",
|
||||
// color: colors.closes1YMA,
|
||||
// dataset: datasets[`${datasetKey}Ratio1YearMovingAverage`],
|
||||
// },
|
||||
// ],
|
||||
// });
|
||||
// },
|
||||
// description: "",
|
||||
// },
|
||||
// createMomentumPresetFolder({
|
||||
// datasets,
|
||||
// scale,
|
||||
// id: `${scale}-${id}-ratio-averages`,
|
||||
// title: `${title} Ratio Moving Averages`,
|
||||
// datasetKey: `${datasetKey}Ratio`,
|
||||
// }),
|
||||
// ],
|
||||
// },
|
||||
// {
|
||||
// id: `${scale}-${id}-ratio-extremes`,
|
||||
// name: "Extremes",
|
||||
// tree: [
|
||||
// {
|
||||
// id: `${scale}-${id}-extreme-top-ratios`,
|
||||
// name: "Top Ratios",
|
||||
// description: "",
|
||||
// icon: () => IconTablerJetpack,
|
||||
// title: `${title} Extreme Top Ratios`,
|
||||
// applyPreset(params) {
|
||||
// return applyMultipleSeries({
|
||||
// scale,
|
||||
// ...params,
|
||||
// priceScaleOptions: {
|
||||
// halved: true,
|
||||
// },
|
||||
// list: [
|
||||
// {
|
||||
// id: "ratio",
|
||||
// title: "Ratio",
|
||||
// color: colors.white,
|
||||
// seriesType: SeriesType.Based,
|
||||
// dataset: datasets[`${datasetKey}Ratio`],
|
||||
// options: {
|
||||
// base: 1,
|
||||
// options: {
|
||||
// baseLineColor: color,
|
||||
// baseLineVisible: true,
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// id: "99.9-percentile",
|
||||
// title: "99.9th Percentile",
|
||||
// dataset: datasets[`${datasetKey}Ratio99.9Percentile`],
|
||||
// color: colors.extremeMax,
|
||||
// },
|
||||
// {
|
||||
// id: "99.5-percentile",
|
||||
// title: "99.5th Percentile",
|
||||
// color: colors.extremeMiddle,
|
||||
// dataset: datasets[`${datasetKey}Ratio99.5Percentile`],
|
||||
// },
|
||||
// {
|
||||
// id: "99-percentile",
|
||||
// title: "99th Percentile",
|
||||
// color: colors.extremeMin,
|
||||
// dataset: datasets[`${datasetKey}Ratio99Percentile`],
|
||||
// },
|
||||
// ],
|
||||
// });
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// id: `${scale}-${id}-extreme-bottom-ratios`,
|
||||
// name: "Bottom Ratios",
|
||||
// description: "",
|
||||
// icon: () => IconTablerScubaMask,
|
||||
// title: `${title} Extreme Bottom Ratios`,
|
||||
// applyPreset(params) {
|
||||
// return applyMultipleSeries({
|
||||
// scale,
|
||||
// ...params,
|
||||
// priceScaleOptions: {
|
||||
// halved: true,
|
||||
// },
|
||||
// list: [
|
||||
// {
|
||||
// id: "ratio",
|
||||
// title: "Ratio",
|
||||
// color: colors.white,
|
||||
// seriesType: SeriesType.Based,
|
||||
// dataset: datasets[`${datasetKey}Ratio`],
|
||||
// options: {
|
||||
// base: 1,
|
||||
// options: {
|
||||
// baseLineColor: color,
|
||||
// baseLineVisible: true,
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// id: "1-percentile",
|
||||
// title: "1st Percentile",
|
||||
// color: colors.extremeMin,
|
||||
// dataset: datasets[`${datasetKey}Ratio1Percentile`],
|
||||
// },
|
||||
// {
|
||||
// id: "0.5-percentile",
|
||||
// title: "0.5th Percentile",
|
||||
// color: colors.extremeMiddle,
|
||||
// dataset: datasets[`${datasetKey}Ratio0.5Percentile`],
|
||||
// },
|
||||
// {
|
||||
// id: "0.1-percentile",
|
||||
// title: "0.1th Percentile",
|
||||
// color: colors.extremeMax,
|
||||
// dataset: datasets[`${datasetKey}Ratio0.1Percentile`],
|
||||
// },
|
||||
// ],
|
||||
// });
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// id: `${scale}-${id}-extreme-top-prices`,
|
||||
// name: "Top Prices",
|
||||
// description: "",
|
||||
// icon: () => IconTablerRocket,
|
||||
// title: `${title} Extreme Top Prices`,
|
||||
// applyPreset(params) {
|
||||
// return applyMultipleSeries({
|
||||
// scale,
|
||||
// ...params,
|
||||
// list: [
|
||||
// {
|
||||
// id: "99.9-percentile",
|
||||
// title: "99.9th Percentile",
|
||||
// color: colors.extremeMax,
|
||||
// dataset: datasets[`${datasetKey}Ratio99.9Price`],
|
||||
// },
|
||||
// {
|
||||
// id: "99.5-percentile",
|
||||
// title: "99.5th Percentile",
|
||||
// color: colors.extremeMiddle,
|
||||
// dataset: datasets[`${datasetKey}Ratio99.5Price`],
|
||||
// },
|
||||
// {
|
||||
// id: "99-percentile",
|
||||
// title: "99th Percentile",
|
||||
// color: colors.extremeMin,
|
||||
// dataset: datasets[`${datasetKey}Ratio99Price`],
|
||||
// },
|
||||
// ],
|
||||
// });
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// id: `${scale}-${id}-extreme-bottom-prices`,
|
||||
// name: "Bottom Prices",
|
||||
// description: "",
|
||||
// icon: () => IconTablerSubmarine,
|
||||
// title: `${title} Extreme Bottom Prices`,
|
||||
// applyPreset(params) {
|
||||
// return applyMultipleSeries({
|
||||
// scale,
|
||||
// ...params,
|
||||
// list: [
|
||||
// {
|
||||
// id: "1-percentile",
|
||||
// title: "1st Percentile",
|
||||
// color: colors.extremeMin,
|
||||
// dataset: datasets[`${datasetKey}Ratio1Price`],
|
||||
// },
|
||||
// {
|
||||
// id: "0.5-percentile",
|
||||
// title: "0.5th Percentile",
|
||||
// color: colors.extremeMiddle,
|
||||
// dataset: datasets[`${datasetKey}Ratio0.5Price`],
|
||||
// },
|
||||
// {
|
||||
// id: "0.1-percentile",
|
||||
// title: "0.1th Percentile",
|
||||
// color: colors.extremeMax,
|
||||
// dataset: datasets[`${datasetKey}Ratio0.1Price`],
|
||||
// },
|
||||
// ],
|
||||
// });
|
||||
// },
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
// ],
|
||||
// };
|
||||
// }
|
||||
@@ -0,0 +1,225 @@
|
||||
import { colors } from "../../utils/colors";
|
||||
import { applyMultipleSeries } from "../templates/multiple";
|
||||
|
||||
export function createPresets(scale: ResourceScale) {
|
||||
return {
|
||||
name: "Transactions",
|
||||
tree: [
|
||||
{
|
||||
scale,
|
||||
icon: IconTablerHandThreeFingers,
|
||||
name: "Count",
|
||||
title: "Transaction Count",
|
||||
description: "",
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "1M SMA",
|
||||
color: colors.momentumYellow,
|
||||
dataset: params.datasets[scale].transaction_count_1m_sma,
|
||||
},
|
||||
{
|
||||
title: "1W SMA",
|
||||
color: colors.bitcoin,
|
||||
dataset: params.datasets[scale].transaction_count_1w_sma,
|
||||
},
|
||||
{
|
||||
title: "Raw",
|
||||
color: colors.darkBitcoin,
|
||||
dataset: params.datasets[scale].transaction_count,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
name: "Volume",
|
||||
tree: [
|
||||
{
|
||||
scale,
|
||||
icon: IconTablerCoinBitcoin,
|
||||
name: "In Bitcoin",
|
||||
title: "Transaction Volume",
|
||||
description: "",
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "1M SMA",
|
||||
color: colors.momentumYellow,
|
||||
dataset: params.datasets[scale].transaction_volume_1m_sma,
|
||||
},
|
||||
{
|
||||
title: "1W SMA",
|
||||
color: colors.bitcoin,
|
||||
dataset: params.datasets[scale].transaction_volume_1w_sma,
|
||||
},
|
||||
{
|
||||
title: "Raw",
|
||||
color: colors.darkBitcoin,
|
||||
dataset: params.datasets[scale].transaction_volume,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
scale,
|
||||
icon: IconTablerCoin,
|
||||
name: "In Dollars",
|
||||
title: "Transaction Volume In Dollars",
|
||||
description: "",
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
mode: 1,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "1M SMA",
|
||||
color: colors.lightDollars,
|
||||
dataset:
|
||||
params.datasets[scale]
|
||||
.transaction_volume_in_dollars_1m_sma,
|
||||
},
|
||||
{
|
||||
title: "1W SMA",
|
||||
color: colors.dollars,
|
||||
dataset:
|
||||
params.datasets[scale]
|
||||
.transaction_volume_in_dollars_1w_sma,
|
||||
},
|
||||
{
|
||||
title: "Raw",
|
||||
color: colors.darkDollars,
|
||||
dataset:
|
||||
params.datasets[scale].transaction_volume_in_dollars,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
{
|
||||
name: "Annualized Volume",
|
||||
tree: [
|
||||
{
|
||||
scale,
|
||||
icon: IconTablerCoinBitcoin,
|
||||
name: "In Bitcoin",
|
||||
title: "Annualized Transaction Volume",
|
||||
description: "",
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "Volume",
|
||||
color: colors.bitcoin,
|
||||
dataset:
|
||||
params.datasets[scale].annualized_transaction_volume,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
scale,
|
||||
icon: IconTablerCoin,
|
||||
name: "In Dollars",
|
||||
title: "Annualized Transaction Volume In Dollars",
|
||||
description: "",
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "Volume",
|
||||
color: colors.dollars,
|
||||
dataset:
|
||||
params.datasets[scale]
|
||||
.annualized_transaction_volume_in_dollars,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
scale,
|
||||
icon: IconTablerWind,
|
||||
name: "Velocity",
|
||||
title: "Transactions Velocity",
|
||||
description: "",
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "Transactions Velocity",
|
||||
color: colors.bitcoin,
|
||||
dataset: params.datasets[scale].transaction_velocity,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
scale,
|
||||
icon: IconTablerAlarm,
|
||||
name: "Per Second",
|
||||
title: "Transactions Per Second",
|
||||
description: "",
|
||||
applyPreset(params) {
|
||||
return applyMultipleSeries({
|
||||
...params,
|
||||
priceScaleOptions: {
|
||||
halved: true,
|
||||
},
|
||||
list: [
|
||||
{
|
||||
title: "1M SMA",
|
||||
color: colors.lightBitcoin,
|
||||
dataset: params.datasets[scale].transactions_per_second_1m_sma,
|
||||
},
|
||||
{
|
||||
title: "1W SMA",
|
||||
color: colors.bitcoin,
|
||||
dataset: params.datasets[scale].transactions_per_second_1w_sma,
|
||||
},
|
||||
{
|
||||
title: "Raw",
|
||||
color: colors.darkBitcoin,
|
||||
dataset: params.datasets[scale].transactions_per_second,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
],
|
||||
} satisfies PartialPresetFolder;
|
||||
}
|
||||
Vendored
+62
@@ -0,0 +1,62 @@
|
||||
interface PartialPreset {
|
||||
scale: ResourceScale;
|
||||
icon?: () => JSXElement;
|
||||
name: string;
|
||||
title: string;
|
||||
applyPreset: ApplyPreset;
|
||||
description: string;
|
||||
}
|
||||
|
||||
interface Preset extends PartialPreset {
|
||||
id: string;
|
||||
path: FilePath;
|
||||
isFavorite: RWS<boolean>;
|
||||
visited: RWS<boolean>;
|
||||
}
|
||||
|
||||
type FilePath = {
|
||||
id: string;
|
||||
name: string;
|
||||
}[];
|
||||
|
||||
type ApplyPreset = (params: {
|
||||
chart: IChartApi;
|
||||
datasets: Datasets;
|
||||
preset: Preset;
|
||||
activeResources: Accessor<Set<ResourceDataset<any, any>>>;
|
||||
}) => ApplyPresetReturn;
|
||||
|
||||
type ApplyPresetReturn = PresetLegend;
|
||||
|
||||
interface PartialPresetFolder {
|
||||
name: string;
|
||||
tree: PartialPresetTree;
|
||||
}
|
||||
|
||||
interface PresetFolder extends PartialPresetFolder {
|
||||
id: string;
|
||||
tree: PresetTree;
|
||||
}
|
||||
|
||||
type PartialPresetTree = (PartialPreset | PartialPresetFolder)[];
|
||||
type PresetTree = (Preset | PresetFolder)[];
|
||||
// type PresetList = Preset[];
|
||||
// type FavoritePresets = Accessor<Preset[]>;
|
||||
|
||||
type PresetsHistory = { date: Date; preset: Preset }[];
|
||||
type PresetsHistorySignal = RWS<PresetsHistory>;
|
||||
type SerializedPresetsHistory = { p: string; d: number }[];
|
||||
|
||||
interface Presets {
|
||||
tree: (Preset | PresetFolder)[];
|
||||
list: Preset[];
|
||||
favorites: Accessor<Preset[]>;
|
||||
history: PresetsHistorySignal;
|
||||
|
||||
selected: RWS<Preset>;
|
||||
openedFolders: RWS<Set<string>>;
|
||||
|
||||
select(preset: Preset): void;
|
||||
}
|
||||
|
||||
type PresetLegend = SeriesLegend[];
|
||||
Reference in New Issue
Block a user