found the bug that cost me $5k in april. took 6 hours but finally fucking fixed it.
the problem #
selling options spreads. sometimes short leg gets assigned early (ITM before expiration).
my code didn’t handle this. kept treating it like an open position. meanwhile i’m holding naked long option with no hedge.
happened twice in april:
- first time: lost $2,800 before i noticed
- second time: lost $2,100
total damage: $4,900
what i should’ve coded #
def check_assignments(self):
"""Check for early assignments on short options"""
for position in self.open_positions:
if position.is_short and position.option_type in ['call', 'put']:
# Query broker API for assignment
assigned = self.broker.check_assignment(position.symbol)
if assigned:
self.handle_assignment(position)
logger.warning(f"Assignment detected: {position.symbol}")
what i actually coded #
nothing. literally no assignment detection at all.
just assumed spreads would stay spreads until expiration or i closed them. dumb AF.
the fix #
added assignment checking to my position monitor. runs every 15 minutes during market hours.
if short leg assigned:
- immediately close long leg
- log the assignment
- update position database
- recalculate risk exposure
- alert me via pushover notification
also added backtest logic to simulate early assignments (using ITM probability distribution). now my backtests account for this.
testing the fix #
can’t fully test without getting assigned (which is random). but paper trading should catch obvious issues.
added unit tests that mock assignment scenarios:
- ITM assignment with profit
- ITM assignment with loss
- assignment near expiration
- assignment far from expiration
all tests pass. code handles assignments correctly now.
the real cost #
$4,900 in actual losses, but also:
- probably another $2k in missed opportunities (was scared to trade while bug existed)
- week of stress wondering if i’d get assigned again
- lost confidence in my code
lesson #
when selling options you MUST handle:
- early assignment risk
- dividend risk (for stock options)
- pin risk (at expiration)
- corporate actions
i had none of this. just assumed happy path where spreads closed normally.
options trading is hard enough without your code actively fucking you.
code changes #
class PositionMonitor:
def __init__(self, broker):
self.broker = broker
self.check_interval = 900 # 15 minutes
def monitor_loop(self):
while market_open():
self.check_assignments()
self.check_risk_limits()
self.check_stop_losses()
time.sleep(self.check_interval)
def check_assignments(self):
positions = self.broker.get_positions()
for pos in positions:
if pos.is_short_option:
if self.broker.was_assigned(pos.symbol):
self.handle_assignment(pos)
def handle_assignment(self, position):
# Close corresponding long leg immediately
long_leg = self.find_long_leg(position)
if long_leg:
self.broker.close_position(long_leg, 'ASSIGNMENT')
# Update internal state
self.positions.remove(position)
self.log_assignment(position)
# Alert
self.send_alert(f"Assignment: {position.symbol}")
not perfect but way better than before.
may so far #
3 days in, +$340 total. no assignments yet (knock on wood).
smaller position sizes helping. less stress. can actually focus on coding instead of panic-managing positions.
if this month goes well, might finally feel like i know what i’m doing.
3:47am. finally fixed this shit. gonna sleep better knowing assignments won’t fuck me anymore.
-AK