Standalone API client on LINUX running Oracle/Sun Java Server VM JDK 7 update 45 on an Amazon Linux EC2 AMI . JForex API 2.8.0 One client already running 8 strategies. During startup of second client process, same Live account login, different process, I see this exception while the second client is attempting to start its strategies, which is an identical set of strategies as the first client process is already running.
May be simply a synchronization issue of delivering Ticks to a strategy simultaneous with an internal Strategy list being modified, since it is intermittent?? So the additional process stuff may be a "red herring"........
Is there some synchronization issue you can recognize, since I don't think it's a problem on my end... ? Since these are separate processes, I don't think there is anything I can do in my code, so could be an issue in Dukascopy API and/or server side coding. Would appreciate if you could look into it.
HyperScalper
after call startStrategy HyperBOT_EURJPY Waiting for Strategy HyperBOT_EURJPY 2013-11-28 16:59:25.959 ERROR LiveCurrencyMarketProcessingThread - java.util.ConcurrentModificationException java.util.concurrent.ExecutionException: java.util.ConcurrentModificationException at java.util.concurrent.FutureTask.report(FutureTask.java:122) at java.util.concurrent.FutureTask.get(FutureTask.java:188) at com.dukascopy.dds2.greed.market.LiveCurrencyMarketProcessingThread.run(LiveCurrencyMarketProcessingThread.java:84) Caused by: java.util.ConcurrentModificationException at java.util.HashMap$HashIterator.nextEntry(HashMap.java:926) at java.util.HashMap$ValueIterator.next(HashMap.java:954) at com.dukascopy.api.impl.connect.DCClientImpl$7.tickReceived(DCClientImpl.java:821) at com.dukascopy.dds2.greed.market.LiveCurrencyMarketProcessingThread$1.run(LiveCurrencyMarketProcessingThread.java:138) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471) at java.util.concurrent.FutureTask.run(FutureTask.java:262) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) at java.lang.Thread.run(Thread.java:744)
Here is the code section where the error occurs, as a list of Strategy instances is started. Very reliable with a single process but, as I say, when a second process instance is started this code throws the ConcurrentModificationException.
final void startStrategies() { int numStrategies = instrumentNamesList.size(); log("StartStrategies running "+instrumentNamesList.size()+" instances."); IHyperBotStrategy strategy = null; String instrumentName = null; String currency1 = null; String currency2 = null; String slashName = null; long id = 0; try { log("Run RemoteServerTickTimestamps"); RemoteServerTickTimestamps remoteServerTickTimestamps = new RemoteServerTickTimestamps(); // use defaults id = getIClient().startStrategy(remoteServerTickTimestamps, myStrategyExceptionHandler); synchronized(strategiesMapMutex) { strategiesMap.put(new Long(id), remoteServerTickTimestamps); } log("after RemoteServerTickTimestamps"); } catch(Exception e) { e.printStackTrace(); } pause(10000); for (int i=0; i<numStrategies; i++) { Instrument instrument = null; instrumentName = instrumentNamesList.get(i); if (instrumentName.length()!=6) continue; boolean error = false; try { // create an Instrument currency1 = instrumentName.substring(0,3); currency2 = instrumentName.substring(3,6); slashName = currency1+"/"+currency2; log("Slashed name: "+slashName); instrument = Instrument.fromString(slashName); } catch(Exception e) { log("Error creating instrument "+instrumentName); error=true; } if (instrument==null || error) { log("ERROR INSTRUMENT "+instrumentName+" does not exist."); continue; // skip it } if ( !availableInstruments.contains(instrument)) { log("ERROR INSTRUMENT "+instrumentName+" is NOT AVAILABLE to your account."); continue; // skip it } masterStrategy = new HyperBot(); //RemoteServerTickTimestamps(); masterStrategy.selectedInstrument = instrument; boolean validStrategy = validStrategy(masterStrategy); if ( !validStrategy) { log("Invalid HyperBot strategy failed."); systemExit(1); } // cast is guaranteed by validStrategy check strategy = (IHyperBotStrategy)masterStrategy; strategy.setHyperBotHost(this); // this is the host String strategyName = "HyperBOT"+"_"+instrumentName; strategy.setName(strategyName); try { log("call startStrategy "+strategyName); id = getIClient().startStrategy(masterStrategy, myStrategyExceptionHandler); synchronized(strategiesMapMutex) { strategiesMap.put(new Long(id), masterStrategy); } log("after call startStrategy "+strategyName); } catch(Exception e) { e.printStackTrace(); } if (id==0) { log("Start strategy failed."); systemExit(1); } log("Waiting for Strategy "+strategyName); if (i<numStrategies) { pause(5000); } } }
|