Rounding issue in DVO effecting m15 and bellow strategies significantly

This probable edge case usage example but here we go:

m1 EURAUD test gets 50% trades symmetry. In fact many forex ( up bias or low bias pairs) on m1 get about 2x as many short trades with this simple dvo strategy. removing dvo from the equation fixes the issue. A further look in to DVO calculations reveals a potential rounding issue in these lines:

EDIT: Even m15 strats can be significantly effected by this rounding issue.



if(Buffer.getRounded(0,6)>Buffer.getRounded(i,6)){ pRank = pRank+1; } } } dvo = 100.0d*pRank/(double)PercentRankPeriod;



In fact, changing the code to this appears to solve the issue (96.5% trades symmetry now!):




for(int i = 1; i<= PercentRankPeriod; i++){ if(Buffer.getRounded(0,12)>Buffer.getRounded(i,12)){ pRank = pRank+1; } } } dvo = 100.0d*((double)pRank/(double)PercentRankPeriod);







I attached two DVO strategies exactly the same, one tested with the old DVO and one tested with my suggested fixed DVO.



Why so sensitive?
This indicator is extra sensitive to rounding. Taking the high and the low and dividing by two gets us the middle of a single bar expressed in price but half the time the high+low is an odd number of points resulting in precisely half a point being rounded off and will be rounded in one direction only. Some markets have 15 minute bars that are as small as 10 points or less so a significant bias will exist due to this rounding. So yeah 12 decimals is not needed only 7 I think.

And also, while I'm looking at this, I think it is technically correct to account for when the two buffers are precisely the same like this:



protected void OnInit() throws TradingException { SMAAverageCalculator = new AverageCalculator(AverageCalculator.SMA, MAPeriod); } @Override protected void OnBarUpdate() throws TradingException {       double price =0 ;   double dvo = 0;   double pRank =0;   double maValue =0;    if (CurrentBar < Math.max(PercentRankPeriod,MAPeriod)) { Value.set(0, 0); Buffer.set(0,0); } else { SMAAverageCalculator.onBarUpdate(Chart.Close.get(0)/((Chart.High.get(0)+Chart.Low.get(0))/2), CurrentBar); maValue = SMAAverageCalculator.getValue(); Buffer.set(0,maValue); if(CurrentBar<PercentRankPeriod+MAPeriod+1){ Value.set(0, 0); } else{ for(int i = 1; i<= PercentRankPeriod; i++){ if(Buffer.getRounded(0,12)>Buffer.getRounded(i,12)){ pRank = pRank+1; } else if(Buffer.getRounded(0,12)==Buffer.getRounded(i,12)){ pRank = pRank + 0.5; } } } dvo = 100.0d*(pRank/(double)PercentRankPeriod); } Value.set(0,dvo);    } }











Attachments
Strategy 1215177 dvo.sqx
(3.24 MiB)
Strategy 1215177 dvobroken.sqx
(3.23 MiB)
  • Votes +3
  • Project StrategyQuant X
  • Type Bug
  • Status New
  • Priority Normal

History

b
#1

bentra

28.09.2022 17:12

Task created

b
#2

bentra

28.09.2022 17:22
On m15 and on 6-digit forex, this can still be a significant 5% change due to the rounding issues. So it's not that edge case after-all...


Also, certainly, 12 is overkill, I just put something extra large in for testing.

CG
#3

Chris G

29.09.2022 01:08
Voted for this task.
E
#4

Emmanuel

29.09.2022 21:13
Voted for this task.
b
#5

bentra

30.09.2022 22:21

Description changed:

This probable edge case usage example but here we go:

m1 EURAUD test gets 50% trades symmetry. In fact many forex ( up bias or low bias pairs) on m1 get about 2x as many short trades with this simple dvo strategy. removing dvo from the equation fixes the issue. A further look in to DVO calculations reveals a potential rounding issue in these lines:

EDIT: Even m15 strats are significantly effected by this rounding issue.



if(Buffer.getRounded(0,6)>Buffer.getRounded(i,6)){ pRank = pRank+1; } } } dvo = 100.0d*pRank/(double)PercentRankPeriod;



In fact, changing the code to this appears to solve the issue (96.5% trades symmetry now!):




for(int i = 1; i<= PercentRankPeriod; i++){ if(Buffer.getRounded(0,12)>Buffer.getRounded(i,12)){ pRank = pRank+1; } } } dvo = 100.0d*((double)pRank/(double)PercentRankPeriod);







I attached two DVO strategies exactly the same, one tested with the old DVO and one tested with my suggested fixed DVO.



Why so sensitive?
This indicator is extra sensitive to rounding. Taking the high and the low and dividing by two gets us the middle of a single bar expressed in price but half the time the high+low is an odd number of points resulting in precisely half a point being rounded off and will be rounded in one direction only. So yeah 12 decimals is not needed only 7 I think.

And also, while I'm looking at this, I think it is technically correct to account for when the two buffers are precisely the same like this:


protected void OnInit() throws TradingException { SMAAverageCalculator = new AverageCalculator(AverageCalculator.SMA, MAPeriod); } @Override protected void OnBarUpdate() throws TradingException {       double price =0 ;   double dvo = 0;   double pRank =0;   double maValue =0;    if (CurrentBar < Math.max(PercentRankPeriod,MAPeriod)) { Value.set(0, 0); Buffer.set(0,0); } else { SMAAverageCalculator.onBarUpdate(Chart.Close.get(0)/((Chart.High.get(0)+Chart.Low.get(0))/2), CurrentBar); maValue = SMAAverageCalculator.getValue(); Buffer.set(0,maValue); if(CurrentBar<PercentRankPeriod+MAPeriod+1){ Value.set(0, 0); } else{ for(int i = 1; i<= PercentRankPeriod; i++){ if(Buffer.getRounded(0,12)>Buffer.getRounded(i,12)){ pRank = pRank+1; } else if(Buffer.getRounded(0,12)==Buffer.getRounded(i,12)){ pRank = pRank + 0.5; } } } dvo = 100.0d*(pRank/(double)PercentRankPeriod); } Value.set(0,dvo);    } }







This indicator is extra sensitive to rounding. Taking the high and the low and dividing by two gets us the middle of a single bar expressed in price but half the time the high+low is an odd number of points resulting in precisely half a point being rounded off and will be rounded in one direction only. 

And also wouldn't it be technically correct to account for when the two buffers are precisely the same like this?



protected void OnInit() throws TradingException { SMAAverageCalculator = new AverageCalculator(AverageCalculator.SMA, MAPeriod); } @Override protected void OnBarUpdate() throws TradingException {       double price =0 ;   double dvo = 0;   double pRank =0;   double maValue =0;    if (CurrentBar < Math.max(PercentRankPeriod,MAPeriod)) { Value.set(0, 0); Buffer.set(0,0); } else { SMAAverageCalculator.onBarUpdate(Chart.Close.get(0)/((Chart.High.get(0)+Chart.Low.get(0))/2), CurrentBar); maValue = SMAAverageCalculator.getValue(); Buffer.set(0,maValue); if(CurrentBar<PercentRankPeriod+MAPeriod+1){ Value.set(0, 0); } else{ for(int i = 1; i<= PercentRankPeriod; i++){ if(Buffer.getRounded(0,12)>Buffer.getRounded(i,12)){ pRank = pRank+1; } else if(Buffer.getRounded(0,12)==Buffer.getRounded(i,12)){ pRank = pRank + 0.5; } } } dvo = 100.0d*(pRank/(double)PercentRankPeriod); } Value.set(0,dvo);    } }





b
#6

bentra

30.09.2022 22:48
Voted for this task.
b
#7

bentra

15.12.2022 18:24

Subject changed from Minor rounding issue in DVO to Rounding issue in DVO effecting m15 and bellow strategies significantly


Votes: +3

Drop files to upload

or

choose files

Max size: 5MB

Not allowed: exe, msi, application, reg, php, js, htaccess, htpasswd, gitignore

...
Wait please