mirror of
https://github.com/wassname/pandas-ta.git
synced 2026-07-16 01:20:21 +08:00
1.3 MiB
1.3 MiB
In [1]:
%matplotlib inline
import datetime as dt
import random as rnd
import numpy as np
import pandas as pd
import mplfinance as mpf
from alphaVantageAPI.alphavantage import AlphaVantage
import pandas_ta as ta
from watchlist import colors
%pylab inline
e = pd.DataFrame()Populating the interactive namespace from numpy and matplotlib
In [2]:
e.ta.indicators()Pandas TA - Technical Analysis Indicators - v0.2.08b
Total Indicators: 121
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, cdl_inside, cg, chop, cksp, cmf, cmo, coppock, cross, cross_value, decay, decreasing, dema, donchian, dpo, efi, ema, entropy, eom, er, eri, fisher, fwma, ha, hilo, hl2, hlc3, hma, ichimoku, increasing, inertia, kama, kc, kdj, kst, kurtosis, linreg, log_return, long_run, macd, mad, massi, median, mfi, midpoint, midprice, mom, natr, nvi, obv, ohlc4, pdist, percent_return, pgo, ppo, psar, psl, pvi, pvo, pvol, pvt, pwma, qstick, quantile, rma, roc, rsi, rvgi, rvi, short_run, sinwma, skew, slope, sma, smi, squeeze, stdev, stoch, stochrsi, supertrend, swma, t3, tema, trend_return, trima, trix, true_range, tsi, ttm_trend, ui, uo, variance, vortex, vp, vwap, vwma, wcp, willr, wma, zlma, zscore
In [3]:
help(ta.ema)Help on function ema in module pandas_ta.overlap.ema:
ema(close, length=None, offset=None, **kwargs)
Exponential Moving Average (EMA)
The Exponential Moving Average is more responsive moving average compared to the
Simple Moving Average (SMA). The weights are determined by alpha which is
proportional to it's length. There are several different methods of calculating
EMA. One method uses just the standard definition of EMA and another uses the
SMA to generate the initial value for the rest of the calculation.
Sources:
https://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:moving_averages
https://www.investopedia.com/ask/answers/122314/what-exponential-moving-average-ema-formula-and-how-ema-calculated.asp
Calculation:
Default Inputs:
length=10, adjust=False, sma=True
if sma:
sma_nth = close[0:length].sum() / length
close[:length - 1] = np.NaN
close.iloc[length - 1] = sma_nth
EMA = close.ewm(span=length, adjust=adjust).mean()
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, optional): Default: False
sma (bool, optional): If True, uses SMA for initial value. Default: True
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", timeframe="DA", cols=["dividend", "split_coefficient"]):
AV = AlphaVantage(api_key="YOUR API KEY", premium=False, clean=True, output_size="full")
df = AV.data(symbol=ticker, function=timeframe)
df.set_index(pd.DatetimeIndex(df["date"]), inplace=True) if not df.ta.datetime_ordered else None
df.drop(cols, axis=1, inplace=True, errors="ignore")
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})"
def ta_ylim(series: pd.Series, percent: float = 0.1):
smin, smax = series.min(), series.max()
if isinstance(percent, float) and 0 <= float(percent) <= 1:
y_min = (1 + percent) * smin if smin < 0 else (1 - percent) * smin
y_max = (1 - percent) * smax if smax < 0 else (1 + percent) * smax
return (y_min, y_max)
return (smin, smax)In [5]:
price_size = (16, 8)
ind_size = (16, 3.25)
ticker = "SPY"
# All Data: 0, Last Four Years: 0.25, Last Two Years: 0.5, This Year: 1, Last Half Year: 2, Last Quarter: 3
yearly_divisor = 1
recent = int(ta.TRADING_DAYS_PER_YEAR / yearly_divisor) if yearly_divisor > 0 else df.shape[0]In [6]:
# All the Data
df = farm(ticker)
print(f"{df.name}{df.shape} from {df.index[0]} to {df.index[-1]}\n{df.describe()}")
df.head()Out [6]:
SPY(5250, 7) from 1999-11-01 00:00:00 to 2020-09-11 00:00:00
open high low close adj_close \
count 5250.000000 5250.000000 5250.000000 5250.000000 5250.000000
mean 162.536632 163.498417 161.465172 162.533567 138.609095
std 63.510375 63.701597 63.293436 63.521877 71.070742
min 67.950000 70.000000 67.100000 68.110000 53.914200
25% 116.500000 117.400000 115.580000 116.542500 87.510800
50% 138.352500 139.320000 137.225000 138.183750 106.456300
75% 204.762500 206.070000 203.917500 204.970000 185.195375
max 355.870000 358.750000 353.430000 357.700000 357.700000
volume
count 5.250000e+03
mean 1.112000e+08
std 9.800456e+07
min 6.790000e+04
25% 4.760167e+07
50% 8.220760e+07
75% 1.490664e+08
max 8.708580e+08
| date | open | high | low | close | adj_close | volume | |
|---|---|---|---|---|---|---|---|
| date | |||||||
| 1999-11-01 | 1999-11-01 | 136.5000 | 137.0000 | 135.5625 | 135.5625 | 91.9725 | 4006500.0 |
| 1999-11-02 | 1999-11-02 | 135.9687 | 137.2500 | 134.5937 | 134.5937 | 91.3152 | 6516900.0 |
| 1999-11-03 | 1999-11-03 | 136.0000 | 136.3750 | 135.1250 | 135.5000 | 91.9301 | 7222300.0 |
| 1999-11-04 | 1999-11-04 | 136.7500 | 137.3593 | 135.7656 | 136.5312 | 92.6297 | 7907500.0 |
| 1999-11-05 | 1999-11-05 | 138.6250 | 139.1093 | 136.7812 | 137.8750 | 93.5414 | 7431500.0 |
In [7]:
# Recent Data
recent_startdate = df.tail(recent).index[0]
recent_enddate = df.tail(recent).index[-1]
print(f"{df.name}{df.tail(recent).shape} from {recent_startdate} to {recent_enddate}\n{df.describe()}")
df.tail(recent).head()Out [7]:
SPY(252, 7) from 2019-09-13 00:00:00 to 2020-09-11 00:00:00
open high low close adj_close \
count 5250.000000 5250.000000 5250.000000 5250.000000 5250.000000
mean 162.536632 163.498417 161.465172 162.533567 138.609095
std 63.510375 63.701597 63.293436 63.521877 71.070742
min 67.950000 70.000000 67.100000 68.110000 53.914200
25% 116.500000 117.400000 115.580000 116.542500 87.510800
50% 138.352500 139.320000 137.225000 138.183750 106.456300
75% 204.762500 206.070000 203.917500 204.970000 185.195375
max 355.870000 358.750000 353.430000 357.700000 357.700000
volume
count 5.250000e+03
mean 1.112000e+08
std 9.800456e+07
min 6.790000e+04
25% 4.760167e+07
50% 8.220760e+07
75% 1.490664e+08
max 8.708580e+08
| date | open | high | low | close | adj_close | volume | |
|---|---|---|---|---|---|---|---|
| date | |||||||
| 2019-09-13 | 2019-09-13 | 301.78 | 302.1700 | 300.6800 | 301.09 | 295.1126 | 62053458.0 |
| 2019-09-16 | 2019-09-16 | 299.84 | 301.1378 | 299.4500 | 300.16 | 294.2011 | 57934320.0 |
| 2019-09-17 | 2019-09-17 | 299.94 | 301.0200 | 299.7500 | 300.92 | 294.9460 | 42770135.0 |
| 2019-09-18 | 2019-09-18 | 300.49 | 301.2200 | 298.2400 | 301.10 | 295.1224 | 73875018.0 |
| 2019-09-19 | 2019-09-19 | 301.53 | 302.6300 | 300.7103 | 301.08 | 295.1028 | 77933334.0 |
In [8]:
opendf = df["open"]
closedf = df["close"]
volumedf = df["volume"]In [9]:
# help(df.ta.constants) # for more info
chart_lines = np.append(np.arange(-5, 6, 1), np.arange(-100, 110, 10))
df.ta.constants(True, chart_lines) # Adding the constants for the charts
df.ta.constants(False, np.array([-60, -40, 40, 60])) # Removing some constants from the DataFrame
print(f"Columns: {', '.join(list(df.columns))}")Columns: date, open, high, low, close, adj_close, volume, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, -100, -90, -80, -70, -50, -30, -20, -10, 10, 20, 30, 50, 70, 80, 90, 100
In [ ]:
In [10]:
class Chart(object):
def __init__(self, df: pd.DataFrame = None, strategy: ta.Strategy = ta.CommonStrategy, *args, **kwargs):
self.verbose = kwargs.pop("verbose", False)
if isinstance(df, pd.DataFrame) and df.ta.datetime_ordered:
self.df = df
if self.df.name is not None and self.df.name != "":
df_name = str(self.df.name)
else:
df_name = "DataFrame"
if self.verbose: print(f"[i] Loaded {df_name}{self.df.shape}")
else:
print(f"[X] Oops! Missing 'ohlcv' data or index is not datetime ordered.\n")
return None
self._validate_ta_strategy(strategy)
self._validate_mpf_kwargs(**kwargs)
self._validate_chart_kwargs(**kwargs)
# Build TA and Plot
self.df.ta.strategy(self.strategy, verbose=self.verbose)
self._plot(**kwargs)
def _validate_ta_strategy(self, strategy):
if strategy is not None or isinstance(strategy, ta.Strategy):
self.strategy = strategy
elif len(self.strategy_ta) > 0:
print(f"[+] Strategy: {self.strategy_name}")
else:
self.strategy = ta.CommonStrategy
def _validate_chart_kwargs(self, **kwargs):
"""Chart Settings"""
self.config = {}
self.config["last"] = kwargs.pop("last", recent)
self.config["rpad"] = kwargs.pop("rpad", 10)
self.config["title"] = kwargs.pop("title", "Asset")
self.config["volume"] = kwargs.pop("volume", True)
def _validate_mpf_kwargs(self, **kwargs):
# mpf global chart settings
default_chart = mpf.available_styles()[-1]
default_mpf_width = {
'candle_linewidth': 0.6,
'candle_width': 0.525,
'volume_width': 0.525
}
mpfchart = {}
mpf_style = kwargs.pop("style", "")
if mpf_style == "" or mpf_style.lower() == "random":
mpf_styles = mpf.available_styles()
mpfchart["style"] = mpf_styles[rnd.randrange(len(mpf_styles))]
elif mpf_style.lower() in mpf.available_styles():
mpfchart["style"] = mpf_style
mpfchart["figsize"] = kwargs.pop("figsize", (12, 10))
mpfchart["non_trading"] = kwargs.pop("nontrading", False)
mpfchart["rc"] = kwargs.pop("rc", {'figure.facecolor': '#EDEDED'})
mpfchart["plot_ratios"] = kwargs.pop("plot_ratios", (12, 1.7))
mpfchart["scale_padding"] = kwargs.pop("scale_padding", {'left': 1, 'top': 4, 'right': 1, 'bottom': 1})
mpfchart["tight_layout"] = kwargs.pop("tight_layout", True)
mpfchart["type"] = kwargs.pop("type", "candle")
mpfchart["width_config"] = kwargs.pop("width_config", default_mpf_width)
mpfchart["xrotation"] = kwargs.pop("xrotation", 15)
self.mpfchart = mpfchart
def _attribution(self):
print(f"\nPandas v: {pd.__version__} [pip install pandas] https://github.com/pandas-dev/pandas")
print(f"Data from AlphaVantage v: 1.0.19 [pip install alphaVantage-api] http://www.alphavantage.co https://github.com/twopirllc/AlphaVantageAPI")
print(f"Technical Analysis with Pandas TA v: {ta.version} [pip install pandas_ta] https://github.com/twopirllc/pandas-ta")
print(f"Charts by Matplotlib Finance v: {mpf.__version__} [pip install mplfinance] https://github.com/matplotlib/mplfinance\n")
def _right_pad_df(self, rpad: int, delta_unit: str = "D", range_freq: str = "B"):
if rpad > 0:
dfpad = self.df[-rpad:].copy()
dfpad.iloc[:,:] = np.NaN
df_frequency = self.df.index.value_counts().mode()[0] # Most common frequency
freq_delta = pd.Timedelta(df_frequency, unit=delta_unit)
new_dr = pd.date_range(start=self.df.index[-1] + freq_delta, periods=rpad, freq=range_freq)
dfpad.index = new_dr # Update the padded index with new dates
self.df = self.df.append(dfpad)
def _plot(self, **kwargs):
if not isinstance(self.mpfchart["plot_ratios"], tuple):
print(f"[X] plot_ratios must be a tuple")
return
# Override Chart Title Option
chart_title = self.config["title"]
if "title" in kwargs and isinstance(kwargs["title"], str):
chart_title = kwargs.pop("title")
# Override Right Bar Padding Option
rpad = self.config["rpad"]
if "rpad" in kwargs and kwargs["rpad"] > 0:
rpad = int(kwargs["rpad"])
def cpanel():
return len(self.mpfchart['plot_ratios'])
# Last Second Default TA Indicators
linreg = kwargs.pop("linreg", False)
linreg_name = self.df.ta.linreg(append=True).name if linreg else ""
midpoint = kwargs.pop("midpoint", False)
midpoint_name = self.df.ta.midpoint(append=True).name if midpoint else ""
ohlc4 = kwargs.pop("ohlc4", False)
ohlc4_name = self.df.ta.ohlc4(append=True).name if ohlc4 else ""
clr = kwargs.pop("clr", False)
clr_name = self.df.ta.log_return(cumulative=True, append=True).name if clr else ""
rsi = kwargs.pop("rsi", False)
rsi_length = kwargs.pop("rsi_length", None)
if isinstance(rsi_length, int) and rsi_length > 1:
rsi_name = self.df.ta.rsi(length=rsi_length, append=True).name
elif rsi:
rsi_name = self.df.ta.rsi(append=True).name
else: rsi_name = ""
zscore = kwargs.pop("zscore", False)
zscore_length = kwargs.pop("zscore_length", None)
if isinstance(zscore_length, int) and zscore_length > 1:
zs_name = self.df.ta.zscore(length=zscore_length, append=True).name
elif zscore:
zs_name = self.df.ta.zscore(append=True).name
else: zs_name = ""
macd = kwargs.pop("macd", False)
macd_name = ""
if macd:
macds = self.df.ta.macd(append=True)
macd_name = macds.name
squeeze = kwargs.pop("squeeze", False)
lazybear = kwargs.pop("lazybear", False)
squeeze_name = ""
if squeeze:
squeezes = self.df.ta.squeeze(lazybear=lazybear, detailed=True, append=True)
squeeze_name = squeezes.name
ama = kwargs.pop("archermas", False)
ama_name = ""
if ama:
amas = self.df.ta.amat(append=True)
ama_name = amas.name
aobv = kwargs.pop("archerobv", False)
aobv_name = ""
if aobv:
aobvs = self.df.ta.aobv(append=True)
aobv_name = aobvs.name
treturn = kwargs.pop("trendreturn", False)
if treturn:
# Long Trend requires Series Comparison (<=. <, = >, >=)
# or Trade Logic that yields trends in binary.
default_long = self.df["SMA_10"] > self.df["SMA_20"]
long_trend = kwargs.pop("long_trend", default_long)
short_trend = ~long_trend # Opposite/Inverse
self.df["TRl"] = ta.trend_return(self.df["close"], long_trend, cumulative=True)
self.df["TRs"] = ta.trend_return(self.df["close"], short_trend, cumulative=True)
self.df["TR"] = self.df["TRl"] + self.df["TRs"]
# Pad and trim Chart
self._right_pad_df(rpad)
mpfdf = self.df.tail(self.config["last"])
mpfdf_columns = list(self.df.columns)
# BEGIN: Custom TA Plots and Panels
# Modify the area below
taplots = [] # Holds all the additional plots
# Panel 0: Price Overlay
if linreg_name in mpfdf_columns:
taplots += [mpf.make_addplot(mpfdf[linreg_name], type=kwargs.pop("linreg_type", "line"), color=kwargs.pop("linreg_color", "black"), linestyle="-.", width=1.2, panel=0)]
if midpoint_name in mpfdf_columns:
taplots += [mpf.make_addplot(mpfdf[midpoint_name], type=kwargs.pop("midpoint_type", "scatter"), color=kwargs.pop("midpoint_color", "fuchsia"), width=0.4, panel=0)]
if ohlc4_name in mpfdf_columns:
taplots += [mpf.make_addplot(mpfdf[ohlc4_name], ylabel=ohlc4_name, type=kwargs.pop("ohlc4_type", "scatter"), color=kwargs.pop("ohlc4_color", "blue"), alpha=0.85, width=0.4, panel=0)]
if self.strategy.name == ta.CommonStrategy.name:
total_sma = 0 # Check if all the overlap indicators exists before adding plots
for c in ["SMA_10", "SMA_20", "SMA_50", "SMA_200"]:
if c in mpfdf_columns: total_sma += 1
else: print(f"[X] Indicator: {c} missing!")
if total_sma == 4:
ta_smas = [
mpf.make_addplot(mpfdf["SMA_10"], color="green", width=1.5, panel=0),
mpf.make_addplot(mpfdf["SMA_20"], color="orange", width=2, panel=0),
mpf.make_addplot(mpfdf["SMA_50"], color="red", width=2, panel=0),
mpf.make_addplot(mpfdf["SMA_200"], color="maroon", width=3, panel=0),
]
taplots += ta_smas
if len(ama_name):
amat_sr_ = mpfdf[amas.columns[-1]][mpfdf[amas.columns[-1]] > 0]
amat_sr = amat_sr_.index.to_list()
else:
amat_sr = None
# Panel 1: If volume=True, the add the VOL MA. Since we know there is only one, we immediately pop it.
if self.config["volume"]:
volma = [x for x in list(self.df.columns) if x.startswith("VOL_")].pop()
max_vol = mpfdf["volume"].max()
ta_volume = [mpf.make_addplot(mpfdf[volma], color="red", width=2, panel=1, ylim=(-.2 * max_vol, 1.5 * max_vol))]
taplots += ta_volume
# Panels 2 - 9
common_plot_ratio = (3,)
if len(aobv_name):
_p = kwargs.pop("aobv_percenty", 0.2)
aobv_ylim = ta_ylim(mpfdf[aobvs.columns[0]], _p)
taplots += [
mpf.make_addplot(mpfdf[aobvs.columns[0]], ylabel=aobv_name, color="black", width=1.5, panel=cpanel(), ylim=aobv_ylim),
mpf.make_addplot(mpfdf[aobvs.columns[2]], color="silver", width=1, panel=cpanel(), ylim=aobv_ylim),
mpf.make_addplot(mpfdf[aobvs.columns[3]], color="green", width=1, panel=cpanel(), ylim=aobv_ylim),
mpf.make_addplot(mpfdf[aobvs.columns[4]], color="red", width=1.2, panel=cpanel(), ylim=aobv_ylim),
]
self.mpfchart["plot_ratios"] += common_plot_ratio # Required to add a new Panel
if clr_name in mpfdf_columns:
_p = kwargs.pop("clr_percenty", 0.1)
clr_ylim = ta_ylim(mpfdf[clr_name], _p)
taplots += [mpf.make_addplot(mpfdf[clr_name], ylabel=clr_name, color="black", width=1.5, panel=cpanel(), ylim=clr_ylim)]
if (1 - _p) * mpfdf[clr_name].min() < 0 and (1 + _p) * mpfdf[clr_name].max() > 0:
taplots += [mpf.make_addplot(mpfdf["0"], color="gray", width=1.2, panel=cpanel(), ylim=clr_ylim)]
self.mpfchart["plot_ratios"] += common_plot_ratio # Required to add a new Panel
if rsi_name in mpfdf_columns:
rsi_ylim = (0, 100)
taplots += [
mpf.make_addplot(mpfdf[rsi_name], ylabel=rsi_name, color=kwargs.pop("rsi_color", "black"), width=1.5, panel=cpanel(), ylim=rsi_ylim),
mpf.make_addplot(mpfdf["20"], color="green", width=1, panel=cpanel(), ylim=rsi_ylim),
mpf.make_addplot(mpfdf["50"], color="gray", width=0.8, panel=cpanel(), ylim=rsi_ylim),
mpf.make_addplot(mpfdf["80"], color="red", width=1, panel=cpanel(), ylim=rsi_ylim),
]
self.mpfchart["plot_ratios"] += common_plot_ratio # Required to add a new Panel
if macd_name in mpfdf_columns:
_p = kwargs.pop("macd_percenty", 0.15)
macd_ylim = ta_ylim(mpfdf[macd_name], _p)
taplots += [
mpf.make_addplot(mpfdf[macd_name], ylabel=macd_name, color="black", width=1.5, panel=cpanel()),#, ylim=macd_ylim),
mpf.make_addplot(mpfdf[macds.columns[-1]], color="blue", width=1.1, panel=cpanel()),#, ylim=macd_ylim),
mpf.make_addplot(mpfdf[macds.columns[1]], type="bar", alpha=0.8, color="dimgray", width=0.8, panel=cpanel()),#, ylim=macd_ylim),
mpf.make_addplot(mpfdf["0"], color="black", width=1.2, panel=cpanel()),#, ylim=macd_ylim),
]
self.mpfchart["plot_ratios"] += common_plot_ratio # Required to add a new Panel
if zs_name in mpfdf_columns:
_p = kwargs.pop("zascore_percenty", 0.2)
zs_ylim = ta_ylim(mpfdf[zs_name], _p)
taplots += [
mpf.make_addplot(mpfdf[zs_name], ylabel=zs_name, color="black", width=1.5, panel=cpanel(), ylim=zs_ylim),
mpf.make_addplot(mpfdf["-3"], color="red", width=1.2, panel=cpanel(), ylim=zs_ylim),
mpf.make_addplot(mpfdf["-2"], color="orange", width=1, panel=cpanel(), ylim=zs_ylim),
mpf.make_addplot(mpfdf["-1"], color="silver", width=1, panel=cpanel(), ylim=zs_ylim),
mpf.make_addplot(mpfdf["0"], color="black", width=1.2, panel=cpanel(), ylim=zs_ylim),
mpf.make_addplot(mpfdf["1"], color="silver", width=1, panel=cpanel(), ylim=zs_ylim),
mpf.make_addplot(mpfdf["2"], color="orange", width=1, panel=cpanel(), ylim=zs_ylim),
mpf.make_addplot(mpfdf["3"], color="red", width=1.2, panel=cpanel(), ylim=zs_ylim)
]
self.mpfchart["plot_ratios"] += common_plot_ratio # Required to add a new Panel
if squeeze_name in mpfdf_columns:
_p = kwargs.pop("squeeze_percenty", 0.6)
sqz_ylim = ta_ylim(mpfdf[squeeze_name], _p)
taplots += [
mpf.make_addplot(mpfdf[squeezes.columns[-4]], type="bar", color="lime", alpha=0.65, width=0.8, panel=cpanel(), ylim=sqz_ylim),
mpf.make_addplot(mpfdf[squeezes.columns[-3]], type="bar", color="green", alpha=0.65, width=0.8, panel=cpanel(), ylim=sqz_ylim),
mpf.make_addplot(mpfdf[squeezes.columns[-2]], type="bar", color="maroon", alpha=0.65, width=0.8, panel=cpanel(), ylim=sqz_ylim),
mpf.make_addplot(mpfdf[squeezes.columns[-1]], type="bar", color="red", alpha=0.65, width=0.8, panel=cpanel(), ylim=sqz_ylim),
mpf.make_addplot(mpfdf["0"], color="black", width=1.2, panel=cpanel(), ylim=sqz_ylim),
mpf.make_addplot(mpfdf[squeezes.columns[4]], ylabel=squeeze_name, color="green", width=2, panel=cpanel(), ylim=sqz_ylim),
mpf.make_addplot(mpfdf[squeezes.columns[5]], color="red", width=1.8, panel=cpanel(), ylim=sqz_ylim),
]
self.mpfchart["plot_ratios"] += common_plot_ratio # Required to add a new Panel
if treturn:
_p = kwargs.pop("treturn_percenty", 0.33)
treturn_ylim = ta_ylim(mpfdf["TR"], _p)
taplots += [
mpf.make_addplot(mpfdf["TRl"], ylabel="Trend Return", type="bar", color="green", alpha=0.45, width=0.8, panel=cpanel(), ylim=treturn_ylim),
mpf.make_addplot(mpfdf["TRs"], type="bar", color="red", alpha=0.45, width=0.8, panel=cpanel(), ylim=treturn_ylim),
mpf.make_addplot(mpfdf["TR"], color="black", width=1.5, panel=cpanel(), ylim=treturn_ylim),
mpf.make_addplot(mpfdf["0"], color="black", width=1.2, panel=cpanel(), ylim=treturn_ylim),
]
self.mpfchart["plot_ratios"] += common_plot_ratio # Required to add a new Panel
_p = kwargs.pop("cstreturn_percenty", 0.33)
trcs = mpfdf["TR"].cumsum()
treturncs_ylim = ta_ylim(trcs, _p)
taplots += [
mpf.make_addplot(trcs, ylabel="Trend B&H", color="black", width=1.5, panel=cpanel(), ylim=treturncs_ylim),
mpf.make_addplot(mpfdf["0"], color="black", width=1.2, panel=cpanel(), ylim=treturncs_ylim),
]
self.mpfchart["plot_ratios"] += common_plot_ratio # Required to add a new Panel
# END: Custom TA Plots and Panels
if self.verbose:
additional_ta = []
chart_title = f"{chart_title} [{self.strategy.name}] (last {self.config['last']} bars)"
chart_title += f"\nSince {mpfdf.index[0]} till {mpfdf.index[-1]}"
if len(linreg_name) > 0: additional_ta.append(linreg_name)
if len(midpoint_name) > 0: additional_ta.append(midpoint_name)
if len(ohlc4_name) > 0: additional_ta.append(ohlc4_name)
if len(additional_ta) > 0:
chart_title += f"\nIncluding: {', '.join(additional_ta)}"
if amat_sr:
vlines_ = dict(vlines=amat_sr, alpha=0.1, colors="red")
else:
# Hidden because vlines needs valid arguments even if None
vlines_ = dict(vlines=mpfdf.index[0], alpha=0, colors="white")
# Create Final Plot
mpf.plot(mpfdf,
title=chart_title,
type=self.mpfchart["type"],
style=self.mpfchart["style"],
datetime_format="%-m/%-d/%Y",
volume=self.config["volume"],
figsize=self.mpfchart["figsize"],
tight_layout=self.mpfchart["tight_layout"],
scale_padding=self.mpfchart["scale_padding"],
panel_ratios=self.mpfchart["plot_ratios"], # This key needs to be update above if adding more panels
xrotation=self.mpfchart["xrotation"],
update_width_config=self.mpfchart["width_config"],
show_nontrading=self.mpfchart["non_trading"],
vlines=vlines_,
addplot=taplots
)
self._attribution()In [11]:
# Used for example Trend Return Long Trend Below
macd_ = ta.macd(closedf)
macdh = macd_[macd_.columns[1]]
Chart(df,
# style: which mplfinance chart style to use. Added "random" as an option.
# rpad: how many bars to leave empty on the right of the chart
style="yahoo", title=ticker, last=recent, rpad=10,
# Overlap Indicators
linreg=True, midpoint=False, ohlc4=False, archermas=True,
# Example Indicators with default parameters
volume=True, rsi=True, clr=True, macd=True, zscore=False, squeeze=False, lazybear=False,
# Archer OBV and OBV MAs (https://www.tradingview.com/script/Co1ksara-Trade-Archer-On-balance-Volume-Moving-Averages-v1/)
archerobv=False,
# Create trends and see their returns
trendreturn=False,
# Example Trends or create your own. Trend must yield Booleans
long_trend=ta.sma(closedf,10) > ta.sma(closedf,20), # trend: sma(close,10) > sma(close,20) [Default Example]
# long_trend=closedf > ta.ema(closedf,5), # trend: close > ema(close,5)
# long_trend=ta.sma(closedf,10) > ta.ema(closedf,50), # trend: sma(close,10) > ema(close,50)
# long_trend=macdh > 0, # trend: macd hist > 0
# long_trend=ta.increasing(ta.sma(ta.rsi(closedf), 10), 5, asint=False), # trend: rising sma(rsi, 10) for the previous 5 periods
show_nontrading=False, # Intraday use if needed
verbose=True, # More detail
)Out [11]:
[i] Loaded SPY(5250, 34)
[+] Strategy: Common Price and Volume SMAs
[i] Indicator arguments: {'append': True}
[i] Multiprocessing: 4 of 4 cores.
[i] Total indicators: 5
[i] Columns added: 5
Pandas v: 1.1.0 [pip install pandas] https://github.com/pandas-dev/pandas Data from AlphaVantage v: 1.0.19 [pip install alphaVantage-api] http://www.alphavantage.co https://github.com/twopirllc/AlphaVantageAPI Technical Analysis with Pandas TA v: 0.2.08b [pip install pandas_ta] https://github.com/twopirllc/pandas-ta Charts by Matplotlib Finance v: 0.12.6a3 [pip install mplfinance] https://github.com/matplotlib/mplfinance
<__main__.Chart at 0x11348ee20>
In [12]:
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=colors("BkBl"), linewidth=1, title=ctitle(clrdf.name, ticker=ticker, length=recent), grid=True)Out [12]:
<matplotlib.axes._subplots.AxesSubplot at 0x116d6ab20>
In [13]:
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=colors("BkBl"), 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 [13]:
<matplotlib.lines.Line2D at 0x117267250>
In [14]:
zscoredf = df.ta.zscore(length=30, append=True)
zcolors = ["darkgreen", "green", "silver", "silver", "red", "maroon", "black"]
zcols = df[["-4", "-3", "-2", "2", "3", "4", zscoredf.name]].tail(recent)
zcols.plot(figsize=ind_size, color=zcolors, linewidth=1.2, title=ctitle(zscoredf.name, ticker=ticker, length=recent), grid=True).axhline(y=0, color="black", lw=1.1)Out [14]:
<matplotlib.lines.Line2D at 0x1167a4a00>
In [15]:
# Now Volume Z Score
zvscoredf = df.ta.zscore(close="volume", length=30, prefix="VOL", append=True)
zcolors = ["darkgreen", "green", "silver", "silver", "red", "maroon", "black"]
zvcols = df[["-4", "-3", "-2", "2", "3", "4", zvscoredf.name]].tail(recent)
zvcols.plot(figsize=ind_size, color=zcolors, linewidth=1.2, title=ctitle(zvscoredf.name, ticker=ticker, length=recent), grid=True).axhline(y=0, color="black", lw=1.1)Out [15]:
<matplotlib.lines.Line2D at 0x1175b2730>
In [16]:
# help(ta.squeeze)In [17]:
Chart(df, style="yahoo", title=ticker, verbose=False,
last=recent, rpad=10, clr=True, squeeze=True,
show_nontrading=False, # Intraday use if needed
)Out [17]:
Pandas v: 1.1.0 [pip install pandas] https://github.com/pandas-dev/pandas Data from AlphaVantage v: 1.0.19 [pip install alphaVantage-api] http://www.alphavantage.co https://github.com/twopirllc/AlphaVantageAPI Technical Analysis with Pandas TA v: 0.2.08b [pip install pandas_ta] https://github.com/twopirllc/pandas-ta Charts by Matplotlib Finance v: 0.12.6a3 [pip install mplfinance] https://github.com/matplotlib/mplfinance
<__main__.Chart at 0x1175701f0>
In [18]:
Chart(df, style="yahoo", title=ticker, verbose=False,
last=recent, rpad=10, clr=True, squeeze=True, lazybear=True,
show_nontrading=False, # Intraday use if needed
)Out [18]:
Pandas v: 1.1.0 [pip install pandas] https://github.com/pandas-dev/pandas Data from AlphaVantage v: 1.0.19 [pip install alphaVantage-api] http://www.alphavantage.co https://github.com/twopirllc/AlphaVantageAPI Technical Analysis with Pandas TA v: 0.2.08b [pip install pandas_ta] https://github.com/twopirllc/pandas-ta Charts by Matplotlib Finance v: 0.12.6a3 [pip install mplfinance] https://github.com/matplotlib/mplfinance
<__main__.Chart at 0x114347e20>
In [19]:
Chart(df, style="yahoo", title=ticker, verbose=False,
last=recent, rpad=10,
volume=True, midpoint=False, ohlc4=False,
rsi=False, clr=True, macd=False, zscore=False, squeeze=False, lazybear=False,
archermas=True, archerobv=False,
show_nontrading=False, # Intraday use if needed
)Out [19]:
Pandas v: 1.1.0 [pip install pandas] https://github.com/pandas-dev/pandas Data from AlphaVantage v: 1.0.19 [pip install alphaVantage-api] http://www.alphavantage.co https://github.com/twopirllc/AlphaVantageAPI Technical Analysis with Pandas TA v: 0.2.08b [pip install pandas_ta] https://github.com/twopirllc/pandas-ta Charts by Matplotlib Finance v: 0.12.6a3 [pip install mplfinance] https://github.com/matplotlib/mplfinance
<__main__.Chart at 0x117cfcbe0>
In [20]:
Chart(df, style="yahoo", title=ticker, verbose=False,
last=recent, rpad=10,
volume=True, midpoint=False, ohlc4=False,
rsi=False, clr=True, macd=False, zscore=False, squeeze=False, lazybear=False,
archermas=False, archerobv=True,
show_nontrading=False, # Intraday use if needed
)Out [20]:
Pandas v: 1.1.0 [pip install pandas] https://github.com/pandas-dev/pandas Data from AlphaVantage v: 1.0.19 [pip install alphaVantage-api] http://www.alphavantage.co https://github.com/twopirllc/AlphaVantageAPI Technical Analysis with Pandas TA v: 0.2.08b [pip install pandas_ta] https://github.com/twopirllc/pandas-ta Charts by Matplotlib Finance v: 0.12.6a3 [pip install mplfinance] https://github.com/matplotlib/mplfinance
<__main__.Chart at 0x116ce9820>
In [ ]: