mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-05-29 21:29:27 -07:00
global: 4y zscore + 200d sma + mayer's multiple
This commit is contained in:
@@ -63,14 +63,14 @@ function initPackages() {
|
||||
const imports = {
|
||||
async signals() {
|
||||
return import("../packages/solid-signals/wrapper.js").then(
|
||||
(d) => d.default
|
||||
(d) => d.default,
|
||||
);
|
||||
},
|
||||
async lightweightCharts() {
|
||||
return window.document.fonts.ready.then(() =>
|
||||
import("../packages/lightweight-charts/wrapper.js").then(
|
||||
(d) => d.default
|
||||
)
|
||||
(d) => d.default,
|
||||
),
|
||||
);
|
||||
},
|
||||
async leanQr() {
|
||||
@@ -78,7 +78,7 @@ function initPackages() {
|
||||
},
|
||||
async ufuzzy() {
|
||||
return import("../packages/ufuzzy/v1.0.18/script.js").then(
|
||||
({ default: d }) => d
|
||||
({ default: d }) => d,
|
||||
);
|
||||
},
|
||||
};
|
||||
@@ -586,7 +586,7 @@ function createUtils() {
|
||||
window.history.pushState(
|
||||
null,
|
||||
"",
|
||||
`${pathname}?${urlParams.toString()}`
|
||||
`${pathname}?${urlParams.toString()}`,
|
||||
);
|
||||
} catch (_) {}
|
||||
},
|
||||
@@ -603,7 +603,7 @@ function createUtils() {
|
||||
window.history.replaceState(
|
||||
null,
|
||||
"",
|
||||
`${pathname}?${urlParams.toString()}`
|
||||
`${pathname}?${urlParams.toString()}`,
|
||||
);
|
||||
} catch (_) {}
|
||||
},
|
||||
@@ -752,7 +752,8 @@ function createUtils() {
|
||||
(id.includes("realized") &&
|
||||
!id.includes("ratio") &&
|
||||
!id.includes("relative-to")) ||
|
||||
(id.endsWith("sma") && !id.includes("ratio")) ||
|
||||
((id.endsWith("sma") || id.includes("sma-x")) &&
|
||||
!id.includes("ratio")) ||
|
||||
id === "ath")
|
||||
) {
|
||||
if (unit) throw Error(`Unit "${unit}" already assigned "${id}"`);
|
||||
@@ -1242,8 +1243,8 @@ function createUtils() {
|
||||
today.getUTCDate(),
|
||||
0,
|
||||
0,
|
||||
0
|
||||
)
|
||||
0,
|
||||
),
|
||||
);
|
||||
},
|
||||
/**
|
||||
@@ -1336,7 +1337,7 @@ function createUtils() {
|
||||
*/
|
||||
function getNumberOfDaysBetweenTwoDates(oldest, youngest) {
|
||||
return Math.round(
|
||||
Math.abs((youngest.getTime() - oldest.getTime()) / date.ONE_DAY_IN_MS)
|
||||
Math.abs((youngest.getTime() - oldest.getTime()) / date.ONE_DAY_IN_MS),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1554,7 +1555,7 @@ function createVecsResources(signals, utils) {
|
||||
const fetchedRecord = signals.createSignal(
|
||||
/** @type {Map<string, {loading: boolean, at: Date | null, vec: Signal<T[] | null>}>} */ (
|
||||
new Map()
|
||||
)
|
||||
),
|
||||
);
|
||||
|
||||
return {
|
||||
@@ -1602,7 +1603,7 @@ function createVecsResources(signals, utils) {
|
||||
index,
|
||||
id,
|
||||
from,
|
||||
to
|
||||
to,
|
||||
)
|
||||
);
|
||||
fetched.at = new Date();
|
||||
@@ -1863,7 +1864,7 @@ function initWebSockets(signals, utils) {
|
||||
|
||||
window.document.addEventListener(
|
||||
"visibilitychange",
|
||||
reinitWebSocketIfDocumentNotHidden
|
||||
reinitWebSocketIfDocumentNotHidden,
|
||||
);
|
||||
|
||||
window.document.addEventListener("online", reinitWebSocket);
|
||||
@@ -1872,7 +1873,7 @@ function initWebSockets(signals, utils) {
|
||||
ws?.close();
|
||||
window.document.removeEventListener(
|
||||
"visibilitychange",
|
||||
reinitWebSocketIfDocumentNotHidden
|
||||
reinitWebSocketIfDocumentNotHidden,
|
||||
);
|
||||
window.document.removeEventListener("online", reinitWebSocket);
|
||||
live.set(false);
|
||||
@@ -1898,7 +1899,7 @@ function initWebSockets(signals, utils) {
|
||||
symbol: ["BTC/USD"],
|
||||
interval: 1440,
|
||||
},
|
||||
})
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
@@ -1927,7 +1928,7 @@ function initWebSockets(signals, utils) {
|
||||
|
||||
/** @type {ReturnType<typeof createWebsocket<CandlestickData>>} */
|
||||
const kraken1dCandle = createWebsocket((callback) =>
|
||||
krakenCandleWebSocketCreator(callback)
|
||||
krakenCandleWebSocketCreator(callback),
|
||||
);
|
||||
|
||||
kraken1dCandle.open();
|
||||
@@ -1986,7 +1987,7 @@ function main() {
|
||||
}
|
||||
|
||||
const frame = window.document.getElementById(
|
||||
/** @type {string} */ (input.value)
|
||||
/** @type {string} */ (input.value),
|
||||
);
|
||||
|
||||
if (!frame) {
|
||||
@@ -2084,23 +2085,23 @@ function main() {
|
||||
|
||||
function initDark() {
|
||||
const preferredColorSchemeMatchMedia = window.matchMedia(
|
||||
"(prefers-color-scheme: dark)"
|
||||
"(prefers-color-scheme: dark)",
|
||||
);
|
||||
const dark = signals.createSignal(
|
||||
preferredColorSchemeMatchMedia.matches
|
||||
preferredColorSchemeMatchMedia.matches,
|
||||
);
|
||||
preferredColorSchemeMatchMedia.addEventListener(
|
||||
"change",
|
||||
({ matches }) => {
|
||||
dark.set(matches);
|
||||
}
|
||||
},
|
||||
);
|
||||
return dark;
|
||||
}
|
||||
const dark = initDark();
|
||||
|
||||
const qrcode = signals.createSignal(
|
||||
/** @type {string | null} */ (null)
|
||||
/** @type {string | null} */ (null),
|
||||
);
|
||||
|
||||
function createLastHeightResource() {
|
||||
@@ -2111,7 +2112,7 @@ function main() {
|
||||
lastHeight.set(h);
|
||||
},
|
||||
/** @satisfies {Height} */ (5),
|
||||
"height"
|
||||
"height",
|
||||
);
|
||||
}
|
||||
fetchLastHeight();
|
||||
@@ -2155,10 +2156,10 @@ function main() {
|
||||
const owner = signals.getOwner();
|
||||
|
||||
const chartOption = signals.createSignal(
|
||||
/** @type {ChartOption | null} */ (null)
|
||||
/** @type {ChartOption | null} */ (null),
|
||||
);
|
||||
const simOption = signals.createSignal(
|
||||
/** @type {SimulationOption | null} */ (null)
|
||||
/** @type {SimulationOption | null} */ (null),
|
||||
);
|
||||
|
||||
let previousElement = /** @type {HTMLElement | undefined} */ (
|
||||
@@ -2204,9 +2205,9 @@ function main() {
|
||||
webSockets,
|
||||
vecsResources,
|
||||
vecIdToIndexes,
|
||||
})
|
||||
)
|
||||
)
|
||||
}),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
firstTimeLoadingChart = false;
|
||||
@@ -2227,8 +2228,8 @@ function main() {
|
||||
vecsResources,
|
||||
option,
|
||||
vecIdToIndexes,
|
||||
})
|
||||
)
|
||||
}),
|
||||
),
|
||||
);
|
||||
}
|
||||
firstTimeLoadingTable = false;
|
||||
@@ -2252,9 +2253,9 @@ function main() {
|
||||
signals,
|
||||
utils,
|
||||
vecsResources,
|
||||
})
|
||||
)
|
||||
)
|
||||
}),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
firstTimeLoadingSimulation = false;
|
||||
@@ -2283,7 +2284,7 @@ function main() {
|
||||
createMobileSwitchEffect();
|
||||
|
||||
utils.dom.onFirstIntersection(elements.aside, () =>
|
||||
signals.runWithOwner(owner, initSelectedFrame)
|
||||
signals.runWithOwner(owner, initSelectedFrame),
|
||||
);
|
||||
}
|
||||
initSelected();
|
||||
@@ -2361,7 +2362,7 @@ function main() {
|
||||
if (indexes?.length) {
|
||||
const maxIndex = Math.min(
|
||||
(order || indexes).length - 1,
|
||||
minIndex + RESULTS_PER_PAGE - 1
|
||||
minIndex + RESULTS_PER_PAGE - 1,
|
||||
);
|
||||
|
||||
list = Array(maxIndex - minIndex + 1);
|
||||
@@ -2437,7 +2438,7 @@ function main() {
|
||||
haystack,
|
||||
needle,
|
||||
undefined,
|
||||
infoThresh
|
||||
infoThresh,
|
||||
);
|
||||
|
||||
if (!result?.[0]?.length || !result?.[1]) {
|
||||
@@ -2445,7 +2446,7 @@ function main() {
|
||||
haystack,
|
||||
needle,
|
||||
outOfOrder,
|
||||
infoThresh
|
||||
infoThresh,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2454,7 +2455,7 @@ function main() {
|
||||
haystack,
|
||||
needle,
|
||||
outOfOrder,
|
||||
infoThresh
|
||||
infoThresh,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2463,7 +2464,7 @@ function main() {
|
||||
haystack,
|
||||
needle,
|
||||
outOfOrder,
|
||||
infoThresh
|
||||
infoThresh,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2472,7 +2473,7 @@ function main() {
|
||||
haystack,
|
||||
needle,
|
||||
undefined,
|
||||
infoThresh
|
||||
infoThresh,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2481,7 +2482,7 @@ function main() {
|
||||
haystack,
|
||||
needle,
|
||||
outOfOrder,
|
||||
infoThresh
|
||||
infoThresh,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2564,7 +2565,7 @@ function main() {
|
||||
|
||||
shareDiv.hidden = false;
|
||||
});
|
||||
})
|
||||
}),
|
||||
);
|
||||
}
|
||||
initShare();
|
||||
@@ -2588,7 +2589,7 @@ function main() {
|
||||
utils.storage.write(barWidthLocalStorageKey, String(width));
|
||||
} else {
|
||||
elements.main.style.width = elements.style.getPropertyValue(
|
||||
"--default-main-width"
|
||||
"--default-main-width",
|
||||
);
|
||||
utils.storage.remove(barWidthLocalStorageKey);
|
||||
}
|
||||
@@ -2625,9 +2626,9 @@ function main() {
|
||||
window.addEventListener("mouseleave", setResizeFalse);
|
||||
}
|
||||
initDesktopResizeBar();
|
||||
})
|
||||
)
|
||||
)
|
||||
}),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
main();
|
||||
|
||||
@@ -162,15 +162,16 @@ function createPartialOptions(colors) {
|
||||
*/
|
||||
|
||||
const averages = /** @type {const} */ ([
|
||||
{ name: "1 Week", key: "1w", days: 7, color: colors.orange },
|
||||
{ name: "8 Day", key: "8d", days: 8, color: colors.amber },
|
||||
{ name: "13 Day", key: "13d", days: 13, color: colors.yellow },
|
||||
{ name: "21 Day", key: "21d", days: 21, color: colors.lime },
|
||||
{ name: "1 Month", key: "1m", days: 30, color: colors.green },
|
||||
{ name: "34 Day", key: "34d", days: 34, color: colors.emerald },
|
||||
{ name: "55 Day", key: "55d", days: 55, color: colors.teal },
|
||||
{ name: "89 Day", key: "89d", days: 89, color: colors.cyan },
|
||||
{ name: "144 Day", key: "144d", days: 144, color: colors.sky },
|
||||
{ name: "1 Week", key: "1w", days: 7, color: colors.red },
|
||||
{ name: "8 Day", key: "8d", days: 8, color: colors.orange },
|
||||
{ name: "13 Day", key: "13d", days: 13, color: colors.amber },
|
||||
{ name: "21 Day", key: "21d", days: 21, color: colors.yellow },
|
||||
{ name: "1 Month", key: "1m", days: 30, color: colors.lime },
|
||||
{ name: "34 Day", key: "34d", days: 34, color: colors.green },
|
||||
{ name: "55 Day", key: "55d", days: 55, color: colors.emerald },
|
||||
{ name: "89 Day", key: "89d", days: 89, color: colors.teal },
|
||||
{ name: "144 Day", key: "144d", days: 144, color: colors.cyan },
|
||||
{ name: "200 Day", key: "200d", days: 200, color: colors.sky },
|
||||
{ name: "1 Year", key: "1y", days: 365, color: colors.blue },
|
||||
{ name: "2 Year", key: "2y", days: 2 * 365, color: colors.indigo },
|
||||
{ name: "200 Week", key: "200w", days: 200 * 7, color: colors.violet },
|
||||
@@ -1057,12 +1058,6 @@ function createPartialOptions(colors) {
|
||||
},
|
||||
},
|
||||
}),
|
||||
createBaseSeries({
|
||||
key: `${key}-ratio-sma`,
|
||||
name: "sma",
|
||||
color: colors.yellow,
|
||||
defaultActive: false,
|
||||
}),
|
||||
createBaseSeries({
|
||||
key: `${key}-ratio-p1sd`,
|
||||
name: "+1σ",
|
||||
@@ -1153,6 +1148,18 @@ function createPartialOptions(colors) {
|
||||
color: colors.rose,
|
||||
defaultActive: false,
|
||||
}),
|
||||
createBaseSeries({
|
||||
key: `${key}-ratio-4y-sma`,
|
||||
name: "4y-sma",
|
||||
color: colors.violet,
|
||||
defaultActive: false,
|
||||
}),
|
||||
createBaseSeries({
|
||||
key: `${key}-ratio-sma`,
|
||||
name: "sma",
|
||||
color: colors.yellow,
|
||||
defaultActive: false,
|
||||
}),
|
||||
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
|
||||
key: `${key}-ratio-1y-sma-momentum-oscillator`,
|
||||
title: "1Y Momentum",
|
||||
@@ -1165,7 +1172,7 @@ function createPartialOptions(colors) {
|
||||
}),
|
||||
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
|
||||
key: `${key}-ratio-zscore`,
|
||||
title: "Score",
|
||||
title: "All time",
|
||||
type: "Baseline",
|
||||
options: {
|
||||
createPriceLine: {
|
||||
@@ -1173,6 +1180,17 @@ function createPartialOptions(colors) {
|
||||
},
|
||||
},
|
||||
}),
|
||||
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
|
||||
key: `${key}-ratio-4y-zscore`,
|
||||
title: "4y",
|
||||
type: "Baseline",
|
||||
colors: [colors.yellow, colors.pink],
|
||||
options: {
|
||||
createPriceLine: {
|
||||
value: 0,
|
||||
},
|
||||
},
|
||||
}),
|
||||
],
|
||||
};
|
||||
}
|
||||
@@ -1413,7 +1431,7 @@ function createPartialOptions(colors) {
|
||||
key: `${fixKey(key)}realized-price`,
|
||||
name,
|
||||
color,
|
||||
})
|
||||
}),
|
||||
),
|
||||
}
|
||||
: createPriceWithRatio({
|
||||
@@ -1496,7 +1514,7 @@ function createPartialOptions(colors) {
|
||||
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
|
||||
type: "Baseline",
|
||||
key: `${fixKey(
|
||||
key
|
||||
key,
|
||||
)}net-realized-profit-and-loss-relative-to-realized-cap`,
|
||||
title: useGroupName ? name : "Net",
|
||||
color: useGroupName ? color : undefined,
|
||||
@@ -1530,6 +1548,9 @@ function createPartialOptions(colors) {
|
||||
key: `${fixKey(key)}adjusted-spent-output-profit-ratio`,
|
||||
title: useGroupName ? name : "asopr",
|
||||
color: useGroupName ? color : undefined,
|
||||
colors: useGroupName
|
||||
? undefined
|
||||
: [colors.yellow, colors.pink],
|
||||
options: {
|
||||
createPriceLine: {
|
||||
value: 1,
|
||||
@@ -1567,7 +1588,7 @@ function createPartialOptions(colors) {
|
||||
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
|
||||
type: "Baseline",
|
||||
key: `${fixKey(
|
||||
key
|
||||
key,
|
||||
)}adjusted-spent-output-profit-ratio`,
|
||||
title: useGroupName ? name : "asopr",
|
||||
color: useGroupName ? color : undefined,
|
||||
@@ -1590,7 +1611,7 @@ function createPartialOptions(colors) {
|
||||
key: `${fixKey(key)}sell-side-risk-ratio`,
|
||||
name: useGroupName ? name : "Risk",
|
||||
color: color,
|
||||
})
|
||||
}),
|
||||
),
|
||||
},
|
||||
],
|
||||
@@ -1679,7 +1700,7 @@ function createPartialOptions(colors) {
|
||||
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
|
||||
type: "Baseline",
|
||||
key: `${fixKey(
|
||||
key
|
||||
key,
|
||||
)}net-unrealized-profit-and-loss-relative-to-market-cap`,
|
||||
title: useGroupName ? name : "Net",
|
||||
color: useGroupName ? color : undefined,
|
||||
@@ -1857,7 +1878,7 @@ function createPartialOptions(colors) {
|
||||
key: `${key}-sma`,
|
||||
name: key,
|
||||
color,
|
||||
})
|
||||
}),
|
||||
),
|
||||
},
|
||||
...averages.map(({ key, name, color }) =>
|
||||
@@ -1867,7 +1888,7 @@ function createPartialOptions(colors) {
|
||||
title: `${name} Market Price Moving Average`,
|
||||
legend: "average",
|
||||
color,
|
||||
})
|
||||
}),
|
||||
),
|
||||
],
|
||||
},
|
||||
@@ -1904,6 +1925,32 @@ function createPartialOptions(colors) {
|
||||
],
|
||||
})),
|
||||
},
|
||||
{
|
||||
name: "Indicators",
|
||||
tree: [
|
||||
{
|
||||
name: "Mayer's multiple",
|
||||
title: "Mayer's multiple",
|
||||
top: [
|
||||
createBaseSeries({
|
||||
key: `200d-sma`,
|
||||
name: "200d sma",
|
||||
color: colors.yellow,
|
||||
}),
|
||||
createBaseSeries({
|
||||
key: `200d-sma-x2-4`,
|
||||
name: "200d sma x2.4",
|
||||
color: colors.green,
|
||||
}),
|
||||
createBaseSeries({
|
||||
key: `200d-sma-x0-8`,
|
||||
name: "200d sma x0.8",
|
||||
color: colors.red,
|
||||
}),
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -1958,7 +2005,7 @@ function createPartialOptions(colors) {
|
||||
},
|
||||
}),
|
||||
],
|
||||
})
|
||||
}),
|
||||
),
|
||||
.../** @type {const} */ ([
|
||||
{ name: "2 Year", key: "2y" },
|
||||
@@ -2029,7 +2076,7 @@ function createPartialOptions(colors) {
|
||||
},
|
||||
}),
|
||||
],
|
||||
})
|
||||
}),
|
||||
),
|
||||
],
|
||||
},
|
||||
@@ -2045,7 +2092,7 @@ function createPartialOptions(colors) {
|
||||
name: `${year}`,
|
||||
color,
|
||||
defaultActive,
|
||||
})
|
||||
}),
|
||||
),
|
||||
},
|
||||
...dcaClasses.map(
|
||||
@@ -2072,7 +2119,7 @@ function createPartialOptions(colors) {
|
||||
},
|
||||
}),
|
||||
],
|
||||
})
|
||||
}),
|
||||
),
|
||||
],
|
||||
},
|
||||
@@ -2133,10 +2180,10 @@ function createPartialOptions(colors) {
|
||||
bottom: [
|
||||
...createAverageSumCumulativeMinMaxPercentilesSeries("fee"),
|
||||
...createAverageSumCumulativeMinMaxPercentilesSeries(
|
||||
"fee-in-btc"
|
||||
"fee-in-btc",
|
||||
),
|
||||
...createAverageSumCumulativeMinMaxPercentilesSeries(
|
||||
"fee-in-usd"
|
||||
"fee-in-usd",
|
||||
),
|
||||
],
|
||||
},
|
||||
@@ -2892,7 +2939,7 @@ export function initOptions({ colors, signals, env, utils, qrcode }) {
|
||||
const detailsList = [];
|
||||
|
||||
const treeElement = signals.createSignal(
|
||||
/** @type {HTMLDivElement | null} */ (null)
|
||||
/** @type {HTMLDivElement | null} */ (null),
|
||||
);
|
||||
|
||||
/** @type {string[] | undefined} */
|
||||
@@ -3004,7 +3051,7 @@ export function initOptions({ colors, signals, env, utils, qrcode }) {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
null
|
||||
null,
|
||||
);
|
||||
|
||||
partialTree.forEach((anyPartial, partialIndex) => {
|
||||
@@ -3027,7 +3074,7 @@ export function initOptions({ colors, signals, env, utils, qrcode }) {
|
||||
|
||||
if ("tree" in anyPartial) {
|
||||
const folderId = utils.stringToId(
|
||||
`${(path || []).join(" ")} ${anyPartial.name} folder`
|
||||
`${(path || []).join(" ")} ${anyPartial.name} folder`,
|
||||
);
|
||||
|
||||
/** @type {Omit<OptionsGroup, keyof PartialOptionsGroup>} */
|
||||
@@ -3042,13 +3089,13 @@ export function initOptions({ colors, signals, env, utils, qrcode }) {
|
||||
const thisPath = groupAddons.id;
|
||||
|
||||
const passedDetails = signals.createSignal(
|
||||
/** @type {HTMLDivElement | HTMLDetailsElement | null} */ (null)
|
||||
/** @type {HTMLDivElement | HTMLDetailsElement | null} */ (null),
|
||||
);
|
||||
|
||||
const childOptionsCount = recursiveProcessPartialTree(
|
||||
anyPartial.tree,
|
||||
passedDetails,
|
||||
[...(path || []), thisPath]
|
||||
[...(path || []), thisPath],
|
||||
);
|
||||
|
||||
listForSum.push(childOptionsCount);
|
||||
@@ -3180,7 +3227,7 @@ export function initOptions({ colors, signals, env, utils, qrcode }) {
|
||||
});
|
||||
|
||||
return signals.createMemo(() =>
|
||||
listForSum.reduce((acc, s) => acc + s(), 0)
|
||||
listForSum.reduce((acc, s) => acc + s(), 0),
|
||||
);
|
||||
}
|
||||
recursiveProcessPartialTree(partialOptions, treeElement);
|
||||
@@ -3207,7 +3254,7 @@ export function initOptions({ colors, signals, env, utils, qrcode }) {
|
||||
console.log(
|
||||
[...m.entries()]
|
||||
.filter(([_, value]) => value > 1)
|
||||
.map(([key, _]) => key)
|
||||
.map(([key, _]) => key),
|
||||
);
|
||||
|
||||
throw Error("ID duplicate");
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user