Risposta

Possibile nuovo modo per randomizzare i dati con %change invece di %ATR

5 risposte

bentra

Cliente, bbp_partecipante, comunità, sq-ultimate, 22 risposte.

Visita il profilo

3 anni fa #267915

Come qui: https://roadmap.strategyquant.com/tasks/sq4_7233
e qui:  https://roadmap.strategyquant.com/tasks/sq4_7350
Il metodo attuale non è perfetto e alcune strategie possono sfruttare l'algoritmo di randomizzazione dei dati storici mentre altre soffrono della distorsione di questo test. Credo che ciò sia dovuto al modo in cui l'ATR viene utilizzato nell'algoritmo, combinato con il fatto che la nuova posizione randomizzata si basa sempre sul successivo tick dei dati originali (il che avrà un ulteriore effetto di ritorno alla media e un x% più alto dell'ATR aumenterà la volatilità).

In questo nuovo metodo, randomizzo il % della variazione di prezzo invece del % dell'ATR e permetto al prezzo di impostare un nuovo percorso in modo che ogni tick si basi sull'ultimo tick dei dati randomizzati (permettendo al prezzo di allontanarsi lentamente dai dati originali, eliminando l'eccessivo effetto di inversione alla media). Questo dovrebbe mantenere la volatilità durante la randomizzazione dei dati, a patto che la variazione di % sia ragionevole.

Apro questo thread per la discussione e il test. Al momento si tratta di un lavoro in corso. Non ho molta dimestichezza con java, quindi mi servirebbe una mano con il codice e con i test.

Ho avuto il tempo di lavorarci oggi ed ecco quello che ho finora, ma potreste voler controllare le nuove versioni più avanti in questo thread, man mano che progrediamo e ne pubblichiamo di nuove.

 

 

 

 

 

Che tutti i vostri abiti siano sciolti.


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

0

bentra

Cliente, bbp_partecipante, comunità, sq-ultimate, 22 risposte.

Visita il profilo

3 anni fa #267956

OK sembra che questa volta abbia risolto il bug del primo tick in modo corretto

 

/*
 * Copyright (c) 2017-2018, StrategyQuant - Tutti i diritti riservati.
 *
 * Il codice contenuto in questo file è stato realizzato in buona fede, in modo che sia corretto e faccia ciò che dovrebbe.
 * Se avete trovato un bug in questo codice O avete un suggerimento di miglioramento O volete includere
 * un vostro frammento di codice nella nostra libreria standard, contattateci all'indirizzo:
 * https://roadmap.strategyquant.com
 *
 * Questo codice può essere utilizzato solo all'interno dei prodotti StrategyQuant.
 * Ogni proprietario di una licenza valida (gratuita, di prova o commerciale) di qualsiasi prodotto StrategyQuant
 * è autorizzato a utilizzare, copiare, modificare o fare lavori derivati da questo codice senza limitazioni,
 * da utilizzare in tutti i prodotti StrategyQuant e condividere le sue modifiche o i suoi lavori derivati
 * con la comunità StrategyQuant.
 *
 * IL SOFTWARE VIENE FORNITO "COSÌ COM'È", SENZA GARANZIE DI ALCUN TIPO, ESPRESSE O IMPLICITE,
 * INCLUSE, A TITOLO ESEMPLIFICATIVO, LE GARANZIE DI COMMERCIABILITÀ, IDONEITÀ PER UN PARTICOLARE
 * SCOPO E NON VIOLAZIONE. IN NESSUN CASO GLI AUTORI POTRANNO ESSERE RITENUTI RESPONSABILI PER QUALSIASI RECLAMO, DANNO
 * O ALTRA RESPONSABILITÀ, SIA IN UN'AZIONE CONTRATTUALE, CHE IN UN ILLECITO O ALTRO, DERIVANTI DA,
 * DA O IN RELAZIONE AL SOFTWARE O ALL'USO O AD ALTRI RAPPORTI CON IL SOFTWARE.
 *
 */
pacchetto SQ.MonteCarlo.Retest;

importare org.slf4j.Logger;
importare org.slf4j.LoggerFactory;

import com.strategyquant.lib.*;
import com.strategyquant.datalib.*;
import com.strategyquant.datalib.consts.Precisions;
import com.strategyquant.tradinglib.*;

@ClassConfig(name="Randomizza dati storici", display="Randomizza dati storici v2.0, con variazione massima del prezzo #MaxChange# % di PRICE")
@Help("<b>Nota!</b>Se si sceglie questa opzione, i test di robustezza saranno testati con la precisione del Timeframe selezionato, mentre la strategia originale sarà testata con la precisione configurata.<br/>Questo potrebbe causare differenze nei risultati tra la strategia originale e le simulazioni a causa della diversa precisione.<br/>Per evitare questo problema, utilizzare la precisione del timeframe selezionato in Setings : Data")
public class RandomizeHistoryData2 extends MonteCarloRetest {
	public static final Logger Log = LoggerFactory.getLogger(RandomizeHistoryData2.class);
	
	//@Parametro(name="Probability change price", defaultValue="20", minValue=1, maxValue=100, step=1)
	//public int Probability;
	
	@Parametro(nome="Prezzo massimo di variazione", valore predefinito="10", valore minimo=1, valore massimo=100, passo=1)
	public int MaxChange;
	
	private int barsProcessed = 0;
	private double atrValue = 0;
	private int atrPeriod = 14;
	
	private int relativeMaxChange = -1;
	
	
	//bendedit: abbiamo bisogno di alcune variabili persistenti in modo da poter tracciare il prezzo e permettergli di allontanarsi dai dati originali
	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) {
		//doppio dblProbability = ((double) Probability/ 100.0d);
		
			
		//if(rng.probability(dblProbability)) {
			// bendedit: non&#039;vedo l'utilità della probabilità di cambiamento, cambiamo sempre ogni tick, sarà molto più fluido ora che abbiamo eliminato l'ATR dall'equazione.

			// dovremmo cambiare questo prezzo

			double ask = tickEvent.getAsk();
			double bid = tickEvent.getBid();
			double spread = ask - bid;
			double tickorgchange=0;
			long currentticktime = tickEvent.getTime();
			
			//bendedit: controlla se il primo tick, in caso contrario imposta il cambiamento del tick originale.
			se (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;
			}
			
		}
	}	

}

 

Che tutti i vostri abiti siano sciolti.


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

0

bentra

Cliente, bbp_partecipante, comunità, sq-ultimate, 22 risposte.

Visita il profilo

3 anni fa #267958

Questo funziona su b130

/*
 * Copyright (c) 2017-2018, StrategyQuant - Tutti i diritti riservati.
 *
 * Il codice contenuto in questo file è stato realizzato in buona fede, in modo che sia corretto e faccia ciò che dovrebbe.
 * Se avete trovato un bug in questo codice O avete un suggerimento di miglioramento O volete includere
 * un vostro frammento di codice nella nostra libreria standard, contattateci all'indirizzo:
 * https://roadmap.strategyquant.com
 *
 * Questo codice può essere utilizzato solo all'interno dei prodotti StrategyQuant.
 * Ogni proprietario di una licenza valida (gratuita, di prova o commerciale) di qualsiasi prodotto StrategyQuant
 * è autorizzato a utilizzare, copiare, modificare o fare lavori derivati da questo codice senza limitazioni,
 * da utilizzare in tutti i prodotti StrategyQuant e condividere le sue modifiche o i suoi lavori derivati
 * con la comunità StrategyQuant.
 *
 * IL SOFTWARE VIENE FORNITO "COSÌ COM'È", SENZA GARANZIE DI ALCUN TIPO, ESPRESSE O IMPLICITE,
 * INCLUSE, A TITOLO ESEMPLIFICATIVO, LE GARANZIE DI COMMERCIABILITÀ, IDONEITÀ PER UN PARTICOLARE
 * SCOPO E NON VIOLAZIONE. IN NESSUN CASO GLI AUTORI POTRANNO ESSERE RITENUTI RESPONSABILI PER QUALSIASI RECLAMO, DANNO
 * O ALTRA RESPONSABILITÀ, SIA IN UN'AZIONE CONTRATTUALE, CHE IN UN ILLECITO O ALTRO, DERIVANTI DA,
 * DA O IN RELAZIONE AL SOFTWARE O ALL'USO O AD ALTRI RAPPORTI CON IL SOFTWARE.
 *
 */
pacchetto SQ.MonteCarlo.Retest;

importare org.slf4j.Logger;
importare org.slf4j.LoggerFactory;

import com.strategyquant.lib.*;
import com.strategyquant.datalib.*;
import com.strategyquant.datalib.consts.Precisions;
import com.strategyquant.tradinglib.*;

@ClassConfig(name="Randomizza dati storici", display="Randomizza dati storici v2.0, con variazione massima #MaxChange# % di TICK PRICE CHANGES")
@Help("<b>Nota!</b>Se si sceglie questa opzione, i test di robustezza saranno testati con la precisione del Timeframe selezionato, mentre la strategia originale sarà testata con la precisione configurata.<br/>Questo potrebbe causare differenze nei risultati tra la strategia originale e le simulazioni a causa della diversa precisione.<br/>Per evitare questo problema, utilizzare la precisione del timeframe selezionato in Setings : Data")
public class RandomizeHistoryData2 extends MonteCarloRetest {
	public static final Logger Log = LoggerFactory.getLogger(RandomizeHistoryData2.class);
	
	//@Parametro(name="Probability change price", defaultValue="20", minValue=1, maxValue=100, step=1)
	//public int Probability;
	
	@Parametro(nome="Prezzo massimo di variazione", valore predefinito="10", valore minimo=1, valore massimo=100, passo=1)
	public int MaxChange;
	
	private int barsProcessed = 0;
	private double atrValue = 0;
	private int atrPeriod = 14;
	
	private int relativeMaxChange = -1;
	
	
	//bendedit: abbiamo bisogno di alcune variabili persistenti in modo da poter tracciare il prezzo e permettergli di allontanarsi dai dati originali
	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) {
		//doppio dblProbability = ((double) Probability/ 100.0d);
		
			
		//if(rng.probability(dblProbability)) {
			// bendedit: non&#039;vedo l'utilità della probabilità di cambiamento, cambiamo sempre ogni tick, sarà molto più fluido ora che abbiamo eliminato l'ATR dall'equazione.

			// dovremmo cambiare questo prezzo

			double ask = tickEvent.getAsk();
			double bid = tickEvent.getBid();
			double spread = ask - bid;
			double tickorgchange=0;
			long currentticktime = tickEvent.getTime();
			
			//bendedit: controlla se il primo tick, in caso contrario imposta il cambiamento del tick originale.
			se (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;
		
	}	

}

Che tutti i vostri abiti siano sciolti.


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

0

clonex / Ivan Hudec

Cliente, bbp_partecipante, comunità, sq-ultimate, collaboratore, autore, editore, 271 risposte.

Visita il profilo

3 anni fa #267976

Ciao Bendex. Lo testeremo su alcune migliaia di strategie e pubblicheremo i risultati. Grazie per questo snippet,

0

bentra

Cliente, bbp_partecipante, comunità, sq-ultimate, 22 risposte.

Visita il profilo

3 anni fa #267979

Grazie, mi preoccupano le potenziali differenze su mercati diversi, forse dovute all'arrotondamento. Anche gli effetti dei diversi timeframe e delle diverse precisioni.

Che tutti i vostri abiti siano sciolti.


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

0

bentra

Cliente, bbp_partecipante, comunità, sq-ultimate, 22 risposte.

Visita il profilo

3 anni fa #268127

La nuova versione è qui:
https://roadmap.strategyquant.com/tasks/sq4_7233
-Correzione di potenziali errori di arrotondamento
-Impostazione predefinita su 40%

Qualsiasi aiuto nei test è apprezzato, si prega di inviare qualsiasi problema di configurazione/strato a questo ticket.

Che tutti i vostri abiti siano sciolti.


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

0

Stai visualizzando 5 risposte - da 1 a 5 (di 5 totali)