Resposta

Possível nova maneira de randomizar dados com %change em vez de %ATR

5 respostas

bentra

Cliente, bbp_participante, comunidade, sq-ultimate, 22 respostas.

Perfil da visita

3 anos atrás #267915

Como aqui: https://roadmap.strategyquant.com/tasks/sq4_7233
e aqui:  https://roadmap.strategyquant.com/tasks/sq4_7350
A maneira atual não é perfeita e algumas estratégias podem explorar o algoritmo de randomização de dados históricos, enquanto outras sofrem com o viés desse teste. Acredito que isso se deva à maneira como o ATR é usado no algoritmo, combinado com o fato de que a nova posição aleatória sempre se baseia no próximo tick de dados original (que terá um efeito extra de reversão à média e um x% de ATR mais alto aumentará a volatilidade).

Nesse novo método, eu randomizo o % da mudança de preço em vez do % do ATR e permito que o preço defina um novo caminho para que cada tick seja baseado no último tick dos dados randomizados (permitindo que o preço se afaste lentamente dos dados originais, eliminando a reversão excessiva ao efeito médio). Isso deve manter a volatilidade durante a randomização dos dados, desde que a alteração do % seja razoável.

Abri este tópico para discussão e teste. No momento, trata-se de um trabalho em andamento. Não tenho muita familiaridade com Java, portanto, poderia me ajudar com o código e com os testes.

Tive tempo de trabalhar nisso hoje e aqui está o que tenho até agora, mas você pode querer verificar se há novas versões mais adiante neste tópico, à medida que progredimos e publicamos novas versões.

 

 

 

 

 

Que todos os seus ajustes sejam soltos.


https://www.darwinex.com/darwin/SUG.4.2/

0

bentra

Cliente, bbp_participante, comunidade, sq-ultimate, 22 respostas.

Perfil da visita

3 anos atrás #267956

Parece que, desta vez, corrigi corretamente o erro do primeiro tique

 

/*
 * Copyright (c) 2017-2018, StrategyQuant - Todos os direitos reservados.
 *
 * O código neste arquivo foi criado de boa-fé, garantindo que está correto e faz o que deveria.
 * Se você encontrou um bug neste código OU tem uma sugestão de melhoria OU deseja incluir
 * seu próprio trecho de código em nossa biblioteca padrão, entre em contato conosco em:
 * https://roadmap.strategyquant.com
 *
 * Este código pode ser usado somente em produtos StrategyQuant.
 * Todo proprietário de uma licença válida (gratuita, de teste ou comercial) de qualquer produto StrategyQuant
 * tem permissão para usar, copiar, modificar ou fazer trabalhos derivados desse código livremente, sem limitações,
 * para ser usado em todos os produtos StrategyQuant e compartilhar suas modificações ou trabalhos derivados
 * com a comunidade StrategyQuant.
 *
 * O SOFTWARE É FORNECIDO "COMO ESTÁ", SEM GARANTIA DE QUALQUER TIPO, EXPRESSA OU IMPLÍCITA,
 * INCLUINDO, MAS NÃO SE LIMITANDO A, GARANTIAS DE COMERCIALIZAÇÃO, ADEQUAÇÃO A UM DETERMINADO
 * FINALIDADE ESPECÍFICA E NÃO VIOLAÇÃO. EM NENHUMA HIPÓTESE OS AUTORES SERÃO RESPONSÁVEIS POR QUALQUER REIVINDICAÇÃO, DANO
 * OU OUTRA RESPONSABILIDADE, SEJA EM UMA AÇÃO DE CONTRATO, ATO ILÍCITO OU DE OUTRA FORMA, DECORRENTE DE,
 * DECORRENTES DE, FORA DE OU EM CONEXÃO COM O SOFTWARE OU COM O USO OU OUTRAS NEGOCIAÇÕES COM O 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="Randomizar dados do histórico", display="Randomizar dados do histórico v2.0, com alteração máxima de preço #MaxChange# % de PRICE")
@Help("<b>Nota!</b>Se você escolher essa opção, os testes de robustez serão testados com a precisão do período de tempo selecionado, enquanto a estratégia original será testada com a precisão configurada.<br/>Isso pode causar diferenças nos resultados entre a estratégia original e as simulações devido à precisão diferente.<br/>Para evitar isso, use a precisão do período de tempo selecionado em Setings : Data.")
classe pública RandomizeHistoryData2 extends MonteCarloRetest {
	logger final estático público Logger = 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: precisamos de algumas variáveis persistentes para que possamos rastrear o preço e permitir que ele se afaste dos dados originais
	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);
		
			
		//se(rng.probability(dblProbability)) {
			// bendedit: I don&#039;t see a point in probability of change, lets just always change every tick, it will be much smooth more now that we turfed ATR from the equation.

			// devemos alterar esse preço

			double ask = tickEvent.getAsk();
			double bid = tickEvent.getBid();
			double spread = ask - bid;
			double tickorgchange=0;
			long currentticktime = tickEvent.getTime();
			
			//bendedit: verifica se é o primeiro tick; caso contrário, define a alteração do tick original.
			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&#039;t changed too much
			
			//bendedit: Hopefully we don&#039;t need this adjustment anymore since we aren&#039;t using globalATR which is inflated by higher timeframes. deviding by 3 arbitrarily was suspect anyways. If we still need to adjust, I&#039;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;
			}
			
		}
	}	

}

 

Que todos os seus ajustes sejam soltos.


https://www.darwinex.com/darwin/SUG.4.2/

0

bentra

Cliente, bbp_participante, comunidade, sq-ultimate, 22 respostas.

Perfil da visita

3 anos atrás #267958

Este funciona no b130

/*
 * Copyright (c) 2017-2018, StrategyQuant - Todos os direitos reservados.
 *
 * O código neste arquivo foi criado de boa-fé, garantindo que está correto e faz o que deveria.
 * Se você encontrou um bug neste código OU tem uma sugestão de melhoria OU deseja incluir
 * seu próprio trecho de código em nossa biblioteca padrão, entre em contato conosco em:
 * https://roadmap.strategyquant.com
 *
 * Este código pode ser usado somente em produtos StrategyQuant.
 * Todo proprietário de uma licença válida (gratuita, de teste ou comercial) de qualquer produto StrategyQuant
 * tem permissão para usar, copiar, modificar ou fazer trabalhos derivados desse código livremente, sem limitações,
 * para ser usado em todos os produtos StrategyQuant e compartilhar suas modificações ou trabalhos derivados
 * com a comunidade StrategyQuant.
 *
 * O SOFTWARE É FORNECIDO "COMO ESTÁ", SEM GARANTIA DE QUALQUER TIPO, EXPRESSA OU IMPLÍCITA,
 * INCLUINDO, MAS NÃO SE LIMITANDO A, GARANTIAS DE COMERCIALIZAÇÃO, ADEQUAÇÃO A UM DETERMINADO
 * FINALIDADE ESPECÍFICA E NÃO VIOLAÇÃO. EM NENHUMA HIPÓTESE OS AUTORES SERÃO RESPONSÁVEIS POR QUALQUER REIVINDICAÇÃO, DANO
 * OU OUTRA RESPONSABILIDADE, SEJA EM UMA AÇÃO DE CONTRATO, ATO ILÍCITO OU DE OUTRA FORMA, DECORRENTE DE,
 * DECORRENTES DE, FORA DE OU EM CONEXÃO COM O SOFTWARE OU COM O USO OU OUTRAS NEGOCIAÇÕES COM O 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>Nota!</b>Se você escolher essa opção, os testes de robustez serão testados com a precisão do período de tempo selecionado, enquanto a estratégia original será testada com a precisão configurada.<br/>Isso pode causar diferenças nos resultados entre a estratégia original e as simulações devido à precisão diferente.<br/>Para evitar isso, use a precisão do período de tempo selecionado em Setings : Data.")
classe pública RandomizeHistoryData2 extends MonteCarloRetest {
	logger final estático público Logger = 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: precisamos de algumas variáveis persistentes para que possamos rastrear o preço e permitir que ele se afaste dos dados originais
	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);
		
			
		//se(rng.probability(dblProbability)) {
			// bendedit: I don&#039;t see a point in probability of change, lets just always change every tick, it will be much smooth more now that we turfed ATR from the equation.

			// devemos alterar esse preço

			double ask = tickEvent.getAsk();
			double bid = tickEvent.getBid();
			double spread = ask - bid;
			double tickorgchange=0;
			long currentticktime = tickEvent.getTime();
			
			//bendedit: verifica se é o primeiro tick; caso contrário, define a alteração do tick original.
			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&#039;t changed too much
			
			//bendedit: Hopefully we don&#039;t need this adjustment anymore since we aren&#039;t using globalATR which is inflated by higher timeframes. deviding by 3 arbitrarily was suspect anyways. If we still need to adjust, I&#039;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;
		
	}	

}

Que todos os seus ajustes sejam soltos.


https://www.darwinex.com/darwin/SUG.4.2/

0

clonex / Ivan Hudec

Cliente, bbp_participant, comunidade, sq-ultimate, colaborador, autor, editor, 271 respostas.

Perfil da visita

3 anos atrás #267976

Oi Bendex. Vamos testá-lo em alguns milhares de estratégias e publicaremos os resultados aqui. Obrigado por esse snippet,

0

bentra

Cliente, bbp_participante, comunidade, sq-ultimate, 22 respostas.

Perfil da visita

3 anos atrás #267979

Muito obrigado, mas estou preocupado com as possíveis diferenças em diferentes mercados, talvez devido ao arredondamento. Além disso, os efeitos de diferentes cronogramas e precisões.

Que todos os seus ajustes sejam soltos.


https://www.darwinex.com/darwin/SUG.4.2/

0

bentra

Cliente, bbp_participante, comunidade, sq-ultimate, 22 respostas.

Perfil da visita

3 anos atrás #268127

A nova versão está aqui:
https://roadmap.strategyquant.com/tasks/sq4_7233
-Possíveis erros de arredondamento corrigidos
-configuração padrão para 40%

Qualquer ajuda nos testes é bem-vinda. Publique quaisquer configurações/estratos problemáticos nesse tíquete.

Que todos os seus ajustes sejam soltos.


https://www.darwinex.com/darwin/SUG.4.2/

0

Visualizando 5 respostas - 1 até 5 (de um total de 5)