You are down on the position and the fill is right there. What does taking it actually do to your average, and what does it cost you to find out?
Opens straight in the browser. No install, no signup, no account.
The number · The next buy · Target average · What it does not do · Under the hood
Three fills, six contracts, one number. Everything to the right of the rule is what the next buy would do to it.
Light and dark, both drawn rather than inverted, following the system by default. |
On a phone the columns stack and the ledger stays whole. Down to 360px. |
Average cost is weighted by contracts:
Σ (price × contracts)
average = ───────────────────────
Σ contracts
One contract at $1.50, then one at $1.00, averages $1.25. That much anyone can do in their head.
Ten at $1.00 and one at $2.00 does not average $1.50. It averages $1.09, because the second fill is one eleventh of the position and gets one eleventh of the vote. That is the arithmetic people actually get wrong, and it gets worse the more uneven the fills are — which, when you are averaging down into a move, is every time.
BASIS takes any number of fills at any size, weights them properly, and states the result in money rather than points: every dollar figure is premium × multiplier, so $0.8933 across six contracts reads as $536 committed, not 5.36 of something.
Under the headline is the composition bar — one segment per fill, width by capital, the dearest fills darkest. A position that looks averaged down but is still three quarters made of the first bad fill says so at a glance.
The right-hand column models a buy without committing it. Price, size, and you get the new average, the drop it buys you, what the position becomes and what it costs. Nothing is written to the ledger until you say so.
4 contracts at $0.55 takes the basis down $0.1373 to $0.756, and puts $220 more at risk.
Underneath it is the curve, which is the part worth internalising.
Averaging down has sharply diminishing returns. The first contract does most of the work. The tenth barely moves the number. The average bends toward the price you are buying at and never arrives — you cannot average your way to a $0.55 basis by buying at $0.55, only get arbitrarily close at arbitrarily large risk.
The curve draws exactly that: average cost against contracts added, your proposed size marked on it, the buy price as the dashed floor it never touches. If your size sits out on the flat part, you are spending a lot of capital for very little basis.
Happy with it? Commit this as a fill drops it into the ledger.
The inverse question, which is usually the real one. I want my average at $0.80 and I can buy at $0.55 — how many?
Solving avg₀·q₀ + p·n = target·(q₀ + n) for n:
q₀ (avg₀ − target)
n = ────────────────────
target − p
You get the whole number of contracts, rounded up so you land at or under the target rather than just short of it, the exact fractional answer beside it, the capital it takes, and how much of the position would then be new.
It also refuses honestly. Ask for an average below the price you are buying at and it tells you why that is impossible, rather than returning a plausible-looking number.
No mark, no live P/L, no greeks, no expiry payoff, no order entry, no broker connection. Four screens of that already exist and your platform has one of them open.
This answers one question — what is my basis, and what does the next buy do to it — and it answers it without asking you for anything it does not need. Price, contracts, done.
The multiplier is the one knob, and it sits in the header rather than in your way. Leave it at 100 for US equity options, set it to 1 and it averages anything else — shares, crypto, a stack of the same thing bought at different prices. The maths does not care what the contract is.
git clone https://github.com/RatterAU/basis.git
cd basis
open index.htmlThat is the whole setup. No build, no dependencies, no package.json. Serve it with python3 -m http.server 8000 if you would rather, or drop index.html on any static host.
Sanity-check the maths anytime: open the console and run basisCheck(). It asserts the worked examples, that weighting is by contracts and not by fill count, that the average always lands between the cheapest and dearest fill, that the solver round-trips exactly against the forward calculation over a few hundred random books, that rounding contracts up never overshoots the target, that adding below the average always lowers it and never past the buy price, and that unreachable targets return nothing instead of nonsense.
| Size | one file, ~40 KB, zero dependencies |
| Storage | localStorage, on your machine. No account, no server, nothing leaves the page |
| Input | price and contracts. Any number of fills, fractional sizes allowed, edited in place |
| Keyboard | Enter adds a fill · ⌫ on an empty row removes it · ↑↓ move between rows |
| Theme | light and dark, system by default, remembered |
| Mobile | responsive to 360px |
| Check | basisCheck() in the console, assertions only |
Little tool I built for myself. It is not financial advice, I am not liable for anything you do with it, and averaging down into something that expires today is a decision with a clock on it — this tells you what it costs, not whether to do it. Check your fills against your broker.
MIT licensed. Take it, fork it, do whatever.

