Reconciling local state vs broker order book

Your bot almost certainly keeps some local record of "what I think my positions/orders are" (for speed, for strategy logic, for tagging attribution). The broker's order book and positions API are the only ground truth. These two views will drift apart eventually — from crashes, manual intervention, partial fills your code didn't handle, or bugs. Reconciliation is the discipline of catching and correcting that drift before it causes a bad decision.

When to reconcile

  • On every startup — never trust local state to reflect reality after any restart, planned or crash-induced.
  • Periodically during the day — e.g. every few minutes, or after every order event, depending on strategy frequency.
  • Before every new order placement — a lightweight check that your local "current position" for this instrument matches what the broker reports.
def reconcile_positions(kite, local_positions: dict[str, int]) -> dict[str, dict]:
    """local_positions: tradingsymbol -> quantity your bot believes it holds.
    Returns a diff report of mismatches."""
    broker_positions = {p["tradingsymbol"]: p["quantity"] for p in kite.positions()["net"] if p["quantity"] != 0}

    all_symbols = set(local_positions) | set(broker_positions)
    diffs = {}
    for sym in all_symbols:
        local_qty = local_positions.get(sym, 0)
        broker_qty = broker_positions.get(sym, 0)
        if local_qty != broker_qty:
            diffs[sym] = {"local": local_qty, "broker": broker_qty}
    return diffs

The broker's state always wins

def resync_local_state(local_positions: dict, kite) -> dict:
    broker_positions = {p["tradingsymbol"]: p["quantity"] for p in kite.positions()["net"] if p["quantity"] != 0}
    diffs = reconcile_positions(kite, local_positions)
    if diffs:
        logging.warning(f"Position drift detected, resyncing to broker truth: {diffs}")
        send_alert(f"Position mismatch corrected: {diffs}")
    return broker_positions   # always trust this over local state

A mismatch is not something to silently "fix and continue" — it's a signal something in your bot's own bookkeeping is wrong, and it should be logged and alerted on (chapter 91), not just quietly patched over every time. Repeated mismatches indicate a real bug worth finding.

Same discipline applies to orders

def reconcile_open_orders(kite, local_order_ids: set[str]) -> set[str]:
    broker_open = {o["order_id"] for o in kite.orders() if o["status"] in ("OPEN", "TRIGGER PENDING")}
    return local_order_ids ^ broker_open   # symmetric difference = discrepancies

Next: 067 — Building an Order Manager abstraction