mirror of
https://github.com/wassname/pandas-ta.git
synced 2026-07-19 11:26:11 +08:00
941 KiB
941 KiB
In [1]:
%matplotlib inline
import datetime as dt
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 - v0.1.75b
Total Indicators: 111
Abbreviations:
aberration, above, above_value, accbands, ad, adosc, adx, amat, ao, aobv, apo, aroon, atr, bbands, below, below_value, bias, bop, brar, cci, cdl_doji, cg, chop, cksp, cmf, cmo, coppock, cross, cross_value, decreasing, dema, donchian, dpo, efi, ema, entropy, eom, fisher, fwma, ha, hl2, hlc3, hma, ichimoku, increasing, inertia, kama, kc, kdj, kst, kurtosis, linear_decay, linreg, log_return, long_run, macd, mad, massi, median, mfi, midpoint, midprice, mom, natr, nvi, obv, ohlc4, pdist, percent_return, ppo, psar, psl, pvi, pvo, pvol, pvt, pwma, qstick, quantile, rma, roc, rsi, rvgi, rvi, short_run, sinwma, skew, slope, sma, stdev, stoch, supertrend, swma, t3, tema, trend_return, trima, trix, true_range, tsi, uo, variance, vortex, vp, vwap, vwma, wcp, 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(pd.DatetimeIndex(df['date']), inplace=True) if not df.ta.datetime_ordered else None
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(5032, 6) from 2020-01-03 00:00:00 to 2020-07-02 00:00:00
open high low close volume
count 5032.000000 5032.000000 5032.000000 5032.000000 5.032000e+03
mean 161.538411 162.482372 160.494256 161.538568 1.151123e+08
std 62.555181 62.736339 62.356801 62.565415 9.808883e+07
min 67.950000 70.000000 67.100000 68.110000 6.790000e+04
25% 115.467500 116.397500 114.552500 115.500000 5.054542e+07
50% 136.480000 137.170000 135.510000 136.420000 8.560940e+07
75% 204.960000 206.205000 204.112500 205.210000 1.531777e+08
max 337.790000 339.080000 337.480000 338.340000 8.708580e+08
| date | open | high | low | close | volume | |
|---|---|---|---|---|---|---|
| date | ||||||
| 2000-07-03 | 2000-07-03 | 145.4375 | 147.4375 | 145.1875 | 147.2812 | 1436600.0 |
| 2000-07-05 | 2000-07-05 | 146.3750 | 146.6562 | 144.3750 | 144.6250 | 2748200.0 |
| 2000-07-06 | 2000-07-06 | 144.9375 | 146.4687 | 144.2187 | 145.7500 | 5963200.0 |
| 2000-07-07 | 2000-07-07 | 146.6875 | 148.7812 | 146.2500 | 148.0937 | 3034800.0 |
| 2000-07-10 | 2000-07-10 | 147.8750 | 148.9062 | 147.5312 | 147.8437 | 2816100.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(append, lower_bound=-100, upper_bound=100, every=1) method of pandas_ta.core.AnalysisIndicators instance
Constants
Useful for creating indicator levels or if you need some constant value
easily added to your DataFrame.
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:
append (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.
| date | open | high | low | close | volume | -4 | -3 | -2 | -1 | 0 | 1 | 2 | 3 | 4 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| date | |||||||||||||||
| 2020-06-26 | 2020-06-26 | 306.1600 | 306.39 | 299.4200 | 300.05 | 127811745.0 | -4 | -3 | -2 | -1 | 0 | 1 | 2 | 3 | 4 |
| 2020-06-29 | 2020-06-29 | 301.4100 | 304.61 | 298.9300 | 304.46 | 79411577.0 | -4 | -3 | -2 | -1 | 0 | 1 | 2 | 3 | 4 |
| 2020-06-30 | 2020-06-30 | 303.9900 | 310.20 | 303.8200 | 308.36 | 112828251.0 | -4 | -3 | -2 | -1 | 0 | 1 | 2 | 3 | 4 |
| 2020-07-01 | 2020-07-01 | 309.5700 | 311.85 | 309.0371 | 310.57 | 71910372.0 | -4 | -3 | -2 | -1 | 0 | 1 | 2 | 3 | 4 |
| 2020-07-02 | 2020-07-02 | 314.2379 | 315.70 | 310.5962 | 312.19 | 69214995.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'), rot=None):
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[0], 2), width=0.5, color=colors, alpha=alpha, stacked=True, rot=rot)
vadf = df.ta(kind=kind, close=volumedf, length=length).tail(last)
vadf.plot(figsize=(figsize[0], 2), lw=1.4, color='black', title=title, grid=True, rot=rot)In [10]:
machart('ema', 8, 21, 50, last=recent)
volumechart('ema', last=recent, rot=90)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 0x11db02df0>
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 0x11db022b0>
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 0x11dc20100>
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 0x11d489280>
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, rot=90)
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 0x11b37d7f0>
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 0x11e2ce6a0>
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 0x11b293790>
In [21]:
def recent_crosses(series, **kwargs):
last = kwargs.pop('last', 5)
timestamp = list(series[series > 0].tail(last).index[::-1])
return [t.strftime('%Y-%m-%d') for t in timestamp]
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"\nMost recent {cross_above.name} Dates:\n {', '.join(recent_crosses_above)}")
print(f"Most recent {cross_below.name} Dates:\n {', '.join(recent_crosses_below)}", "\n")Most recent close_XA_SMA_10 Dates:
2020-06-30, 2020-06-23, 2020-05-18, 2020-05-07, 2020-05-05
Most recent close_XB_SMA_10 Dates:
2020-06-24, 2020-06-11, 2020-05-12, 2020-05-06, 2020-05-01
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)In [ ]: