Expected Behavior
ChoppinessIndex(1) either works or is rejected by the constructor, the way ValueAtRisk rejects a period its formula cannot use.
Actual Behavior
The constructor accepts the value. The first update after warm-up throws System.OverflowException: Value was either too large or too small for a Decimal, so the failure lands on the data rather than on the call that is wrong.
Indicators/ChoppinessIndex.cs:106 divides by Math.Log10(_period):
return (decimal)(100.0 * Math.Log10(((double) _trueRangeHistory.Sum()) / ((double) (maxHigh - minLow))) / Math.Log10(_period));
Math.Log10(1) is 0, so the double is infinite and the cast to decimal throws. It is only period 1: Log10 is zero nowhere else, and a period of zero or less is already rejected by RollingWindow.
Potential Solution
Reject period < 2 in the constructor, with the message shape ValueAtRisk.cs:61 uses.
Reproducing the Problem
var chop = new ChoppinessIndex(1);
var time = new DateTime(2020, 1, 1);
chop.Update(new TradeBar(time, Symbols.SPY, 100m, 101m, 99m, 100.5m, 1000));
System Information
master, net10.0.
Expected Behavior
ChoppinessIndex(1)either works or is rejected by the constructor, the wayValueAtRiskrejects a period its formula cannot use.Actual Behavior
The constructor accepts the value. The first update after warm-up throws
System.OverflowException: Value was either too large or too small for a Decimal, so the failure lands on the data rather than on the call that is wrong.Indicators/ChoppinessIndex.cs:106divides byMath.Log10(_period):Math.Log10(1)is 0, so the double is infinite and the cast to decimal throws. It is only period 1:Log10is zero nowhere else, and a period of zero or less is already rejected byRollingWindow.Potential Solution
Reject
period < 2in the constructor, with the message shapeValueAtRisk.cs:61uses.Reproducing the Problem
System Information
master, net10.0.