Hi, Please check my code for paper trading on live straddle chart.
import pdb
import time
import datetime
import traceback
from Dhan_Tradehull import Tradehull
import pandas as pd
from pprint import pprint
import talib
import pandas_ta as ta
import xlwings as xw
import pytz
# Initialize client and connection
client_code = "11"
token_id = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJpc3MiOiJkaGFuIiwicGFydG5lcklkIjoiIiwiZXhwIjoxNzM5MDk5MTc3LCJ0b2tlbkNvbnN1bWVyVHlwZSI6IlNFTEYiLCJ3ZWJob29rVXJsIjoiIiwiZGhhbkNsaWVudElkIjoiMXcTTEwMDg4OTA1NSJ9.bX2eeT5ZMHh689KIp_3dUzRzbohivQvgAkrbjZonf2tTq6c4soTcMqnlP6gR4wOIVY1ctBSu_tL4_T51kcFyTA"
tsl = Tradehull(client_code, token_id)
ce_name, pe_name, strike_price = tsl.ATM_Strike_Selection(Underlying='SENSEX', Expiry=0)
last_candle_time = datetime.datetime.now()
last_candle_time = last_candle_time.replace(hour=9, minute=15, second=0, microsecond=0)
ce_data = tsl.get_historical_data(tradingsymbol=ce_name, exchange='BFO', timeframe="1")
pe_data = tsl.get_historical_data(tradingsymbol=pe_name, exchange='BFO', timeframe="1")
print(ce_name)
print(pe_name)
single_order = {'Option name': None,'entry_strike': None, 'date': None, 'entry_time': None, 'ce_entry_price': None, 'pe_entry_price': None, 'buy_sell': None, 'qty': None, 'sl': None, 'exit_time': None, 'exit_price': None, 'pnl': None, 'remark': None, 'traded': None}
orderbook = {}
completed_orders = {'Option name': None,'entry_strike': None, 'date': None, 'entry_time': None, 'ce_entry_price': None, 'pe_entry_price': None, 'buy_sell': None, 'qty': None, 'sl': None, 'exit_time': None, 'exit_price': None, 'pnl': None, 'remark': None, 'traded': None}
watchlist = ['SENSEX']
all_dataframes = []
completed_orders = []
reentry = "yes" #"yes/no"
completed_orders = []
# Initialize merged_df outside the if block
merged_df = None
# Initialize Supertrend outside the if block
Supertrend = None
# bot_token = "8059847390:AAECSnQK-yOaGJ-clJchb1cx8CDhx2VQq-M"
# receiver_chat_id = "1918451082"
book = xw.Book("Straddle.xlsx")
Straddle_chart = book.sheets['Straddle Chart']
config_sheet = book.sheets['Config']
running_orders_sheet = book.sheets['Running Orders']
completed_orders_sheet = book.sheets['Completed Orders']
for name in watchlist:
orderbook[name] = single_order.copy()
while True:
loop_start_time = time.time() # Record start time of loop
print("Starting while loop\n\n")
current_time = datetime.datetime.now().time()
# Market timing checks
if current_time < datetime.time(8, 15):
print(f"Wait for market to start", current_time)
time.sleep(60)
continue
if current_time > datetime.time(23, 30):
order_details = tsl.cancel_all_orders()
print(f"Market over Closing all trades!! Bye Bye See you Tomorrow", current_time)
break
for name in watchlist:
# ------------------------------------- GET DATA -------------------------------------
# Create DataFrame with explicit index to avoid ValueError
orderbook_df = pd.DataFrame([orderbook[name]], index=[name]) # Changed from .from_dict() to list with single dict
# Clear and write to Excel with error handling
try:
# Create DataFrame from orderbook with explicit index
orderbook_df = pd.DataFrame.from_dict(orderbook, orient='index')
running_orders_sheet.range('A1').value = orderbook_df
# Create DataFrame from completed_orders with index
if completed_orders: # Check if there are any completed orders
completed_orders_df = pd.DataFrame(completed_orders)
completed_orders_df.reset_index(drop=True, inplace=True) # Create numeric index
else:
completed_orders_df = pd.DataFrame(columns=single_order.keys()) # Empty DataFrame with correct columns
completed_orders_sheet.range('A1').value = completed_orders_df
current_time = datetime.datetime.now()
print(f"Scanning {name} {current_time}")
except Exception as e:
print(f"Error writing to Excel: {str(e)}")
# Continue execution even if Excel write fails
pass
candle_is_still_running = datetime.datetime.now() < last_candle_time + datetime.timedelta(minutes=1)
ce_name, pe_name, strike_price = tsl.ATM_Strike_Selection(Underlying='SENSEX', Expiry=0)
if candle_is_still_running is False:
ce_data = tsl.get_historical_data(tradingsymbol = ce_name,exchange = 'BFO',timeframe="1")
pe_data = tsl.get_historical_data(tradingsymbol = pe_name,exchange = 'BFO',timeframe="1")
last_candle_time = ce_data.iloc[-1]['timestamp'].to_pydatetime().replace(tzinfo=None)
continue
all_ltp_data = tsl.get_ltp_data(names=[ce_name, pe_name])
if candle_is_still_running:
ce_ltp = all_ltp_data[ce_name]
ce_data.iloc[-1, ce_data.columns.get_loc('close')] = ce_ltp
pe_ltp = all_ltp_data[pe_name]
pe_data.iloc[-1, pe_data.columns.get_loc('close')] = pe_ltp
merged_df = pd.merge(ce_data[['timestamp', 'close']], pe_data[['timestamp', 'close']], on='timestamp', suffixes=('_ce', '_pe')).set_index('timestamp')
merged_df['combined_premium'] = merged_df['close_ce'] + merged_df['close_pe']
# Calculate OHLC for combined premium
merged_df['combined_premium_high'] = merged_df['combined_premium'].rolling(window=1).max()
merged_df['combined_premium_low'] = merged_df['combined_premium'].rolling(window=1).min()
merged_df['combined_premium_open'] = merged_df['combined_premium'].shift(1)
merged_df['combined_premium_close'] = merged_df['combined_premium']
merged_df['ROC'] = talib.ROC(merged_df['combined_premium'], timeperiod=9)
# Calculate Supertrend using pandas_ta
Supertrend = ta.supertrend(merged_df['combined_premium_high'], merged_df['combined_premium_low'], merged_df['combined_premium_close'], 10, 2)
merged_df = pd.concat([merged_df, Supertrend], axis=1, join='inner')
# Remove .values from numpy float values since they don't have that attribute
combined_premium_value = merged_df['combined_premium'].iloc[-1]
roc_value = merged_df['ROC'].iloc[-1]
supertrend_value = Supertrend['SUPERTd_10_2.0'].iloc[-1]
data_to_write = [str(current_time), combined_premium_value, strike_price, roc_value, supertrend_value]
print(f"ce_ltp {ce_ltp}")
print(f"pe_ltp {pe_ltp}")
last_row = 2
while Straddle_chart.range(f'A{last_row}').value is not None:
last_row += 1
if last_row > 30000: # Safety limit
last_row = 2 # Reset to top if sheet is full
break
# Add strike change message if strike price changed
if last_row > 2 and Straddle_chart.range(f'C{last_row-1}').value != strike_price:
data_to_write.append("Strike change to " + str(strike_price))
print(f"Strike price changed from {Straddle_chart.range(f'C{last_row-1}').value} to {strike_price}")
else:
data_to_write.append("")
Straddle_chart.range(f'A{last_row}:E{last_row}').value = data_to_write
# Initialize variables with default values before try block
tc1 = tc2 = tc3 = tc4 = False
try:
# Get first and current candle for 3-minute timeframe
First_cc = merged_df.iloc[0] # First candle of 1-min period
cc = merged_df.iloc[-1] # Current candle of 1-min period
# Check if we're at the 3-min candle close
current_minute = current_time.minute
if current_minute % 3 != 0: # Only take trade at 3-min candle close
continue
# Check if combined premium is lower than 3 candles ago
tc1 = cc['combined_premium'] < First_cc['combined_premium']
# Check if Supertrend exists and has data before accessing it
tc2 = False # Default value
if Supertrend is not None and len(Supertrend) > 0:
tc2 = Supertrend['SUPERTd_10_2.0'].iloc[-1] == -1
tc3 = current_time.time() > datetime.time(9, 15) and current_time.time() < datetime.time(23, 30)
tc4 = orderbook[name]['traded'] is None
except Exception as e:
print("Error accessing data:", e)
print("Supertrend status:", "None" if Supertrend is None else "Has data")
print("merged_df status:", "None" if merged_df is None else f"Has {len(merged_df)} rows")
continue
# Add a check before using Supertrend
ec1 = False # Default value
if Supertrend is not None and len(Supertrend) > 0:
ec1 = Supertrend['SUPERTd_10_2.0'].iloc[-1] == 1
# Exit if current strike price differs from entry strike price
if orderbook[name].get('entry_strike') is None:
ec2 = False
else:
ec2 = strike_price != orderbook[name]['entry_strike']
ec3 = current_time.time() >= datetime.time(15, 15) # Exit at 3:15 PM
ec4 = orderbook[name]['traded'] == "yes" # Check if trade is active
if tc1 and tc2 and tc3 and tc4:
print("Trade condition met. Placing order...Short Straddle")
# margin_avialable = tsl.get_balance()
# margin_required = 200000
# if margin_avialable < margin_required:
# print(f"Less margin, not taking order : margin_avialable is {margin_avialable} and margin_required is {margin_required} for {name}")
ce_lot_size = tsl.get_lot_size(tradingsymbol=ce_name)
pe_lot_size = tsl.get_lot_size(tradingsymbol=pe_name)
# Set the quantity to 1 lot for both CE and PE
ce_qty = ce_lot_size * 5
pe_qty = pe_lot_size * 5
print(f"Attempting to place CE order: Symbol={ce_name}, Qty={ce_qty}")
print(f"Attempting to place PE order: Symbol={pe_name}, Qty={pe_qty}")
orderbook[name]['name'] = name
orderbook[name]['date'] = str(current_time.date())
orderbook[name]['entry_time'] = str(current_time.time())[:8]
orderbook[name]['buy_sell'] = "SELL"
orderbook[name]['qty'] = ce_qty or pe_qty
try:
# ce_entry_ordrid = tsl.order_placement(...)
orderbook[name]['ce_entry_ordrid'] = 11111111
orderbook[name]['pe_entry_ordrid'] = 11111111
# orderbook[name]['ce_entry_price'] = tsl.get_executed_price(orderid=orderbook[name]['ce_entry_ordrid'])
# orderbook[name]['pe_entry_price'] = tsl.get_executed_price(orderid=orderbook[name]['pe_entry_ordrid'])
orderbook[name]['entry_time'] = str(datetime.datetime.now().time())[:8]
orderbook[name]['entry_datetime'] = datetime.datetime.now()
orderbook[name]['traded'] = "yes"
# message = "\n".join(f"'{key}': {repr(value)}" for key, value in orderbook[name].items())
# message = f"Entry_done {name} \n\n {message}"
# tsl.send_telegram_alert(message=message,receiver_chat_id=receiver_chat_id,bot_token=bot_token)
except Exception as e:
print(f"Error placing orders: {str(e)}")
print(f"Traceback: {traceback.format_exc()}")
else:
print("Trade condition not met. Skipping entry.")
if orderbook[name]['traded'] == "yes":
orderbook[name]['buy_sell'] == "SELL"
# ------------------------------------- Exit Condition -------------------------------------
if (ec1 or ec2 or ec3) and ec4:
print("Exit condition met. Closing straddle position...")
try:
# Store exit details
current_trade = orderbook[name].copy()
orderbook[name]['ce_name'] = ce_name
orderbook[name]['pe_name'] = pe_name
orderbook[name]['buy_sell'] = "BUY"
orderbook[name]['date'] = str(datetime.datetime.now().date())
orderbook[name]['exit_time'] = str(datetime.datetime.now().time())[:8]
orderbook[name]['exit_datetime'] = datetime.datetime.now()
# Place sell orders to close straddle position
# ce_exit_ordrid = tsl.order_placement(tradingsymbol=orderbook[name]['ce_name'], exchange='BFO', quantity=orderbook[name]['qty'], price=0, trigger_price=0, order_type='MARKET', transaction_type='BUY', trade_type='MIS')
# pe_exit_ordrid = tsl.order_placement(tradingsymbol=orderbook[name]['pe_name'], exchange='BFO', quantity=orderbook[name]['qty'], price=0, trigger_price=0, order_type='MARKET', transaction_type='BUY', trade_type='MIS')
# Store exit order IDs
orderbook[name]['ce_exit_ordrid'] = 11111111
orderbook[name]['pe_exit_ordrid'] = 11111111
orderbook[name]['traded'] = None # Reset traded status
# Get exit prices with timeout and error handling
ce_exit_price = tsl.get_executed_price(orderid=orderbook[name]['ce_exit_ordrid'])
pe_exit_price = tsl.get_executed_price(orderid=orderbook[name]['pe_exit_ordrid'])
if ce_exit_price is None or pe_exit_price is None:
print("Failed to get exit prices, will retry next iteration")
continue
# Update the current trade with PnL information
current_trade.update({
'ce_pnl': (ce_exit_price - current_trade['ce_entry_price']) * current_trade['ce_qty'],
'pe_pnl': (pe_exit_price - current_trade['pe_entry_price']) * current_trade['pe_qty'],
'total_pnl': (ce_exit_price - current_trade['ce_entry_price']) * current_trade['ce_qty'] +
(pe_exit_price - current_trade['pe_entry_price']) * current_trade['pe_qty']
})
# Append completed trade to completed_orders list
completed_orders.append(current_trade)
print(f"Straddle PnL: CE={current_trade['ce_pnl']:.2f}, PE={current_trade['pe_pnl']:.2f}, Total={current_trade['total_pnl']:.2f}")
# Reset orderbook entry for new trades
orderbook[name] = single_order.copy()
except Exception as e:
print(f"Error closing straddle position: {str(e)}")
print(f"Traceback: {traceback.format_exc()}")
if reentry == "yes":
completed_orders.append(orderbook[name])
orderbook[name] = None
# Modify sleep calculation to account for processing time more precisely
current_time = datetime.datetime.now()
time_since_last_candle = (current_time - last_candle_time).total_seconds()
if time_since_last_candle < 60: # If we haven't reached the next 1-minute mark
sleep_time = 60 - time_since_last_candle
if sleep_time > 0:
time.sleep(sleep_time)