ZigZag based on Close Prices
-
Hey guys, I'm new here. I'm trying to reply a zigzag based on closes prices in python. I have this Metastock Formula. I have a python code with similar results but not the right ones. The timeseries of python and Metastock are the same from Yahoo finance!
Thanks for your help!Metastock Formula:
{ Copyright (c) 2004, John Bruns and Financial Trading Inc. } reversal:=Input("Reversal",0,100,5); pc:=Input("Use Percentage?",0,1,1); z:=If(pc,Zig(CLOSE,reversal,%),Zig(CLOSE,reversal,$)); peakbar:=LastValue(BarsSince((z>Ref(z,-1)AND Ref(Z,-1)<Ref(Z,-2)) OR (z<Ref(z,-1))AND Ref(Z,-1)>Ref(Z,-2)))+1; lastpeak:=LastValue(Ref(z,-peakbar)); lastend:=LastValue(z); bars:=Cum(1); invalid:=If(pc,If(Abs(lastend-lastpeak)*100/lastpeak<reversal,1,0),If(Abs(lastend-lastpeak)<reversal,1,0)); If(bars>=LastValue(bars)-peakbar AND invalid,lastpeak,z);
Metastock Results:
Python Results:
Python code:
from __future__ import division import matplotlib.pyplot as plt import numpy as np def islocalmax(x): """Both neighbors are lower, assumes a centered window of size 3""" return (x[0] < x[1]) & (x[2] < x[1]) def islocalmin(x): """Both neighbors are higher, assumes a centered window of size 3""" return (x[0] > x[1]) & (x[2] > x[1]) def isextrema(x): return islocalmax(x) or islocalmin(x) def create_zigzag(col, p=0.05): # Find the local min/max # converting to bool converts NaN to True, which makes it include the endpoints ext_loc = col.rolling(3, center=True).apply(isextrema, raw=False).astype(np.bool_) # extract values at local min/max ext_val = col[ext_loc] # filter locations based on threshold thres_ext_loc = (ext_val.diff().abs() > (ext_val.shift(-1).abs() * p)) # Keep the endpoints thres_ext_loc.iloc[0] = True thres_ext_loc.iloc[-1] = True thres_ext_loc = thres_ext_loc[thres_ext_loc] # extract values at filtered locations thres_ext_val = col.loc[thres_ext_loc.index] # again search the extrema to force the zigzag to always go from high > low or vice versa, # never low > low, or high > high ext_loc = thres_ext_val.rolling(3, center=True).apply(isextrema, raw=False).astype(np.bool_) thres_ext_val =thres_ext_val[ext_loc] return thres_ext_val from pandas_datareader import data # Only get the adjusted close. serie = data.DataReader( "AAPL", start='2018-1-1', end='2020-12-31', data_source='yahoo' ) dfzigzag = serie.apply(create_zigzag) data1_zigzag = dfzigzag['Close'].dropna() fig, axs = plt.subplots(figsize=(10, 3)) axs.plot(serie.Close, '-', ms=4, label='original') axs.plot(data1_zigzag, 'ro-', ms=4, label='zigzag') axs.legend() plt.show()
-
Just a friendly notice, that this forum is dedicated to
backtrader
, so you may not be able to see an answer on your question since it is not related tobt
. As ofzigzag
indicator forbt
- it was several topics, you may want to search it on the forum. -
@Martin-Bouhier said in ZigZag based on Close Prices:
Input("Reversal",0,100,5);
Hi Martin, I would suspect that you're either not using the same input data (ie. a moving average or smoother that is smaller and finer in the Metastock formula) or that the "percentage" input involves specifying a retracement perhaps before it counts as a peak or valley in that zig zag routine. Also I'm curious to know what the 5 in the "reversal" params specifies.
I don't like that python version. If there are repeated values at a peak, for example such as 200, 201, 201, 199, then it's possible for the code to entirely miss a peak.
Good luck.