Please help my code some error i not understand where is i mistake,
error below
PS D:\Dhan Practice> & C:/Users/Lenovo1/AppData/Local/Programs/Python/Python313/python.exe “d:/Dhan Practice/Dhan_KBS.py”
Codebase Version 3
Codebase Version 3
-----Logged into Dhan-----
-----Logged into Dhan-----
reading existing file all_instrument 2025-10-31.csv
reading existing file all_instrument 2025-10-31.csv
Got the instrument file
— Starting MACD Crossover Strategy —
— Performing Initial Daily Scan —
— Pre-filtering watchlist by price (₹25 - ₹5000) —
Price filter reduced watchlist from 199 to 170 stocks.
— Initial Daily Scan Complete. Starting trading loop. —
Current Day P&L: ₹0.00
Scanning for new trades at 15:04:15…
Not enough historical data for M&MFIN
BUY signal (Supertrend Confirmed) for PREMIERENE at 1098.6
'Got exception in place_order as {‘status’: ‘failure’, ‘remarks’: {‘error_code’: ‘DH-906’, ‘error_type’: ‘Order_Error’, ‘error_message’: ‘Basic Validation Failed’}, ‘data’: {‘errorType’: ‘Order_Error’, ‘errorCode’: ‘DH-906’, ‘errorMessage’: ‘Basic Validation Failed’}}
BUY signal (Supertrend Confirmed) for SUPREMEIND at 3825.2
'Got exception in place_order as {‘status’: ‘failure’, ‘remarks’: {‘error_code’: ‘DH-906’, ‘error_type’: ‘Order_Error’, ‘error_message’: ‘Basic Validation Failed’}, ‘data’: {‘errorType’: ‘Order_Error’, ‘errorCode’: ‘DH-906’, ‘errorMessage’: ‘Basic Validation Failed’}}
Current available balance after scan: ₹5134.86
— Scan complete. Waiting for the next 15-minute candle… —
import pdb
from Dhan_Tradehull import Tradehull
import pandas as pd
import talib
import numpy as np
import pandas_ta as ta
import requests
import datetime
import time
import json
BASE_URL = "https://api.dhan.co/v2"
try:
with open('config.json', 'r') as f:
config = json.load(f)
client_id = config['client_id']
access_token = config['access_token']
except FileNotFoundError:
print("Error: config.json not found. Please create it with your client_id and access_token.")
exit()
tsl = Tradehull(client_id, access_token)
try:
with open('stocks.json', 'r') as f:
stocks_data = json.load(f)
stocks = stocks_data['stocks']
except FileNotFoundError:
print("Error: stocks.json not found. Please create it with a list of stock symbols.")
stocks = []
CAPITAL_ALLOCATION_PERCENT = 0.50
RISK_REWARD_RATIO = 2.0
ATR_PERIOD = 14
ATR_MULTIPLIER = 1.5
MAX_DAILY_LOSS = -2000
MAX_DAILY_TRADES = 6
RISK_PER_TRADE_PERCENT = 0.02
MAX_RISK_PER_TRADE_RUPEES = 500
def get_price_filtered_watchlist(full_watchlist):
print("--- Pre-filtering watchlist by price (₹25 - ₹5000) ---")
filtered_stocks = []
try:
ltp_data = tsl.get_ltp_data(full_watchlist)
if not ltp_data:
print("Could not fetch LTP data for watchlist. Using full list.")
return full_watchlist
for stock, price in ltp_data.items():
if 25 < price < 5000:
filtered_stocks.append(stock)
print(f"Price filter reduced watchlist from {len(full_watchlist)} to {len(filtered_stocks)} stocks.")
return filtered_stocks
except Exception as e:
print(f"Error during price filtering: {e}. Using full list.")
return full_watchlist
def round_to_tick(price, tick_size=0.05):
"""Rounds a price to the nearest valid tick size."""
return round(price / tick_size) * tick_size
def run_macd_strategy():
print("--- Starting MACD Crossover Strategy ---")
print("\n--- Performing Initial Daily Scan ---")
eligible_stocks = get_price_filtered_watchlist(stocks)
print("--- Initial Daily Scan Complete. Starting trading loop. ---")
if not eligible_stocks:
print("No eligible stocks found after price filtering. The script will wait for the next day.")
kill_switch_activated = False
trades_today_count = 0
current_day = datetime.date.today()
try:
positions_df = tsl.get_positions()
open_positions = {}
if positions_df is not None and not positions_df.empty:
open_positions_df = positions_df[positions_df['netQty'] != 0]
order_book_df = tsl.get_orderbook()
if order_book_df is not None and not order_book_df.empty:
co_orders = order_book_df[(order_book_df['productType'] == 'CO') & (order_book_df['orderStatus'] == 'TRADED')]
for index, row in open_positions_df.iterrows():
parent_order = co_orders[co_orders['tradingSymbol'] == row['tradingSymbol']].iloc[0] if not co_orders[co_orders['tradingSymbol'] == row['tradingSymbol']].empty else None
if parent_order is not None:
open_positions[row['tradingSymbol']] = {
'qty': row['netQty'], 'orderId': parent_order['orderId'],
'sl': parent_order['stopLoss'], 'direction': parent_order['transactionType']
}
if open_positions:
print(f"Found existing open positions: {list(open_positions.keys())}")
except Exception as e:
print(f"Warning: Could not fetch initial positions: {e}")
open_positions = {}
while True:
try:
current_time = datetime.datetime.now().time()
if current_time > datetime.time(15, 30):
print("Market is closed (after 15:30). Stopping strategy for the day.")
break
if datetime.date.today() != current_day:
print("New day detected. Resetting daily limits and kill switch.")
current_day = datetime.date.today()
kill_switch_activated = False
trades_today_count = 0
print("\n--- Performing Initial Daily Scan for new day---")
eligible_stocks = get_price_filtered_watchlist(stocks)
print("--- Initial Daily Scan Complete. Starting trading loop. ---")
if kill_switch_activated:
print(f"Kill switch is active. No new trades will be placed today. Waiting for next day.")
time.sleep(60 * 5)
continue
available_balance = tsl.get_balance()
if not available_balance or available_balance == 0:
print("Could not fetch balance or balance is zero. Waiting...")
time.sleep(60)
continue
risk_from_capital = available_balance * RISK_PER_TRADE_PERCENT
risk_amount = min(risk_from_capital, MAX_RISK_PER_TRADE_RUPEES)
live_pnl = tsl.get_live_pnl()
print(f"Current Day P&L: ₹{live_pnl:.2f}")
if live_pnl is not None and live_pnl < MAX_DAILY_LOSS:
print(f"!!! MAX DAILY LOSS of ₹{MAX_DAILY_LOSS} REACHED. ACTIVATING KILL SWITCH. !!!")
print("--- Closing all open MIS/BO positions. ---")
tsl.cancel_all_orders(trade_type='CO')
kill_switch_activated = True
continue
if open_positions:
print("--- Managing open positions ---")
for symbol, trade_info in list(open_positions.items()):
end_date = datetime.date.today()
start_date = end_date - datetime.timedelta(days=5)
hist_data_15min = tsl.get_historical_data(symbol, 'NSE', '15',
start_date=start_date.strftime('%Y-%m-%d'),
end_date=end_date.strftime('%Y-%m-%d'))
if hist_data_15min is None or len(hist_data_15min) < 30: continue
macd, macdsignal, _ = talib.MACD(hist_data_15min['close'], fastperiod=12, slowperiod=26, signalperiod=9)
previous_macd = macd.iloc[-2]
latest_macd = macd.iloc[-1]
previous_signal = macdsignal.iloc[-2]
latest_signal = macdsignal.iloc[-1]
if trade_info['direction'] == 'BUY' and previous_macd > previous_signal and latest_macd < latest_signal:
print(f"EXIT (MACD Crossover): Closing BUY on {symbol} at {hist_data_15min['close'].iloc[-1]}")
tsl.order_placement(
tradingsymbol=symbol, exchange='NSE', quantity=trade_info['qty'], price=0,
trigger_price=0, order_type='MARKET', transaction_type='SELL', trade_type='MIS'
)
del open_positions[symbol]
continue
try:
hist_data = hist_data_15min
if hist_data is None or hist_data.empty:
continue
atr = talib.ATR(hist_data['high'], hist_data['low'], hist_data['close'], timeperiod=ATR_PERIOD)
latest_close = hist_data['close'].iloc[-1]
latest_atr = atr.iloc[-1]
if pd.isna(latest_atr):
continue
current_sl = trade_info['sl']
if trade_info['direction'] == 'BUY':
new_sl = latest_close - (latest_atr * ATR_MULTIPLIER)
if new_sl > current_sl:
print(f"Trailing SL (in memory) for BUY {symbol} from {current_sl:.2f} to {new_sl:.2f}")
open_positions[symbol]['sl'] = new_sl
if latest_close < open_positions[symbol]['sl']:
print(f"EXIT (Trailing SL Hit): Closing BUY on {symbol} at {latest_close}")
tsl.order_placement(
tradingsymbol=symbol, exchange='NSE', quantity=trade_info['qty'], price=0,
trigger_price=0, order_type='MARKET', transaction_type='SELL', trade_type='MIS'
)
del open_positions[symbol]
except Exception as e:
print(f"Error trailing SL for {symbol}: {e}")
if available_balance <= 0:
print("Balance is zero or less. Skipping scan for new opportunities.")
time.sleep(15 * 60)
continue
print(f"\nScanning for new trades at {datetime.datetime.now().strftime('%H:%M:%S')}...")
for stock_symbol in eligible_stocks:
if trades_today_count >= MAX_DAILY_TRADES:
print("Max daily trades limit reached. No more new trades today.")
break
if stock_symbol in open_positions.keys():
continue
try:
end_date = datetime.date.today()
start_date = end_date - datetime.timedelta(days=5)
hist_data = tsl.get_historical_data(stock_symbol, 'NSE', '15',
start_date=start_date.strftime('%Y-%m-%d'),
end_date=end_date.strftime('%Y-%m-%d'))
if hist_data is None or len(hist_data) < 30:
print(f"Not enough historical data for {stock_symbol}")
continue
macd, macdsignal, macdhist = talib.MACD(hist_data['close'], fastperiod=12, slowperiod=26, signalperiod=9)
atr = talib.ATR(hist_data['high'], hist_data['low'], hist_data['close'], timeperiod=ATR_PERIOD)
rsi = talib.RSI(hist_data['close'], timeperiod=14)
hist_data.ta.supertrend(length=ATR_PERIOD, multiplier=3.0, append=True)
latest_close = hist_data['close'].iloc[-1]
previous_close = hist_data['close'].iloc[-2]
latest_atr = atr.iloc[-1]
latest_rsi = rsi.iloc[-1]
if pd.isna(latest_atr):
continue
if pd.isna(latest_rsi):
continue
latest_macd = macd.iloc[-1]
previous_macd = macd.iloc[-2]
latest_signal = macdsignal.iloc[-1]
previous_signal = macdsignal.iloc[-2]
st_col = f'SUPERT_{ATR_PERIOD}_3.0'
latest_supertrend = hist_data[st_col].iloc[-1]
previous_supertrend = hist_data[st_col].iloc[-2]
two_ago_supertrend = hist_data[st_col].iloc[-3]
two_ago_close = hist_data['close'].iloc[-3]
trade_placed = False
if previous_macd < previous_signal and latest_macd > latest_signal and latest_close > previous_close and (58 < latest_rsi < 70):
print(f"BUY signal (MACD) for {stock_symbol} at {latest_close}")
trade_placed = True
elif not trade_placed:
is_crossover = two_ago_close < two_ago_supertrend and previous_close > previous_supertrend
is_confirmed = latest_close > latest_supertrend
if is_crossover and is_confirmed:
print(f"BUY signal (Supertrend Confirmed) for {stock_symbol} at {latest_close}")
trade_placed = True
if trade_placed:
stop_loss_price = latest_close - (latest_atr * ATR_MULTIPLIER)
trade_placed = True
if trade_placed:
stop_loss_price = latest_close - (latest_atr * ATR_MULTIPLIER)
risk_per_share = latest_close - stop_loss_price
if risk_per_share <= 0: continue
quantity = int(risk_amount / risk_per_share)
if quantity == 0:
print(f"Skipping {stock_symbol}, not enough capital for 1 share.")
continue
order_id = tsl.order_placement(
tradingsymbol=stock_symbol, exchange='NSE', quantity=quantity, price=0,
trigger_price=round_to_tick(stop_loss_price),
order_type='MARKET', transaction_type='BUY', trade_type='CO'
)
if order_id:
print(f"Placed BUY Cover Order for {stock_symbol} | Qty: {quantity} | SL: {stop_loss_price:.2f}")
trades_today_count += 1
print(f"Trades taken today: {trades_today_count}/{MAX_DAILY_TRADES}")
open_positions[stock_symbol] = {
'qty': quantity, 'orderId': order_id,
'sl': stop_loss_price, 'direction': 'BUY'
}
except Exception as e:
print(f"Error processing {stock_symbol}: {e}")
print(f"Current available balance after scan: ₹{available_balance:.2f}")
print("--- Scan complete. Waiting for the next 15-minute candle... ---")
time.sleep(15 * 60)
except KeyboardInterrupt:
print("Strategy stopped by user.")
break
except Exception as e:
print(f"An unexpected error occurred in the main loop: {e}")
time.sleep(60)
if __name__ == "__main__":
run_macd_strategy()


