- ago
I'm trying to calculate the slope of a trendline (log scale) in annualized % terms.

Test code:
CODE:
using WealthLab.Backtest; using System; using WealthLab.Core; using WealthLab.Indicators; using System.Collections.Generic; namespace WealthScript8 {    public class MyStrategy : UserStrategyBase    {       //create indicators and other objects here, this is executed prior to the main trading loop       public override void Initialize(BarHistory bars)       {          cds = new ChartDisplaySettings();          cds.LogScale = true;          SetChartDrawingOptions(cds);          pt = new PeakTroughCalculator(bars, 20.00, PeakTroughReversalType.Percent); // 20% reversals          StartIndex = 53;       }       //execute the strategy rules here, this is executed once for each bar in the backtest history       public override void Execute(BarHistory bars, int idx)       {          double slp = 0;          double apr = 0;          TrendLine tl = pt.GetLowerTrendLine(idx, 2, true);          if (tl != null)             DrawLine(tl.Index1, tl.Value1, idx, tl.ExtendTo(idx, true), WLColor.Blue, 2, LineStyle.Solid, "Price", false, false);          // Calculate trendline slope (annualized, %) - Method 1          if (tl != null)          {             slp = tl.Slope(true);             apr = (Math.Exp(slp) - 1) * 100;             WriteToDebugLog(idx + "\t" + "Method 1" + "\t" + apr.ToString("#0.##%"));          }          // Calculate trendline slope (annualized, %) - Method 2          if (tl != null)          {             int lastTr = tl.Index1;             int current = tl.Index2;             DateTime dt1 = bars.DateTimes[lastTr];             DateTime dt2 = bars.DateTimes[current];             TimeSpan ts = dt2 - dt1;             double x = tl.Value2 / tl.Value1;             apr = Math.Pow(x, 365 / ts.TotalDays) - 1;             WriteToDebugLog(idx + "\t" + "Method 2" + "\t" + apr.ToString("#0.##%"));          }       }       //declare private variables below       private ChartDisplaySettings cds;       private PeakTroughCalculator pt;    } }


Using QQQ/WEEKLY bars/10 years.
The 2 methods give different values, check the debug window.

Qs:
1. Which is the correct method to use (and what's wrong in the other method)?
2. Are both methods wrong? If so, which is the best way to calculate?
0
344
Solved
13 Replies

Reply

Bookmark

Sort
Cone8
 ( 24.99% )
- ago
#1
Method 2 is correct.

I don't know how you could use slope alone to get APR. Slope only defines the line, not distance (time).
0
Best Answer
- ago
#2
Thanks.

Given that this is a Weekly chart AND that traders typically deal with trading bars rather than calendar days is the following line in method #2 still correct
CODE:
apr = Math.Pow(x, 365 / ts.TotalDays) - 1;

?
0
Cone8
 ( 24.99% )
- ago
#3
The scale/interval is irrelevant. The TimeSpan.TotalDays are the total calendar days between 2 dates.
0
- ago
#4
Got it.
********************************************************************************

Lastly... a suggestion:
I like TrendLineEnvelope. However, take a look at the weekly chart of AAPL below


This trendline based on troughs lasted > 2.5 years (5/13/16 - 1/4/19) based on 2 troughs that occurred a short interval apart. Perhaps an overload can be added allowing one to specify the minimum interval between troughs? Rest of the logic can remain the same. Ditto for GetLower(Upper)Trendline.
0
Cone8
 ( 24.99% )
- ago
#5
Use "Calendar Days Lookback":
Discards peaks/troughs that are "too old" as of the current bar. This is an optimization feature that can help speed up a trendline search especially for intraday simulations that use Trend Line Break Advanced.

It's the 1500 parameter in this call -
QUOTE:
TrendLine tl = pt.TrendlineEnvelope(bars, index, PeakTroughType.Peak, 3, true, 2.00, false, 1500);


Edit ---
On my first reading, I didn't get the point about the trendline being based on 2 close troughs, but now I see what you mean. However, that trendline seems insignificant only because of what AAPL did later. If prices had moved down 10 or 20 bars after that most-recent trough, we wouldn't be talking about this.

TrendlineEnvelope gives you the trendline whose projection is closest to the current price. You can evaluate in your own code if you want to use the trendline based on its proximity or the the distance between the PeakTroughs. In the chart above, the only reason you don't see closer trendlines is because they've all been broken.
0
- ago
#6
I drew a manual trendline for the same period:



As you can see this one is better as it hugs the prices closer AND touches 4 points (including 2 small incursions).
All I'm saying is the selection logic for troughs (and possible peaks too) can be tweaked a bit.
0
Cone8
 ( 24.99% )
- ago
#7
TrendlineEnvelope gives you the trendline whose projection is closest to the current price. ... and hasn't been broken.

What I'm saying is that if that trendline were not already broken (note the subjunctive tense), TrendlineEnvelope would have returned that line. 🤷‍♂️
0
Cone8
 ( 24.99% )
- ago
#8
Proof: This Strategy -



Found these trendline crossing trades - (the trendline on the left is nearly precisely what you drew)



Let me stress that TrendlineEnvelope will find ALL active trendlines (not crossed) and return the one that is closest to the current price at "index".
0
- ago
#9
(Most experienced chartists will tell you to use Log scale for drawing trendlines, not Linear as you used in your example. Putting that aside...)

Note that your trendline started at a higher trough point than the one I illustrated - likely a result of the parameters you used; of course, as variables change so does the output. Also, as new data comes in new trendlines will be considered, some will be discarded and eventually a new one will supersede the old one. And a trendline needs to be broken by > specified amount (another variable!) to be considered broken o/w its just an incursion.
The chart below shows how the trendlines on AAPL *might* have evolved over time (for simplicity I used only 1 trough point):



Let me summarize what I'm trying to say in one sentence:
While TrendlineEnvelope is good, it can be made better.
0
Glitch8
 ( 10.94% )
- ago
#10
Are you saying your Trendline in Post #6 should be considered valid because it didn't really break, just had an "incursion?"

And yes, everything can be made better. Fortunately this platform is open so you can even code your own, better, version of a Trendline engine. Let us know what you come up with, we love seeing new and positive contributions from the community!
1
- ago
#11
The trendlines might have evolved over time as in Post #9. Each time they would have been replaced by a new trendline as a new trough point occurred, culminating in the one shown in Post #6 which is the only one that got ultimately broken. And when the last trendline was selected (among other likely candidates) only then the previous breaches would've been recognized as incursions (depending on the setting, of course), not before.
----------------------------------

We are going off-track here. The issue I discovered, by serendipity I might add, was that TrendLineEnvelope would consider even those trendlines based on troughs situated close together. If an option can be provided for the user to specify minimum bars between troughs (peaks) that would be great. The default value can be set to whatever it is currently (if any) so that in case the user doesn't specify a value the logic will simply run as it does currently.
0
Cone8
 ( 24.99% )
- ago
#12
QUOTE:
(Most experienced chartists will tell you to use Log scale for drawing trendlines, not Linear as you used in your example. Putting that aside...)

You don't have to put it aside. Linear/Log is an option for all WealthLab Trendlines and Trendline projections.
0
Cone8
 ( 24.99% )
- ago
#13
I was looking at the code and found that TrendlineEnvelope returned the unbroken Trendline that had most negative slope for peaks, most positive slope for troughs only when the number of points was set to 2. In this case, you "usually" get the line whose extension is closest to the current price.

In the case you search for lines with 3 or more points, TrendlineEnvelope returns the unbroken Trendline with the least deviation - in other words, the line whose points line up the best.

This isn't going to change, but what we'll do for Build 27 is expose the whole list with a new "plural" call to TrendlineEnvelopes. That way you can search the list to pick or discard the Trendline you want to use.

QUOTE:
public List<TrendLine> TrendlineEnvelopes(BarHistory bars, int idx, PeakTroughType ptType, int points, bool useDescendingPeakTroughs, double allowableIncursionPct = 3, bool useLog = false, int maxLookbackDays = 1000)
0

Reply

Bookmark

Sort