guest@rootware:~$
HOME

BTC Backtester: badreddot.com

Text with image example

I got interested in ways to visualize BTC strategies that could outperform simply holding the asset without taking on the risk of options or leverage. I pictured a tool that would start by testing a wide range of strategies and parameters, then refine around the best performers. The first prototype worked, but I realized my bigger challenge was coming up with enough initial strategy templates. I needed a broader set of ideas, so I made the code public to elicit help from others with their own approaches. That’s when I pivoted to building a website with a front-end UI.

How it works: the site lets you paste a readable strategy with buy and sell rules. For each strategy, it substitutes values into the rule templates, precomputes only the needed indicators (RET(n), MA(n)), compiles the rules into functions, and runs a lightweight backtest that builds an equity curve from historical BTC prices. It then computes stats like total return, CAGR, max drawdown, and Sharpe, tracks the current best run in a live readout, and plots up to five top equity curves against a HODL baseline.

This was my first time building a lightweight API to submit results to a MySQL database and pull top results for the front end. The client sends a normalized payload to a PHP endpoint, which hashes the generic equation to deduplicate entries and validates key fields.

A few surprises popped up once I moved from a prototype to something people could use. I kept running into data quirks, like CSVs with mixed timestamp formats, short windows that produced empty equity curves, and gaps that turned Sharpe into NaN. Early on I also submitted under-HODL or non-finite results, which MySQL happily stored as zeros because of defaults. A small field name mismatch and a no-op upsert meant some bad rows stayed “stuck” even after I fixed the math. On the strategy side, the real bottleneck was idea generation and avoiding overfitting to one period, so I focused on making the DSL readable and the results transparent.

Text with image example

On the front end, the first version did too much work per tick. I sorted and re-rendered a growing leaderboard, pushed full equity arrays for every run, and did extra network posts. That created UI jank and memory churn. I fixed it by trimming DOM updates to a single live “best run” line, keeping only a few equity curves for the chart, validating stats before any submit, and gating out runs that did not beat HODL. I also normalized the API payload, added basic server-side checks, and reserved chart layout up front so the page stays stable while results stream in.