Options Basics
Chapter: 5.2 Options Basics Difficulty: Level 5 — Mastery (cross-domain: quantitative finance + mathematics + coding + proof) Time Limit: 90 minutes Total Marks: 60
Instructions: Answer all three questions. Show full derivations. For coding parts, write clean pseudocode or Python. All prices in ₹ (INR). Assume no transaction costs unless stated.
Question 1 — Payoff Algebra, Breakeven & Put–Call Parity (22 marks)
A Nifty-style underlying trades at spot . Consider European options with strike , expiry . The call premium is , the put premium is .
(a) Write the expiry payoff functions and as piecewise functions including premium paid. Hence derive the breakeven points for the long call and long put. (6)
(b) A trader constructs a long straddle (buy the call + buy the put, same ). Derive the total-profit function , state both breakeven points, and prove that the position's profit is a convex function of . (6)
(c) Using continuous compounding at risk-free rate , state and prove the put–call parity relation using a no-arbitrage replication argument. Then, given the observed prices above with p.a. and years, compute the theoretical implied by parity and determine whether an arbitrage exists. If so, state the exact riskless-profit trade. (10)
Question 2 — Intrinsic/Time Value, Moneyness & Option-Chain Coding (20 marks)
You are given a fragment of an option chain for expiry with spot :
| Strike | Call LTP | Call OI | Put LTP | Put OI |
|---|---|---|---|---|
| 19900 | 320 | 45,000 | 95 | 60,000 |
| 20000 | 250 | 80,000 | 180 | 120,000 |
| 20100 | 190 | 110,000 | 260 | 70,000 |
(a) For each strike, classify the call and the put as ITM / ATM / OTM, and compute the intrinsic value and time value of each call and each put. Present as a table. (8)
(b) The Put–Call Ratio (PCR) by open interest is . Compute it for this fragment and interpret its sentiment meaning. (4)
(c) Write a function analyze_chain(spot, rows) (Python) that, given the spot and a list of rows (strike, call_ltp, call_oi, put_ltp, put_oi), returns for each strike a dict containing call/put moneyness, intrinsic and time values, and finally returns the overall PCR. Your code must handle negative time-value inputs by flagging an arbitrage-warning. (8)
Question 3 — American vs European, Assignment & Early-Exercise Proof (18 marks)
(a) Precisely distinguish European and American style exercise, and explain the mechanics of exercise (buyer's action) versus assignment (seller's obligation). (4)
(b) Prove the classic result: For a non-dividend-paying underlying, it is never optimal to exercise an American call early. Use the lower bound and compare the payoff of exercising now versus selling the option. (8)
(c) Give a concrete numerical counterexample showing that early exercise of an American put CAN be optimal (deep ITM put), and explain the intuition in one line why puts differ from calls here. (6)
Answer keyMark scheme & solutions
Question 1
(a) Payoffs & breakevens (6)
Call buyer profit (premium ): (1) payoff form, (1) premium subtracted.
Put buyer profit (premium ): (1).
Breakevens (set profit in the ITM region):
- Call: . (1)
- Put: . (2)
(b) Long straddle (6)
Total cost . (1) (2) Breakevens: (upper) and (lower). (2)
Convexity proof: . The absolute-value function is convex (composition of affine argument into ; for any , by triangle inequality). Subtracting a constant preserves convexity. Hence is convex. (1)
(c) Put–call parity — statement, proof, arbitrage check (10)
Statement: For European options same : . (1)
Proof (replication / no-arbitrage): Form two portfolios:
- A: long 1 call + cash (invested at ).
- B: long 1 put + 1 unit of underlying.
At expiry :
- A value .
- B value .
Both give identical terminal payoff in every state. (3) By the law of one price / no-arbitrage, their values today must be equal: (2)
Numerical check: , , , . . Parity RHS . (2)
Observed . Since , an arbitrage exists (call is cheap / put+stock rich relative to parity). (1)
Arbitrage trade: Since market fair , buy the cheap side (the call side, portfolio A) and sell the rich side (portfolio B):
- Buy call, invest at ; short the underlying, and write (sell) the put.
- Net cash flow today received, with zero terminal net payoff (both legs cancel). Locked riskless profit . (1)
Question 2
(a) Moneyness, intrinsic, time value (8)
Spot . Call intrinsic ; Put intrinsic ; Time value LTP intrinsic.
| Strike | Call class | Call IV | Call TV | Put class | Put IV | Put TV |
|---|---|---|---|---|---|---|
| 19900 | ITM () | 150 | 320−150=170 | OTM | 0 | 95 |
| 20000 | ITM | 50 | 250−50=200 | OTM | 0 | 180 |
| 20100 | OTM | 0 | 190 | ITM () | 50 | 260−50=210 |
Nearest-to-spot strike (20000, and 20100) are effectively near-ATM; strictly ATM = strike closest to spot (20000/20100). (0.5 per correct cell region — 8 total)
(b) PCR (4)
Put OI . (1) Call OI . (1) (1) Interpretation: PCR (more put OI than call OI) — often read as bearish positioning / put-heavy hedging, or contrarian bullish at extremes. Here mildly put-skewed, near-neutral. (1)
(c) Code (8)
def analyze_chain(spot, rows):
total_put_oi = 0
total_call_oi = 0
result = {}
for strike, c_ltp, c_oi, p_ltp, p_oi in rows:
c_iv = max(spot - strike, 0.0)
p_iv = max(strike - spot, 0.0)
c_tv = c_ltp - c_iv
p_tv = p_ltp - p_iv
def moneyness(intrinsic, at_spot):
if abs(strike - spot) < 1e-9: # exact ATM
return "ATM"
return "ITM" if intrinsic > 0 else "OTM"
entry = {
"call": {
"moneyness": moneyness(c_iv, spot),
"intrinsic": c_iv, "time_value": c_tv,
"arb_warning": c_tv < 0,
},
"put": {
"moneyness": moneyness(p_iv, spot),
"intrinsic": p_iv, "time_value": p_tv,
"arb_warning": p_tv < 0,
},
}
result[strike] = entry
total_call_oi += c_oi
total_put_oi += p_oi
pcr = total_put_oi / total_call_oi if total_call_oi else float('inf')
return {"per_strike": result, "PCR": round(pcr, 4)}Marks: intrinsic logic (2), time value (1), moneyness classification (2), negative-TV arbitrage flag (2), PCR return (1).
Question 3
(a) European vs American; exercise vs assignment (4)
- European: exercisable only at expiry . American: exercisable any time up to and including expiry. (2)
- Exercise is the buyer's right/action: the long holder chooses to convert the option into the underlying position (call → buy at ; put → sell at ). Assignment is the seller's (writer's) obligation: when a buyer exercises, the clearinghouse assigns a short-position holder to fulfil the contract (deliver/receive underlying or cash-settle). (2)
(b) No early exercise of American call (non-dividend) (8)
Lower bound (no-arbitrage): . (2) Payoff from exercising the call now . (1) Since and , , hence (3) Because an American call is worth at least its European counterpart, and the European value already exceeds the exercise value, the holder does strictly better by selling the option (capturing ) than exercising (getting ). Also exercising forfeits remaining time value and pays early (losing interest). Therefore early exercise is never optimal. (2)
(c) American put early-exercise counterexample (6)
Take , spot (deep ITM put), , .
- Exercise now: receive immediately, which can be invested to earn interest. (2)
- Max value from waiting is bounded by but the discounted strike caps European put value near . (2) So holding is worth less than the ₹95 obtainable now → early exercise optimal.
- Intuition: For a put, exercising brings in cash early (earning interest), so time value of money favours early exercise deep ITM; for a call you would pay out , so delaying is better. Puts and calls differ by the sign of the strike cash flow. (2)
[
{"claim":"Long call breakeven = 20250", "code":"K=20000; C=250; result = (K + C == 20250)"},
{"claim":"Straddle upper/lower breakevens 20430 and 19570", "code":"K=20000; cost=430; result = (K+cost==20430) and (K-cost==19570)"},
{"claim":"Put-call parity fair C-P = 297.76 with r=6%,T=0.25", "code":"import sympy as sp; val=20000-20000*sp.exp(sp.Rational(-6,100)*sp.Rational(1,4)); result = abs(float(val)-297.76) < 0.5"},
{"claim":"Arbitrage exists: observed C-P=70 differs from fair 297.76", "code":"import sympy as sp; fair=20000-20000*sp.exp(sp.Rational(-6,100)*sp.Rational(1,4)); obs=250-180; result = abs(float(fair)-obs) > 1"},
{"claim":"PCR = 1.0638", "code":"put=60000+120000+70000; call=45000+80000+110000; result = round(put/call,4)==1.0638"},
{"claim":"American put early exercise optimal: 95 > European bound 85.48", "code":"import sympy as sp; euro_bound=100*sp.exp(sp.Rational(-1,10))-5; result = 95 > float(euro_bound)"}
]