--- id: staskh/trading_skills/ib-pmcc-advisor version: "7530efee" license: MIT install: manual updated: 2026-07-20 --- # ib-pmcc-advisor — Pulls all diagonal call spreads from your IB portfolio and surfaces actionable metrics on the short leg: delta, IV, assignment probability, and daily P&L projections. Ranks the top roll candidates by delta improvement and net credit, then displays a side-by-side comparison to help you decide whether to hold, roll, or close. Requires TWS or IB Gateway running locally with API enabled. Publisher: staskh · Stars: 299 · Updated: 2026-07-20 Install (manual): `git clone https://github.com/staskh/trading_skills` ## SKILL.md # IB PMCC Advisor Analyzes all PMCC (diagonal call spread) positions in the IB portfolio and provides actionable advice on the short leg: assignment risk, P&L projections per day, and ranked roll recommendations. ## IB Connection TWS or IB Gateway must be running locally with API enabled: - **Paper trading** — port 7497 - **Live trading** — port 7496 - **`IB_PORT` env var** — default port when `--port` is omitted (e.g. `IB_PORT=4001` for a Gateway container). Precedence: `--port` flag > `IB_PORT` > built-in default. Set it in the shell or a `.env` file. **Port fallback:** If the configured port fails, automatically retry on the other port. If the retry succeeds, save to memory which account type worked (live/paper) and reuse it for all IB skill calls in this and future sessions — until the user explicitly asks for the other account. If both ports fail, ask the user to verify that TWS or IB Gateway is running with API access enabled. ## Instructions ### Step 1: Run the script ```bash uv run python .claude/skills/ib-pmcc-advisor/scripts/pmcc_advisor.py [--port PORT] [--account ACCOUNT] [--min-roll-dte N] [--price-mode mid|last] ``` The script returns JSON to stdout. Parse it and use it for the response below. ### Step 2: Default response — brief inline summary Unless the user explicitly asks for a report or JSON output, respond with a **concise inline summary only**. No files saved. Format: - One line per spread: `SYMBOL — short $STRIKE exp DATE (δ=X, assign=Y%) — [HOLD / ROLL to $STRIKE]` - Lead with any red flags (assignment > 40%, DTE < 7, earnings within short window). - For flagged spreads, add one extra line with the top roll candidate and net credit. - Clean positions: the one-line summary is enough. ### Step 3: Generate files only when explicitly requested **MD report** — triggered by: "save a report", "generate a report", "write a report", "markdown", "PDF". Read `.claude/skills/ib-pmcc-advisor/templates/markdown-template.md` for full formatting instructions. Save to `sandbox/pmcc_advisor_{ACCOUNT}_{YYYY-MM-DD}_{HHmm}.md`. Use first account ID; derive timestamp from `generated_at`. The report must include all sections per spread: 1. **Red flags summary** — assignment > 40%, DTE < 7, no rolls, earnings warnings 2. **Company description** — one sentence from your own knowledge (always) 3. **Technical profile** — RSI, MACD, EMA crossover, ADX, SMA distance, 3mo return, bullish score (only if technical data is present in conversation context; omit otherwise) 4. **Spread structure table** — both legs: strike, expiry, DTE, cost, current price, IV 5. **Short leg risk** — delta (BS + IB), assignment probability with risk label 6. **Daily P&L projections** — all rows: date, days to expiry, best exit spot, max P&L (mark peak row) 7. **Roll candidates table** — strike, expiry, DTE, delta, assign%, IV, net credit, $/day, P&L if assigned, bid/ask 8. **Comparison table** — current vs roll_1/2/3 side by side 9. **Recommendation** — hold/roll/close with reasoning **JSON output** — triggered by: "save JSON", "export JSON", "save the data", "output file". Save raw script output to `sandbox/pmcc_advisor_{ACCOUNT}_{YYYY-MM-DD}_{HHmm}.json`. ## Arguments | Flag | Default | Description | |------|---------|-------------| | `--port` | 7497 | IB Gateway/TWS port | | `--account` | all | Specific account ID | | `--min-roll-dte` | 7 | Minimum DTE for roll candidates | | `--price-mode` | mid | Option price: `mid` (bid+ask)/2 or `last` | | `--symbols` | all | Analyze only these symbols (e.g. `--symbols NVDA WMT`) | ## JSON Output Structure ```json { "generated_at": "2026-04-30 10:25 ET", "data_delay": "real-time", "accounts": ["Uxxxxxxxx"], "price_mode": "mid", "min_roll_dte": 7, "symbols_filter": ["NVDA", "WMT"], "spreads": [ { "symbol": "NVDA", "account": "Uxxxxxxxx", "qty": 10, "underlying_price": 201.46, "leaps_expiry": "20260918", "earnings": { "date": "2026-05-20", "timing": "AMC", "warning_short": false, "warning_roll_indices": [1, 2, 3] }, "long": { "strike": 180.0, "expiry": "20260918", "dte": 141, "avg_cost": 35.51, "current_price": 36.20, "iv_pct": 42.1, "ib_delta": 0.7821, "ib_iv_pct": 41.8 }, "short": { "strike": 210.0, "expiry": "20260618", "dte": 49, "premium_received": 6.88, "current_price": 5.10, "iv_pct": 38.5, "delta": 0.3421, "assignment_prob_pct": 28.4, "ib_delta": 0.3415, "ib_iv_pct": 38.2 }, "daily_pnl": [ {"date": "2026-04-30", "days_to_short_expiry": 49.0, "optimal_spot": 215.20, "pnl": 1234.56}, {"date": "2026-05-01", "days_to_short_expiry": 48.0, "optimal_spot": 214.80, "pnl": 1289.10} ], "roll_candidates": [ { "strike": 215.0, "expiry": "20260717", "dte": 78, "price": 5.80, "delta": 0.2910, "assignment_prob": 22.5, "iv_pct": 37.2, "net_credit": 0.70, "profit_per_day": 0.0744, "pnl_if_assigned": 3580.0, "bid": 5.60, "ask": 6.00 } ], "comparison": { "current": {"strike": 210, "expiry": "20260618", "dte": 49, "delta": 0.3421, "assignment_prob": 28.4, "profit_per_day": 0.1404, "pnl_if_assigned": 1880.0}, "roll_1": {"strike": 215, "expiry": "20260717", "dte": 78, "delta": 0.2910, "assignment_prob": 22.5, "profit_per_day": 0.0744, "pnl_if_assigned": 3580.0} } } ] } ``` ## Key Fields - `symbols_filter` — list of uppercase symbols when `--symbols` was used; `null` means full portfolio - `data_delay` — `"real-time"` if live quotes available, `"stalled - using last price"` if IBKR quotes unavailable - `generated_at` — NY timezone timestamp - `leaps_expiry` — expiry of the long leg (YYYYMMDD); all roll candidates are capped at or before this date - `earnings.date` — next earnings date (YYYY-MM-DD) from Yahoo Finance; null for ETFs - `earnings.timing` — `"BMO"` (before open) or `"AMC"` (after close) - `earnings.warning_short` — true if earnings fall within the last 7 calendar days before short expiry - `earnings.warning_roll_indices` — 1-based indices of roll candidates whose expiry window contains the earnings date - `delta` / `ib_delta` — BS-calculated vs. IBKR model Greeks (both reported when available) - `iv_pct` / `ib_iv_pct` — IV in percent; BS-calculated from option price vs. IBKR model Greeks - `assignment_prob_pct` — N(d2): risk-neutral probability the short expires ITM - `net_credit` — credit received when rolling (negative = debit); rolls with debit > $0.10/share excluded - `pnl_if_assigned` — P&L if underlying finishes above short_strike at expiry: `(short_strike - long_strike - long_cost + total_premium) × 100` - `daily_pnl[].optimal_spot` — spot price that maximises exit P&L on that day (found via numerical optimisation); increases as theta decays the short leg - `daily_pnl[].pnl` — total dollars (qty × 100 contracts) at the optimal spot on that day ## Roll Selection Criteria Candidates must satisfy both: 1. **Delta ≤ 0.40** (absolute cap — allows same-strike forward rolls when current short is near expiry) 2. **Net credit ≥ -$0.10/share** (not a large debit) Scans the next 5 available chain expirations after the current short expiry, bounded by the LEAPS expiry. Ranked by: delta improvement (highest weight) → net credit → DTE extension. ## Example Usage ```bash # All accounts (paper, default) uv run python .claude/skills/ib-pmcc-advisor/scripts/pmcc_advisor.py # Live account, 14-day minimum roll DTE, last-price mode uv run python .claude/skills/ib-pmcc-advisor/scripts/pmcc_advisor.py --port 7496 --account Uxxxxxxxx --min-roll-dte 14 --price-mode last # Analyze only specific symbols uv run python .claude/skills/ib-pmcc-advisor/scripts/pmcc_advisor.py --symbols NVDA WMT ``` ## Architecture All logic lives in `src/trading_skills/broker/pmcc_advisor.py`: - **Analytics functions** (top half, no IBKR imports): `get_option_price`, `calc_iv`, `calc_delta`, `calc_assignment_prob`, `calc_bs_price`, `calc_daily_pnl_table`, `check_earnings_warning`, `find_best_rolls`, `build_comparison_table`, `score_roll_candidate` - **Data layer** (bottom half, uses IBKR + Yahoo Finance): `get_pmcc_data`, `_identify_pmcc_spreads`, `_fetch_single_option_quote`, `_fetch_option_quotes_batch`, `_get_chain_params`, `_fetch_earnings_dates` Reuses from `src/trading_skills/broker/`: - `connection.py` — `ib_connection`, `CLIENT_IDS`, `fetch_positions`, `fetch_spot_prices`, `normalize_positions`, `best_option_chain` - `black_scholes.py` — `implied_volatility`, `black_scholes_price`, `black_scholes_delta`, `estimate_iv` [View on SkillFed](https://skillfed.io/staskh/trading_skills/ib-pmcc-advisor) · [View on GitHub](https://github.com/staskh/trading_skills)