- ago
Is there a way to create a Bullish percent index with Wealth-Lab 8?
2
414
Solved
14 Replies

Reply

Bookmark

Sort
- ago
#1
No, it's not possible. In WL6 it depended on a C# framework not ported over to WL8.
0
Cone8
 ( 5.78% )
- ago
#2
I think I'll have to disagree with that (without looking into it). Maybe Eugene is thinking in terms of Index-Lab? It might be a problem to do it there.

If I remember correctly, BPI is determined by the percentage of stocks currently bullish for their Point and Figure (PnF) chart.
That shouldn't be a problem with WL8, and furthermore, since we have dynamic DataSets, you'll even get the correct BPI historically.
0
- ago
#3
QUOTE:
Maybe Eugene is thinking in terms of Index-Lab? It might be a problem to do it there.

Right, I meant that PnF framework you put in ChartStyles.Trending that powered up my Index-Lab script.
0
Cone8
 ( 5.78% )
- ago
#4
It's just a new and improved framework now - see the PointAndFigure* classes.

Give me a 15 minutes.. maybe I can knock it out.
0
Cone8
 ( 5.78% )
- ago
#5

This is set up for P&F based on Closes and Percentage Boxes. You can change the number of boxes and reversal box count in the parameters.

Run it on a Wealth-Data DataSet (e.g., Nasdaq 100, S&P 500, etc.) for a real historical BPI.

CODE:
using WealthLab.Backtest; using System; using WealthLab.Core; using WealthLab.Data; using WealthLab.Indicators; using System.Collections.Generic; using WealthLab.TrendChartStyles; namespace WealthScript2 { public class BullishPercentIndexDemo : UserStrategyBase {       public BullishPercentIndexDemo()       {          _boxSize = AddParameter("Box Size %", ParameterType.Double, 2.0, 1, 3, 0.5);          _boxCount = AddParameter("Box Count", ParameterType.Int32, 3, 2, 5, 1);       } public override void Initialize(BarHistory bars) {           } public override void PreExecute(DateTime dt, List<BarHistory> participants)       {          int bullishCount = 0;          foreach (BarHistory bh in participants)          {                         PointAndFigure pnf = new PointAndFigure(bh, SourceDataType.CloseOnly, PointAndFigureBoxType.Percent, _boxSize.AsDouble, _boxCount.AsInt);             if (pnf?.Events.Count == 0)                continue;                             int bar = GetCurrentIndex(bh);             PointAndFigureEvent pfev = pnf.Events[pnf.Events.Count - 1];             for (int n = pnf.Events.Count - 2; n >= 0; n--)                {                PointAndFigureEvent pfev1 = pnf.Events[n];                if (pfev.Index <= bar && bar > pfev1.Index)                {                   if (pfev.IsUpsideReversal)                      bullishCount++;                   break;                }                pfev = pfev1;             }                      }          double value = 100 * bullishCount / (double)participants.Count;          _bpiSource.Add(value, dt); } public override void Execute(BarHistory bars, int idx) {           }       public override void Cleanup(BarHistory bars)       {          _bpi = TimeSeriesSynchronizer.Synchronize(_bpiSource, bars);          PlotTimeSeriesLine(_bpi, "Bullish Percent Index", "BPI");       }       static TimeSeries _bpiSource = new TimeSeries();       TimeSeries _bpi;       Parameter _boxSize;       Parameter _boxCount;    } }

BPI is built during execution and synchronized in the Cleanup() method. To use the values the same Strategy in Execute(), you'd have to be careful with the synchronization. Probably it would be best to export the BPI data to a text file and consume it in another strategy. Other ideas?

Of course, since the calculation is performed in PreExecute, you can acess the current value of BPI in Execute like this:

CODE:
public override void Execute(BarHistory bars, int idx) {          double bpiToday = _bpiSource.LastValue; }
1
Best Answer
Glitch8
 ( 11.21% )
- ago
#6
Wow, I guess it was possible after all! 👍
0
- ago
#7
I have a weird question. Could you do the same thing using bullish/bearish candlestick patterns? Of course you couldn't call it the Bullish Percent Index anymore because it would be based on a slightly different criteria, but the "intent of the method" would still be the same. (I wonder which approach would be more revealing?)

I'm "guessing" that using candlestick patterns would require significantly more CPU time than using Point and Figure methodology.
0
Cone8
 ( 5.78% )
- ago
#8
Sure, why not?
(I'm kind of surprised you're asking!)
1
Cone8
 ( 5.78% )
- ago
#9
Glitch, what do you think about making BPI an IndexLab indicator?
It fits the framework for an IndexLab-type indicator.
1
Glitch8
 ( 11.21% )
- ago
#10
Absolutely!
0
- ago
#11
Hi Glitch!

Is BPI as an IndexLab indicator still the plan?

Thanks,
Matthias
0
Glitch8
 ( 11.21% )
- ago
#12
Kind of lost track of this but let me tag it as a #FeatrureRequest. Give the main topic a thumbs up to vote for it. It will be tricky since it requires classes that span 2 extensions but will figure it out if there’s a demand!
0
Cone8
 ( 5.78% )
- ago
#13
As a workaround, just add this to the code above to create your own ASCII BPI indices in the UserData folder \BPI.
Rerun the strategy code on each index to refresh the data.

CODE:
// Also add: using System.IO;       public override void BacktestComplete()       {          string path = Path.Combine(WLHost.Instance.DataFolder, "BPI");          if (!Directory.Exists(path))             Directory.CreateDirectory(path);          //DataSet Name          string[] dsname = Backtester.ExecutionDataSetName.Split(';');          string dsn = dsname[0].Replace("&", "").Replace(" ", "");          string filepath = Path.Combine(path, $"BPI-{dsn}.txt");          //write to file          List<string> bpi = [];          for (int n = 0; n < _bpiSource.Count; n++)             bpi.Add($"{_bpiSource.DateTimes[n]:yyyy-MM-dd}\t{_bpiSource[n]}");          File.WriteAllLines(filepath, bpi);       }
1
- ago
#14
Thanks a lot! I’ll try that later today!
0

Reply

Bookmark

Sort