Option Payoff & Breakeven Calculator¶

Open In Colab

Multi-leg payoff curves, breakevens, and max profit/loss at expiry.

Part 07 of 20 in the ServLoci algo/options trading notebook series — full index in notebooks/README.md.

Setup¶

# Get your dedicated static IPv6 + SOCKS5 credentials free:
#   https://comm.servloci.in/register        (or /auth/google?free=1 for an instant trial)
# Your api_key / api_secret pair shows up in the portal after signup:
#   https://comm.servloci.in/user
!pip install -q "requests[socks]"
!curl -sL https://comm.servloci.in/sdk/servloci.py -o servloci.py

import os
from servloci import ServLoci

SERVLOCI_API_KEY = os.environ.get("SERVLOCI_API_KEY", "dhan:1000000001")   # broker:client_id
SERVLOCI_API_SECRET = os.environ.get("SERVLOCI_API_SECRET", "")            # from the portal — leave blank to run this notebook in demo mode

sl = None
if SERVLOCI_API_SECRET:
    sl = ServLoci(api_key=SERVLOCI_API_KEY, api_secret=SERVLOCI_API_SECRET)
    print("ServLoci configured:", sl.host, sl.port)
else:
    print("SERVLOCI_API_SECRET not set — running in demo mode (no live proxy calls).")

Python port of shared/lib/strategyMath.js — payoff is computed at expiry (intrinsic value only), same as the payoff chart on /tools/strategy-builder.

def leg_payoff_at_expiry(leg, underlying_price):
    iv = max(underlying_price - leg["strike"], 0) if leg["type"] == "CE" else max(leg["strike"] - underlying_price, 0)
    sign = 1 if leg["side"] == "buy" else -1
    return sign * (iv - leg["premium"]) * leg["qty"]

def strategy_payoff_at_expiry(legs, underlying_price):
    return sum(leg_payoff_at_expiry(leg, underlying_price) for leg in legs)

def net_premium(legs):
    return sum((-1 if leg["side"] == "buy" else 1) * leg["premium"] * leg["qty"] for leg in legs)

def payoff_curve(legs, spot, rng=0.15, steps=120):
    lo, hi = spot * (1 - rng), spot * (1 + rng)
    pts = []
    for i in range(steps + 1):
        p = lo + (hi - lo) * i / steps
        pts.append({"price": p, "pnl": strategy_payoff_at_expiry(legs, p)})
    return pts

def breakevens(points):
    crossings = []
    for a, b in zip(points, points[1:]):
        if (a["pnl"] < 0 <= b["pnl"]) or (a["pnl"] > 0 >= b["pnl"]):
            t = 0 if a["pnl"] == b["pnl"] else -a["pnl"] / (b["pnl"] - a["pnl"])
            crossings.append(a["price"] + t * (b["price"] - a["price"]))
    return crossings

def max_profit_loss(points):
    pnls = [p["pnl"] for p in points]
    return {"maxProfit": max(pnls), "maxLoss": min(pnls)}

legs = [
    {"side": "buy", "type": "CE", "strike": 24000, "premium": 180, "qty": 75},
    {"side": "sell", "type": "CE", "strike": 24200, "premium": 90, "qty": 75},
]
points = payoff_curve(legs, spot=24000)
print("Net premium:", net_premium(legs))
print("Breakevens:", breakevens(points))
print("Max P/L:", max_profit_loss(points))
import matplotlib.pyplot as plt

def plot_payoff(points, title):
    xs = [p["price"] for p in points]
    ys = [p["pnl"] for p in points]
    plt.axhline(0, color="grey", linewidth=0.8)
    plt.plot(xs, ys)
    plt.title(title)
    plt.xlabel("Underlying spot")
    plt.ylabel("P&L (INR)")
    plt.show()

plot_payoff(points, "Bull call spread payoff at expiry")

« Previous: Black-Scholes Pricing & Greeks
Next: Strategy: Straddle & Strangle »

Try the concepts above interactively: Options Strategy Builder · Docs · Get your static IP