FNOTrader Algo — Help
A no-code builder for F&O algos. Author multi-leg strategies, backtest them against minute-bar history, and ship the exact same recipe to live trading through your broker. This page documents every feature in the builder, the backtest engine, and the live runtime — with worked examples for each.
Welcome
The execution engine is a standalone Go service that runs configurable multi-leg F&O strategies on your behalf. It pairs three pieces:
- A visual builder (this UI) where you describe a strategy as a recipe — no programming required.
- A backtest engine that replays the recipe against last year of minute-bar history (CE/PE OHLC + IV + OI per ATM±10 strike).
- A live runtime that ships the exact same recipe to your broker — Kite/Dhan/paper — and supervises the trade end-to-end.
Trader's mental model
WHEN some condition is true on these WATCH instruments, FIRE these legs, MONITOR them under these stop/target rules, and EXIT when this other condition is true (or at square-off time).
Builder is laid out the same way: Step 1–2 define your universe, Step 3 defines triggers, Step 4–5 define legs and risk, Step 6 defines how orders go out.
Five-minute quick-start
- Open the builder and pick a Template in Step 1 — e.g. Short Straddle. It seeds the legs for you.
- Skip straight to Step 6 → press ▶ Run Backtest. You'll get a full report in 10–20 seconds covering the last month.
- Tweak the SL/TG in Step 4 → re-run. Compare results in the Backtest History tab.
- Press 💾 Save Strategy. The recipe is now reusable in live trading too.
- From the home screen, attach the saved strategy to a Broker Account and press ▶ Start.
✨ New — build & backtest by just asking your AI
You can now simply ask Claude, ChatGPT or any AI assistant to create a strategy and backtest it using FNOTrader MCP — no Builder clicks needed. Connect once, then talk to it like a colleague:
“Backtest a NIFTY 09:20 short straddle with 30% stop-loss per leg for
2023–2025 and show me the worst days.”
“Try the same on RELIANCE. Then sweep the stop-loss at 20 / 30 / 40%
and tell me which wins on drawdown.”
The AI understands every feature in this manual — all strike-selection modes, stop types, ladders, adjustments, sweeps — and runs on the same engine, data and credits as the Backtest page. Indices and 200+ F&O stocks, plus mutual-fund research.
Get started in two minutes: mcp.fnotrader.com — see what's possible, generate your personal token, and copy-paste the setup for your AI of choice.
Colors & conventions
Badges: BACKTEST works in backtest, LIVE works in live trading, BETA accepted but not fully wired, TODO deferred.
Step 1 · Strategy identity
Three fields define what the strategy is and where it trades.
| Field | What it does |
|---|---|
| Strategy Name | Free-form label — appears in the Strategies tab, save modal, and backtest history. Autofill is disabled so the browser doesn't accidentally fill your login email here. |
| Symbol | The instrument the strategy trades. Searchable dropdown of every F&O index (NIFTY / BANKNIFTY / FINNIFTY / MIDCPNIFTY / SENSEX / BANKEX) plus every F&O stock. The chosen symbol drives ATM-strike resolution, lot-size lookup, and weekly-vs-monthly expiry eligibility. |
| Template | Pre-built recipes you can use as a starting point:
short_straddle, iron_condor,
BTST, STBT,
rolling_straddle, rolling_strangle, or
custom (blank slate). Picking one seeds Steps 4–6. |
Step 2 · Instruments to Watch
The "vocabulary" your conditions can use. Anything you name here is
readable in Step 3 conditions via ALIAS.METRIC.
Scope dropdown
| Scope | What it resolves to | Example alias |
|---|---|---|
| Spot | Underlying spot index/stock | NIFTY.CLOSE |
| Option | One specific strike + CE/PE | OPT_ATM_CE.LTP, OPT_OTM2_PE.IV |
| ATM Straddle | Sum of ATM CE + ATM PE LTPs | ATM_STRADDLE.LTP |
| Strangle | Sum of OTMn CE + OTMn PE LTPs | OTM2_STRANGLE.LTP |
| Custom Combiner | Arbitrary linear combination of legs (synthetic) | MY_SYNTH.LTP |
Per-row fields
- Alias — what you'll type in Step-3 expressions. Auto-populates
from Scope but is fully editable. Keep it descriptive
(
OPT_ATM_CEnotfoo). - Timeframe — bucket size for indicator aggregation
(1m / 3m / 5m / 15m / 30m / 1h / 1d). Drives
EMA,RSIetc. on that alias. A 5m TF meansOPT_ATM_CE.EMA(10)reads the 10-bar EMA of 5-min candles, not 10 raw minutes. - Symbol / Expiry / Strike Distance — adapt to the chosen scope.
Add Scope = Option, Alias = OPT_ATM_CE, Option Type = CE, Distance = ATM, TF = 5m. Now in Step 3A you can write:
OPT_ATM_CE.CLOSE > OPT_ATM_CE.EMA(10)
Entry only when ATM CE breaks above its own 10-bar (5m) EMA.
Step 3A · Entry conditions
Multi-row builder. Each row is one boolean clause; rows combine with AND
or OR (your choice). The full expression is evaluated every bar (or
throttled — see Check Frequency) and the
strategy enters on the first true.
Per-row fields
| Field | Purpose |
|---|---|
| Symbol | Step-1 instrument the metric reads from. Defaults to the strategy underlying. |
| Metric | Indicator to evaluate. 40+ choices — see catalog. |
| Metric args | Inline numeric inputs for parameters (e.g. EMA period, MACD fast/slow). All values are user-editable. |
| Operator | How LHS is compared (full list below). |
| RHS | A literal value, another metric on the same instrument, or an instrument — a metric on a DIFFERENT Step-1 instrument (e.g. compare ATM_CE.OI_CHG against ATM_PE.OI_CHG). |
| Change basis | Shown for *_CHG metrics. vs prev bar (default) = this bar minus the previous bar — on a 3-min instrument that IS the 3-minute change. vs day open = running change since today's first data point. vs prev day close (OI only) = change from the previous trading day's closing OI. |
Operator catalog
| Operator | Fires when… |
|---|---|
greater_than / less_than | Plain numeric comparison. |
above / below | LHS above/below a price reference (e.g. above_VWAP). |
crossing | LHS crosses RHS in either direction this bar. |
crossing_up / crossing_down | LHS crosses RHS from below / above this bar. |
moving_up / moving_down | LHS strictly increasing / decreasing N bars in a row. |
inside_channel / outside_channel | LHS is between (or outside) two RHS values. |
entering_channel / exiting_channel | Entered / left the channel this bar. |
new_day_high / new_day_low | LHS prints a fresh intraday extreme. |
range_breakout_up / _down / _either | LHS breaks above/below/either side of the opening-range high/low. Window is user-editable (Start–End times). |
Combine mode
Toggle AND (all rows must fire) or OR (any one). Rows cannot mix AND/OR within one block — for that, save two strategies and cascade them via On-Hit actions.
Check Frequency
How often the expression is evaluated:
tick— every market tick (live) / every minute-bar (backtest).every X-min bar close— only when minute-of-day mod X == 0 (e.g. 5 = 09:20, 09:25, …).
Comparing two instruments — CE vs PE OI crossover
Pick RHS mode instrument to compare one instrument's metric against
another's. The canonical intraday use: two ATM watches (ATM_CE,
ATM_PE, ATM tracking = Auto, Timeframe 3m) and a row
ATM_CE · OI Chg · Crossing Up · instrument · ATM_PE · OI Chg.
Crossings against a moving right-hand side are TRUE crossings — both sides
are read at the previous bar too, so the row is true on exactly the
crossing bar, not while one side merely stays ahead. Pairs without a
previous-bar form (e.g. IV Chg) compile as a plain level check — the
Preview always shows exactly what will run.
Already crossed at the open? Some days the two lines START the session in the crossed state (e.g. CE OI above PE OI from the very first data point) and never cross again — a pure crossing row would sit silent all day. Tick "or fire on day's 1st bar if already crossed" on the crossing row to ALSO enter on the session's first closed bar when the condition already holds there. It evaluates exactly once, on the day's first bar-close check; after that only real crossings fire. Works in live and backtest identically.
On an Auto-tracking ATM watch, a strike change resets OI continuity: the new contract's book has nothing to do with the old one's, so OI-change metrics read 0 until the new strike establishes its own baseline (prices are left untouched).
When conditions evaluate — and when entries fill
With Check Frequency every X-min bar close, the expression is
evaluated ONCE per bar, in the first second after the bar closes — never
mid-bar, never on an intrabar spike, and never against the half-formed
bar the strategy started inside. A condition fires the first time it is
true (a crossing is true for exactly one bar; a level like
LTP > 100 fires once when first satisfied). The entry
then executes immediately — effectively the next bar's open. The
backtest enforces the same discipline: signal on bar X's close → fill at
bar X+1's open (see no-lookahead-bias).
tick mode evaluates in real time, live only at tick granularity
(the backtest's floor is 1-minute bars).
Step 3B · Exit conditions
Same builder as 3A but evaluated after entry. If any exit row fires (when combine = OR) or all exit rows fire (combine = AND), the engine flattens every open leg at next bar's open.
Exit conditions compose with the per-leg SL/TG (Step 4) and Combined SL/TG (Step 5). Whichever triggers first wins — they're not mutually exclusive.
Step 3C · BTST / STBT mode
Buy-Today-Sell-Tomorrow / Sell-Today-Buy-Tomorrow. Two time pickers:
Start Time (today's entry window) and Exit Time (next
trading day's square-off). When both are set, the engine flips
overnight_hold = true and the strategy is held across the
EOD square-off boundary. Entry/Exit conditions 3A/3B remain available
but optional.
Step 3D · Overnight Protection
Carrying short option legs overnight exposes you to gap risk and higher peak margin. Overnight Protection automatically buys a protective hedge against every open short option leg at a set time (typically just before close) and sells it back at a set time the next trading morning — no manual step, and it survives engine restarts (the hedge is rebuilt from the order ledger).
Controls
| Field | What it does |
|---|---|
| Enable | Turns it on. Requires product NRML — MIS is squared off intraday, so there is no overnight to protect.📎 A short straddle on NRML gets hedged and carried; the same straddle on MIS is rejected at launch with "needs NRML". Set Product = NRML in Step 6 first. |
| Strike by | How the hedge strike is picked — always further OTM than the short. Six methods (below).📎 Short 25000 CE, spot 25000. Strike distance = 3 → buys the 25150 CE. Delta ≈ 0.10 → buys whichever strike is ~10-delta today (further out on a low-IV day, nearer on a high-IV day) so the wing cost stays roughly constant. |
| ± strikes | Extra ladder steps applied AFTER the method resolves (e.g. Max-OI + 1). Clamped so the hedge always stays beyond the short. |
| Apply at | IST time the hedges are BOUGHT (default 15:20).📎 15:20 — 10 minutes before the 15:30 close, so the wings are on and confirmed before the session ends and margin is measured. |
| Remove at | IST time they are SOLD next session (default 09:20). Weekends / holidays wait for the next trading session automatically.📎 09:20 — 5 minutes after the 09:15 open, once the opening auction settles and the gap (if any) has printed. A Friday-evening hedge simply waits and sells at Monday 09:20. |
Strike-selection methods
| Method | Picks the OTM strike… |
|---|---|
| Strike distance | N ladder steps further OTM than the short (classic). |
| Premium closest to ₹ | whose premium is nearest your ₹ target — cheap fixed-cost wings. |
| Delta closest to | whose |delta| is nearest a target (e.g. 0.10) — constant risk shape. |
| Max OI strike | carrying the highest open interest — the market's wall. |
| Straddle-width × | a multiple of the ATM straddle premium away — the market's own expected-move yardstick. |
| Underlying % away | nearest spot ± X% of the underlying. |
Step 4 · Strategy Legs
Table of legs the strategy fires. One row per leg.
Main-row columns
| Col | What it does |
|---|---|
| Idle | Leg is deferred — won't fire at entry. Activated only by another leg's execute_other_leg / enter_leg_id action.📎 Mark a BUY-CE wing Idle so it sits dormant; a short CE's SL then wakes it as an emergency hedge. |
| Hedge | Marks a protective BUY leg. Excluded from Move-SL-to-Cost and exits LAST on flatten.📎 On an iron condor, tick Hedge on both BUY wings — on a square-off the shorts close first and the wings last, so you are never momentarily naked. |
| Side | BUY / SELL |
| Fut/Opt | OPT (default) or FUT. FUT hides Type/Strike-Selection cells. |
| Type | CE or PE |
| Strike Selection | How the strike is picked — see below. |
| Strike Value | Adapts to the selection mode.📎 Distance → "OTM2"; Absolute → "24500"; Premium → "₹120"; Delta → "0.30"; Underlying → "+0.5%". The field label changes with the mode you pick. |
| Expiry | Relative (Current Weekly / Next Weekly / Current Monthly / Next Monthly) or Absolute date.📎 Current Weekly always tracks the nearest weekly expiry as weeks roll — a saved strategy stays "this week's expiry" forever without editing. Use Next Weekly to systematically trade the far expiry. |
| Qty (lots) | Multiplied by lot_size at order time.📎 Qty 2 on NIFTY (lot 75) → 150 units sent. On MCX the lot is the real contract size (e.g. CRUDEOILM = 10 barrels) and freeze limits auto-split large orders. |
| ⚙ Settings | Expands the advanced 4-tab panel. |
Strike Selection modes
| Mode | Behaviour | Backtest support |
|---|---|---|
| Distance | ATM / OTM1–15 / ITM1–15 strike steps from ATM. Most common. | ATM±10 — deeper strikes clamp to boundary with a warning. |
| Absolute | Exact strike number (e.g. 24500). | LIVE — backtest clamps to nearest archived strike with a warning. |
| Premium | Engine picks the strike whose LTP is closest to a target ₹ value. | LIVE — backtest clamp warning. |
| Delta | Target |delta| (e.g. 0.30 for ~30-delta). | LIVE — backtest clamp warning. |
| Straddle Width | Strike whose premium is N% (or N×) of the ATM straddle premium. | LIVE |
| Underlying Price | Signed % offset from spot — e.g. +0.5% on NIFTY=24000 → strike ≈ 24120. | LIVE |
Advanced (⚙) — tabbed panel
Tab 1 · Wait & Trade
Delay this leg's entry until its premium crosses a trigger price. Useful for buying weakness or selling strength after the basket has already fired.
- Wait & Trade Trigger — value + unit
(
ptsabsolute /pts_relrelative to LTP at entry /%). - 📎 Sell a CE, then Wait & Trade Trigger =
pts_rel +10→ the leg only fires once the CE trades ₹10 ABOVE its price when the basket armed — you sell strength (a bounce) instead of chasing a falling premium.
Tab 2 · Stoploss (SL1+)
| SL Type | Meaning |
|---|---|
pct | % of entry premium (e.g. 30 = 30%). |
points | Flat ₹ move from entry (e.g. 15 = ₹15 swing). |
pnl | Per-leg ₹ loss (qty-aware).📎 5000 → exit the leg once it is down ₹5,000 across its full quantity (2 lots of NIFTY = 150 units, so a ₹33/unit adverse move). |
underlying_move / _up / _down | SL trips when spot moves N points or N% in the chosen direction.📎 underlying_move_up 100 on a short CE → exit when NIFTY rises 100 pts from your entry spot, regardless of the option's own premium (a directional stop, not a premium stop). |
delta | SL trips when the leg's |delta| crosses a threshold.📎 0.60 → exit the short CE once it reaches ~0.60 delta (going deep ITM) — a moneyness-based stop that fires the same whether the move was slow or a spike. |
atr | SL = entry ± N × ATR(period). ATR source is a Step-1 watch instrument.📎 1.5 × ATR(14) → a volatility-scaled stop: it sits wider on choppy high-ATR days and tighter on calm days, instead of a fixed % that's too tight in a storm and too loose in a lull. |
SL Wait (sec) — SL breach debounce (next to the tab's Check Frequency): a breached stoploss must STAY breached for this many consecutive seconds before the exit fires; a recovery inside the window resets the timer. Ignores flash-spikes / single-tick wicks. 0 = exit on first breach. The same knob exists at basket level on the Combined Stoploss tab (Step 5).
Per-rung fields: SL Qty (% or lots), On-Hit action, Check Frequency. Add SL2 / SL3 rungs for laddered exits.
On-Hit action catalog
| Action | Effect |
|---|---|
just exit | Close the leg, do nothing else (default). |
keep_leg_running | Don't close — mark SL fired but continue holding.📎 SL1 at 30% with keep_leg_running only triggers a partial (SL Qty 50%) and holds the rest; SL2 at 50% then closes what's left — a two-rung scale-out instead of an all-or-nothing exit. |
re_execute_N_times | Close, then re-fire the same leg up to N times.📎 Short CE with re_execute 2×: SL closes it, the engine re-sells a fresh ATM CE, and can do so twice more — three total attempts to collect premium on a range day. |
close_leg_id | Also close another leg by ID (e.g. spread partner). |
enter_leg_id | Fire a leg marked Idle.📎 Sell a naked CE now; keep a BUY-CE wing marked Idle. If the CE's SL hits, enter_leg_id fires the wing — a protective hedge that only exists once you're in trouble. |
move_sl_to_cost | Move every other leg's SL to its entry price (lock breakeven).📎 On a short strangle, once the CE hits its target the PE's SL jumps to its entry price — the winning side can no longer turn into a loser. |
add_qty_pct | Scale up the leg by N% (martingale-style — use with care).📎 add_qty_pct 100 → when the short PE's SL hits, double its size at the new (higher) premium, betting on mean-reversion. Powerful and dangerous: pair it with a hard combined SL. |
execute_other_leg | Trigger another leg with optional delay (live engine cascade).📎 CE target hit → after a 30s delay, fire a fresh OTM CE sell to keep theta working on the call side while the put runs. |
execute_other_strategy | Launch a separate saved strategy.📎 A directional breakout strategy's target hit launches your "trend-continuation" saved strategy — chaining two independent recipes into one workflow. |
Tab 3 · Target (TGT1+)
Same structure as SL. Target Types include all SL types plus
r_multiple (risk-reward — target distance = N × stop distance).
Tab 4 · Per-leg Trailing
- Trail Trigger — profit ₹ threshold that arms the trail.
- Trail Step — every N₹ further profit, ratchet the stop up.
- Trail Lock — minimum ₹ locked in once trail is armed.
- Check Frequency — tick / xm_close.
Profit Lock & Trail (per leg)
₹-P&L guards on ONE leg, independent of the price trail and of its "Trailing enabled" switch. Profit Locking: when this leg's P&L reaches ₹X, a minimum of ₹Y is locked — if P&L falls back to ₹Y, the leg exits in full. Profit Trailing: every further ₹X of PEAK P&L lifts the locked floor by ₹Y. Evaluated on every tick live (a ₹ guard, like Combined SL); at bar closes in backtest.
The per-leg price trail's Trigger / Step / Lock take a unit — % of entry premium (default) or Pts (absolute premium points). The hints and "What this means" readback speak whichever unit you pick.
Step 4B · Strategy Adjustment Conditions
The engine's most powerful section — modify a LIVE position without stopping the run. Where SL/Target close a leg, adjustment rules re-strike it: roll a threatened short leg further OTM, roll a decayed winner back in, re-center a straddle when spot drifts, or delta-hedge the whole book. Each rule is a card — click + Add rule and pick its type (one rule per type; a duplicate type overrides the earlier card).
A roll closes the leg (fill-confirmed) and re-opens at the target strike off the live option chain; the new leg gets a fresh SL/Target from its own entry. Every action is journaled.
Global guards (apply to every rule)
| Guard | Effect |
|---|---|
| Min CE−PE strike gap | Inversion guard — a roll that would leave the lowest CE strike below the highest PE + gap is aborted whole. Default 100.📎 Gap = 100. A delta-hedge roll wants to push your short 25500 CE down to 25300, but the short PE sits at 25400. Post-roll the CE (25300) would be BELOW the PE (25400) — an inverted, un-manageable book. The gap rule sees 25300 < 25400 + 100 and aborts the whole roll, leaving the position untouched. |
| Auto-action limit | Max rolls/day (ALL rules share this budget) + cooldown seconds between actions. Default 3 / 60s — stops a whipsaw from churning the book.📎 3 / 60s. On a fast trend day your CE rolls at 10:05, 10:40 and 11:15 (3 rolls). At 11:20 a 4th trigger fires — it is ignored and journaled ("budget spent"), so the strategy can't roll itself to death chasing the move. Cooldown also blocks two rolls inside 60 seconds. The count resets next trading morning. |
| Only sold (short) legs | Leg-price / delta rules act on SHORT legs only by default. Uncheck to also act on bought legs.📎 ON (default). On a short strangle with protective BUY wings, a leg-price roll rule ignores the wings and only manages the sold CE/PE. Turn OFF for a LONG straddle where you actually want the rule to roll the bought legs as they move. |
Rule types
1 · Roll / exit a leg at a price level
Per-side premium trigger off each leg's own entry (% / points / absolute ₹). On breach: roll away N strikes, roll in, or exit.
2 · Price-diff band around entry (two-sided)
One band, a different action on each side: LTP ≥ entry + band fires the ▲ action; LTP ≤ entry − band fires the ▼ action.
3 · Roll / exit a leg at a delta level
The delta twin of the price rule — fires on the leg's |delta| off the live chain greeks (a short 0.45δ call is a threatened call regardless of premium). Roll by strikes, exit, or roll AWAY to a target |delta|.
4 · CE/PE divergence — winner & loser actions
Straddle/strangle only. When |CE − PE| crosses a threshold, the winner (decayed, in profit) premium-matches IN and the loser rolls AWAY — in one inversion-guarded action.
5 · Rebalance — roll the cheap side in (premium match)
Straddle/strangle only. When one side's premium reaches N× the other, the CHEAP (decayed) leg rolls IN to the strike worth ≈ the target % of the expensive side — the running side is left alone.
6 · Delta / gamma hedge — re-balance when net delta skews
Watches the whole book's net delta (Σ ±δ·qty / Σqty off the live greeks; SELL negates) — 0 when balanced, drifting toward ±1 as one side runs ITM. Two actions:
- Roll the heavy leg (default) — the side whose |delta| ran up is re-struck AWAY to match the light side's delta.
- Hedge with FUTURES — the classic hedge: BUY/SELL the front-month future against the net delta (rounded to whole lots, optional max-lots cap). It manages itself — re-balances as the book moves, unwinds when net delta falls inside half the trigger, closes with the strategy.
An optional net-gamma trigger fires the same fix earlier, before the delta itself looks bad.
7 · Spot re-center at ATM ± offset
Straddle/strangle only. When the underlying moves ≥ X% from the armed reference, close both legs and re-open at the new ATM ± offset. The reference re-bases after each fire.
Step 5 · Strategy Risk Settings (Combined)
Same shape as the per-leg advanced panel but at the basket level. Four tabs: Wait & Trade, Stoploss, Target, Trailing.
Combined SL/TG fires when the basket-level MTM (sum of all open-leg PnLs) crosses a ₹ or % threshold. On hit, the action choices include:
just exit— flatten all legs.close_current_strategy— explicit version of above.close_and_re_enter_strategy— flatten, then re-fire after a configured delay (capped by NTimes).close_all_losing/close_all_profitable— partial flatten. 📎 On a 4-leg book at +₹2,000 combined, close_all_profitable books the two green legs and lets the two red ones run for a possible recovery.close_all_ce_buys/_ce_sells/_pe_buys/_pe_sells— close by option-type + side. 📎 Spot breaks down hard → close_all_ce_sells removes only your short calls (the safe side isn't earning much anyway) and keeps the short puts + hedges working.move_sl_to_cost_profitable_legs— lock breakeven on the winners.execute_other_leg/execute_other_strategy— cascade.
SL Wait (sec) — the same debounce as the per-leg one, at basket level (next to the group Check Frequency): a breached Combined SL must STAY breached for N consecutive seconds before its action fires; if the basket MTM recovers inside the window the timer resets. Applies to every Combined SL condition (AND groups included). In backtests (1-min bars) waits under 60s are absorbed into the bar; longer waits require the breach to persist across bars.
Profit Locking & Trailing (basket)
The same two ₹ guards on the WHOLE basket's combined MTM, next to Combined Trailing: when combined P&L reaches ₹X, a floor of ₹Y is locked (and optionally lifted by ₹L per further ₹S of peak). Falling back to the floor squares off every leg. Works alongside — not instead of — the classic Combined Trailing.
Step 6 · Execution Settings
| Field | What it does |
|---|---|
| Legs Execution | parallel (all at once), sequential (fire next after prev fills), buy_first (BUYs in parallel, then SELLs after delay).📎 An iron condor with buy_first buys both protective wings first, waits Hold Sell Sec, then sells the ATM legs — so you are never even briefly naked short (and get the margin benefit immediately). |
| Hold Sell Sec | Delay between BUY batch and SELL batch in buy_first mode. Used to lock hedges before opening short exposure.📎 2 → a 2-second gap: long enough for the two wing BUY fills to confirm before the short CE/PE orders go out. |
| If Leg Fails | cancel_all / keep_placed / retry_failed (with Max Retries).📎 4-leg condor, cancel_all: if the far CE wing is rejected (illiquid), the other 3 filled legs are pulled too — you never end up holding a lopsided, unhedged book. |
| Spike Protect % | Skip entry if the basket's spread blows out beyond %.📎 5 → on a news-spike or thin open where the combined bid/ask gaps past 5%, the entry is skipped rather than filled at a bad price. It re-checks on the next bar. |
| Spread Limit % | Reject any leg whose bid/ask spread exceeds %.📎 3 → a far-OTM wing quoting 12 / 13 (≈8% spread) is rejected as illiquid; a liquid ATM leg at 100 / 100.5 (0.5%) passes. |
| Premium Gap % | Reject if the leg's LTP gapped more than % from its prior close.📎 20 → on a gap-open day, a CE that closed ₹80 and opens ₹105 (+31%) is skipped — you avoid selling a premium that has already spiked. |
| Slippage % | Cap acceptable slippage at fill.📎 1 → an order expecting ₹100 accepts fills up to ₹101 (BUY) / down to ₹99 (SELL); a worse fill is flagged as slippage-rejected. This same % is applied to entry AND exit fills in backtests. |
| Run On Days | Mon–Sun checkboxes. Strategy is paused on un-checked days.📎 Tick only Tue + Thu for a NIFTY/expiry-focused seller — the strategy sleeps Mon/Wed/Fri and only fires on your chosen days. |
| DTE Filter | Only enter when days-to-expiry matches the chosen set (discrete: pick 0,1,2…) or range (e.g. 3–7). Basis = weekly or monthly cycle. |
| Max Lots | Hard cap on total lot count across all legs.📎 10 → an exposure-sized basket that computes 14 lots is capped down to 10 — a hard ceiling on position size regardless of what the sizing math returns. |
| Exposure (₹) | Auto-size qty from capital — engine divides this by margin/lot to compute lots.📎 ₹3,00,000 on a straddle needing ~₹1.5L margin/lot → auto-sizes to 2 lots. Change your capital and the qty scales with it — no manual re-entry. |
| Order Type | MKT / LMT / LMT-BUF (limit with N% buffer off LTP).📎 LMT-BUF 0.5% on a BUY at LTP 100 places a limit at 100.5 — fills quickly but caps how far above the touch you pay (protection against a market-order spike fill). |
| Product | NRML (carry) / MIS (intraday).📎 NRML to carry a BTST straddle overnight (and to use Overnight Protection); MIS for an intraday scalp auto-squared-off at 15:25 (23:25 for MCX). |
| Send to Telegram | Mirror lifecycle events to your bot.📎 With it on, entry, each SL/target hit, every 4B roll and the square-off land as messages in your configured Telegram bot — a live audit trail on your phone. |
Step 7 · Summary & Save
A single-page English-prose recap of everything you've configured. Refresh it (↻) any time. Then ▶ Start Strategy (live), 💾 Save Strategy (reusable recipe), or Export JSON / Import JSON (share/version).
Expression language
Conditions internally compile to a small expression language. The builder writes it for you, but you can also type it directly into the Preview box (advanced).
Operators & precedence
| Class | Operators | Notes |
|---|---|---|
| Boolean | AND OR NOT | Case-insensitive; standard precedence (NOT > AND > OR). |
| Comparison | > < >= <= == != | Pair LHS metric to RHS value/metric. |
| Arithmetic | + - * / | Standard math precedence. Use parentheses freely. |
| Grouping | ( ) | Override precedence. |
Symbol resolution
Three styles, all interchangeable:
NIFTY.CLOSE— bare underlying token. Recognised symbols: NIFTY, BANKNIFTY, FINNIFTY, MIDCPNIFTY, SENSEX, BANKEX.ATM_CE.IV,OTM2_PE.OI,ITM3_CE.DELTA— relative option symbols. Strike-offset computed automatically; CE/PE explicit.LEG1.CLOSE,LEG2.IV— refers to leg #1, #2, … of this strategy.ALIAS.METRIC— any alias you defined in Step 2.
Special identifiers
| Token | Value |
|---|---|
TIME | Current bar in HHMM (e.g. TIME >= 0930). |
PREV_CLOSE | Yesterday's last bar close — persists across overnight gap. |
LAST_TICK | Tick-level LTP (not candle-level). Useful for sub-second alerts in live. |
Multi-instrument (Phase 4.6)
You can reference foreign underlyings in the same expression. Common use: trade NIFTY only when the broader market (SENSEX) also agrees.
// NIFTY straddle, only when SENSEX is trending up
TIME >= 0920 AND SENSEX.CLOSE > SENSEX.EMA(10)
Backtest data: only NIFTY and SENSEX have archived spot bars today. BANKNIFTY / FINNIFTY references compile fine but produce a warning + read as 0 (so the gate effectively never fires). Live trading is unaffected — all 6 indices stream.
Arithmetic between metrics
The evaluator supports full arithmetic between metric reads. Strike-wise PCR is the canonical example:
// Strike-wise PCR > 1.5 (puts dominate at ATM = bearish hedging)
ATM_PE.OI / ATM_CE.OI > 1.5
// Straddle premium relative to spot > 1.5%
(ATM_CE.LTP + ATM_PE.LTP) / NIFTY.CLOSE * 100 > 1.5
// Credit-spread net premium > ₹50
LEG1.LTP - LEG2.LTP > 50
Every condition row in Steps 3A/3B has an optional arithmetic
combinator between the primary metric and the operator — a small
dropdown reading — by default. Pick +, −,
×, or ÷ and a second
[Symbol] + [Metric] + [args] block appears, so you
can build composite LHS expressions like
ATM_PE.OI ÷ ATM_CE.OI > 1.5 entirely from dropdowns. The
Preview textarea is still available for power users who want to type
longer compound expressions directly.
Metrics & indicator catalog
Every metric below works on any symbol — spot, option, alias.
Price & structural
| Metric | Returns | Example |
|---|---|---|
LTP | Last traded price | OPT_ATM_CE.LTP > 200 |
OPEN / HIGH / LOW / CLOSE | Current bar's OHLC | NIFTY.CLOSE > NIFTY.OPEN |
DAY_HIGH / DAY_LOW | Intraday extreme | NIFTY.CLOSE >= NIFTY.DAY_HIGH |
PREV_CLOSE | Yesterday's last close | NIFTY.CLOSE > PREV_CLOSE |
VWAP | Volume-weighted avg price (day-anchored) | NIFTY.CLOSE > NIFTY.VWAP |
SMA(N) | Simple moving avg over N bars | NIFTY.CLOSE > NIFTY.SMA(20) |
EMA(N) | Exponential MA | NIFTY.CLOSE > NIFTY.EMA(10) |
WMA(N) | Weighted MA | NIFTY.WMA(14) |
SAR(step, max) | Parabolic SAR (defaults 0.02, 0.2) | NIFTY.CLOSE > NIFTY.SAR(0.02, 0.2) |
Momentum
| Metric | Returns | Example |
|---|---|---|
RSI(N) | Wilder RSI (0–100) | NIFTY.RSI(14) < 30 |
ROC(N) | Rate of change (%) over N bars | NIFTY.ROC(5) > 0.5 |
MACD(fast, slow) | MACD line | NIFTY.MACD(12, 26) > 0 |
MACD_SIGNAL(f, s, sig) | Signal line | NIFTY.MACD(12,26) > NIFTY.MACD_SIGNAL(12,26,9) |
MACD_HIST(...) | Histogram (MACD − signal) | NIFTY.MACD_HIST(12,26,9) > 0 |
STOCH_K(N) / STOCH_D(N, d) | Stochastic %K / %D | NIFTY.STOCH_K(14) > 80 |
ADX(N) | Average Directional Index | NIFTY.ADX(14) > 25 |
CCI(N) | Commodity Channel Index | NIFTY.CCI(20) > 100 |
WILLR(N) | Williams %R (−100..0) | NIFTY.WILLR(14) > -20 |
Volatility & channels
| Metric | Returns | Example |
|---|---|---|
ATR(N) | Avg True Range | NIFTY.ATR(14) > 100 |
BB_UPPER(N, σ) | Bollinger upper band | NIFTY.CLOSE > NIFTY.BB_UPPER(20, 2) |
BB_MIDDLE(N) | BB middle (SMA(N)) | NIFTY.BB_MIDDLE(20) |
BB_LOWER(N, σ) | BB lower band | NIFTY.CLOSE < NIFTY.BB_LOWER(20, 2) |
SUPERTREND(N, mult) | Supertrend value | NIFTY.CLOSE > NIFTY.SUPERTREND(10, 3) |
Volume / OI / CDV
| Metric | Returns | Example |
|---|---|---|
VOLUME | Bar volume | OPT_ATM_CE.VOLUME > 100000 |
OBV | On-Balance Volume | NIFTY.OBV > 0 |
OI | Open interest (options only) | ATM_PE.OI / ATM_CE.OI > 1.5 |
CDV | Cumulative delta volume (signed) | NIFTY.CDV > 0 |
BUILDUP | OI buildup tag (long/short addition/unwinding) | OPT_ATM_CE.BUILDUP == 1 |
OI_CHG | OI change vs the previous bar close (contracts). Bar-anchored: on a 3-min instrument this is the 3-minute change. | ATM_CE.OI_CHG > 8000 |
OI_CHG_PCT | Same, as % of the previous bar's OI | ATM_CE.OI_CHG_PCT > 2 |
OI_CHG_FROM_OPEN | OI change since today's first data point (the day-open basis; every *_CHG metric has a _FROM_OPEN form) | ATM_CE.OI_CHG_FROM_OPEN > 50000 |
OI_CHG_FROM_PREV_CLOSE | OI change from the previous trading day's closing OI (OI only) | ATM_CE.OI_CHG_FROM_PREV_CLOSE > 0 |
PREV_OI / PREV_OI_CHG… | Previous-bar forms — the anchors crossings compile against, so an OI crossing fires on the crossing bar only | (emitted by the builder's Crossing operators) |
Spot instruments have no OI — OI metrics on a spot watch read 0. The condition-row basis picker ("vs prev bar / vs day open / vs prev day close") writes these forms for you; you rarely type them by hand.
Option Greeks
Computed via Black-Scholes (Hull 11e) at risk-free rate 6.5%. Returned per option symbol; backtest computes on-the-fly from (spot, strike, IV, DTE).
| Metric | Returns | Example |
|---|---|---|
IV | Implied volatility (%) | ATM_CE.IV > 25 |
DELTA | Price sensitivity to spot | OPT_ATM_CE.DELTA > 0.4 |
GAMMA | Δ sensitivity to spot | ATM_CE.GAMMA > 0.001 |
THETA | Per-day time decay (₹) | OPT_ATM_CE.THETA < -50 |
VEGA | Per-1%-IV sensitivity (₹) | ATM_CE.VEGA > 20 |
Pivots, CPR, Camarilla
| Metric | Returns |
|---|---|
PIVOT_P, PIVOT_R1..R3, PIVOT_S1..S3 | Standard floor pivots |
CPR_PIVOT, CPR_TC, CPR_BC, CPR_WIDTH | Central Pivot Range bands |
FIB_P, FIB_R1..R3, FIB_S1..S3 | Fibonacci pivots |
CAM_H1..H4, CAM_L1..L4 | Camarilla bands |
TIME & PREV_CLOSE
// Window-only entry
TIME >= 0925 AND TIME < 1100
// Gap-up open
NIFTY.OPEN > PREV_CLOSE * 1.005
Backtest engine
Replays your saved strategy against minute-by-minute history — years of option prices (open/high/low/close), implied volatility and open interest for strikes around the money, plus the index itself. Hit ▶ Run Backtest on any saved strategy; reports are persisted to Backtest History.
External signals — backtest a TradingView strategy (or any signal list)
The Backtest tab has an optional Entry signals row (below the main settings). Upload a CSV of timestamped entry/exit signals and the backtest fires your strategy only when the file says so — your SuperTrend / Pine-script / Python / Excel logic decides when, while everything you built in the Builder decides what: legs, strikes, expiry, SL/Target, trailing, square-off. It works in Single-strategy, Portfolio and Parameter-sweep runs, and costs the same credits as a normal backtest.
Two accepted file formats
- TradingView export, as-is. Put your strategy (not just an indicator) on the chart → Strategy Tester → List of Trades → Export data. Upload the downloaded CSV without editing. Rows TradingView marks as still-open ("Open") are skipped automatically, and a re-exported file's duplicate rows are de-duplicated.
- The template ("Download the template" link) for hand-written or
program-generated signals. Two columns matter —
Date and time(IST, 24h,YYYY-MM-DD HH:MM) andSignal; a third Notes column in the template documents everything and is ignored by the upload.
Signal types
A signal row is a pure entry or exit event — the engine never reads a direction out of it and never changes your strategy's legs because of it. The long/short tag is only a label you can filter on:
| Signal value | Code | Meaning |
|---|---|---|
ENTRY / EXIT | E / X | Untagged entry / exit — counts in every "Use rows" mode. |
LONG ENTRY / LONG EXIT | LE / LX | Entry / exit tagged as the long side of your signal system. |
SHORT ENTRY / SHORT EXIT | SE / SX | Entry / exit tagged as the short side. |
Word order and case don't matter (Entry Long,
exit_short, close long all work). Every entry
needs an explicit exit row — an opposite-side entry does not imply one.
This is the same E/X/LE/LX/SE/SX taxonomy the live Signals page
(webhooks) uses, so a system you backtest from a file can go live on a
webhook unchanged.
The "Use rows" filter
- All signals (default) — every row drives the run.
- Long only — only
LONG ENTRY/LONG EXITrows are used. - Short only — only
SHORT ENTRY/SHORT EXITrows.
Untagged ENTRY/EXIT rows pass every filter. Build
the strategy for the side you want, then pick the matching rows. Example — a
SuperTrend stop-and-reverse export: run a BUY CE strategy with
Long only (holds a call through the long stretches) and a
BUY PE strategy with Short only (holds a put through the
short stretches).
How the gate actually fires
- The signal is a state, not a one-bar event: it is ON from an entry row until the next exit row — riding overnight if the file holds overnight. A signal that fired at 09:05 still admits an entry when your strategy's window opens at 09:20; a position squared off at day-end re-enters next morning while the state is still ON.
- Built with an External Signal condition? If the strategy's entry
(or exit) conditions contain the Builder's External Signal row, the
file drives that exact
SIGNALterm inside your composition — e.g.(TIME ≥ 09:20) AND SIGNAL AND (LTP > VWAP)replays verbatim, so you can gate the signal with time windows and price conditions. - No SIGNAL condition? The gate wraps the whole entry automatically: entry = signal ON AND your entry conditions; exit = signal OFF OR your exit conditions.
- Entries fill at the next bar's open after the combined condition turns true (the engine's standard no-lookahead rule); exits, SL, Target, trailing and square-off all keep working exactly as configured — a stop can close you out while the signal is still ON.
- The engine remains one entry-cycle per day per strategy (plus your configured re-entries), and the report's rules header + warnings strip always state how many signal events were used and which rows.
Backtest vs Live — what matches, what doesn't
| What you build | Backtest | Live / Forward | Plain-English note |
|---|---|---|---|
| Entry & exit conditions (time, price, indicators) | ✓ | ✓ | Same rules, same trigger logic. |
| Per-leg SL / Target / Trailing (ladders) | ✓ | ✓ | Every rung replays; intrabar-SL fills stops off the bar's high/low. |
| Combined (basket) SL / Target / Trailing | ✓ | ✓ | Same basket-MTM maths. |
| Re-entry, spike guard, gap gate, DTE, run-on-days | ✓ | ✓ | All top-of-day gates apply identically. |
| Strike selection (Distance / Premium / Delta / Straddle / Underlying %) | ✓ | ✓ | Dynamic strikes resolve off the same greeks — deep OTM clamps to ATM±10 in backtest. |
| External signals (SIGNAL condition) | ✓ | ✓ | Backtest drives it from an uploaded CSV; live from the Signals page's webhook — same E/X/LE/LX/SE/SX taxonomy. |
| BTST / STBT overnight hold | ✓ | ✓ | Position rides the gap; exits next morning at your time. |
| Overnight Protection (auto-hedge) | ✓ | ✓ | All six strike methods — only for overnight (BTST/STBT) strategies. |
| 4B adjustment rules — roll actions | ✓ | ✓ | Rolls close & re-open at the target strike, per bar. |
| Delta hedge — FUTURES action | ✗ | ✓ | The archive has no futures bars, so futures hedging can't be replayed (the delta roll action does). |
| Alert-only rules (auto = off) | ✗ | ✗ | They don't place orders anywhere — nothing to simulate. |
| Costs & slippage | ≈ | ✓ | Backtest uses your flat ₹/leg + slippage%; live is your broker's actual charges. |
| Order fills | ≈ | ✓ | Backtest fills at the bar's open/close; live gets real fills — partial fills, freeze-splits and the odd rejection happen only live. |
| Timing resolution | ≈ | ✓ | Backtest = 1-minute bars; live = ~1-second ticks. Live can act up to a bar sooner, never later. |
| Instruments with history | ≈ | ✓ | Only NIFTY & SENSEX are backtestable. BANKNIFTY, FINNIFTY, stock F&O and MCX have no backtest data — use a paper Forward Test. |
| Marketplace, copy trading, credits/billing | ✗ | ✓ | Live-only features — not part of a replay. |
What's loaded
- Spot bars for the primary underlying (NIFTY / SENSEX) + every foreign underlying referenced in expressions (Phase 4.6).
- Option bars (CE/PE OHLC + IV + OI) for the strike offsets the
strategy needs — folded from per-leg Distance + any
ATM_CE/OTM2_PEtokens in the entry/exit expressions. - The day's ATM strike, expiry and days-to-expiry.
On-the-fly Greeks
The archive carries OHLC + IV + OI but not Δ Γ Θ Vega. The engine computes them per-minute from (spot, strike, IV, DTE) via Black-Scholes. Theta ticks down throughout the day as DTE shrinks. Verified by 7 unit tests including ATM sanity, deep ITM/OTM bounds, Γ-peak-at-ATM, vega-peak-at-ATM, garbage-input guards, and put-call parity at 1e-9 precision.
Multi-instrument
Expression tokens like SENSEX.RSI(14) in a NIFTY backtest
transparently load SENSEX spot bars in lock-step. Unsupported foreign
underlyings (BANKNIFTY, FINNIFTY, MIDCPNIFTY, BANKEX) surface a clear
Warnings entry instead of silently zeroing — see
multi-instrument.
No-lookahead-bias
Common backtester bug: signal fires at bar X's close and "fills" at bar X's open. That's physically impossible — the open already happened 60s before the close existed — and inflates results.
This engine enforces a 1-bar defer: indicator signal at bar X → fill at bar X+1's OPEN. The rule applies to entry, exit_condition, per-leg SL/TG, AND combined SL/TG.
Pure-TIME strategies (no bar data read) still fill same-bar — no lookahead since no bar was consulted to decide.
Friction model
Two knobs in the Run-Backtest dialog:
- cost_inr_per_leg — flat ₹ deducted per round-trip (brokerage + STT + exchange + GST + stamp). Typical ₹50–80 for NIFTY.
- slippage_pct — adverse fill at entry and exit. SELL at mid×(1−slip%) on entry, mid×(1+slip%) on exit; BUY direction reverses. You pay both sides.
The report has 3 tabs: Plain, Costs only, +Slippage — so you can see the friction sensitivity instantly.
Check Frequency throttle
Honored independently per surface: entry expression, exit expression, per-leg SL1/SL2/TGT1/TGT2/Trail, and combined SL/TG/Trail. You get three modes:
tick— every minute bar.every_xm— N-min interval from StartHHMM.xm_close— minute-of-day grid (MM mod N == 0).
Use this to model "evaluate SL only on 5-min close" or "Combined SL every minute, per-leg SL every 5 minutes" mixtures.
Strike clamp at ATM±10
The archive only has ATM±10 strike data. Out-of-range legs are clamped to the boundary (with a warning) — never silently skipped. Live trading uses the exact strike you specified.
You'll also see a clamp notification toast in the Builder when:
- You pick a Distance outside ATM±10 (OTM12, ITM15, etc.).
- You pick any dynamic mode (Premium / Delta / Absolute / Straddle / UndPrice) — since the resolved strike is unknown at build time.
Report & History
Every backtest produces:
- Daily P&L list with trade-by-trade detail, ATM, skip reasons.
- Headline stats — total PnL, win rate, day count, best/worst day, max drawdown, avg daily.
- Monthly calendar — hedge-fund-style P&L heat-map.
- Equity curve + running drawdown chart (TradingView Lightweight Charts).
- Strategy rules header — exact entry/exit/SL/TG echoed back.
- Warnings panel — strike clamps, unsupported metrics, missing data, and a line describing exactly which advanced features were simulated (overnight carry, protection hedges, adjustment rules).
Every run is persisted to Backtest History — a professional table you can filter by strategy/symbol/result, with one-click 🧪 Forward test and 🚀 Deploy live on each row.
Parameter sweep — variants, not clones
On the Backtest page, tick Parameter sweep to compare tweaks of ONE strategy without saving a copy per tweak. The composer mirrors the sections your strategy actually configures — each leg's Stoploss row (type / value / then / then) and the enabled Adjustment rules — using the builder's own controls. Change any combination, name it, + Save as variant. Variants persist on the strategy, so the same comparison re-runs later on any date range.
- The run replays the original as the baseline plus every ticked variant; results sort best-P&L first with each variant's changes and its delta vs the original, and each row opens its full report.
- Use this applies the winning variant's settings onto the strategy itself — what won the backtest is what trades, live and in forward test. No cloned strategies.
- Credits: 1 per year of range × runs (original + variants) — quoted on the button before you click.
Live trading · broker adapters
| Adapter | Status | Use case |
|---|---|---|
| stub | READY | No real orders. Lifecycle / smoke tests. |
| paper | READY | Fills at current LTP from quote feed. Realistic dry-run with live data. |
| kite | READY | Zerodha — real orders on the assigned broker account. |
| dhan | READY | Dhan — real orders on the assigned broker account. |
Strategy lifecycle
- Start — registry spawns a supervised goroutine for the strategy.
- Wait for entry — evaluates entry condition every tick (or per check_freq) until firing.
- Resolve strikes — uses the per-leg strike-selection mode (Distance / Premium / Delta / OI-based / etc.).
- Fire legs — atomically, per execution-mode (parallel / sequential / buy-first).
- Monitor — quote feed per leg → per-leg SL/TG → combined SL/TG → trail SL — all gated by their own check_freq.
- Exit — on SL/TG hit, exit-condition fire, sqoff time, or kill-switch.
- Settle — records realised P&L, updates daily-loss counters, marks strategy complete.
Leg execution modes
parallel— all legs fired concurrently (default).sequential— wait for leg N to fill before firing leg N+1.buy_first— all BUY legs in parallel; wait HoldSellSec; then all SELL legs. Locks hedges before opening short exposure.
Fail policies when any leg fails to fill:
cancel_all— square off any filled legs and abort.keep_placed— proceed with the partial basket.retry_failed— retry up to MaxRetries before falling back to cancel_all.
On-Hit actions
Fire on SL or TGT events at the leg level (Step 4 → SL/TGT tabs) or the basket level (Step 5 → Combined SL/TGT). See the Step 4 action catalog for per-leg; basket-level actions are listed in Step 5. All actions can chain and most carry a delay parameter for staged behaviour.
Hedges & Move-SL-to-Cost
- IsHedge flag (checkbox on a leg) — that leg is excluded from Move-SL-to-Cost and is exited last when flatting the basket. Use on BUY legs that protect a SELL.
- Move-SL-to-Cost (Combined SL action) — once profitable legs cross a threshold, move every other (non-hedge) leg's SL to its entry price. Locks breakeven on the open legs.
Risk gate
| Setting | Effect |
|---|---|
| Max Daily Loss | Kill switch — once realised P&L for the day drops below this, no new entries fire (across all strategies). Resets at IST midnight. |
| Max Daily Trades | Cap on entry count per day. |
Webhook entry (OnSignal)
Get a private token from the Webhook page. POST to
/api/webhook/signal/{token} with no body — the token is
the auth. The configured saved-strategy fires immediately. Useful for
TradingView / Python alerts / external scanners.
curl -X POST https://your-engine/api/webhook/signal/AbC123xyz
Telegram notifications
Tick Send to Telegram in Step 6 to mirror every lifecycle event
to your bot — entry fills, SL/TG hits, leg closes, re-entries,
auto-hedge applied. Configure bot_token + chat_id
in config.yml. Buffered, non-blocking, Markdown-formatted.
Signals · repeat policy (ignore vs pyramid)
A webhook sender can retry or double-fire. Each Signal chooses what a REPEAT same-side entry does while that strategy is already live on that broker: with Pyramid on repeat signals unticked (the default), the repeat is ignored and logged in the signal log — your position cannot be multiplied by a duplicated alert. Ticked, each repeat ADDS another position up to Max positions (a ceiling always applies). A same-side check is side-aware: a Short Entry while a long is open is a reversal, not a repeat, and still fires. Exit signals always close every matching run.
Deployments & mornings
- Only logged-in & enabled brokers can be assigned. The Assign picker offers an account only when it can actually place an order right now; hidden accounts are counted with a note pointing at the Brokers page.
- 08:45 IST pre-open check. On trading days, everyone holding a live deployment gets an email (and WhatsApp, when your 24-hour window is open) listing each deployment and whether its broker is ready — with time to log in before 09:15.
- A blocked launch says why. If the broker is still logged out at launch time, the deployment shows an amber ⚠ with the reason, and the strategy launches by itself the moment the broker is ready.
- No late auto-entries. If the entry time has already passed by the time the broker is ready, the strategy is NOT auto-started for the day — a late entry at a different price is your call, via ▶ Run now.
- Deployment log. The pre-open check, blocked launches and skipped late starts are all recorded per strategy and per portfolio — visible in Logs even on days no run was created.
Strategy recipes
Fifteen worked examples covering the breadth of features. Each is a complete spec you can paste into the builder.
R1 · Short Straddle Beginner
TIME >= 0920SELL CE · ATM · 1 lot · SL 30% · TG 50%
R · Protected BTST straddle Intermediate
SELL CE ATM · 1 lot
R · Self-managing short straddle Advanced
TIME >= 0920 · SELL ATM CE + PERebalance at 2.5× → cheap side to 80%
Leg-price roll-away at +60% (backstop)
R2 · Iron Condor with hedges Beginner
TIME >= 0920SELL CE ATM · SL 30% · TG 50%
BUY PE OTM3 · Hedge ✓
BUY CE OTM3 · Hedge ✓
R3 · EMA-crossover long CE Beginner
TIME >= 0925 AND OPT_ATM_CE.CLOSE > OPT_ATM_CE.EMA(10)R4 · Range Breakout strangle Intermediate
NIFTY.CLOSE range_breakout_either (window 09:15–10:00)R5 · PCR-gated straddle Intermediate
Row 2: ATM_PE · OI · ÷ · ATM_CE · OI · > · 1.5 (use the arithmetic ÷ between the two metrics)
Compiled:
TIME >= 0930 AND (ATM_PE.OI / ATM_CE.OI) > 1.5
R6 · IV-filtered iron fly Intermediate
TIME >= 0920 AND ATM_CE.IV > 18R7 · BTST overnight strangle Intermediate
R8 · Cross-index gate Advanced
TIME >= 0920 AND SENSEX.CLOSE > SENSEX.EMA(10)R9 · Delta-gated CE seller Advanced
TIME >= 0920 AND ATM_CE.DELTA > 0.4 AND ATM_CE.DELTA < 0.6R10 · Multi-level SL ladder Advanced
just exit · check freq tickmove_sl_to_cost on remaining · check freq 5m closeR11 · Combined SL kill-switch + re-enter Advanced
close_and_re_enter_strategy · delay 300s · NTimes 2R12 · 5m TF indicator + 1m execution Advanced
OPT_ATM_CE.CLOSE > OPT_ATM_CE.EMA(10)R13 · ATM CE/PE OI crossover → buy PE Intermediate
ATM_CE and ATM_PE — Option (single strike) · Relative → ATM · ATM tracking Auto · Timeframe 3mATM_CE · OI · Crossing Up · instrument · ATM_PE · OI — true on exactly the bar where CE open interest crosses above PE open interestR14 · OI-Chg crossover — 3-minute flow flip Advanced
ATM_CE · OI Chg · (vs day open) · Crossing Up · instrument · ATM_PE · OI ChgR15 · Multi-timeframe Supertrend BUY / SELL Intermediate
SPOT (NIFTY) at Timeframe 5m and SPOT at 15m — the builder auto-suffixes them to SPOT_5M and SPOT_15M so each is addressable separatelySPOT_5M.CLOSE > SPOT_5M.SUPERTREND(10,3)SPOT_15M.CLOSE > SPOT_15M.SUPERTREND(10,3)< and BUY the PE (or SELL the CE) — same structure, opposite side.Known limits
- Backtest strike range — ATM±10 only. Beyond that, legs clamp with a warning. Live trading unaffected.
- Backtest spot underlyings — NIFTY, SENSEX and BANKNIFTY have archived spot bars. FINNIFTY / MIDCPNIFTY / BANKEX references warn and read 0 in backtests. Live trading unaffected.
Glossary
| Term | Meaning |
|---|---|
| ATM | At-the-money. Strike closest to current spot. |
| ATM±N | N strike steps away from ATM (typically 50pt for NIFTY, 100pt for BANKNIFTY). |
| OTM | Out-of-the-money. CE strike > spot, or PE strike < spot. |
| ITM | In-the-money. Opposite of OTM. |
| DTE | Days to expiry. |
| MTM | Mark-to-market — current unrealised P&L. |
| NRML | Carry-forward (overnight) product. |
| MIS | Intraday product — must square off by 15:25 IST. |
| PCR | Put-Call Ratio. OI(PE) / OI(CE) — at a strike or aggregated. |
| IV | Implied Volatility (%). |
| VWAP | Volume-Weighted Average Price (day-anchored). |
| Lookahead bias | Backtester bug where a signal fills at a price that didn't yet exist when the signal computed. |
| Combined SL/TG | Basket-level stop/target on the sum of all open-leg PnLs. |
| Move-SL-to-Cost | Action that moves every other leg's stop to its entry price (lock breakeven). |
| BTST / STBT | Buy-Today-Sell-Tomorrow / Sell-Today-Buy-Tomorrow — overnight hold. |
| Hedge leg | A BUY leg flagged to cap basket loss; excluded from Move-SL-to-Cost; exits last. |
| Idle leg | Leg that doesn't fire at entry — activated only by another leg's execute_other_leg action. |
FAQ
Why are my backtest trades different from yesterday's run?
Most likely you tweaked something in the Builder, or the engine received a lookahead-bias fix / Greeks fix / TF-fix in a recent release. If the recipe is unchanged and pre-dates a fix, results should diverge — the older results were quietly wrong.
My strategy never enters in backtest. Why?
Check the Warnings panel of the report. Common reasons:
- Foreign underlying referenced but unarchived (e.g. BANKNIFTY).
- Out-of-archive strike (Distance > ATM±10 or Premium/Delta/etc. resolving outside).
- Entry condition that depends on an indicator that hasn't warmed up
yet — e.g.
EMA(200)with only ~50 bars in history.
Why is my entry timing one bar later than my signal?
That's the lookahead-bias guard working as intended — see No-lookahead-bias. Pure-TIME entries don't defer; only indicator-driven entries do.
How do I compute strike-wise PCR?
Pick the primary metric (e.g. ATM_PE · OI), then choose
÷ from the arithmetic-combinator dropdown in the same row,
then pick the second metric (ATM_CE · OI). Set the operator
to greater than and the RHS value to 1.5. The
Preview compiles to (ATM_PE.OI / ATM_CE.OI) > 1.5 and the
backtest/live engine evaluates it natively — no special PCR metric needed
because the same UI supports any ratio / sum / difference / product of two
metrics.
What's the difference between "tick" and "xm_close" check freq?
tick evaluates every minute bar. xm_close only
evaluates on bars whose minute-of-day mod X is zero — so 5m_close fires
at 09:20, 09:25, 09:30, … and ignores the bars between. Use xm_close
to model "candle-close confirmation" entry/exit logic.