Learn Advanced Algo Trading Series | Codes | Youtube

Hi Folks,

Our Algo Trading Series, hosted by @Tradehull_Imran, has been incredibly well-received, benefiting 5,000+ traders so far with in-depth, practical insights.

Due to popular demand, we’re back with the second edition of the Algo Trading Series, designed to help our Algo Trading community systematically master advanced algorithmic trading concepts.

Video Series:

Episode 1: Introduction to Advance Algo Trading

Topics covered:
:one: Introduction to Advanced Algo Trading – The series builds upon the basics covered in the previous playlist, focusing on creating fully functional live trading algorithms.

:two: Pandas Library for Data Handling – The session covers how to use Pandas to process market data efficiently, including sorting, filtering, and calculating indicators like moving averages.

:three: Technical Indicators & Customization – Explains how to apply and customize technical indicators such as SMA, Bollinger Bands, MACD, RSI, and Supertrend using Python’s TA-Lib.

:four: Candlestick Pattern Recognition – Demonstrates how to detect common patterns like Doji, Marubozu, and Engulfing patterns programmatically using Python.

:five: Foundation for Building Scanners & Strategies – Sets the stage for the next sessions by discussing how to create personalized scanners and automate strategy execution using algorithmic trading concepts.

Codes: Session 1: Introduction to Advance Algo Trading

Episode 2: How To Create A Scanner & Scanning Option Chain

Topics covered:

Summary: Advanced Algo Trading Series | Episode 2

:pushpin: Introduction to Scanners in Algo Trading

  • Understanding the difference between a scanner and an algo
  • Scanners help identify trade opportunities; algos handle order execution

:pushpin: Creating Different Types of Scanners

  • Basic Scanners: Normal scanner and option chain scanner
  • Indicator-Based Scanners: Using RSI, Supertrend, and candlestick patterns
  • Price Action-Based Scanners: Implementing bullish and bearish engulfing patterns

:pushpin: Building Heikin Ashi & Renko Charts

  • How to convert candlestick data into Heikin Ashi and Renko charts
  • Applying indicators like Supertrend on these charts

:pushpin: Debugging & Testing Scanners

  • Importance of backtesting scanners before live deployment
  • Using print statements and debugging techniques to fix scanner issues
  • Handling errors when stock symbols change or data isn’t available

:pushpin: Option Chain Scanning

  • Understanding the importance of API access to real-time option chain data
  • Fetching option chain data for index and stock options
  • Extracting ATM (At-the-Money) strike prices

:pushpin: Selecting Strikes Based on Data Metrics

  • LTP-Based Selection: Finding strikes with LTP below a certain value
  • Volume & Open Interest-Based Selection: Identifying strikes with the highest volume or OI
  • Change in Open Interest: Spotting potential trend shifts
  • Put-Call Ratio (PCR) Calculation: Using volume and OI to gauge market sentiment

:pushpin: Strategic Approach to Algo Trading

  • Learning fundamental concepts before combining them into an advanced algo
  • Step-by-step approach to integrating scanners, indicators, and execution strategies

:link: Watch the Full Video Here:

Session 2 codes: Session 2.zip - Google Drive

This session provides an in-depth, hands-on approach to creating scanners and working with option chain data—ideal for traders looking to automate their strategies! :rocket:

Episode 3: Advanced Algo Trading Series

:small_blue_diamond: Connecting Algo with Excel – Learn how to integrate Excel to view and control your algo’s decision-making process.
:small_blue_diamond: Automating Trade Execution – Execute buy/sell orders directly from Excel by inputting values.
:small_blue_diamond: Reading & Writing Data in Excel – Learn how to fetch live market data into Excel and track indicators like LTP, RSI, and entry conditions in real-time.
:small_blue_diamond: Managing Trades with API – How to execute, modify, and track orders dynamically.
:small_blue_diamond: Rate Limits & Optimization – Techniques to make your algo more efficient and avoid API rate limitations.
:small_blue_diamond: Creating a Mini RoboCop – Build a simplified trading bot that automates order placement & risk management via Excel.
:small_blue_diamond: Upcoming in Part 2 – Automating option chain updates and sending alerts via Telegram for key trade updates.

This episode is a must-watch for traders looking to bridge the gap between algo trading and Excel automation. :rocket:

Watch the video :point_down:

Stay tuned for the next episodes! From here on, we will upload two weekly videos for everyone to learn and implement!

Episode 3 codes: Session 3.zip - Google Drive

Episode 4: Framework of Live Algo

In Episode 4, we dive into building a structured framework for live algo trading, ensuring precision, scalability, and efficiency.

:small_blue_diamond: Key Highlights:

:white_check_mark: Blueprint for Live Algo – A structured approach to executing strategies seamlessly.
:white_check_mark: Managing Multiple Positions – Track & automate entries, exits, SL, and P&L dynamically.
:white_check_mark: Trade Execution & Monitoring – Build an order book system for real-time tracking.
:white_check_mark: Re-Entry & Risk Management – Avoid duplicate trades, implement trailing SL & pyramiding.
:white_check_mark: Testing & Debugging – Simulate trades before going live for smooth execution.

:rocket: Why Watch? Learn how to automate & scale your trading system with a powerful framework!
:point_right: Watch now for real-time coding & implementation! :movie_camera::fire:

Code files for Episode 4: Session 4.zip - Google Drive

Episode 5: Testing Your Algo

Code files: Session 5.zip - Google Drive

Episode 6 is now live!

Watch it here:

Here are the codes:

Epsiode 7 is now live:

Here are the codes:
Session 7.zip - Google Drive

Episode 8:

Here are the codes:

Episode 9 :

Here are the codes:

Episode 10 :

Here are the codes:

Episode 11 :slight_smile:

Here are the codes:

As usual, @Tradehull_Imran will be there to help you with any doubts!

19 Likes

Hi @RahulDeshpande ,
FYI,

This link is not working.
It is redirecting to,
https://github.com/TradeHull/Dhan_Tradehull

Hi @Tradehull_Imran ,

I am facing an error while fetching OHLC data while executing the following code. Please resolve the issue

Here is the Code…

import time
import datetime
from Dhan_Tradehull import Tradehull
import pandas as pd
import talib
import logging
from dotenv import load_dotenv
import os

# Load environment variables
load_dotenv('dhan.env')

# API credentials
client_code = os.getenv('CLIENT_ID')
token_id = os.getenv('API_KEY')

broker = Tradehull(client_code, token_id)

# Global variables for position tracking
active_position = None

def clear_screen():
    """Clear the terminal screen"""
    os.system('cls' if os.name == 'nt' else 'clear')

def display_header(title):
    """Display section header"""
    clear_screen()
    print(f"\n{'='*50}")
    print(f"{title.center(50)}")
    print(f"{'='*50}\n")

def select_from_list(options, prompt):
    """Display a numbered list and return selected value"""
    for idx, option in enumerate(options, 1):
        print(f"{idx}. {option}")
    while True:
        try:
            choice = int(input(f"\n{prompt} (1-{len(options)}): "))
            if 1 <= choice <= len(options):
                return options[choice-1]
            print("Invalid choice. Please try again.")
        except ValueError:
            print("Please enter a number.")

def get_instrument():
    """Select trading instrument"""
    instruments = ["NIFTY", "BANKNIFTY", "SENSEX"]
    return select_from_list(instruments, "Select Instrument")

def get_expiry(instrument):
    """Select expiry date"""
    expiries = broker.get_expiry_list(Underlying=instrument, exchange='INDEX')
    return select_from_list(expiries, "Select Expiry")

def get_quantity(instrument):
    """Get quantity input with lot size display"""
    try:
        lot_size = int(broker.get_lot_size(tradingsymbol=instrument))
        print(f"\n\033[1;36mLot size for {instrument}: {lot_size}\033[0m")
    except:
        # Fallback hardcoded lot sizes
        lot_sizes = {"NIFTY": 50, "BANKNIFTY": 25, "SENSEX": 10}
        lot_size = lot_sizes.get(instrument, 1)
        print(f"\n\033[1;33mUsing default lot size for {instrument}: {lot_size}\033[0m")
    
    while True:
        try:
            lots = int(input("\nEnter number of lots: "))
            total_qty = lots * lot_size
            print(f"\033[1;36mTotal Quantity: {total_qty}\033[0m")
            return total_qty
        except ValueError:
            print("\033[1;31mPlease enter a valid number.\033[0m")

def get_product_type():
    """Select product type with warnings"""
    product = select_from_list(["MIS", "CNC"], "Select Product Type")
    print("\n\033[1;33m" + "="*50)
    if product == "MIS":
        print("⚠️  Exiting MIS trade at 3:25 PM")
    else:
        print("ℹ️  CNC trade will continue to the next day.")
    print("="*50 + "\033[0m")
    return product

def get_order_type(instrument, ltp):
    """Select order type with strike info"""
    # Ensure ltp is a numeric value
    try:
        if isinstance(ltp, dict):
            ltp = float(ltp.get('last_price', 0))
        else:
            ltp = float(ltp)
    except (ValueError, TypeError):
        print("\n\033[1;31mError: Could not fetch valid LTP!\033[0m")
        return None, None
    
    # Calculate step size
    step = broker.index_step_dict.get(instrument, 50)
    
    # Calculate ATM strike
    atm_strike = round(ltp / step) * step
    
    # Order type selection
    order_type = select_from_list(["MARKET", "LIMIT"], "Select Order Type")
    
    # Display strike info
    print("\n\033[1;36m" + "="*50)
    if order_type == "MARKET":
        print(f"ATM Price: {atm_strike}")
    else:
        strikes = [atm_strike + (i * step) for i in range(1, 6)]
        print("OTM Strikes:")
        print(", ".join([f"OTM{i+1}: {strike}" for i, strike in enumerate(strikes)]))
    print("="*50 + "\033[0m")
    
    return order_type, atm_strike

def get_valid_strikes(instrument, indicators, order_type):
    ltp = indicators['close']
    step = broker.index_step_dict.get(instrument, 50)
    atm_strike = round(ltp / step) * step
    strikes = [atm_strike + (i * step) for i in range(-3, 7)]
    
    h4, h3, l3, l4 = indicators['pivots']
    ema13, ema21, ema34 = indicators['emas']
    close = indicators['close']
    
    valid_strikes = []
    for strike in strikes:
        is_otm = (strike > ltp) if (close >= h4 or close <= l3) else (strike < ltp)
        ema_condition = (close > ema13 and close > ema21 and close > ema34) if is_otm else (
                        close < ema13 and close < ema21 and close < ema34)
        
        if indicators['cpr_class'] in ['Narrow', 'Normal'] and ema_condition:
            if order_type == 'LIMIT' and is_otm:
                valid_strikes.append(strike)
            elif order_type == 'MARKET' and strike == atm_strike:
                valid_strikes.append(strike)
    
    return valid_strikes, atm_strike


def get_strike_price(instrument, indicators, order_type):
    valid_strikes, atm_strike = get_valid_strikes(instrument, indicators, order_type)
    
    if order_type == 'MARKET':
        if atm_strike in valid_strikes:
            print(f"\nAuto-selected ATM strike: {atm_strike}")
            return atm_strike
        print("\nNo valid ATM strike available based on strategy rules")
        return None
    
    if not valid_strikes:
        print("\nNo valid strikes available based on strategy rules")
        return None
    
    return select_from_list(valid_strikes, "Select Strike Price")

def calculate_indicators(data):
    """Calculate technical indicators with validation"""
    try:
        # Validate input data
        required_columns = ['open', 'high', 'low', 'close']
        if not all(col in data.columns for col in required_columns):
            raise ValueError(f"Missing required columns: {required_columns}")
        
        # EMAs
        data['13_EMA'] = talib.EMA(data['close'], timeperiod=13)
        data['21_EMA'] = talib.EMA(data['close'], timeperiod=21)
        data['34_EMA'] = talib.EMA(data['close'], timeperiod=34)
        
        # ATR
        data['ATR'] = talib.ATR(data['high'], data['low'], data['close'], 14)
        
        # CPR Calculations
        high = data['high'].iloc[-1]
        low = data['low'].iloc[-1]
        close = data['close'].iloc[-1]
        pivot = (high + low + close) / 3
        bc = (high + low) / 2
        tc = (pivot - bc) + pivot
        cpr_width = ((tc - bc) / pivot) * 100
        
        cpr_class = 'Wide'
        if cpr_width <= 20: cpr_class = 'Narrow'
        elif cpr_width <= 25: cpr_class = 'Normal'
        
        # Camarilla Pivots
        h4 = close + (high - low) * 1.1 / 2
        h3 = close + (high - low) * 1.1 / 4
        l3 = close - (high - low) * 1.1 / 4
        l4 = close - (high - low) * 1.1 / 2
        
        return {
            'cpr_class': cpr_class,
            'h4': h4,
            'h3': h3,
            'l3': l3,
            'l4': l4,
            'close': close,
            'emas': (data['13_EMA'].iloc[-1], data['21_EMA'].iloc[-1], data['34_EMA'].iloc[-1]),
            'ATR': data['ATR'].iloc[-1]
        }
        
    except Exception as e:
        print(f"\n\033[1;31mError calculating indicators: {str(e)}\033[0m")
        return None

def strategy_1(data, broker, params):
    """CPR-EMA Strategy Implementation"""
    try:
        data, cpr_class, h4, h3, l3, l4 = calculate_indicators(data)
        close = data['close'].iloc[-1]
        ema_13 = data['13_EMA'].iloc[-1]
        ema_21 = data['21_EMA'].iloc[-1]
        ema_34 = data['34_EMA'].iloc[-1]

        signal = None
        if cpr_class in ['Narrow', 'Normal']:
            if (close <= l3 or close >= h4) and close > ema_13 and close > ema_21 and close > ema_34:
                signal = 'Buy'
            elif (close >= h3 or close <= l4) and close < ema_13 and close < ema_21 and close < ema_34:
                signal = 'Sell'
        
        if signal:
            result = broker.execute_trade(
                instrument=params['instrument'],
                expiry=params['expiry'],
                quantity=params['quantity'],
                product=params['product'],
                order_type=params['order_type'],
                strike=params['strike']
            )
            return result
        return None
    except Exception as e:
        logging.error(f"Strategy 1 error: {str(e)}")
        print("\n\033[1;31mStrategy entry conditions not met!\033[0m")
        print("Required conditions:")
        print("- Close price beyond H4/L3 Camarilla levels")
        print("- EMA alignment (price above/below all 3 EMAs)")
        return None

def execute_strategy():
    """Execute trading strategy"""
    global active_position

    display_header("Execute Trading Strategy")
    
    # Strategy Selection
    strategies = [
        "CPR-EMA Strategy", 
        "Momentum Breakout Strategy",
        "Mean Reversion Strategy",
        "MACD Crossover Strategy",
        "Bollinger Bands Strategy"
    ]
    strategy = select_from_list(strategies, "Select Trading Strategy")
    
    if strategy != "CPR-EMA Strategy":
        print("\n\033[1;33mSelected strategy is not implemented yet!\033[0m")
        return

    # Get trade parameters
    instrument = get_instrument()
    expiry = get_expiry(instrument)

    try:
        # Fetch and process OHLC data
        raw_data = broker.get_ohlc_data([instrument])
        if not isinstance(raw_data, dict) or instrument not in raw_data:
            raise ValueError("Invalid data format received from broker")
        
        instrument_data = raw_data[instrument]
        if not isinstance(instrument_data, dict):
            raise ValueError("Unexpected data structure for instrument OHLC")
        
        # Create DataFrame with proper column names
        data = pd.DataFrame([{
            'close': instrument_data.get('last_price'),
            'high': instrument_data.get('day_high'),
            'low': instrument_data.get('day_low'),
            'open': instrument_data.get('day_open')
        }])
        
        # Validate required columns
        if data.isnull().values.any():
            missing = data.columns[data.isnull().any()].tolist()
            raise ValueError(f"Missing data for columns: {missing}")
        
        indicators = calculate_indicators(data)
    except Exception as e:
        print(f"\nError processing market data: {str(e)}")
        return

    order_type = get_order_type()
    strike = get_strike_price(instrument, indicators, order_type)

    if not strike:
        print("Aborting trade execution due to invalid strike price")
        return
    
    quantity = get_quantity(instrument)
    product = get_product_type()

    # Check market hours
    if not is_market_open():
        print("\nMarket is closed. Trading not allowed.")
        return

    # Execute trade
    try:
        params = {
            "instrument": instrument,
            "expiry": expiry,
            "quantity": quantity,
            "product": product,
            "order_type": order_type,
            "strike": strike
        }


        result = strategy_1(pd.DataFrame(ohlc_data), broker, params)

        if result:
            active_position = {
                "strategy": strategy,
                "instrument": instrument,
                "strike": strike,
                "quantity": quantity,
                "product": product,
                "order_type": order_type,
                "expiry": expiry,
                "timestamp": datetime.datetime.now()
            }
            print("\n\033[1;32mTrade executed successfully!\033[0m")
            print("Order Details:", result)
        else:
            print("\n\033[1;31mTrade execution failed!\033[0m")
    except Exception as e:
        logging.error(f"Strategy Execution Error: {str(e)}")
        print(f"\n\033[1;31mError executing trade: {str(e)}\033[0m")

def close_position():
    """Close active position"""
    global active_position

    display_header("Close Position")
    if not active_position:
        print("No active position to close")
        return

    print("Current Position Details:")
    for key, value in active_position.items():
        print(f"{key.capitalize()}: {value}")

    confirm = input("\nAre you sure you want to close this position? (y/n): ").lower()
    if confirm == 'y':
        try:
            result = broker.execute_trade(
                instrument=active_position['instrument'],
                expiry=active_position['expiry'],
                quantity=active_position['quantity'],
                product=active_position['product'],
                order_type="MARKET",
                strike=active_position['strike'],
                transaction_type="SELL"
            )
            if result:
                active_position = None
                print("\nPosition closed successfully!")
            else:
                print("\nFailed to close position")
        except Exception as e:
            print(f"\nError closing position: {str(e)}")

def is_market_open():
    """Check if market is open"""
    now = datetime.datetime.now().time()
    market_open = datetime.time(9, 15)  # Market opens at 9:15 AM
    market_close = datetime.time(15, 30)  # Market closes at 3:30 PM
    return market_open < now < market_close

def account_info():
    print("\n=== Account Information ===")
    try:
        balance = broker.get_balance()
        positions = broker.get_positions()
        orders = broker.get_orderbook()
        
        print(f"\nAccount Balance: ₹{balance:,.2f}")
        
        print("\nActive Positions:")
        if not positions.empty:
            print(positions)
        else:
            print("No active positions")
        
        print("\nOrder Book:")
        if not orders.empty:
            print(orders)
        else:
            print("No active orders")
    except Exception as e:
        print(f"\nError fetching account info: {str(e)}")

def main_menu():
    while True:
        print("\n=== Main Menu ===")
        print("1. Execute Strategy")
        print("2. Close Position")
        print("3. Account Info")
        print("4. Exit")
        
        choice = input("Select Action (1-4): ")
        
        if choice == "1":
            execute_strategy()
        elif choice == "2":
            close_position()
        elif choice == "3":
            account_info()
        elif choice == "4":
            print("\nExiting program...")
            break
        else:
            print("Invalid choice. Please try again.")

if __name__ == "__main__":
    main_menu()

And Here is the ERROR…

Select Instrument (1-3): 1
1. 2025-02-20
2. 2025-02-27
3. 2025-03-06
4. 2025-03-13
5. 2025-03-20
6. 2025-03-27
7. 2025-04-24
8. 2025-06-26
9. 2025-09-25
10. 2025-12-24
11. 2026-06-25
12. 2026-12-31
13. 2027-06-24
14. 2027-12-30
15. 2028-06-29
16. 2028-12-28
17. 2029-06-28
18. 2029-12-27

Select Expiry (1-18): 1

Error processing market data: Missing data for columns: ['high', 'low', 'open']

=== Main Menu ===
1. Execute Strategy
2. Close Position
3. Account Info
4. Exit
Select Action (1-4):

Some parameters related error i think in fetching OHLC from Tradehull class. Please help me.

1 Like

Episode 2: How To Create A Scanner & Scanning Option Chain session 2 codes is now up!

Hope you all are liking this series till now.

8 Likes

Yes, I have already Watched 2 Episodes. Thanks to Imran Ali sir, for his sincere efforts in explaining the concepts. I have to make in depth study and try using the codes.
Thanks again to the Dhan/TradeHull Team involved in developing and making the interested people to learn.
VBR Prasad

2 Likes

Episode 3 is now LIVE!

The topic can be of interest to a lot of algo trading enthusiasts:

1 Like

Very Good Morning Sir,
May I know the reason for not Using: Dhan_TradeHull_V2 is not imported . What’s the reason sir?
VBR Prasad

Dear Imran Sir, Greatest content you are producing for indian learners…
I would request please help us in reply, How to code for Trailing stop loss once SL order is provided

1 Like

Also waiting for PART 2 of Episode 3 eagerly…
Thanks and Regards

Hello @Tradehull_Imran Sir,

I am trying to access the existing code which you provided in google drive

I am getting below error:

8. Tick By TICK Option Chain.py"
Codebase Version 3
-----Logged into Dhan-----
reading existing file all_instrument 2025-02-26.csv
Got the instrument file
Traceback (most recent call last):
  File "c:/Projects/Algo_Web/AlgoPython/AdvanceAlgo/8. Tick By TICK Option Chain.py", line 22, in <module>
    atm_strike, option_chain = tsl.get_option_chain(Underlying="NIFTY", exchange="INDEX", expiry=1,num_strikes=15)
TypeError: get_option_chain() got an unexpected keyword argument 'num_strikes'

I checked with latest Dhan_Tradehull lib file that get_option_chain() defination contains no parameter called num_strikes. Can you share latest Dhan_Tradehull lib file?

Thanks,
Sudip

Hi @Tradehull, I’m facing the same error as well. I’ve upgraded to Dhan_Tradehull version 3.0.5, but still facing the issue
Thanks

Hi Sir, Good Evening. While practicing the Episode 1, I have come across the following Error sir. How to resolve it?

At cmd Prompt:

(Pdb++) new_chart[‘high’][‘max’]
*** KeyError: ‘max’
Traceback (most recent call last):
File “C:\Users\RP\AppData\Local\Programs\Python\Python38\lib\site-packages\pandas\core\series.py”, line 1007, in getitem
return self._get_value(key)
File “C:\Users\RP\AppData\Local\Programs\Python\Python38\lib\site-packages\pandas\core\series.py”, line 1116, in _get_value
loc = self.index.get_loc(label)
File “C:\Users\RP\AppData\Local\Programs\Python\Python38\lib\site-packages\pandas\core\indexes\range.py”, line 349, in get_loc
raise KeyError(key)

https://madefortrade.in/t/i-got-error-while-i-write-right-code-which-sir-teach-for-scanning-option-chain/44446?u=skillet_flash

Hi @Tradehull_Imran ,

I’m facing issue with the HeikenAshi Candle,

using HA candle,
I want to print data of HighestHigh of Length 20.

Please help me out.

bai iam also facing same problem

sir provide session 4 code

pls add fibbonnaci sir

Hi @Akshay_Bawane ,

Do update the codebase, Use the below code:
pip install --upgrade Dhan-Tradehull

1 Like

Hi @SUDIP_NATH ,

Do update the codebase :
pip install --upgrade Dhan-Tradehull

Refer the below pypi link for more details:
https://pypi.org/project/Dhan-Tradehull/