Trading Strategy: A Guide to K-Nearest Neighbors (KNN) Classifier

Trading Strategy: A Guide to K-Nearest Neighbors (KNN) Classifier

Looking to build a trading strategy for Bank Nifty? In this article, we will explore how the K-Nearest Neighbors (KNN) classifier can enhance your trading decisions. Learn about the code implementation and gain insights into the strategy’s performance.

Read on to discover a step-by-step guide and frequently asked questions (FAQ) related to this powerful approach.

Step 1: Importing Libraries and Data for Bank Nifty

To get started, we import essential libraries like pandas, yfinance, numpy, and pandas_ta. These libraries provide valuable functions for data manipulation, fetching financial data, and performing technical indicator calculations. With these tools in hand, we proceed to download the historical data for Bank Nifty using the yfinance library.

# Importing libraries 
import pandas as pd
import yfinance as yf 
import numpy as np
import pandas_ta as ta

# Downloading Data using yfinance 
start='2020-01-01'
end='2023-01-01'
df = yf.download(tickers="^NSEBANK",
                 period="max",
                )
                #  start=start,   # <- Uncomment and add dates for speciifed period
                #  end=end)

#Adding Dailly percentage returns into the analysis
df['daily_returns']=df['Adj Close'].pct_change()

print("Number of data points are" , len(df))

df['Close'].plot(
    figsize=[15,6],
    title="Closing Prices ",
    xlabel="Dates",
    ylabel="Price")

Step 2: Data Preprocessing for Accurate Analysis

Before diving into strategy development, it’s crucial to preprocess the data. This step involves handling missing values and zeros to ensure data integrity. By removing problematic rows and ensuring data quality, we lay a solid foundation for accurate analysis.

# Data Preprocessing 
counter=0
# Check if any variable is zero or NaN
for col in df.columns:
    zero_index = df[ df[col] == 0 ].index
    df.drop(zero_index , inplace=True)
df.dropna(inplace=True)
print("Number of NaNs Left  = ",int(df.isna().sum().sum()))
for col in df.columns:
    zero_index = df[ df[col] == 0 ].index
    counter+=len(zero_index)
print("Number of zeros left = ",counter)

Step 3: Enhancing Strategy with Technical Indicators

To boost our trading strategy, we leverage technical indicators through the pandas_ta library. These indicators, including Average True Range (ATR), Relative Strength Index (RSI), Moving Averages (MA), and slope calculations provide valuable insights into market volatility, price momentum, and trend strength. Incorporating these indicators can help refine your trading decisions.

#Building Techical Indicaotrs Using Pandas TA Library in a DataFrame Structure 

period = {
        "ATR_period"        : 20,
        "RSI_period"        : 14,
        "Average"           : 1 ,
        "Moving_Average"    : [9,26,150] 
        }

df['ATR'] = df.ta.atr(length=20)
df['RSI'] = df.ta.rsi()
df['Average'] = df.ta.midprice(length=1) #midprice
df['MA9'] = df.ta.sma(length=9)
df['MA26'] = df.ta.sma(length=26)
df['MA150'] = df.ta.sma(length=50)

from scipy.stats import linregress
def get_slope(array):
    y = np.array(array)
    x = np.arange(len(y))
    slope, intercept, r_value, p_value, std_err = linregress(x,y)
    return slope

#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
backrollingN = 6
#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
df['slopeMA9'] = df['MA9'].rolling(window=backrollingN).apply(get_slope, raw=True)
df['slopeMA26'] = df['MA26'].rolling(window=backrollingN).apply(get_slope, raw=True)
df['slopeMA150'] = df['MA150'].rolling(window=backrollingN).apply(get_slope, raw=True)
df['AverageSlope'] = df['Average'].rolling(window=backrollingN).apply(get_slope, raw=True)
df['RSISlope'] = df['RSI'].rolling(window=backrollingN).apply(get_slope, raw=True)

Step 4: Leveraging the KNN Classifier for Trading Signals

In this step, we introduce the KNN classifier, a powerful machine learning algorithm, to generate trading signals. We define the classfier function, which incorporates a specified look-ahead window and the data frame. The function calculates price differences and assigns trend categories based on predefined thresholds, indicating uptrends, downtrends, or no clear trends.

from sklearn.neighbors import KNeighborsClassifier

model = KNeighborsClassifier(n_neighbors=200, weights='uniform', algorithm='kd_tree', leaf_size=30, p=1, metric='minkowski', metric_params=None, n_jobs=1)
model.fit(X_train, y_train)

y_pred_train = model.predict(X_train)
y_pred_test = model.predict(X_test)

Step 5: Model Training, Evaluation, and Performance Analysis

To implement the KNN classifier, we split the preprocessed DataFrame into input features (X) and the target variable (y). Using the train_test_split function from scikit-learn, we divide the data into training and testing sets. We train the KNN classifier on the training data and evaluate its performance by making predictions on both the training and testing sets. This evaluation provides valuable insights into the model’s accuracy and helps us analyze its performance.

from sklearn.metrics import accuracy_score
accuracy_train = accuracy_score(y_train, y_pred_train)
accuracy_test = accuracy_score(y_test, y_pred_test)
print("Accuracy train: %.2f%%" % (accuracy_train * 100.0))
print("Accuracy test: %.2f%%" % (accuracy_test * 100.0))

#------------------------------------------------------------------
#--- How should I compare my accuracy ?
print(df_model['classfier'].value_counts()*100/df_model['mytarget'].count())

# Random Model, gambler?
pred_test = np.random.choice([0, 1, 2], len(y_pred_test))
accuracy_test = accuracy_score(y_test, pred_test)
print("Accuracy Gambler: %.2f%%" % (accuracy_test * 100.0))

Step 6: Results and Comparison Analysis

In this step, we analyze the model’s results and compare them with alternative approaches. By examining histograms of trend categories for different technical indicators, we gain a deeper understanding of their distribution and their impact on trading decisions. Furthermore, we compare the KNN classifier’s accuracy with a random model and an alternative algorithm, XGBoost, to assess its effectiveness in generating trading signals.

plt.rcParams.update({'figure.figsize':(5,4), 'figure.dpi':100})

from matplotlib import pyplot
from xgboost import plot_importance
#plot feature importance
plot_importance(model)
pyplot.show()

Step 7: Strategy Implementation and Returns Calculation

To put the strategy into action, we assign trading positions based on the predicted trend categories. By multiplying these positions with the daily returns of Bank Nifty, we calculate the trading returns. Additionally, we calculate the cumulative returns for both long-only and long-short trading strategies. This analysis provides a comprehensive view of the strategy’s performance.

df_predictions['Date'] =df_predictions.index
df_predictions['Positions'] = 0
df_predictions['Positions'].loc[df_predictions['Pred'] ==1] = 1
df_predictions['Positions'].loc[df_predictions['Pred'] ==2] = -1

df_predictions['Strat_ret'] = df_predictions['Positions'].shift(1) * df_predictions['Ret']
df_predictions['Positions_L'] = df_predictions['Positions'].shift(1)
df_predictions.loc[df_predictions['Positions_L'] == -1, 'Positions_L'] = 0
df_predictions['Strat_ret_L'] = df_predictions['Positions_L'] * df_predictions['Ret']

df_predictions['CumRet'] = (1 + df_predictions['Strat_ret']).cumprod() - 1
df_predictions['CumRet_L'] = (1 + df_predictions['Strat_ret_L']).cumprod() - 1
df_predictions['bhRet'] = df_predictions['Ret'].cumsum()

Final_Return_L = np.prod(1 + df_predictions["Strat_ret_L"]) - 1
Final_Return = np.prod(1 + df_predictions["Strat_ret"]) - 1
Buy_Return = np.prod(1 + df_predictions["Ret"]) - 1

print("Strat Return Long Only =", Final_Return_L * 100, "%")
print("Strat Return =", Final_Return * 100, "%")
print("Buy and Hold Return =", Buy_Return * 100, "%")

fig = plt.figure(figsize=(12, 6))
ax = plt.gca()
df_predictions.plot(x="Date", y="bhRet", label="Buy & Hold Only ", ax=ax)
df_predictions.plot(x="Date", y="CumRet_L", label="Taking Only Long from Strategy", ax=ax)
df_predictions.plot(x="Date", y="CumRet", label="Taking Both Long Short from Strategy", ax=ax)
plt.xlabel("date")
plt.ylabel("Cumulative Returns")
plt.grid()
plt.show()

Conclusion: Optimizing Bank Nifty Trading with KNN Classifier

In conclusion, leveraging the K-Nearest Neighbors (KNN) classifier can enhance your Bank Nifty trading strategy. By following the step-by-step guide presented in this article, you can develop a robust approach based on technical indicators and machine learning. Remember to conduct a thorough analysis, backtesting, and risk assessment before implementing any trading strategy. With careful consideration and informed decisions, you can potentially improve your trading performance and achieve your financial goals.

You can find many such codes in my GitHub repo https://github.com/quantifiedtrader/AI_Trading_Engines

Frequently Asked Questions (FAQ)

Q1: What is the role of technical indicators in the trading strategy?

Technical indicators provide valuable insights into market dynamics, including volatility, momentum, and trend strength. By incorporating these indicators, traders gain a deeper understanding of the market conditions and can make more informed trading decisions.

Q2: How does the KNN classifier help in generating trading signals?

The KNN classifier analyzes historical data and assigns trend categories based on predefined thresholds. By comparing price differences within a look-ahead window, the classifier identifies uptrends, downtrends, or no clear trends. These trend categories serve as trading signals, guiding traders in their decision-making process.

Q3: How do I evaluate the performance of the KNN classifier?

To assess the model’s performance, we calculate its accuracy by comparing the predicted trend categories with the actual trend categories. Additionally, we compare the accuracy with alternative models, such as a random model or another machine learning algorithm, to gain insights into the classifier’s effectiveness.

Q4: Can the trading strategy be applied to other financial instruments?

While this article focuses on Bank Nifty, the strategy can be adapted to other financial instruments with appropriate adjustments. It’s important to consider the unique characteristics of each instrument and perform a thorough analysis to ensure the strategy’s suitability.

Q5: How should I approach risk management when implementing this strategy?

Risk management is crucial in trading. It’s recommended to set appropriate stop-loss and take-profit levels based on your risk tolerance and the specific instrument being traded. Additionally, regularly review and adjust your risk management approach as market conditions evolve.

Remember, developing a successful trading strategy requires continuous learning, practice, and adaptation. Stay informed, keep refining your approach, and always prioritize risk management to maximize your chances of success.

Leave a Comment

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

Your email address will not be published. Required fields are marked *