Strategy 4 — Stretched Double Calendar (DCS)
DCS_DRY_RUN = True. Scanner fires and positions are tracked with simulated fills. No real orders placed. To go live, set DCS_DRY_RUN = False in config.py.
How it works
The Stretched DC is a DC + OTM calendar wings structure. It adds two extra calendar spreads — one on each side of the ATM — at a distance that adapts to the current IV regime (45–60% of the expected 1-standard-deviation move). The result is a wider, shallower profit tent that tolerates moderate spot moves that would hurt a pure DC.
8-Leg Structure
ATM legs (same as base DC) + OTM calendar on each wing:
DC vs DCS: Profit Tent Comparison
Interactive payoff chart at expiry. Green = DC (narrow tent), Purple = DCS (wide tent). Drag the spot slider to compare the P&L at different spot levels.
Approximated at expiry using intrinsic value only. Actual P&L during holding period depends on IV and theta.
Wing Sizing — Adaptive by IV Regime
Wing distance = adaptive_wing_pct × 1SD, rounded to the nearest 100-pt step.
| Near IV range | Wing pct | Config param | Typical wing (NIFTY ~24500, DTE 8) |
|---|---|---|---|
| < 22.5% (low vol) | 45% | DCS_WING_PCT_LOW_IV | ~200–300 pts |
| 22.5% – 24.0% (mid vol) | 52% | DCS_WING_PCT_MID_IV | ~300–400 pts |
| > 24.0% (high vol) | 60% | DCS_WING_PCT_HIGH_IV | ~400–500 pts |
SkewedDCSScanner
that runs alongside DCS and uses asymmetric CE/PE wings when put or call skew exceeds a threshold.
It includes an interactive skew calculator and side-by-side profit tent comparison.
DC vs DCS Selector — Realized Range Filter
Every scan cycle, each scanner appends the current NIFTY spot to an intraday observation list. The realized range is the high − low of all spot readings for the current trading day. This is used as an entry gate for both DC and DCS:
| Scanner | Skip if realized range exceeds … | Config | Logic |
|---|---|---|---|
| DC | 45% of near ATM straddle | DC_REALIZED_RANGE_MAX_PCT = 0.45 | Market already moved — prefer DCS which has OTM wings to absorb a wider range |
| DCS / DCS_SKEW | 80% of near ATM straddle | DCS_REALIZED_RANGE_MAX_PCT = 0.80 | Market too volatile for even an 8-leg structure — skip entirely |
Natural selector: when range is <45%, DC and DCS both enter (DC preferred by being simpler). When range is 45–80%, DC auto-skips and DCS takes the trade. When range is >80%, both skip. Spot history is cleared at end of each trading day.
Entry Filters (all must pass)
| Filter | Config | Why |
|---|---|---|
| DTE to near expiry | DCS_MIN_DTE=7 to DCS_MAX_DTE=10 | OTM near legs below 5 DTE have negligible theta (₹5-15 premium) — wings add capital risk with no edge |
| Near ATM IV ≥ min | DC_MIN_IV = 15% (shared) | Same IV floor as DC — enter only when premium supports the theta edge |
| Near ATM IV ≤ max | DC_MAX_IV = 25% (shared) | Avoid event risk |
| Far−Near IV gap | DC_MAX_IV_SPREAD = 5% (shared) | Skip if far expiry has event premium priced in |
| Near ATM straddle premium | DC_MIN_NEAR_STRADDLE = 80 pts | Same floor as DC |
| OTM strikes must exist in chain | checked via _find_row(oc, otm_ce_k) | Wing offset may land between listed strikes if it's an unusual value |
| Realized range filter | DCS_REALIZED_RANGE_MAX_PCT = 0.80 | Skip if today's observed spot range (high − low across scan cycles) > 80% of near ATM straddle. Market moved too far for the OTM wings to still be symmetric around spot. |
| Position limits (3-layer guard) | DCS_MAX_CONCURRENT = 3 | (1) Max 3 concurrent DCS positions; (2) at most one new DCS entry per calendar day (prevents stacking at the same spot level); (3) skip if an open DCS already exists at this exact ATM + near expiry (dedup guard) |
DCS_MIN_DTE (7 days), get_expiries() automatically looks ahead one full week to the following Tuesday. This expands the valid DCS entry window from effectively 1–2 days per cycle to a broader window across the full DTE 7–10 range.
Stop Triggers (same as DC)
| Trigger | Condition | Why |
|---|---|---|
| Time stop | dte_near < 0, or dte_near = 0 at/after 15:00 IST | Hold through expiry day morning, then exit before the close window. |
| Trigger 1 — P&L stop | Net P&L ≤ −20% of net debit | Max loss guardrail |
| Trigger 2 — IV crush | Entry IV − current IV ≥ 10 pts | Sustained IV drop kills far legs faster than theta helps |
| Trigger 3 — Tent break | |spot − ATM| > near_straddle × 0.90 (DTE ≥ 3 only) | Spot outside profit tent — delta no longer neutral |
| Profit target | Net P&L ≥ 42% of net debit | Higher than DC's 32% — wings take 1-2 extra days to contribute |
TransactionCosts.dcs_entry_cost() and dcs_close_cost()
in arb_bot/costs.py. The entry_cost is stored in the trade record at execution time and used in all subsequent net P&L calculations.