Hello,
I've recently been trying to run a few simultaneous Renko simulations but keep getting thread overloads (it never happened with just one sim working - each simulation is a different currency pair as I find it easier than chasing around multiple pairs within one single strategy).
After reading through the wiki and support boards I implemented asynchronously "read"-ing the necessary historical data onStart (which didn't solve the issue, but I've decided to leave it in anyway), further reading lead me onto threading which (fingers crossed) will solve the problem. I took a look at:
https://www.dukascopy.com/wiki/#Threadingand tried to implement an asynchronous version as best I could just to test that it was working but couldn't quite manage it. I tried implementing it within onFeedData (which is necessary when using a Renko feed) but I just can't debug the last compile error (asynchronous threading is new to me!).
If anyone could shed some light onto this it would be much appreciated. I have included the complete code below:
Many thanks
J
package jforex;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.Callable;
//Dukascopy imports=========================
import com.dukascopy.api.*;
import com.dukascopy.api.feed.*;
import com.dukascopy.api.feed.util.*;
import com.dukascopy.api.IIndicators.AppliedPrice;
import com.dukascopy.api.feed.IFeedDescriptor;
import com.dukascopy.api.feed.IFeedListener;
import com.dukascopy.api.feed.util.RenkoFeedDescriptor;
import com.dukascopy.api.feed.util.TimePeriodAggregationFeedDescriptor;
import com.dukascopy.api.IEngine.OrderCommand;
import com.dukascopy.api.util.DateUtils;
import java.text.SimpleDateFormat;
import java.util.TimeZone;
import com.dukascopy.api.IOrder;
//============================================
public class RenkoThreadingTest implements IStrategy, IFeedListener {
//================================
private IEngine engine;
private IConsole console;
private IHistory history;
private IContext context;
private IIndicators indicators;
private IUserInterface userInterface;
//=================================
//------FEED DESCRIPTORS---------------------
//---This is the renko data feed descriptor (2 pip bricks)
public IFeedDescriptor feedDescriptor = new RenkoFeedDescriptor(Instrument.EURUSD,PriceRange.TWO_PIPS,OfferSide.BID);
//---------------------------------------------
//-------------SET DATE AND TIME FORMATS---------
public static SimpleDateFormat MyDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS") {
{
setTimeZone(TimeZone.getTimeZone("GMT"));
}
};
private Instrument selectedInstrument = Instrument.EURUSD;
//constant & variable declarations
private double latestRenkoClosePrice;
private IBar latestRenkoBrick;
private int dataCount=0;
//-------------------------------
public void onStart(final IContext context) throws JFException {
this.engine = context.getEngine();
this.console = context.getConsole();
this.history = context.getHistory();
this.context = context;
this.indicators = context.getIndicators();
this.userInterface = context.getUserInterface();
//--subscribe to renko feed
context.setSubscribedInstruments(java.util.Collections.singleton(feedDescriptor.getInstrument()), true);
context.subscribeToFeed(feedDescriptor, this);
//------------------------------last renko brick----------------------------------------------------
latestRenkoBrick = history.getRenkoBar(selectedInstrument, OfferSide.BID, PriceRange.TWO_PIPS, 0);
final long fromTime = latestRenkoBrick.getTime()-TimeUnit.DAYS.toMillis(3);
final long toTime = latestRenkoBrick.getTime();
history.readFeedData(feedDescriptor, fromTime, toTime, new IFeedListener(){
public void onFeedData(IFeedDescriptor feedDescriptor, ITimedData feedData) {
dataCount++;
}
}, new LoadingProgressListener(){
public void dataLoaded(long start, long end, long currentPosition, String information) {
}
public void loadingFinished(boolean allDataLoaded, long start, long end, long currentPosition) {
if(allDataLoaded){
console.getOut().format("%s - %s %s %s feed elements loaded",
DateUtils.format(fromTime), DateUtils.format(fromTime), dataCount, feedDescriptor.getDataType()).println();
//context.stop();
}
}
public boolean stopJob() {
return false;
}
}
);
}//--------------------------------end of onStart----------------------------------------------------------------
public void onFeedData(IFeedDescriptor feedDescriptor, ITimedData feedData){
Instrument myInstrument = feedDescriptor.getInstrument();
OfferSide myOfferSide = feedDescriptor.getOfferSide();
try{
IRenkoBar latestRenkoBar = history.getRenkoBar(selectedInstrument, OfferSide.BID, PriceRange.TWO_PIPS, 0);
latestRenkoClosePrice = latestRenkoBar.getClose();
final AsynchThrdTest ThrdTest = new AsynchThrdTest(latestRenkoClosePrice);
final IContext finalContext = context;
Thread thread = new Thread(new Runnable(){
public void run(){
try {
finalContext.executeTask(ThrdTest);
} catch (Exception e) {
console.getErr().println(Thread.currentThread().getName() + " " + e);
}
}
});
thread.start();
}catch (JFException e) {
console.getErr().println(e);
e.printStackTrace();
} //end of try
} // -----------------------------------end of onFeedData-----------------------------------------------------
private class AsynchThrdTest{
private final double currentBrickPrice;
public AsynchThrdTest(double currentBrickPrice){
this.currentBrickPrice = currentBrickPrice;
if(currentBrickPrice>0){
console.getOut().format("This asynchronous threading seems to be working: \n");
}
}
}
public void onAccount(IAccount account) throws JFException {
}
public void onMessage(IMessage message) throws JFException {
}
public void onStop() throws JFException {
}
public void onTick(Instrument instrument, ITick tick) throws JFException {
}
public void onBar(Instrument instrument, Period period, IBar askBar, IBar bidBar) throws JFException {
}
}