Combine Stochastic MACD, RS EMA, and RS VolatAdj EMA

References

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)

png

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)

png

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)

png