How to Handle Partial Fills in Automated Crypto Orders

Partial fills happen when only part of your order executes. Here is how to handle partial fills in automated crypto orders so your bot stays in sync with your real position.

How to Handle Partial Fills in Automated Crypto Orders

You send an order to buy one Bitcoin, and the exchange fills 0.4 of it. The rest sits open, or gets cancelled, or fills seconds later at a worse price. If your automation assumed the whole order executed, it is now tracking a position that does not match reality. Learning to handle partial fills in automated crypto orders is one of the least glamorous and most important parts of building reliable execution. A signal is easy to generate. Getting the exchange to do exactly what you intended, and knowing precisely what happened afterward, is the hard part.

This guide explains what a partial fill is, why partial fills are common in crypto, how they break naive automation, and the steps you can take so your bot always knows its true position.

What Is a Partial Fill?

A partial fill is when an exchange executes only some of your order quantity and leaves the remainder resting on the book or cancelled. If you submit a limit order for 5 ETH and only 2 ETH trade at your price, you have a partial fill: 2 ETH filled, 3 ETH outstanding.

Every fill an exchange sends you carries a filled quantity and an average price. The important number is not whether the order was accepted, but how much of it actually executed. An order can be accepted, acknowledged, and still only partially filled. Treating acceptance as completion is the most common mistake in automated execution.

Why Partial Fills Happen in Crypto Markets

Partial fills are a normal feature of how order books work, not an error. There are several ordinary reasons your order does not fill at once.

The first is thin liquidity. If you want more size than is available at your price level, the exchange fills what it can and stops. On smaller pairs or during quiet hours, the book simply does not hold enough resting orders to complete a large request. Understanding how crypto exchange order books work makes this behavior far more predictable.

The second is a fast-moving market. Price can move away from your limit before the whole order executes, leaving the rest unfilled. The third is order type and time-in-force rules. An immediate-or-cancel order fills what it can right now and cancels the rest by design. Even market orders can walk the book and fill at several price levels, which is closely related to slippage in automated trading.

Hidden liquidity, exchange rate limits, and per-order size caps can all contribute as well. The point is that partial fills are expected, so your automation has to treat them as a normal outcome rather than a rare edge case.

Why Partial Fills Break Naive Automation

Most first attempts at a trading bot assume a binary result: the order either worked or it did not. That assumption fails the moment a fill comes back partial.

Imagine your logic wants to be long 1 BTC, sends a market buy, and immediately records the position as 1 BTC. If only 0.6 BTC actually filled, your internal state now overstates your real holding by 0.4 BTC. The next stop or take-profit will be sized against a position you do not fully have, and a later attempt to close 1 BTC may itself be rejected. Errors compound quietly.

The same problem appears with scaled exits and any strategy that flips direction. If you do not measure filled quantity precisely, every downstream decision inherits the error. This is closely tied to handling failed and rejected orders in a trading bot: both are cases where the exchange did something other than what your naive model assumed.

How to Handle Partial Fills in Automated Crypto Orders

The fix is to make filled quantity, not order acceptance, the source of truth. A few concrete steps get you there.

Start by reading the fill, not the acknowledgment. When you submit an order, capture the returned filled quantity and average fill price. Do not assume the requested size executed. Persist the order by its client order ID so you can look it up again.

Next, poll or subscribe until the order reaches a terminal state. An order is only done when its status is filled, cancelled, expired, or rejected. Until then, keep checking the remaining quantity. Many exchanges push fill updates over a websocket stream, which is faster than polling; a REST fallback keeps you correct if the stream drops.

Then update your position from actual fills. Increase or decrease your tracked position by the exact filled quantity each time a fill event arrives, and recompute your average entry price from real executions. Your internal state should always be a running total of confirmed fills, never a copy of what you requested.

Finally, decide what to do with the unfilled remainder. You generally have three choices: leave the remainder resting, cancel it, or re-submit it at a new price. Which you pick depends on your strategy, but the decision must be explicit in code, because doing nothing is itself a choice that leaves an order working on the exchange.

Order Types and Time-in-Force Choices That Reduce Partial Fills

You cannot eliminate partial fills, but you can shape how often they happen and how they behave. Your order type is the main lever.

Market orders prioritize completion over price. They usually fill fully, but by walking multiple price levels they trade certainty of size for uncertainty of price. Limit orders do the opposite: they protect your price but accept the risk that only part of the order trades. Choosing between them deliberately is the core of market versus limit orders in automated trading.

Time-in-force settings change the remainder behavior directly. Fill-or-kill requires the entire quantity to execute at once or nothing does, removing partial fills at the cost of more rejected orders. Immediate-or-cancel fills what it can immediately and cancels the rest, so a partial fill is expected and the leftover never lingers. Good-till-cancelled leaves the remainder working until it fills or you cancel it. Picking the right one is easier once you understand time-in-force options like GTC, IOC, and FOK.

Reconciling Position State After a Partial Fill

Even with careful handling, your bot's view of a position can drift from the exchange's. Reconciliation is the process of periodically comparing the two and trusting the exchange.

On a regular interval, and always before acting on a new signal, fetch your actual position and open orders from the exchange and compare them to your internal state. If they disagree, the exchange is correct, so overwrite your local numbers. This single habit catches partial fills you missed, fills that arrived after a disconnect, and manual trades.

Reduce-only orders are a useful safety net here. When you close or trim a position, marking the order reduce-only ensures it can never accidentally flip you the other way if your size estimate was off. If that concept is new, see what a reduce-only order is.

Best Practices for Handling Partial Fills

A short checklist keeps partial-fill handling reliable as your automation grows:

  • Treat filled quantity, not order acceptance, as the source of truth for every order.
  • Wait for a terminal order status before recording a trade as complete.
  • Update your tracked position and average price incrementally from real fill events.
  • Decide explicitly whether to rest, cancel, or re-price any unfilled remainder.
  • Prefer websocket fill streams with a REST fallback so a dropped connection never loses a fill.
  • Reconcile against the exchange on a schedule and before every new order.
  • Use reduce-only orders when closing so a size mismatch cannot open a new position.
  • Log every fill event with its quantity, price, and client order ID for later auditing.

Frequently Asked Questions

Is a partial fill a problem or normal?

Partial fills are completely normal. They are a routine result of how order books and time-in-force rules work. They only become a problem when your automation ignores them and tracks a position that does not match what actually executed.

How do I stop partial fills entirely?

You cannot stop them entirely, but a fill-or-kill order comes closest, because it either fills the whole quantity at once or cancels. The trade-off is more rejected orders. Market orders also usually fill fully, at the cost of less price control.

How should my bot track a partially filled position?

Update your tracked position by the exact filled quantity from each fill event and recompute your average entry price from real executions. Never set the position to the size you requested. Reconcile against the exchange regularly to catch anything you missed.

Can I handle partial fills from a TradingView webhook?

Your TradingView alert only sends the intent to trade. Partial-fill handling happens on the execution side, after the order reaches the exchange. A relay layer that reads real fills and reconciles position state is what turns that alert into a correctly tracked order.

Start Automating Your Signals

Partial fills are a reminder that execution is harder than firing a signal: the order you send and the fill you get are not always the same size. SignalToExchange is a non-custodial webhook relay that handles that gap for you. It receives your signal from TradingView or an automation platform and submits the order to your exchange using trade-only API keys, so your funds never leave the exchange and no one, including us, can withdraw them. You keep control of the strategy; the relay focuses on reliable, low-latency order submission. If that is the piece you want off your plate, request access or start your free trial with SignalToExchange.

Automated trading involves risk. SignalToExchange is execution infrastructure and does not provide financial advice, trading signals, or guarantees of any kind.

Secure Signal Routing Infrastructure

Non-custodial execution. Trade-only API keys. Independent infrastructure built for reliability.

Request Early Access

Trade-only API key enforcement. No withdrawal permissions. No custody.