Bitcoin ETF calculator
Ten shares bought at 20 and now priced at 25 are worth 250, a gain of 50 and a 25% return. Enter your own lot of IBIT, FBTC or any spot Bitcoin ETF and the current price you see. Free in your browser.
- Free
- Runs in your browser
- No sign-up
- Your data stays on your device
Run — free
Worked example
- Shares
- 10
- Purchase price
- 20
- Current price
- 25
- Value
- 250
- Cost basis
- 200
- Gain
- 50
- Return percent
- 25
Spot Bitcoin exchange-traded funds hold bitcoin in trust and issue shares that trade through ordinary brokerages. Once you have bought a lot, three numbers decide the mark-to-market snapshot: how many shares you own, the price you paid per share, and the current net asset value or last trade. This Bitcoin ETF calculator multiplies shares by the current price to produce current value, subtracts cost basis to produce gain, and divides the price change by the purchase price to produce return percentage. Purchase price must also be positive so the return ratio is defined.
What a Bitcoin ETF lot is and how value, gain, and return are computed
A spot Bitcoin ETF does not give you a private key. It gives you fund shares whose economic exposure tracks the net asset value of bitcoin held by the issuer, minus the fund fee. After the trade settles, the holding is a lot: a share count, a purchase price (your fill, average cost, or stated NAV at buy), and a current price you supply from a quote, a statement, or a NAV publication.
Current value is shares times current price. Cost basis is shares times purchase price. Gain is value minus cost basis, which is also shares times the per-share change.
Return percentage is the per-share change divided by the purchase price, times one hundred; it does not depend on how many shares you bought, so a ten-share lot and a one-hundred-share lot at the same prices report the same percent. That identity is useful when comparing a small paper trade with a later scaled position. When current price is below purchase price the gain is negative and the return is negative; a current price of zero is a total loss of one hundred percent.
Money totals are rounded half-up to two decimal places, matching cents in a dollar-denominated quote; return percentage is rounded half-up to four decimal places so small NAV moves still show. Fractional shares are allowed because many brokerages support them on IBIT, FBTC, ARKB, and similar tickers.
Where a Bitcoin ETF calculator earns its keep
Educators teaching digital-asset wrappers can seed classroom examples that show how a two-percent NAV move scales linearly with share count while the return percent stays the same, without standing up a market-data vendor. Failed validation does not consume balance. Keep share count positive, pin the rounded money fields in tests, and you get reproducible Bitcoin ETF marks for widgets, LMS modules, and edge workers without a quote feed of your own.
The contract is deliberately small: three numbers in, value and return out, so clients can wrap it in their own ticker pickers and statement parsers without fighting hidden state.
What you can do with it
Mark a brokerage Bitcoin ETF lot
Enter shares, the fill price, and today’s NAV or last trade to see current value, dollar gain, and return percent for IBIT, FBTC, ARKB, or any similar fund.
Journal dollar-cost-average buys
Store each purchase as a lot and re-mark it when you update the current price so a DCA log shows both cash gain and percent return without a market-data feed.
Classroom wrapper versus wallet comparison
Show how ETF share counts convert to a mark at a supplied price while the return percent stays independent of lot size, as a deterministic oracle for worksheets.
FAQ
How is Bitcoin ETF value and return calculated?
Current value is shares times current price; gain is value minus cost basis; return percent is (current price minus purchase price) divided by purchase price, times 100.
Does this fetch a live IBIT or GBTC quote?
There is no ticker lookup and no network, so results stay deterministic for tests and offline widgets.
Does the number of shares change my return percentage?
No. The return percent only compares the current price with the price you paid per share, so a ten-share lot and a one-hundred-share lot at the same prices show the same percent. The share count only scales the value and the gain.
What happens if the ETF price is now below what I paid?
The gain and the return come out negative, and the value falls below what the lot cost you. A current price of zero means a total loss of 100%. The percent still depends only on the per-share prices, not on how many shares you hold.
Which purchase price should I enter for my Bitcoin ETF?
Use the price you actually paid per share: your fill price, your average cost if you bought in several steps, or the published net asset value on the day you bought. Fractional shares are fine too.
Related tools
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, by email and from Telegram — and soon from our app too.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/fin/bitcoin-etf \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"shares":10,"purchase_price":20,"current_price":25}'const res = await fetch("https://api.kit.forhosting.com/fin/bitcoin-etf", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"shares": 10,
"purchase_price": 20,
"current_price": 25
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/fin/bitcoin-etf",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"shares": 10,
"purchase_price": 20,
"current_price": 25
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/fin/bitcoin-etf", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"shares":10,"purchase_price":20,"current_price":25}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"shares":10,"purchase_price":20,"current_price":25}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/fin/bitcoin-etf", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"shares": 10,
"purchase_price": 20,
"current_price": 25
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "fin.bitcoin_etf",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |
Technical notes
Share count must be strictly positive; a zero or negative lot is rejected as invalid_input instead of a hollow zero-value success.
What a Bitcoin ETF lot is and how value, gain, and return are computed
Overflow guards cap share count and unit prices so a typo cannot produce a non-finite JSON number.
Input contract, response shape, and error behaviour
If share count is not positive the task fails with a message that share count is not positive — those failures are not billed. Share counts above one trillion or prices above one billion are rejected as overflow guards. Example: ten shares bought at twenty and marked at twenty-five yield cost basis two hundred, current value two hundred fifty, gain fifty, and return twenty-five percent. A loss example is equally first-class: five shares bought at forty and marked at thirty yield cost two hundred, value one hundred fifty, gain negative fifty, and return negative twenty-five percent. POST a JSON body with three required finite numbers: shares (strictly greater than zero; aliases share_count, qty, quantity), purchase_price (strictly greater than zero; aliases buy_price, cost_per_share, cost), and current_price (greater than or equal to zero; aliases price, nav, market_price). Each field may arrive as a JSON number or as a numeric string. Missing fields, empty strings, and non-finite values fail with invalid_input naming the field. If current_price is negative the request fails because a fund NAV or last trade cannot be negative in this model. On success the body echoes the three inputs and returns cost_basis, value, gain, return_percent, and a formula string restating the identities. Pair the snapshot with your own tax-lot engine if you need wash-sale or holding-period lots; this endpoint values one lot from three numbers only and does not emit tax lots, tickers, or charts.
Where a Bitcoin ETF calculator earns its keep
Portfolio dashboards and dollar-cost-average journals can call the same pure module from the browser for free previews and from the API when storing scenarios, so the value a reader saw on a landing page matches the value stored after they save a position. Advisors comparing a spot bitcoin ETF with a self-custodied coin can mark both sides of a worksheet at a supplied price: this calculator handles the share lot; a satoshi converter handles on-chain units.
Technical questions
What if I enter zero or negative shares?
The task fails with invalid_input because share count is not positive. A zero or negative lot is not a holding this calculator can mark, and the request is not billed.
Why must purchase price be greater than zero?
Return percent divides by the purchase price. A zero or negative cost makes that ratio undefined, so the handler rejects it instead of returning Infinity or a fake percent.
What does the Bitcoin ETF calculator cost?
The browser tool is free. API requests use prepaid balance at $0.002 per successful call; invalid input is not billed.