Config Reference
All tunable parameters live in class Config in arb_bot/config.py.
Runtime-Editable Config
A subset of the knobs listed below — everything registered in
arb_bot/settings/registry.py — can be changed at runtime without a
code deploy or bot restart. The database stores only overrides; an
absent row means "use the code default." Changes take effect immediately via
Postgres LISTEN/NOTIFY (the listener thread in the running bot process
receives the notification and clears the in-memory snapshot instantly). For processes
that did not receive the notification, the snapshot is refreshed automatically on a
5-minute TTL. There is no outage window.
There are three ways to edit a runtime-editable knob:
-
Dashboard Settings page — navigate to
/settings in the
React dashboard. Knobs are grouped (Risk, Timing, DC, DCS, MDC, AI, Dry-Run).
Each row shows the key, current effective value, code default, and description.
Click a row to set a new value; the page validates bounds before saving.
-
Telegram
/set KEY VALUE — e.g., /set DC_PROFIT_TARGET_PCT 0.38.
The bot validates the type and bounds, writes to DB, and broadcasts the change.
-
Telegram
/config [group] — lists all runtime-editable
knobs with their current effective value. Pass a group name (e.g., /config DC)
to filter the output.
Secrets and static infrastructure are never runtime-editable.
Only the named scalar knobs in arb_bot/settings/registry.py go through
the settings store. Everything else — API tokens, DB URLs, strategy-slot dicts,
enum constants — passes through the normal class attribute path with no DB access.
Go-live state overrides dry-run flags after first run
DC_DRY_RUN, DCS_DRY_RUN, SDCS_DRY_RUN, DDC_DRY_RUN, IC_DRY_RUN, MDC_DRY_RUN, and AI_MARKET_DRY_RUN are first-run or strategy-local safety defaults. Once go-live records exist, runtime state is changed with Telegram commands, not by rereading config flags. AI_MARKET remains dry-run-only in phase 1.
Capital & Risk
| Parameter | Default | Meaning |
PHASE1_CAPITAL | ₹8,00,000 | Capital allocated to this bot |
DEPLOYED_CAPITAL | ₹17,00,000 | Operator-deployed capital used by the autonomous roadmap risk envelope. |
KILL_SWITCH_LOSS | −₹10,000 | Daily loss limit before halting new trades. Also the envelope daily cap. |
WEEKLY_DD_CAP | −₹25,000 | Risk envelope rolling weekly drawdown cap. |
MONTHLY_DD_CAP | −₹50,000 | Risk envelope absolute monthly drawdown cap. |
LIFETIME_DD_CAP | −₹1,00,000 | Risk envelope hard cumulative drawdown halt. |
LOSS_STREAK_PAUSE_DAYS | 3 | Consecutive losing days that pause new entries until operator resume. |
LOT_LOCK_DAYS | 30 | Minimum live-trading age before strategies can use their default lot sizing. |
LOT_UNLOCK_PROFIT | ₹50,000 | Cumulative profit required, in addition to LOT_LOCK_DAYS, to unlock default lot sizing. |
CASH_BUFFER_PCT | 15% | Minimum undeployed cash fraction |
MAX_OPEN_POSITIONS | 10 | Max simultaneous positions |
MAX_DAILY_TRADES | 10 | Max orders per day (including reversals) |
PORTFOLIO_GREEKS_GATE_ENABLED | True | Master switch for the portfolio Greeks runtime gate before option entries. |
PORTFOLIO_BLOCK_DRY_RUN | False | When false, dry-run trades that would breach Greek limits still simulate so research data is preserved; SHADOW/LIVE entries are blocked. |
PORTFOLIO_MAX_ABS_DELTA | 130.0 | Maximum absolute portfolio delta after adding a candidate trade. |
PORTFOLIO_MAX_ABS_GAMMA | 0.35 | Maximum absolute portfolio gamma after adding a candidate trade. |
PORTFOLIO_MAX_ABS_THETA | 25,000 | Maximum absolute portfolio theta per day after adding a candidate trade. |
PORTFOLIO_MAX_ABS_VEGA | 25,000 | Maximum absolute portfolio vega per 1% IV move after adding a candidate trade. |
BROKER_HEALTH_ENABLED | True | Master switch for scan-cycle broker health sampling and runtime entry downgrades. |
BROKER_HEALTH_OPTION_CHAIN_LATENCY_MS | 2,500 ms | Option-chain latency threshold that degrades broker health and forces dry-run-only entries. |
BROKER_HEALTH_API_LATENCY_MS | 1,500 ms | Order, position, and margin API latency threshold that degrades broker health. |
BROKER_HEALTH_RECENT_LIMIT | 20 | Recent persisted health samples returned by /api/broker/health. |
IV_SNAPSHOT_RETENTION_DAYS | 180 | Prune cutoff, in days, for the iv_snapshots table. Enforced on every insert. |
BATTLE_LOG_RETENTION_DAYS | 60 | Prune cutoff, in days, for the strategy_battle_log table. Enforced on every insert. |
Event Calendar Guard
| Parameter / Command | Default | Meaning |
EVENT_GUARD_ENABLED | True | Master switch for event-risk blocking before DC, DCS, DCS_SKEW, DDC, MDC, and IC scans. |
EVENT_LOOKAHEAD_DAYS | 7 | Default pre-event block window for blocking market events. |
EVENT_CALENDAR_SEED_FILE | data/market_events_seed.json | Manual official/seeded events loaded on bot startup and by the fetch job. |
make fetch-events | manual/operator-run | Loads the seed file, fetches NSE holidays for current/next year, fetches MoSPI CPI/GDP/IIP events, fetches OEA WPI warning events, normalizes rules, and upserts into SQLite. |
Box Spread
| Parameter | Default | Meaning |
min_profit_per_lot (per-underlying) | NIFTY ₹300 / BANKNIFTY ₹450 | Minimum net profit after all charges. NIFTY is lower because its premiums are structurally smaller. BANKNIFTY stays at ₹450 to absorb the ₹300–400/lot gap between scan prices and fill prices. |
BOX_MAX_MARGIN_PER_TRADE | ₹80,000 | Skip if margin estimate exceeds this |
BOX_CLOSE_DAYS_BEFORE_EXPIRY | 2 | Close N days before expiry (pin risk) |
BOX_PROFIT_TARGET_PCT | 70% | Close early when this % of max profit is captured |
Calendar Spread
| Parameter | Default | Meaning |
CAL_ENTRY_SIGMA | 2.0 | Enter when spread deviates > 2σ from mean |
CAL_EXIT_SIGMA | 0.5 | Exit when spread returns within 0.5σ |
CAL_LOOKBACK_DAYS | 20 | Rolling window for mean / std computation |
CAL_MIN_NET_PROFIT_PER_LOT | ₹50 | Skip if net profit after charges is below this |
NEAR_EXPIRY_TIME_STOP_HOUR | 15 | Hour in IST for DC, DCS/DCS_SKEW, DDC, and IC expiry-day time stops. |
NEAR_EXPIRY_TIME_STOP_MIN | 0 | Minute in IST for expiry-day time stops. With the default, near-expiry option spreads close at/after 15:00 IST on expiry day, or immediately if near expiry has already passed. |
Double Calendar Straddle (DC)
| Parameter | Default | Meaning |
DC_LOT_SIZE | 65 | NIFTY lot size |
DC_MIN_DTE | 3 | Minimum DTE to near expiry at entry — below this gamma risk too high |
DC_MAX_DTE | 7 | Maximum DTE to near expiry at entry — beyond this theta advantage is minimal |
DC_MIN_IV | 15% | Minimum near ATM IV — enter only when premium is high enough for the theta edge to materialise |
DC_MAX_IV | 25% | Maximum near ATM IV — skip if event risk (RBI, results); IV could explode and kill the short near leg |
DC_MAX_IV_SPREAD | 5% | Skip if far_iv − near_iv > this — event premium priced into far expiry |
DC_MIN_NEAR_STRADDLE | 80 pts | Minimum near straddle premium — enough theta to collect |
DC_PROFIT_TARGET_PCT | 32% | Close when net P&L ≥ 32% of net debit (after entry + close costs). Theta is front-loaded — bulk arrives in first 2-3 days. |
DC_STOP_PNL_PCT | 20% | Trigger 1: close if net P&L ≤ −20% of net debit. Max-loss guardrail regardless of IV or spot. |
DC_STOP_IV_DROP | 10.0 pts | Trigger 2: close if entry IV − current IV ≥ 10 pts. IV crush kills far legs faster than near theta helps. |
DC_STOP_TENT_DTE | 3 | Trigger 3 only active when DTE ≥ this — inside 3 DTE the near gamma is too volatile to trust the tent shape. |
DC_STOP_TENT_WIDTH | 1.30 | Trigger 3: close if |spot − atm| > near_straddle_entry × 1.30. Widened from 0.90 after live data showed 0.90 exits consistently exited on normal NIFTY noise before theta could accrue. |
DC_STOP_CONFIRM_CYCLES | 2 | Panic stops (P&L stop + tent break) must breach this many consecutive monitor cycles before closing. 1 = fire immediately (legacy). Live data showed every stop fired on a transient intraday tick — many trades were positive at the prior snapshot — so >1 requires the breach to persist. Not applied in EXPIRY_APPROACH (gamma risk demands immediate action). Shipped at 2 (A/B: DC −₹33k → −₹6.5k). |
DCS_STOP_CONFIRM_CYCLES | 1 | Same as DC_STOP_CONFIRM_CYCLES but for DCS / DCS_SKEW. Separate knob so DC can gate without dragging DCS — DCS's gating effect is marginal (its losses trend rather than mean-revert). |
TRAILING_PROFIT_ARM_DEBIT_PCT | 0.15 | Arm the trailing lock once peak P&L ≥ 15% of net debit — a deterministic, reachable anchor. Replaces the old expected_profit-based arm, which live data showed was unreachable (trades peaked ≈13% of debit), leaving the trail dead and peaks given back into losses. |
TRAILING_PROFIT_LOCK_PCT | 0.70 | Deprecated — superseded by TRAILING_PROFIT_ARM_DEBIT_PCT. Kept for back-compat; no longer used by the exit. |
TRAILING_PROFIT_FLOOR_PCT | 0.85 | Once trailing is active, close if live P&L drops below 85% of the peak seen since the lock activated. Locks in most of the profit while allowing normal intraday breathing room. |
DC_MAX_MARGIN | ₹1,50,000 | Skip if net debit × lot exceeds this (capital cap per trade) |
DC_DRY_RUN | True | First-run seed for DC go-live state. Runtime state is stored in SQLite records. |
DC_REALIZED_RANGE_MAX_PCT | 0.45 | Skip DC if today's intraday spot range > 45% of near ATM straddle — prefer DCS which has OTM wings to absorb the wider range. |
DC_IV_PERCENTILE_GATE_ENABLED | True | Enable the IV percentile quality gate after DC scanner signal generation. |
DC_BLOCK_TOP_IV_PERCENTILE | 90 | Skip new DC entries when mature IV history says current ATM IV percentile is at or above this threshold. |
Stretched Double Calendar (DCS)
| Parameter | Default | Meaning |
DCS_MIN_DTE | 7 | Minimum DTE to near expiry — OTM near legs below 5 DTE have negligible theta differential (₹5-15 premium) |
DCS_MAX_DTE | 10 | Maximum DTE — wider than DC to give OTM wings time to contribute theta |
DCS_IV_REGIME_LOW | 22.5 | Near IV below this → low-vol tier; apply DCS_WING_PCT_LOW_IV (tighter wings, less capital). |
DCS_IV_REGIME_HIGH | 24.0 | Near IV above this → high-vol tier; apply DCS_WING_PCT_HIGH_IV (wider wings to stay within likely range). |
DCS_WING_PCT_LOW_IV | 0.45 | Wing = 45% of 1SD when near IV < 22.5%. Tighter tent in low-vol conditions. |
DCS_WING_PCT_MID_IV | 0.52 | Wing = 52% of 1SD when 22.5% ≤ near IV ≤ 24.0%. Standard mid-vol sizing. |
DCS_WING_PCT_HIGH_IV | 0.60 | Wing = 60% of 1SD when near IV > 24.0%. Wider tent to tolerate the larger expected moves. |
DCS_REALIZED_RANGE_MAX_PCT | 0.80 | Skip DCS if today's intraday spot range > 80% of near ATM straddle — market too volatile for an 8-leg structure. |
DCS_SKEW_THRESHOLD | 2.0 | Min IV-pt gap between put skew and call skew to trigger asymmetric wings in DCS_SKEW. Below this, wings are symmetric. |
DCS_SKEW_CE_WING_PCT | 0.45 | CE wing pct used when put skew is dominant (tighter upside tent, wider downside tent). |
DCS_SKEW_PE_WING_PCT | 0.60 | PE wing pct used when put skew is dominant (wider downside tent where risk is concentrated). |
DCS_PROFIT_TARGET_PCT | 42% | Close when net P&L ≥ 42% of net debit. Higher than DC's 32% — wings take 1-2 extra days to contribute. |
DCS_MAX_MARGIN | ₹2,50,000 | Capital cap for 8-leg structure (net debit × lot) |
DCS_DRY_RUN | True | First-run seed for DCS go-live state. Stop triggers same as DC (DC_STOP_*). |
DCS_MAX_CONCURRENT | 3 | Max simultaneous DCS positions. Each open position must be at a different ATM + near expiry. At most one new DCS entry is allowed per calendar day. |
Skew-Aware DCS (DCS_SKEW)
SkewedDCSScanner runs as a separate strategy alongside DCS for side-by-side comparison.
It uses asymmetric CE/PE wings when put or call skew exceeds the threshold; otherwise identical to DCS.
| Parameter | Default | Meaning |
SDCS_DRY_RUN | True | First-run seed for skew-aware DCS go-live state. |
SDCS_MAX_CONCURRENT | 1 | Max simultaneous DCS_SKEW positions. Kept at 1 during comparison phase to minimize capital commitment. |
DCS_SKEW_DISABLED | False | Re-enabled in dry-run to evaluate performance with AI market context active. Was disabled after 0% win rate in 5 live trades; scanner returns None immediately when True. |
Directional Diagonal Calendar (DDC)
DirectionalDiagonalScanner is a dry-run 2-leg strategy. It buys the far-month ATM option and sells the near-week OTM option on the same side after a strong intraday trend from the captured day open.
| Parameter | Default | Meaning |
DDC_DRY_RUN | True | First-run seed for DDC go-live state. |
DDC_DISABLED | False | Re-enabled in dry-run to evaluate performance with AI market context active. Was disabled after 0% win rate in 3 live trades; scanner returns None immediately when True. |
DDC_TREND_THRESHOLD_PCT | 0.5% | Minimum absolute intraday move from captured day open before DDC can signal. |
DDC_MIN_IV | 20% | Minimum ATM IV. Config stores 0.20; scanner normalizes it to the existing percent IV convention. |
DDC_MAX_IV | 25% | Maximum ATM IV. Above this, event risk is too high for the short near-week leg. |
DDC_NEAR_DTE_MIN | 5 | Minimum DTE for the near-week short leg. |
DDC_NEAR_DTE_MAX | 9 | Maximum DTE for the near-week short leg. |
DDC_OTM_DISTANCE_PTS | 200 pts | Fixed OTM distance for the short near-week leg: ATM + 200 for CE, ATM − 200 for PE. |
DDC_PROFIT_TARGET_PCT | 30% | Close when net P&L reaches 30% of entry debit. |
DDC_STOP_LOSS_PCT | 20% | Close when net P&L falls to −20% of entry debit. |
DDC_MAX_MARGIN | ₹80,000 | Skip signal if entry debit × lot size exceeds this cap. |
Iron Condor Fallback (IC)
IronCondorScanner is a dry-run fallback. It only scans when no DC, DCS, DCS_SKEW, or DDC trade is open, and it persists simulated fills instead of placing live orders.
| Parameter | Default | Meaning |
IC_DRY_RUN | True | First-run seed for IC go-live state. |
IC_MIN_IV | 18% | Minimum ATM IV. Config stores 0.18; scanner normalizes it to percent. |
IC_MAX_IV | 26% | Maximum ATM IV. Above this, event risk is too high for a short-vol range trade. |
IC_DTE_MIN | 3 | Minimum DTE for near-week IC entry. |
IC_DTE_MAX | 7 | Maximum DTE for near-week IC entry. |
IC_OTM_DISTANCE_PTS | 300 pts | Short CE/PE distance from ATM: CE at ATM + 300, PE at ATM − 300. |
IC_WING_WIDTH_PTS | 200 pts | Long hedge distance beyond each short: CE wing at ATM + 500, PE wing at ATM − 500. |
IC_MIN_CREDIT_PCT | 20% | Skip if net credit is below 20% of wing width × lot size. |
IC_IV_PERCENTILE_CREDIT_ADJUST_ENABLED | True | Enable the low-IV percentile credit adjustment when mature IV history exists. |
IC_LOW_IV_PERCENTILE | 25 | Percentile at or below which IC requires extra credit because short-vol premium is relatively cheap. |
IC_LOW_IV_MIN_CREDIT_MULTIPLIER | 1.25× | Multiplier applied to IC_MIN_CREDIT_PCT × wing width × lot size on low-IV percentile days. |
IC_PROFIT_TARGET_PCT | 50% | Close when credit captured reaches 50% of entry credit. |
IC_STOP_LOSS_CREDIT_X | 1.5× | Close when current loss reaches 1.5× entry credit. |
IC_MAX_RANGE_PCT | 60% | Skip if today's realized spot range exceeds 60% of the near ATM straddle. |
IC_MAX_MARGIN | ₹60,000 | Skip signal if max loss estimate exceeds this cap. |
AI Market Strategy
All AI calls go through CodexRunner (arb_bot/ai/codex_runner.py) which shells to codex exec — no OpenAI API key, $0 per token. Auth uses the machine's existing free ChatGPT login (mounted at ~/.codex); no API key and no per-token budget. Three flows: Flow 1 = AI_MARKET single-leg trade (premarket + confirmation), Flow 2 = shared market_view prediction every 30 min, Flow 3 = breakout_risk exit overlay every 30 min. News and macro context are fetched via Firecrawl (http://localhost:3002).
| Parameter | Default | Meaning |
CODEX_MODEL | gpt-5.5 | Model ID passed to codex exec -m. All three AI flows use this model. |
CODEX_REQUEST_TIMEOUT_SECONDS | 420 | Subprocess timeout for a single codex exec call. Longer than a typical OpenAI request because the Codex sandbox has startup overhead. |
CODEX_HOME | empty | Override path to the codex binary. When empty, the runner searches PATH and then ~/.local/bin/codex. |
CODEX_USE_FREE_CHATGPT_AUTH | True | When true (default), the runner strips any OPENAI_API_KEY from the subprocess environment so the free ChatGPT login under ~/.codex is used untouched. Set to false only if you are paying per-token with an explicit API key. There is no AI_*_BUDGET_* config — Codex is free. |
CODEX_RETRY_ON_429_TIMEOUT | True | When true, a transient codex failure (HTTP 429 rate-limit or a subprocess timeout) is retried up to CODEX_MAX_RETRIES times with backoff before giving up. |
CODEX_MAX_RETRIES | 2 | Number of retry attempts for a transient codex failure. Total attempts = retries + 1. |
CODEX_RETRY_BACKOFF_SEC | 20 | Seconds to sleep between retry attempts. Set to 0 to retry immediately (useful in tests). |
ENRICHER_RETRY_COUNT | 2 | Number of retry attempts for a single data-enricher fetch (yfinance / NSE) before it is considered failed. A failed fetch falls back to the last good cached value when available. |
ENRICHER_CACHE_TTL_MIN | 120 | TTL (minutes) of the in-process enricher cache. On a transient upstream failure, a stale-but-fresh value within this window is returned instead of None so a single provider outage does not force NO_TRADE. |
FIRECRAWL_API_URL | http://localhost:3002 | Self-hosted Firecrawl API base URL. Used by MacroSearchCollector for daily macro and per-cycle news fetches. |
FIRECRAWL_API_KEY | local | API key for the self-hosted Firecrawl instance. |
FIRECRAWL_ENABLED | True | When false, macro and news collection is skipped and the bundle gets empty dicts/lists. |
AI_PREDICT_ENABLED | True | Master switch for Flow 2 and Flow 3 (market_view + breakout_risk). Disabling this stops the 30-min scheduled runs; AI hints and breakout overlay are inactive. |
AI_PREDICT_INTERVAL_MIN | 30 | How often (minutes) the market_view and breakout_risk tasks are run during market hours. |
AI_PREDICT_MAX_AGE_MIN | 35 | Maximum age (minutes) of a prediction row before it is considered stale and ignored by the scan cycle. |
AI_PREDICT_DAILY_RUN_CAP | 20 | Maximum prediction rows per calendar day across both tasks combined. Guards against runaway calls. |
AI_HINT_ENABLED | True | When true, market_view predictions are applied to strategy signals via each spec’s ai_hint_consumer. Set to false to run AI predictions but ignore the hints (shadow mode for tuning). |
AI_EXIT_OVERLAY_ENABLED | True | Master switch for the breakout-risk exit overlay (Flow 3). Disabling skips the advisory check during position monitoring. |
AI_EXIT_MIN_CONFIDENCE | 75 | Minimum breakout confidence (%) required before the overlay triggers. Below this threshold no action is taken. |
AI_EXIT_AUTO_CLOSE | True | When true, a high-confidence breakout signal auto-closes the range-bound trade and writes action_taken=AUTO_CLOSE. When false, the advisory is written as ADVISORY_ONLY and a Telegram alert is sent for manual review. |
AI_EXIT_TENT_BUFFER_PCT | 0.5 | Distance from a short strike (as % of spot) within which the overlay considers the tent at risk and eligible for exit. |
AI_DEBRIEF_ENABLED | True | When true, closed-trade journal rows attempt a Codex-backed post-trade debrief after the close snapshot is saved. |
AI_DEBRIEF_DAILY_TOKEN_BUDGET | 200,000 | Daily rolling Codex token cap across all post-trade debriefs. |
AI_DEBRIEF_DAILY_COUNT_CAP | 50 | Maximum number of debriefs generated per calendar day. |
AI_MARKET_ENABLED | True | Master switch for the scheduled 09:05 AI_MARKET analysis (Flow 1). |
AI_MARKET_DRY_RUN | True | Safety default. Dry-run only — refuses live AI_MARKET broker orders. |
AI_MARKET_SHADOW | False | When true, analysis is stored but execution is suppressed for observation-only comparison. |
AI_MARKET_MAX_MARGIN | ₹1,00,000 | Maximum planned exposure for the simulated AI_MARKET trade. |
AI_MARKET_LOTS | 1 | Lots used for simulated AI_MARKET trade sizing. |
AI_MARKET_MIN_CONFIDENCE | 65 | Minimum confidence required before the confirmation stage can create a simulated trade. |
AI_MARKET_CONFIRMATION_TIME | 09:20 | Scheduler time for the live confirmation pass. |
AI_MARKET_MIN_CONFIRM_MOVE_PCT | 0.15 | Minimum confirmation move from the day’s first IV-snapshot spot before the setup is considered live enough to trade. |
AI_MARKET_MAX_CHASE_MOVE_PCT | 0.60 | Maximum move before the setup is too extended to chase. |
AI_MARKET_STOP_PCT | 0.35 | Index-based stop percentage for the confirmed dry-run option trade. |
AI_MARKET_TARGET_PCT | 0.70 | Index-based target percentage for the confirmed dry-run option trade. |
AI_MARKET_TRANSIENT_RETRIES | 1 | Retry count for transient Codex failures. |
AI_MARKET_MAX_OUTPUT_TOKENS | 16000 | Codex output budget for the market analysis prompt. |
AI_GATE_ENABLED | False | Optional gate for blocking MDC entries from the AI verdict. |
AI Market Sentiment (deterministic)
Flow 4 — a fully deterministic ~10-min intraday sentiment score (no LLM, no Codex call). SentimentService collects spot/PCR/IV + cached technicals, computes a weighted composite in [−100, +100] that renormalizes over whichever components are present, persists each reading to ai_market_sentiment, and feeds a conservative 4-condition exit overlay for range trades.
| Parameter | Default | Meaning |
AI_SENTIMENT_ENABLED | True | Master switch for the scheduled sentiment service. When false, no ai_market_sentiment rows are written and no sentiment job is scheduled. |
AI_SENTIMENT_INTERVAL_MIN | 10 | Minutes between sentiment runs. Runtime-editable knob. |
AI_SENTIMENT_ENRICHER_CACHE_TTL_MIN | 30 | Reserved cache TTL for enricher reuse across sentiment cycles. |
AI_SENTIMENT_MIN_COVERAGE_PCT | 30 | Minimum coverage below which a sentiment reading is considered low-confidence for downstream consumers. |
AI_SENTIMENT_EXIT_ENABLED | True | Master switch for the sentiment-risk exit overlay checked during position monitoring. |
AI_SENTIMENT_EXIT_MIN_STRENGTH | 70 | Minimum strength_pct required before the overlay can trigger an exit. |
AI_SENTIMENT_EXIT_MIN_COVERAGE_PCT | 40 | Minimum coverage_pct required before the overlay can trigger an exit. |
AI_SENTIMENT_EXIT_ADVERSE_MOVE_PCT | 0.6 | Confirmed adverse spot move (as % from prev_close) required to confirm the flip is hurting the trade. |
AI_SENTIMENT_EXIT_AUTO_CLOSE | True | When true, a qualifying signal auto-closes the range trade and writes action_taken=AUTO_CLOSE. When false, an ADVISORY_ONLY row plus a Telegram alert is emitted. |
AI_SENTIMENT_EXIT_SHADOW | False | Forces advisory-only regardless of AI_SENTIMENT_EXIT_AUTO_CLOSE, for observation before trusting the overlay. |
AI_SENTIMENT_W_MOMENTUM / _W_PCR / _W_VOL / _W_TECHNICAL / _W_GLOBAL | 0.35 / 0.25 / 0.15 / 0.15 / 0.10 | Component weights. Their sum need not be 1.0 — the composite renormalizes over whichever components are present, so a missing input is excluded rather than averaged as zero. |
Dashboard AI Assistant
Read-only advisory widget for grounded Q&A on open/closed trades, strategies, and live market state. Answers are grounded in build_context_pack(); suggestions go to Telegram for confirmation.
| Parameter | Default | Meaning |
AI_ASSISTANT_ENABLED | True | Master switch for the dashboard floating AI assistant widget (Ask + Refresh). |
AI_ASSISTANT_DAILY_CALL_CAP | 50 | Maximum cumulative assistant API calls per calendar day (both Ask and Refresh combined). |
AI_ASSISTANT_SESSION_CALL_CAP | 20 | Maximum assistant API calls per user session (4-hour TTL cookie). Limits concurrent tab spam. |
IV Surface Tracker
| Parameter | Default | Meaning |
IV_SNAPSHOT_RETENTION_DAYS | 180 | Retention window for iv_snapshots; stale rows are pruned on insert. |
BATTLE_LOG_RETENTION_DAYS | 60 | Retention window for strategy_battle_log. |
IV_SURFACE_SMILE_RANGE_PCT | 2.0 | Capture smile rows where strike distance from ATM is within this percent of spot. |
IV_SURFACE_MAX_SMILE_STRIKES | 21 | Maximum smile rows stored per snapshot, centered on ATM. |
Master DC (MDC)
MasterDCScanner is a meta-strategy wrapper. It classifies the current regime each cycle, delegates to the best DC-family sub-scanner, and stores the resulting trade under an MDC_* strategy key so it can coexist with standalone trades.
| Parameter | Default | Meaning |
MDC_DRY_RUN | True | First-run seed for MDC go-live state. MDC state is propagated into the selected sub-executor. |
MDC_MAX_CONCURRENT | 2 | Max simultaneous MDC_* positions; the second requires all controlled scale-in gates. |
MDC_MAX_MARGIN | ₹2,50,000 | Per-trade margin cap applied to whichever sub-strategy is selected. |
MDC_SCALE_IN_COOLDOWN_MINUTES | 90 | Minimum elapsed time from the newest remaining MDC anchor before another MDC position is considered. |
MDC_SCALE_IN_MIN_MOVE_PTS | 200 | Absolute minimum NIFTY movement required from the anchor spot. |
MDC_SCALE_IN_STRADDLE_PCT | 0.50 | Dynamic movement threshold as a fraction of the anchor near straddle; effective threshold is the maximum of this value and the fixed-point minimum. |
MDC_SCALE_IN_MAX_ANCHOR_LOSS_PCT | 0.10 | Scale-in is blocked when anchor P&L is at or below −10% of its strategy risk basis. |
MDC_TREND_THRESHOLD_PCT | 0.006 | Intraday spot move ≥ 0.6% from the captured open → trending → DDC. |
MDC_SKEW_THRESHOLD | 2.5 | CE/PE IV gap in points → skewed → DCS_SKEW. |
MDC_CALM_RANGE_PCT | 0.35 | Realized range / near straddle ≤ 35% → calm → DC. |
MDC_WIDE_RANGE_PCT | 0.70 | 35% to 70% → wider → DCS; above 70% → IC fallback or no trade. |
MDC_MAX_IV_FOR_DC | 25.0 | Near IV above this makes DC unattractive; the wrapper falls through to IC. |
MDC_MAX_IV_FOR_IC | 30.0 | Near IV above this is too risky even for IC, so the wrapper returns no signal. |
MAX_CONCURRENT_OPEN_TRADES | 2 | Phase 2: Hard cap on total open trades across all strategies. Scan cycle skips new entries when len(open_trades) ≥ MAX_CONCURRENT_OPEN_TRADES. Prevents correlated exposure explosion during high-IV days. |
STRATEGY_SLOTS | {"dc_family": 2} | Explicit DC-family exposure cap. The second slot is available only after MDC cooldown, movement, anchor-health, margin, Greeks, and exact-leg duplicate gates; a third entry is blocked. |
Order Execution
| Parameter | Default | Meaning |
ORDER_SLIPPAGE_PCT | 0.2% | Drift buffer added on top of the scanner bid/ask anchor (first attempt). Previously 0.4% LTP-based — that approach consistently underpriced BUY legs since LTP + 0.4% often sat below the ask on wide BANKNIFTY spreads. |
LEG_RETRY_SLIPPAGE_PCT | 0.8% | Retry uses fresh LTP + 0.8% (not bid/ask anchor) — on retry, the scanner price is too stale to trust so we fall back to aggressive LTP-based crossing. |
REVERSAL_LIMIT_SLIPPAGE_PCT | 0.1% | When reversal IS needed, _auto_reverse() tries IOC LIMIT at LTP ± this much first, then MARKET as fallback. Captures roughly half the bid-ask spread vs a direct MARKET hit (~₹150-200 saved per forced reversal). |
ORDER_FILL_TIMEOUT | 30 s | Max wait for all legs to fill (internal) |
NSE_TICK_SIZE | ₹0.05 | All limit prices rounded to this boundary |
ORDER_DELAY_SEC | 0.3 s | Delay between consecutive order placements |
OPTION_CHAIN_COOLDOWN | 3.5 s | Min gap between option chain API calls |
Partial Fill Recovery
| Parameter | Default | Meaning |
RECOVERY_TRAILING_STOP_PCT | 3% | Trailing stop from peak LTP on kept leg |
RECOVERY_TAKE_PROFIT_PCT | 10% | Take profit from entry LTP on kept leg |
RECOVERY_DIRECTION_LOOKBACK | 10 | Compare current spot vs this many readings ago (Gate 1) |
RECOVERY_MIN_TREND_PCT | 0.15% | Minimum point-to-point move to pass Gate 1; below this → FLAT |
RECOVERY_CONSISTENCY_THRESHOLD | 60% | Minimum fraction of tick intervals that must move in the trend direction to pass Gate 2. Filters spikes that fool Gate 1. |
Market Index Dashboard
Live NSE index tiles (LTP + day change% + sparkline) pushed over /ws/live on a decoupled timer. MarketIndexService batches LTP via the shared DhanClient and caches per-index intraday candles. The enabled-index list is persisted as JSON in the Postgres bot_settings table and edited via GET/PUT /api/market/indices/config.
| Parameter | Default | Meaning |
MARKET_INDEX_REFRESH_SEC | 60 | Seconds between /ws/live index frames. Runtime-tunable (10–600 s); drives the decoupled index push timer independent of trade-monitoring ticks. |
MARKET_INDEX_INTRADAY_INTERVAL | 5 | Dhan intraday candle interval (minutes) used for the sparkline series. |
MARKET_INDEX_INTRADAY_CACHE_SEC | 240 | Server-side intraday cache TTL — roughly one fetch per 5-min candle to respect DhanHQ rate limits. |
MARKET_INDEX_SPARKLINE_POINTS | 75 | Number of recent points rendered in each index tile's sparkline. |
MARKET_INDEX_DEFAULTS | 7 indices | Default NSE indices (Dhan marketfeed segment IDX_I): NIFTY_50 (13), NIFTY_BANK (25), NIFTY_NEXT50 (38), NIFTY_MIDCAP100 (37), NIFTY_SMLCAP100 (5), NIFTY_500 (19), INDIA_VIX (21). Each tuple is (key, label, segment, security_id). |
Research Strategies
Equity research subsystem configuration. Read-only backtest engine; never touches live trading. See arb_bot/research/ and docs/research_backtest.md.
| Parameter | Default | Meaning |
RESEARCH_FUNDAMENTALS_ENABLED | True | Enable fundamentals injection into market_data each rebalance (ROE, D/E, margin, FCF derived from yfinance). |
RESEARCH_FUNDAMENTALS_FILING_LAG_DAYS | 45 | Days after period_end before fundamental data is available (avoids lookahead bias on point-in-time snapshots). |
RESEARCH_MQ_MIN_ROE | 0.12 | momentum_quality: minimum ROE quality gate (12% threshold for financial health). |
RESEARCH_MQ_MAX_DE | 1.0 | momentum_quality: maximum debt-to-equity ratio (leverage cap). |
RESEARCH_MQ_QUALITY_WEIGHT | 0.5 | momentum_quality: blend weight for quality z-score vs momentum z-score (0.5 = equal). |
RESEARCH_QA_MIN_ROE | 0.15 | quality_alpha: minimum return on equity (15% threshold). |
RESEARCH_QA_MIN_ROCE | 0.15 | quality_alpha: minimum return on capital employed; approx. = ROE via yfinance derivation. |
RESEARCH_QA_MAX_DE | 0.6 | quality_alpha: maximum debt-to-equity (stricter than momentum_quality for high-quality screen). |
RESEARCH_QA_MIN_MARGIN | 0.08 | quality_alpha: minimum net profit margin (8% operational efficiency threshold). |
RESEARCH_QA_TREND_FILTER | True | quality_alpha: enable 200-SMA price trend filter (confirm uptrend before entry). |
RESEARCH_QA_TREND_SMA | 200 | quality_alpha: SMA period (days) for trend filter. |
RESEARCH_VT_MIN_PASS | 2 | value_trend: minimum value metrics ≥ universe median to qualify (E/P, B/P, S/P, div yield); requires ≥2 of 4. |
RESEARCH_VT_TREND_SMA | 200 | value_trend: SMA period (days) for trend confirmation filter. |
| pair_statarb strategy (market-neutral pairs trading) |
RESEARCH_PAIR_LOOKBACK | 120 | pair_statarb: lookback window (days) for spread z-score calculation. |
RESEARCH_PAIR_CORR_MIN | 0.8 | pair_statarb: minimum closing-return correlation to qualify as a cointegrated pair (same sector). |
RESEARCH_PAIR_Z_IN | 2.0 | pair_statarb: entry z-score threshold (|z| ≥ this triggers long/short placement). |
RESEARCH_PAIR_Z_OUT | 0.5 | pair_statarb: exit z-score threshold (mean reversion exit when |z| ≤ this). |
RESEARCH_PAIR_Z_STOP | 3.5 | pair_statarb: extreme-loss exit when |z| ≥ this (cointegration break protection). |
RESEARCH_PAIR_MAX_PAIRS | 10 | pair_statarb: maximum concurrent pairs to trade (capital split equally per pair). |
RESEARCH_PAIR_MAX_HOLDING_DAYS | 30 | pair_statarb: maximum holding period (days) — force-exit after this regardless of z-score. |
RESEARCH_SHORT_BORROW_BPS_ANNUAL | 50 | pair_statarb: annualized short-borrow cost (basis points); accrued daily on short-leg notional. |
| options_vol_premium strategy (IV-rank iron condor) |
RESEARCH_OVP_MIN_IVRANK | 0.5 | Minimum IV-rank to open an OVP iron condor (0–1) |
RESEARCH_OVP_IVRANK_LOOKBACK | 120 | Rolling window (days) for IV-rank calculation |
RESEARCH_OVP_DELTA | 0.16 | Approximate delta target for short strikes (informational) |
RESEARCH_OVP_DTE_MIN | 5 | Minimum DTE to open a new OVP position |
RESEARCH_OVP_DTE_MAX | 10 | Maximum DTE to open a new OVP position |
RESEARCH_OVP_WING_POINTS | 300 | Points from spot to short strike; wings bought same distance further out |
RESEARCH_OVP_PROFIT_TARGET | 0.5 | Close at this fraction of max credit received (0.5 = 50%) |
RESEARCH_OVP_STOP_MULT | 2.0 | Close when loss exceeds this multiple of credit received |
RESEARCH_OVP_LOT_SIZE | 50 | Contract lot size for NIFTY (units per trade) |
RESEARCH_COMBINE_MODE | off | Combination mode: off | composite (Mode A z-blend) | sleeve (Mode B) |
RESEARCH_COMBINE_MEMBERS | | Comma-separated member strategy names for combination runs |
RESEARCH_COMBINE_WEIGHTS | | Comma-separated weights aligned to RESEARCH_COMBINE_MEMBERS |
RESEARCH_EVENTS_ENABLED | True | Inject corporate-events dict into market_data on each rebalance |
RESEARCH_EVENT_LOOKBACK_DAYS | 5 | Rolling window (calendar days) for which events are visible to strategies |
RESEARCH_PEAD_MIN_SURPRISE | 0.05 | Minimum earnings surprise (fraction, e.g. 0.05 = 5 %) to trigger PEAD entry |
RESEARCH_PEAD_HOLDING_DAYS | 40 | Maximum holding period for earnings_pead positions (calendar days) |
RESEARCH_EVENT_TYPES_ENABLED | buyback,index_inclusion,pledge_reduction,block_deal,earnings | Comma-separated event types the event_driven strategy will act on |
RESEARCH_EVENT_HOLDING_DAYS | 30 | Maximum holding period for event_driven positions (calendar days) |
Backtest Config Overrides
The backtesting engine does not add live config parameters — instead it temporarily overrides existing
Config attributes per simulated cycle through a BacktestConfig proxy
(arb_bot/backtest/simulation/context.py).
- Validation up front.
BacktestConfig({...}) raises ValueError for any key that is not a real Config attribute, so a typo in a CLI/API parameter fails before simulation starts. It always forces OPTION_CHAIN_COOLDOWN = 0 so replays do not sleep between option-chain fetches.
- Disabled-strategy replay. Standalone DDC/DCS_SKEW runs, and MDC runs that may select them, temporarily set
DDC_DISABLED = False and/or DCS_SKEW_DISABLED = False inside the isolated backtest worker unless the caller explicitly supplies those keys. Live process values remain unchanged.
- Temporary, cycle-local patching. Existing scanners and exit helpers read
Config class attributes directly. Rather than refactor them, the engine wraps each historical cycle in patch.object(Config, key, value) for every validated override and restores the original class attributes when the cycle exits.
- Restoration guarantee. After every cycle the live
Config values are exactly what they were before — a unit test asserts a patched value is reverted on context exit.
- Worker-process isolation. Single runs and grid-search combinations execute in separate
ProcessPoolExecutor worker processes. Because patch.object mutates class attributes, process isolation prevents one job's overrides from being observed by another job or by the live bot process. Workers receive the database db_path (a string), never a live source or SQLite connection.
Default grid-search sweeps live in arb_bot/backtest/optimizer/param_space.py and reference only real Config keys:
| Strategy | Swept Config keys |
DC | DC_STOP_TENT_WIDTH, DC_PROFIT_TARGET_PCT, DC_STOP_PNL_PCT |
DCS / DCS_SKEW | DCS_STOP_TENT_WIDTH, DCS_PROFIT_TARGET_PCT |
DDC | DDC_STOP_LOSS_PCT, DDC_PROFIT_TARGET_PCT |
IC | IC_PROFIT_TARGET_PCT, IC_STOP_LOSS_CREDIT_X |
MDC | MDC_TREND_THRESHOLD_PCT, MDC_CALM_RANGE_PCT, MDC_WIDE_RANGE_PCT |
Backtest fill model
Two Config attributes exist solely for the backtest fill model — they have no effect on live trading:
| Parameter | Default | Meaning |
BACKTEST_SPREAD_PCT | 1.2% | Backtest fill model: full bid-ask spread as a fraction of premium. Every simulated fill pays half of it — buys fill higher, sells fill lower. Matches the Black-Scholes synthesizer's spread model. |
BACKTEST_SPREAD_MIN | ₹0.50 | Minimum full spread per leg in the backtest fill model. Set both spread params to 0 to reproduce pre-fill-model results. |