Combine Stochastic MACD, RS EMA, and RS VolatAdj EMA
References
- Stochastic Moving Average Convergence/Divergence (MACD) traders.com: TradersTips 2019-11
- Relative Strength Exponential Moving Averages (RS EMA)traders.com: TradersTips 2022-03
- Relative Strength Volatility-Adjusted Exponential Moving Averages (RS VolatAdj EMA)traders.com: TradersTips 2022-05
TASC 2019-11: Combine Stochastic Moving Average Convergence/Divergence (MACD)
In "The Stochastic MACD Oscillator" in this issue, author Vitali Apirine introduces a new indicator created by combining the stochastic oscillator and the MACD. He describes the new indicator as a momentum oscillator and explains that it allows the trader to define overbought and oversold levels similar to the classic stochastic but based on the MACD.
TASC 2022-03: relative strength volatility-adjusted exponential moving average (RS VolatAdj EMA)
For this month's Traders' Tips, the focus is Vitali Apirine's article in this issue, "Relative Strength Moving Averages, Part 3." Here, we present the March 2022 Traders' Tips code with possible implementations in various software.
The current article series "Relative Strength Moving Averages" by Vitali Apirine focuses on differences between traditional exponential moving averages (EMAs) and relative strength-based EMA indicators. In this issue's article, Apirine describes the relative strength volatility-adjusted exponential moving average (RS VolatAdj EMA).
The indicator is designed to account for relative strength of volatility, and it requires a second, corresponding volatility index. For example, if charting the S&P 500 ETF (SPY), one can use the CBOE Volatility Index ($VIX.X). The indicator compared to itself of varying lengths, or the indicator compared to a traditional EMA with the same length, can be used to help to identify trends and turning points. During an uptrend, RS VolatAdj EMA crossovers can be used to help identify entry points for long trades.
TASC 2022-05: Relative Strength Moving Averages (RS_EMA)
For this month's Traders' Tips, the focus is Vitali Apirine's article in the January 2022 issue, "Relative Strength Moving Averages, Part 1: The Relative Strength Exponential Moving Average (RS EMA)." Here, we present the May 2022 Traders' Tips code with possible implementations in various software.
In part 1 of a three-part series focused on differences between traditional EMAs and relative strength-based EMA indicators, author Vitali Apirine introduces the relative strength exponential moving average (RS EMA). The study is designed to account for relative strength of price and is considered a trend-following indicator that can be used in combination with an EMA of the same length to identify the overall trend. RS EMAs with different lengths can define turning points and filter price movements.
Load basic packages
import pandas as pd
import numpy as np
import os
import gc
import copy
from pathlib import Path
from datetime import datetime, timedelta, time, date
#this package is to download equity price data from yahoo finance
#the source code of this package can be found here: https://github.com/ranaroussi/yfinance/blob/main
import yfinance as yf
pd.options.display.max_rows = 100
pd.options.display.max_columns = 100
import warnings
warnings.filterwarnings("ignore")
import pytorch_lightning as pl
random_seed=1234
pl.seed_everything(random_seed)
Global seed set to 1234
1234
Download data via yfinance package
#S&P 500 (^GSPC), Dow Jones Industrial Average (^DJI), NASDAQ Composite (^IXIC)
#Russell 2000 (^RUT), Crude Oil Nov 21 (CL=F), Gold Dec 21 (GC=F)
#Treasury Yield 10 Years (^TNX)
#benchmark_tickers = ['^GSPC', '^DJI', '^IXIC', '^RUT', 'CL=F', 'GC=F', '^TNX']
benchmark_tickers = ['^GSPC', '^VIX']
tickers = benchmark_tickers + ['GSK', 'NVO', 'PFE']
#https://github.com/ranaroussi/yfinance/blob/main/yfinance/base.py
# def history(self, period="1mo", interval="1d",
# start=None, end=None, prepost=False, actions=True,
# auto_adjust=True, back_adjust=False,
# proxy=None, rounding=False, tz=None, timeout=None, **kwargs):
dfs = {}
for ticker in tickers:
cur_data = yf.Ticker(ticker)
hist = cur_data.history(period="max", start='2000-01-01')
print(datetime.now(), ticker, hist.shape, hist.index.min(), hist.index.max())
dfs[ticker] = hist
2022-09-06 23:55:59.571501 ^GSPC (5707, 7) 1999-12-31 00:00:00 2022-09-06 00:00:00
2022-09-06 23:56:00.382183 ^VIX (5707, 7) 1999-12-31 00:00:00 2022-09-06 00:00:00
2022-09-06 23:56:00.652416 GSK (5707, 7) 1999-12-31 00:00:00 2022-09-06 00:00:00
2022-09-06 23:56:01.023093 NVO (5707, 7) 1999-12-31 00:00:00 2022-09-06 00:00:00
2022-09-06 23:56:01.369962 PFE (5707, 7) 1999-12-31 00:00:00 2022-09-06 00:00:00
ticker = 'GSK'
dfs[ticker].tail(5)
Open | High | Low | Close | Volume | Dividends | Stock Splits | |
---|---|---|---|---|---|---|---|
Date | |||||||
2022-08-30 | 33.230000 | 33.290001 | 32.919998 | 32.959999 | 3994500 | 0.0 | 0.0 |
2022-08-31 | 32.790001 | 32.880001 | 32.459999 | 32.480000 | 4291800 | 0.0 | 0.0 |
2022-09-01 | 31.830000 | 31.990000 | 31.610001 | 31.690001 | 12390900 | 0.0 | 0.0 |
2022-09-02 | 31.600000 | 31.969999 | 31.469999 | 31.850000 | 8152600 | 0.0 | 0.0 |
2022-09-06 | 31.650000 | 31.760000 | 31.450001 | 31.580000 | 2253660 | 0.0 | 0.0 |
Calculate
df = dfs[ticker][['Open', 'High', 'Low', 'Close', 'Volume']]
df = df.round(2)
df_vix = dfs[ '^VIX'][['Open', 'High', 'Low', 'Close', 'Volume']]
from core.finta import TA
TA.RS_EMA, TA.RS_VOLADJ_EMA, TA.STOCH_MACD
(<function core.finta.TA.RS_EMA(ohlc: pandas.core.frame.DataFrame, ema_period: int = 50, rs_period: int = 50, multiplier: float = 10.0, column: str = 'close', adjust: bool = True) -> pandas.core.series.Series>,
<function core.finta.TA.RS_VOLADJ_EMA(ohlc: pandas.core.frame.DataFrame, vix: pandas.core.series.Series, ema_period: int = 50, rs_period: int = 50, multiplier: float = 10.0, column: str = 'close', adjust: bool = True) -> pandas.core.series.Series>,
<function core.finta.TA.STOCH_MACD(ohlc: pandas.core.frame.DataFrame, period: int = 45, fast_period: int = 12, slow_period: int = 26, signal: int = 9, adjust: bool = True) -> pandas.core.frame.DataFrame>)
df_ta = TA.STOCH_MACD(df, period=45, fast_period = 12, slow_period = 26, signal = 9)
df = df.merge(df_ta, left_index = True, right_index = True, how='inner' )
df_ta = TA.RS_EMA(df, ema_period=14, rs_period=14, multiplier=10, column="close")
df = df.merge(df_ta, left_index = True, right_index = True, how='inner' )
df_ta = TA.RS_VOLADJ_EMA(df, vix = df_vix["Close"], ema_period=20, rs_period=20, multiplier=10, column="close")
df = df.merge(df_ta, left_index = True, right_index = True, how='inner' )
df_ta = TA.EMA(df, period = 20, column="close")
df_ta.name='EMA'
df = df.merge(df_ta, left_index = True, right_index = True, how='inner' )
del df_ta
gc.collect()
66307
display(df.head(5))
display(df.tail(5))
Open | High | Low | Close | Volume | STMACD | STMACD_SIGNAL | RS_EMA | RS_VOLADJ_EMA | EMA | |
---|---|---|---|---|---|---|---|---|---|---|
Date | ||||||||||
1999-12-31 | 19.60 | 19.67 | 19.52 | 19.56 | 139400 | NaN | NaN | 19.560000 | 19.560000 | 19.560000 |
2000-01-03 | 19.58 | 19.71 | 19.25 | 19.45 | 556100 | NaN | NaN | 19.398692 | 19.444762 | 19.502250 |
2000-01-04 | 19.45 | 19.45 | 18.90 | 18.95 | 367200 | NaN | NaN | 18.740637 | 18.926440 | 19.299467 |
2000-01-05 | 19.21 | 19.58 | 19.08 | 19.58 | 481700 | NaN | NaN | 18.963926 | 19.145873 | 19.380453 |
2000-01-06 | 19.38 | 19.43 | 18.90 | 19.30 | 853800 | NaN | NaN | 19.072495 | 19.229105 | 19.360992 |
Open | High | Low | Close | Volume | STMACD | STMACD_SIGNAL | RS_EMA | RS_VOLADJ_EMA | EMA | |
---|---|---|---|---|---|---|---|---|---|---|
Date | ||||||||||
2022-08-30 | 33.23 | 33.29 | 32.92 | 32.96 | 3994500 | -17.783726 | -17.798241 | 32.946965 | 33.026347 | 35.514463 |
2022-08-31 | 32.79 | 32.88 | 32.46 | 32.48 | 4291800 | -17.041234 | -17.646840 | 32.407926 | 32.615475 | 35.225467 |
2022-09-01 | 31.83 | 31.99 | 31.61 | 31.69 | 12390900 | -16.177153 | -17.352902 | 31.523679 | 31.891145 | 34.888756 |
2022-09-02 | 31.60 | 31.97 | 31.47 | 31.85 | 8152600 | -15.936165 | -17.069555 | 31.882197 | 31.865853 | 34.599350 |
2022-09-06 | 31.65 | 31.76 | 31.45 | 31.58 | 2253660 | -15.848321 | -16.825308 | 31.539481 | 31.677276 | 34.311793 |
from core.visuals import *
start = -150
end = df.shape[0]
names = {'main_title': f'{ticker}'}
lines0 = basic_lines(df.iloc[start:end][['RS_VOLADJ_EMA', 'EMA']],
colors = [],
**dict(panel=0, width=2, secondary_y=False))
lines1 = basic_lines(df.iloc[start:end][['STMACD', 'STMACD_SIGNAL']],
colors = ['dodgerblue', 'tomato'],
**dict(panel=1, width=1, secondary_y=False))
lines2 = basic_lines(df.iloc[start:end]['STMACD']-df.iloc[start:end]['STMACD_SIGNAL'],
colors = ['pink'],
**dict(type='bar',width=0.7,panel=1, alpha=0.65,secondary_y=False))
lines_ = dict(**lines0, **lines1)
lines_.update(lines2)
shadows_ = basic_shadows(bands=[-10, 10], nsamples=df.iloc[start:end].shape[0], **dict(panel=1, color="lightskyblue",alpha=0.1,interpolate=True))
fig_config_ = dict(figratio=(18,10), volume=True, volume_panel=2,panel_ratios=(4,3,2), tight_layout=True, returnfig=True,)
ax_cfg_ = {0:dict(basic=[4, 2, ['RS_VOLADJ_EMA', 'EMA']],
title=dict(label = 'RS Volat Adj EMA', fontsize=9, style='italic', loc='left'),
),
2:dict(basic=[3, 0, ['STMACD', 'STMACD_SIGNAL', 'STMACD-STMACD_SIGNAL']],
title=dict(label = 'Stochastic MACD: OverBought>10,OverSold<-10', fontsize=9, style='italic', loc='left'),
),
}
names = {'main_title': f'{ticker}'}
aa_, bb_ = make_panels(main_data = df.iloc[start:end][['Open', 'High', 'Low', 'Close', 'Volume']],
added_plots = lines_,
fill_betweens = shadows_,
fig_config = fig_config_,
axes_config = ax_cfg_,
names = names)
lines0 = basic_lines(df.iloc[start:end][['RS_EMA', 'EMA']],
colors = [],
**dict(panel=0, width=2, secondary_y=False))
lines1 = basic_lines(df.iloc[start:end][['STMACD', 'STMACD_SIGNAL']],
colors = ['dodgerblue', 'tomato'],
**dict(panel=1, width=1, secondary_y=False))
lines2 = basic_lines(df.iloc[start:end]['STMACD']-df.iloc[start:end]['STMACD_SIGNAL'],
colors = ['pink'],
**dict(type='bar',width=0.7,panel=1, alpha=0.65,secondary_y=False))
lines_ = dict(**lines0, **lines1)
lines_.update(lines2)
shadows_ = basic_shadows(bands=[-10, 10], nsamples=df.iloc[start:end].shape[0], **dict(panel=1, color="lightskyblue",alpha=0.1,interpolate=True))
fig_config_ = dict(figratio=(18,10), volume=True, volume_panel=2,panel_ratios=(4,3,2), tight_layout=True, returnfig=True,)
ax_cfg_ = {0:dict(basic=[4, 2, ['RS_EMA', 'EMA']],
title=dict(label = 'RS EMA', fontsize=9, style='italic', loc='left'),
),
2:dict(basic=[3, 0, ['STMACD', 'STMACD_SIGNAL', 'STMACD-STMACD_SIGNAL']],
title=dict(label = 'Stochastic MACD: OverBought>10,OverSold<-10', fontsize=9, style='italic', loc='left'),
),
}
names = {'main_title': f'{ticker}'}
aa_, bb_ = make_panels(main_data = df.iloc[start:end][['Open', 'High', 'Low', 'Close', 'Volume']],
added_plots = lines_,
fill_betweens = shadows_,
fig_config = fig_config_,
axes_config = ax_cfg_,
names = names)
start = -150
end = df.shape[0]
names = {'main_title': f'{ticker}'}
lines0 = basic_lines(df.iloc[start:end][['RS_VOLADJ_EMA', 'RS_EMA', 'EMA']],
colors = [],
**dict(panel=0, width=2, secondary_y=False))
lines1 = basic_lines(df.iloc[start:end][['STMACD', 'STMACD_SIGNAL']],
colors = ['dodgerblue', 'tomato'],
**dict(panel=1, width=1, secondary_y=False))
lines2 = basic_lines(df.iloc[start:end]['STMACD']-df.iloc[start:end]['STMACD_SIGNAL'],
colors = ['pink'],
**dict(type='bar',width=0.7,panel=1, alpha=0.65,secondary_y=False))
lines_ = dict(**lines0, **lines1)
lines_.update(lines2)
shadows_ = basic_shadows(bands=[-10, 10], nsamples=df.iloc[start:end].shape[0], **dict(panel=1, color="lightskyblue",alpha=0.1,interpolate=True))
fig_config_ = dict(figratio=(18,10), volume=False, volume_panel=2,panel_ratios=(4,2), tight_layout=True, returnfig=True,)
ax_cfg_ = {0:dict(basic=[5, 2, ['RS_VOLADJ_EMA', 'RS_EMA','EMA']],
),
2:dict(basic=[3, 0, ['STMACD', 'STMACD_SIGNAL', 'STMACD-STMACD_SIGNAL']],
title=dict(label = 'Stochastic MACD: OverBought>10,OverSold<-10', fontsize=9, style='italic', loc='left'),
),
}
names = {'main_title': f'{ticker}'}
aa_, bb_ = make_panels(main_data = df.iloc[start:end][['Open', 'High', 'Low', 'Close', 'Volume']],
added_plots = lines_,
fill_betweens = shadows_,
fig_config = fig_config_,
axes_config = ax_cfg_,
names = names)