This is the code i have created using dhanhq library with my own logiv but untill morning 10 this was working fine I am using this for around a month now below is the code
import asyncio
import json
import uuid
import pandas as pd
import requests
import websockets
from datetime import datetime, time
import pytz
from dhanhq import DhanContext, dhanhq, MarketFeed
──────────────────────────────────────────────────────────────
CONFIGURATION
CLIENT_ID = “1107042532”
ACCESS_TOKEN = “eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJpc3MiOiJkaGFuIiwicGFydG5lcklkIjoiIiwiZXhwIjoxNzUyODI3OTE1LCJ0b2tlbkNvbnN1bWVyVHlwZSI6IlNFTEYiLCJ3ZWJob29rVXJsIjoiIiwiZGhhbkNsaWVudElkIjoiMTEwNzA0MjUzMiJ9.splNe0x9bItfGxFSrnDDkOF0BeTDKvXXXQvxx02mRK2bovrDx7t3vpk30m6dkCgCwCtohpBh9asPXcFQ_Z-6ww”
STRIKE_PRICE = 24850
BUY_PRICE = 300 # Adjusted to recent LTP (~188–189)
TOTAL_LOTS = 24
OPTION_TYPE = “CE”
EXPIRY = “Jun2025”
print(BUY_PRICE)
MAX_UNITS_PER_ORDER = 1800
TRADING_END_TIME = “15:30:00” # 3:30 PM IST
LOT_SIZE = 75
TARGET_PROFIT = 10
STOPLOSS = 20
SYMBOL = “NIFTY”
──────────────────────────────────────────────────────────────
Initialize Dhan Client
dhan_context = DhanContext(CLIENT_ID, ACCESS_TOKEN)
dhan = dhanhq(dhan_context)
Global variables
order_placed = False
active_orders =
current_ltp = None
candle_data = {} # Store per-minute candle data: {candle_start_timestamp: [ltps]}
def get_ist_time():
“”“Get current time in IST.”“”
return datetime.now(pytz.timezone(“Asia/Kolkata”))
def get_security_id(symbol, expiry, strike, option_type):
“”“Fetch security ID from CSV.”“”
try:
df = pd.read_csv(“api-scrip-master.csv”, low_memory=False)
trading_symbol = f"{symbol}-{expiry}-{strike}-{option_type}"
filtered_df = df[
(df[“SEM_EXM_EXCH_ID”] == “NSE”)
& (df[“SEM_TRADING_SYMBOL”] == trading_symbol)
]
if not filtered_df.empty:
security_id = filtered_df.iloc[0][“SEM_SMST_SECURITY_ID”]
print(f"Found Security ID: {security_id} for {trading_symbol}“)
return str(security_id).strip()
else:
raise ValueError(f"Security ID not found for {trading_symbol}”)
except Exception as e:
print(f"
Error fetching security ID: {e}")
return None
def is_within_first_3_minutes(current_time):
“”“Check if within first 3 minutes of a 5-minute candle.”“”
minutes = current_time - get_candle_start_time(current_time)
minute_offset = minutes.total_seconds() / 60
print(
f"
Current minute offset: {minute_offset:.2f}, Window check: {minute_offset < 3}"
)
return minute_offset < 3
def is_fourth_minute(current_time, candle_start):
“”“Check if in the 4th minute (3:00–4:00) of a 5-minute candle.”“”
time_diff_minutes = (current_time - candle_start).total_seconds() / 60
print(f"
4th minute check: time_diff_minutes={time_diff_minutes:.2f}")
return 3 <= time_diff_minutes < 4
def get_candle_start_time(current_time):
“”“Get the start time of the current 5-minute candle.”“”
minutes = current_time.minute
candle_start_minute = minutes - (minutes % 5)
return current_time.replace(minute=candle_start_minute, second=0, microsecond=0)
async def place_super_order(buy_price, security_id, quantity):
“”“Place a Super Order with target and stop-loss.”“”
try:
correlation_id = str(uuid.uuid4())
payload = {
“dhanClientId”: CLIENT_ID,
“correlationId”: correlation_id,
“transactionType”: “BUY”,
“exchangeSegment”: “NSE_FNO”,
“productType”: “INTRADAY”,
“orderType”: “MARKET”,
“securityId”: str(security_id),
“quantity”: quantity,
“price”: 0.0,
“targetPrice”: float(buy_price + TARGET_PROFIT),
“stopLossPrice”: float(buy_price - STOPLOSS),
“trailingJump”: 0,
}
url = “i had put correct url but cannot post so removeing”
headers = {“Content-Type”: “application/json”, “access-token”: ACCESS_TOKEN}
print(f"
Sending Super Order: {json.dumps(payload, indent=2)}“)
response = requests.post(url, headers=headers, json=payload)
print(f"
Super Order Response: {response.status_code} - {response.text}”)
if response.status_code == 200:
data = response.json()
print(
f"
Super Order Placed: Order ID {data.get(‘orderId’)}, Qty {quantity}"
)
return data
else:
print(
f"
Failed to place Super Order: {response.status_code} - {response.text}"
)
return None
except Exception as e:
print(f"
Error placing order: {e}")
return None
async def monitor_position(security_id, entry_price):
“”“Monitor position for target, stop-loss, or session end.”“”
global current_ltp
end_time = time.fromisoformat(TRADING_END_TIME)
while True:
try:
current_time = get_ist_time().time()
if current_time >= end_time:
print(“
Trading session ended, closing position”)
await close_position()
break
if current_ltp:
ltp = float(current_ltp)
if ltp >= entry_price + TARGET_PROFIT:
print(f"
Target profit reached: LTP {ltp}, Exiting")
await close_position()
break
elif ltp <= entry_price - STOPLOSS:
print(f"
Stop-loss triggered: LTP {ltp}, Exiting")
await close_position()
break
await asyncio.sleep(1)
except Exception as e:
print(f"
Error in position monitoring: {e}")
await asyncio.sleep(5)
async def close_position():
“”“Close all active orders and positions.”“”
global order_placed, active_orders
try:
for order in active_orders:
order_id = order.get(“orderId”)
if order_id:
try:
dhan.cancel_order(order_id)
print(f"
Order {order_id} cancelled")
except Exception as e:
print(f"
Failed to cancel order {order_id}: {e}“)
order_placed = False
active_orders.clear()
except Exception as e:
print(f"
Error closing position: {e}”)
async def trading_strategy():
“”“Main trading strategy logic.”“”
global order_placed, current_ltp, active_orders, candle_data
security_id = get_security_id(SYMBOL, EXPIRY, STRIKE_PRICE, OPTION_TYPE)
if not security_id:
print(“
Failed to retrieve security ID. Exiting.”)
return
print(f"
Using Security ID: {security_id} (type: {type(security_id)})")
# Subscribe to Full Packet data for LTP
subscribe_inst = [(MarketFeed.NSE_FNO, str(security_id), MarketFeed.Full)]
market_feed = MarketFeed(dhan_context, subscribe_inst, version="v2")
async def on_data_received():
global current_ltp, order_placed, active_orders, candle_data
max_retries = 5
retry_delay = 5
retries = 0
while retries < max_retries:
try:
if not market_feed.ws:
print("🔌 WebSocket not connected, attempting to reconnect...")
await market_feed.connect()
await asyncio.sleep(2)
data = await market_feed.get_instrument_data()
print(f"Raw data: {data}")
if not isinstance(data, dict):
print(f"❌ Invalid data (not a dict): {data}")
return True
data_type = data.get("type")
if data_type == "OI Data":
print(
f"📊 Received OI Data: OI={data.get('OI')}, skipping processing"
)
return True # Skip OI Data and continue receiving next message
if data_type != "Full Data":
print(f"❌ Invalid data type: {data_type}, expected 'Full Data'")
return True
data_security_id = str(data.get("security_id")).strip()
print(
f"🔍 Comparing security IDs: Data ID={data_security_id} (type: {type(data_security_id)}, len: {len(data_security_id)}), Expected ID={security_id} (type: {type(security_id)}, len: {len(security_id)})"
)
if data_security_id == security_id:
current_ltp = data.get("LTP")
try:
ltp = float(current_ltp)
print(
f"📈 Received LTP: {current_ltp} for Security ID: {security_id}"
)
current_time = get_ist_time()
candle_start = get_candle_start_time(current_time)
minute_offset = int(
(current_time - candle_start).total_seconds() // 60
)
# Initialize candle data for this 5-minute candle
if candle_start not in candle_data:
candle_data[candle_start] = [
[] for _ in range(5)
] # List for each minute
# Store LTP for the current minute
candle_data[candle_start][minute_offset].append(ltp)
# Clean up old candle data (keep last 2 candles)
old_candles = [
k
for k in candle_data
if k < candle_start - pd.Timedelta(minutes=5)
]
for k in old_candles:
del candle_data[k]
if order_placed:
print(f"📊 Order already placed, monitoring LTP: {ltp}")
return False # Stop processing after order is placed
# Existing Condition: Buy in first 3 minutes if LTP in range
if is_within_first_3_minutes(current_time):
if BUY_PRICE <= ltp <= BUY_PRICE + 3:
print(f"📈 Buy condition met (price range): LTP {ltp}")
total_quantity = LOT_SIZE * TOTAL_LOTS
quantities = []
if total_quantity > MAX_UNITS_PER_ORDER:
while total_quantity > 0:
qty = min(total_quantity, MAX_UNITS_PER_ORDER)
quantities.append(qty)
total_quantity -= qty
else:
quantities.append(total_quantity)
for qty in quantities:
order = await place_super_order(
BUY_PRICE, security_id, qty
)
if order:
active_orders.append(order)
order_placed = True
asyncio.create_task(
monitor_position(security_id, BUY_PRICE)
)
return False # Stop processing after placing order
else:
print(
f"📉 LTP {ltp} outside buy range ({BUY_PRICE} to {BUY_PRICE + 2})"
)
# New Condition: Buy in 4th minute (3:00–4:00) if any LTP breaks 3-minute high and current LTP in range
elif is_fourth_minute(current_time, candle_start):
# Calculate 3-minute candle high (minutes 0–2)
three_min_high = (
max(
max(candle_data[candle_start][i], default=0)
for i in range(3)
if candle_data[candle_start][i]
)
if any(candle_data[candle_start][i] for i in range(3))
else 0
)
# Max LTP in 4th minute (minute 3)
fourth_min_ltps = candle_data[candle_start][3]
fourth_min_high = max(fourth_min_ltps, default=ltp)
print(
f"🕒 4th minute check (3:00–4:00): 3-min high={three_min_high}, 4th min LTPs={fourth_min_ltps}, 4th min high={fourth_min_high}"
)
if (
three_min_high > 0
and fourth_min_high > three_min_high
and BUY_PRICE <= ltp <= BUY_PRICE + 3
):
print(
f"📈 Buy condition met (4th min breakout): LTP {ltp}, 4th min high {fourth_min_high} > 3-min high {three_min_high}"
)
total_quantity = LOT_SIZE * TOTAL_LOTS
quantities = []
if total_quantity > MAX_UNITS_PER_ORDER:
while total_quantity > 0:
qty = min(total_quantity, MAX_UNITS_PER_ORDER)
quantities.append(qty)
total_quantity -= qty
else:
quantities.append(total_quantity)
for qty in quantities:
order = await place_super_order(
ltp, security_id, qty
)
if order:
active_orders.append(order)
order_placed = True
asyncio.create_task(monitor_position(security_id, ltp))
return False # Stop processing after placing order
else:
print(
f"📉 Breakout failed: 4th min high {fourth_min_high} <= 3-min high {three_min_high} or LTP {ltp} outside range ({BUY_PRICE} to {BUY_PRICE + 2})"
)
except ValueError:
print(f"❌ Invalid LTP value: {current_ltp}")
else:
print(
f"❌ Security ID mismatch: Expected '{security_id}' (type: {type(security_id)}), Got '{data_security_id}' (type: {type(data_security_id)})"
)
return True
except websockets.exceptions.ConnectionClosed as e:
retries += 1
print(f"🔌 Connection closed (attempt {retries}/{max_retries}): {e}")
await market_feed.disconnect()
await asyncio.sleep(retry_delay)
except Exception as e:
retries += 1
print(
f"❌ Error in data processing (attempt {retries}/{max_retries}): {e}"
)
if retries == max_retries:
print("❌ Max retries reached, exiting data processing.")
raise
await market_feed.disconnect()
await asyncio.sleep(retry_delay)
return False
try:
print("🔌 Initiating WebSocket connection...")
await market_feed.connect()
print("✅ WebSocket connection established")
while True:
if order_placed:
print(
"✅ Order placed, stopping trading strategy. Restart script manually to continue."
)
break
if not await on_data_received():
print("✅ Order placed or session ended, stopping trading strategy.")
break
await asyncio.sleep(0.1)
except asyncio.CancelledError:
print("⏹ Program interrupted")
except Exception as e:
print(f"❌ Program terminated with error: {e}")
finally:
try:
if hasattr(market_feed, "ws") and market_feed.ws:
await market_feed.disconnect()
print("🔌 WebSocket connection closed")
except Exception as e:
print(f"❌ Error closing WebSocket: {e}")
Run the trading strategy
if name == “main”:
try:
asyncio.run(trading_strategy())
except KeyboardInterrupt:
print(“
Program interrupted by user”)
except Exception as e:
print(f"
Program terminated with error: {e}")