Please correct my code for Trading strategy and Performance Metrics

Please check all Performance Metrics and let me know is it correct or not ? 

import pandas as pd
import numpy as np
import talib as ta


# Data reading
columns = ['index','Date','Open','High','Low','Close','Volume','OI']
df = pd.read_csv(r'D:/Algorithmic Trading Proejct/Project/stock_data/downloaded_data/nifty_bank_10minute.txt', names=columns, index_col='Date')
df.drop(['index','Volume','OI'], axis=1, inplace=True)
df = pd.DataFrame(df)

#---------------------- DEMA Indicators ---------------------#

df['DEMA21'] = ta.DEMA(df['Close'], 21)
df['DEMA42'] = ta.DEMA(df['Close'], 42)

#---------------------- Creat Buy and Sell Postion ---------------------#
account_size= 1000000
buy_teade_Postion={}
sell_teade_Postion={}
buy_postion = 0 
sell_postion = 0 
postion_size = 1


for i in range(1,len(df)):  
    # Buy   
    if df['DEMA21'][i] > df['DEMA42'][i] and buy_postion == 0:
        buy_postion = 1
        buy_teade_Postion[i]= {
                   'Date': df.index[i],
                   'Single': 'Buy',
                   'postion_size' :postion_size,               
                   'Enter_Price' : df['Close'][i],                  
                   'Exit_Price' : 0,
           }
    # exit Buy
    elif df['Close'][i] < df['DEMA42'][i]  and buy_postion == 1:
        buy_postion = 0
        buy_teade_Postion[i]= {
                   'Date': df.index[i],
                   'Single': 'SL', 
                   'postion_size' :postion_size,                 
                   'Enter_Price' : 0,                                
                   'Exit_Price' : df['Close'][i],
           }   
    # Sell
    elif df['DEMA21'][i] < df['DEMA42'][i] and sell_postion == 0:
        sell_postion = 1
        sell_teade_Postion[i]= {
                   'Date': df.index[i],
                   'Single': 'Sell',
                   'postion_size' :postion_size,               
                   'Enter_Price' : df['Close'][i],                  
                   'Exit_Price' : 0,
           }
    # exit Sell
    elif df['Close'][i] > df['DEMA42'][i]  and sell_postion == 1:
        sell_postion = 0
        sell_teade_Postion[i]= {
                   'Date': df.index[i],
                   'Single': 'Sl', 
                   'postion_size' :postion_size,                 
                   'Enter_Price' : 0,                                
                   'Exit_Price' : df['Close'][i],
           }
    
        
#buy strategy returns   
buy_teade_Postion = pd.DataFrame.from_dict(buy_teade_Postion, orient='index')
buy_teade_Postion.set_index(buy_teade_Postion['Date'], inplace = True)
buy_teade_Postion['buy_strategy_returns'] = (buy_teade_Postion['Exit_Price'] - buy_teade_Postion['Enter_Price'].shift(1)) * postion_size

# Sell strategy returns 
sell_teade_Postion = pd.DataFrame.from_dict(sell_teade_Postion, orient='index')
sell_teade_Postion.set_index(sell_teade_Postion['Date'], inplace = True)
sell_teade_Postion['sell_strategy_returns'] = (sell_teade_Postion['Enter_Price'].shift(1) - sell_teade_Postion['Exit_Price']) * postion_size

# Creat total teade Postion
total_teade_Postion = buy_teade_Postion.append(sell_teade_Postion)

# Remove NaN Value 
total_teade_Postion['sell_strategy_returns'] = total_teade_Postion['sell_strategy_returns'].fillna(0)
total_teade_Postion['buy_strategy_returns'] = total_teade_Postion['buy_strategy_returns'].fillna(0)

#Total strategy returns
total_teade_Postion['strategy_returns'] = total_teade_Postion['buy_strategy_returns'] + total_teade_Postion['sell_strategy_returns']


# create df strategy_returns for Buy and Sell
df['strategy_returns'] = total_teade_Postion['strategy_returns']

df['strategy_returns'] = df['strategy_returns'].fillna(0)

#Total strategy returns
df['returns'] = df['strategy_returns'].cumsum() + account_size


# Calculate Total Profit
def Total_Profit_percentage (df):
    FirstValue = df['returns'].iloc[0]
    LastValue = df['returns'].iloc[-1]
    total =  ((LastValue - FirstValue) / FirstValue )* 100
    return total

# Calculate compounded annual growth rate
def get_CAGR(df,  price_col_name = "Adj Close"):
    intraday_trading_hours = 6
    days = len(df)/intraday_trading_hours
    return "{0:.2f}%".format((df[price_col_name].iloc[-1]**(252/days)-1)*100)

# Calculate annualised volatility
def get_annualised_volatility(df,  price_col_name = "Adj Close"):       
    return "{0:.2f}%".format(df[price_col_name].std()*np.sqrt(252) * 100)

# Calculate Sharpe ratio
def get_sharpe_ratio(df,  price_col_name = "Adj Close"):
    risk_free_rate = 0.02/252       
    return np.sqrt(252)*(np.mean(df[price_col_name]) - (risk_free_rate))/np.std(df[price_col_name])

# Calculate the maximum drawdown
def get_max_drawdown(df,  price_col_name = "Adj Close"):
    df['Peak'] = df[price_col_name].cummax()
    df['Drawdown'] = ((df[price_col_name]- df['Peak'])/df['Peak'])
    return "{0:.2f}%".format((df['Drawdown'].min())*100)


def print_strategy_summary(df, price_col_name = "Adj Close"):
    print("Total Profit:", Total_Profit_percentage(df))
    print("CAGR:", get_CAGR(df, price_col_name = price_col_name))
    print("annualised volatility:", get_annualised_volatility(df, price_col_name = price_col_name))
    print("Sharpe ratio:", get_sharpe_ratio(df, price_col_name = price_col_name))  
    print("Maximum drawdown:", get_max_drawdown(df, price_col_name = price_col_name))  



print(print_strategy_summary(df, price_col_name = "returns"))

Total Profit: 4.808780000000005

CAGR: 71.47%

annualised volatility: 25121290.81%

Sharpe ratio: 1021.9114652415966

Maximum drawdown: -0.57%

Hi Shirish,

Based on the first looks of the results posted above, it seems as though there may be something wrong here. And to fix it, you can expand your knowledge about ways to correctly evaluate your trading strategy's performance.



For a start, I encourage you to check out the practice modules covering Sharpe Ratio and Maximum Drawdown on Quantra:



Alternatively, you can also make use of packages such as pyfolio for quickly evaluating and generating strategy results. The same can then be used as a benchmark for comparison, to eventually find the inconsistencies in your own code.



I hope this helped.

Thanks… i try to use pyfolio but also give same error on my data… i add pyfolio and share error

i used vectorbt  for Performance Metrics but not much confidence on output  is it correct or not ?

import pandas as pd
import numpy as np
from sqlalchemy import false, true
import talib as ta
import vectorbt as bt



#---------------------- Stock data reading ---------------------#
columns = ['index','Date','Open','High','Low','Close','Volume','OI']
df = pd.read_csv(r'D:/Algorithmic Trading Proejct/Project/stock_data/downloaded_data/nifty_bank_10minute.txt', names=columns, index_col='Date')
df.drop(['index','Volume','OI'], axis=1, inplace=True)
data = pd.DataFrame(df)

#---------------------- Stock data Indicators ---------------------#

data['SMA_48_high'] = ta.SMA(data['High'], 48)
data['SMA_48_low'] = ta.SMA(data['Low'], 48)
data['ADX'] = ta.ADX(data['High'], data['Low'], data['Close'], timeperiod=14)


#---------------------- Stock data Buy and Sell ---------------------#
data['buy'] = np.where((data['Close'] > data['SMA_48_high']) & (data['ADX'] > 30), True, False)
data['exit_buy'] = np.where(data['Close'] < data['SMA_48_low'], True, False)
data['sell'] = np.where((data['Close'] < data['SMA_48_low']) & (data['ADX'] > 30), True, False)
data['exit_sell'] = np.where(data['Close'] > data['SMA_48_high'] , True, False)


#---------------------- Stock data Returns ---------------------#
print(data)
Portfolio = bt.Portfolio.from_signals(init_cash=1000000,
                                        size=250,
                                        close=data['Close'],
                                        entries=data['buy'],
                                        exits=data['exit_buy'],
                                        short_entries=data['sell'],
                                        short_exits=data['exit_sell'],
                                        direction='both'
                                        )
pf = Portfolio.stats()
print(pf)

Start                         2018-06-01T09:15:00+0530

End                           2022-07-22T15:25:00+0530

Period                                           38870

Start Value                                  1000000.0

End Value                               3464563.639986

Total Return [%]                            246.456364

Benchmark Return [%]                          36.56439

Max Gross Exposure [%]                           100.0

Avg Losing Trade [%]                         -0.731816

Avg Winning Trade Duration                   72.126214

Avg Losing Trade Duration                    24.212389

Profit Factor                                 1.199427

Expectancy                                 4512.219899

Hello Shirish,

Would it be possible for you to share the data file that you are presently working on?

Following this, we will compute certain performance metrics at our end and share them along, for ease of comparison.



Also regarding the pyfolio error, we will get back to you shortly on this thread.



Thanks!