Buy the same size at 2000 and again at 4000 on a coin-margined contract, and your average entry is 2666.67, not 3000. The gap is 12.5%, and nothing on the screen looks off when you use the wrong one. This guide shows where the number comes from, a second case where the textbook shape is wrong in the same way, and how to check both with a few lines of code.
On a linear contract (USDT-margined) the size is a number of coins and the average entry is the usual weighted average of the prices. On an inverse contract (coin-margined, such as Bybit BTCUSD or Deribit BTC-PERPETUAL) the size is a number of dollar contracts. Each fill buys size / price coins, so a fill at a lower price buys more coins for the same size.
linear (USDT-margined): size in coins, PnL in USDTinverse (coin-margined): size in USD contracts PnL in coins a fill on an inverse contractbuys size / price coins coins = sum of size / priceaverage = total size / coins (a harmonic mean) linear: sum of price x size / total sizeYour average entry is the price at which all the dollars you spent would have bought all the coins you ended up with. That is total size divided by total coins, which is a harmonic mean of the prices. Equal sizes weigh the cheaper fill more, because it contributed more coins.
fills: 1000 contracts at 2000 1000 contracts at 4000 coins = 1000/2000 + 1000/4000 = 0.5 + 0.25 = 0.75 average = 2000 / 0.75 = 2666.67 plain average = 3000.00difference = 333.33 = 12.5% of 2666.67Same two fills on a linear contract average to 3000, as you would expect. The table has both results from the engine behind the calculator and the MCP tool, with the default fees of 0.02% to open and 0.05% to close. The breakeven moves with the average, so using the wrong average also puts your breakeven in the wrong place.
| WHAT | LINEAR | INVERSE |
|---|---|---|
| Average entry | 3,000.00 | 2,666.67 |
| Notional | 6M USDT | 0.75 coins |
| Breakeven with fees | 3,002.10 | 2,668.53 |
The same shift of units changes option payoffs. Deribit BTC and ETH options are settled in the coin, so the payoff of a call is (S − K) / S coins, not S − K dollars. The textbook says a long call has unlimited upside, and for a dollar-settled option that holds. Here the fraction can approach 1 but never pass it, so the profit is capped at one coin minus the premium.
long BTC call, strike 90,000premium 0.04 BTC, paid in BTC payoff = (S - K) / S in BTCprofit = payoff - 0.04 S=180,000 payoff 0.50 profit 0.46S=900,000 payoff 0.90 profit 0.86S=9,000,000 payoff 0.99 profit 0.95 as S grows the payoff nears 1max profit = 1 - 0.04 = 0.96 BTC breakeven: (S - K) / S = 0.04 S = 90,000 / 0.96 S = 93,750In dollars the profit still grows as the price rises, because each coin is worth more. The cap is in coin terms: nine million BTC would pay 0.95 coin per contract, not more than 0.96.
A language model is built to continue text, not to run a calculation. Both cases above have the shape of a formula that everyone has seen: a plain average, an unlimited call. When the units change, the familiar shape stays and the result is different, and the wrong answer arrives in the same calm sentence as a right one. There is no error message to notice. This guide makes no claim about how often any particular model gets these two cases wrong, because that depends on the model and the question. The point is about the kind of formula: one where a changed unit turns a familiar result into a wrong one, and nothing signals it.
The remedy is not a better prompt. It is to take the arithmetic away from the model. The model decides what to ask, a program with tested formulas computes the answer, and the result can be checked afterwards. That is how the TradingCalc MCP tools work: the same inputs always return the same numbers, and every response carries a signature you can verify.
Every figure in this guide came from the engine behind the calculators and the MCP tools, and each was reproduced with the snippet below, which needs nothing installed beyond Node.
// each fill is [price, size]const fills = [[2000, 1000], [4000, 1000]];const size = fills.reduce((s, [, n]) => s + n, 0); const linear = fills .reduce((s, [p, n]) => s + p * n, 0) / size;const inverse = size / fills.reduce((s, [p, n]) => s + n / p, 0);console.log(linear, inverse.toFixed(2));// 3000 2666.67 // coin-settled call: payoff (S - K) / Sconst profit = (S, K, premium) => Math.max(S - K, 0) / S - premium;const f = (S) => profit(S, 90000, 0.04).toFixed(2);console.log(f(180000), f(900000), f(9e6));// 0.46 0.86 0.95If you work with an agent, the first case is a call to workflow.run_dca_entry with contractType set to inverse, and the second is workflow.run_options_payoff. The responses are signed, and the daily public record shows how the engine's own tests did that day.