SMA Percent Band

1. The SPY closes above its upper band, buy
2. If the SPY closes below its lower band, sell your long position.

(optimize band)

In [1]:
import pandas as pd
import matplotlib.pyplot as plt
import datetime
from talib.abstract import *

import pinkfish as pf
import strategy

# format price data
pd.options.display.float_format = '{:0.2f}'.format

%matplotlib inline

In [2]:
# set size of inline plots
'''note: rcParams can't be in same cell as import matplotlib
   or %matplotlib inline
   
   %matplotlib notebook: will lead to interactive plots embedded within
   the notebook, you can zoom and resize the figure
   
   %matplotlib inline: only draw static images in the notebook
'''
plt.rcParams["figure.figsize"] = (10, 7)

Some global data


In [3]:
symbol = '^GSPC'
#symbol = 'SPY'
#symbol = 'DIA'
#symbol = 'QQQ'
#symbol = 'IWM'
#symbol = 'TLT'
#symbol = 'GLD'
#symbol = 'AAPL'
#symbol = 'BBRY'
#symbol = 'GDX'
capital = 10000
start = datetime.datetime(1900, 1, 1)
#start = datetime.datetime.strptime(pf.SP500_BEGIN, '%Y-%m-%d')
end = datetime.datetime.now()

Define percent bands (from 0 to 10% increment by 0.5)


In [4]:
bands = range(0, 100, 5)
bands = [str(band) for band in bands]

Run Strategy


In [5]:
strategies = pd.Series(dtype=object)
for band in bands:
    print("{0}".format(band), end=" ")
    strategies[band] = strategy.Strategy(symbol, capital, start, end, sma_period=200, percent_band=int(band)/10)
    strategies[band].run()
    _, strategies[band].tlog, strategies[band].dbal = strategies[band].get_logs()
    strategies[band].stats = strategies[band].get_stats()


0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 95 

Summarize results


In [6]:
metrics = ('annual_return_rate',
           'ending_balance',
           'max_closed_out_drawdown',
           'drawdown_annualized_return',
           'drawdown_recovery',
           'best_month',
           'worst_month',
           'sharpe_ratio',
           'sortino_ratio',
           'monthly_std',
           'pct_time_in_market',
           'total_num_trades',
           'pct_profitable_trades',
           'trades_per_year',
           'avg_points')

df = strategy.summary(strategies, metrics)
df


Out[6]:
0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 95
annual_return_rate 6.44 6.37 6.44 6.16 6.17 6.49 6.50 6.45 6.38 6.46 6.38 5.94 5.57 5.42 4.92 5.18 4.94 5.08 5.09 4.85
ending_balance 3061631.13 2877296.31 3064011.06 2404279.91 2432794.48 3203066.99 3231184.92 3106257.51 2913748.74 3125324.64 2917736.15 1983737.25 1439355.71 1271055.72 822060.06 1029797.91 835955.42 943765.91 952106.53 772450.35
max_closed_out_drawdown -51.57 -49.47 -49.46 -55.14 -54.31 -55.76 -57.79 -56.58 -53.61 -54.99 -49.72 -50.56 -50.56 -53.51 -54.49 -47.54 -47.54 -47.54 -50.32 -52.65
drawdown_annualized_return -8.01 -7.77 -7.68 -8.96 -8.80 -8.59 -8.89 -8.77 -8.40 -8.51 -7.79 -8.52 -9.08 -9.87 -11.07 -9.18 -9.62 -9.36 -9.88 -10.85
drawdown_recovery -3.51 -3.51 -3.51 -3.51 -3.51 -3.51 -3.51 -3.51 -3.51 -3.51 -3.51 -3.42 -3.42 -3.59 -3.59 -3.59 -3.59 -3.59 -3.59 -3.59
best_month 27.01 27.01 27.01 27.02 27.02 27.01 27.00 27.01 27.01 27.02 27.01 27.02 27.02 22.42 22.41 22.41 22.41 22.41 22.42 22.42
worst_month -26.88 -26.88 -26.89 -30.46 -27.07 -27.06 -27.06 -29.72 -29.72 -29.72 -29.72 -31.45 -31.46 -31.45 -31.47 -31.46 -31.47 -31.45 -31.46 -31.45
sharpe_ratio 0.58 0.57 0.58 0.55 0.55 0.58 0.58 0.57 0.56 0.57 0.56 0.52 0.49 0.48 0.44 0.46 0.44 0.45 0.45 0.43
sortino_ratio 0.59 0.58 0.59 0.56 0.57 0.59 0.59 0.58 0.57 0.58 0.58 0.51 0.49 0.48 0.44 0.46 0.44 0.45 0.45 0.44
monthly_std 3.33 3.36 3.37 3.39 3.38 3.37 3.36 3.43 3.40 3.43 3.44 3.55 3.56 3.55 3.59 3.53 3.57 3.60 3.61 3.66
pct_time_in_market 67.11 66.98 66.64 66.62 66.79 66.40 66.75 67.09 66.35 67.35 68.43 68.61 68.97 69.71 69.29 68.63 69.09 70.28 70.50 72.40
total_num_trades 280.00 161.00 120.00 93.00 78.00 60.00 54.00 47.00 45.00 41.00 38.00 36.00 36.00 34.00 34.00 29.00 28.00 26.00 24.00 23.00
pct_profitable_trades 25.71 38.51 43.33 44.09 47.44 56.67 61.11 65.96 66.67 68.29 71.05 75.00 72.22 67.65 64.71 72.41 71.43 76.92 79.17 78.26
trades_per_year 3.05 1.75 1.31 1.01 0.85 0.65 0.59 0.51 0.49 0.45 0.41 0.39 0.39 0.37 0.37 0.32 0.31 0.28 0.26 0.25
avg_points 7.38 14.36 18.73 26.98 34.03 48.78 56.24 59.80 59.15 65.80 72.27 69.24 65.29 65.55 57.99 63.03 60.54 70.79 66.24 60.63

Bar graphs


In [7]:
strategy.plot_bar_graph(df, 'annual_return_rate')
strategy.plot_bar_graph(df, 'ending_balance')
strategy.plot_bar_graph(df, 'sharpe_ratio')
strategy.plot_bar_graph(df, 'max_closed_out_drawdown')


Run Benchmark


In [8]:
s = strategies[bands[0]]
benchmark = pf.Benchmark(symbol, capital, s._start, s._end)
benchmark.run()
benchmark.tlog, benchmark.dbal = benchmark.get_logs()
benchmark.stats = benchmark.get_stats()


1928-10-16 00:00:00 BUY  460 ^GSPC @ 21.72
2020-07-17 00:00:00 SELL 460 ^GSPC @ 3224.73

Equity curve


In [9]:
pf.plot_equity_curve(strategies['35'].dbal, benchmark=benchmark.dbal)