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