I would like to see an indicator that indicates yes or no.
Ex. If RSI falls under 40 it stays 1 until it crosses 80 and then it becomes 1.
Bollingerband %B added
Ex. If RSI falls under 40 it stays 1 until it crosses 80 and then it becomes 1.
Bollingerband %B added
Rename
You can accomplish this binary wave with programming. Alternatively, use a Multi-Condition Group together with conditions like 'Within the Past N Bars'.
Here's a template of the custom indicator for your own nurturing:
CODE:
using WealthLab.Core; using System; using System.Drawing; using WealthLab.Indicators; namespace WealthLab.MyIndicators { public class BinaryWave : IndicatorBase { public BinaryWave() : base() { } public BinaryWave(TimeSeries source, int crossunder, int crossover) : base() { Parameters[0].Value = source; Parameters[1].Value = crossunder; Parameters[2].Value = crossover; Populate(); } public static BinaryWave Series(TimeSeries source, int crossunder, int crossover) => new BinaryWave(source, crossunder, crossover); public override string Name => "Binary Wave"; public override string Abbreviation => "BinaryWave"; public override string HelpDescription => "If RSI falls under 40 it turns -1 until it crosses 80 when it becomes 1."; public override string PaneTag => "bwPane"; public override WLColor DefaultColor => WLColor.Navy; public override void Populate() { TimeSeries source = Parameters[0].AsTimeSeries; var rsi = RSI.Series(source, 20); Int32 xu = Parameters[1].AsInt; Int32 xo = Parameters[2].AsInt; DateTimes = source.DateTimes; if (source.Count < 20) { return; } for (int bar = 20; bar < source.Count; bar++) { if (rsi.CrossesUnder(xu, bar)) Values[bar] = -1; else if (rsi.CrossesOver(xo, bar)) Values[bar] = 1; // else // Values[bar] = 0; } } protected override void GenerateParameters() { AddParameter("Source", ParameterType.TimeSeries, PriceComponent.Close); AddParameter("Crossunder", ParameterType.Int32, 40); AddParameter("Crossover", ParameterType.Int32, 80); } } }
Thank you very much.
I still stays complicated for a non programmer like me.
To copy/paste the code to the Code tab can't be more simple. 🤷♂️
Anyway, this revision should retain the value in between the events - that was an issue with code in Post #1:
Anyway, this revision should retain the value in between the events - that was an issue with code in Post #1:
CODE:
using WealthLab.Core; using System; using System.Drawing; using WealthLab.Indicators; namespace WealthLab.MyIndicators { public class BinaryWave : IndicatorBase { public BinaryWave() : base() { } public BinaryWave(TimeSeries source, int rsiPeriod, int crossUnder, int crossOver) : base() { Parameters[0].Value = source; Parameters[1].Value = rsiPeriod; Parameters[2].Value = crossUnder; Parameters[3].Value = crossOver; Populate(); } public static BinaryWave Series(TimeSeries source, int rsiPeriod, int crossUnder, int crossOver) => new BinaryWave(source, rsiPeriod, crossUnder, crossOver); public override string Name => "Binary Wave"; public override string Abbreviation => "BinaryWave"; public override string HelpDescription => "If RSI falls under 40 it turns -1 until it crosses 80 when it becomes 1."; public override string PaneTag => "bwPane"; public override WLColor DefaultColor => WLColor.Navy; public override void Populate() { TimeSeries source = Parameters[0].AsTimeSeries; int rsiPeriod = Parameters[1].AsInt; var rsi = RSI.Series(source, rsiPeriod); Int32 xu = Parameters[2].AsInt; Int32 xo = Parameters[3].AsInt; DateTimes = source.DateTimes; if (source.Count < rsiPeriod) { return; } for (int bar = rsiPeriod; bar < source.Count; bar++) { if (rsi.CrossesUnder(xu, bar)) Values[bar] = -1; else if (rsi.CrossesOver(xo, bar)) Values[bar] = 1; else if (bar > rsiPeriod) Values[bar] = Values[bar - 1]; } } protected override void GenerateParameters() { AddParameter("Source", ParameterType.TimeSeries, PriceComponent.Close); AddParameter("RSI Period", ParameterType.Int32, 7); AddParameter("CrossUnder", ParameterType.Int32, 40); AddParameter("CrossOver", ParameterType.Int32, 80); } } }
Henk,
here's how to do it. You just need to put enough to get to the next page.
1. Then replace the code with Eugene's code.
2. Hit Compile, and,
3. Save to My Indicators folder.
here's how to do it. You just need to put enough to get to the next page.
1. Then replace the code with Eugene's code.
2. Hit Compile, and,
3. Save to My Indicators folder.
Great. Thank you!
Should it be added " User must be in Admin Mode" to access "my indicators"?
Looks like you got it though @Henk
Looks like you got it though @Henk
QUOTE:
Should it be added " User must be in Admin Mode" to access "my indicators"?
You're right but let's assume that since that's in the Help, the user has read it.
Looking good!
Correct i have read it in the help function.
Now i woud like to create the same binarywave for BB%b but i got an error.
i repLaced RSI by BollingerPctB in Eugene's code.
i repLaced RSI by BollingerPctB in Eugene's code.
CODE:
using WealthLab.Core; using System; using System.Drawing; using WealthLab.Indicators; namespace WealthLab.MyIndicators { public class BinaryWaveBBPctB : IndicatorBase { public BinaryWaveBBPctB() : base() { } public BinaryWaveBBPctB(TimeSeries source, int BollingerPctBPeriod, int crossUnder, int crossOver) : base() { Parameters[0].Value = source; Parameters[1].Value = BollingerPctBPeriod; Parameters[2].Value = crossUnder; Parameters[3].Value = crossOver; Populate(); } public static BinaryWaveBBPctB Series(TimeSeries source, int BollingerPctBPeriod, int crossUnder, int crossOver) => new BinaryWaveBBPctB(source, BollingerPctBPeriod, crossUnder, crossOver); public override string Name => "BinaryWaveBBPctB"; public override string Abbreviation => "BinaryWaveBBPctB"; public override string HelpDescription => "If BollingerPctB falls under 0 it turns -1 until it crosses 1 when it becomes 1."; public override string PaneTag => "bwBBPctBPane"; public override WLColor DefaultColor => WLColor.Navy; public override void Populate() { TimeSeries source = Parameters[0].AsTimeSeries; int BollingerPctBPeriod = Parameters[1].AsInt; var BollingerPctB = BollingerPctB.Series(source, BollingerPctBPeriod); Int32 xu = Parameters[2].AsInt; Int32 xo = Parameters[3].AsInt; DateTimes = source.DateTimes; if (source.Count < BollingerPctBPeriod) { return; } for (int bar = BollingerPctBPeriod; bar < source.Count; bar++) { if (BollingerPctB.CrossesUnder(xu, bar)) Values[bar] = 0; else if (BollingerPctB.CrossesOver(xo, bar)) Values[bar] = 1; else if (bar > BollingerPctBPeriod) Values[bar] = Values[bar - 1]; } } protected override void GenerateParameters() { AddParameter("Source", ParameterType.TimeSeries, PriceComponent.Close); AddParameter("BollingerPctBPeriod", ParameterType.Int32, 20); AddParameter("CrossUnder", ParameterType.Int32, 0); AddParameter("CrossOver", ParameterType.Int32, 1); } } }
Henk - at the top of the code you need to add a using statement:
using WealthLab.TASC;
using WealthLab.TASC;
For the people who are interested in latch BBpctB, this should be the correct code.
CODE:
using WealthLab.Core; using System; using System.Drawing; using WealthLab.Indicators; using WealthLab.TASC; namespace WealthLab.MyIndicators { public class BinaryWaveBBPctB : IndicatorBase { public BinaryWaveBBPctB() : base() { } public BinaryWaveBBPctB(TimeSeries source, int BollingerPctBPeriod, int crossUnder, int crossOver) : base() { Parameters[0].Value = source; Parameters[1].Value = BollingerPctBPeriod; Parameters[2].Value = crossUnder; Parameters[3].Value = crossOver; Populate(); } public static BinaryWaveBBPctB Series(TimeSeries source, int BollingerPctBPeriod, int crossUnder, int crossOver) => new BinaryWaveBBPctB(source, BollingerPctBPeriod, crossUnder, crossOver); public override string Name => "BinaryWaveBBPctB"; public override string Abbreviation => "BinaryWaveBBPctB"; public override string HelpDescription => "If BollingerPctB falls under 0 it turns 0 until it crosses 100 when it becomes 1."; public override string PaneTag => "bwBBPctBPane"; public override WLColor DefaultColor => WLColor.Navy; public override void Populate() { TimeSeries source = Parameters[0].AsTimeSeries; int BollingerPctBPeriod = Parameters[1].AsInt; var bollingerPctB = BollingerPctB.Series(source, BollingerPctBPeriod); Int32 xu = Parameters[2].AsInt; Int32 xo = Parameters[3].AsInt; DateTimes = source.DateTimes; if (source.Count < BollingerPctBPeriod) { return; } for (int bar = BollingerPctBPeriod; bar < source.Count; bar++) { if (bollingerPctB.CrossesUnder(xu, bar)) Values[bar] = 0; else if (bollingerPctB.CrossesOver(xo, bar)) Values[bar] = 100; else if (bar > BollingerPctBPeriod) Values[bar] = Values[bar - 1]; } } protected override void GenerateParameters() { AddParameter("Source", ParameterType.TimeSeries, PriceComponent.Close); AddParameter("BollingerPctBPeriod", ParameterType.Int32, 20); AddParameter("CrossUnder", ParameterType.Int32, 0); AddParameter("CrossOver", ParameterType.Int32, 100); } } }
You should be able to use IndOnInd to "latch" any indicator you want without creating a new customer indicator.
@Cone, it's unlikely since topic starter requires some extra logic that goes beyond IndOnInd's capability, such as:
1) to make values sticky past some event
2) assign a custom value to the indicator
1) to make values sticky past some event
2) assign a custom value to the indicator
You're right. The problem is that BinaryWave wasn't designed to do that because it hard-coded the source indicator.
It would have been better to create a indicator that took any TimeSeries and returned 1 and 0 (by default) if a source indicator crosses above or below some other parameter values.
It would have been better to create a indicator that took any TimeSeries and returned 1 and 0 (by default) if a source indicator crosses above or below some other parameter values.
Agreed. I'm onto it.
UPDATE: CrossoverIndValue added to upcoming B81.
UPDATE: CrossoverIndValue added to upcoming B81.
Your Response
Post
Edit Post
Login is required