Skip to main content

theta decay tracking - why i obsess over time

3am on a monday and i’m watching theta tick down across my options book.

most people don’t realize how much money they’re leaving on the table by not tracking theta properly.

the time decay advantage
#

options are decaying assets.

every day that passes, extrinsic value evaporates.

if you’re selling premium, theta is your friend.

if you’re buying premium, theta is quietly robbing you.

my algo tracks theta decay across every position in real time.

the decay curve
#

not all theta is created equal.

Theta Decay Curve

theta decay accelerates as expiration approaches. green zone (21-35 DTE) is the sweet spot for premium selling. red zone (under 7 DTE) is where gamma risk explodes.

key insight:

theta decay isn’t linear. it’s exponential near expiration.

the math:

  • 30 DTE: losing ~0.8 bps/day
  • 14 DTE: losing ~1.4 bps/day
  • 7 DTE: losing ~2.1 bps/day
  • 3 DTE: losing ~3.5 bps/day

this is why i close most positions at 21 DTE.

the last 3 weeks of theta aren’t worth the gamma risk.

my theta vs gamma framework
#

every options position is a theta/gamma tradeoff.

high theta = high gamma risk.

low gamma = slow theta.

pick your poison.

Portfolio Greeks

current portfolio positions plotted by theta vs gamma exposure. premium selling positions (blue) cluster in the high-theta/negative-gamma quadrant. vol plays (orange) are the opposite.

my current breakdown:

  • premium selling: 60% of options book
  • directional: 25% of options book
  • vol plays: 15% of options book

the premium selling positions generate most of my theta.

vol plays are hedge positions that bleed theta but protect against gap moves.

the tracking system
#

from dataclasses import dataclass
from typing import List, Dict
import numpy as np
from datetime import datetime, timedelta

@dataclass
class OptionsPosition:
    symbol: str
    strike: float
    expiry: datetime
    position_type: str  # 'call' or 'put'
    quantity: int
    entry_price: float
    current_price: float
    delta: float
    gamma: float
    theta: float
    vega: float

class ThetaTracker:
    def __init__(self):
        self.positions: List[OptionsPosition] = []
        self.theta_history: List[Dict] = []

    def add_position(self, pos: OptionsPosition):
        self.positions.append(pos)

    def calculate_portfolio_theta(self) -> float:
        """Total daily theta across all positions"""
        return sum(p.theta * p.quantity * 100 for p in self.positions)

    def calculate_portfolio_gamma(self) -> float:
        """Total gamma exposure"""
        return sum(p.gamma * p.quantity * 100 for p in self.positions)

    def get_dte_breakdown(self) -> Dict[str, float]:
        """Theta by DTE bucket"""
        buckets = {'0-7': 0, '8-14': 0, '15-21': 0, '22-35': 0, '35+': 0}
        today = datetime.now()

        for p in self.positions:
            dte = (p.expiry - today).days
            theta_contrib = p.theta * p.quantity * 100

            if dte <= 7:
                buckets['0-7'] += theta_contrib
            elif dte <= 14:
                buckets['8-14'] += theta_contrib
            elif dte <= 21:
                buckets['15-21'] += theta_contrib
            elif dte <= 35:
                buckets['22-35'] += theta_contrib
            else:
                buckets['35+'] += theta_contrib

        return buckets

    def get_theta_weighted_dte(self) -> float:
        """Theta-weighted average DTE"""
        today = datetime.now()
        total_theta = 0
        weighted_dte = 0

        for p in self.positions:
            theta = abs(p.theta * p.quantity * 100)
            dte = (p.expiry - today).days
            total_theta += theta
            weighted_dte += theta * dte

        return weighted_dte / total_theta if total_theta > 0 else 0

    def identify_risk_positions(self) -> List[OptionsPosition]:
        """Flag positions with high gamma/theta ratio"""
        risky = []
        today = datetime.now()

        for p in self.positions:
            dte = (p.expiry - today).days

            # flag if under 7 DTE with significant gamma
            if dte <= 7 and abs(p.gamma) > 0.05:
                risky.append(p)

            # flag if gamma/theta ratio is extreme
            if abs(p.theta) > 0.001:
                ratio = abs(p.gamma / p.theta)
                if ratio > 50:  # high gamma relative to theta
                    risky.append(p)

        return list(set(risky))

    def daily_snapshot(self) -> Dict:
        """Record daily portfolio state"""
        snapshot = {
            'timestamp': datetime.now().isoformat(),
            'total_theta': self.calculate_portfolio_theta(),
            'total_gamma': self.calculate_portfolio_gamma(),
            'theta_weighted_dte': self.get_theta_weighted_dte(),
            'dte_breakdown': self.get_dte_breakdown(),
            'risk_positions': len(self.identify_risk_positions()),
            'position_count': len(self.positions)
        }
        self.theta_history.append(snapshot)
        return snapshot

nothing fancy.

tracks theta across all positions.

flags risky positions when gamma/theta ratio gets extreme.

records daily snapshots for analysis.

what the data tells me
#

ran this for all of 2025.

findings:

  • avg portfolio theta: +$47/day (selling premium)
  • best month theta capture: 84% (may)
  • worst month theta capture: 61% (august vol spike)
  • positions closed at 21 DTE avg return: +18%
  • positions held to 7 DTE avg return: +22% but 3x the drawdown

the extra 4% return from holding to 7 DTE isn’t worth the ulcers.

current state
#

as of today (jan 20):

  • total portfolio theta: +$52/day
  • theta-weighted avg DTE: 26 days
  • positions at risk (under 7 DTE): 0
  • gamma exposure: slightly negative (want to be short gamma in low vol)

sitting in a good spot.

VIX around 17 means premium selling is working.

if vol spikes, i’ll close some positions and let gamma flatten out.

been trading through different vol regimes on NexusFi with other options traders - the consensus is that tracking theta is table stakes. if you’re not doing it, you’re guessing.

the edge
#

most retail options traders think about individual trades.

pros think about portfolio theta.

your daily theta target should be a function of:

  1. account size (mine is roughly 0.01% daily = $50 on $500k options allocation)
  2. vol environment (reduce theta targets when VIX > 20)
  3. upcoming events (close positions before binary events)

hit your theta target. manage your gamma. don’t hold through expiration.

that’s the game.


2am monday. tracking theta across my options book. +$52/day in time decay. closing positions at 21 DTE to avoid gamma risk. the extra return from holding to expiration isn’t worth the variance. theta-weighted avg DTE is 26 days. sitting in the sweet spot.

-AK

Related

saturday slippage deep dive - where your edge goes to die
woke up at 2am couldn’t sleep. decided to run a full slippage analysis on last quarter’s trades. what i found is annoying but fixable. the invisible tax # every algo trader knows slippage exists.
volatility regime detection - when to switch strategies
the market doesn’t care what strategy you’re running. it runs whatever regime it wants. your job is to detect the regime and adapt. why regime matters # every strategy has conditions where it crushes and conditions where it bleeds.
first week 2026 - january momentum algo kicking off
new year. new momentum. first real trading week of 2026 in the books. january effect algo activated. the january effect # some people think it’s BS.
year-end portfolio rebalancing algo - detecting institutional flows
december means institutional rebalancing. pension funds, endowments, mutual funds all adjusting. built an algo to detect and trade the flows. the concept # year-end rebalancing patterns:
vix term structure algo - contango/backwardation trading
been researching VIX term structure trades. contango vs backwardation. predictable patterns. finally got an algo working. the concept # contango: front month VIX < back month VIX
sector rotation algo - implementation with relative strength scoring
been working on a sector rotation algo. concept: own the strongest sectors, short the weakest. simple in theory. complex in implementation. the core idea # sectors rotate in predictable cycles.