Relative Strength Index and Average True Range Strategy with Backtesting

This notebook demonstrates the use of my financial calculations library to determine how a stategy will perform. Assuming that historical data is fairly representative of future data.

In [1]:
import numpy as np
import pandas as pd
import pandas_datareader as pdr
import matplotlib.pyplot as plt
%matplotlib inline
import sys
sys.path.insert(0,'./financial_calcs/')
import trading_calcs.standard as std_calcs
In [2]:
from datetime import timedelta
import datetime
date1 = datetime.date.today()
date_earlier = date1+timedelta(days=-60)
date_90_days_ago = date1+timedelta(days=-90)
date_90_days_ago_iso = date_90_days_ago.isoformat()
last_60_days_iso = date_earlier.isoformat()
Out[2]:
'2021-08-14'
In [3]:
stock_symbol = 'FSM'
In [4]:
df1 = pdr.get_data_yahoo([stock_symbol],start=last_60_days_iso)
df1.tail()
Out[4]:
Attributes Adj Close Close High Low Open Volume
Symbols FSM FSM FSM FSM FSM FSM
Date
2021-10-07 4.10 4.10 4.21 4.00 4.00 3654000
2021-10-08 4.15 4.15 4.34 4.13 4.29 3394500
2021-10-11 4.14 4.14 4.28 4.12 4.12 2061100
2021-10-12 4.27 4.27 4.32 4.10 4.16 3791000
2021-10-13 4.57 4.57 4.59 4.33 4.36 2413487
In [5]:
df1 = round(df1,4)
df1.head(7)
Out[5]:
Attributes Adj Close Close High Low Open Volume
Symbols FSM FSM FSM FSM FSM FSM
Date
2021-08-16 4.20 4.20 4.42 4.19 4.38 4193200
2021-08-17 4.10 4.10 4.29 4.05 4.20 3445900
2021-08-18 4.01 4.01 4.13 3.96 4.13 6465600
2021-08-19 3.86 3.86 4.01 3.82 3.98 4469800
2021-08-20 3.83 3.83 3.97 3.81 3.83 3350700
2021-08-23 4.13 4.13 4.15 3.93 3.97 3782200
2021-08-24 4.21 4.21 4.25 4.10 4.25 3904000
In [7]:
settings_file = "./financial_calcs/optimal_settings_file.json"
In [8]:
st1 = std_calcs.Strategy(stock_symbol, df1, settings_file)
st1
Out[8]:
<trading_calcs.standard.Strategy at 0x7fb29fee4e80>

Get the settings from the settings file, this stores the parameters from the previous run.

In [9]:
st1.get_settings()
Out[9]:
True

Uncomment the following to optimize the strategy based on the most current data, and also to update the settings file. The optimize_strategy() method runs the back-testing to see which strategy has the best returns.

In [10]:
#st1.optimize_strategy()

#st1.update_settings_file()

Various calculations based on the current strategy.

In [12]:
st1.calculate_strategy()

The best settings gives you a percent return, overbought and oversold and stops.

In [13]:
st1.best_settings
Out[13]:
{'percent_return': 0.018467336683417074,
 'rsi_high': 90.0,
 'rsi_low': 50.0,
 'rsi_periods': 16.0,
 'stops_periods': 24.0,
 'stops_mult': 1.0,
 'date_processed': '2021-06-08'}
In [14]:
stops_periods = int(st1.best_settings['stops_periods'])
stops_mult = int(st1.best_settings['stops_mult'])
rsi_periods = int(st1.best_settings['rsi_periods'])
rsi_high = int(st1.best_settings['rsi_high'])
rsi_low = int(st1.best_settings['rsi_low'])
std_calcs.calc_range_position(df1['Close'][stock_symbol].iloc[-1].item(),df1['Low'][stock_symbol].iloc[-1].item(),st1.df_stops, st1.s_rsi, rsi_high, rsi_low)
Out[14]:
0

The following shows a chart with the strategy positions. 1 is buy, 0 is hold, and -1 is sell.

In [15]:
df2 = pd.concat([st1.data_frame['Close'][st1.stock_symbol], st1.df_stops, st1.s_pos], axis=1)
df2.plot(figsize=(12, 9), secondary_y='Position')
Out[15]:
<matplotlib.axes._subplots.AxesSubplot at 0x7fb29f52c208>