|
Attention! Read the forum rules carefully before posting a topic.
Submit JForex API function requests in this forum only. Off topics are strictly forbidden.
Any topics which do not satisfy these rules will be deleted.
ITesterClient, optimize the code for parallel strategy backtesting |
nicofr0707
|
Post subject: ITesterClient, optimize the code for parallel strategy backtesting |
Post rating: 0
|
Posted: Wed 12 Feb, 2014, 17:55
|
|
User rating: 5
Joined: Fri 02 Sep, 2011, 10:08 Posts: 157 Location: FranceFrance
|
Hi, I just figured out how to backtest strategies in parallel with ITesterClient and the MA_Play.java example provided with the JFOREX SDK. How would you optimize things in order to use close to 100% of the CPU ? I never managed to stay above 50-60% (I7 4770k 4 cores / 4 threads). Please see the following code, I'm starting the same strategy with a different parameter through a loop. The higher the number of strategies loaded, the higher the number of threads is in the Windows task manager (+6000 threads for 200 strategies) and the higher is the Ram usage. But CPU load still remains at 50-60% Why ? Thanks for your help and knowledge. /* * Copyright (c) 2009 Dukascopy (Suisse) SA. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * -Redistribution of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * -Redistribution in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Dukascopy (Suisse) SA or the names of contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * This software is provided "AS IS," without a warranty of any kind. ALL * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. DUKASCOPY (SUISSE) SA ("DUKASCOPY") * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL DUKASCOPY OR ITS LICENSORS BE LIABLE FOR ANY LOST * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, * EVEN IF DUKASCOPY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. */ package singlejartest;
import com.dukascopy.api.Instrument; import com.dukascopy.api.LoadingProgressListener; import com.dukascopy.api.OfferSide; import com.dukascopy.api.Period; import com.dukascopy.api.system.ISystemListener; import com.dukascopy.api.system.ITesterClient; import com.dukascopy.api.system.TesterFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory;
import java.io.File; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashSet; import java.util.Set; import java.util.TimeZone; import java.util.concurrent.Future;
/** * This small program demonstrates how to initialize Dukascopy tester and start * a strategy */ public class TesterMain {
private static final Logger LOGGER = LoggerFactory.getLogger(Main.class);
//url of the DEMO jnlp private static String jnlpUrl = "https://www.dukascopy.com/client/demo/jclient/jforex.jnlp"; //user name private static String userName = "****"; //password private static String password = "****";
public static void main(String[] args) throws Exception { //get the instance of the IClient interface final ITesterClient client = TesterFactory.getDefaultInstance(); //set the listener that will receive system events client.setSystemListener(new ISystemListener() { @Override public void onStart(long processId) { LOGGER.info("Strategy started: " + processId); }
@Override public void onStop(long processId) { LOGGER.info("Strategy stopped: " + processId); File reportFile = new File("C:\\report.html"); try { client.createReport(processId, reportFile); } catch (Exception e) { LOGGER.error(e.getMessage(), e); } if (client.getStartedStrategies().size() == 0) { System.exit(0); } }
@Override public void onConnect() { LOGGER.info("Connected"); }
@Override public void onDisconnect() { //tester doesn't disconnect } }); // setting the cacheFolder File CacheFolder = new File("C:/JforexSDKCache/.cache"); client.setCacheDirectory(CacheFolder);
LOGGER.info("Connecting..."); //connect to the server using jnlp, user name and password //connection is needed for data downloading client.connect(jnlpUrl, userName, password);
//wait for it to connect int i = 10; //wait max ten seconds while (i > 0 && !client.isConnected()) { Thread.sleep(1000); i--; } if (!client.isConnected()) { LOGGER.error("Failed to connect Dukascopy servers"); System.exit(1); }
//set instruments that will be used in testing Set<Instrument> instruments = new HashSet<Instrument>(); instruments.add(Instrument.EURUSD); LOGGER.info("Subscribing instruments..."); client.setSubscribedInstruments(instruments); //setting initial deposit client.setInitialDeposit(Instrument.EURUSD.getSecondaryCurrency(), 100000);
// final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
Date dateFrom = dateFormat.parse("2013/01/01 00:00:00"); Date dateTo = dateFormat.parse("2014/01/01 00:00:00");
//client.setDataInterval(ITesterClient.DataLoadingMethod.ALL_TICKS, dateFrom.getTime(), dateTo.getTime()); client.setDataInterval(Period.ONE_MIN, OfferSide.BID, ITesterClient.InterpolationMethod.FOUR_TICKS ,dateFrom.getTime(), dateTo.getTime()); //load data LOGGER.info("Downloading data"); Future<?> future = client.downloadData(null); //wait for downloading to complete future.get();
//workaround for LoadNumberOfCandlesAction for JForex-API versions > 2.6.64 Thread.sleep(5000);
for (int j = 0; j < 80; j++) {
MA_Play strategy1 = new MA_Play(); strategy1.testParam01 = j;
//start the strategy LOGGER.info("Starting strategy"); client.startStrategy(strategy1, new LoadingProgressListener() { @Override public void dataLoaded(long startTime, long endTime, long currentTime, String information) { //LOGGER.info(information); }
@Override public void loadingFinished(boolean allDataLoaded, long startTime, long endTime, long currentTime) { }
@Override public boolean stopJob() { return false; } }); //now it's running } } }
|
|
|
|
|
API Support
|
Post subject: Re: ITesterClient, optimize the code for parallel strategy backtesting |
Post rating: 0
|
Posted: Fri 14 Feb, 2014, 09:51
|
|
User rating: ∞
Joined: Fri 31 Aug, 2007, 09:17 Posts: 6139
|
To reach 100% the of the CPU usage the ITesterClient should keep all of your 4 processors busy at all times, which it is obviously not doing and it should not be doing this. You should be able reach 100% CPU if you ran 4 instances of the following program: public class WhileTrue { public static void main(String[] args) { while(true){} } }
Also mind that even though you are starting the strategies in a cycle, in ITesterClient only one strategy at a time is being back-tested (in IClient in comparison they run in parallel). If you wish to back-test multiple strategies in parallel, you need to run them from separate ITesterClient instances each of which get ran from a separate process.
|
|
|
|
|
nicofr0707
|
Post subject: Re: ITesterClient, optimize the code for parallel strategy backtesting |
Post rating: 0
|
Posted: Mon 17 Feb, 2014, 17:24
|
|
User rating: 5
Joined: Fri 02 Sep, 2011, 10:08 Posts: 157 Location: FranceFrance
|
Hi support, I've figured out a lot of things. One thing bothers me, backtesting in JForex is faster than in the standalone API with ITesterClient : For my test I tried to backtest only one strategy. - JForex with "Optimization" selected took about 20 minutes with a CPU load of 10-15% - Standalone API with ITesterClient with no GUI (and no console print) took about 30 minutes with a CPU load of 15-30% How is that possible ? It's a huge difference with even more CPU usage. I tried both of these startStrategy calls, it doesn't make that much difference : public long startStrategy(IStrategy strategy)
public long startStrategy(IStrategy strategy, LoadingProgressListener testerProgressListener, ITesterExecution testerExecution, ITesterUserInterface testerUserInterface) Could you please give me some advice to solve this ? Thanks
|
|
|
|
|
API Support
|
Post subject: Re: ITesterClient, optimize the code for parallel strategy backtesting |
Post rating: 0
|
Posted: Thu 20 Feb, 2014, 15:13
|
|
User rating: ∞
Joined: Fri 31 Aug, 2007, 09:17 Posts: 6139
|
Could you please provide an example ITesterClient program, an example strategy and Historical Tester setting and optimization setting printscreen?
|
|
|
|
|
nicofr0707
|
Post subject: Re: ITesterClient, optimize the code for parallel strategy backtesting |
Post rating: 0
|
Posted: Mon 24 Feb, 2014, 19:03
|
|
User rating: 5
Joined: Fri 02 Sep, 2011, 10:08 Posts: 157 Location: FranceFrance
|
Hello, I did further testing and I may know why the JForex optimizer is faster than API ITesterClient's public long startStrategy(IStrategy strategy) AND even faster than the JForex tester itself (without Visual mode nor Optimization checked). Let's assume we test with 1 minute candles, BID and 4 ticks at OHLC. The tester and ITesterClient are writing very large amounts of 1 minute intraperiod cache files. This is causing the computer to slow down because of heavy disk utilization. Moreover, this intraperiod cache has to be flushed after each restart, it's very painful after a multiyear, multicurrency backtest of 100GB ! In opposition, JForex Tester with "Optimization" checked doesn't write any intraperiod 1 minute cache file. This is for sure the reason why it is faster and does use less cpu than all other backtest method. In the case exposed in the first post, starting multiple strategies with ITesterClient in a loop like the following code, is creating as much duplicated intraperiod folders as they are strategies started. for (int j = 0; j < 80; j++) { MA_Play strategy1 = new MA_Play();
//start the strategy LOGGER.info("Starting strategy"); client.startStrategy(strategy1)
This creates for each currency pair : intraperiod intraperiod1 intraperiod2 intraperiod3 ... ... intraperiod80 Each intraperiod is dupplicated and has the same data for hundred's of MB on the hard drive ! I don't see the need to duplicate all this data since ITesterClient has only one instance. What can we do to have the same behavior than the tester with Optimization checked ? Thanks for your support. Nicolas
|
|
|
|
|
nicofr0707
|
Post subject: Re: ITesterClient, optimize the code for parallel strategy backtesting |
Post rating: 0
|
Posted: Tue 25 Feb, 2014, 08:59
|
|
User rating: 5
Joined: Fri 02 Sep, 2011, 10:08 Posts: 157 Location: FranceFrance
|
If I can't desactivate Intraperiod data to be written, is there a way to modify the API in order to write Intraperiod data on an other disk than the cache data disk ?
The idea would be to use RAMDisk software to load Intraperiods in RAM with a program periodically flushing the unused data.
|
|
|
|
|
nicofr0707
|
Post subject: Re: ITesterClient, optimize the code for parallel strategy backtesting |
Post rating: 0
|
Posted: Wed 26 Feb, 2014, 17:35
|
|
User rating: 5
Joined: Fri 02 Sep, 2011, 10:08 Posts: 157 Location: FranceFrance
|
Hi support, I did start a new topic concerning intraperiod data issues and had a response from the platform support. Since my last messages here are related to the same topic, please see the following link with tests and screenshots. I am looking forward for some solution on this because right now it's impossible for me to go further with my strategy because of this intraperiod issue. Thanks viewtopic.php?f=85&t=50828&p=78057#p78057
|
|
|
|
|
|
Pages: [
1
]
|
|
|
|
|