The week I built a feature and then switched it off
Accessible Trade Terminal — week ending 12 August 2026
I shipped a release this week that deliberately does less than the code inside it can do. It took me a couple of days to decide that wasn't a failure, so let me start there.
Quick background
The Accessible Trade Terminal is trading software built for blind and visually impaired traders. Not a normal app with a screen reader bolted on — those exist and they're miserable, because trading interfaces are walls of numbers and a screen reader reading a wall of numbers out loud is worse than nothing.
The idea is that market data becomes a soundscape. Price movement maps to pitch, volatility to texture. You arrow through a chart and you hear its shape, while speech fills in the specifics and a braille display gives you exact characters.
I started it in 2023 in Python, hit a wall on audio latency, and rewrote it in C#. It's been through a couple of UI frameworks since. Three years in, it now runs as a desktop app and as a browser-based version that most people seem to prefer.
One rule matters more than the rest: the terminal ships tools, not opinions. It used to recommend a strategy for each asset. I tore that out, because a highlighted row in your own app reads as an endorsement, and I was endorsing something my own research had already disproved. The app measures and it describes. It doesn't tell you what to think.
Almost everything below follows from that.
Short selling came back, with the part that hurts
I'd pulled short selling from the practice account a while back. It was on the menu and it didn't really work, so I took it off and said so publicly. This week it came back properly.
The interesting bit isn't the shorting, it's the liquidation.
A normal position can only lose you what you put in. A short can lose you more than you have. A practice account that lets you short but never wipes you out isn't teaching you to short — it's teaching you that shorting is free money with no way to blow up, which is the exact opposite of the truth. Honestly, worse than not offering it at all.
So now it liquidates you, and it triggers on the worst price the bar touched rather than where it closed, because a spike that recovered still would have taken you out on a real exchange.
I also made the margin requirements stricter than real exchanges use. A practice account that teaches you thinner margin than reality is setting you up to learn the difference with real money.
Capital letters, and why they nearly cost people funds
I added deposit support — ask the terminal for a deposit address and it gives you one. This was the part of the week where accessibility design and financial safety turned out to be the same problem, which I didn't expect.
Crypto addresses are case-sensitive. "b" and "B" are different addresses. And here's the thing: speech doesn't carry case. Braille does. So the address sits in a field a braille display can walk through character by character, and for anyone without one there's a reading that explicitly says which letters are capitals.
A few other decisions in the same spirit:
The form is ordered by what it costs to get it wrong — asset, then network, then address. The network has no default and the button stays greyed out until you pick one, because choosing a network for someone is choosing which blockchain their money goes down. Get it wrong and it's gone.
A memo gets its own field with its own warning, not a footnote. Leaving one off loses your funds just as completely as a wrong address.
And if copying to the clipboard fails, it tells you. Silent failure there is the worst possible outcome — you'd paste whatever was in the clipboard before and send money to it.
Before you debug your code, check the thing underneath it
I wrote a tool to test all this against a real exchange account, and I made it verify my API key first, before anything else. That turned out to be the whole point.
It came back saying: your key is fine, your signing is fine, your permissions are fine — and the exchange has no funding method set up for this account.
Without that check running first, I'd have read the error as "my code is broken" and spent an hour debugging code that worked perfectly. It was an identity-verification step on the exchange's end. Two different problems with two different owners.
I've made a rule of it now.
The best security feature I've ever shipped is a restriction
Then I built withdrawals — the only thing in this app that moves money off an exchange.
The design decision I'm proudest of: the terminal cannot accept a raw address. It can only withdraw to addresses you've already saved and approved on the exchange's own website, behind the exchange's own two-factor.
Which means — and I want to say this plainly — even if this software were completely compromised, it could not send your money anywhere you hadn't personally pre-approved.
Withdrawals also require a totally separate API key from the one used for trading, with no fallback. If you haven't set one up, the answer is just "not configured." It will never quietly reach for your trading key.
And then I switched it off
So: the release has two new exchanges, a wallet, a balances screen that finally tells you what your account is worth instead of how many units you hold, and short selling back with teeth.
The withdrawal feature is in there too, finished and tested.
It ships switched off.
Everything else unverified in this release costs you, worst case, a wasted click. Withdrawals move real money off an exchange, and nobody — including me — has ever run a real one through it. Finding out something's wrong while your funds are in flight is the wrong way to find out.
So there's a single switch, currently off. The button doesn't appear, and the service itself refuses before anything leaves your computer. There's even a test that fails the day someone turns it on, with a message explaining what has to happen first.
That's the entire next release: do one real withdrawal, then flip the switch.
Reasoning about something isn't the same as checking
My plan was to add Bybit next. Big exchange, good documentation, free test environment. I checked whether I could actually reach their API before writing any code — and it's blocked from the US entirely. Not the website, which loads fine. The API. Not a single call works from where I sit.
That's the second exchange in two weeks to evaporate on me; another one quietly shut down their practice environment in July and I only found out when the signup page redirected to a marketing page.
So I built Gemini instead, and then did the thing that actually matters: made an account, generated a real key, and used it.
The first two calls each found a bug that no amount of testing on my own machine would ever have caught. One of them was a timestamp in the wrong units, which the exchange was reading as roughly the year 58,000.
I keep relearning this and it keeps being worth relearning. Reading the documentation carefully is not the same as making the call.
A result I'm proud of and refuse to ship
I spent a chunk of the week testing the four-year Bitcoin cycle theory properly, because people keep asking me to build it into the app.
Measured the usual way, it doesn't hold up — the impressive numbers require deciding after the fact which lows "count," which is circular.
But measured from the halving — a date fixed years in advance, no judgement involved — it's startlingly consistent. I ran 400 randomised simulations and not one of them clustered as tightly as the real thing.
That's the strongest result this project has ever produced. I'm not shipping it.
Three data points isn't a sample. Nothing except Bitcoin even has a halving, so it can never be checked anywhere else. And halvings land on US election years every single time, so I genuinely can't tell you which one is doing the work.
Passing your own test isn't the same as being useful. Put it on a chart and it borrows the app's authority, and the evidence doesn't earn that. Tools, not opinions.
While I was in there I also killed a seasonality claim and picked up a habit I'll keep: always write the plain base rate next to the impressive-sounding one. "Midterm years bring a 10–20% correction" sounds like a pattern until you notice 11 of the last 19 years had one anyway. Without that, a coin flip reads as a cycle.
Two things I got wrong
The release process builds native Windows and Mac apps, and those builds had never actually run — they'd been sitting in the pipeline for several releases untested. So I did a dry run first, and it failed immediately on a real bug that would have broken the release. One of my variable names collided with a reserved word, and it only showed up on the Mac build because it uses a stricter compiler version than everything else.
Which taught me the second thing: "our automated builds compile it" is not the same as "it compiles." Mine was building on a version that tolerated the bug.
I also claimed in my own release notes that everything compiled without warnings. It didn't. I'd run the check in a way that skipped recompiling anything, so it reported zero because nothing had actually been checked. Turns out the previous release's identical claim was wrong too.
Neither is dramatic. Both are the small kind of false confidence that eventually costs somebody something.
Next up
Finish verifying deposits, put a short position through to liquidation by hand — my track record says the practice engine gives up its bugs to a human using it, never to the test suite — and do one real withdrawal so I can turn that switch on.
Where to find it
Everything above is in version 2.3.0, which is out now at accessibletrader.com. There's a live demo that runs in your browser with nothing to install, a free paper-trading account if you want the full charting workspace, and desktop builds for Windows, macOS and Linux on the download page. It's free and open source, and it always will be.
People ask whether I use AI on this. Heavily, and it's made a real difference to how much ground one person can cover. What it hasn't changed is the part that decides whether the software is any good: going and checking against reality. Every genuine bug this week was found by a real API key, a real account, or a build that had never been run. Not one of them was found by thinking harder about it.
Comments (0)
No comments yet.