129 MC test makes no sense

This MC test makes me think something is broken or needs to be improved.

"The Probability of change sets for every bar how probable it is that open, high, low or close price will be changed."

Does the next bar start at the last bars ORIGINAL data close (anchored) or last bars RANDOMIZED close (floating) +/- the next adjustment? Also, is there an equal chance of bars being larger and smaller?



Attachments
Screenshot 58.png
(376.75 KiB)
mc-bugged.sqx
(781.36 KiB)
mc-bugged.cfx
(6.77 KiB)
Screenshot 59.png
(74.93 KiB)
  • Votes +8
  • Project StrategyQuant X
  • Type Bug
  • Status Fixed
  • Priority Normal

History

b
#1

bentra

14.11.2020 18:42

Task created

k
#2

Karish

14.11.2020 18:46
Voted for this task.
k
#3

Karish

14.11.2020 18:47
Would like to join the request on the way of how these tests are working behind the scenes
b
#4

bentra

14.11.2020 18:59
I think if price is not allowed to "float/wander" and is instead "anchored" to the next original bar then I think we are biased to mean reversion strategies and or limit orders. 

I suggest maintain approximate gap sizes between the original and randomized set but otherwise allow price to "wander." 
b
#5

bentra

14.11.2020 19:17
Voted for this task.
o
#6

Enric

15.11.2020 08:10
Voted for this task.
IH
#7

clonex / Ivan Hudec

15.11.2020 14:14
Voted for this task.
b
#8

bentra

16.11.2020 03:12
Also is it +/- ATR(1) just using the one bar in it's calculation that it is randomizing? I hope so otherwise it will be lagging and could cause a very small bar to become much larger.
b
#9

gin

16.11.2020 07:17
Voted for this task.
MF
#10

Mark Fric

19.11.2020 10:01

Status changed from New to Refused

you can see it in the snippet source: SQ.MonteCarlo.Retest.RandomizeHistoryData


It is not based on OHLC prices but ticks - where each O,H,L,C price is represented as tick. Each tick can be modified with the same probability.


You can make your own data changing algorithm by copying and modifying the default one.



public void modifyData(IRandomGenerator rng, TickEvent tickEvent, double globalATR) {

double dblProbability = ((double) Probability/ 100.0d);

if(rng.probability(dblProbability)) {

// we should change this price

double ask = tickEvent.getAsk();

double bid = tickEvent.getBid();

double spread = ask - bid;

int change;

if(relativeMaxChange <= 0) {

change = rng.nextInt(MaxChange);

} else {

change = rng.nextInt(relativeMaxChange);

}

double dblChange = ((double) change)/ 100.0d;


double priceChange = 2 * globalATR * dblChange;

bid = (rng.nextInt(2) == 0 ? bid + priceChange : bid - priceChange);

tickEvent.setBid(bid);

tickEvent.setAsk(bid + spread);

}

}

h
#11

hankeys

19.11.2020 12:31
i am not a programmer so i cant really understand the compuation logic, but if i look at the picture and see, that the MC EQ curves are holding the same direction and only 1 EQ curve as original strategy is going differently i can say that something is not working, because from principle it doesnt make sense


how every MC run could have better stats than original strategy?

MF
#12

Mark Fric

20.11.2020 08:56

Status changed from Refused to In progress

you have a point. I suspect the problem will be not in history data change but in MC tests runnign with better commission, spread or something similar than original strategy.


We'll check it.

b
#13

bentra

21.11.2020 02:09
Transaction cost does not explain all the extra trades taken.

My settings were 50% of ATR. Now that I see that it is applied to every tick it seems 50% of an ATR is actually quite a ridiculous setting, probably not meant to be set so high. Each tick is calculated from it's original position instead of allowing price to wander so I'm sure it is triggering limit orders from far away because of the violent choppy ticks. You may think why doesn't it also hit the SL more? Strategy has far away SL (9 ATR) and very near TP (1.4 ATR) Also, strategy has exit after X bars and another exit rule so SL is rarely hit. This strategy is basically exploiting the MC tick randomizer =)

One day when I have time I'll try some other code and try to find something that is not exploitable thanks for exposing the code to make it possible.


b
#14

bentra

21.11.2020 20:08
Does the MC data randomizer have an effect on indicator readings and price levels i.e. does it give bars different highs and lows? Or does it only effect the execution of orders?
JK
#15

Insanity82007

22.11.2020 11:36

Attachment MC Global ATR.png added

MC Global ATR.png
(77.53 KiB)
Hi Mark,


What is GlobalATR?

JK
#16

Insanity82007

23.11.2020 02:41
Voted for this task.
JK
#17

Insanity82007

23.11.2020 02:43

Attachment MC Price 100 100 settings.png added

Attachment MC Price 100 100.png added

Attachment EURGBP MC Price 100 100 Strategy 22356.sqx added

Attachment project.cfx added

project.cfx
(3.50 KiB)
MC Price 100 100 settings.png
(144.62 KiB)
EURGBP MC Price 100 100 Strategy 22356.sqx
(502.78 KiB)
MC Price 100 100.png
(477.92 KiB)
There is DEFINITELY something funny about the way this test is handled. Look at this result! 


With the settings of 100% probability and 100% of ATR I would expect to see similar results to the backtests on additional markets.

MF
#18

Mark Fric

23.11.2020 13:22

Status changed from In progress to Fixed

ok, we made some improvements in the history data MC simulation:

- you can select % and size of change for Up and Down side separately

- there is optional check to keep gaps (or no gaps) between close and next open


Global ATR is average ATR(14) of the data, the change is defined as % of this ATR.


As for the "strange" results - the attached examples are most probably strategies that benefit fom increased volatility which happens with simulation configured like this.



With the settings of 100% probability and 100% of ATR I would expect to see similar results to the backtests on additional markets.


I don't see why you'd expect something like this. With change of 100% ATR you'd have much bigger volatility of the data, possibly much bigger than any other real existing symbols.

b
#19

bentra

23.11.2020 17:00
Here you're admitting this test is biased to strategies that "benefit from extra volatility." I think it's possible to come up with something much less exploitable/biased....

ATR is not even needed. I suggest using the raw change between each tick event instead of ATR. ATR is weird in this algorithm. It will have some odd behavior such as cause some tiny bars within a string of large bars to become much larger and as mentioned the increase in volatility. So, instead I would use the difference between this tick (of original data) and last tick (of original data) +/- % of that difference. This would keep the bars relative size to each other and volatility still similar. This could have helped solve your gap problem as well without the need to add a control for it. (existing gaps can become larger or smaller by x%, non existing gaps would remain unchanged)  This should be easy to code, make it more like an actual alternate market data (and therefore much less exploitable/biased) and I don't think it will cause any other issues. This only works if we have 4 ticks per bar: ohlc. 

If this function is being called before the indicator readings and price levels are all calculated then it might also be beneficial to record last tick and start the next tick from the randomized last ticks position +/- the actual change +/- random change. In this way to allow price "base" to wander instead of price base remaining the same as the original data. Any prerecorded or preset data would be way off by the end of the sample though...

I'll try these ideas out myself and share it in the next few weeks if anybody wants...




MF
#20

Mark Fric

24.11.2020 09:24
every algorithm is biased to something. But the codes to MC simulations in StrategyQuant are open and the whole functionality is extendable, this is one of SQ strong points.


You are welcome to make your own version, if you'll send it to us we could add it to the official distribution.

b
#21

bentra

05.12.2020 01:25

Attachment Screenshot 98.png added

Screenshot 98.png
(522.72 KiB)
I got rid of the bias effecting the original strategy using my own data randomizing method. Working for b129. 

https://strategyquant.com/forum/topic/possible-new-way-to-randomize-data-with-change-instead-of-atr/






/*  * Copyright (c) 2017-2018, StrategyQuant - All rights reserved.  *  * Code in this file was made in a good faith that it is correct and does what it should.  * If you found a bug in this code OR you have an improvement suggestion OR you want to include  * your own code snippet into our standard library please contact us at:  * https://roadmap.strategyquant.com  *  * This code can be used only within StrategyQuant products.  * Every owner of valid (free, trial or commercial) license of any StrategyQuant product  * is allowed to freely use, copy, modify or make derivative work of this code without limitations,  * to be used in all StrategyQuant products and share his/her modifications or derivative work  * with the StrategyQuant community.  *  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,  * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR  * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES  * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  *  */ package SQ.MonteCarlo.Retest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.strategyquant.lib.*; import com.strategyquant.datalib.*; import com.strategyquant.datalib.consts.Precisions; import com.strategyquant.tradinglib.*; @ClassConfig(name="Randomize history data", display="Randomize history data v2.0, with max price change #MaxChange# % of PRICE") @Help("<b>Note!</b>If you choose this option then robustness tests will be tested with Selected Timeframe precision, while original strategy will be tested with configured precision.<br/>This might cause difference in results between original strategy and simulations because of different precision.<br/>To avoid this, use Selected Timeframe precision in Setings : Data.") public class RandomizeHistoryData2 extends MonteCarloRetest {     public static final Logger Log = LoggerFactory.getLogger(RandomizeHistoryData2.class);          //@Parameter(name="Probability change price", defaultValue="20", minValue=1, maxValue=100, step=1)     //public int Probability;          @Parameter(name="Max change price", defaultValue="10", minValue=1, maxValue=100, step=1)     public int MaxChange;          private int barsProcessed = 0;     private double atrValue = 0;     private int atrPeriod = 14;          private int relativeMaxChange = -1;               //bendedit: we need some persistant variables so we can track price and allow it to wander away from original data     private double lastbid=0;     private double lastorgbid=0;     private long lastticktime=0;               //------------------------------------------------------------------------     //------------------------------------------------------------------------     //------------------------------------------------------------------------     public RandomizeHistoryData2() {         super(MonteCarloTestTypes.ModifyData);     }          //------------------------------------------------------------------------     public void modifyData(IRandomGenerator rng, TickEvent tickEvent, double globalATR) {         //double dblProbability = ((double) Probability/ 100.0d);                               //if(rng.probability(dblProbability)) ;{             // bendedit: I don't see a point in probability of change, lets just always change every tick, it will be much smoother now that we turfed ATR from the equation.             // we should change this price             double ask = tickEvent.getAsk();             double bid = tickEvent.getBid();             double spread = ask - bid;             double tickorgchange=0;             long currentticktime = tickEvent.getTime();                          //bendedit: check if first tick, if not then set original tick change.             if (lastticktime <= currentticktime && lastticktime!=0) {                 //bendedit: calculate the price change from last original tick to the current tick from original data                 tickorgchange=bid-lastorgbid;                 //debug("MC price randomizer", "tickorgchange is: "+tickorgchange);                 //debug("MC price randomizer", "time is: "+currentticktime);                 //debug("MC price randomizer", "last time is: "+lastticktime);                 //debug("MC price randomizer", "EOL");             } else { //bendedit: in case of first tick there is no change.                 lastbid=bid;                 tickorgchange=0;             }                          //bendedit:set last original data bid in to variable before we change bid, we only need it to calculate the price change next time.             lastorgbid=bid;                          //bendedit:store the ticktime.             lastticktime = currentticktime;                          int change;                          if(relativeMaxChange <= 0) {                 change = rng.nextInt(MaxChange);             } else {                 change = rng.nextInt(relativeMaxChange);             }                          double dblChange = ((double) change)/ 10000.0d;              //bendedit: Modding every tick and allowing price to move far away from original data therefore we need to use much smaller adjustments.             //bendedit: I chose a percent of a percent             //bendedit: changed from using ATR to just use tick price change of original data.             double priceChange = tickorgchange * dblChange;                                       //bendedit: set the working bid relative to the last bid instead of itself             //bid = (rng.nextInt(2) == 0 ? bid + priceChange : bid - priceChange);             bid = (rng.nextInt(2) == 0 ? lastbid + tickorgchange + priceChange : lastbid + tickorgchange - priceChange);                          tickEvent.setBid(bid);             tickEvent.setAsk(bid + spread);                          //bendedit:set last bid in to variable for next time.             lastbid = bid;                       //}     }     //------------------------------------------------------------------------          public void initSettings(SettingsMap settings) {         super.initSettings(settings);                  // compute relative Max Change according to chart TF and precision         ChartSetup chartSetup = (ChartSetup) settings.get(SettingsKeys.BacktestChart);         if(chartSetup != null) {             int testPrecision = chartSetup.getTestPrecision();                          if(testPrecision == Precisions.SelectedTF) {                 // do nothing for selected TF precision                 relativeMaxChange = MaxChange;                 return;             }                          // it is higher precision, set MaxChange to 1/3 of the value             // because the change is applied o every minute bar / tick we have to lower the MaxChange              // so that the resulting full bar in target timeframe (for example H1) isn't changed too much                          //bendedit: Hopefully we don't need this adjustment anymore since we aren't using globalATR which is inflated by higher timeframes. deviding by 3 arbitrarily was suspect anyways. If we still need to adjust, I'll hopefully find a better way.             //bendedit: Now that we are doing change % instead of atr %, we may not need any further adjustments relative to precision or TF. Turned off this equalizer for now.             //relativeMaxChange = MaxChange / 3;             relativeMaxChange = MaxChange;             if(relativeMaxChange <= 0) {                 relativeMaxChange = 1;             }                      }     }    }


b
#22

bentra

05.12.2020 02:04

Attachment Screenshot 99.png added

Attachment Screenshot 100.png added

Screenshot 99.png
(405.01 KiB)
Screenshot 100.png
(442.21 KiB)
Insanity82007's strategy also looks much more reasonable too.

MF
#23

Mark Fric

05.12.2020 08:03

Status changed from Fixed to In progress

bendx77 - thank you, we'll review it. Would you agree to put it into a standard SQ distribution? You'll be in the snippet as an author.
b
#24

bentra

05.12.2020 08:33
Sure it would be an honor. I'm not sure it's ready yet, we should test it more first I think. Also, I'm not sure about the name. Can someone help think of a name?

I have the one that works on b130 :



/*  * Copyright (c) 2017-2018, StrategyQuant - All rights reserved.  *  * Code in this file was made in a good faith that it is correct and does what it should.  * If you found a bug in this code OR you have an improvement suggestion OR you want to include  * your own code snippet into our standard library please contact us at:  * https://roadmap.strategyquant.com  *  * This code can be used only within StrategyQuant products.  * Every owner of valid (free, trial or commercial) license of any StrategyQuant product  * is allowed to freely use, copy, modify or make derivative work of this code without limitations,  * to be used in all StrategyQuant products and share his/her modifications or derivative work  * with the StrategyQuant community.  *  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,  * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR  * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES  * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  *  */ package SQ.MonteCarlo.Retest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.strategyquant.lib.*; import com.strategyquant.datalib.*; import com.strategyquant.datalib.consts.Precisions; import com.strategyquant.tradinglib.*; @ClassConfig(name="Randomize history data", display="Randomize history data v2.0, with max change #MaxChange# % of TICK PRICE CHANGES") @Help("<b>Note!</b>If you choose this option then robustness tests will be tested with Selected Timeframe precision, while original strategy will be tested with configured precision.<br/>This might cause difference in results between original strategy and simulations because of different precision.<br/>To avoid this, use Selected Timeframe precision in Setings : Data.") public class RandomizeHistoryData2 extends MonteCarloRetest { public static final Logger Log = LoggerFactory.getLogger(RandomizeHistoryData2.class); //@Parameter(name="Probability change price", defaultValue="20", minValue=1, maxValue=100, step=1) //public int Probability; @Parameter(name="Max change price", defaultValue="10", minValue=1, maxValue=100, step=1) public int MaxChange; private int barsProcessed = 0; private double atrValue = 0; private int atrPeriod = 14; private int relativeMaxChange = -1; //bendedit: we need some persistant variables so we can track price and allow it to wander away from original data private double lastbid=0; private double lastorgbid=0; private long lastticktime=0; //------------------------------------------------------------------------ //------------------------------------------------------------------------ //------------------------------------------------------------------------ public RandomizeHistoryData2() { super(MonteCarloTestTypes.ModifyData); } //------------------------------------------------------------------------ public void modifyData(IRandomGenerator rng, TickEvent tickEvent, double globalATR) { //double dblProbability = ((double) Probability/ 100.0d); //if(rng.probability(dblProbability)) { // bendedit: I don't see a point in probability of change, lets just always change every tick, it will be much smoother now that we turfed ATR from the equation. // we should change this price double ask = tickEvent.getAsk(); double bid = tickEvent.getBid(); double spread = ask - bid; double tickorgchange=0; long currentticktime = tickEvent.getTime(); //bendedit: check if first tick, if not then set original tick change. if (lastticktime <= currentticktime && lastticktime!=0) { //bendedit: calculate the price change from last original tick to the current tick from original data tickorgchange=bid-lastorgbid; //debug("MC price randomizer", "tickorgchange is: "+tickorgchange); //debug("MC price randomizer", "time is: "+currentticktime); //debug("MC price randomizer", "last time is: "+lastticktime); //debug("MC price randomizer", "EOL"); } else { //bendedit: in case of first tick there is no change. lastbid=bid; tickorgchange=0; } //bendedit:set last original data bid in to variable before we change bid, we only need it to calculate the price change next time. lastorgbid=bid; //bendedit:store the ticktime. lastticktime = currentticktime; int change; if(relativeMaxChange <= 0) { change = rng.nextInt(MaxChange); } else { change = rng.nextInt(relativeMaxChange); } double dblChange = ((double) change)/ 10000.0d;  //bendedit: Modding every tick and allowing price to move far away from original data therefore we need to use much smaller adjustments. //bendedit: I chose a percent of a percent //bendedit: changed from using ATR to just use tick price change of original data. double priceChange = tickorgchange * dblChange; //bendedit: set the working bid relative to the last bid instead of itself //bid = (rng.nextInt(2) == 0 ? bid + priceChange : bid - priceChange); bid = (rng.nextInt(2) == 0 ? lastbid + tickorgchange + priceChange : lastbid + tickorgchange - priceChange); tickEvent.setBid(bid); tickEvent.setAsk(bid + spread); //bendedit:set last bid in to variable for next time. lastbid = bid;  //} } //------------------------------------------------------------------------ public void initSettings(SettingsMap settings) { super.initSettings(settings); // compute relative Max Change according to chart TF and precision ChartSetup chartSetup = (ChartSetup) settings.get(SettingsKeys.BacktestChart); if(chartSetup != null) { int testPrecision = chartSetup.getTestPrecision(); if(testPrecision == Precisions.SelectedTF) { // do nothing for selected TF precision relativeMaxChange = MaxChange; return; } // it is higher precision, set MaxChange to 1/3 of the value // because the change is applied o every minute bar / tick we have to lower the MaxChange  // so that the resulting full bar in target timeframe (for example H1) isn't changed too much //bendedit: Hopefully we don't need this adjustment anymore since we aren't using globalATR which is inflated by higher timeframes. deviding by 3 arbitrarily was suspect anyways. If we still need to adjust, I'll hopefully find a better way. //bendedit: Now that we are doing change % instead of atr %, we may not need any further adjustments relative to precision or TF. Turned off this equalizer for now. //relativeMaxChange = MaxChange / 3; relativeMaxChange = MaxChange; if(relativeMaxChange <= 0) { relativeMaxChange = 1; } } } //------------------------------------------------------------------------ /** * Clones this MC retest object * * @return the clone * @throws Exception the exception */ @Override public RandomizeHistoryData2 getClone() throws Exception { RandomizeHistoryData2 mc = new RandomizeHistoryData2(); mc.MaxChange = this.MaxChange; return mc; } }



g
#25

Gin

05.12.2020 16:58
Voted for this task.
b
#26

bentra

06.12.2020 17:22
Hi Marc, it looks like there is a problem with my data randomizer script when trading options are turned on such as Exit Friday. Is it possible the trade may be exiting because of "Exit Friday"  before the last tick has a chance to be modified by my script? If so this would cause the last tick to be nonsense right before the trade is exited.

My script will only work properly if modifydata is called before everything else. It should also be called even outside of trading hours.

EDIT: maybe I can override ontick to make sure modifydata gets called first otherwise we will need new versions of all the trading options scripts to mod the data before the exit. I'llk work on it tonight.
MF
#27

Mark Fric

07.12.2020 12:31
I didn't notice any problems running it with trading options turned on. MOdification of data is done before any trading options are applied.


Please attach the strategy where you see this problem and I'll check it.

b
#28

bentra

08.12.2020 04:48
OK. randomize data bendx mod v1.1:
-potential rounding errors fixed
-default setting to 40%


/*  * Copyright (c) 2017-2018, StrategyQuant - All rights reserved.  *  * Code in this file was made in a good faith that it is correct and does what it should.  * If you found a bug in this code OR you have an improvement suggestion OR you want to include  * your own code snippet into our standard library please contact us at:  * https://roadmap.strategyquant.com  *  * This code can be used only within StrategyQuant products.  * Every owner of valid (free, trial or commercial) license of any StrategyQuant product  * is allowed to freely use, copy, modify or make derivative work of this code without limitations,  * to be used in all StrategyQuant products and share his/her modifications or derivative work  * with the StrategyQuant community.  *  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,  * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR  * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES  * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  *  */ package SQ.MonteCarlo.Retest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.strategyquant.lib.*; import com.strategyquant.datalib.*; import com.strategyquant.datalib.consts.Precisions; import com.strategyquant.tradinglib.*; @ClassConfig(name="Randomize history data", display="Randomize history bendx mod v1.1, with max change #MaxChange# % of TICK PRICE CHANGES") @Help("<b>Note!</b>If you choose this option then robustness tests will be tested with Selected Timeframe precision, while original strategy will be tested with configured precision.<br/>This might cause difference in results between original strategy and simulations because of different precision.<br/>To avoid this, use Selected Timeframe precision in Setings : Data.") public class RandomizeHistoryData2 extends MonteCarloRetest {     public static final Logger Log = LoggerFactory.getLogger(RandomizeHistoryData2.class);          //@Parameter(name="Probability change price", defaultValue="20", minValue=1, maxValue=100, step=1)     //public int Probability;          @Parameter(name="Max change price", defaultValue="40", minValue=0, maxValue=1000, step=1)     public int MaxChange;          private int barsProcessed = 0;     private double atrValue = 0;     private int atrPeriod = 14;          private int relativeMaxChange = -1;               //bendedit: we need some persistant variables so we can track price and allow it to wander away from original data     private double lastbid=0;     private double lastorgbid=0;     private long lastticktime=0;     //digits for symbol for rounding     private int SymDigMod;          //------------------------------------------------------------------------     //------------------------------------------------------------------------     //------------------------------------------------------------------------     public RandomizeHistoryData2() {         super(MonteCarloTestTypes.ModifyData);     }          //------------------------------------------------------------------------     public void modifyData(IRandomGenerator rng, TickEvent tickEvent, double globalATR) {         //double dblProbability = ((double) Probability/ 100.0d);                               //if(rng.probability(dblProbability)) {             // bendedit: I don't see a point in probability of change, lets just always change every tick, it will be much smoother now that we turfed ATR from the equation.             // we should change this price             double ask = tickEvent.getAsk();             double bid = tickEvent.getBid();             double spread = ask - bid;             double tickorgchange=0;             long currentticktime = tickEvent.getTime();                          //bendedit: check if first tick, if not then set original tick change.             if (lastticktime <= currentticktime && lastticktime!=0) {                 //bendedit: calculate the price change from last original tick to the current tick from original data                 tickorgchange=bid-lastorgbid;                 //debug("MC price randomizer", "tickorgchange is: "+tickorgchange);                 //debug("MC price randomizer", "time is: "+currentticktime);                 //debug("MC price randomizer", "last time is: "+lastticktime);                 //debug("MC price randomizer", "EOL");             } else { //bendedit: in case of first tick there is no change.                 lastbid=bid;                 tickorgchange=0;             }                          //bendedit:set last original data bid in to variable before we change bid, we only need it to calculate the price change next time.             lastorgbid=bid;                          //bendedit:store the ticktime.             lastticktime = currentticktime;                          int change;                          if(relativeMaxChange <= 0) {                 change = rng.nextInt(MaxChange);             } else {                 change = rng.nextInt(relativeMaxChange);             }                          double dblChange = ((double) change)/ 10000.0d;              //bendedit: changed from using ATR to just use tick price change of original data.             double priceChange = tickorgchange * dblChange;                                       //bendedit: set the working bid relative to the last bid instead of itself             //bid = (rng.nextInt(2) == 0 ? bid + priceChange : bid - priceChange);             bid = (rng.nextInt(2) == 0 ? lastbid + tickorgchange + priceChange : lastbid + tickorgchange - priceChange);             //bendedit:set last bid in to variable for next time undrounded             lastbid = bid;              //round to proper tick for engine             bid = SQUtils.round(bid, SymDigMod);             //set modded bid and ask for further processing             tickEvent.setBid(bid);             tickEvent.setAsk(bid + spread);                                                //}     }     //------------------------------------------------------------------------          public void initSettings(SettingsMap settings) {         super.initSettings(settings);                  // compute relative Max Change according to chart TF and precision         // Get symbolinfo for digits         ChartSetup chartSetup = (ChartSetup) settings.get(SettingsKeys.BacktestChart);         ChartDef chart = chartSetup.getMainChart();         InstrumentInfo symbolInfo = chart.getSymbolInfo();         SymDigMod = symbolInfo.decimals;         // debug("MC price randomizer", "EOL:" + SymDigMod );         if(chartSetup != null) {             int testPrecision = chartSetup.getTestPrecision();                          if(testPrecision == Precisions.SelectedTF) {                 // do nothing for selected TF precision                 relativeMaxChange = MaxChange;                 return;             }                          // it is higher precision, set MaxChange to 1/3 of the value             // because the change is applied o every minute bar / tick we have to lower the MaxChange              // so that the resulting full bar in target timeframe (for example H1) isn't changed too much                          //bendedit: Hopefully we don't need this adjustment anymore since we aren't using globalATR which is inflated by higher timeframes. deviding by 3 arbitrarily was suspect anyways. If we still need to adjust, I'll hopefully find a better way.             //bendedit: Now that we are doing change % instead of atr %, we may not need any further adjustments relative to precision or TF. Turned off this equalizer for now.             //relativeMaxChange = MaxChange / 3;             relativeMaxChange = MaxChange;             if(relativeMaxChange <= 0) {                 relativeMaxChange = 1;             }                      }     }     //------------------------------------------------------------------------          /**      * Clones this MC retest object      *      * @return the clone      * @throws Exception the exception      */     @Override     public RandomizeHistoryData2 getClone() throws Exception {         RandomizeHistoryData2 mc = new RandomizeHistoryData2();         mc.MaxChange = this.MaxChange;                  return mc;              }    }


MF
#29

Mark Fric

09.12.2020 12:08

Status changed from In progress to Fixed

ok, I added it into standard SQ distribution undr the name "Randomize history data (fixed range)"


I refactored the code a little, but with no changes in functionality.


Votes: +8

Drop files to upload

or

choose files

Max size: 5MB

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

...
Wait please