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.

Automating backtesting
 Post subject: Automating backtesting Post rating: 0   New post Posted: Fri 27 May, 2011, 22:54 

User rating: -
I have several strategies that I want to back test against several instruments so there are many combinations. Is there a way to automate back testing and capture the optimization outputs in a csv file?


 
 Post subject: Re: Automating backtesting Post rating: 0   New post Posted: Fri 03 Jun, 2011, 14:07 
User avatar

User rating:
Joined: Fri 31 Aug, 2007, 09:17
Posts: 6139
Unlike JForex client, for API logging messages to a .csv file is not supported. However, it is rather straighforward to implement such functionality.
Consider a program which tests against historical data two instances of the same strategy with different parameters:

package singlejartest;

import com.dukascopy.api.*;
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;

import jforex.strategies.*;

/**
 * This small program demonstrates how to initialize Dukascopy tester and start a strategy
 */
public class TestHistoricalMultipleStrategies {
    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 = "USERNAME";
    //password
    private static String password = "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:\\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);
        }

        //custom historical data
        String dateFromStr = "05/25/2011 00:00:00";
        String dateToStr = "05/26/2011 00:00:00";
       
        SimpleDateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
        dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
     
        Date dateFrom = dateFormat.parse(dateFromStr);
        Date dateTo = dateFormat.parse(dateToStr);
   

        client.setDataInterval ( Period.THIRTY_MINS,
              OfferSide.BID,
              ITesterClient.InterpolationMethod.CLOSE_TICK,
              dateFrom.getTime(), dateTo.getTime() );
       
       
        //set instruments that will be used in testing
        Set<Instrument> instruments = new HashSet<Instrument>();
        instruments.add(Instrument.EURUSD);
        instruments.add(Instrument.USDCHF);
        LOGGER.info("Subscribing instruments...");
        client.setSubscribedInstruments(instruments);
        //setting initial deposit
        client.setInitialDeposit(Instrument.EURUSD.getSecondaryCurrency(), 50000);
        //load data
        LOGGER.info("Downloading data");
        Future<?> future = client.downloadData(null);
        //wait for downloading to complete
        future.get();
       
        //two strategies, each with different parameters, but both log their messages to the same file
        MaintainOneOrderWithLog strategy1 = new MaintainOneOrderWithLog();
        MaintainOneOrderWithLog strategy2 = new MaintainOneOrderWithLog();
        strategy1.instrument = Instrument.EURUSD;
        strategy1.strategyInstanceName = "EURUSD instance";
        strategy1.amount = 0.01;
        strategy1.stopLossPrice = 0.0020;
        strategy1.takeProfitPrice = 0.0020;
        strategy2.instrument = Instrument.USDCHF;
        strategy2.strategyInstanceName = "USDCHF instance";
        strategy2.amount = 0.02;
        strategy2.stopLossPrice = 0.0030;
        strategy2.takeProfitPrice = 0.0030;

        //start both strategies
        LOGGER.info("Starting strategy 1");
        client.startStrategy(strategy1);
        LOGGER.info("Starting strategy 2");
        client.startStrategy(strategy2);
       
    }
}



Consider a strategy which logs its data to a file and is ran by the program in two instances:

package jforex.strategies;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;

import com.dukascopy.api.*;
import com.dukascopy.api.IEngine.OrderCommand;

/**
 * The strategy while running maintains one order with SL and TP.
 * Once an order gets closed on SL or TP a new one gets created
 *
 */
@RequiresFullAccess
public class MaintainOneOrderWithLog implements IStrategy {

   //general strategy parameters
   @Configurable("Instrument")
   public Instrument instrument = Instrument.EURUSD;
   @Configurable("Amount")
   public double amount = 0.02;
   @Configurable("Stop loss")
   public double stopLossPrice = 0.0020;
   @Configurable("Take profit")
   public double takeProfitPrice = 0.0030;

   //parameters for logging to file
   @Configurable("LogFile")
   public File file = new File("C:\\temp\\log.txt");
   @Configurable("StrategyInstanceName")
   public String strategyInstanceName = "default instance";

   private int slippage = 20; // pips

   private IConsole console;
   private IEngine engine;
   private IHistory history;

   private final String label = "order";
   private int counter;
   private IOrder order;

   @Override
   public void onStart(IContext context) throws JFException {
      this.engine = context.getEngine();
      this.console = context.getConsole();
      this.history = context.getHistory();
      console.getOut().println("Start");

      //create the first order
      this.order = submitOrder();
   }

   @Override
   public void onTick(Instrument instrument, ITick tick) throws JFException {}

   @Override
   public void onBar(Instrument instrument, Period period, IBar askBar, IBar bidBar) throws JFException {}

   @Override
   public void onMessage(IMessage message) throws JFException {
      writeToFile(strategyInstanceName + " message: " + message.getOrder().getLabel() + " - " + message.getContent());
      //once the order has been closed we create a new one
      if (!engine.getOrders().contains(this.order)) {
         this.order = submitOrder();
      }
   }

   @Override
   public void onAccount(IAccount account) throws JFException {}

   @Override
   public void onStop() throws JFException {
      if (order == null)
         return;
      try {
         order.close();
      } catch (JFException e) {
         console.getOut().println(e.getMessage());
      }

   }

   private IOrder submitOrder() throws JFException {
      return engine.submitOrder(label + counter++, instrument, OrderCommand.BUY, amount, 0, slippage,
            history.getLastTick(instrument).getBid() - stopLossPrice, // SL
            history.getLastTick(instrument).getAsk() + takeProfitPrice);// TP
   }

   private void writeToFile(String message) {
      try {
         FileWriter fstream = new FileWriter(this.file, true);
         BufferedWriter out = new BufferedWriter(fstream);
         out.append(message + "\n");
         out.close();
      } catch (Exception e) {
         console.getOut().println("Error: " + e.getMessage());
      }
   }

}


 

Jump to:  

cron
  © 1998-2025 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