How to migrate from Pi bridge to Kite Connect
Zerodha Pi was Zerodha’s desktop trading terminal that included a bridge allowing algorithmic strategies written in AFL (AmiBroker Formula Language) or Excel macros to place orders programmatically via a COM/DDE interface. Zerodha discontinued Pi and the Pi bridge, directing users to the Kite Connect API as the supported replacement. This guide walks through every step of migrating a Pi bridge-based strategy to Kite Connect, with direct function-level equivalents and rewritten code examples.
Why Pi was discontinued
Zerodha Pi was a resource-intensive desktop application based on an older trading platform codebase. Maintaining a Windows COM/DDE bridge alongside a modern REST API created duplicate infrastructure and reliability issues. Zerodha shifted its development focus entirely to Kite (the web and mobile platform) and Kite Connect (the API). Pi reached end-of-life and Zerodha stopped issuing new Pi installations and ended technical support for the bridge.
The Kite Connect ecosystem offers everything Pi’s bridge did, plus significantly more: live WebSocket tick streaming, historical data, options chain queries, margin calculators, MF orders, and basket orders. The main difference is that Kite Connect is a paid API (Rs 2,000/month plus GST), whereas Pi was a free desktop application.
Mapping Pi bridge features to Kite Connect
| Pi bridge capability | Kite Connect equivalent |
|---|---|
Place order via AFL PlaceOrder() | kite.place_order(...) |
| Place order via Excel DDE | kite.place_order(...) |
| Get LTP via DDE-linked cell | kite.ltp(["NSE:SYMBOL"]) |
| Get OHLC via DDE | kite.ohlc(["NSE:SYMBOL"]) |
| Real-time tick stream | KiteTicker WebSocket |
| Get positions | kite.positions() |
| Get holdings | kite.holdings() |
| Get margin | kite.margins() |
| Historical data (for AFL) | kite.historical_data(...) |
| Order book | kite.orders() |
| Trade book | kite.trades() |
| Modify order | kite.modify_order(...) |
| Cancel order | kite.cancel_order(...) |
Step-by-step procedure
Audit your Pi bridge code
Before writing a single line of Kite Connect code, catalogue every action your strategy takes through the Pi bridge:
- How many and which instruments does it trade?
- What order types does it use: market, limit, SL, SL-M?
- Does it use intraday (MIS) or delivery (CNC) or overnight derivative (NRML) products?
- How does it read price data: DDE-linked cells, AFL arrays, or a combination?
- Does it use Pi’s bracket-order or cover-order support?
- What does it do when an order is filled, modified, or rejected?
Write this audit down. Each item corresponds to a Kite Connect call.
Subscribe to Kite Connect and obtain credentials
Follow the steps in How to generate a Kite Connect API key to create an app and subscribe. You will receive an api_key and api_secret. Store them as environment variables:
export KITE_API_KEY="your_api_key"
export KITE_API_SECRET="your_api_secret"
Set up the Python environment
mkdir kite-migration && cd kite-migration
python -m venv .venv
source .venv/bin/activate
pip install kiteconnect pyotp python-dotenv requests
For the daily authentication, follow How to authenticate Kite Connect with TOTP automation if you want headless login, or How to generate the request_token and access_token for the standard flow.
Rewrite order placement calls
AFL PlaceOrder() equivalent:
A typical AFL Pi bridge order looked like:
// AFL (AmiBroker Pi bridge)
PlaceOrder("NSE", "RELIANCE", "BUY", 1, "MARKET", 0, 0, "MIS", "");
The Kite Connect Python equivalent:
from kiteconnect import KiteConnect
import os
kite = KiteConnect(api_key=os.environ["KITE_API_KEY"])
kite.set_access_token(os.environ["KITE_ACCESS_TOKEN"])
order_id = kite.place_order(
variety=kite.VARIETY_REGULAR,
exchange=kite.EXCHANGE_NSE,
tradingsymbol="RELIANCE",
transaction_type=kite.TRANSACTION_TYPE_BUY,
quantity=1,
product=kite.PRODUCT_MIS,
order_type=kite.ORDER_TYPE_MARKET,
)
print("Order placed:", order_id)
Limit order equivalent:
order_id = kite.place_order(
variety=kite.VARIETY_REGULAR,
exchange=kite.EXCHANGE_NSE,
tradingsymbol="INFY",
transaction_type=kite.TRANSACTION_TYPE_BUY,
quantity=10,
product=kite.PRODUCT_MIS,
order_type=kite.ORDER_TYPE_LIMIT,
price=1450.00,
)
For full details and all parameters, see How to place an order via the Kite Connect REST API.
Replace DDE price feeds with KiteTicker or REST quotes
DDE-linked LTP in Excel (Pi):
Pi populated an Excel cell with the live LTP of a symbol via a DDE formula such as =Pi|NSE_RELIANCE!LTP. Your macro read this cell value.
Kite Connect REST equivalent (snapshot, not streaming):
quotes = kite.ltp(["NSE:RELIANCE", "NSE:INFY"])
reliance_ltp = quotes["NSE:RELIANCE"]["last_price"]
infy_ltp = quotes["NSE:INFY"]["last_price"]
Streaming equivalent using KiteTicker (closer to DDE):
from kiteconnect import KiteTicker
ticker = KiteTicker(os.environ["KITE_API_KEY"], os.environ["KITE_ACCESS_TOKEN"])
TOKENS = [738561, 341249] # RELIANCE, INFY instrument tokens from instruments CSV
price_cache = {}
def on_ticks(ws, ticks):
for tick in ticks:
price_cache[tick["instrument_token"]] = tick.get("last_price")
def on_connect(ws, response):
ws.subscribe(TOKENS)
ws.set_mode(ws.MODE_LTP, TOKENS)
ticker.on_ticks = on_ticks
ticker.on_connect = on_connect
ticker.connect(threaded=True)
For the full WebSocket guide, see How to stream live ticks via Kite WebSocket.
Migrate AFL historical data to kite.historical_data
AFL strategies that fetch historical OHLC data for indicator calculation (for example, an EMA crossover) used Pi’s built-in data feed. The Kite Connect equivalent:
import datetime
instruments = kite.instruments("NSE")
reliance_token = next(
i["instrument_token"] for i in instruments if i["tradingsymbol"] == "RELIANCE"
)
to_date = datetime.date.today()
from_date = to_date - datetime.timedelta(days=365)
candles = kite.historical_data(
instrument_token=reliance_token,
from_date=from_date,
to_date=to_date,
interval="day",
)
# candles is a list of dicts: [{"date": ..., "open": ..., "high": ..., "low": ..., "close": ..., "volume": ...}, ...]
closes = [c["close"] for c in candles]
Supported intervals: minute, 3minute, 5minute, 10minute, 15minute, 30minute, 60minute, day.
Migrate Pi bracket orders to Kite Connect cover orders
Pi supported bracket orders (BO). Kite Connect supports Cover Orders (CO), which are the two-legged entry-plus-stop-loss orders. There is no direct bracket-order variety in Kite Connect.
# Cover order: entry + stop-loss leg
order_id = kite.place_order(
variety=kite.VARIETY_CO,
exchange=kite.EXCHANGE_NSE,
tradingsymbol="HDFCBANK",
transaction_type=kite.TRANSACTION_TYPE_BUY,
quantity=5,
product=kite.PRODUCT_MIS,
order_type=kite.ORDER_TYPE_MARKET,
trigger_price=1590.00, # stop-loss trigger
)
For target-exit logic (the third leg of a bracket order), implement a limit sell order placed after the entry order is filled, monitoring the order via kite.orders() or postback URL.
Run in parallel and validate
Before switching live trading to the Kite Connect version, run both systems in parallel for at least one week:
- Pi bridge: continues trading normally.
- Kite Connect script: runs with all
kite.place_order()calls commented out. Log every order decision it would have made.
Compare the two logs daily. When the Kite Connect decisions match Pi’s behaviour (accounting for latency differences and any logic you intentionally changed), switch live.
Common migration pitfalls
Instrument tokens vs trading symbols. Pi used human-readable symbols everywhere. Kite Connect’s WebSocket uses numeric instrument tokens. Maintain a symbol-to-token mapping refreshed daily from the instruments CSV.
Pi’s built-in data vendor vs Kite’s historical API. Pi’s historical data was available through AmiBroker’s internal database. Kite Connect provides historical data via kite.historical_data(), but has rate limits. Cache data locally; do not re-fetch the same symbol repeatedly.
Strategy loop timing. Pi’s AFL ran on each bar in AmiBroker’s event loop. In Python, you must implement your own loop using time.sleep() or a scheduler such as APScheduler. A common pattern is a one-minute loop that fetches new data, recalculates indicators, and places orders.
Order tagging. Pi identified orders by their context in the AFL script. Kite Connect returns an order_id that you must store and associate with your strategy context. Maintain a local dictionary mapping strategy signals to order_id values.
Error handling. Pi’s bridge was largely silent on errors; failed orders often required manual inspection. In Python, wrap every kite.place_order() in try/except as shown in How to place an order via the Kite Connect REST API.
What can go wrong
InputException: No such instrumentafter migration. Thetradingsymbolformat differs between Pi and Kite Connect for some instruments (particularly F&O). Download the instruments CSV and verify exact symbols.- Scripts not running at market open. Unlike Pi’s always-on desktop application, Python scripts must be explicitly started. Set up a cron job or systemd service to start your script at 8:45 AM IST on trading days.
- TOTP prompt at automation time. If you have not set up TOTP automation, your script requires manual intervention daily. Implement the approach in How to authenticate Kite Connect with TOTP automation.
- Higher latency than Pi for order placement. Kite Connect REST calls add one HTTP round-trip per order. For high-frequency strategies, the WebSocket connection and local order queue reduce latency.
- Pi AFL indicator libraries have no Python equivalent. Some advanced AFL functions require reimplementation in Python (using
pandas,numpy, orta-lib). Budget time for this if your strategy uses complex indicators.
Related guides
- How to generate a Kite Connect API key
- How to generate the request_token and access_token
- How to authenticate Kite Connect with TOTP automation
- How to place an order via the Kite Connect REST API
- How to stream live ticks via Kite WebSocket
- How to write a basic Python script using kiteconnect
- How to use postback URLs on Kite Connect
- Kite Connect API overview
- Kite Connect ecosystem
- Zerodha overview
- Zerodha Pi discontinuation
- Zerodha tech stack and engineering
References
- Zerodha, Kite Connect developer documentation, kite.trade/docs/connect/, accessed 2024.
- kiteconnect Python SDK, github.com/zerodha/pykiteconnect, accessed 2024.
- Zerodha Z-Connect blog, Pi bridge sunset announcement, zerodha.com/z-connect, accessed 2024.
- Zerodha Support, Migrating from Pi to Kite Connect, support.zerodha.com.
- SEBI, Circular on algorithmic trading by retail investors, SEBI/HO/MRD/2021 series, sebi.gov.in.
- Zerodha, Kite Connect instruments CSV, api.kite.trade/instruments, accessed 2024.