website: update

This commit is contained in:
k
2024-11-27 18:36:43 +01:00
parent d39e7584c0
commit 71871901ef
4 changed files with 216 additions and 115 deletions

View File

@@ -252,7 +252,6 @@
--fuchsia: oklch(0.629 0.294 322.523);
--pink: oklch(0.624 0.245 357.444);
--rose: oklch(0.6155 0.2495 17.012);
--dollar: var(--green);
--background-color: light-dark(var(--white), var(--black));
--color: light-dark(var(--black), var(--white));
--off-color: light-dark(var(--light-gray), var(--dark-gray));
@@ -654,11 +653,11 @@
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
background: url('data:image/svg+xml;utf-8,<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24"><path d="M7 10l5 5 5-5z" fill="gray"/><path d="M0 0h24v24H0z" fill="none"/></svg>')
background: url('data:image/svg+xml;utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="gray"><path fill-rule="evenodd" d="M4.22 6.22a.75.75 0 0 1 1.06 0L8 8.94l2.72-2.72a.75.75 0 1 1 1.06 1.06l-3.25 3.25a.75.75 0 0 1-1.06 0L4.22 7.28a.75.75 0 0 1 0-1.06Z" clip-rule="evenodd" /></svg>')
100% 50% no-repeat transparent;
&:focus-visible {
border: none;
border: 0;
}
}

View File

@@ -1,7 +1,7 @@
// @ts-check
/**
* @import { Option, ResourceDataset, TimeScale, TimeRange, Unit, Marker, Weighted, DatasetPath, OHLC, FetchedJSON, DatasetValue, FetchedResult, AnyDatasetPath, SeriesBlueprint, BaselineSpecificSeriesBlueprint, CandlestickSpecificSeriesBlueprint, LineSpecificSeriesBlueprint, SpecificSeriesBlueprintWithChart, Signal, Color, DatasetCandlestickData, PartialChartOption, ChartOption, AnyPartialOption, ProcessedOptionAddons, OptionsTree, AnyPath, SimulationOption, Frequency, CreatePaneParameters, CreateBaselineSeriesParams, CreateCandlestickSeriesParams, CreateLineSeriesParams } from "./types/self"
* @import { Option, ResourceDataset, TimeScale, TimeRange, Unit, Marker, Weighted, DatasetPath, OHLC, FetchedJSON, DatasetValue, FetchedResult, AnyDatasetPath, SeriesBlueprint, BaselineSpecificSeriesBlueprint, CandlestickSpecificSeriesBlueprint, LineSpecificSeriesBlueprint, SpecificSeriesBlueprintWithChart, Signal, Color, DatasetCandlestickData, PartialChartOption, ChartOption, AnyPartialOption, ProcessedOptionAddons, OptionsTree, AnyPath, SimulationOption, Frequency, CreatePaneParameters, CreateBaselineSeriesParams, CreateCandlestickSeriesParams, CreateLineSeriesParams, LastValues } from "./types/self"
* @import {createChart as CreateClassicChart, createChartEx as CreateCustomChart, LineStyleOptions} from "../packages/lightweight-charts/v4.2.0/types";
* @import * as _ from "../packages/ufuzzy/v1.0.14/types"
* @import { DeepPartial, ChartOptions, IChartApi, IHorzScaleBehavior, WhitespaceData, SingleValueData, ISeriesApi, Time, LineData, LogicalRange, SeriesMarker, CandlestickData, SeriesType, BaselineStyleOptions, SeriesOptionsCommon } from "../packages/lightweight-charts/v4.2.0/types"
@@ -665,8 +665,7 @@ function initPackages() {
const chartModes = /** @type {const} */ (["Linear", "Log"]);
const chartMode = signals.createSignal(
/** @type {Lowercase<typeof chartModes[number]>} */ (
localStorage.getItem(id) ||
chartModes[chartIndex ? 0 : 1].toLowerCase()
localStorage.getItem(id) || "linear"
),
);
@@ -2048,6 +2047,8 @@ function createColors(dark) {
blue,
rose,
pink,
green,
purple,
_1d: pink,
_1w: red,
@@ -2138,7 +2139,6 @@ function createColors(dark) {
coinblocksCreated: purple,
coinblocksDestroyed: red,
coinblocksStored: green,
momentum: [green, yellow, red],
momentumGreen: green,
momentumYellow: yellow,
momentumRed: red,
@@ -2703,9 +2703,8 @@ packages.signals().then((signals) =>
}
const lastHeight = createLastHeightResource();
const lastValues = signals.createSignal(
/** @type {Record<LastPath, number> | null} */ (null),
);
const lastValues = signals.createSignal(/** @type {LastValues} */ (null));
function createFetchLastValuesWhenNeededEffect() {
let previousHeight = -1;
signals.createEffect(lastHeight, (lastHeight) => {
@@ -2831,17 +2830,12 @@ packages.signals().then((signals) =>
signals.runWithOwner(owner, () =>
init({
colors,
consts,
dark,
datasets,
elements,
ids,
lightweightCharts,
options,
selected: option,
signals,
utils,
webSockets,
lastValues,
}),
),
),

View File

@@ -1,35 +1,26 @@
/**
* @import { Options } from './options';
* @import { ColorName } from './types/self';
*/
/**
* @param {Object} args
* @param {Colors} args.colors
* @param {Consts} args.consts
* @param {LightweightCharts} args.lightweightCharts
* @param {SimulationOption} args.selected
* @param {Signals} args.signals
* @param {Utilities} args.utils
* @param {Options} args.options
* @param {Datasets} args.datasets
* @param {WebSockets} args.webSockets
* @param {Elements} args.elements
* @param {Ids} args.ids
* @param {Accessor<boolean>} args.dark
* @param {Signal<LastValues>} args.lastValues
*/
export function init({
colors,
consts,
dark,
datasets,
elements,
ids,
lightweightCharts,
options,
selected,
signals,
utils,
webSockets,
lastValues,
}) {
const simulationElement = elements.simulation;
@@ -137,6 +128,25 @@ export function init({
}).headerElement,
);
/**
* @param {Object} param0
* @param {ColorName} param0.color
* @param {string} param0.type
* @param {string} param0.text
*/
function createColoredTypeHTML({ color, type, text }) {
return `${createColoredSpan({ color, text: `${type}:` })} ${text}`;
}
/**
* @param {Object} param0
* @param {ColorName} param0.color
* @param {string} param0.text
*/
function createColoredSpan({ color, text }) {
return `<span style="color: ${colors[color]()}; font-weight: var(--font-weight-bold)">${text}</span>`;
}
parametersElement.append(
createFieldElement({
title: createColoredTypeHTML({
@@ -291,9 +301,10 @@ export function init({
}),
);
const firstParagraph = window.document.createElement("p");
const secondParagraph = window.document.createElement("p");
const p1 = window.document.createElement("p");
const p2 = window.document.createElement("p");
const p3 = window.document.createElement("p");
const p4 = window.document.createElement("p");
const owner = signals.getOwner();
@@ -326,8 +337,9 @@ export function init({
console.log({ start, end });
resultsElement.innerHTML = "";
resultsElement.append(firstParagraph);
resultsElement.append(secondParagraph);
resultsElement.append(p1);
resultsElement.append(p2);
resultsElement.append(p3);
if (!start || !end || start > end) return;
@@ -361,6 +373,8 @@ export function init({
const daysCountData = [];
/** @type {LineData<Time>[]} */
const profitableDaysRatioData = [];
/** @type {LineData<Time>[]} */
const unprofitableDaysRatioData = [];
let bitcoin = 0;
let dollars = initialDollarAmount;
@@ -374,6 +388,8 @@ export function init({
let daysCount = range.length;
let profitableDays = 0;
let unprofitableDays = 0;
let profitableDaysRatio = 0;
let unprofitableDaysRatio = 0;
range.forEach((date, index) => {
const year = date.getUTCFullYear();
@@ -423,6 +439,8 @@ export function init({
roi = (bitcoinValue / investedAmount - 1) * 100;
const daysCount = index + 1;
profitableDaysRatio = (profitableDays / daysCount) * 100;
unprofitableDaysRatio = (unprofitableDays / daysCount) * 100;
if (roi >= 0) {
profitableDays += 1;
@@ -497,20 +515,78 @@ export function init({
profitableDaysRatioData.push({
time,
value: profitableDays / daysCount,
value: profitableDaysRatio,
});
unprofitableDaysRatioData.push({
time,
value: unprofitableDaysRatio,
});
});
const f = utils.locale.numberToUSFormat;
/**
* @param {string} c
* @param {ColorName} c
* @param {string} t
*/
const c = (c, t) => createColoredSpan({ color: c, text: t });
firstParagraph.innerHTML = `After exchanging ${c("dollar", `$${f(investedAmount)}`)} in the span of ${c("sky", f(daysCount))} days, you would've accumulated ${c("orange", f(bitcoin))} Bitcoin worth ${c("dollar", `$${f(bitcoinValue)}`)} at an average price of ${c("dollar", `$${f(averagePricePaid)}`)} per Bitcoin with a return of investment of ${c("yellow", `${f(roi)}%`)}.`;
const serInvestedAmount = c("dollars", `$${f(investedAmount)}`);
const serDaysCount = c("sky", f(daysCount));
const serBitcoin = c("orange", f(bitcoin));
const serBitcoinValue = c("dollars", `$${f(bitcoinValue)}`);
const serAveragePricePaid = c("dollars", `$${f(averagePricePaid)}`);
const serRoi = c("yellow", `${f(roi)}%`);
secondParagraph.innerHTML = `Work in progress`;
p1.innerHTML = `After exchanging ${serInvestedAmount} in the span of ${serDaysCount} days, you would've accumulated ${serBitcoin} Bitcoin worth ${serBitcoinValue} at an average price of ${serAveragePricePaid} per Bitcoin with a return of investment of ${serRoi}.`;
const serProfitableDaysRatio = c(
"green",
`${f(profitableDaysRatio)}%`,
);
const serUnprofitableDaysRatio = c(
"red",
`${f(unprofitableDaysRatio)}%`,
);
p2.innerHTML = `You would've been ${serProfitableDaysRatio} of the time profitable and ${serUnprofitableDaysRatio} of the time unprofitable.`;
signals.createEffect(lastValues, (lastValues) => {
const lowestAnnual4YReturn = 23.68;
// const lowestAnnual4YReturn = lastValues?.["price-4y-compound-return"] || 0
const serLowestAnnual4YReturn = c(
"yellow",
`${f(lowestAnnual4YReturn)}%`,
);
const lowestAnnual4YReturnPercentage =
1 + lowestAnnual4YReturn / 100;
/**
* @param {number} power
*/
function bitcoinValueReturn(power) {
return (
bitcoinValue * Math.pow(lowestAnnual4YReturnPercentage, power)
);
}
const bitcoinValueAfter4y = bitcoinValueReturn(4);
const serBitcoinValueAfter4y = c(
"rose",
`$${f(bitcoinValueAfter4y)}`,
);
const bitcoinValueAfter10y = bitcoinValueReturn(10);
const serBitcoinValueAfter10y = c(
"pink",
`$${f(bitcoinValueAfter10y)}`,
);
const bitcoinValueAfter20y = bitcoinValueReturn(20);
const serBitcoinValueAfter20y = c(
"purple",
`$${f(bitcoinValueAfter20y)}`,
);
p3.innerHTML = `Historically, the lowest annual return after 4 years has been ${serLowestAnnual4YReturn}.<br/>Using this as our baseline and assuming you don't swap any more US Dollars, your Bitcoin would be worth ${serBitcoinValueAfter4y} after 4 years, ${serBitcoinValueAfter10y} after 10 years and ${serBitcoinValueAfter20y} after 20 years.`;
});
lightweightCharts.createChart({
parent: resultsElement,
@@ -523,12 +599,6 @@ export function init({
unit: "US Dollars",
scale: "date",
config: [
{
kind: "line",
color: colors.dollars,
owner,
data: totalInvestedAmountData,
},
{
kind: "line",
color: colors.bitcoin,
@@ -549,9 +619,9 @@ export function init({
},
{
kind: "line",
color: colors.yellow,
color: colors.dollars,
owner,
data: investmentData,
data: totalInvestedAmountData,
},
{
kind: "line",
@@ -564,6 +634,28 @@ export function init({
],
});
// lightweightCharts.createChart({
// parent: resultsElement,
// signals,
// colors,
// id: `simulation-0`,
// kind: "static",
// config: [
// {
// unit: "US Dollars",
// scale: "date",
// config: [
// {
// kind: "line",
// color: colors.yellow,
// owner,
// data: investmentData,
// },
// ],
// },
// ],
// });
lightweightCharts.createChart({
parent: resultsElement,
signals,
@@ -581,43 +673,38 @@ export function init({
owner,
data: bitcoinData,
},
{
kind: "line",
color: colors.lightBitcoin,
owner,
data: bitcoinAddedData,
},
],
},
],
});
lightweightCharts.createChart({
parent: resultsElement,
signals,
colors,
id: `simulation-2`,
kind: "static",
config: [
{
unit: "US Dollars",
scale: "date",
config: [
{
kind: "baseline",
owner,
data: resultData,
},
],
},
],
});
// lightweightCharts.createChart({
// parent: resultsElement,
// signals,
// colors,
// id: `simulation-1`,
// kind: "static",
// config: [
// {
// unit: "US Dollars",
// scale: "date",
// config: [
// {
// kind: "line",
// color: colors.lightBitcoin,
// owner,
// data: bitcoinAddedData,
// },
// ],
// },
// ],
// });
lightweightCharts.createChart({
parent: resultsElement,
signals,
colors,
id: `simulation-3`,
id: `simulation-average-price`,
kind: "static",
config: [
{
@@ -645,7 +732,66 @@ export function init({
parent: resultsElement,
signals,
colors,
id: `simulation-4`,
id: `simulation-return-ratio`,
kind: "static",
config: [
{
unit: "US Dollars",
scale: "date",
config: [
{
kind: "baseline",
owner,
data: resultData,
// TODO: Doesn't work for some reason
// options: {
// baseLineColor: "#888",
// baseLineVisible: true,
// baseLineWidth: 1,
// baseValue: {
// price: 0,
// type: "price",
// },
// },
},
],
},
],
});
lightweightCharts.createChart({
parent: resultsElement,
signals,
colors,
id: `simulation-profitability-ratios`,
kind: "static",
config: [
{
unit: "Percentage",
scale: "date",
config: [
{
kind: "line",
owner,
color: colors.pink,
data: unprofitableDaysRatioData,
},
{
kind: "line",
owner,
color: colors.lime,
data: profitableDaysRatioData,
},
],
},
],
});
lightweightCharts.createChart({
parent: resultsElement,
signals,
colors,
id: `simulation-counts`,
kind: "static",
config: [
{
@@ -668,28 +814,6 @@ export function init({
},
],
});
lightweightCharts.createChart({
parent: resultsElement,
signals,
colors,
id: `simulation-5`,
kind: "static",
config: [
{
unit: "Percentage",
scale: "date",
config: [
{
kind: "line",
owner,
color: colors.pink,
data: profitableDaysRatioData,
},
],
},
],
});
},
);
});
@@ -804,25 +928,6 @@ function getOrdinalDay(day) {
}`;
}
/**
* @param {Object} param0
* @param {string} param0.color
* @param {string} param0.type
* @param {string} param0.text
*/
function createColoredTypeHTML({ color, type, text }) {
return `${createColoredSpan({ color, text: `${type}:` })} ${text}`;
}
/**
* @param {Object} param0
* @param {string} param0.color
* @param {string} param0.text
*/
function createColoredSpan({ color, text }) {
return `<span style="color: var(--${color}); font-weight: var(--font-weight-bold)">${text}</span>`;
}
function computeFrequencies() {
const weekDays = [
"Monday",

View File

@@ -42,6 +42,7 @@ type AnyDatasetPath = import("./paths").DatePath | import("./paths").HeightPath;
type AnyPath = AnyDatasetPath | LastPath;
type Color = () => string;
type ColorName = keyof Colors;
interface BaselineSpecificSeriesBlueprint {
type: "Baseline";
@@ -399,3 +400,5 @@ interface CreatePaneParameters {
| ({ kind: "baseline" } & CreateBaselineSeriesParams)
)[];
}
type LastValues = Record<LastPath, number> | null;