Intraday Rolling Straddles
Overview
Key Features
Python Strategy
import time as systime
from datetime import datetime, time as dtime
from apscheduler.schedulers.background import BackgroundScheduler
from openalgo import api
import pytz
print("🔁 OpenAlgo Python Bot is running.")
# === USER PARAMETERS ===
STRADDLE_ENTRY_HOUR = 10 # 10 for 10:00 AM
STRADDLE_ENTRY_MINUTE = 0 # 0 for 10:00 AM
SQUAREOFF_HOUR = 15 # 15 for 3:15 PM
SQUAREOFF_MINUTE = 15 # 15 for 3:15 PM
MAX_STRADDLES_PER_DAY = 3 # Daily limit on rolling straddles
ROLLING_THRESHOLD_PCT = 0.4 # Threshold for rolling (in percent, e.g. 0.4 means 0.4%)
LOT_SIZE = 75
STRATEGY = "rolling_straddle"
SYMBOL = "NIFTY"
EXPIRY = "19JUN25"
EXCHANGE = "NSE_INDEX"
OPTION_EXCHANGE = "NFO"
STRIKE_INTERVAL = 50
API_KEY = "YOU-OPENALGO-APIKEY"
API_HOST = "http://127.0.0.1:5000"
client = api(api_key=API_KEY, host=API_HOST)
def get_atm_strike(spot):
return int(round(spot / STRIKE_INTERVAL) * STRIKE_INTERVAL)
def get_spot():
quote = client.quotes(symbol=SYMBOL, exchange=EXCHANGE)
print("Quote:", quote)
data = quote['data']
if isinstance(data, list):
data = data[0]
return data['ltp']
def get_option_symbol(base, expiry, strike, opttype):
return f"{base}{expiry}{strike}{opttype}"
# --- State ---
last_reference_spot = None
current_leg_symbols = []
straddle_entry_count = 0
def reset_daily_counter():
global straddle_entry_count
straddle_entry_count = 0
print(f"Daily straddle entry counter reset to zero at {datetime.now()}")
def place_straddle():
global last_reference_spot, current_leg_symbols, straddle_entry_count
if straddle_entry_count >= MAX_STRADDLES_PER_DAY:
print(f"Straddle entry limit ({MAX_STRADDLES_PER_DAY}) reached for today.")
return
spot = get_spot()
atm_strike = get_atm_strike(spot)
ce = get_option_symbol(SYMBOL, EXPIRY, atm_strike, "CE")
pe = get_option_symbol(SYMBOL, EXPIRY, atm_strike, "PE")
for sym in [ce, pe]:
order = client.placeorder(
strategy=STRATEGY, symbol=sym, action="SELL",
exchange=OPTION_EXCHANGE, price_type="MARKET",
product="MIS", quantity=LOT_SIZE
)
print(f"Order placed for {sym}: {order}")
last_reference_spot = spot
current_leg_symbols = [ce, pe]
straddle_entry_count += 1
print(f"Straddle Entry Count updated: {straddle_entry_count}")
def close_straddle():
for sym in current_leg_symbols:
order = client.placeorder(
strategy=STRATEGY, symbol=sym, action="BUY",
exchange=OPTION_EXCHANGE, price_type="MARKET",
product="MIS", quantity=LOT_SIZE
)
print(f"Order EXIT for {sym}: {order}")
def rolling_monitor():
global last_reference_spot
spot = get_spot()
print(f"Spot: {spot}")
print(f"Last Reference Spot: {last_reference_spot}")
threshold = last_reference_spot * (ROLLING_THRESHOLD_PCT / 100.0)
if abs(spot - last_reference_spot) >= threshold:
print(f"Rolling: Spot moved {spot} from ref {last_reference_spot} (Threshold: {threshold})")
close_straddle()
place_straddle()
def eod_exit():
print("EOD exit triggered.")
close_straddle()
# === Scheduler ===
scheduler = BackgroundScheduler(timezone="Asia/Kolkata")
scheduler.add_job(reset_daily_counter, 'cron', day_of_week='mon-fri', hour=STRADDLE_ENTRY_HOUR, minute=STRADDLE_ENTRY_MINUTE)
scheduler.add_job(place_straddle, 'cron', day_of_week='mon-fri', hour=STRADDLE_ENTRY_HOUR, minute=STRADDLE_ENTRY_MINUTE)
scheduler.add_job(eod_exit, 'cron', day_of_week='mon-fri', hour=SQUAREOFF_HOUR, minute=SQUAREOFF_MINUTE)
scheduler.start()
try:
while True:
now = datetime.now(pytz.timezone("Asia/Kolkata")).time()
entry_start = dtime(STRADDLE_ENTRY_HOUR, STRADDLE_ENTRY_MINUTE)
squareoff_time = dtime(SQUAREOFF_HOUR, SQUAREOFF_MINUTE)
# Rolling monitor runs during straddle session only
if entry_start < now < squareoff_time and last_reference_spot:
rolling_monitor()
systime.sleep(5)
except (KeyboardInterrupt, SystemExit):
scheduler.shutdown()
Parameters (Edit at Top of Script)
Variable
Purpose
Example
Order Format
How the Strategy Works
Usage
Limitations and Notes
Last updated