whalebeings.com

An Advanced Python Trading Strategy: A Case Study on Algo Trading

Written on

Introduction to a New Trading Approach

In today's trading landscape, sticking with outdated algorithms like SMA crossover or RSI threshold breakout strategies is no longer viable. These methods have become ineffective due to their simplicity and the overwhelming number of traders attempting to apply them in the market. Instead, we should explore innovative strategies. In this article, we will harness Python alongside Benzinga's APIs to formulate and backtest a novel trading strategy aimed at outperforming the market.

With that in mind, let’s delve into the details!

Understanding the Trading Strategy

Before jumping into the coding aspect, it’s crucial to grasp the foundation of the strategy we will be implementing. Our approach is centered around a straightforward yet powerful breakout strategy.

  • Entry Condition: We enter the market when the current high of the stock surpasses its 50-week high.
  • Exit Condition: We exit the market when the current low of the stock drops below its 40-week low.

To monitor the 50-week high and the 40-week low, we will utilize the Donchian Channel indicator. This strategy operates on a weekly basis, so our backtesting will be conducted on a weekly timeframe.

Now that we have the strategy outlined, let's proceed to the coding section.

Importing Required Libraries

In this section, we will be using four primary libraries: pandas, requests, pandas_ta, and matplotlib. We will also use optional libraries such as termcolor and math. Below is the code to import these libraries into our Python environment:

# IMPORTING LIBRARIES

import pandas as pd

import requests

import pandas_ta as ta

import matplotlib.pyplot as plt

from termcolor import colored as cl

import math

plt.rcParams['figure.figsize'] = (20,10)

plt.style.use('fivethirtyeight')

Ensure that you have installed these packages using the pip command in your terminal if you haven't done so yet.

Gathering Historical Data

We will backtest our breakout strategy using Apple's stock data. To obtain historical stock information, we will leverage Benzinga’s Historical Bar Data API endpoint. The following Python function extracts Apple’s stock data starting from 1993:

# FETCHING HISTORICAL DATA

def get_historical_data(symbol, start_date, interval):

querystring = {"token":"YOUR API KEY","symbols":f"{symbol}","from":f"{start_date}","interval":f"{interval}"}

hist_json = requests.get(url, params=querystring).json()

df = pd.DataFrame(hist_json[0]['candles'])

return df

aapl = get_historical_data('AAPL', '1993-01-01', '1W')

aapl.tail()

In this code, we define a function get_historical_data that takes the stock symbol, start date, and interval as parameters. The function stores the API URL and query parameters, retrieves the data, and converts the JSON response into a Pandas DataFrame.

Now, let's proceed to calculating the Donchian Channel indicator based on the historical data obtained for Apple.

Calculating the Donchian Channel Indicator

The Donchian Channel indicator highlights the highest high and the lowest low of a stock over a defined timeframe. Here’s a brief overview of how to calculate it using pandas_ta:

# CALCULATING DONCHIAN CHANNEL

aapl[['dcl', 'dcm', 'dcu']] = aapl.ta.donchian(lower_length=40, upper_length=50)

aapl = aapl.dropna().drop('time', axis=1).rename(columns={'dateTime':'date'})

aapl = aapl.set_index('date')

aapl.index = pd.to_datetime(aapl.index)

aapl.tail()

In the first line, we use the Donchian function from pandas_ta to calculate the indicator, with parameters for the lower and upper lengths corresponding to our strategy's requirements. Afterward, we clean and format the DataFrame.

To visualize the Donchian Channel indicator, we will create a plot using Matplotlib:

# PLOTTING DONCHIAN CHANNEL

plt.plot(aapl[-300:].close, label='CLOSE')

plt.plot(aapl[-300:].dcl, color='black', linestyle='--', alpha=0.3)

plt.plot(aapl[-300:].dcm, color='orange', label='DCM')

plt.plot(aapl[-300:].dcu, color='black', linestyle='--', alpha=0.3, label='DCU,DCL')

plt.legend()

plt.title('AAPL DONCHIAN CHANNELS 50')

plt.xlabel('Date')

plt.ylabel('Close')

This code generates a visualization of the Donchian Channel for Apple stock. The chart effectively illustrates three key components of the indicator:

  • Upper Band: Represents the highest high over the specified period.
  • Lower Band: Indicates the lowest low for the same period.
  • Middle Band: Calculates the average between the upper and lower bands.

The Donchian Channel is extensively utilized for identifying breakouts in stock price movements, which is why we incorporate it into our strategy.

Backtesting Our Trading Strategy

Now we arrive at the crucial step of backtesting our breakout strategy. The following code executes a basic backtesting process:

# BACKTESTING THE STRATEGY

def implement_strategy(aapl, investment):

in_position = False

equity = investment

for i in range(3, len(aapl)):

if aapl['high'][i] == aapl['dcu'][i] and not in_position:

no_of_shares = math.floor(equity / aapl.close[i])

equity -= (no_of_shares * aapl.close[i])

in_position = True

print(cl('BUY: ', color='green', attrs=['bold']), f'{no_of_shares} Shares bought at ${aapl.close[i]} on {str(aapl.index[i])[:10]}')

elif aapl['low'][i] == aapl['dcl'][i] and in_position:

equity += (no_of_shares * aapl.close[i])

in_position = False

print(cl('SELL: ', color='red', attrs=['bold']), f'{no_of_shares} Shares sold at ${aapl.close[i]} on {str(aapl.index[i])[:10]}')

if in_position:

equity += (no_of_shares * aapl.close[i])

print(cl(f'nClosing position at {aapl.close[i]} on {str(aapl.index[i])[:10]}', attrs=['bold']))

in_position = False

earning = round(equity - investment, 2)

roi = round(earning / investment * 100, 2)

print(cl(f'EARNING: ${earning} ; ROI: {roi}%', attrs=['bold']))

implement_strategy(aapl, 100000)

This code snippet implements the trading strategy based on predefined entry and exit conditions. It allows for straightforward trading decisions, and the results of the backtesting are as follows:

Backtesting results for AAPL stock strategy

As indicated, our strategy has achieved an astonishing ROI of 8371%. However, we must verify whether this strategy genuinely surpasses the market performance.

Comparing with SPY ETF

To gauge our strategy's success, we can compare its backtesting results against the buy-and-hold returns of the SPY ETF. The following code calculates the returns of the SPY ETF over the years:

spy = get_historical_data('SPY', '1993-01-01', '1W')

spy_ret = round(((spy.close.iloc[-1] - spy.close.iloc[0]) / spy.close.iloc[0]) * 100)

print(cl('SPY ETF buy/hold return:', attrs=['bold']), f'{spy_ret}%')

In this code, we extract SPY's historical data and compute its return percentage, yielding the following result:

SPY ETF buy/hold return results

The SPY ETF’s buy-and-hold return stands at 936%, which is commendable; however, it pales in comparison to our strategy's impressive performance.

Conclusion

In this article, we thoroughly examined the process of coding to backtest a straightforward yet highly effective breakout strategy. As anticipated, the results were remarkable. We began by extracting Apple's historical data using Benzinga’s API, explored the Donchian Channel, and ultimately backtested our strategy while comparing it against the SPY ETF.

Numerous improvements could be made, including enhancing the backtesting system with considerations for brokerage fees and slippage, as well as implementing a robust risk management strategy. There are many avenues to explore, and I encourage you to investigate them further.

Before concluding, I want to extend my gratitude to Benzinga for providing an excellent suite of APIs that include top-tier market news and data. I hope you found this article informative and valuable. Thank you for your attention!

Explore an effective algorithmic trading strategy using Python, including coding and implementation insights.

Learn about algorithmic trading strategies in Python, focusing on practical applications and backtesting methodologies.

Share the page:

Twitter Facebook Reddit LinkIn

-----------------------

Recent Post:

Exploring the Minimum Infinite Sum: A Fun Algebra Challenge

Discover the intriguing puzzle of the smallest infinite sum with a fun algebraic approach.

Unearthing Japan's Hidden Wealth: Secrets of a Warrior's Hoard

Archaeologists in Japan uncover over 100,000 ancient coins buried by a secretive warrior, revealing insights into history and culture.

The Disturbing Reality of Kim Jong Un's Threats

An exploration of the geopolitical tensions involving North Korea and the implications of Kim Jong Un's aggressive posturing.

Maximize Your Productivity with These 5 Essential macOS Apps

Discover five powerful macOS apps that enhance productivity and streamline your workflow.

Unlock the Secret to Longevity: Steps to a Healthier Life

Discover how daily steps can significantly impact your health and longevity, with insights from recent studies.

Embracing Freedom from Negativity: A Journey Within

A reflective exploration of overcoming negativity and embracing self-love through divine guidance.

# The Impact of Reading at the Right Time

Discover how reading the right book at a pivotal moment can profoundly influence one's life journey.

Understanding Our Emotional Filters: Why People Affect Us Deeply

Explore how our past experiences shape our perceptions of others and ourselves, influencing our relationships and emotions.