import pandas as pd
import numpy as np
import tradingWithPython as twp
import tradingWithPython.lib.yahooFinance as yf # yahoo finance module
twp.extra.setNotebookStyle()
import ffn
data = twp.yahooFinance.getHistoricData('SPY')
Got 4660 days of data
data.head()
open | high | low | close | adj_close | volume | |
---|---|---|---|---|---|---|
Date | ||||||
1999-12-31 | 146.84 | 147.50 | 146.25 | 146.88 | 103.95 | 3172700 |
2000-01-03 | 148.25 | 148.25 | 143.88 | 145.44 | 102.93 | 8164300 |
2000-01-04 | 143.53 | 144.06 | 139.64 | 139.75 | 98.91 | 8089800 |
2000-01-05 | 139.94 | 141.53 | 137.25 | 140.00 | 99.08 | 12177900 |
2000-01-06 | 139.62 | 141.50 | 137.75 | 137.75 | 97.49 | 6227200 |
close=data['close']
close.plot()
<matplotlib.axes._subplots.AxesSubplot at 0x1a0bd1fc50>
data['SMAslow']=data['close'].rolling(window=252).mean()
data['SMAfast']=close.rolling(window=42).mean()
data.tail()
open | high | low | close | adj_close | volume | SMAslow | SMAfast | |
---|---|---|---|---|---|---|---|---|
Date | ||||||||
2018-07-03 | 272.87 | 272.98 | 270.42 | 270.90 | 270.90 | 42187100 | 262.49 | 273.16 |
2018-07-05 | 272.17 | 273.18 | 270.96 | 273.11 | 273.11 | 56925900 | 262.61 | 273.33 |
2018-07-06 | 273.14 | 275.84 | 272.71 | 275.42 | 275.42 | 66493700 | 262.75 | 273.53 |
2018-07-09 | 276.55 | 277.96 | 276.50 | 277.90 | 277.90 | 50401600 | 262.89 | 273.79 |
2018-07-10 | 278.41 | 279.01 | 278.08 | 278.12 | 278.12 | 29520229 | 263.03 | 273.99 |
data[['close','SMAfast','SMAslow']].plot()
<matplotlib.axes._subplots.AxesSubplot at 0x1a0ca314a8>
data['signal'] = data['SMAfast'] - data['SMAslow']
data.tail()
open | high | low | close | adj_close | volume | SMAslow | SMAfast | signal | Stance | |
---|---|---|---|---|---|---|---|---|---|---|
Date | ||||||||||
2018-07-03 | 272.87 | 272.98 | 270.42 | 270.90 | 270.90 | 42187100 | 262.49 | 273.16 | 10.67 | 10 |
2018-07-05 | 272.17 | 273.18 | 270.96 | 273.11 | 273.11 | 56925900 | 262.61 | 273.33 | 10.72 | 10 |
2018-07-06 | 273.14 | 275.84 | 272.71 | 275.42 | 275.42 | 66493700 | 262.75 | 273.53 | 10.78 | 10 |
2018-07-09 | 276.55 | 277.96 | 276.50 | 277.90 | 277.90 | 50401600 | 262.89 | 273.79 | 10.90 | 10 |
2018-07-10 | 278.41 | 279.01 | 278.08 | 278.12 | 278.12 | 29520229 | 263.03 | 273.99 | 10.97 | 10 |
X = 0
data['Stance'] = np.where(data['signal'] > X, 1, 0)
data['Stance'] = np.where(data['signal'] < X, -1, data['Stance'])
data['Stance'].value_counts()
1 3072 -1 1337 0 251 Name: Stance, dtype: int64
data.tail()
open | high | low | close | adj_close | volume | SMAslow | SMAfast | signal | Stance | Market Returns | Strateg | equity | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Date | |||||||||||||
2018-07-03 | 272.87 | 272.98 | 270.42 | 270.90 | 270.90 | 42187100 | 262.49 | 273.16 | 10.67 | 1 | -3.54e-03 | -3.54e-02 | 114.44 |
2018-07-05 | 272.17 | 273.18 | 270.96 | 273.11 | 273.11 | 56925900 | 262.61 | 273.33 | 10.72 | 1 | 8.12e-03 | 8.12e-02 | 114.52 |
2018-07-06 | 273.14 | 275.84 | 272.71 | 275.42 | 275.42 | 66493700 | 262.75 | 273.53 | 10.78 | 1 | 8.42e-03 | 8.42e-02 | 114.61 |
2018-07-09 | 276.55 | 277.96 | 276.50 | 277.90 | 277.90 | 50401600 | 262.89 | 273.79 | 10.90 | 1 | 8.96e-03 | 8.96e-02 | 114.70 |
2018-07-10 | 278.41 | 279.01 | 278.08 | 278.12 | 278.12 | 29520229 | 263.03 | 273.99 | 10.97 | 1 | 7.91e-04 | 7.91e-03 | 114.70 |
data['Stance'].plot()
<matplotlib.axes._subplots.AxesSubplot at 0x1a0bdaea20>
data['Market Returns'] = np.log(data['close'] / data['close'].shift(1))
data['Strateg']=data['Market Returns']*data['Stance'].shift(1)
data
open | high | low | close | adj_close | volume | SMAslow | SMAfast | signal | Stance | Market Returns | Strateg | equity | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Date | |||||||||||||
1999-12-31 | 146.84 | 147.50 | 146.25 | 146.88 | 103.95 | 3172700 | NaN | NaN | NaN | 0 | NaN | NaN | NaN |
2000-01-03 | 148.25 | 148.25 | 143.88 | 145.44 | 102.93 | 8164300 | NaN | NaN | NaN | 0 | -9.85e-03 | -0.00e+00 | 100.00 |
2000-01-04 | 143.53 | 144.06 | 139.64 | 139.75 | 98.91 | 8089800 | NaN | NaN | NaN | 0 | -3.99e-02 | -0.00e+00 | 100.00 |
2000-01-05 | 139.94 | 141.53 | 137.25 | 140.00 | 99.08 | 12177900 | NaN | NaN | NaN | 0 | 1.79e-03 | 0.00e+00 | 100.00 |
2000-01-06 | 139.62 | 141.50 | 137.75 | 137.75 | 97.49 | 6227200 | NaN | NaN | NaN | 0 | -1.62e-02 | -0.00e+00 | 100.00 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
2018-07-03 | 272.87 | 272.98 | 270.42 | 270.90 | 270.90 | 42187100 | 262.49 | 273.16 | 10.67 | 1 | -3.54e-03 | -3.54e-03 | 114.44 |
2018-07-05 | 272.17 | 273.18 | 270.96 | 273.11 | 273.11 | 56925900 | 262.61 | 273.33 | 10.72 | 1 | 8.12e-03 | 8.12e-03 | 114.52 |
2018-07-06 | 273.14 | 275.84 | 272.71 | 275.42 | 275.42 | 66493700 | 262.75 | 273.53 | 10.78 | 1 | 8.42e-03 | 8.42e-03 | 114.61 |
2018-07-09 | 276.55 | 277.96 | 276.50 | 277.90 | 277.90 | 50401600 | 262.89 | 273.79 | 10.90 | 1 | 8.96e-03 | 8.96e-03 | 114.70 |
2018-07-10 | 278.41 | 279.01 | 278.08 | 278.12 | 278.12 | 29520229 | 263.03 | 273.99 | 10.97 | 1 | 7.91e-04 | 7.91e-04 | 114.70 |
4660 rows × 13 columns
data[['Market Returns','Strateg']].cumsum().plot()
<matplotlib.axes._subplots.AxesSubplot at 0x1a0c7cc860>
data['equity']=data['Strateg'].cumsum()+100
data
open | high | low | close | adj_close | volume | SMAslow | SMAfast | signal | Stance | Market Returns | Strateg | equity | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Date | |||||||||||||
1999-12-31 | 146.84 | 147.50 | 146.25 | 146.88 | 103.95 | 3172700 | NaN | NaN | NaN | 0 | NaN | NaN | NaN |
2000-01-03 | 148.25 | 148.25 | 143.88 | 145.44 | 102.93 | 8164300 | NaN | NaN | NaN | 0 | -9.85e-03 | -0.00e+00 | 100.00 |
2000-01-04 | 143.53 | 144.06 | 139.64 | 139.75 | 98.91 | 8089800 | NaN | NaN | NaN | 0 | -3.99e-02 | -0.00e+00 | 100.00 |
2000-01-05 | 139.94 | 141.53 | 137.25 | 140.00 | 99.08 | 12177900 | NaN | NaN | NaN | 0 | 1.79e-03 | 0.00e+00 | 100.00 |
2000-01-06 | 139.62 | 141.50 | 137.75 | 137.75 | 97.49 | 6227200 | NaN | NaN | NaN | 0 | -1.62e-02 | -0.00e+00 | 100.00 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
2018-07-03 | 272.87 | 272.98 | 270.42 | 270.90 | 270.90 | 42187100 | 262.49 | 273.16 | 10.67 | 1 | -3.54e-03 | -3.54e-03 | 101.44 |
2018-07-05 | 272.17 | 273.18 | 270.96 | 273.11 | 273.11 | 56925900 | 262.61 | 273.33 | 10.72 | 1 | 8.12e-03 | 8.12e-03 | 101.45 |
2018-07-06 | 273.14 | 275.84 | 272.71 | 275.42 | 275.42 | 66493700 | 262.75 | 273.53 | 10.78 | 1 | 8.42e-03 | 8.42e-03 | 101.46 |
2018-07-09 | 276.55 | 277.96 | 276.50 | 277.90 | 277.90 | 50401600 | 262.89 | 273.79 | 10.90 | 1 | 8.96e-03 | 8.96e-03 | 101.47 |
2018-07-10 | 278.41 | 279.01 | 278.08 | 278.12 | 278.12 | 29520229 | 263.03 | 273.99 | 10.97 | 1 | 7.91e-04 | 7.91e-04 | 101.47 |
4660 rows × 13 columns
writer = pd.ExcelWriter('output.xlsx')
data.to_excel(writer,'Sheet1')
writer.save()
perf = data['equity'].calc_stats()
/Users/ludeksk/anaconda3/lib/python3.6/site-packages/ffn/core.py:2054: RuntimeWarning: invalid value encountered in minimum negative_returns = np.minimum(returns, 0.)
ffn.core.PerformanceStats
ffn.core.PerformanceStats
perf.plot()
<matplotlib.axes._subplots.AxesSubplot at 0x1a1764ab00>
perf.display()
Stats for equity from 1999-12-31 00:00:00 - 2018-07-10 00:00:00 Annual risk-free rate considered: 0.00% Summary: Total Return Sharpe CAGR Max Drawdown -------------- -------- ------ -------------- - 0.43 0.08% -0.54% Annualized Returns: mtd 3m 6m ytd 1y 3y 5y 10y incep. ----- ----- ----- ----- ----- ------ ----- ----- -------- 0.02% 0.05% 0.01% 0.04% 0.14% -0.00% 0.04% 0.05% 0.08% Periodic: daily monthly yearly ------ ------- --------- -------- sharpe 0.43 0.57 0.53 mean 0.08% 0.08% 0.08% vol 0.18% 0.14% 0.15% skew -0.27 0.08 0.93 kurt 12.32 2.01 1.72 best 0.10% 0.18% 0.48% worst -0.13% -0.13% -0.15% Drawdowns: max avg # days ------ ------ -------- -0.54% -0.04% 70.69 Misc: --------------- ------ avg. up month 0.03% avg. down month -0.03% up year % 68.42% 12m up % 77.00% --------------- ------