- ago
Why does this code not work?
CODE:
using WealthLab.Backtest; using System; using WealthLab.Core; using WealthLab.Data; using WealthLab.Indicators; using System.Collections.Generic; using WealthLab.AdvancedSmoothers; using WLUtility.Indicators; namespace WealthScript1 { 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) {          StartIndex = 100;          TimeSeries smoothHigh = TEMA.Series(bars.High, 24);          TimeSeries smoothLow = TEMA.Series(bars.Low, 24);          TimeSeries vhf = VerticalHorizontalFilter.Series(smoothHigh, smoothLow, 10);          PlotTimeSeries(vhf, "VHF", "VHF", WLColor.Blue, PlotStyle.Line);       } //execute the strategy rules here, this is executed once for each bar in the backtest history public override void Execute(BarHistory bars, int idx) { if (!HasOpenPosition(bars, PositionType.Long)) { //code your buy conditions here } else { //code your sell conditions here } } //declare private variables below } }
0
88
5 Replies

Reply

Bookmark

Sort
- ago
#1
Because you're using WLUtility.Indicators, I guess you were using the VHF indicator that I published in another thread. But, WealthLab build 139 includes the VHF indicator. You should probably just get rid of the one I published and use the VHF indicator from WealthLab build 139.
0
- ago
#2
@Glitch - looks like the VHF indicator you published in Build 139 is in the WLUtility.Indicators namespace which is the namespace I used when publishing the VHF indicator (in another thread). You may have meant to put VHF in the WealthLab.Indicators namespace.
0
- ago
#3
There is something more basic wrong with the instantiation of this indicator.
CODE:
using WealthLab.Backtest; using System; using WealthLab.Core; using WealthLab.Data; using WealthLab.Indicators; using System.Collections.Generic; using WealthLab.AdvancedSmoothers; using WLUtility.Indicators; namespace WealthScript1 {    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)       {          StartIndex = 100;          TimeSeries smoothHigh = EMA.Series(bars.High, 10);          TimeSeries smoothLow = EMA.Series(bars.Low, 10);          TimeSeries vhf = VerticalHorizontalFilter.Series(smoothHigh, smoothLow, 10);          PlotTimeSeries(vhf, "VHF", "VHF", WLColor.Blue, PlotStyle.Line);       }       //execute the strategy rules here, this is executed once for each bar in the backtest history       public override void Execute(BarHistory bars, int idx)       {          if (!HasOpenPosition(bars, PositionType.Long))          {             //code your buy conditions here          }          else          {             //code your sell conditions here          }       }       //declare private variables below    } }

Results

The VHF should be between 0 and 1.0, correct?
0
ww58
- ago
#4
The code
CODE:
new VerticalHorizontalFilter(bars.Close,bars.Close,10);
works as intended, between 0 and 1
0
- ago
#5
As ww5 indicated, if you use the closing price then the range is 0 to 1. However, the code I published here https://www.wealth-lab.com/Discussion/VHF-Indicator-Can-it-be-added-12722 uses the high series as the summing of the absolute changes over period n. Hence, that is why you are seeing values greater than 1. I wrote an updated version, VHF2, that still uses two time series, but it averages the two series for summing the absolute changes over the given period.
CODE:
using System; using WealthLab.Core; namespace WealthLab.Indicators; /// <summary> /// Vertical Horizontal Filter 2 (VHF2) measures trend strength by evaluating /// This implementation has TimeSeries inputs for each of the highest and lowest price calculations. /// The sum of absolute changes is based on the average of the two provided series. /// Hence, using closing prices for both high and low series replicates the classic VHF behavior. /// </summary> public sealed class VerticalHorizontalFilter2 : IndicatorBase { private const int DefaultPeriod = 14; public VerticalHorizontalFilter2() { // for WL8 - do not remove! } public VerticalHorizontalFilter2(BarHistory bars, int period = DefaultPeriod) : this(bars.Close, bars.Close, period) { } public VerticalHorizontalFilter2(TimeSeries highSeries, TimeSeries lowSeries, int period = DefaultPeriod) { Parameters[0].Value = highSeries; Parameters[1].Value = lowSeries; Parameters[2].Value = period; Populate(); } public override string Name => "Vertical Horizontal Filter 2"; public override string Abbreviation => "VHF2"; public override string HelpDescription => "Vertical Horizontal Filter 2 (VHF2) measures trend strength using custom high and low series. The summing of absolute changes is based on the average of the two series."; public override string PaneTag => "VHF2"; public override bool IsSmoother => false; public override bool IsCalculationLengthy => false; public override bool PeekAheadFlag => false; public override PlotStyle DefaultPlotStyle => PlotStyle.Line; public override WLColor DefaultColor => WLColor.Orange; public override void Populate() { var highSeries = Parameters[0].AsTimeSeries; var lowSeries = Parameters[1].AsTimeSeries; var period = Parameters[2].AsInt; DateTimes = highSeries.DateTimes; if (period <= 0 || highSeries.Count == 0 || lowSeries.Count == 0) { return; } var highest = new Highest(highSeries, period); var lowest = new Lowest(lowSeries, period); // Use the average of the two series for the sum of absolute changes. // This fits with the classic VHF which uses the closing prices for the sum of absolute changes. var sumSeries = (highSeries + lowSeries) / 2.0; for (var i = 0; i < period; i++) { Values[i] = double.NaN; } var sumChangeAbs = 0.0; // Sum the first window for (var i = 1; i < period; i++) { sumChangeAbs += Math.Abs(sumSeries[i] - sumSeries[i - 1]); } for (var idx = period; idx < highSeries.Count; idx++) { sumChangeAbs += Math.Abs(sumSeries[idx] - sumSeries[idx - 1]); sumChangeAbs -= Math.Abs(sumSeries[idx - period + 1] - sumSeries[idx - period]); Values[idx] = sumChangeAbs == 0 ? 0 : (highest[idx] - lowest[idx]) / sumChangeAbs; } } protected override void GenerateParameters() { AddParameter("High Series", ParameterType.TimeSeries, PriceComponent.Close); AddParameter("Low Series", ParameterType.TimeSeries, PriceComponent.Close); AddParameter("Period", ParameterType.Int32, DefaultPeriod); } public static VerticalHorizontalFilter2 Series(TimeSeries highSeries, TimeSeries lowSeries, int period = DefaultPeriod) { var key = CacheKey("VerticalHorizontalFilter2", highSeries, lowSeries, period); if (highSeries.Cache.TryGetValue(key, out var obj)) { return (VerticalHorizontalFilter2) obj; } var indicator = new VerticalHorizontalFilter2(highSeries, lowSeries, period); highSeries.Cache[key] = indicator; return indicator; } // Convenience overload for BarHistory public static VerticalHorizontalFilter2 Series(BarHistory bars, int period = DefaultPeriod) => Series(bars.Close, bars.Close, period); }
0

Reply

Bookmark

Sort