park-btc.web.val.run
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
/** @jsxImportSource https://esm.sh/react */
import { useEffect, useState } from "https://esm.sh/react";
import { renderToString } from "npm:react-dom/server";
const CONFIG = {
COIN_GECKO_CURRENCY: "usd",
COIN_GECKO_DAYS: 200,
SMA_PERIODS: [5, 10, 20, 50, 100, 120, 150, 180, 200],
};
async function getBitcoinData() {
try {
const [priceResponse, historyResponse] = await Promise.all([
fetch(`https://api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_currencies=${CONFIG.COIN_GECKO_CURRENCY}`),
fetch(
`https://api.coingecko.com/api/v3/coins/bitcoin/market_chart?vs_currency=${CONFIG.COIN_GECKO_CURRENCY}&days=${CONFIG.COIN_GECKO_DAYS}&interval=daily`,
),
]);
if (!priceResponse.ok || !historyResponse.ok) throw new Error("API request failed");
const priceData = await priceResponse.json();
const historyData = await historyResponse.json();
return {
currentPrice: priceData.bitcoin[CONFIG.COIN_GECKO_CURRENCY],
prices: historyData.prices.map(e => e[1]),
times: historyData.prices.map(e => e[0]),
};
} catch (error) {
console.error("An error occurred:", error.message);
return null;
}
}
function getChange(prices, times, daysAgo) {
const now = new Date().getTime();
const targetTime = now - daysAgo * 24 * 60 * 60 * 1000;
const closestTimeIndex = times.findIndex(time => time >= targetTime);
if (closestTimeIndex === -1) return null;
const targetPrice = prices[closestTimeIndex];
const currentPrice = prices[prices.length - 1];
return ((currentPrice - targetPrice) / targetPrice * 100).toFixed(2);
}
function calculateSMA(prices, period) {
return prices.slice(-period).reduce((sum, price) => sum + price, 0) / period;
}
function formatPrice(price) {
return Math.round(price).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
function daysBetween(date1, date2) {
const oneDay = 24 * 60 * 60 * 1000;
return Math.abs((date1 - date2) / oneDay);
}
function calculatePowerLawSupport(daysSinceGenesis) {
const logPrice = -17.35 + 5.836 * Math.log10(daysSinceGenesis);
return Math.pow(10, logPrice);
}
function generateSupportPrices(currentPrice) {
const genesisDate = new Date(2009, 0, 3);
const today = new Date();
const supportPrices = [];
for (let year = 10; year >= 0; year--) {
for (let month = 9; month >= 0; month -= 3) {
const futureDate = new Date(today);
futureDate.setFullYear(futureDate.getFullYear() + year);
futureDate.setMonth(futureDate.getMonth() + month);
const futureDays = daysBetween(futureDate, genesisDate);
const price = calculatePowerLawSupport(futureDays);
supportPrices.push({ year, month, price });
}
}
return supportPrices;
}
function BitcoinData({ data }) {
if (!data) return <p>Failed to fetch Bitcoin data.</p>;
const supportPrices = generateSupportPrices(data.currentPrice);
const currentPrice = data.currentPrice;
// Find the range where the current price fits
let lowerIndex = supportPrices.findIndex(sp => sp.price < currentPrice);
if (lowerIndex === -1) lowerIndex = supportPrices.length - 1;
if (lowerIndex === 0) lowerIndex = 1;
const upperIndex = lowerIndex - 1;
// Determine the range to display (2 years above and below)
const endYear = Math.max(5, supportPrices[upperIndex].year + 2);
const startYear = Math.min(0, supportPrices[lowerIndex].year - 2);
const displayPrices = supportPrices.filter(sp => sp.year <= endYear && sp.year >= startYear);
Val Town is a social website to write and deploy JavaScript.
Build APIs and schedule functions from your browser.
Comments
Nobody has commented on this val yet: be the first!
July 17, 2024