mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-04-25 15:19:58 -07:00
websites: default: add auto price series type
This commit is contained in:
@@ -2,6 +2,9 @@
|
||||
|
||||
const keyPrefix = "chart";
|
||||
const ONE_BTC_IN_SATS = 100_000_000;
|
||||
const AUTO = "auto";
|
||||
const LINE = "line";
|
||||
const CANDLE = "candle";
|
||||
|
||||
/**
|
||||
* @param {Object} args
|
||||
@@ -95,15 +98,32 @@ export function init({
|
||||
|
||||
elements.charts.append(fieldset);
|
||||
|
||||
const { field: seriesTypeField, selected: topSeriesType } =
|
||||
const { field: seriesTypeField, selected: topSeriesType_ } =
|
||||
utils.dom.createHorizontalChoiceField({
|
||||
defaultValue: "Line",
|
||||
defaultValue: AUTO,
|
||||
keyPrefix,
|
||||
key: "seriestype-0",
|
||||
choices: /** @type {const} */ (["Candles", "Line"]),
|
||||
choices: /** @type {const} */ ([AUTO, CANDLE, LINE]),
|
||||
signals,
|
||||
});
|
||||
|
||||
const topSeriesType = signals.createMemo(() => {
|
||||
const topSeriesType = topSeriesType_();
|
||||
if (topSeriesType === AUTO) {
|
||||
const t = to();
|
||||
const f = from();
|
||||
if (!t || !f) return null;
|
||||
const diff = t - f;
|
||||
if (diff / chart.inner.paneSize().width <= 0.5) {
|
||||
return CANDLE;
|
||||
} else {
|
||||
return LINE;
|
||||
}
|
||||
} else {
|
||||
return topSeriesType;
|
||||
}
|
||||
});
|
||||
|
||||
const { field: topUnitField, selected: topUnit } =
|
||||
utils.dom.createHorizontalChoiceField({
|
||||
defaultValue: "USD",
|
||||
@@ -241,7 +261,7 @@ export function init({
|
||||
chart.addFieldsetIfNeeded({
|
||||
id: "charts-seriestype-0",
|
||||
paneIndex: 0,
|
||||
position: "ne",
|
||||
position: "se",
|
||||
createChild() {
|
||||
return seriesTypeField;
|
||||
},
|
||||
@@ -260,7 +280,7 @@ export function init({
|
||||
switch (topUnit) {
|
||||
case "USD": {
|
||||
switch (topSeriesType) {
|
||||
case "Candles": {
|
||||
case CANDLE: {
|
||||
series = chart.addCandlestickSeries({
|
||||
vecId: "ohlc",
|
||||
name: "Price",
|
||||
@@ -271,7 +291,7 @@ export function init({
|
||||
|
||||
break;
|
||||
}
|
||||
case "Line": {
|
||||
case LINE: {
|
||||
series = chart.addLineSeries({
|
||||
vecId: "close",
|
||||
name: "Price",
|
||||
@@ -289,7 +309,7 @@ export function init({
|
||||
}
|
||||
case "Sats": {
|
||||
switch (topSeriesType) {
|
||||
case "Candles": {
|
||||
case CANDLE: {
|
||||
series = chart.addCandlestickSeries({
|
||||
vecId: "ohlc-in-sats",
|
||||
name: "Price",
|
||||
@@ -300,7 +320,7 @@ export function init({
|
||||
});
|
||||
break;
|
||||
}
|
||||
case "Line": {
|
||||
case LINE: {
|
||||
series = chart.addLineSeries({
|
||||
vecId: "close-in-sats",
|
||||
name: "Price",
|
||||
|
||||
@@ -76,7 +76,7 @@ export function init({
|
||||
input.value = value;
|
||||
stateValue = value;
|
||||
}
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
input.addEventListener("input", () => {
|
||||
@@ -139,7 +139,7 @@ export function init({
|
||||
input.value = value;
|
||||
stateValue = value;
|
||||
}
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
input.addEventListener("change", () => {
|
||||
@@ -328,7 +328,7 @@ export function init({
|
||||
keyPrefix,
|
||||
key: "top-up-freq",
|
||||
},
|
||||
},
|
||||
}
|
||||
),
|
||||
},
|
||||
},
|
||||
@@ -356,7 +356,7 @@ export function init({
|
||||
keyPrefix,
|
||||
key: "swap-freq",
|
||||
},
|
||||
},
|
||||
}
|
||||
),
|
||||
},
|
||||
},
|
||||
@@ -369,7 +369,7 @@ export function init({
|
||||
keyPrefix,
|
||||
key: "interval-start",
|
||||
},
|
||||
},
|
||||
}
|
||||
),
|
||||
end: signals.createSignal(/** @type {Date | null} */ (new Date()), {
|
||||
save: {
|
||||
@@ -391,7 +391,7 @@ export function init({
|
||||
};
|
||||
|
||||
parametersElement.append(
|
||||
utils.dom.createHeader("Save in Bitcoin").headerElement,
|
||||
utils.dom.createHeader("Save in Bitcoin").headerElement
|
||||
);
|
||||
|
||||
/**
|
||||
@@ -410,7 +410,9 @@ export function init({
|
||||
* @param {string} param0.text
|
||||
*/
|
||||
function createColoredSpan({ color, text }) {
|
||||
return `<span style="color: ${colors[color]()}; font-weight: 500; text-transform: uppercase;
|
||||
return `<span style="color: ${colors[
|
||||
color
|
||||
]()}; font-weight: 500; text-transform: uppercase;
|
||||
font-size: var(--font-size-sm);">${text}</span>`;
|
||||
}
|
||||
|
||||
@@ -429,9 +431,9 @@ export function init({
|
||||
title: "Initial Dollar Amount",
|
||||
signal: settings.dollars.initial.amount,
|
||||
signals,
|
||||
}),
|
||||
})
|
||||
),
|
||||
}),
|
||||
})
|
||||
);
|
||||
|
||||
parametersElement.append(
|
||||
@@ -449,9 +451,9 @@ export function init({
|
||||
list: frequencies.list,
|
||||
signal: settings.dollars.topUp.frenquency,
|
||||
deep: true,
|
||||
}),
|
||||
})
|
||||
),
|
||||
}),
|
||||
})
|
||||
);
|
||||
|
||||
parametersElement.append(
|
||||
@@ -469,9 +471,9 @@ export function init({
|
||||
title: "Top Up Dollar Amount",
|
||||
signal: settings.dollars.topUp.amount,
|
||||
signals,
|
||||
}),
|
||||
})
|
||||
),
|
||||
}),
|
||||
})
|
||||
);
|
||||
|
||||
parametersElement.append(
|
||||
@@ -489,9 +491,9 @@ export function init({
|
||||
title: "Initial Swap Amount",
|
||||
signal: settings.bitcoin.investment.initial,
|
||||
signals,
|
||||
}),
|
||||
})
|
||||
),
|
||||
}),
|
||||
})
|
||||
);
|
||||
|
||||
parametersElement.append(
|
||||
@@ -508,9 +510,9 @@ export function init({
|
||||
list: frequencies.list,
|
||||
signal: settings.bitcoin.investment.frequency,
|
||||
deep: true,
|
||||
}),
|
||||
})
|
||||
),
|
||||
}),
|
||||
})
|
||||
);
|
||||
|
||||
parametersElement.append(
|
||||
@@ -528,9 +530,9 @@ export function init({
|
||||
title: "Bitcoin Recurrent Investment",
|
||||
signal: settings.bitcoin.investment.recurrent,
|
||||
signals,
|
||||
}),
|
||||
})
|
||||
),
|
||||
}),
|
||||
})
|
||||
);
|
||||
|
||||
parametersElement.append(
|
||||
@@ -547,9 +549,9 @@ export function init({
|
||||
title: "First Simulation Date",
|
||||
signal: settings.interval.start,
|
||||
signals,
|
||||
}),
|
||||
})
|
||||
),
|
||||
}),
|
||||
})
|
||||
);
|
||||
|
||||
parametersElement.append(
|
||||
@@ -566,9 +568,9 @@ export function init({
|
||||
title: "Last Simulation Day",
|
||||
signal: settings.interval.end,
|
||||
signals,
|
||||
}),
|
||||
})
|
||||
),
|
||||
}),
|
||||
})
|
||||
);
|
||||
|
||||
parametersElement.append(
|
||||
@@ -589,9 +591,9 @@ export function init({
|
||||
step: 0.01,
|
||||
signals,
|
||||
placeholder: "Fees",
|
||||
}),
|
||||
})
|
||||
),
|
||||
}),
|
||||
})
|
||||
);
|
||||
|
||||
const p1 = window.document.createElement("p");
|
||||
@@ -606,94 +608,94 @@ export function init({
|
||||
const owner = signals.getOwner();
|
||||
|
||||
const totalInvestedAmountData = signals.createSignal(
|
||||
/** @type {LineData<Time>[]} */ ([]),
|
||||
/** @type {LineData<number>[]} */ ([]),
|
||||
{
|
||||
equals: false,
|
||||
},
|
||||
}
|
||||
);
|
||||
const bitcoinValueData = signals.createSignal(
|
||||
/** @type {LineData<Time>[]} */ ([]),
|
||||
/** @type {LineData<number>[]} */ ([]),
|
||||
{
|
||||
equals: false,
|
||||
},
|
||||
}
|
||||
);
|
||||
const bitcoinData = signals.createSignal(
|
||||
/** @type {LineData<Time>[]} */ ([]),
|
||||
/** @type {LineData<number>[]} */ ([]),
|
||||
{
|
||||
equals: false,
|
||||
},
|
||||
}
|
||||
);
|
||||
const resultData = signals.createSignal(
|
||||
/** @type {LineData<Time>[]} */ ([]),
|
||||
/** @type {LineData<number>[]} */ ([]),
|
||||
{
|
||||
equals: false,
|
||||
},
|
||||
}
|
||||
);
|
||||
const dollarsLeftData = signals.createSignal(
|
||||
/** @type {LineData<Time>[]} */ ([]),
|
||||
/** @type {LineData<number>[]} */ ([]),
|
||||
{
|
||||
equals: false,
|
||||
},
|
||||
}
|
||||
);
|
||||
const totalValueData = signals.createSignal(
|
||||
/** @type {LineData<Time>[]} */ ([]),
|
||||
/** @type {LineData<number>[]} */ ([]),
|
||||
{
|
||||
equals: false,
|
||||
},
|
||||
}
|
||||
);
|
||||
const investmentData = signals.createSignal(
|
||||
/** @type {LineData<Time>[]} */ ([]),
|
||||
/** @type {LineData<number>[]} */ ([]),
|
||||
{
|
||||
equals: false,
|
||||
},
|
||||
}
|
||||
);
|
||||
const bitcoinAddedData = signals.createSignal(
|
||||
/** @type {LineData<Time>[]} */ ([]),
|
||||
/** @type {LineData<number>[]} */ ([]),
|
||||
{
|
||||
equals: false,
|
||||
},
|
||||
}
|
||||
);
|
||||
const averagePricePaidData = signals.createSignal(
|
||||
/** @type {LineData<Time>[]} */ ([]),
|
||||
/** @type {LineData<number>[]} */ ([]),
|
||||
{
|
||||
equals: false,
|
||||
},
|
||||
}
|
||||
);
|
||||
const bitcoinPriceData = signals.createSignal(
|
||||
/** @type {LineData<Time>[]} */ ([]),
|
||||
/** @type {LineData<number>[]} */ ([]),
|
||||
{
|
||||
equals: false,
|
||||
},
|
||||
}
|
||||
);
|
||||
const buyCountData = signals.createSignal(
|
||||
/** @type {LineData<Time>[]} */ ([]),
|
||||
/** @type {LineData<number>[]} */ ([]),
|
||||
{
|
||||
equals: false,
|
||||
},
|
||||
}
|
||||
);
|
||||
const totalFeesPaidData = signals.createSignal(
|
||||
/** @type {LineData<Time>[]} */ ([]),
|
||||
/** @type {LineData<number>[]} */ ([]),
|
||||
{
|
||||
equals: false,
|
||||
},
|
||||
}
|
||||
);
|
||||
const daysCountData = signals.createSignal(
|
||||
/** @type {LineData<Time>[]} */ ([]),
|
||||
/** @type {LineData<number>[]} */ ([]),
|
||||
{
|
||||
equals: false,
|
||||
},
|
||||
}
|
||||
);
|
||||
const profitableDaysRatioData = signals.createSignal(
|
||||
/** @type {LineData<Time>[]} */ ([]),
|
||||
/** @type {LineData<number>[]} */ ([]),
|
||||
{
|
||||
equals: false,
|
||||
},
|
||||
}
|
||||
);
|
||||
const unprofitableDaysRatioData = signals.createSignal(
|
||||
/** @type {LineData<Time>[]} */ ([]),
|
||||
/** @type {LineData<number>[]} */ ([]),
|
||||
{
|
||||
equals: false,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const index = () => /** @type {DateIndex} */ (0);
|
||||
@@ -933,8 +935,7 @@ export function init({
|
||||
let lastSatsAdded = 0;
|
||||
|
||||
range.forEach((date, index) => {
|
||||
const year = date.getUTCFullYear();
|
||||
const time = utils.date.toString(date);
|
||||
const time = date.valueOf() / 1000;
|
||||
|
||||
if (topUpFrequency.isTriggerDay(date)) {
|
||||
dollars += topUpAmount;
|
||||
@@ -1095,16 +1096,21 @@ export function init({
|
||||
p1.innerHTML = `After exchanging ${serInvestedAmount} in the span of ${serDaysCount} days, you would have accumulated ${serSats} Satoshis (${serBitcoin} Bitcoin) worth today ${serBitcoinValue} at an average price of ${serAveragePricePaid} per Bitcoin with a return of investment of ${serRoi}, have ${serDollars} left and paid a total of ${serTotalFeesPaid} in fees.`;
|
||||
|
||||
const dayDiff = Math.floor(
|
||||
utils.date.differenceBetween(new Date(), lastInvestDay),
|
||||
utils.date.differenceBetween(new Date(), lastInvestDay)
|
||||
);
|
||||
const serDailyInvestment = c("emerald", fd(dailyInvestment));
|
||||
const setLastSatsAdded = c("orange", f(lastSatsAdded));
|
||||
p2.innerHTML = `You would've last bought ${c("blue", dayDiff ? `${f(dayDiff)} ${dayDiff > 1 ? "days" : "day"} ago` : "today")} and exchanged ${serDailyInvestment} for approximately ${setLastSatsAdded} Satoshis`;
|
||||
p2.innerHTML = `You would've last bought ${c(
|
||||
"blue",
|
||||
dayDiff
|
||||
? `${f(dayDiff)} ${dayDiff > 1 ? "days" : "day"} ago`
|
||||
: "today"
|
||||
)} and exchanged ${serDailyInvestment} for approximately ${setLastSatsAdded} Satoshis`;
|
||||
|
||||
const serProfitableDaysRatio = c("green", fp(profitableDaysRatio));
|
||||
const serUnprofitableDaysRatio = c(
|
||||
"red",
|
||||
fp(unprofitableDaysRatio),
|
||||
fp(unprofitableDaysRatio)
|
||||
);
|
||||
|
||||
p3.innerHTML = `You would've been ${serProfitableDaysRatio} of the time profitable and ${serUnprofitableDaysRatio} of the time unprofitable.`;
|
||||
@@ -1114,7 +1120,7 @@ export function init({
|
||||
(lowestAnnual4YReturn) => {
|
||||
const serLowestAnnual4YReturn = c(
|
||||
"cyan",
|
||||
`${fp(lowestAnnual4YReturn)}`,
|
||||
`${fp(lowestAnnual4YReturn)}`
|
||||
);
|
||||
|
||||
const lowestAnnual4YReturnPercentage = 1 + lowestAnnual4YReturn;
|
||||
@@ -1130,22 +1136,22 @@ export function init({
|
||||
const bitcoinValueAfter4y = bitcoinValueReturn(4);
|
||||
const serBitcoinValueAfter4y = c(
|
||||
"purple",
|
||||
fd(bitcoinValueAfter4y),
|
||||
fd(bitcoinValueAfter4y)
|
||||
);
|
||||
const bitcoinValueAfter10y = bitcoinValueReturn(10);
|
||||
const serBitcoinValueAfter10y = c(
|
||||
"fuchsia",
|
||||
fd(bitcoinValueAfter10y),
|
||||
fd(bitcoinValueAfter10y)
|
||||
);
|
||||
const bitcoinValueAfter21y = bitcoinValueReturn(21);
|
||||
const serBitcoinValueAfter21y = c(
|
||||
"pink",
|
||||
fd(bitcoinValueAfter21y),
|
||||
fd(bitcoinValueAfter21y)
|
||||
);
|
||||
|
||||
/** @param {number} v */
|
||||
p4.innerHTML = `The lowest annual return after 4 years has historically been ${serLowestAnnual4YReturn}.<br/>Using it as the baseline, your Bitcoin would be worth ${serBitcoinValueAfter4y} after 4 years, ${serBitcoinValueAfter10y} after 10 years and ${serBitcoinValueAfter21y} after 21 years.`;
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
totalInvestedAmountData.set((a) => a);
|
||||
@@ -1163,7 +1169,7 @@ export function init({
|
||||
daysCountData.set((a) => a);
|
||||
profitableDaysRatioData.set((a) => a);
|
||||
unprofitableDaysRatioData.set((a) => a);
|
||||
},
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user