Oracle3
Open-source trading engine and MCP server for prediction markets. Fee-aware no-arbitrage trading across related contracts, live on Kalshi, Polymarket and Solana or on paper.
Free Bitcoin dollar-cost-averaging calculator. Pick a start date, interval and amount to see what that plan would be worth today, using real daily closes.
FinanceHTML · JavaScriptGitHub @00xJSOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
Dollar Cost Averaging Analysis for Bitcoin Investing
Translation pending
Taken from the repository README
Loading the full README. The saved excerpt is shown below.
Dollar Cost Averaging (DCA) is an investment strategy where an investor divides up the total amount to be invested across periodic purchases of a target asset, to reduce the impact of volatility on the overall purchase. This project replays that strategy against real historical Bitcoin prices, so you can see what a fixed schedule of purchases would actually have produced in a highly volatile asset.Read the full README ↗Dollar Cost Averaging (DCA) is an investment strategy where an investor divides up the total amount to be invested across periodic purchases of a target asset, to reduce the impact of volatility on the overall purchase. This project replays that strategy against real historical Bitcoin prices, so you can see what a fixed schedule of purchases would actually have produced in a highly volatile asset.
₿itcoin DCA Calculator — a browser-based simulator. Set a start date, contribution frequency and dollar amount, and your total return, portfolio growth chart, and full purchase history update live as you go.
The S&P 500 / 401(k) calculator is a separate project: https://project401k.netlify.app/
The calculator is driven by pre-baked static JSON committed to this repo.
| Bitcoin | |
|---|---|
| Source | Kaggle mczielinski — minute-level Bitstamp, aggregated to daily closes |
| Coverage | 2012-01-01 → today (5,300+ closes) |
| Schedule | Daily, 08:00 UTC |
| Credentials | Requires KAGGLE_USERNAME + KAGGLE_KEY |
| Script | scripts/fetch_btc_prices.py |
| Output | data/btc-prices.json |
Kaggle downloads require authentication, so add KAGGLE_USERNAME and KAGGLE_KEY under Settings → Secrets and variables → Actions. Generate them from your Kaggle account under Settings → API → Create New Token. Expired Kaggle credentials are the most likely cause of stale data — the job fails, commits nothing, and the site keeps serving the last good file.
The scheduled Action writes the JSON, commits it, and Netlify auto-deploys. This means:
├── index.html # the calculator (single-page app)
├── netlify.toml # publish root + no-cache header for the data file
├── data/
│ └── btc-prices.json # auto-generated, daily
├── scripts/
│ └── fetch_btc_prices.py # Kaggle download → daily closes
├── tests/
│ ├── engine.test.mjs # simulate(), xirr(), the formatters
│ ├── timezone.test.mjs # same plan, three timezones
│ ├── harness.mjs # pulls the inline <script> into a vm
│ └── fixtures/
│ └── prices.json # committed synthetic price series
└── .github/
└── workflows/
├── update-btc-data.yml # daily cron
└── test.yml # node --test on push and PR
netlify.toml is load-bearing twice: publish = "." is what makes the page's
absolute /data/btc-prices.json request resolve, and the must-revalidate header
on that path is what stops the CDN serving yesterday's prices.
The page fetches /data/btc-prices.json by absolute path, and browsers block
fetch() on file:// outright — so opening index.html by double-clicking it
will always fail with the "no price data" error. Serve the directory instead:
python3 -m http.server 8000
Then open http://localhost:8000. Any static server works; it just has to serve
the repo root so /data/… resolves. No build step, no dependencies, no API keys
— the price file is committed, so the calculator works offline once served.
Rebuilding price data is only needed for fresher numbers than the committed file, and that part does need Kaggle credentials:
pip install kaggle && KAGGLE_USERNAME=you KAGGLE_KEY=xxxx python3 scripts/fetch_btc_prices.py
data/btc-prices.json is a standalone, reusable artifact (~175 KB):
{
"generated": "2026-08-01T09:54:16Z", // UTC build time
"source": "Kaggle/mczielinski — minute-level Bitstamp data aggregated to daily closes",
"count": 5327,
"prices": [ { "ts": 1325376000, "price": 5.0 } ] // ts = UNIX SECONDS (UTC), ascending
}
No dependencies and no install step — the engine is exercised straight out of
index.html:
node --test tests/*.test.mjs
tests/harness.mjs extracts the inline <script>, evaluates it in a node:vm
context against a minimal DOM stub, and hands back the pure functions. The boot
code at the end of the script is cut off, so nothing fetches or renders.
engine.test.mjs — golden results for several plans (purchase counts,
totals, units, final value, ROI, average cost and the last history row), XIRR
against closed-form cases including one it cannot solve, the averaging effect
invariant that average cost never exceeds the mean price paid, the guard that a
purchase never fills at a close later than its own date, the start-date rules,
and the formatters.heatmap.test.mjs — the start-date heatmap's grid builder: that a cell is
simulate()'s own annual for the same plan (and reports the same "no rate
solves" where simulate() does), that a cell is unchanged by the contribution
amount, the row and column geometry (a holding period the data cannot fill is
dropped whole; no cell's window runs past the last close), and the per-row
worst / median / best / share-positive figures against hand-worked values.timezone.test.mjs — runs the same plans in child processes under TZ=UTC,
TZ=America/New_York and TZ=Australia/Sydney and requires byte-identical
output. The schedule steps with setUTCDate(); stepping in local time would
drift by an hour across a daylight-saving change and can roll a purchase back
onto the previous UTC day, filling it at the previous close.Every expectation runs against tests/fixtures/prices.json — a small, committed,
deterministic series in the same schema as the real file — and against an end date
passed into simulate(). Nothing depends on data/btc-prices.json or on today's
date, so the daily data job can never turn the suite red.
The calculator supports:
?start=2020-01-01&freq=7&amt=100), and Copy link puts it on the clipboardFor each purchase date, the simulator binary-searches for the most recent daily close at or before that date — never a later one, so the model can't look ahead — and calculates:
Results update live — there is no Run button. The page leads with the portfolio value and a plain-English summary of the plan, then six KPI tiles, a chart of portfolio value against total invested (linear or log scale, gain/loss shading between the lines, and a readout of value, invested and ROI at whatever date the pointer is on), an averaging effect card, a collapsible start-date heatmap, and a collapsible purchase history with sortable columns and CSV export.
Did your start date matter? — a collapsed panel under the averaging card, answering the question the rest of the tool keeps implying: how much of an outcome is the month you happened to begin, and how much of that fades as the holding period grows.
Rows are holding periods of 1, 2, 3, 5 and 10 years; a period the price history cannot
fill even once is dropped rather than shown empty. Columns are every calendar month
from the 2013 floor up to the last month whose window still finishes on or before the
newest close — so the grid's right edge is ragged, and the longer the hold, the sooner
it stops. Each cell is a whole plan of its own, run through the same simulate() the
headline figures use, and coloured by its money-weighted annualised return on a
diverging scale clamped symmetrically at ±100%/yr. Your own start month is outlined in
the accent colour.
A cell does not depend on the amount you buy. Scaling every contribution scales the cash flows by the same factor and leaves the rate that discounts them to zero exactly where it was, so the grid is a function of the price history and the frequency alone. Changing the amount or the start date repaints it (to move the marker) but never recomputes it; changing the frequency does recompute, and abandons any pass still in flight. Each frequency's finished grid is cached, so going back to one is instant.
Building it is around 560 simulations on the Bitcoin series (and one more column every
month), so it runs in frame-sized chunks
rather than one blocking pass, seeding each XIRR solve with the previous cell's answer
to cut Newton's iterations by about a quarter. Nothing is computed until the panel is
first opened. Below the canvas, each row's worst, median and best outcome and the share
of start months that ended positive are written out as text — the canvas itself is a
labelled role="img" that takes focus, so the arrow keys walk it cell by cell and the
colour key is aria-hidden — no figure is ever reachable by hover alone.
These are stated on the page too, under How this works, but they matter to anyone reading the numbers:
(value / invested)^(1/years) shortcut credits every dollar with the full elapsed period and materially understates a contribution stream — on a weekly run from 2013 it reports roughly 39%/yr against a true 59%/yr.This project illustrates how Dollar Cost Averaging can be applied to Bitcoin investments over any time horizon, by replaying purchases at regular intervals against real historical prices.
The clearest thing it demonstrates is the mechanic DCA is named for: because a fixed dollar amount buys more BTC when the price is low, average cost per BTC lands below the average of the prices actually paid. Run weekly buys from 2013 and the average cost comes out near $970 against a mean paid price above $26,000 — the two numbers sit side by side in the page's averaging effect card.
What it does not show is whether DCA beats the alternatives. There is no lump-sum or buy-the-dip baseline to compare against, the sample is one asset over one stretch of history, and fees are excluded. Treat the output as "here is what this schedule would have produced," not as evidence that this schedule is best.
The approach adapts to different amounts, frequencies, or other assets — it is a worked example for anyone wanting to understand or implement a DCA strategy, not a recommendation to adopt one.
Disclaimer: This tool is for educational and informational purposes only. Past performance does not guarantee future results. Bitcoin is a highly volatile asset — always conduct your own research before making any investment decisions.