PremiumGuardHQ
Methodology v2026.07
Methodology

How the math gets to your screen.

This is the PremiumGuardHQ calculation reference. Every formula the platform runs on your broker data is documented here, with the source-of-truth in production code. No black box, no proprietary fudge factors. If a number is on your dashboard, it came from one of these formulas.

Last updated 2026-07 8 sections decimal.js precision
The Three Numbers

Premium P/L. Equity P/L. Net P/L.

These are the only three numbers a wheel trader needs to trust. Every cycle PremiumGuard detects produces exactly these three values, computed from your raw trade data.

01

Premium P/L

Formula totalPremiumReceived − totalPremiumCosts

Sum of credits from sold options, minus debits from bought options. Includes both opening and closing legs.

Why it matters The unearned-income meter. Tells you what the market paid you to take risk, before any assignment math.

cycle-detector.ts
02

Equity P/L

Formula equityProceeds − equityCost

Sale proceeds of shares sold minus the cost basis of shares acquired (via buy, put assignment, or call exercise).

Why it matters What the underlying did to your book. Captures whether assignments hurt you or whether shares appreciated through the cycle.

cycle-detector.ts
03

Net P/L

Formula premiumPl + equityPl

The cycle’s real outcome. Combines what you earned from options with what the underlying cost or gave you.

Why it matters The single number a wheel trader can trust. Brokers obscure this by adjusting cost basis for premiums received and wash sales. PremiumGuard never does.

cycle-detector.ts:44

Each value is computed in decimal.js arbitrary-precision arithmetic. No floating-point drift, no rounding errors at scale.

The cycle

The cycle is the unit of measurement.

PremiumGuard doesn’t track individual trades. It tracks cycles: every option sale, every assignment, every closing leg gets stitched into the wheel or standalone position it belongs to. P/L lives on the cycle, never on the trade.

Primary case wheel

Wheel

A multi-leg cycle that holds shares plus the option activity tied to them. Created when a put is assigned or shares are bought into an open option position. Closes when shares fall below 100 (the call-writing floor).

Common zero_duration

Zero-duration

A cycle that opens and closes without shares ever changing hands. The classic case: sell a put, it expires worthless, premium booked. No equity leg, no assignment.

Edge case standalone

Standalone

A bought-option position not tied to an existing wheel. Long calls and long puts held outright. Tracked separately so hedges and speculation never pollute wheel P/L. A standalone stays open until every contract is closed, expired, or exercised. Scaling out across multiple orders keeps all fills in one cycle.

Trade classification

14 trade events. Every broker row classified into one.

Each row from your broker feed is mapped to exactly one of these events before the cycle engine processes it. Everything else (transfers, fees, dividends, splits) is filtered out as non-trading account activity.

Equity
  • equity_buy
  • equity_sell
Sell to open
  • sell_call_to_open
  • sell_put_to_open
Buy to open
  • buy_call_to_open
  • buy_put_to_open
Closing
  • buy_to_close
  • sell_to_close
Settlement
  • call_assigned
  • put_assigned
  • call_expired
  • put_expired
  • call_exercised
  • put_exercised
Action priority

Same-day trades, ordered before processing.

When multiple trades share a date (the assignment-then-sell scenario, the expire-then-resell roll), priority decides which the engine sees first. Assignments always process before sells so the wheel knows about the new shares before they’re traded, and an expiring contract settles before any new sale that day, so a covered call that expires and is rewritten the same session reads in the right order. Before this ordering runs, a single equity order that the broker filled in pieces (same symbol, same day, same side) is aggregated into one logical trade, so a position is attributed in full before it can cross the 100-share floor.

  1. assignment First — new shares must register before sells
  2. exercise Option exercised into shares
  3. buy Equity purchase
  4. buy_to_open New long option position
  5. expiration Old contract settles before any new sale that day
  6. sell_to_open New short option position
  7. sell Equity sale
  8. buy_to_close Close a short option
  9. sell_to_close Close a long option
Capital at Risk

The most you could lose at any point in the cycle.

Not your current exposure. Not your average exposure. The peak dollar amount the platform observed at any moment between the cycle’s open and close. PremiumGuard walks each cycle’s trades chronologically and tracks the running notional, recording the maximum.

Algorithm

For each trade in the cycle, ordered by date + action priority, apply the delta. Track the running total. Clamp at zero (CAR is never negative). Record the peak.

Event Delta Note
sell_put_to_open + strike × qty × 100 Full notional obligation to buy if assigned.
sell_call_to_open + strike × uncovered × 100 Covered contracts add nothing. Only naked / uncovered exposure counts.
put_assigned − strike × qty × 100 Obligation fulfilled; shares received.
call_assigned − strike × qty × 100 Shares called away.
buy + total cash deployed Equity bought outright.
sell − proceeds Equity sold; clamps at zero, never negative.
Worked example

AAPL wheel · May 2026

Sell a $180 put. Get assigned. Cover with a $185 call. Get called away. The peak observed exposure becomes the cycle’s maxCapitalAtRisk.

  1. Day 1 2026-05-01
    sell_put_to_open 1× AAPL put, strike $180
    Δ + 180 × 1 × 100 = +$18,000
    Running CAR $18,000 Peak
  2. Day 14 2026-05-15
    put_assigned Put exercised, 100 shares received
    Δ − 180 × 1 × 100 = −$18,000
    Running CAR $0
  3. Day 14 2026-05-15
    sell_call_to_open 1× covered call, strike $185
    Δ + $0 (covered — no notional)
    Running CAR $0
  4. Day 30 2026-05-31
    call_assigned Shares called away at $185
    Δ − 185 × 1 × 100 (clamped at 0)
    Running CAR $0
Cycle maxCapitalAtRisk $18,000
Safe Withdrawal Engine

Three scenarios. One safe withdrawal.

The unique math at the heart of the platform. PremiumGuard takes your closed-cycle profits and nets previous withdrawals. Above target, it caps the draw at the room above target so a withdrawal never erodes the base capital that’s producing your income. Below target, it throttles the draw to a configurable fraction while you rebuild.

Gross Available Closed-cycle profits − Previous withdrawals
Room Above Target Account value − Target equity
Safe To Withdraw max( min(Gross Available, Room Above Target), $0 )
A Above target

Account value sits above target and realised profit fits within the room above target. The full profit is yours.

Setup
Target equity
$50,000
Account value
$65,000
Closed profits
$15,000
Previous withdrawals
$0
What the engine sees
Room above target
$15,000 above target
Gross available
$15,000

Profit ≤ room above target. Take the full gross.

Safe to withdraw $15,000
C Below target

Account value is below target. Withdrawals are throttled to a configurable fraction of profit while you rebuild.

Setup
Target equity
$50,000
Account value
$30,000
Closed profits
$15,000
Previous withdrawals
$0
What the engine sees
Room above target
−$20,000 below target
Gross available
$15,000
Throttle rate
50%

Below target. Throttle to 50%: $15,000 × 0.50.

Safe to withdraw $7,500
Cost basis

Three ways shares enter a cycle. One source of truth.

Brokerages reshape cost basis for wash sales and premiums received, which is why the number on your broker screen often disagrees with what your wheel actually did. PremiumGuard ignores those adjustments and applies one of three deterministic formulas, based on how the shares were acquired.

01 weightedAvgCostBasis

Weighted average — multiple buys

When you add to an existing share position, cost basis re-averages across all shares held. PremiumGuard computes the weighted mean using existing shares + new shares.

Formula (existingShares × existingAvg + newShares × newPrice) ÷ totalShares
Worked

100 sh @ $30 avg. Buy 200 more @ $25.

(100 × 30) + (200 × 25) = 3,000 + 5,000 = 8,000 8,000 ÷ 300 sh = $26.67 / share
Cost basis $26.67
02 assignmentCostBasis

Put assignment — shares received

When a cash-secured put is assigned, the strike price is your cost. The premium you collected stays in Premium P/L — it does not lower the cost basis.

Formula cost = strikePrice
Worked

Sold $50 put for $200 premium. Assigned.

cost basis = $50 / share Premium of $200 stays in totalPremiumReceived
Cost basis $50.00
03 exerciseCostBasis

Call exercise — exercising a long call

When you exercise a bought call into shares, your cost per share is the strike plus the premium you paid (amortized across the share count).

Formula cost = strike + (premiumPaidTotal ÷ shareCount)
Worked

Bought call $15 strike for $200 total premium. Exercised.

$15 + ($200 ÷ 100 sh) $15 + $2.00 = $17.00 / share
Cost basis $17.00
Insights

Eighteen rules. Zero models. Every one documented.

Insights is a deterministic rule engine: plain arithmetic over your own fills, detected cycles, live quotes, the earnings calendar, and the strategy profile you declared. The same inputs always produce the same output, and every insight carries the numbers that fired it. It runs after every sync and nightly, and a code-level test bans prescriptive language from every template: an insight reports what crossed a line, never what to do about it.

Inputs your fills + detected cycles live quotes earnings calendar daily price snapshots declared strategy profile withdrawal history
Info

A neutral observation worth knowing. Nothing is wrong; the numbers just say something you might not have noticed.

Watch

Worth attention. A measurement is moving toward a line you or the rule defines, but has not crossed it.

Flag

A defined line has been crossed and the condition is true right now. Flags never age out while they remain true.

Severity describes the state of a measurement. It never encodes a recommendation.

A

Track record

7 rules

Computed over your full closed-cycle history, but reported only for tickers you are still involved with: an open cycle, or cycle activity inside a trailing activity window.

  1. premium_equity_decomposition

    Splits a ticker’s closed-cycle P/L into premium collected versus equity result, so a winner propped up by one stock move (or dragged by one assignment) is visible as such.

  2. win_rate_outlier

    Compares a ticker’s closed-cycle win rate against your account average and reports material outliers in either direction, subject to per-ticker and account sample floors.

  3. ticker_annualized_return

    Annualizes each ticker’s closed-cycle returns and reports meaningful deviation from your account’s own annualized rate.

  4. capital_efficiency

    Return per unit of capital-time deployed, per ticker versus account. Standout tickers are reported.

  5. repeat_offender

    Cumulative closed losses concentrated in a single ticker. Escalates from watch to flag as the cumulative loss deepens.

  6. open_cycle_aging

    Days an open cycle has been running versus a multiple of your own median closed-cycle length.

  7. entry_yield_quality

    Groups closed cycles into entry premium-yield buckets (premium ÷ strike notional at entry) and compares win rates across buckets that meet the sample floor.

B

Open risk

5 rules

Evaluated against open positions at current quotes. Short legs whose expiration has passed but whose outcome the broker has not reported yet are excluded; they are not open risk.

  1. earnings_before_expiration

    An earnings date landing before an open short option’s expiration. Flag when the report is imminent; watch otherwise.

  2. short_put_near_money

    Open short puts near the money at current quotes. In the money is always a flag.

  3. assigned_shares_underwater

    Assigned shares trading below their weighted-average cost basis. Deeper price-to-basis ratios escalate from watch to flag.

  4. expiration_week

    A radar of open contracts expiring within the coming sessions, so expiration week never arrives unannounced.

  5. concentration_snapshot

    Any single ticker’s share of your total open capital at risk. Profile-independent; it fires whether or not you declared a cap.

C

Strategy conformance

6 rules

These rules only run if you declare a strategy profile for the account: target return, concentration cap, strike range, diversification floor, DTE habits. You declare it once; the engine measures drift against it.

  1. concentration_vs_cap

    A ticker’s share of open capital at risk versus the per-position cap you declared. Materially exceeding your own cap escalates to flag.

  2. strike_drift

    Recent short-put openings versus your declared strikes-out-of-the-money range, measured in per-symbol strike increments (see definitions below).

  3. pace_vs_target

    Realized return pace over the trailing window versus the annual target you declared.

  4. diversification_floor

    Distinct tickers deployed versus the minimum you declared.

  5. withdrawal_conformance

    Actual withdrawals over the window versus what the Safe Withdrawal Engine computed as safe.

  6. dte_drift

    Days-to-expiration of recent openings versus the typical and maximum DTE you declared.

Insight lifecycle

One insight per condition
Insights deduplicate on account, rule, and entity. Refreshes update the existing row instead of stacking duplicates, so the “since” date is the day the condition first became true and survives every refresh and cycle rebuild.
Auto-resolve
If a rule stops being true, its insight resolves on the next refresh. Nothing lingers by inertia.
Acknowledge
Acknowledging an insight collapses it out of the list and every contextual badge while the engine keeps tracking it. It resurfaces on its own only if the severity escalates.
Info aging
Info-severity observations quietly self-acknowledge after sitting unacknowledged for a stretch. Watch and flag never age out: an active flag is a currently-true condition.

Definitions that matter

open capital at risk

The concentration denominator

Concentration rules divide by your total open capital at risk, not account equity. On a margin account, equity understates what is actually deployed; capital at risk is the true allocation base. “31% of open capital at risk” means 31% of the dollars currently exposed, not 31% of your account value.

strike increment

Measuring drift in strikes, per symbol

Your strike range is declared the way traders speak: “I sell 1 to 3 strikes out.” The engine infers each symbol’s strike increment from the gaps in your own traded strikes, snapped to the standard 0.50 / 1 / 2.50 / 5 / 10 ladder, with a price-based fallback for symbols you have not traded. Drift classification allows half-strike tolerance.

entry premium yield

Yield at the moment you sold

Premium received divided by strike notional at entry. It captures how rich the entry was independent of what happened afterward, which is what makes cross-bucket win-rate comparison meaningful.

Trigger thresholds are versioned in code, set conservatively, and tuned as live data accumulates. The rules themselves, and everything on this page, hold regardless of tuning.

Precision & sources

Reproducible math. Auditable inputs.

Every number on your dashboard traces back to a formula on this page and a row in your broker history. If a calculation surprises you, the source is recoverable.

Precision
decimal.js arithmetic
No floating-point drift. No rounding errors at scale.
Determinism
Same trades, same numbers
Action-priority ordering means a re-sync produces identical cycles.
Source of truth
Your broker, read-only
OAuth (Schwab), Flex token (IBKR), or SnapTrade (Robinhood, Fidelity). No writes.
Edge cases
Explicit, not silent
Missing equity returns null. Negative withdrawal clamps to zero.
See the math on your own book
Connect a broker. PremiumGuard backfills your cycles and runs every formula on this page against your real trade history.
Start free trial

Methodology questions? Email support@premiumguardhq.com. Engineering answers, not marketing.