Can someone please explain to me how to create a basic strategy using the Keltner Channels indicator? I'm new to C# and I didn't find documentation for programming a strategy.
Rename
A good place to start is using the Building Blocks. Then, if you're really interested in the code, you can hit the button for "Open as C# Coded Strategy", where you can review and edit the code yourself. The block coded output is verbose, but it's correct and gives you a place to start.
For more WL orientation and using blocks, see the WealthLab University playlist:
https://www.youtube.com/playlist?list=PLcYQ6caO-N5yiSXsCqbDoAHDIdxTgFOEQ
For more WL orientation and using blocks, see the WealthLab University playlist:
https://www.youtube.com/playlist?list=PLcYQ6caO-N5yiSXsCqbDoAHDIdxTgFOEQ
I attempted to convert the WL6 Keltner band strategy to WL8. The code is given below. But there's a problem. When the period is set to 20, the averagePrice line (the blue line) is center perfectly within the Keltner bands as expected. But if that period is changed (The illustration uses period=5), the bands are no longer enveloping the blue averagePrice line. It's like the KeltnerUpper and KeltnerLower band indicators simply ignore their period parameter. Perhaps someone can explain this.
![](/api/discussion/download/image/8022-Kelter-bands-gif)
The converted WL8 code is below. Feel free to make any corrections.
The converted WL8 code is below. Feel free to make any corrections.
CODE:UPDATE: The period for both the averagePrice and Keltner bands is now the same in the above code.
using WealthLab.Backtest; using WealthLab.Core; using WealthLab.Indicators; //using Superticker.Components; /* WLUtil.HideVolume here */ namespace WealthScript3 { //conversion from WL6 www2.wealth-lab.com/WL5Wiki/KeltnerLower.ashx public class KeltnerBands : UserStrategyBase { Parameter period, atrFactor; TimeSeries averagePriceSmoothed; IndicatorBase keltnerUp, keltnerLow; public KeltnerBands() { period = AddParameter("Keltner period", ParameterType.Int32, 14, 5, 35); atrFactor = AddParameter("ATR factor", ParameterType.Double, 2.0, 1.0, 3.0, 0.2); //SetChartDrawingOptions(WLUtil.HideVolume()); } public override void Initialize(BarHistory bars) { const bool useAtrBands = false; //change to "true" to get ATR volatility bands keltnerUp = new KeltnerUpper(bars,period.AsInt,atrFactor.AsDouble,10,useAtrBands); keltnerLow = new KeltnerLower(bars,period.AsInt,atrFactor.AsDouble,10,useAtrBands); averagePriceSmoothed = SMA.Series(bars.AveragePriceHLC,period.AsInt); PlotIndicatorCloud(keltnerUp, keltnerLow); PlotTimeSeries(averagePriceSmoothed, "Average price", "Price"); } public override void Execute(BarHistory bars, int idx) { if (HasOpenPosition(bars, PositionType.Long)) { //sell Long conditions below if (bars.Close.CrossesUnder(keltnerLow, idx)) { PlaceTrade(bars, TransactionType.Sell, OrderType.Market, 0.0, "Sell Long"); PlaceTrade(bars, TransactionType.Short, OrderType.Market, 0.0, "Buy Short"); } } else if (HasOpenPosition(bars, PositionType.Short)) { //sell Short conditions below if (bars.Close.CrossesOver(keltnerUp, idx)) { PlaceTrade(bars, TransactionType.Cover, OrderType.Market, 0.0, "Sell Short"); PlaceTrade(bars, TransactionType.Buy, OrderType.Market, 0.0, "Buy Long"); } } else { //buy conditions below if (bars.Close.CrossesOver(keltnerUp, idx)) PlaceTrade(bars, TransactionType.Buy, OrderType.Market, 0.0, "Buy Long"); else if (bars.Close.CrossesUnder(keltnerLow, idx)) PlaceTrade(bars, TransactionType.Short, OrderType.Market, 0.0, "Buy Short"); } } } }
It's clear from your screenshot (and the WL8 source code to me) that KetnerBands do interpret their period parameter correctly. Your average price, however, is not as you divide it by two and arrive at a different period:
CODE:
averagePriceSmoothed = SMA.Series(bars.AveragePriceHLC,period.AsInt/2);
If you take the divide by 2 out, it gets even worse.
The bands should always envelope the the bars and the average. Clearly with a period=5, the bands are not enveloping the bars. Some is seriously wrong if the bands don't envelop the bars.
Forget about the average line. Look at the bands in relationship to the bars. The bands are way outside of the bars for period=5--not right.
The bands should always envelope the the bars and the average. Clearly with a period=5, the bands are not enveloping the bars. Some is seriously wrong if the bands don't envelop the bars.
Forget about the average line. Look at the bands in relationship to the bars. The bands are way outside of the bars for period=5--not right.
I reran the Chart below with all three lines (averagePrice, KeltnerUpper, KeltnerLower) set to a period of 5. With this setting, the averagePrice should be exactly half way between the Keltner bands and it isn't. So there's some kind of problem. I'm testing this on WL8 Build 94 here.
I'm afraid this is a bug. When "Use ATR Bands" is unchecked, the indicator mistakenly takes the ATR period. Thanks for the heads-up, this is fixed for B95.
There's a way to plot the keltner channel without filling the channel with color?
CODE:
kUp = new KeltnerUpper(bars, 12, 2.00, 13, false); kLower = new KeltnerLower(bars, 12, 2.00, 13, false); PlotIndicator(kUp, new WLColor(0, 255, 0, 0)); PlotIndicator(kLower, new WLColor(0, 0, 255, 0));
Yes, that should work. You can just call out the color names to use. The link below gives the color names the .NET framework recognizes. https://www.w3schools.com/colors/colors_groups.asp
CODE:Better yet, you can reduce the opacity of the shading so it's more faded. The default opacity is 25 for PlotIndicatorCloud.
PlotIndicator(kUp, WLColor.Red); PlotIndicator(kLower, WLColor.Green); //PlotIndicator(kUp, new WLColor(0, 255, 0, 0)); //PlotIndicator(kLower, new WLColor(0, 0, 255, 0));
CODE:
PlotIndicatorCloud(keltnerUp, keltnerLow, opacity: 8);
It hasn't worked out that way yet:
CODE:
public override void Initialize(BarHistory bars) { kUp = new KeltnerUpper(bars, 10); kLower = new KeltnerLower(bars, 10); PlotIndicator(kUp, WLColor.Red); PlotIndicator(kLower, WLColor.Green); }
It didn't work that way, but I changed it to this one and it worked:
CODE:
kUp = new KeltnerUpper(bars, 10); kLower = new KeltnerLower(bars, 10); PlotIndicatorLine(kUp, WLColor.Red); PlotIndicatorLine(kLower, WLColor.Green);
KeltnerUpper and KeltnerLower are companion indicators. Their default plot style is Bands. Hence, if you don't tell PlotIndicator to use something other than Bands then it will show bands. If you want to use PlotIndicator then explicitly set the plot style:
CODE:
kUp = new KeltnerUpper(bars, 10); kLower = new KeltnerLower(bars, 10); PlotIndicator(kUp, WLColor.Red, PlotStyle.Line); PlotIndicator(kLower, WLColor.Green, PlotStyle.Line);
Your Response
Post
Edit Post
Login is required