Back
Learning Hub/ Python for Algo Trading/ Lesson 8 Phase 1 of 6
Python for Algo Trading · Phase 1

Error Handling — Try / Except

A trading bot that crashes silently can place wrong orders, hold open positions, or miss exits. Learn to catch errors gracefully, log them, and keep your system running safely — even when the API is down or data is missing.

Lesson 8 of 9 ~40 min Intermediate–Advanced Production-grade resilience
Lesson 8 of 9 — Error Handling89% complete
LESSON 08 · SECTION 1
Why Error Handling Matters
advanced

In production algo trading, errors are inevitable: API timeouts, missing price data, division by zero in P&L calculations, network drops. Without proper error handling, your bot crashes at the worst possible moment — during market hours with open positions.

🛡️
try / except
Wrap risky code in try. If an error occurs, the except block runs instead of crashing.
🧹
finally
Runs whether or not an error occurred — used for cleanup like closing connections.
🚨
raise
Throw your own errors intentionally — e.g., raise an error if lot size is invalid.
🔖
Custom Exceptions
Create trading-specific error classes: KillSwitchError, InvalidOrderError.

Section 2
Basic try / except
Without error handling — CRASH
data = {}
ltp = data["ltp"]   # KeyError: 'ltp'
# Program crashes — open positions unmanaged!
try_except.pypython
# With error handling — safe
def get_ltp(data):
    try:
        ltp = data["ltp"]
        if ltp <= 0:
            raise ValueError(f"Invalid LTP: {ltp}")
        return ltp
    except KeyError:
        print("⚠️ LTP key missing in market data")
        return None
    except ValueError as e:
        print(f"⚠️ Data error: {e}")
        return None
    except Exception as e:
        print(f"❌ Unexpected error: {e}")
        return None

print(get_ltp({"ltp": 22450}))   # 22450
print(get_ltp({}))                  # KeyError caught
print(get_ltp({"ltp": -5}))        # ValueError caught
Output
22450
⚠️ LTP key missing in market data
None
⚠️ Data error: Invalid LTP: -5
None

Section 3
Common Trading Exceptions
ExceptionWhen it occurs in tradingHow to handle
KeyErrorAPI response missing a field (e.g., no "ltp")Use .get() or catch KeyError
ZeroDivisionErrorDividing by zero lot size or zero priceCheck denominator before division
ValueErrorInvalid order type string or negative priceValidate inputs before use
TypeErrorAdding int + None (missing data)Type-check or use try
ConnectionErrorBroker API / WebSocket disconnectedRetry with backoff, alert user
TimeoutErrorAPI call took too long — order not confirmedCancel and re-query order status

Section 4
finally & Custom Exceptions
custom_exceptions.pypython
# Custom trading exceptions
class KillSwitchError(Exception):
    """Raised when daily loss limit is breached."""
    pass

class InvalidOrderError(Exception):
    """Raised when an order has invalid parameters."""
    pass

def place_order(symbol, side, lots, daily_pnl, loss_limit=-10000):
    try:
        # Validate inputs
        if lots <= 0:
            raise InvalidOrderError(f"Lots must be > 0, got {lots}")
        if side not in ("BUY", "SELL"):
            raise InvalidOrderError(f"Invalid side: {side}")
        if daily_pnl <= loss_limit:
            raise KillSwitchError(f"Daily P&L {daily_pnl} ≤ limit {loss_limit}")
        print(f"✅ Order placed: {side} {lots} lot(s) of {symbol}")
    except KillSwitchError as e:
        print(f"🚨 KILL SWITCH: {e}")
    except InvalidOrderError as e:
        print(f"❌ INVALID ORDER: {e}")
    finally:
        print(f"   [Order attempt logged for audit]")

place_order("NIFTY", "BUY", 2, daily_pnl=5000)
place_order("NIFTY", "BUY", 2, daily_pnl=-12000)
place_order("NIFTY", "LONG", 2, daily_pnl=500)
Output
✅ Order placed: BUY 2 lot(s) of NIFTY
   [Order attempt logged for audit]
🚨 KILL SWITCH: Daily P&L -12000 ≤ limit -10000
   [Order attempt logged for audit]
❌ INVALID ORDER: Invalid side: LONG
   [Order attempt logged for audit]
💡 PRO TIP
The finally block is perfect for audit logging — it always runs, success or failure. SEBI's algo trading guidelines require every order attempt to be logged regardless of outcome.

Section 5
Quick Quiz
QUESTION 1 OF 3
What does the finally block guarantee?
AIt runs only when no error occurs
BIt runs only when an error occurs
CIt always runs regardless of error or success
DIt suppresses all errors silently
QUESTION 2 OF 3
When should you catch Exception (the base exception class)?
AAlways — it catches everything cleanly
BAs a last resort — catch specific exceptions first, then Exception for unexpected errors
CNever — use specific exceptions only
DOnly in class methods
QUESTION 3 OF 3
Why create a custom KillSwitchError instead of using a plain ValueError?
ACustom exceptions run faster
BLets you catch it specifically — other code won't accidentally catch a KillSwitch as a general ValueError
CPython requires custom exceptions for trading apps
DCustom exceptions have better error messages by default

Section 6
Practice Exercises
EXERCISE 1 · EASY
Safe Division
Write a function safe_rr(sl_pts, tgt_pts) that returns the risk:reward ratio. Handle ZeroDivisionError if SL points is 0. Return 0 on error.
Hint: wrap the division in try/except ZeroDivisionError.
EXERCISE 2 · MEDIUM
Safe API Response Parser
Write parse_tick(data) that extracts ltp, volume, and symbol from a broker API dict. Handle KeyError (missing field), TypeError (wrong type), and log which field failed.
Hint: use multiple except clauses with different exception types.
EXERCISE 3 · CHALLENGE
Robust Order Manager
Create InvalidOrderError and KillSwitchError custom exceptions. Write an order_manager(orders, daily_pnl) function that processes a list of order dicts, validates each (lots > 0, valid side), checks kill switch, and logs every attempt in a audit_log list using finally.
Hint: build the audit_log list outside the function and append to it inside finally.
🚀 ALMOST DONE — LESSON 9 NEXT
Your strategy now runs, makes decisions, handles errors. But where does the data live between sessions? Lesson 9: File I/O & JSON Logs — save trade journals, read config files, and build a persistent audit trail. The final piece of Phase 1!
Prev