StockSharp/StockSharp · error · ArgumentException

Active order cannot have zero balance.

Error message

Active order cannot have zero balance.

What it means

Thrown by ProcessOrder when an order is in the Active state but its Balance is zero. An active order must still have remaining volume; a fully filled order should be in the Done state, so Active + zero balance is an inconsistent state that the position ledger refuses to process.

Source

Thrown at Algo.Strategies/StrategyPositionManager.cs:303

	/// <param name="order">Order to process.</param>
	/// <returns><see cref="OrderResults"/></returns>
	public OrderResults ProcessOrder(Order order)
	{
		ArgumentNullException.ThrowIfNull(order);

		var txId = order.TransactionId;

		if (txId <= 0)
			throw new ArgumentException(LocalizedStrings.TransactionInvalid, nameof(order));

		if (order.Balance < 0)
			throw new ArgumentException(LocalizedStrings.OrderBalanceNotEnough.Put(order.TransactionId, order.Balance), nameof(order));

		if (order.Volume <= 0)
			throw new ArgumentException(LocalizedStrings.WrongOrderVolume.Put(order.TransactionId), nameof(order));

		if (order.State == OrderStates.Active && order.Balance == 0)
			throw new ArgumentException("Active order cannot have zero balance.", nameof(order));

		if (order.State is OrderStates.None or OrderStates.Pending or OrderStates.Failed)
			return OrderResults.InvalidStatus; // not yet active

		var matchedAbs = order.GetMatchedVolume() ?? 0m; // cumulative executed volume (absolute)
		var signSide = order.Side == Sides.Sell ? -1 : 1;

		Position position;
		bool isNew;

		var commission = order.Commission;

		using (_lock.EnterScope())
		{
			var key = (order.Security.ToSecurityId(), order.Portfolio);
			var posExists = _positions.ContainsKey(key);

			// If there are no executions yet and the order state is not Active and no position exists yet, ignore.

View on GitHub (pinned to 601a191de6)

Solutions

  1. Upstream, ensure fully filled orders are transitioned to Done (and Balance set to 0 only when Done).
  2. Before calling ProcessOrder, reconcile: if Balance == 0 and State == Active, correct the state to Done (or reject the message).
  3. If the source is an adapter, fix its state transitions so Active never coexists with zero balance.

Example fix

// before
_posManager.ProcessOrder(order); // State==Active && Balance==0 -> throws

// after
if (order.State == OrderStates.Active && order.Balance == 0)
    order.State = OrderStates.Done; // reconcile inconsistent snapshot
_posManager.ProcessOrder(order);
Defensive patterns

Strategy: validation

Validate before calling

if (order.State == OrderStates.Active && order.Balance == 0)
    order.State = OrderStates.Done; // reconcile inconsistent snapshot
_posManager.ProcessOrder(order);

Prevention

When it happens

Trigger: Passing an Order whose State is OrderStates.Active while Balance == 0 — e.g. an execution feed that reported full fills but left the order state as Active, or a state-machine transition that forgot to flip to Done.

Common situations: Adapter/connector bugs reporting 100% execution without transitioning to Done; out-of-order messages where the fill arrived before the status update; replayed snapshots with mismatched State and Balance.

Related errors


AI-assisted analysis of StockSharp/StockSharp@601a191de6 (2026-08-13). Data as JSON: /api/errors/7ab78ce87d95c094. Report an issue: GitHub.