- ago
Hello,
I've been doing some experimentation with percentile-based indicators in python and wanted to see if something similar could be implemented in Wealth Lab. This post shares some simple Wealth Code to implement a rolling percentile based on true range: https://www.wealth-lab.com/Strategy/DesignPublished?strategyID=22 Is there a way to accomplish this or something similar with drag and drop indicators?
0
358
15 Replies

Reply

Bookmark

Sort
- ago
#1
I don't understand your question. Do you own the finantic.Indicators extension for WL? If so, can't you simply drag-and-drop the MP indicator over a TR indicator plot on the Chart to get a percentile True-Range result? If not, why not?

What's wrong with simply coding it like in your cited example?
CODE:
   public override void Initialize(BarHistory bars)    {       TR tr = new TR(bars);       MP movingPercentile = new MP(tr, lookback: 100, percentile: 75);       PlotIndicator(movingPercentile);    }
Also, the TimeSeries class has a PercentRank property that can evaluate the percentile for any TimeSeries. Have you tried it?

In my own applications, I do a discriminate analysis against two different populations: [1] position "winners" and [2] position "loosers". This setup creates two sparse vectors (i.e. TimeSeries) of winner instances and looser instances with many NaN's in between. The problem I face is that percentile indicators like MP can't handle a sparse vectors too well and neither can Math.NET. So I end up writing my own "robust" percentile indicator that can handle sparse vectors--big hassle--when all I want to do is a robust discriminate analysis of winners and loosers.
1
- ago
#2
Superticker,
Thanks for sharing your knowledge. No, I don't own the finantic.Indicators extension for Wealth Lab, and I haven't learned to code in WL. All of the backtesting I do in WL is with building block strategies. When I need to test something that can’t be accomplished with the building blocks I use Python. Are you saying that I would be able to use the finantic.Indicators extension with a building blocks strategy to create a percentile-based indicator?
0
- ago
#3
A built-in indicator called IndOnInd can accomplish the "MP of TR" task as per @superticker's example in Post #1. Which of course can be used in Blocks.
1
- ago
#4
QUOTE:
Are you saying that I would be able to use the finantic.Indicators extension with a building blocks strategy to create a percentile-based indicator?

Building blocks does not create code-based indicators. But it can create a TimeSeries that you can plot and test against (see Post #3) in Blocks. And once you install the finantic.Indicators extension in WL, you can drag and drop it onto other plotted indicators like TR.

If you code in Python, then you can program. C# is more complicated than Python, but you don't have to know that complicated stuff to run code like I posted. Take your C# textbook and read up to, but not including, the chapter about classes and encapsulation. With that much knowledge, you can get going with WL and C#. Once you've done that and are ready to create your own class libraries, then you can read the chapter about classes and beyond.

My strategies are around 200 to 300 lines of C# code, which changes. But my local code library is over 2500 lines of code that rarely changes. So you really do the heavy lifting with the custom code libraries such as compute the ideal trailing stop value, statistical analysis (Math.NET), or ScottPlot. The finantic.Indicators extension installs the Math.NET library, which it uses.
2
- ago
#5
@digitalsculpture - superticker's recommendations are spot-on. By learning C# you'll probably find that building strategies are easier and more flexible than using building blocks.

In any case, if you want to see the One Night with Percentile in blocks, here it is. You need the MP indicator from finantic.Indicators extension to do this...

Make sure you select "Multiple Positions"...


And, here is the detail for the Buy at Limit's indicator...


For me, using building blocks for that strategy is very cumbersome. Look at the equivalent published C# strategy that you linked-to at: https://www.wealth-lab.com/Strategy/DesignPublished?strategyID=22

The C# is a piece of cake to think through - very straightforward.
1
- ago
#6
Thank you all for sharing this great information. You're making a compelling case for the value of learning C#. Sometime soon I need to bite the bullet and get up to speed with it. At times like these I wish I could have five more lifetimes to learn all of the skills I'd like to have!
0
- ago
#7
Hi Paul,
QUOTE:
One Night with Percentile in blocks,

Great work!

...anyway:

did you see the Eval indcator (from the finantic.Eval extension).
Makes this thing much simpler, more elegant, better understandable....
0
- ago
#8
@DrKoch - what timing - I was just trying that out! I find the results are different. So, I took the above block strategy and added an Eval equivalent to it.

In the following turn on the first Buy at Limit block (uses Eval) and turn off the second Buy at Limit block and run a backtest. Then, turn off the first block and turn on the second (Buy at Limit) block and run a backtest. They produce different results.

(Note: I don't need any support on this. I write 99.9% of my code in C#. I just wanted to try out Eval. And, I wanted to let you know in case there is a bug)...

0
- ago
#9
QUOTE:
there is a bug


Problem confirmed... :(

Working on a fix...

thanks for the report!
0
- ago
#10
@DrKoch - one other problem I found. In the following strategy you get a parse error in the expression that does not contain spaces...

CODE:
using WealthLab.Backtest; using System; using WealthLab.Core; using WealthLab.Data; using WealthLab.Indicators; using System.Collections.Generic; using finantic.Eval; namespace WealthScript1 { public class MyStrategy : UserStrategyBase {     public MyStrategy() : base() { StartIndex = 0; } public override void Initialize(BarHistory bars) {          // The only difference between the following is the use of spaces.          // The expression without spaces generates a parse error.                    source = new Eval(bars,"Close-MP(TR(Bars),100,75)*0.70");          //source = new Eval(bars, "Close - MP(TR(Bars), 100, 75) * 0.70");                    PlotIndicator(source,new WLColor(0,0,0));          _startIndexList.Add(source);          pct = 0.00;          pct = (100.0 + pct) / 100.0;          multSource = source * pct;          PlotStopsAndLimits(3); foreach(IndicatorBase ib in _startIndexList) if (ib.FirstValidIndex > StartIndex) StartIndex = ib.FirstValidIndex; } public override void Execute(BarHistory bars, int idx) {          int index = idx;          bool condition0;             {                Backtester.CancelationCode = 1;                val = multSource[idx];                _transaction = PlaceTrade(bars, TransactionType.Buy, OrderType.Limit, val, 0, "Buy " + 0.00 + "% above " + source.Description);             }             {             foreach(Position foundPosition0 in OpenPositions)             {                if (foundPosition0.PositionTag == 0)                {                   Backtester.CancelationCode = 1;                   ClosePosition(foundPosition0, OrderType.Market, 0, "Sell At Market (1)");                }             }             } } public override void NewWFOInterval(BarHistory bars) {          source = new Eval(bars,"Close-MP(TR(Bars),100,75)*0.70");          pct = 0.00;          pct = (100.0 + pct) / 100.0;          multSource = source * pct; }       private double pct;       private double val;       private IndicatorBase source;       private TimeSeries multSource;       private Transaction _transaction; private List<IndicatorBase> _startIndexList = new List<IndicatorBase>(); } }


Here is the error...

CODE:
7/18/2024 13:25:44:396 Evaluate Indicator Expression Parse Error: unexpected token: "MP(TR(Bars),100,75)*0.70" IndiExpression -> [Identifier] IndiParserException Parse Error: unexpected token: "MP(TR(Bars),100,75)*0.70" IndiExpression -> [Identifier] at finantic.Common.IndiParser.Parse2(String input) at finantic.Common.IndiParser.ParseIndicatorSpec(String input) at finantic.Eval.EvalBase.Evaluate(BarHistory bars, String expression) --------
0
- ago
#11
The Eval indicator did not understand this expression correctly:
CODE:
Eval(bars,"Close-MP(TR(Bars),100,75)*0.70")

It was clever enough to handle indicators like DI- and DI+
but was unable to cope with Close-

Fixed in the next build.
1
- ago
#12
Problem mentioned in Post #8 was caused by some strange behavior of MathIndOpInd() as reported here:
https://www.wealth-lab.com/Discussion/MathIndOpInd-not-workin-correctly-11474

Fixed in next build of finantic.Eval.
0
- ago
#13
With the advent of Build 4 of finantic.Eval it is now (finally!) possible to implement the famous "OneNight w Moving Percentile" strategy with Building Blocks:


The indicator expression inside the Eval indicator looks like this:
CODE:
Close - MP(TR(bars), 100, 75) * 0.7

The spaces are there for esthetic reasons only. It works the same without:
CODE:
Close-MP(TR(bars),100,75)*0.7

0
- ago
#14
BTW: It is not possible to do the same without the Eval() indicator, because MathIndOpInd() and MathIndOpValue() do not support the required chaining of indicators. (see link in Post #12 for details)
1
Cone8
 ( 3.70% )
- ago
#15
Since we now understand that we can nest Transformer Indicators, you actually can do this with Transformers. However, using Eval could be more intuitive, and probably Transformers could still have limitations for some combinations.

0

Reply

Bookmark

Sort