Python Environment Setup

Build a robust FastAPI or Flask application to receive webhooks and route orders to Zerodha KiteConnect.

Dependencies

Create a `requirements.txt` file:

# requirements.txt
kiteconnect==4.2.0
fastapi==0.115.0
uvicorn==0.30.0
python-dotenv==1.0.1
requests==2.31.0

Install with: `pip install -r requirements.txt`

Environment Config

Create a `.env` file to store secrets securely. Never commit this file to Git.

# .env
KITE_API_KEY=your_api_key
KITE_API_SECRET=your_api_secret
KITE_REQUEST_TOKEN=your_daily_request_token
KITE_ACCESS_TOKEN=your_daily_access_token
WEBHOOK_SECRET=your_hmac_secret_for_validation

Verified Webhook Handler

This example shows how to verify the TradingView signature and place an order.

import hmac, hashlib, json, os
from fastapi import FastAPI, HTTPException, Request
from kiteconnect import KiteConnect
from dotenv import load_dotenv

load_dotenv()

app = FastAPI()
kite = KiteConnect(api_key=os.getenv("KITE_API_KEY"))
# In production, you'd load the access token from a persistent store
kite.set_access_token(os.getenv("KITE_ACCESS_TOKEN"))

async def verify_signature(request: Request, payload: dict):
    secret = os.getenv("WEBHOOK_SECRET", "")
    # Reconstruct the body for HMAC check (careful with ordering/whitespace)
    # TradingView sends plain text body; simpler to verify raw body if possible.
    # Ideally, send the signature in a header `X-TradingView-Signature` if you can, 
    # but since TV alerts are payload-based, we check the field.
    
    expected_sig = payload.get("signature")
    if not expected_sig:
       # If you didn't set up signatures, skip or fail.
       return 

    # Simplified check (implementation depends on how you generate sig in Pine)
    if expected_sig != "expected_secret_token":
         raise HTTPException(status_code=401, detail="Invalid signature")

@app.post("/webhook/tradingview")
async def receive_webhook(request: Request):
    payload = await request.json()
    await verify_signature(request, payload)

    try:
        order_id = kite.place_order(
            variety=kite.VARIETY_REGULAR,
            exchange=kite.EXCHANGE_NFO,
            tradingsymbol=payload["symbol"],  # e.g., "NIFTY24FEBFUT"
            transaction_type=payload["side"].upper(),
            quantity=int(payload["qty"]),
            product=kite.PRODUCT_MIS,
            order_type=kite.ORDER_TYPE_MARKET,
            tag="tv_autotrade"
        )
        return {"status": "success", "order_id": order_id}
    except Exception as e:
        print(f"Order failed: {e}")
        raise HTTPException(status_code=500, detail=str(e))

Deployment & Production Readiness

Running on your local laptop is fine for testing, but for live markets, you need a stable environment. Here is a production checklist.

1. Process Management

Use a process manager like Supervisor or Systemd on Linux, or Docker. If your script crashes, these tools will auto-restart it.

# Simple Dockerfile example
FROM python:3.9-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "80"]
                

2. HTTPS / SSL

TradingView requires your webhook URL to be publicly accessible. You have two main options:

  • Cloud Hosting (Recommended): Deploy to Heroku, Render, or AWS Lambda. These provide HTTPS URLs automatically (e.g., https://my-app.herokuapp.com).
  • Tunneling (Dev only): Use tools like NGrok (ngrok http 8000) to get a temporary public URL for testing. Do not use this for live trading as the URL changes every restart.

Troubleshooting KiteConnect

TokenException

Usually means your access_token has expired. Tokens are valid for only one day (until approx 7:30 AM next day). You must re-login every morning.

NetworkException

Connection to Kite timed out. Implementing a retry logic with exponential backoff is crucial for handling temporary API blips.