Dukascopy
 
 
Wiki JStore Search Login

Attention! Read the forum rules carefully before posting a topic.

    Try to find an answer in Wiki before asking a question.
    Submit programming questions in this forum only.
    Off topics are strictly forbidden.

Any topics which do not satisfy these rules will be deleted.

ITesterClient run strategy from command line
 Post subject: ITesterClient run strategy from command line Post rating: 0   New post Posted: Sat 29 Dec, 2012, 15:22 
User avatar

User rating: 6
Joined: Thu 19 May, 2011, 11:14
Posts: 235
Location: South Africa,
As part of the documentation on ITesterClient and associated API, it would be *very* useful to have a sample application such as the following:

A command-line tool for invoking a single back-test from the shell, where the following are specified by command-line arguments:
  • start date
  • end date
  • instrument
  • strategy file path
  • strategy parameter xml file path
  • etc.


 
 Post subject: Re: ITesterClient sample application Post rating: 0   New post Posted: Mon 07 Jan, 2013, 09:27 
User avatar

User rating:
Joined: Fri 31 Aug, 2007, 09:17
Posts: 6078
Isak wrote:
strategy file path
strategy parameter xml file path
You can't run in JForex-SDK a strategy from a .jfx file, nor you can pass parameter xml file to it. Please use the JForex platform for such purposes.


 
 Post subject: Re: ITesterClient sample application Post rating: 0   New post Posted: Mon 07 Jan, 2013, 12:05 
User avatar

User rating: 6
Joined: Thu 19 May, 2011, 11:14
Posts: 235
Location: South Africa,
Ok thanks, I see.

Suppose I have a given strategy, StrategyX implementing IStrategy. Now I want to invoke (from the OS command line e.g. batch file / bash script) an application that runs (without any user input) a backtest of this strategy.

For example, I could invoke the strategy from the OS like this:
BacktestStrategyX 120101 130101 EURUSD AllTicks

(In my case I don't really care about the report or results or anything, since my strategies document themselves by writing to custom log files etc... but this may be different for others)

Now, in order to develop BacktestStrategyX, I would need:
1. StrategyX.java
2. The JForex API

Can you help me on how to go about developing BacktestStrategyX.java ? What I was trying to suggest in my original post is that such a sample application should be included in the wiki, as part of documentation on ITesterClient.


 
 Post subject: Re: ITesterClient sample application Post rating: 2   New post Posted: Tue 08 Jan, 2013, 18:04 
User avatar

User rating:
Joined: Fri 31 Aug, 2007, 09:17
Posts: 6078
Add the following program to you JForex-SDK project:
package jforex.sdk;

import com.dukascopy.api.*;
import com.dukascopy.api.system.ISystemListener;
import com.dukascopy.api.system.ITesterClient;
import com.dukascopy.api.system.ITesterClient.DataLoadingMethod;
import com.dukascopy.api.system.TesterFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
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;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.tools.JavaCompiler;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;


/**
 * This example program demonstrates how to compile and run a strategy from a java file
 */
@RequiresFullAccess
public class StrategyRunner {
   private static final Logger LOGGER = LoggerFactory.getLogger(StrategyRunner.class);

    private static String jnlpUrl = "https://www.dukascopy.com/client/demo/jclient/jforex.jnlp";
    private static String userName;
    private static String password; 

   public static void main(String[] args) throws Exception {
      
      if(args.length < 5){
         LOGGER.error("Insufficient parameter count " + args.length + ". Expected 5 arguments." );
         return;
      }
      
      userName = args[0];
      password = args[1];
      String strategyPath = args[2];
      String fromStr = args[3];
      String toStr = args[4];
      
      JavaCompiler jc = ToolProvider.getSystemJavaCompiler();
      StandardJavaFileManager sjfm = jc.getStandardFileManager(null, null, null);
      File javaFile = new File(strategyPath);
      String qualifiedClassName = getQualifiedName(javaFile.getAbsolutePath());

      jc.getTask(null, null, null, null, null, sjfm.getJavaFileObjects(javaFile)).call();

      sjfm.close();
      LOGGER.info("Class has been successfully compiled");

      URL[] urls = new URL[] { new URL("file://.") };
      URLClassLoader ucl = new URLClassLoader(urls);
      Class targetClass = ucl.loadClass(qualifiedClassName);
      IStrategy strategy = (IStrategy) targetClass.newInstance();
      
      // 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:\\temp\\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
         }
      });

      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);
      }

      final SimpleDateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
      dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));

      Date dateFrom = dateFormat.parse(fromStr);
      Date dateTo = dateFormat.parse(toStr);

      client.setDataInterval(DataLoadingMethod.ALL_TICKS, dateFrom.getTime(), dateTo.getTime());

      // 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(), 50000);
      //client.setCacheDirectory(new File("C:/temp/cacheTemp"));
      // load data
      LOGGER.info("Downloading data");
      Future<?> future = client.downloadData(null);
      // wait for downloading to complete
      future.get();
      // start the strategy
      LOGGER.info("Starting strategy"); 

      client.startStrategy(strategy);
      // now it's running

   }
   
   
   private static String getQualifiedName(String path) throws Exception{      
      String fileContents = readFileContents(path);
      String className = findRegex(fileContents, "class ([\\p{Alnum}.]+) ");
      String packageName = findRegex(fileContents, "package ([\\p{Alnum}.]+);");
      if(packageName.isEmpty()){
         throw new RuntimeException("Please define the package of your strategy");
      }
      return packageName + "." + className;
   }
   
   private static String readFileContents(String path) throws IOException {
      FileInputStream stream = new FileInputStream(new File(path));
      try {
         FileChannel fc = stream.getChannel();
         MappedByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
         return Charset.defaultCharset().decode(bb).toString();
      } finally {
         stream.close();
      }
   }
   
   private static String findRegex(String src, String regexpString) {
      Pattern pattern = Pattern.compile(regexpString, Pattern.DOTALL);
      Matcher matcher = pattern.matcher(src);
      return matcher.find() ? matcher.group(1) : "";
   }

}
Then export the program to a runnable jar file and run it in the following manner:
java -jar JarFileName.jar username password ./YourStrategy.java "05/01/2012 00:00:00" "05/01/2012 00:10:00"
If you don't want the strategy to get recompiled every time you run the program, consider passing the strategy's .class file to the program and remove the compilation logic.
Isak wrote:
What I was trying to suggest in my original post is that such a sample application should be included in the wiki, as part of documentation on ITesterClient.
We don't plan to post this example in our wiki, since this is a Java SE problem, not a JForex-API problem. In general wiki's purpose is to show users how to use the JForex-API functionality, not Java SE in whole (which itself has countless online tutorials and forums).


Attachments:
StrategyRunner.java [5.66 KiB]
Downloaded 829 times
DISCLAIMER: Dukascopy Bank SA's waiver of responsability - Documents, data or information available on this webpage may be posted by third parties without Dukascopy Bank SA being obliged to make any control on their content. Anyone accessing this webpage and downloading or otherwise making use of any document, data or information found on this webpage shall do it on his/her own risks without any recourse against Dukascopy Bank SA in relation thereto or for any consequences arising to him/her or any third party from the use and/or reliance on any document, data or information found on this webpage.
 
 Post subject: Re: ITesterClient sample application Post rating: 1   New post Posted: Wed 09 Jan, 2013, 10:58 
User avatar

User rating: 164
Joined: Mon 08 Oct, 2012, 10:35
Posts: 676
Location: NetherlandsNetherlands
This is awesome!!!


 
 Post subject: Re: ITesterClient sample application Post rating: 0   New post Posted: Thu 10 Jan, 2013, 14:24 
User avatar

User rating: 6
Joined: Thu 19 May, 2011, 11:14
Posts: 235
Location: South Africa,
Thank you very much! Exactly what I needed!


 
 Post subject: Re: ITesterClient run strategy from command line Post rating: 0   New post Posted: Fri 15 Jun, 2018, 21:40 
User avatar

User rating: 0
Joined: Sat 29 Dec, 2012, 19:01
Posts: 22
Location: Czech Republic, Praha
It's actually quite easy. Try to read this Building Custom Strategy Trader on Jforex Api, hopefully it makes sense.
I tried to describe how to do exactly what you need. Hopefully it helps.


 

Jump to:  

  © 1998-2011 Dukascopy® Bank SA
On-line Currency forex trading with Swiss Forex Broker - ECN Forex Brokerage,
Managed Forex Accounts, introducing forex brokers, Currency Forex Data Feed and News
Currency Forex Trading Platform provided on-line by Dukascopy.com