Respuesta

Posible nueva forma de aleatorizar datos con %change en lugar de %ATR

5 respuestas

bentra

Cliente, bbp_participante, comunidad, sq-ultimate, 22 respuestas.

Visitar el perfil

hace 3 años #267915

Como aquí: https://roadmap.strategyquant.com/tasks/sq4_7233
y aquí:  https://roadmap.strategyquant.com/tasks/sq4_7350
La forma actual no es perfecta y algunas estrategias pueden explotar la aleatoriedad de los datos históricos algo mientras que otros sufren el sesgo de esta prueba. Creo que esto es debido a la forma en que se utiliza ATR en el algo combinado con el hecho de que la nueva posición aleatoria siempre se basa en el siguiente tick de datos originales (que tendrá un efecto adicional de reversión a la media y mayor x% de ATR aumentará la volatilidad).

En este nuevo método, aleatorizo el % de cambio de precio en lugar del % de ATR y permito que el precio establezca una nueva trayectoria de modo que cada tick se base en el último tick de los datos aleatorizados (permitiendo que el precio se aleje lentamente de los datos originales, eliminando el excesivo efecto de reversión a la media). Esto debería mantener la volatilidad mientras se aleatorizan los datos siempre que el cambio de % sea razonable.

Abro este hilo para la discusión y las pruebas. Es un trabajo en progreso en este momento. No estoy muy familiarizado con java por lo que podría utilizar una mano con el código y con las pruebas.

Tuve tiempo para trabajar en esto hoy y esto es lo que tengo hasta ahora, pero es posible que desee comprobar si hay nuevas versiones más adelante en este hilo a medida que avanzamos y publicar nuevas versiones.

 

 

 

 

 

Que todos tus ajustes sean holgados.


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

0

bentra

Cliente, bbp_participante, comunidad, sq-ultimate, 22 respuestas.

Visitar el perfil

hace 3 años #267956

Vale, parece que esta vez he arreglado bien el error del primer tick.

 

/*
 * Copyright (c) 2017-2018, StrategyQuant - Todos los derechos reservados.
 *
 * Código en este archivo se hizo de buena fe que es correcto y hace lo que debe.
 * Si has encontrado un error en este código O tienes una sugerencia de mejora O quieres incluir
 * su propio fragmento de código en nuestra biblioteca estándar por favor póngase en contacto con nosotros en:
 * https://roadmap.strategyquant.com
 *
 * Este código sólo se puede utilizar en los productos StrategyQuant.
 * Todo propietario de una licencia válida (gratuita, de prueba o comercial) de cualquier producto StrategyQuant
 * está autorizado a utilizar, copiar, modificar o hacer trabajos derivados de este código libremente y sin limitaciones,
 * para ser utilizado en todos los productos StrategyQuant y compartir sus modificaciones o trabajos derivados
 * con la comunidad StrategyQuant.
 *
 * EL SOFTWARE SE PROPORCIONA "TAL CUAL", SIN GARANTÍA DE NINGÚN TIPO, EXPRESA O IMPLÍCITA,
 * INCLUYENDO PERO NO LIMITADO A LAS GARANTÍAS DE COMERCIABILIDAD, IDONEIDAD PARA UN DETERMINADO
 * PROPÓSITO Y NO INFRACCIÓN. EN NINGÚN CASO SERÁN LOS AUTORES RESPONSABLES DE CUALQUIER RECLAMACIÓN, DAÑO
 * U OTRA RESPONSABILIDAD, YA SEA EN UNA ACCIÓN CONTRACTUAL, EXTRACONTRACTUAL O DE OTRO TIPO, QUE SURJA DE,
 * O EN RELACIÓN CON EL SOFTWARE O EL USO U OTRAS OPERACIONES CON EL SOFTWARE.
 *
 */
paquete 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="Aleatorizar datos históricos", display="Aleatorizar datos históricos v2.0, con cambio de precio máximo #MaxChange# % de PRECIO")
@Ayuda("<b>¡Atención!</b>Si elige esta opción, las pruebas de robustez se probarán con la precisión del marco temporal seleccionado, mientras que la estrategia original se probará con la precisión configurada.<br/>Esto podría causar diferencias en los resultados entre la estrategia original y las simulaciones debido a la diferente precisión.<br/>Para evitarlo, utilice la precisión Selected Timeframe en Setings : Datos")
public class RandomizeHistoryData2 extends MonteCarloRetest {
	public static final Logger Log = LoggerFactory.getLogger(RandomizeHistoryData2.class);
	
	//@Parameter(name="Probabilidad cambio precio", defaultValue="20", minValue=1, maxValue=100, step=1)
	//public int Probabilidad;
	
	@Parameter(name="Precio máximo de cambio", defaultValue="10", minValue=1, maxValue=100, step=1)
	public int CambioMáx;
	
	int privado barsProcessed = 0;
	private double atrValue = 0;
	privado int atrPeriod = 14;
	
	privado int relativeMaxChange = -1;
	
	
	//bendedit: necesitamos algunas variables persistentes para poder seguir el precio y permitir que se aleje de los datos originales
	private double lastbid=0;
	private double lastorgbid=0;
	private long lastticktime=0;
	
	
	//------------------------------------------------------------------------
	//------------------------------------------------------------------------
	//------------------------------------------------------------------------

	public AleatorizarHistoriaDatos2() {
		super(MonteCarloTestTypes.ModificarDatos);
	}
	
	//------------------------------------------------------------------------

	public void modificarDatos(IRandomGenerator rng, TickEvent tickEvent, double globalATR) {
		//double dblProbability = ((double) Probability/ 100.0d);
		
			
		//if(rng.probability(dblProbability)) {
			// bendedit: Yo don&#039;t ver un punto en la probabilidad de cambio, vamos a cambiar siempre cada tick, será mucho más suave ahora que turfed ATR de la ecuación.

			// debemos cambiar este precio

			double ask = tickEvent.getAsk();
			double bid = tickEvent.getBid();
			double spread = ask - bid;
			double tickorgchange=0;
			long currentticktime = tickEvent.getTime();
			
			//bendedit: comprueba si es el primer tick, si no entonces establece el cambio de 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 tus ajustes sean holgados.


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

0

bentra

Cliente, bbp_participante, comunidad, sq-ultimate, 22 respuestas.

Visitar el perfil

hace 3 años #267958

Este funciona en b130

/*
 * Copyright (c) 2017-2018, StrategyQuant - Todos los derechos reservados.
 *
 * Código en este archivo se hizo de buena fe que es correcto y hace lo que debe.
 * Si has encontrado un error en este código O tienes una sugerencia de mejora O quieres incluir
 * su propio fragmento de código en nuestra biblioteca estándar por favor póngase en contacto con nosotros en:
 * https://roadmap.strategyquant.com
 *
 * Este código sólo se puede utilizar en los productos StrategyQuant.
 * Todo propietario de una licencia válida (gratuita, de prueba o comercial) de cualquier producto StrategyQuant
 * está autorizado a utilizar, copiar, modificar o hacer trabajos derivados de este código libremente y sin limitaciones,
 * para ser utilizado en todos los productos StrategyQuant y compartir sus modificaciones o trabajos derivados
 * con la comunidad StrategyQuant.
 *
 * EL SOFTWARE SE PROPORCIONA "TAL CUAL", SIN GARANTÍA DE NINGÚN TIPO, EXPRESA O IMPLÍCITA,
 * INCLUYENDO PERO NO LIMITADO A LAS GARANTÍAS DE COMERCIABILIDAD, IDONEIDAD PARA UN DETERMINADO
 * PROPÓSITO Y NO INFRACCIÓN. EN NINGÚN CASO SERÁN LOS AUTORES RESPONSABLES DE CUALQUIER RECLAMACIÓN, DAÑO
 * U OTRA RESPONSABILIDAD, YA SEA EN UNA ACCIÓN CONTRACTUAL, EXTRACONTRACTUAL O DE OTRO TIPO, QUE SURJA DE,
 * O EN RELACIÓN CON EL SOFTWARE O EL USO U OTRAS OPERACIONES CON EL SOFTWARE.
 *
 */
paquete 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="Aleatorizar datos históricos", display="Aleatorizar datos históricos v2.0, con cambio máximo #MaxChange# % de CAMBIOS DE PRECIO DE TICK")
@Ayuda("<b>¡Atención!</b>Si elige esta opción, las pruebas de robustez se probarán con la precisión del marco temporal seleccionado, mientras que la estrategia original se probará con la precisión configurada.<br/>Esto podría causar diferencias en los resultados entre la estrategia original y las simulaciones debido a la diferente precisión.<br/>Para evitarlo, utilice la precisión Selected Timeframe en Setings : Datos")
public class RandomizeHistoryData2 extends MonteCarloRetest {
	public static final Logger Log = LoggerFactory.getLogger(RandomizeHistoryData2.class);
	
	//@Parameter(name="Probabilidad cambio precio", defaultValue="20", minValue=1, maxValue=100, step=1)
	//public int Probabilidad;
	
	@Parameter(name="Precio máximo de cambio", defaultValue="10", minValue=1, maxValue=100, step=1)
	public int CambioMáx;
	
	int privado barsProcessed = 0;
	private double atrValue = 0;
	privado int atrPeriod = 14;
	
	privado int relativeMaxChange = -1;
	
	
	//bendedit: necesitamos algunas variables persistentes para poder seguir el precio y permitir que se aleje de los datos originales
	private double lastbid=0;
	private double lastorgbid=0;
	private long lastticktime=0;
	
	
	//------------------------------------------------------------------------
	//------------------------------------------------------------------------
	//------------------------------------------------------------------------

	public AleatorizarHistoriaDatos2() {
		super(MonteCarloTestTypes.ModificarDatos);
	}
	
	//------------------------------------------------------------------------

	public void modificarDatos(IRandomGenerator rng, TickEvent tickEvent, double globalATR) {
		//double dblProbability = ((double) Probability/ 100.0d);
		
			
		//if(rng.probability(dblProbability)) {
			// bendedit: Yo don&#039;t ver un punto en la probabilidad de cambio, vamos a cambiar siempre cada tick, será mucho más suave ahora que turfed ATR de la ecuación.

			// debemos cambiar este precio

			double ask = tickEvent.getAsk();
			double bid = tickEvent.getBid();
			double spread = ask - bid;
			double tickorgchange=0;
			long currentticktime = tickEvent.getTime();
			
			//bendedit: comprueba si es el primer tick, si no entonces establece el cambio de 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 tus ajustes sean holgados.


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

0

clonex / Ivan Hudec

Cliente, bbp_participant, comunidad, sq-ultimate, colaborador, autor, editor, 271 respuestas.

Visitar el perfil

hace 3 años #267976

Hola Bendex. Vamos a probarlo en unos pocos miles de estrategias y publicar aquí los resultados. Gracias por este fragmento,

0

bentra

Cliente, bbp_participante, comunidad, sq-ultimate, 22 respuestas.

Visitar el perfil

hace 3 años #267979

Muchas gracias, me preocupan las posibles diferencias en los distintos mercados, tal vez por el redondeo. También los efectos de diferentes plazos y precisiones.

Que todos tus ajustes sean holgados.


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

0

bentra

Cliente, bbp_participante, comunidad, sq-ultimate, 22 respuestas.

Visitar el perfil

hace 3 años #268127

La nueva versión está aquí:
https://roadmap.strategyquant.com/tasks/sq4_7233
-corrección de posibles errores de redondeo
-ajuste por defecto 40%

Cualquier ayuda en las pruebas es apreciada, por favor publique cualquier problema de configuraciones/estratos en ese ticket.

Que todos tus ajustes sean holgados.


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

0

Viendo 5 respuestas - de la 1 a la 5 (de un total de 5)