Navigation

    Backtrader Community

    • Register
    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    For code/output blocks: Use ``` (aka backtick or grave accent) in a single line before and after the block. See: http://commonmark.org/help/

    ZigZag based on Close Prices

    Indicators/Strategies/Analyzers
    3
    3
    794
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • ?
      A Former User last edited by

      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:
      IVGWo.png

      Python Results:
      29eq2.png

      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()
      
      1 Reply Last reply Reply Quote 0
      • A
        ab_trader last edited by

        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 to bt. As of zigzag indicator for bt - it was several topics, you may want to search it on the forum.

        • If my answer helped, hit reputation up arrow at lower right corner of the post.
        • Python Debugging With Pdb
        • New to python and bt - check this out
        1 Reply Last reply Reply Quote 1
        • B
          bigdavediode last edited by

          @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.

          1 Reply Last reply Reply Quote 0
          • 1 / 1
          • First post
            Last post
          Copyright © 2016, 2017, 2018, 2019, 2020, 2021 NodeBB Forums | Contributors