- ago
I am new to WL8 and not a experienced programmer.

Therefore I am having trouble translating my WL6.9 code to WL8 for an indicator, which measures the state of stocks in a dataset.
In WealthLab 6 I let this code run over a symbol and it showed me an average value of all stocks in the dataset in which the symbol was in. I have no idea how to implement this in WL8 neither the coding nor if there are other/better ways than the path i took in WL6.
Here is the WL6 code:

CODE:
public DataSeries marketconditionindex( Bars bars, int smavalue, IList<string> dataSetSymbols )       {          DataSeries mci = new DataSeries(bars, "MCI");          DataSeries contribs = new DataSeries(bars, "Contributing Symbol Count");          foreach(string symbol in dataSetSymbols)          {             SetContext(symbol, true);             DataSeries smaser = SMA.Series(Close, smavalue);             DataSeries rslevy = Close/smaser;             for (int bar = Bars.FirstActualBar + sma1.ValueInt + 1; bar < Bars.Count; bar ++)             {                contribs[bar]++;                mci[bar] = mci[bar] + rslevy[bar];             }             RestoreContext();          }          mci= mci/ contribs;          mci.Description = "Market condition index";          return aki;       }           protected override void Execute()       {                    DataSeries mci = marketconditionindex(Bars, sma1.ValueInt, DataSetSymbols); ...

0
828
Solved
12 Replies

Reply

Bookmark

Sort
- ago
#1
A better and proper way in WL8 would be to create a Composite Indicator for use in Index-Lab. But that has to be a full-fledged custom WL8 Extension.
1
- ago
#2
Something like this to expose the general idea (on-the-fly coding):

CODE:
namespace WealthLab.IndexLab { public class CompMCI : CompositeBase ... public override double CalculateCompositeValue(List<BarHistory> constituents, DateTime dt) { int smaPeriod = 20; double count = 0.0; TimeSeries mci = new TimeSeries(0); foreach(BarHistory bh in constituents) { int idx = GetCurrentIndex(bh); if (idx >= smaPeriod) { count++; double _sma = SMA.Value(idx, bh.Close, smaPeriod); double _rsl = bh.Close[idx] / _sma; mci[idx] += _rsl; } } mci[idx] /= count; if (count == 0) return Double.NaN; return mci[idx]; }
0
Cone8
 ( 4.98% )
- ago
#3
I think you can get it with Index-Lab, right?

0
- ago
#4
I'm confused. If ...
CODE:
public override double CalculateCompositeValue(List<BarHistory> constituents, DateTime dt)
... is returning a double, then shouldn't mci be declared as a double (instead of a TimeSeries) as well?
0
Glitch8
 ( 10.62% )
- ago
#5
Agree, the declaration of a TimeSeries here instead of a double seems unnecessary. I think Eugene just wrote out something quick and dirty.

In any event, as Robert showed, writing custom code to accomplish this isn't even required. Just use the IndexLab method he illustrated above.
1
- ago
#6
QUOTE:
Agree, the declaration of a TimeSeries here instead of a double seems unnecessary.
Well, I'm trying to decide if the summing should be done over a mci[DateTime] dictionary instead of a mci[idx] TimeSeries since the BarHistory's aren't aligned. But maybe it wouldn't make much difference either way since we are computing averages. It just looks confusing with the DateTime/bar misalignment.
0
Cone8
 ( 4.98% )
- ago
#7
Not sure what you're talking about, but IndexLab indicators "align" the data for composite calculations.
1
- ago
#8
Thanks for all of your answers. I tried to build it in building Blocks and pushed it from there in C#-Code, because i want to make the SMA length to be optimizable.
The Code, which was thrown out shows some errors. Also I cant see the SMA Indicator anywhere. Could you help me with the code please?

This was thrown out:
CODE:
using WealthLab.Backtest; using System; using WealthLab.Core; using WealthLab.Data; using WealthLab.Indicators; using System.Collections.Generic; using WealthLab.IndexLab; namespace WealthScript2 { public class MyStrategy : UserStrategyBase {     public MyStrategy() : base() { StartIndex = 0; } public override void Initialize(BarHistory bars) {          indicator = new CompInd(bars,"02 Country ETFs;Norgate Data",2000,new MathIndOpInd(bars,Close,MathOperation.Divide,Close,20),1.00));          PlotIndicator(indicator,new WLColor(0,0,0));          indicator2 = new CompInd(bars,"02 Country ETFs;Norgate Data",2000,new MathIndOpInd(bars,Close,MathOperation.Divide,Close,20),1.00)); } public override void Execute(BarHistory bars, int idx) {          int index = idx;          Position foundPosition0 = FindOpenPosition(0);          bool condition0;          if (foundPosition0 == null)          {             condition0 = false;             {                if (indicator.CrossesOver(0.00, index))                {                   condition0 = true;                }             }             if (condition0)             {                _transaction = PlaceTrade(bars, TransactionType.Buy, OrderType.Market, 0, 0, "Buy At Market (1)");             }          }          else          {             condition0 = false;             {                if (indicator2.CrossesUnder(0.00, index))                {                   condition0 = true;                }             }             if (condition0)             {                Backtester.CancelationCode = 136;                ClosePosition(foundPosition0, OrderType.Market, 0, "Sell At Market (1)");             }          } } public override void NewWFOInterval(BarHistory bars) {          indicator = new CompInd(bars,"02 Country ETFs;Norgate Data",2000,new MathIndOpInd(bars,Close,MathOperation.Divide,Close,20),1.00));          indicator2 = new CompInd(bars,"02 Country ETFs;Norgate Data",2000,new MathIndOpInd(bars,Close,MathOperation.Divide,Close,20),1.00)); }       private IndicatorBase indicator;       private IndicatorBase indicator2;       private Transaction _transaction; } }
0
- ago
#9
Unfortunately, it turns out that this strategy won't work for optimization/Blocks for the same reason why nested Transformer indicators aren't supported.
0
Cone8
 ( 4.98% )
- ago
#10
To be clear, nested Transformers are supported - they're just not supported in Building Blocks.

However, this indicator isn't nested. It's one Transformer operation - but it's in Index-Lab, which is the difference. It looks to me like you (ruediger78) divided by the Close and not the SMA. I'll check to make sure we don't have an error there...

... and you're right. The ouput is "MathOperation.Divide,Close,20)". That's a bug.
0
Cone8
 ( 4.98% )
- ago
#11
Below is the "corrected" and reduced code set up to optimize. Change the start, stop, and increment as desired.

The problem is that it doesn't work. The coded CompInd is returning all NaNs. We'll need to dig in and come back to you on this one.

CODE:
using WealthLab.Backtest; using System; using WealthLab.Core; using WealthLab.Data; using WealthLab.Indicators; using System.Collections.Generic; using WealthLab.IndexLab; namespace WealthScript12 {    public class Strategy10406 : UserStrategyBase    {       public Strategy10406() : base()       {          AddParameter("Period", ParameterType.Int32, 20, 5, 50, 5);       }              public override void Initialize(BarHistory bars)       {          indicator = new CompInd(bars,_dataset,2000,new MathIndOpInd(bars,new TimeSeriesIndicatorWrapper(bars.Close),MathOperation.Divide,new SMA(bars.Close,Parameters[0].AsInt),1.00));             PlotIndicator(indicator,new WLColor(0,0,0));          StartIndex = Parameters[0].AsInt;       }              public override void Execute(BarHistory bars, int idx)       {          int index = idx;          Position foundPosition0 = FindOpenPosition(0);          bool condition0;          if (foundPosition0 == null)          {             if (indicator.CrossesOver(0.00, index))             {                _transaction = PlaceTrade(bars, TransactionType.Buy, OrderType.Market, 0, 0, "Buy At Market (1)");             }          }          else          {             if (indicator.CrossesUnder(0.00, index))             {                Backtester.CancelationCode = 136;                ClosePosition(foundPosition0, OrderType.Market, 0, "Sell At Market (1)");             }          }              }              public override void NewWFOInterval(BarHistory bars)       {       indicator = new CompInd(bars,_dataset,2000,new MathIndOpInd(bars,new TimeSeriesIndicatorWrapper(bars.Close),MathOperation.Divide,new SMA(bars.Close,Parameters[0].AsInt),1.00));              }           private IndicatorBase indicator;       private Transaction _transaction;       private string _dataset = "Dow 30";    } }
1
Best Answer
- ago
#12
It looks like Building Blocks fail to insert the TimeSeriesIndicatorWrapper where necessary (hence those raw "Close" references in the code from Post #8) so the strategy in Cone's Post #3 above from yesterday won't even compile. Maybe a fix is required?
0

Reply

Bookmark

Sort