mirror of
https://github.com/wassname/pandas-ta.git
synced 2026-07-15 01:10:57 +08:00
927 KiB
927 KiB
In [1]:
%matplotlib inline
import datetime
import matplotlib.pyplot as plt
import pandas as pd
import pandas_ta as ta
%pylab inline
from alphaVantageAPI.alphavantage import AlphaVantage # pip install alphaVantage-api
e = pd.DataFrame()Populating the interactive namespace from numpy and matplotlib
In [2]:
e.ta.indicators()pandas.ta - Technical Analysis Indicators
Total Indicators: 89
Abbreviations:
accbands, ad, adosc, adx, amat, ao, aobv, apo, aroon, atr, bbands, bop, cci, cg, cmf, cmo, coppock, cross, decreasing, dema, donchian, dpo, efi, ema, eom, fisher, fwma, hl2, hlc3, hma, ichimoku, increasing, kama, kc, kst, kurtosis, linear_decay, linreg, log_return, long_run, macd, mad, massi, median, mfi, midpoint, midprice, mom, natr, nvi, obv, ohlc4, percent_return, ppo, pvi, pvol, pvt, pwma, qstick, quantile, rma, roc, rsi, rvi, short_run, sinwma, skew, slope, sma, stdev, stoch, swma, t3, tema, trend_return, trima, trix, true_range, tsi, uo, variance, vortex, vp, vwap, vwma, willr, wma, zlma, zscore
In [3]:
help(ta.sma)Help on function sma in module pandas_ta.overlap.sma:
sma(close, length=None, offset=None, **kwargs)
Simple Moving Average (SMA)
The Simple Moving Average is the classic moving average that is the equally
weighted average over n periods.
Sources:
https://www.tradingtechnologies.com/help/x-study/technical-indicator-definitions/simple-moving-average-sma/
Calculation:
Default Inputs:
length=10
SMA = SUM(close, length) / length
Args:
close (pd.Series): Series of 'close's
length (int): It's period. Default: 10
offset (int): How many periods to offset the result. Default: 0
Kwargs:
adjust (bool): Default: True
presma (bool, optional): If True, uses SMA for initial value.
fillna (value, optional): pd.DataFrame.fillna(value)
fill_method (value, optional): Type of fill method
Returns:
pd.Series: New feature generated.
In [4]:
def farm(ticker = 'SPY', drop=['dividend', 'split_coefficient']):
AV = AlphaVantage(api_key="YOUR API KEY", premium=False, clean=True, output_size='full')
df = AV.data(symbol=ticker, function='D')
df.set_index(['date'], inplace=True)
df.drop(['dividend', 'split_coefficient'], axis=1, inplace=True) if 'dividend' in df.columns and 'split_coefficient' in df.columns else None
df.name = ticker
return df
def ctitle(indicator_name, ticker='SPY', length=100):
return f"{ticker}: {indicator_name} from {recent_startdate} to {recent_startdate} ({length})"In [5]:
price_size = (16, 8)
ind_size = (16, 2)
ticker = 'SPY'
recent = 126
half_of_recent = int(0.5 * recent)In [6]:
df = farm(ticker)
last_ = df.shape[0]
recent_startdate = df.tail(recent).index[0]
recent_enddate = df.tail(recent).index[-1]
print(f"{df.name}{df.shape} from {recent_startdate} to {recent_enddate}\n{df.describe()}")
df.head()Out [6]:
SPY(5033, 5) from 2019-09-16 to 2020-03-16
open high low close volume
count 5033.000000 5033.000000 5033.000000 5033.000000 5.033000e+03
mean 159.409025 160.322162 158.395389 159.408191 1.131951e+08
std 60.567005 60.680183 60.439239 60.577228 9.854250e+07
min 67.950000 70.000000 67.100000 68.110000 6.790000e+04
25% 115.480000 116.400000 114.570000 115.500000 4.892612e+07
50% 136.480000 137.180000 135.460000 136.410000 8.365357e+07
75% 201.400000 202.300000 200.000000 201.330000 1.516128e+08
max 337.790000 339.080000 337.480000 338.340000 8.708580e+08
| open | high | low | close | volume | |
|---|---|---|---|---|---|
| date | |||||
| 2000-03-14 | 139.2812 | 140.0937 | 136.1562 | 136.6250 | 8263900.0 |
| 2000-03-15 | 136.8750 | 140.4375 | 136.0625 | 139.8125 | 10300800.0 |
| 2000-03-16 | 141.6250 | 146.8437 | 140.8750 | 146.3437 | 25601400.0 |
| 2000-03-17 | 145.8125 | 148.0000 | 145.4375 | 146.9375 | 10272900.0 |
| 2000-03-20 | 146.8750 | 147.3437 | 144.7812 | 146.1875 | 12502300.0 |
In [7]:
opendf = df['open']
closedf = df['close']
volumedf = df['volume']In [8]:
help(df.ta.constants) # for more info
df.ta.constants(True, -4, 4)
df.tail()Out [8]:
Help on method constants in module pandas_ta.core:
constants(apply, lower_bound=-100, upper_bound=100, every=1) method of pandas_ta.core.AnalysisIndicators instance
Constants
Useful for indicator levels or if you need some constant value.
Add constant '1' to the DataFrame
>>> df.ta.constants(True, 1, 1, 1)
Remove constant '1' to the DataFrame
>>> df.ta.constants(False, 1, 1, 1)
Adding constants that range of constants from -4 to 4 inclusive
>>> df.ta.constants(True, -4, 4, 1)
Removing constants that range of constants from -4 to 4 inclusive
>>> df.ta.constants(False, -4, 4, 1)
Args:
apply (bool): Default: None. If True, appends the range of constants to the
working DataFrame. If False, it removes the constant range from the working
DataFrame.
lower_bound (int): Default: -100. Lowest integer for the constant range.
upper_bound (int): Default: 100. Largest integer for the constant range.
every (int): Default: 10. How often to include a new constant.
Returns:
Returns nothing to the user. Either adds or removes constant ranges from the
working DataFrame.
| open | high | low | close | volume | -4 | -3 | -2 | -1 | 0 | 1 | 2 | 3 | 4 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| date | ||||||||||||||
| 2020-03-10 | 284.64 | 288.5200 | 273.5000 | 288.42 | 274894230.0 | -4 | -3 | -2 | -1 | 0 | 1 | 2 | 3 | 4 |
| 2020-03-11 | 280.70 | 281.9400 | 270.8800 | 274.36 | 254604444.0 | -4 | -3 | -2 | -1 | 0 | 1 | 2 | 3 | 4 |
| 2020-03-12 | 256.00 | 266.6600 | 247.6800 | 248.11 | 389612072.0 | -4 | -3 | -2 | -1 | 0 | 1 | 2 | 3 | 4 |
| 2020-03-13 | 263.09 | 271.4754 | 248.5237 | 269.32 | 326142197.0 | -4 | -3 | -2 | -1 | 0 | 1 | 2 | 3 | 4 |
| 2020-03-16 | 241.18 | 256.9000 | 237.3600 | 248.07 | 196588337.0 | -4 | -3 | -2 | -1 | 0 | 1 | 2 | 3 | 4 |
In [9]:
def cscheme(colors):
aliases = {
'BkBu': ['black', 'blue'],
'gr': ['green', 'red'],
'grays': ['silver', 'gray'],
'mas': ['black', 'green', 'orange', 'red'],
}
aliases['default'] = aliases['gr']
return aliases[colors]
def machart(kind, fast, medium, slow, append=True, last=last_, figsize=price_size, colors=cscheme('mas')):
title = ctitle(f"{kind.upper()}s", ticker=ticker, length=last)
ma1 = df.ta(kind=kind, length=fast, append=append)
ma2 = df.ta(kind=kind, length=medium, append=append)
ma3 = df.ta(kind=kind, length=slow, append=append)
madf = pd.concat([closedf, df[[ma1.name, ma2.name, ma3.name]]], axis=1, sort=False).tail(last)
madf.plot(figsize=figsize, title=title, color=colors, grid=True)
def volumechart(kind, length=10, last=last_, figsize=ind_size, alpha=0.7, colors=cscheme('gr')):
title = ctitle("Volume", ticker=ticker, length=last)
volume = pd.DataFrame({'V+': volumedf[closedf > opendf], 'V-': volumedf[closedf < opendf]}).tail(last)
volume.plot(kind='bar', figsize=figsize, width=0.5, color=colors, alpha=alpha, stacked=True)
vadf = df.ta(kind=kind, close=volumedf, length=length).tail(last)
vadf.plot(figsize=figsize, lw=1.4, color='black', title=title, rot=45, grid=True)In [10]:
machart('ema', 8, 21, 50, last=recent)
volumechart('ema', last=recent)In [11]:
clr_ma_length = 8
clrdf = df.ta.log_return(cumulative=True, append=True)
clrmadf = ta.ema(clrdf, length=clr_ma_length)
qqdf = pd.DataFrame({f"{clrdf.name}": clrdf, f"{clrmadf.name}({clrdf.name})": clrmadf})
qqdf.tail(recent).plot(figsize=ind_size, color=cscheme('BkBu'), linewidth=1, title=ctitle(clrdf.name, ticker=ticker, length=recent), grid=True)Out [11]:
<matplotlib.axes._subplots.AxesSubplot at 0x11666f850>
In [12]:
macddf = df.ta.macd(fast=8, slow=21, signal=9, min_periods=None, append=True)
macddf[[macddf.columns[0], macddf.columns[2]]].tail(recent).plot(figsize=(16, 2), color=cscheme('BkBu'), linewidth=1.3)
macddf[macddf.columns[1]].tail(recent).plot.area(figsize=ind_size, stacked=False, color=['silver'], linewidth=1, title=ctitle(macddf.name, ticker=ticker, length=recent), grid=True).axhline(y=0, color="black", lw=1.1)Out [12]:
<matplotlib.lines.Line2D at 0x116647f50>
In [13]:
zscoredf = df.ta.zscore(length=30, append=True)
zcolors = ['maroon', 'red', 'orange', 'silver', 'silver', 'orange', 'red', 'maroon', 'black', 'blue']
zcols = df[['-4', '-3', '-2', '-1', '1', '2', '3', '4', zscoredf.name]].tail(recent)
zcols.plot(figsize=ind_size, color=zcolors, linewidth=1, title=ctitle(zscoredf.name, ticker=ticker, length=recent), grid=True).axhline(y=0, color="black", lw=1.1)Out [13]:
<matplotlib.lines.Line2D at 0x116604690>
In [14]:
matype = 'ema'
fast_length = 8
medfast_length = 21
slow_length = 50
amat = df.ta.amat(mamode=matype, fast=fast_length, slow=slow_length)
machart(matype, fast_length, medfast_length, slow_length, last=recent) # Price Chart so we can see the association with AMAT
amat.tail(recent).plot(kind='area', figsize=(16, 0.35), color=cscheme('gr'), alpha=0.4, stacked=False, title=ctitle(f"{amat.name} Trends", ticker=ticker, length=recent))Out [14]:
<matplotlib.axes._subplots.AxesSubplot at 0x1165c3a50>
In [15]:
matype = 'sma'
fast_length = 10
medfast_length = 20
slow_length = 50
aobvdf = ta.aobv(close=closedf, volume=volumedf, mamode=matype, fast=fast_length, slow=medfast_length)
aobv_colors = ['black', 'silver', 'silver', 'green', 'red']
aobv_trenddf = aobvdf[aobvdf.columns[-2:]]
aobv_trenddf.name = f"{aobvdf.name} Trends"In [16]:
machart(matype, fast_length, medfast_length, slow_length, last=recent) # Price Chart so we can see the association with AOBV
volumechart('ema', length=5, last=recent)
aobvdf[aobvdf.columns[:5]].tail(recent).plot(figsize=ind_size, color=aobv_colors, title=ctitle(aobvdf.name, ticker=ticker, length=recent), grid=True)
aobv_trenddf.tail(recent).plot(kind='area', figsize=(16, 0.35), color=cscheme('gr'), alpha=0.5, title=ctitle(aobv_trenddf.name), stacked=False)Out [16]:
<matplotlib.axes._subplots.AxesSubplot at 0x11676fe50>
In [17]:
matype = 'sma'
fast_length = 10
medfast_length = 20
slow_length = 50
machart(matype, fast_length, medfast_length, slow_length, last=half_of_recent)In [18]:
maf = df.ta(kind=matype, length=fast_length)
mam = df.ta(kind=matype, length=medfast_length)
lrun = df.ta.long_run(maf, mam, append=False) # Long Run of Fast MA and Slow MA
srun = df.ta.short_run(maf, mam, append=False) # Short Run of Fast MA and Slow MA
srun.tail(half_of_recent).plot(kind='bar', figsize=(16,0.25), color=['red'], linewidth=1, alpha=0.45, rot=45)
lrun.tail(half_of_recent).plot(kind='bar', figsize=(16,0.25), color=['green'], linewidth=1, alpha=0.45, title=ctitle(f"{maf.name} & {mam.name} ({lrun.name}(green) & {maf.name} & {mam.name}{srun.name}(red))", length=half_of_recent), rot=45)Out [18]:
<matplotlib.axes._subplots.AxesSubplot at 0x11656b810>
In [19]:
machart(matype, fast_length, medfast_length, slow_length, last=half_of_recent)In [20]:
maf = df.ta(kind=matype, length=fast_length)
cross_above = ta.cross(closedf, maf, above=True)
cross_above.tail(int(0.5 * recent)).plot(kind='bar', figsize=(16, 0.5), color=['green'], linewidth=1, alpha=0.55, stacked=False, rot=45)
cross_below = ta.cross(closedf, maf, above=False)
cross_below.tail(int(0.5 * recent)).plot(kind='bar', figsize=(16, 0.5), color=['red'], linewidth=1, alpha=0.55, stacked=False, title=ctitle(f"{cross_above.name} (orange) & {cross_below.name} (blue)", length=int(0.5 * recent)), rot=45)Out [20]:
<matplotlib.axes._subplots.AxesSubplot at 0x11655c310>
In [21]:
def recent_crosses(series, **kwargs):
last = kwargs.pop('last', 5)
return list(series[series > 0].tail(last).index[::-1])
last_n_crosses = 5
recent_crosses_above = recent_crosses(cross_above, last=last_n_crosses)
recent_crosses_below = recent_crosses(cross_below, last=last_n_crosses)
print(f"Most recent {cross_above.name} Dates:\n {', '.join(recent_crosses_above)}")
print(f"Most recent {cross_below.name} Dates:\n {', '.join(recent_crosses_below)}")Most recent close_XA_SMA_10 Dates:
2020-02-04, 2019-12-06, 2019-10-10, 2019-08-29, 2019-08-16
Most recent close_XB_SMA_10 Dates:
2020-02-21, 2020-01-24, 2019-12-02, 2019-09-20, 2019-08-23
In [22]:
def simple_ma_strategies(kind, fast, slow, cumulative=True, last=last_, figsize=(16, 2), colors=cscheme('default'), alpha=0.35):
"""A very basic long/short cumulative log return model proof of concept (NOT A STRATEGY RECOMMENDATION)"""
title = ctitle(f"{'Cumulative ' if cumulative else ''}Trend Returns of {kind.upper()}s")
last = last if last is not None else df.shape[0]
closedf = df['close']
maf = df.ta(kind=kind, length=fast)
mas = df.ta(kind=kind, length=slow)
def ma_return_name(name):
return f"{name} {' Cumulative' if cumulative else ''} Trend Return"
# Trade Logic
long = (closedf > maf) & (maf > mas)
short = ~long
cum_long_return = ta.trend_return(closedf, long, cumulative=cumulative)
cum_short_return = ta.trend_return(closedf, short, cumulative=cumulative)
tdf = pd.DataFrame({
ma_return_name(f"long: {maf.name} > {mas.name}"): cum_long_return,
ma_return_name(f"short: {maf.name} < {mas.name}"): cum_short_return,
})
tdf.set_index(closedf.index, inplace=True)
window = tdf.tail(last)
window.plot(kind='area', figsize=figsize, color=colors, linewidth=1, alpha=alpha, title=title, stacked=False, grid=True).axhline(y=0, color="black", lw=1.1)In [23]:
matype = 'ema'
fast_length = 10
medfast_length = 20
slow_length = 50
simple_ma_strategies(matype, fast=fast_length, slow=slow_length, last=recent, colors=cscheme('gr'), alpha=0.5)
machart(matype, fast_length, medfast_length, slow_length, last=recent)
volumechart(matype, last=recent)