mjj38
- ago
I'm getting an error when I optimize using the "Max Risk % Limited to % of Equity" Advanced Pos Sizer.

If you just optimize with a blank strategy with a parameter.
CODE:
using WealthLab.Backtest; using System; using WealthLab.Core; using WealthLab.Data; using WealthLab.Indicators; using System.Collections.Generic; namespace WealthScript3 { public class demo : UserStrategyBase {       public demo()       {          length = AddParameter("Length", ParameterType.Int32, 2, 1, 24, 1);       } public override void Initialize(BarHistory bars) { } public override void Execute(BarHistory bars, int idx) { if (!HasOpenPosition(bars, PositionType.Long)) { } else { } }       Parameter length; } }


You get the following error under the Tabular optimization visualizer
QUOTE:
System.ArgumentException: Unable to sort because the IComparer.Compare() method returns inconsistent results. Either a value does not compare equal to itself, or one value repeatedly compared to another value yields different results. IComparer: 'System.Comparison`1[WealthLab.Core.TimeSeriesBase]'.
at System.Collections.Generic.ArraySortHelper`1.Sort(Span`1 keys, Comparison`1 comparer)
at WealthLab.Backtest.UserStrategyExecutor.RunBacktestInternal(List`1 symbols)
at WealthLab.Backtest.Backtester.RunBacktest(StrategyBase strategy, List`1 symbols)
at WealthLab.Backtest.StrategyOptimizer.ExecuteOptimizationRun(ParameterList pl, Backtester bmBacktester, Boolean addToResults)
0
728
Solved
14 Replies

Reply

Bookmark

Sort
Cone8
 ( 28.25% )
- ago
#1
Okay. For now, maybe just avoid optimizing an "anti Strategy'.
0
Glitch8
 ( 12.08% )
- ago
#2
This isn't one of our Position Sizers, where is it coming from? Cannot duplicate this error with a built-in Position Sizer.
0
mjj38
- ago
#3
I just isolated the problem to the sizer. I believe the sizer comes from the finantic.indicator extension.
0
Glitch8
 ( 12.08% )
- ago
#4
Ok I renamed the topic so DrKoch should see this and get a fix in.
0
- ago
#5
I see the exception if I run an Exhaustive optimization with an "empty" strategy and the ""Max Risk % Limited to % of Equity" (from finantic.Indicators) selected:



My Point is: With an "empty" strategy, which produces no trades, an PosSizer is never called (and my breakpoint inside the PosSizer never hit)

So while the problem occurs with this PosSizer only, I can't see what the PosSizer is doing wrong...
0
- ago
#6
Update: Same thing happens with other "Advanced Pos Sizer" like
- Control Drawdown
- D-VarR
- etc...
0
- ago
#7
Not having finantic extensions installed and I'm not getting the exception in Exhaustive optimizations of the empty strategy code from the title post with D-VaR, Control Drawdown etc.
0
- ago
#8
Fresh Install, no Extensions, fresh AppData folder (no Settings changes).

Empty strategy from original post.

I see the same as Post #5 with "Max Entries per Bar" Advanced Pos.Sizer.

Backtest Data: (WD) Dow 30, most recent 10 years.
0
- ago
#9
With a Portfolio optimization I can reproduce, first time tried with Single Symbol. Anyway, it's 1) harmless and 2) not specific to finantic. Let's not waste time on this topic anymore.
0
mjj38
- ago
#10
I only created an empty strategy to demonstrate the problem.

Here is Dr Koch's "Bensdorp Long Trend Low Volatility" strategy. When using the "Max Risk % Limited to % of Equity" position sizer you get the same error (same with many of the Advanced Position Sizers). Works fine with the basic sizers though.

CODE:
// Long Trend Low Volatility // inspired by Lauren Bensdorp's book "Automated Stock Trading Systems" // Please read the book to get the full picture. using WealthLab.Backtest; using System; using WealthLab.Core; using WealthLab.Indicators; using finantic.Indicators; namespace WealthScript1 {    // Universe: NYSE, NASDAQ, AMEX    // Position Sizing: 2% Risk and 10% maximum percentage, max. 10 Position    public class LongTrendLowVol : UserStrategyBase    {       public LongTrendLowVol()       {          stopAtr = AddParameter("Stop ATR's", ParameterType.Double, 1.5, 1, 5, 0.5);          trailPct = AddParameter("Trail Pct", ParameterType.Double, 20, 5, 25, 5);       }       public override void Initialize(BarHistory bars)       {          //--- Indicators ---          avgTurnover = new AvgTurnover(bars, 50);          hv = new HV(bars.Close, 120, 252);          sma200 = new SMA(bars.Close, 200);          spy = GetHistory(bars, "SPY");          smaSpy = new SMA(spy.Close, 200);          rsi4 = new RSI(bars.Close, 4);          atr40 = new ATR(bars, 40);          StartIndex = 200;                    //--- Graphics ---          PlotIndicator(sma200, WLColor.Magenta, paneTag: "Price");          PlotBarHistory(spy, "SPY", WLColor.Gray);          PlotIndicator(smaSpy, WLColor.Red, paneTag: "SPY");          PlotStopsAndLimits(dotSize: 3);       }       public override void Execute(BarHistory bars, int idx)       {          //=== Exit ===          Position p = LastOpenPosition;          if (p != null)          {             // Stop Loss             ClosePosition(p, OrderType.Stop, p.EntryPrice - stopAtr.AsDouble * atr40[p.EntryBar], "Stop Loss");             if (p.IsOpen)             {                // Trailing Stop                CloseAtTrailingStop(p, TrailingStopType.PercentC, trailPct.AsDouble, "Trailing Stop");             }          }          //=== Entry ===          // One position per symbol          if (HasOpenPosition(bars, PositionType.Long)) return;          // check data          if (Double.IsNaN(hv[idx]) || Double.IsNaN(smaSpy[idx]) || Double.IsNaN(atr40[idx]) || Double.IsNaN(avgTurnover[idx]) || Double.IsNaN(sma200[idx]) || Double.IsNaN(rsi4[idx])) return;          //--- Filter ---          // Average daily dollar volume          if (avgTurnover[idx] < 100e6) return;          // Historical Volatility between 10 and 40          if (hv[idx] < 10.0) return;          if (hv[idx] > 40.0) return;          //--- Setup ---          // SPY above SMA          if (spy.Close[idx] < smaSpy[idx]) return;          // close above SMA          if (bars.Close[idx] <= sma200[idx]) return;          Transaction t = PlaceTrade(bars, TransactionType.Buy, OrderType.Market, 0.0, "Long Entry");          //--- Ranking ---          t.Weight = -rsi4[idx];       }       public override double GetMaxRiskStopLevel(BarHistory bars, PositionType pt, int idx)       {          double stop = bars.Close[idx] - stopAtr.AsDouble * atr40[idx];          return stop;       }       // private variables       Parameter stopAtr, trailPct;       IndicatorBase avgTurnover, hv, sma200, smaSpy, rsi4, atr40;       BarHistory spy;    } }
0
- ago
#11
Consider a complex strategy that has one or more parameters and hence can be optimized. If for some optimization parameters no positions occur then it seems the error occurs, and it is shown in the Optimization -> Tabular tab. The end-user has no idea what the errors mean, and may assume that none of the optimization results are valid. The end-user may also assume there is some problem in their strategy implementation. Then, the end-user spends time trying to figure out what is wrong with their strategy. Well, there may be nothing wrong with it. Some combination of optimization parameters produced no results, and hence the error.



Here is a very simple strategy to re-create the problem. Try this with DOW 30, Daily scale, 3 years, Advanced Position Sizer 'Control Drawdown'...

CODE:
using WealthLab.Backtest; using System; using WealthLab.Core; using WealthLab.Data; using WealthLab.Indicators; using System.Collections.Generic; namespace WealthScript1 {    public class MyStrategy : UserStrategyBase    {       public MyStrategy()       {          ParamLength = AddParameter("Length", ParameterType.Int32, 2, 1, 24, 1);       }       //create indicators and other objects here, this is executed prior to the main trading loop       public override void Initialize(BarHistory bars)       {          Length = ParamLength.AsInt;       }       //execute the strategy rules here, this is executed once for each bar in the backtest history       public override void Execute(BarHistory bars, int idx)       {          if (!HasOpenPosition(bars, PositionType.Long))          {             //code your buy conditions here             if (Length == 2 && idx == 100)             {                PlaceTrade(bars, TransactionType.Buy, OrderType.Market);             }          }          else          {             //code your sell conditions here             var pos = FindOpenPosition(PositionType.Long);             if (pos != null && idx == pos.EntryBar + 10)             {                ClosePosition(pos, OrderType.Market);             }          }       }       //declare private variables below       private Parameter ParamLength { get; set; }       private int Length { get; set; }    } }


Obviously, not having the WL source code, I don't know exactly what would be the error cause. But, consider the first answer here: https://stackoverflow.com/questions/57874983/unable-to-sort-because-the-icomparer-compare-method-returns-inconsistent-resul
1
- ago
#12
To recreate the problem we also have to choose strictly Exhaustive because "Exhaustive (non-Parallel)" won't produce these exceptions.
0
mjj38
- ago
#13
So it isn't an error, it's just a parameter set that returns no trades. Thank you very much guys!
0
Glitch8
 ( 12.08% )
- ago
#14
Thanks for the help tracking this down, it's fixed for Build 33.

mjj3: It was indeed a flaw.
2
Best Answer

Reply

Bookmark

Sort