- ago
The PeakTroughCalculator is missing major peaks while flagging little ones. Is this a bug? How can this be fixed? (I can't use PeakTroughReversalType.ATR for the peak detection because the KVO indicator doesn't generate a Bar object.)



CODE:
   public override void Initialize(BarHistory bars)    {       kvo = new KVO(bars,34,55);       PlotIndicator(kvo);       zKvo = new ZScore(kvo,55);       PlotIndicator(zKvo, plotStyle: PlotStyle.Line);       PeakTroughCalculator kvoPeakTroughs = new PeakTroughCalculator(kvo, 150.8, PeakTroughReversalType.Percent);       foreach (PeakTrough peakTrough in kvoPeakTroughs.PeakTroughs)       {          if (peakTrough.Type == PeakTroughType.Peak) //peaks are orange          {             SetBackgroundColor(bars, peakTrough.PeakTroughIndex,WLColor.Orange, kvo.PaneTag);          }          else          {             SetBackgroundColor(bars, peakTrough.PeakTroughIndex,WLColor.LightGreen, kvo.PaneTag);          }             }    } IndicatorBase kvo, zKvo;
I think if the current PeakTroughCalculator had better peak discretion that would fix this problem. But there was once a discussion about allowing the user to pass in his own PeakTroughFinding routine. Has that ever been implemented? If so, where's the interface documenting it?
0
300
Solved
10 Replies

Reply

Bookmark

Sort
- ago
#1
So a KVO move from 247K on Jun 13 to -358K on Jun 14 does not qualify for a 150.8% retracement, triggering a valid peak/trough? In my book, this is a 240% move! Where's the "bug"? The fallacy here IMHO is to pick a very specific indicator with wild swings (like OBV). Try it on RSI with 150.8% and you never get a single peak/trough.
0
- ago
#2
QUOTE:
So a KVO move from 247K on Jun 13 to -358K on Jun 14 does not qualify for a 150.8% retracement,

That one is okay. It's not one that's circled in the example.

So why is it missing the major peaks circled (Feb 16 & May 19) in the diagram (and catching the little ones)? It should flag these major peaks.

At any rate, how can I pass in my own peak detection routine?
0
- ago
#3
For example, what exact peaks/troughs are missed and misdetected? If you show the table with the indicator values that may help.
0
Cone8
 ( 23.86% )
- ago
#4
The problem here is both percentage and negative numbers. A percentage greater than 100 breaks down the calculation once the value turns negative.

Say you start with a value of 50 and you're looking for a "150% peak". That won't happen until you hit 50 * (1 - 150/100) = -25.

Now what's 150% "rise" from -25. That's -25 * (1 + 150/ 100) = -62.5 => fail

Resolved:
Don't use PeakTroughReversalType.Percentage for oscillators, use a PeakTroughReversalType.Point instead.
0
Best Answer
- ago
#5
QUOTE:
The problem here is both percentage and negative numbers. A percentage greater than 100 breaks down the calculation once the value turns negative.

There are two unrelated problems. The first problem is the negative numbers as described in Reply# 4. Thank you for that sample calculation. That's the first time I've seen that calculation described. I solved that with the TimeSeries.GetLowest(...) method on the PeakTroughCalculator call, see code sample.

The second problem is that the PeakTroughCalculator bases its decision on the first bar that turns direction. This is an advantage for quick reaction time (minimizing lag), but a disadvantage when looking for a trend over many bars. The solution is to preprocess the time series with an adaptive, low-lag smoother. Fortunately, John Ehlers' DSMA(...) smoother met this tricky challenge.

It seems the DSMA(KVO(...)) peak-trough plot identifies swing points correctly most of the time. I'll have to study the swing points it gets wrong in more detail before I can add more indicators. I greatly appreciate all the help. Any suggests are welcome.



CODE:
      public override void Initialize(BarHistory bars)       {          kvo = new KVO(bars,34,55);          PlotIndicator(kvo);          kvoDsma = new DSMA(kvo, 20);          PlotIndicator(kvoDsma, paneTag: "DSMA");          //zKvo = new ZScore(kvo,55);          //PlotIndicator(zKvo, plotStyle: PlotStyle.Line);          //kvoVel = new Momentum(kvo, 1);          //PlotIndicator(kvoVel);          PeakTroughCalculator kvoPeakTroughs = new PeakTroughCalculator(kvo-kvo.GetLowest(bars.Count-1,bars.Count-1), 30, PeakTroughReversalType.Percent);          foreach (PeakTrough peakTrough in kvoPeakTroughs.PeakTroughs)          {             if (peakTrough.Type == PeakTroughType.Peak) //peaks are orange                SetBackgroundColor(bars, peakTrough.PeakTroughIndex,WLColor.Orange, kvo.PaneTag);             else                SetBackgroundColor(bars, peakTrough.PeakTroughIndex,WLColor.LightGreen, kvo.PaneTag);                }          PeakTroughCalculator kvoDsmaPeakTroughs = new PeakTroughCalculator(kvoDsma-kvoDsma.GetLowest(bars.Count-1,bars.Count-1), 4, PeakTroughReversalType.Percent);          foreach (PeakTrough peakTrough in kvoDsmaPeakTroughs.PeakTroughs)          {             if (peakTrough.Type == PeakTroughType.Peak) //peaks are orange                SetBackgroundColor(bars, peakTrough.PeakTroughIndex,WLColor.Orange, "DSMA");             else                SetBackgroundColor(bars, peakTrough.PeakTroughIndex,WLColor.LightGreen, "DSMA");                }       }       public override void Execute(BarHistory bars, int idx) { }       IndicatorBase kvo, zKvo, kvoVel, kvoDsma;
0
Cone8
 ( 23.86% )
- ago
#6
QUOTE:
PeakTroughCalculator bases its decision on the first bar that turns direction
What decision?

It's based on the highest (peak) or lowest (trough) point reached.
0
- ago
#7
I guess I don't fully understand its calculation. I wish it was detailed in a more explicit way over time. Currently, it remains a mystery. Really it should be documented in detail in the Help manual. It does now appear that time is somehow involved and there can be a delay of 2 to 11 bars.

UPDATE: The main problem with the PeakTroughCalculator is that there's a long delay before it knowledges a peak. That's not such a problem with the Buy opportunity (which hesitates somewhat), but it's a problem with the Sell signal because price can fall very rapidly. Timing on the Sell operation is everything.

I wish I could pass my own peak detection routine into the calculator. I would do it using first and second derivatives, although they have their down side with noisy data.
0
Glitch8
 ( 13.87% )
- ago
#8
The peak/trough by nature cannot be identified until the price makes its move in the opposite direction. And that can cause a few bars detection delay. The PTC provides properties to return the actual peak/trough index as well as the index on which it was detected.
1
- ago
#9
QUOTE:
The peak/trough by nature cannot be identified until the price makes its move in the opposite direction.

Understood. The problem is that it takes too long to acknowledge that a peak has been detected to make it usable for swing trading exits. Now it's possible the optimizer messed up the reversal amount on the PeakTroughCalculator in favor of a competing robust statistical method for finding signal thresholds. I'm looking into that now. (I guess one should never optimize two competing methods together.)

But the delay the PeakTroughCalculator introduces makes it hard to use for exits in swing strategies since timing there is everything.

The derivative approach for finding peaks (and troughs) that you learn in first year calculus is much faster (no delay), but you would need to smooth its input with a low-lag filter (such as DSMA) first. There's no perfect way. But that's why one should be able to pass in their own peak-finding algorithm.
0
Cone8
 ( 23.86% )
- ago
#10
Use a smaller reversal value in concert with a overbought/sold oscillator to predict where your larger peaktrough might develop.

You'll get "false alarms" w.r.t. larger peaktroughs, but gosh, you can't know where a 25% peak is for sure until price moves 25% the other way. 🤷‍♂️
2

Reply

Bookmark

Sort