Expecting a strong upward move in the market? The Bull Call Ratio Backspread strategy is designed for scenarios where the underlying asset is likely to rally sharply. By combining a greater number of long call options with fewer short calls, this strategy allows traders to benefit from significant upside moves while maintaining controlled downside risk through structured position sizing, predefined exits and disciplined risk management.
In this blog, we’ll break down the mechanics of the Bull Call Ratio Backspread, discuss entry and exit criteria, outline key risk management considerations and explain how this strategy performs under different market conditions.
Understanding the Bull Call Ratio Backspread Strategy
The Bull Call Ratio Backspread is a multi-leg options strategy constructed using call options. It is typically established for a net credit or small net debit and is designed to profit from a strong bullish breakout accompanied by rising volatility.
The strategy benefits from:
-
sharp upward price movement
-
volatility expansion
-
limited or manageable downside risk (depending on structure)
Structure of a Bull Call Ratio Backspread
The classic structure involves:
-
Sell 1 At-the-Money (ATM) Call Option
-
Buy 2 Out-of-the-Money (OTM) Call Options
(Ratios can vary, but 1:2 is the most common.)
How the Bull Call Ratio Backspread Strategy Works
1. Entry Criteria
Eligible Markets: The Bull Call Ratio Backspread is best suited for markets where a strong bullish move and potential volatility expansion are expected. It performs particularly well when the underlying is likely to break out sharply to the upside.
Ideal instruments include:
-
Indices: NSE’s NIFTY 50, FIN NIFTY, and US-based indices such as the S&P 500 (SPX) and Nasdaq 100 (QQQ).
-
Stocks: Liquid large-cap stocks with deep options markets, such as AAPL, MSFT, NFLX, and JNJ.
Trade Trigger & Signal Conditions: To improve trade quality and avoid entering during low-momentum phases, the Bull Call Ratio Backspread is initiated only when bullish breakout conditions are confirmed in the underlying.
Primary entry conditions:
-
The underlying closes above the previous 15-minute high with a small buffer to avoid false breakouts.
-
The underlying price remains above the 20-period EMA, indicating bullish intraday trend support.
-
No active position is currently open in the strategy.
This dual-filter approach ensures the strategy participates primarily in environments with fresh upside momentum and supportive trend structure, which are critical for backspread profitability.
Strike Price Selection: The Bull Call Ratio Backspread is typically constructed by selling an ATM call and buying multiple OTM calls for leveraged upside exposure. Strike selection plays a critical role in shaping the payoff profile:
-
Closer OTM Long Calls: Results in a higher probability of profit on moderate upward moves but may reduce the net credit (or increase the debit).
-
Farther OTM Long Calls: May allow entry at a net credit and delivers stronger convex payoff on sharp rallies, but requires a more significant upward move to realize full profitability.
Expiry Selection: Expiry choice influences both the sensitivity to time decay and the ability to capture large directional moves:
-
Weekly Expiry: Suitable for short-term breakout trades where an immediate sharp move is anticipated. However, rapid time decay and gamma risk must be monitored.
-
Monthly Expiry: Provides more time for the bullish move to materialize, with smoother position behavior and reduced time decay pressure.
Lot Size & Positioning: Position sizing should align with the trader’s risk tolerance and capital allocation. While the strategy offers unlimited upside potential, the downside risk (if structured for a net debit) is limited to the net premium paid. Proper sizing ensures the trade remains within acceptable drawdown limits during sideways or mildly bearish conditions.
Timeframes: The Bull Call Ratio Backspread can be deployed across multiple timeframes, typically ranging from 1 to 60 minutes for systematic setups.
-
Lower timeframes enable precise breakout entries and active trade management.
-
Higher timeframes are better suited for capturing larger directional moves.
For intraday breakout strategies, the 1-minute timeframe can be effective when combined with strict entry filters and disciplined risk controls.
2. Exit Rules & Re-Entry Strategy
The Bull Call Ratio Backspread follows well-defined exit and re-entry rules to manage risk while remaining responsive to strong directional moves.
The strategy exits an active position under the following scenarios:
-
Profit Target Reached:
The position is closed when the predefined profit target is achieved based on the net premium or mark-to-market gains. This allows profits from sharp bullish moves to be systematically locked in rather than left exposed to reversals. -
Stop-Loss Triggered:
If the strategy’s net premium or mark-to-market loss breaches the configured stop-loss threshold, all legs are exited to contain downside risk. This is particularly important in scenarios where the underlying remains range-bound or moves mildly against the expected bullish direction. -
Underlying Price Adverse Movement:
The position may be exited if the underlying fails to show the expected bullish follow-through or moves below a predefined support or invalidation level. This helps avoid capital being tied up in stagnant or weakening market conditions.
Re-Entry Logic
Re-entry is initiated only when fresh bullish momentum is re-established after a prior exit. Following a stop-loss, profit booking, or invalidation exit, the strategy updates its reference price and enters a cooldown phase to avoid repeated trades during choppy market conditions.
After the cooldown period, the system waits for the underlying to once again satisfy the primary breakout conditions:
-
The underlying closes above the updated previous 15-minute high with the defined buffer.
-
The price remains above the 20-period EMA, confirming continued bullish trend support.
-
No active position is currently open.
Once these conditions are met, a new Bull Call Ratio Backspread is established around the updated price zone.
This structured approach ensures that re-entries occur only when fresh upside momentum and trend alignment are present, helping the strategy avoid overtrading during range-bound or indecisive market phases.
Alternative Exit Strategies
-
Trailing Stop-Loss:
Instead of a fixed stop-loss, a trailing stop-loss can be applied at the strategy level. As the position moves into profit during a strong rally, the stop dynamically adjusts upward to lock in gains while preserving upside participation. If the trailing threshold is breached, all open positions are exited. -
Partial Profit Booking:
Traders may optionally scale out of a portion of the long call exposure once predefined profit conditions are met, while keeping the remaining structure active to participate in further upside expansion. -
Time-Based Exit:
Positions may be closed after a predefined portion of the expiry cycle has elapsed, particularly if the expected breakout has not materialized. This helps manage theta exposure and frees capital for higher-conviction opportunities.
![]() |
|---|
| Figure 1: Bull Call Ratio Backspread Strategy Execution Flowchart (Values align with the first sample in the upcoming Profit & Loss Calculations section). |
This section details the Python implementation of a Short Iron Butterfly strategy with fixed strike spacing and automated re-entry logic.
Selecting Instruments and Strikes for Entry
def strategy_select_instruments_for_entry(self, candle, instruments_bucket):
selected_instruments, meta = [], []
for instrument in instruments_bucket:
self.logger.debug(
f"Checking entry conditions for base instrument: {instrument} | "
f"Determining ATM/OTM option instruments and verifying if CE orders are already placed."
)
# Skip the instrument if active order already exists
if self.child_instrument_main_orders.get(instrument):
continue
# Retrieve LTP of the base instrument to setup child instruments
base_instrument_ltp = self.broker.get_ltp(instrument)
# Track re-entry count for this instrument
re_entry_count = self.re_entry_count.get(instrument, 0)
# If re-entry count exceeds the allowed limit, skip further re-entries
if re_entry_count >= self.re_entry_limit:
continue
# otherwise increment re-entry count
else:
re_entry_count += 1
leg_wise_list = [
(BrokerOrderTransactionTypeConstants.BUY, OptionsStrikeDirection.ATM.value, 0),
(BrokerOrderTransactionTypeConstants.SELL, OptionsStrikeDirection.OTM.value, self.no_of_otm_strikes_leg_sell)
]
hist_data = self.get_historical_data(instrument)
ema = talib.EMA(hist_data['close'], timeperiod=self.time_period)
self.logger.debug(f"Latest candle close: {hist_data['close'].iloc[-1]} | Previous candle high: {hist_data['high'].iloc[-2]}")
if hist_data['close'].iloc[-1] > hist_data['high'].iloc[-2] and self.utils.crossover(hist_data['close'], ema) == 1:
for action, strike_direction, no_of_strikes in leg_wise_list:
self.options_instruments_set_up_all_expiries(instrument, 'CE', base_instrument_ltp) # Set up option instruments for available expiries
child_instrument = self.get_child_instrument_details(instrument, 'CE', strike_direction, no_of_strikes) # Retrieve ATM/OTM child instrument details for the given instrument
# Map the base instrument to its corresponding child instrument in the instruments' mapper. This allows tracking of relationships between base and child instruments for further processing.
self.instruments_mapper.add_mappings(instrument, child_instrument)
selected_instruments.append(child_instrument)
meta.append({"action": action, "base_instrument": instrument, "strike_direction": strike_direction})
return selected_instruments, meta
Code Explanation:
1. Skipping Instruments with Active Positions
-
Before evaluating entry conditions, the strategy ensures that no active orders already exist for the base instrument.
-
This prevents:
-
Overlapping positions
-
Duplicate entries
-
Uncontrolled exposure
-
-
Only instruments with no active position are considered for fresh entry.
2. Fetching Underlying Price Once
The latest traded price (LTP) of the base instrument is retrieved once and reused across strike calculations.
Benefits:
- Ensures all legs are aligned to the same price snapshot
- Reduces unnecessary broker/API calls
- Prevents minor inconsistencies in strike selection
3. Re-Entry Control Logic
re_entry_count = self.re_entry_count.get(instrument, 0)
if re_entry_count >= self.re_entry_limit:
continue
else:
re_entry_count += 1
-
This mechanism limits how many times the strategy can re-enter per base instrument.
-
Logic flow:
-
If the re-entry limit is already reached → skip instrument
-
Otherwise → increment counter and proceed
-
-
This ensures:
-
Controlled re-entry frequency
-
Avoidance of repeated entries during choppy conditions
-
Systematic capital protection
-
-
Unlike the earlier implementation, this version increments the re-entry counter only when conditions are about to be evaluated, making it slightly more conservative.
4. Leg Definition in a Data-Driven Format
-
This structure defines all legs programmatically instead of hardcoding each leg’s logic.
-
Each tuple specifies:
-
Transaction type (BUY / SELL)
-
Strike direction (ATM / OTM)
-
Strike distance
-
-
This design:
-
Makes the strategy modular
-
Allows strike adjustments without rewriting logic
-
Enables easy scaling to multi-leg structures
-
5. Entry Condition: Breakout + EMA Confirmation
hist_data = self.get_historical_data(instrument)
ema = talib.EMA(hist_data['close'], timeperiod=self.time_period)
if hist_data['close'].iloc[-1] > hist_data['high'].iloc[-2] and self.utils.crossover(hist_data['close'], ema) == 1:
-
This is the core entry filter.
-
Two conditions must be satisfied:
-
Breakout Condition
- Latest close > previous candle’s high
- Confirms price breakout
-
EMA Crossover Confirmation
- Close crosses above EMA
- Confirms bullish momentum
-
-
This dual filter ensures:
- Structural breakout
- Trend confirmation
- Reduced false signals
-
Entry is triggered only when both price action and trend alignment agree.
6. Option Chain Setup Before Strike Selection
-
Before selecting strikes, the system ensures option instruments for all expiries are initialized and cached.
-
This guarantees:
-
Valid strike availability
-
Correct expiry selection
-
Reliable instrument lookup
-
-
It acts as a preparation step before constructing the option legs.
7. Strike Selection via Directional Rules
child_instrument = self.get_child_instrument_details(
instrument, 'CE', strike_direction, no_of_strikes
)
-
Strike selection is dynamic and based on:
-
Underlying price
-
Strike direction (ATM / OTM)
-
Number of strikes away
-
-
This builds the multi-leg option structure programmatically rather than manually selecting symbols.
8. Instrument Mapping and Execution Metadata
self.instruments_mapper.add_mappings(instrument, child_instrument)
selected_instruments.append(child_instrument)
meta.append({
"action": action,
"base_instrument": instrument,
"strike_direction": strike_direction
})
-
Two outputs are prepared:
- selected_instruments
The actual option instruments to execute trades on. - Meta
Context information for each leg, including:-
Action (BUY / SELL)
-
Base instrument reference
-
Strike type
-
- selected_instruments
-
This separation allows the execution engine to:
-
Place correct order types
-
Track leg relationships
-
Maintain structured order management
-
Creating an Order for a Position
def strategy_enter_position(self, candle, instrument, meta):
child_instrument = instrument
base_instrument = self.instruments_mapper.get_base_instrument(child_instrument)
current_ltp = self.broker.get_ltp(child_instrument)
multiplier = 1 if meta["strike_direction"] == OptionsStrikeDirection.ATM.value else 2
qty = self.number_of_lots * child_instrument.lot_size * multiplier
_order = self.broker.OrderRegular(instrument=child_instrument, order_transaction_type=meta['action'], price=current_ltp, order_code=self.order_code, order_variety=BrokerOrderVarietyConstants.LIMIT, quantity=qty)
# Store details of successful orders
if check_order_placed_successfully(_order):
self.child_instrument_main_orders.setdefault(base_instrument, {})[meta['action']] = _order
else:
# Protection logic incase any of the legs fail to get placed - this will help avoid having naked positions
self.logger.critical('Order placement failed for one of the legs. Exiting position for other leg, if possible and stopping strategy.')
self.exit_all_positions_for_base_instrument(base_instrument)
raise ABSystemExit
return _order
Code Explanation:
1. Dynamic Quantity Multiplier Based on Strike Role
multiplier = 1 if meta["strike_direction"] == OptionsStrikeDirection.ATM.value else 2
qty = self.number_of_lots * child_instrument.lot_size * multiplier
-
The strategy dynamically adjusts quantity using a multiplier tied to strike direction.
-
Logic:
-
ATM leg → multiplier = 1
-
OTM leg → multiplier = 2
-
-
This sizing structure creates the ratio backspread payoff profile, where the long OTM exposure is larger than the ATM leg.
-
Key benefits:
-
Maintains the intended risk–reward convexity
-
Keeps position sizing parameter-driven
-
Avoids hardcoding per-leg quantities
-
-
Without this multiplier logic, the strategy would lose its asymmetric payoff behaviour.
2. Limit Order Placement at Current LTP
_order = self.broker.OrderRegular(
instrument=child_instrument,
order_transaction_type=meta['action'],
price=current_ltp,
order_code=self.order_code,
order_variety=BrokerOrderVarietyConstants.LIMIT,
quantity=qty
)
-
Orders are submitted as LIMIT orders at the current LTP, rather than using market orders.
-
This provides:
-
Better execution control
-
Reduced slippage risk
-
More predictable fill prices across legs
-
-
In multi-leg option strategies, controlled execution is critical because partial or poor fills can temporarily distort the intended payoff structure.
3. Base-to-Child Instrument Mapping Context
-
Before placing the order, the strategy resolves the base instrument corresponding to the option leg.
-
This mapping is essential for:
-
Grouping legs under a single underlying
-
Coordinated position management
-
Structured exit handling later
-
-
It ensures all option legs remain logically tied to their parent instrument.
4. Order Tracking Upon Successful Placement
if check_order_placed_successfully(_order):
self.child_instrument_main_orders.setdefault(base_instrument, {})[meta['action']] = _order
-
Once the broker confirms successful placement, the order is stored in the strategy’s tracking structure.
-
Key design points:
-
Uses setdefault for safe dictionary initialization
-
Groups orders by base instrument
-
Indexes by action type (BUY/SELL)
-
-
This enables the engine to:
-
Monitor open legs
-
Manage exits cleanly
-
Detect incomplete structures
-
-
The structure maintains clear visibility into the live position state.
5. Fail-Safe Protection Against Partial Structures
else:
self.logger.critical(
'Order placement failed for one of the legs. Exiting position for other leg, if possible and stopping strategy.'
)
self.exit_all_positions_for_base_instrument(base_instrument)
raise ABSystemExit
-
If any leg fails to place successfully, the strategy immediately triggers protective action.
-
Protective behaviour:
-
Logs a critical error
-
Attempts to exit any already-open legs
-
Raises ABSystemExit to halt execution
-
-
This is a crucial risk-control safeguard.
-
It prevents:
-
Partially constructed spreads
-
Unhedged directional exposure
-
Accidental naked option risk
-
-
By forcefully stopping after a failure, the strategy preserves its defined-risk discipline.
Exit Condition Checks
def check_exit_conditions(self, base_instrument, child_leg_orders_dict):
"""
Evaluate all exit rules for the Bull Call Ratio Backspread.
Checks:
• Trend Invalidation Check - handled separately in exit selection logic.
• Target Profit - exit if spread rises beyond the profit threshold.
• Stop-Loss - exit if spread falls beyond the stop-loss threshold.
"""
# Retrieve current orders and latest traded prices (LTP) for both legs
ltp_leg_buy = self.broker.get_ltp(child_leg_orders_dict[BrokerOrderTransactionTypeConstants.BUY].instrument)
ltp_leg_sell = self.broker.get_ltp(child_leg_orders_dict[BrokerOrderTransactionTypeConstants.SELL].instrument)
# Initialize key levels at entry:
if not self.spread_entry:
entry_price_leg_buy = self.child_instrument_main_orders.get(base_instrument)[BrokerOrderTransactionTypeConstants.BUY].entry_price
entry_price_leg_sell = self.child_instrument_main_orders.get(base_instrument)[BrokerOrderTransactionTypeConstants.SELL].entry_price
self.spread_entry = entry_price_leg_buy - 2 * entry_price_leg_sell # spread at entry
(multiplier, self.transaction_type) = (1, "Net Debit") if self.spread_entry > 0 else (-1, "Net Credit")
self.stoploss_premium = self.spread_entry * (1 - multiplier * self.stoploss_percentage / 100)
self.target_premium = self.spread_entry * (1 + multiplier * self.target_percentage / 100)
# Current spread price
self.spread_current = ltp_leg_buy - 2 * ltp_leg_sell
# Target Profit and Stop-Loss Threshold Check based on spread value
if self.spread_current > self.target_premium or self.spread_current < self.stoploss_premium:
(threshold_name, threshold) = ("Target", self.target_premium) if self.spread_current > self.target_premium else ("Stoploss", self.stoploss_premium)
self.logger.info(f"{threshold_name} threshold reached: Transaction Type: {self.transaction_type} | Current Net Premium: {abs(self.spread_current):.2f} | {threshold_name} Threshold: {abs(threshold):.2f} - Exiting positions...")
self.spread_entry = None
return True
return False
Code Explanation:
1. Leg-wise LTP Retrieval
ltp_leg_buy = self.broker.get_ltp(child_leg_orders_dict[BUY].instrument)
ltp_leg_sell = self.broker.get_ltp(child_leg_orders_dict[SELL].instrument)
-
The strategy first retrieves the latest traded prices (LTP) of both option legs — the long call and the short call.
-
This ensures:
- Real-time mark-to-market evaluation
- Accurate spread valuation
- Proper exit timing
-
Unlike structure-based exits, this logic is purely spread-value driven.
2. One-Time Spread Entry Initialization
if not self.spread_entry:
entry_price_leg_buy = ...
entry_price_leg_sell = ...
self.spread_entry = entry_price_leg_buy - 2 * entry_price_leg_sell
-
The system computes and stores the initial spread value at entry, but only once per trade cycle.
-
For a 1×2 call backspread:
- Long leg contributes positively
- Two short legs contribute negatively
-
So the spread is calculated as:
-
Spread = Buy Price − 2 × Sell Price
-
This becomes the baseline reference for all future exit checks.
-
-
Why store once?
-
Anchors stop-loss and target to original entry
-
Prevents threshold drift
-
Ensures each re-entry starts fresh
-
3. Automatic Net Debit / Net Credit Detection
(multiplier, self.transaction_type) =
(1, "Net Debit") if self.spread_entry > 0
else (-1, "Net Credit")
-
The strategy dynamically determines whether the structure is entered as:
-
Net Debit (typical backspread case)
-
Net Credit (possible depending on strikes)
-
-
This is an important robustness feature.
-
Why it matters:
-
Profit direction differs for debit vs credit
-
Threshold math must adapt automatically
-
Same code supports multiple payoff regimes
-
-
The multiplier normalizes later calculations.
4. Construction of Stop-Loss and Target Thresholds
self.stoploss_premium = spread_entry * (1 - multiplier * stoploss%)
self.target_premium = spread_entry * (1 + multiplier * target%)
-
Thresholds are derived directly from the entry spread value.
-
Because the multiplier adjusts sign:
-
Works correctly for both debit and credit structures
-
Maintains consistent risk logic
-
Avoids hardcoding comparison directions
-
-
Interpretation:
-
For a typical net debit backspread:
-
Profit occurs when spread value rises
-
Loss occurs when spread value falls
-
-
-
The formula automatically aligns with this behaviour.
5. Real-Time Spread Monitoring
-
The system continuously recomputes the live spread value using current market prices.
-
This represents the true mark-to-market value of the entire strategy.
-
Why this is important:
-
Captures full multi-leg dynamics
-
More accurate than monitoring legs independently
-
Reflects real exit cost
-
-
This is the core trade-level risk monitor.
6. Unified Target and Stop-Loss Check
-
A single conditional checks both exit scenarios.
-
Exit triggers when either:
-
Spread exceeds target threshold → profit booked
-
Spread falls below stop-loss threshold → risk capped
-
-
This keeps the logic:
-
Clean
-
Symmetric
-
execution-efficient
-
7. Resetting Spread State After Exit
-
After an exit, the entry reference is cleared.
-
This is crucial because it:
-
Prepares the system for clean re-entry
-
Prevents stale thresholds
-
Ensures the next trade recalibrates properly
-
-
Without this reset, future exits could be misaligned.
Validation in Short Call Butterfly
def validate_parameters(self):
""" Validates required strategy parameters. """
check_argument(
self.strategy_parameters, "extern_function", lambda x: len(x) >= 5,
err_message=(
"Need 5 parameters for this strategy: \n"
"(1) NUMBER_OF_OTM_STRIKES_SELL_LEG \n"
"(2) TARGET_PERCENTAGE \n"
"(3) STOPLOSS_PERCENTAGE \n"
"(4) RE_ENTRY_LIMIT \n"
"(5) TIME_PERIOD \n"
)
)
# Validate numeric strategy parameters
for param in (self.re_entry_limit, self.no_of_otm_strikes_leg_sell, self.time_period):
check_argument(param, "extern_function", is_positive_int, "Value should be a positive integer")
# Validate percentage strategy parameters
for param in (self.target_percentage, self.stoploss_percentage):
check_argument(param, "extern_function", is_nonnegative_int_or_float, "Value should be >0")
Code Explanation:
The validate_parameters function ensures all required strategy inputs are present and logically valid before any trading logic executes. This prevents runtime failures and protects the integrity of the strategy configuration.
Failure Case 1: Missing Required Strategy Parameters
self.strategy_parameters = {
"NUMBER_OF_OTM_STRIKES_SELL_LEG": 2,
"TARGET_PERCENTAGE": 20,
"STOPLOSS_PERCENTAGE": 10
# Missing RE_ENTRY_LIMIT and TIME_PERIOD
}
validate_parameters()
Error:
Need 5 parameters for this strategy
Reason:
The strategy requires at least five configuration parameters:
- NUMBER_OF_OTM_STRIKES_SELL_LEG
- TARGET_PERCENTAGE
- STOPLOSS_PERCENTAGE
- RE_ENTRY_LIMIT
- TIME_PERIOD
If fewer than five parameters are provided, the strategy cannot safely initialize its execution logic.
Failure Case 2: Invalid integer configuration values
self.re_entry_limit = 0
self.no_of_otm_strikes_leg_sell = -1
self.time_period = "20"
validate_parameters()
Error:
Value should be a positive integer
Reason:
The following parameters must be strictly positive integers (> 0):
-
re_entry_limit
-
no_of_otm_strikes_leg_sell
-
time_period
Invalid cases include:
-
Zero values
-
Negative numbers
-
Non-integer types
These fields control structural behaviour (re-entry count, strike distance, EMA window), so invalid values would break core strategy logic.
Failure Case 3: Invalid percentage inputs
elf.target_percentage = -5
self.stoploss_percentage = "ten"
validate_parameters()
Error:
Value should be >0
Reason:
The following parameters must be non-negative numeric values:
-
target_percentage
-
stoploss_percentage
Invalid inputs include:
-
Negative percentages
-
Non-numeric values
These parameters directly drive risk and profit thresholds, so improper values would distort exit logic and risk management.
💡 Want to see the complete strategy? Check out the full implementation here.
Ideal Market Conditions for Bull Call Ratio Backspread
When to Use
The Bull Call Ratio Backspread works best when a strong bullish move accompanied by potential volatility expansion is expected. The strategy is designed to benefit from sharp upside momentum, making it most effective when the underlying is likely to break out decisively rather than remain range-bound.
Typical scenarios include:
-
Post-Consolidation Bullish Breakouts: After a prolonged period of price compression or range-bound movement, when the market is poised for an upside breakout with expanding momentum.
-
Event-Driven Upside Moves: Around catalysts such as earnings releases, economic data announcements, or policy decisions where a positive surprise could trigger a sharp bullish move and volatility expansion.
-
Strong Trend Continuation Phases: During established uptrends when the underlying shows signs of fresh momentum or breakout from a pullback, indicating potential for accelerated upside.
-
Low-to-Rising Volatility Environments: Markets transitioning from low implied volatility to expanding volatility regimes, where the convex payoff of the backspread benefits from both price acceleration and potential IV expansion.
Interpreting the Bull Call Ratio Backspread Payoff Structure
The following payoff diagram illustrates the profit and loss dynamics of a Bull Call Ratio Backspread strategy. The values used correspond to those depicted in the flowchart.
![]() |
|---|
| Figure 2: Profit and Loss Diagram |
The green curve represents the profit zone of the strategy. In a Bull Call Ratio Backspread, the position begins to generate meaningful gains when the underlying price breaks out strongly above the higher long call strike. Unlike range-bound premium strategies, this structure is specifically designed to capture sharp upside momentum rather than benefit from price stability. As the rally strengthens, the two long calls increasingly drive the payoff, resulting in a convex upside profile.
The strategy offers uncapped profit potential on the upside, with gains expanding as the underlying continues to move higher. The dotted green line marks the target profit level, where traders may choose to exit systematically to secure profits during favourable market moves.
The red curve indicates the loss region, primarily concentrated between the short strike and the long strike. The maximum loss typically occurs near the higher strike at expiry, where the short call retains value while the long calls have not yet provided sufficient offset. Importantly, the downside exposure remains predefined, as highlighted by the red dashed stop-loss line, helping maintain disciplined risk control.
Key dashed markers highlight the important price reference points:
-
Upper breakeven marks the level where the payoff transitions from loss to profit on the upside.
-
Short strike (K1) identifies where the sold call begins to introduce downside pressure.
-
Long strike (K2) indicates the activation zone where the purchased calls start contributing positively.
-
Target profit and stop-loss thresholds outline the active risk management boundaries applied during execution.
Profit and Loss Calculations for Low and High Risk Versions
1. Low-Risk Bull Call Ratio Backspread
The following example illustrates a low-risk Bull Call Ratio Backspread constructed on a liquid US large-cap stock, AAPL. The setup is designed to benefit from a sharp upside move while keeping downside risk limited to the net premium paid.
Key Parameters
-
Target Profit (target_percentage): 50% of the net debit
-
Stop-Loss (stoploss_percentage): 30% of the net debit
-
Instrument: AAPL (Apple Inc.)
-
Expiration Type: Nearest Monthly Expiry
-
Strike Selection:
-
Leg One: ATM (Sell Call) - $180
-
Leg Two: OTM (Buy Call - Quantity 2) - $185
-
(1:2 ratio backspread structure)
-
Re-entry Levels
-
Re-Entry Trigger: Fresh breakout above the recent high
-
Trend Filter: Price crosses above 20 EMA
-
Calculations
(Assume a simple 1:1 relationship between the AAPL stock underlying and the spread for illustration.)
-
Total Premium Collected: $4.50 (ATM Call) = $4.50
-
Total Premium Paid: $2.75 (OTM Call) × 2 = $5.50
-
Net Premium Paid: $5.50 - $4.50 = $1
-
Target Profit (0.5 x Net Premium Paid):
1 x 0.50 = $0.50
Exit when spread profit reaches +$0.50
- Stop-Loss (0.3 x Net Premium Paid):
1 x 0.30 = $0.30
Max possible loss capped at -$0.30.
- Maximum Profit Calculation:
Maximum Profit: Unlimited
To calculate your exact profit at any stock price above the higher strike (K2) at expiration:
Profit = (S−K2) − Max Loss
Alternatively, broken down by individual legs (for a 2:1 ratio):
Profit = [2 × (S−K2)] − (S−K1) + Net Premium
where:
-
K1 = short strike
-
K2 = long strike
-
S = spot at expiry
It occurs when the underlying rallies sharply above the higher long call strike ($185), where the two long calls begin to dominate the payoff. -
Maximum Loss Calculation:
Maximum Loss = K2 - K1 + net debit paid = $5 + $1 = $6
The maximum loss occurs if the stock price is exactly at the higher strike (K₂) at expiration. In this scenario, both long calls expire worthless while the short call remains in the money, resulting in the deepest loss for the position. -
Breakeven Points:
- Upper Breakeven: Long Strike + Maximum Loss = 185 + 6 = $191
(Downside risk is already limited to the debit paid.)
| Spot Price | P&L With Target/Stop-loss | P&L Without Target/Stop-loss |
|---|---|---|
| 180 | Exit at $0.70 = –$0.30 (Capped) | –$1 (Net Debit Loss) |
| 185 | Exit at $0.70 = –$0.30 (Capped) | –$6 (Maximum Loss) |
| 191 | Exit at $1 = $0 (Breakeven) | $0 |
| 195 | Exit at $1.50 = +$0.50 (Target Profit) | $4 |
2. High-Risk Bull Call Ratio Backspread
The following diagram represents the payoff behaviour of a high-risk Bull Call Ratio Backspread position at expiry.
![]() |
|---|
| Figure 3: Profit and Loss Diagram - High Risk Version |
The following example illustrates a high-risk Bull Call Ratio Backspread constructed on the BANK NIFTY Index, designed to capitalize on sharp bullish breakouts while maintaining defined downside risk.
This setup is particularly suited for high-volatility environments where strong directional moves are expected and the convex payoff of the backspread can be effectively captured
Key Parameters
-
Target Profit (target_percentage): 60% of the net debit
-
Stop-Loss (stoploss_percentage): 40% of the net debit
-
Instrument: BANK NIFTY Index
-
Expiration Type: Nearest Weekly Expiry
-
Strike Selection:
-
Leg One: ATM (Sell Call) - 48,000
-
Leg Two: OTM (Buy Call × 2) - 48,500
-
(1:2 ratio backspread structure)
-
Re-Entry Levels
-
Re-Entry Trigger: Breakout above the recent high
-
Trend Filter: Price crosses above 20 EMA
-
Calculations
(Assume a 1:1 relationship between the BANKNIFTY spot price and the option spread for illustration.)
-
Total Premium Collected: ₹220 (ATM Call) = ₹220
-
Total Premium Paid: ₹150 (OTM Call) × 2 = ₹300
Net Premium Paid: 300 - 220 = ₹80
-
Target Profit (0.6 × Net Premium Paid)
80 x 0.60 = ₹48
Exit when spread profit reaches +₹48 profit -
Stop-Loss (0.4 × Net Premium Paid)
80 x 0.40 = ₹32
Maximum loss capped at −₹32 -
Maximum Profit Calculation
Maximum Profit: Unlimited
At expiration above the higher strike (K₂ = 48,500), the two long calls begin to dominate the payoff, producing accelerating upside gains.
Profit Formula
Profit = [2 x (S - K2)] - (S - K1) - Net Debit
where:-
K1 = short strike
-
K2 = long strike
-
S = spot at expiry
-
-
Maximum Loss Calculation
Maximum Loss = (K2 - K1) + Net Debit = 500 + 80 = ₹580
The maximum loss occurs if BANK NIFTY expires exactly at the higher strike (K₂ = 48,500). In this scenario, both long calls expire worthless while the short call remains in the money, producing the deepest loss. -
Breakeven Point
Upper Breakeven = K2 + Maximum Loss = 48,500 + 580 = ₹49,080
Beyond this level, the strategy enters the profit zone.
(Downside risk remains limited to the debit paid.)
| Spot Price | P&L With Target/Stop-loss | P&L Without Target/Stop-loss |
|---|---|---|
| 48,000 | Exit at ₹48 = −₹32 (Capped) | −₹40 (Net Debit Loss) |
| 48,500 | Exit at ₹48 = −₹32 (Capped) | −₹580 (Maximum Loss) |
| 49,080 | Exit near ₹0 (Breakeven) | ₹0 |
| 49,000 | Exit at ₹128 = +₹48 (Target Profit) | ₹420 |
The low-risk version of the Bull Call Ratio Backspread focuses on controlled exposure with smaller debit outlay and tighter risk management, making it suitable for more measured market conditions.
In contrast, the high-risk variant increases sensitivity to sharp upside moves by using wider strikes and more aggressive parameters. While this enhances the potential for accelerated gains during strong breakouts, it also increases mark-to-market volatility and the likelihood of drawdowns if momentum fails to materialize.
A visual comparison below highlights how the risk–reward profile shifts between the two approaches.
Comparing Bull Call Ratio Backspread and Bear Put Ratio Backspread
The Bull Call Ratio Backspread and the Bear Put Ratio Backspread are convex multi-leg options strategies designed to benefit from strong directional moves accompanied by potential volatility expansion. Their payoff structures are mirror images of each other, but they are deployed under opposite market expectations.
The Bull Call Ratio Backspread is structured to profit from sharp upside breakouts, whereas the Bear Put Ratio Backspread is designed to benefit from strong downward moves in the underlying.
| Feature | Bull Call Ratio Backspread | Bear Put Ratio Backspread |
|---|---|---|
| Option Types Used | Sell 1 ATM Call, Buy 2 OTM Calls | Sell 1 ATM Put, Buy 2 OTM Puts |
| Strategy Bias | Bullish convex | Bearish convex |
| Market Expectation | Strong upside breakout | Sharp downside move |
| Initial Trade Type | Usually small debit (can be credit) | Usually small debit (can be credit) |
| Payoff Shape | Convex upside (hockey stick) | Convex downside (inverted hockey stick) |
| Max Profit Scenario | Large upward move | Large downward move |
| Max Loss Scenario | Near the long strike region | Near the long strike region |
![]() |
|---|
| Figure 4: Bull Call Ratio Backspread vs. Bear Put Ratio Backspread Mind Tree |
Which One Is Right for You?
If you expect a strong bullish move and prefer a debit-based strategy with significant upside potential, the Bull Call Ratio Backspread may be more suitable. This strategy typically involves selling fewer lower-strike calls and buying more higher-strike calls, resulting in limited downside risk and unlimited profit potential on the upside. You benefit most when the underlying makes a sharp upward move beyond the higher strike.
If you anticipate only a mild bullish move or expect the price to stay within a range, this strategy may be less effective, since profits depend on a meaningful upward breakout. While the initial setup may result in a small net debit (or sometimes a credit), the key objective is to capture convex upside with controlled risk.
The Bull Call Ratio Backspread offers defined or near-defined risk with strong positive convexity. Choose this strategy if you are positioning for a significant bullish expansion in price while keeping downside risk limited.
Customize the Strategy with Your Own Parameters!
Traders can fine-tune strike selection, expiry choice, stop-loss levels, and profit targets based on risk tolerance.
👉 For testing on the Phoenix platform of AlgoBulls, head over to our site now!
👉 A Jupyter notebook for this strategy is coming soon. Meanwhile, check out All Available Notebooks for Testing Custom Strategies!
Final Thoughts
The Bull Call Ratio Backspread works best as an actively managed structure rather than a set-and-forget position. It is designed to capitalize on sharp upside momentum while keeping downside exposure controlled through its built-in hedge.
This setup performs most efficiently when supported by clear exit rules and price-based supervision. Defined profit objectives, protective loss limits and disciplined re-entry criteria help the strategy stay aligned with the intended bullish thesis while avoiding unnecessary risk.
Instead of waiting passively for expiry, the focus is on responsive, rule-driven trade management that reacts quickly when momentum strengthens or the setup weakens.
Key Risk-Mitigation Techniques
✔ Incorporated in the Strategy
Target profit & hard stop-loss:
The strategy exits automatically once the position reaches predefined profit or loss thresholds. This ensures consistent execution, protects capital during adverse moves, and helps secure gains when the underlying rallies sharply.
Price and trend invalidation exit:
In addition to P&L-based exits, the strategy continuously monitors key underlying price and trend conditions. If the underlying fails to sustain the breakout (e.g., falls back below the recent high reference) or closes below the 20 EMA, indicating loss of bullish momentum, the position is exited promptly, even if the profit target or stop-loss has not been reached. This trend-based exit helps protect against theta decay, failed breakouts, and weakening trend conditions.
Re-entry logic:
If a position exits due to a target hit, stop-loss, or price-level trigger, and the underlying continues to trend upward, the strategy can re-initiate using an updated ATM reference. This enables continued participation in sustained bullish momentum while maintaining controlled exposure.
✔ Additional Enhancements
High-frequency P&L tracking:
Monitoring profit and loss at a finer interval than the primary candle timeframe (for example, frequent checks within a 1-minute setup) allows faster defensive exits, especially when price stalls near critical zones.
Position refinement:
Strike ratios, spread spacing, and lot sizing can be dynamically adjusted based on volatility and momentum conditions. In higher-volatility environments, wider strike spacing can better accommodate large directional moves while preserving the strategy’s positive convexity. Strike selection may also be automated using implied volatility or momentum filters to keep the structure aligned with prevailing market conditions.



