- ago
I've created an indicator that tells me whether the fast average is above the slow average (e.g. EMA9 and EMA21) or the opposite. If it's above, this indicator of mine returns 1 and if it's the opposite, it returns -1.

Is it possible to create an indicator where I select the two indicators I'm comparing using a dropdown menu with the WL indicators?
0
222
Solved
7 Replies

Reply

Bookmark

Sort
Glitch8
 ( 6.16% )
- ago
#2
Sorry, this one slipped. Use GenerateIndicatorParameter in the GenerateParameters method. Here's the source for MathIndOpInd for reference.

CODE:
using WealthLab.Core; namespace WealthLab.Indicators { //perform a mathematical operation between two indicators public class MathIndOpInd : TransformerIndicatorBase { //constructors public MathIndOpInd() : base() { } public MathIndOpInd(BarHistory source, IndicatorBase ind, MathOperation op, IndicatorBase ind2, double multiplier = 1.0) : base(source, ind) { Parameters[2].Value = op; Parameter p = Parameters[3]; p.Value = ind2; p.IndicatorInstance = ind2; p.IndicatorAbbreviation = ind2.Abbreviation; p.IndicatorParameters = ind2.Parameters; Parameters[4].Value = multiplier; Populate(); } //Series method public static MathIndOpInd Series(BarHistory source, IndicatorBase ib, MathOperation op, IndicatorBase ind2, double multiplier = 1.0) { string key = CacheKey("MathIndOpInd", ib.Abbreviation, op, ind2.Abbreviation, multiplier); if (source.Cache.ContainsKey(key)) return (MathIndOpInd)source.Cache[key]; MathIndOpInd indOpInd = new MathIndOpInd(source, ib, op, ind2, multiplier); source.Cache[key] = indOpInd; return indOpInd; } //Name public override string Name => "Indicator/Indicator Operation"; //Abbreviation public override string Abbreviation => "MathIndOpInd"; //Help public override string HelpDescription => "Performs a mathematical operation on two other Indicators."; //default color public override WLColor DefaultColor => WLColor.CadetBlue; //help public override string HelpURL => "<a href="https://www.youtube.com/watch?v=5kOIk99fry8&t=10s" target="_blank">https://www.youtube.com/watch?v=5kOIk99fry8&t=10s</a>"; //Populate public override void Populate() { BarHistory source = Parameters[0].AsBarHistory; DateTimes = source.DateTimes; //get the two Indicators string indName = Parameters[1].IndicatorAbbreviation; ParameterList indParams = Parameters[1].IndicatorParameters; IndicatorBase ind = IndicatorFactory.Instance.CreateIndicator(indName, indParams, source); if (ind == null) return; indName = Parameters[3].IndicatorAbbreviation; indParams = Parameters[3].IndicatorParameters; IndicatorBase ind2 = IndicatorFactory.Instance.CreateIndicator(indName, indParams, source); if (ind2 == null) return; //get the operation, perform calculation double multiplier = 1.0; if (Parameters.Count > 4) multiplier = Parameters[4].AsDouble; MathOperation op = (MathOperation)Enum.Parse(typeof(MathOperation), Parameters[2].AsString); TimeSeries ts2 = ind2; if (multiplier != 1.0) ts2 *= multiplier; TimeSeries result = op.Perform(ind, ts2); AssumeValuesOf(result); //set description Description = ind.Description + Parameters[2].AsMathOperation + ind2.Description; } //pane public override string PaneTag => Parameters[1].AsString + ";" + Parameters[2].AsString + ";" + Parameters[3].AsString; //create parameters protected override void GenerateParameters() { AddParameter("Source", ParameterType.BarHistory, null); AddIndicatorParameter("Indicator 1", "Close"); Parameter p = AddEnumParameter("Operation", MathOperation.Add); p.TypeName = "MathOperation"; AddIndicatorParameter("Indicator 2", "StdDev"); AddParameter("Multiplier", ParameterType.Double, 1.0); } } }
0
Best Answer
- ago
#3
QUOTE:
an indicator that tells me whether the fast average is above the slow average (e.g. EMA9 and EMA21) or the opposite.

The MACD indicator already does this. It's defaults are EMA12 and EMA26, MACD(source, 12, 26), but you can change that.

CODE:
using WealthLab.Backtest; using WealthLab.Core; using WealthLab.Indicators; namespace WealthScript3 { public class MyStrategy : UserStrategyBase { public override void Initialize(BarHistory bars) {          IndicatorBase macd = MACD.Series(bars.Close, 9, 21);          PlotIndicator(macd);          TimeSeries binaryIndicator = (macd > 0.0);          PlotTimeSeries(binaryIndicator, "MACD binary", "MACD pane", WLColor.Green, PlotStyle.Histogram);          }       public override void Execute(BarHistory bars, int idx) { } } }
1
- ago
#4
Nice, I will try.

Thank you both.
0
- ago
#5
QUOTE:
Is it possible to create an indicator where I select the two indicators I'm comparing using a dropdown menu with the WL indicators?

What you need to do is define two distinct "Indicator Sets", then you can use the Indicator Sets dropdown menu to select between them.

Go to the WL Help docs and search on "Indicator Sets" to learn more.

---
There are many variations of the MACD indicator discussed above. Go to the Indicators filter box and type "MACD" and you will see a whole bunch of them. There are numerous articles available discussing the MACD and MACD signal (called the MACDHistogram on WL). I would check out some of those articles.
0
- ago
#6
Well, I thought it was working, but it's only 50% working...

I wrote this code: (in fact, chatGPT)

CODE:
using System; using WealthLab.Core; using WealthLab.Indicators; namespace _GabrielEmilio.Indicators { public class DynamicIndicatorComparator : IndicatorBase { public DynamicIndicatorComparator() : base() { } public DynamicIndicatorComparator(BarHistory source, IndicatorBase ind1, IndicatorBase ind2) : base() { Parameters[0].Value = source; Parameters[1].Value = ind1; Parameters[2].Value = ind2; Populate(); } public static DynamicIndicatorComparator Series(BarHistory source, IndicatorBase ind1, IndicatorBase ind2) { return new DynamicIndicatorComparator(source, ind1, ind2); } public override string Name => "Dynamic Indicator Comparator"; public override string Abbreviation => "DynIndComp"; public override string HelpDescription => "Compares two selected indicators dynamically."; public override string PaneTag => "DynIndComp"; public override WLColor DefaultColor => WLColor.FromArgb(255, 125, 125, 255); public override PlotStyle DefaultPlotStyle => PlotStyle.Mountain; public override void Populate() { BarHistory source = Parameters[0].AsBarHistory; DateTimes = source.DateTimes; string ind1Name = Parameters[1].IndicatorAbbreviation; ParameterList ind1Params = Parameters[1].IndicatorParameters; IndicatorBase ind1 = IndicatorFactory.Instance.CreateIndicator(ind1Name, ind1Params, source); if (ind1 == null) return; string ind2Name = Parameters[2].IndicatorAbbreviation; ParameterList ind2Params = Parameters[2].IndicatorParameters; IndicatorBase ind2 = IndicatorFactory.Instance.CreateIndicator(ind2Name, ind2Params, source); if (ind2 == null) return; for (int n = 1; n < source.Count; n++) { if (ind1[n] > ind2[n]) Values[n] = 1; else if (ind1[n] < ind2[n]) Values[n] = -1; else Values[n] = 0; } } protected override void GenerateParameters() { AddParameter("Source", ParameterType.BarHistory, null); AddIndicatorParameter("Indicator 1", "Close"); AddIndicatorParameter("Indicator 2", "EMA"); } } }




On the chart, it works fine. The default values appear (in this case, Close and EMA(20). Then I change the EMA period to 200 and the chart reflects it.




However, when I'm executing the strategy, it doesn't change the value as I set the period in the building block, keeping the default value and executing only with the default value.

What could be causing it? Is it the syntax of the code?
0
- ago
#7
Resolved.

CODE:
using System; using WealthLab.Core; using WealthLab.Indicators; namespace _GabrielEmilio.Indicators { public class DynamicIndicatorComparator : IndicatorBase { public DynamicIndicatorComparator() : base() { } public DynamicIndicatorComparator(BarHistory source, IndicatorBase ind1, IndicatorBase ind2) : base() { Parameters[0].Value = source; Parameter p1 = Parameters[1]; p1.Value = ind1; p1.IndicatorInstance = ind1; p1.IndicatorAbbreviation = ind1.Abbreviation; p1.IndicatorParameters = ind1.Parameters; Parameter p2 = Parameters[2]; p2.Value = ind2; p2.IndicatorInstance = ind2; p2.IndicatorAbbreviation = ind2.Abbreviation; p2.IndicatorParameters = ind2.Parameters; Populate(); } public static DynamicIndicatorComparator Series(BarHistory source, IndicatorBase ind1, IndicatorBase ind2) { return new DynamicIndicatorComparator(source, ind1, ind2); } public override string Name => "Dynamic Indicator Comparator"; public override string Abbreviation => "DynIndComp"; public override string HelpDescription => "Compares two selected indicators dynamically."; public override string PaneTag => "DynIndComp"; public override WLColor DefaultColor => WLColor.Blue; public override PlotStyle DefaultPlotStyle => PlotStyle.HistogramTwoColor; public override void Populate() { BarHistory source = Parameters[0].AsBarHistory; DateTimes = source.DateTimes; string ind1Name = Parameters[1].IndicatorAbbreviation; ParameterList ind1Params = Parameters[1].IndicatorParameters; IndicatorBase ind1 = IndicatorFactory.Instance.CreateIndicator(ind1Name, ind1Params, source); if (ind1 == null) return; string ind2Name = Parameters[2].IndicatorAbbreviation; ParameterList ind2Params = Parameters[2].IndicatorParameters; IndicatorBase ind2 = IndicatorFactory.Instance.CreateIndicator(ind2Name, ind2Params, source); if (ind2 == null) return; for (int i = 0; i < source.Count; i++) { if (ind1[i] > ind2[i]) Values[i] = 1; else if (ind1[i] < ind2[i]) Values[i] = -1; else Values[i] = 0; } } protected override void GenerateParameters() { AddParameter("Source", ParameterType.BarHistory, null); AddIndicatorParameter("Indicator 1", "Close"); AddIndicatorParameter("Indicator 2", "EMA"); } } }
1

Reply

Bookmark

Sort