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.

Standalone JForex API documentation
 Post subject: Standalone JForex API documentation Post rating: 0   Post Posted: Tue 24 Apr, 2012, 12:24 
User avatar

User rating: 0
Joined: Thu 19 May, 2011, 11:48
Posts: 26
Location: Hungary, Budapest
Dear Support,

Do you have any detailed documentation about Standalone JForex API which describes the threading model of IClient, ISystemListener interfaces? I've made a small standalone client which starts a strategy and I'm looking for a best practice to call strategy's methods from this client. I found out, the main client runs in a thread, the strategy runs in a different thread and the implemented methods of ISystemListener run also a different thread. I just guessing, because ClientFactory.getDefaultInstance(); gives back a DCClientImpl instance and there is no source code for that class. I could just had this class, but it is a little bit unreadable.

Please, let me know, the following code is appropriate for calling strategy's code from standalone client.

public class PositionManagerApp implements ISystemListener{

   private static final Logger LOGGER = LoggerFactory.getLogger(PositionManagerApp.class);
    private static String jnlpUrl = "https://www.dukascopy.com/client/demo/jclient/jforex.jnlp";
    private static String userName = "xxxx";
    private static String password = "xxxx";
    private int lightReconnects = 3;
   private IClient client;
   private PositionManagerStrategy pm;


   /**
    * @param args
    */
   public static void main(String[] args) throws Exception {
      
   PositionManagerApp pa = new PositionManagerApp();
        pa.client = ClientFactory.getDefaultInstance();
        PositionManagerStrategy  pm = new PositionManagerStrategy();
        pa.client.setSystemListener(pa);
       
        LOGGER.info("Main thread: " + Thread.currentThread().getId());
        LOGGER.info("Connecting...");
        pa.client.connect(jnlpUrl, userName, password);

        int i = 10; //wait max ten seconds
        while (i > 0 && !pa.client.isConnected()) {
            Thread.sleep(1000);
            i--;
        }
        if (!pa.client.isConnected()) {
            LOGGER.error("Failed to connect Dukascopy servers");
            System.exit(1);
        }
       
        LOGGER.info("Starting strategy");
        pa.client.startStrategy(pm);

        List<IOrder> orders = pm.getOrders();
        if(orders != null ){
           for(IOrder o : orders){
              if(o.getState().equals(IOrder.State.FILLED)){
                 printOrder(o);
                 //pm.close(o, 2);
              }
           }
        }
   }


   public void onConnect() {
      LOGGER.info("Connected");
        lightReconnects = 3;
        LOGGER.info("ISystemListener thread: " + Thread.currentThread().getId());
   }


   public void onDisconnect() {
      LOGGER.warn("Disconnected");
        if (lightReconnects > 0) {
            client.reconnect();
            --lightReconnects;
        } else {
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
            }
            try {
                client.connect(jnlpUrl, userName, password);
            } catch (Exception e) {
                LOGGER.error(e.getMessage(), e);
            }
        }
   }


   public void onStart(long processId) {
      LOGGER.info("Strategy started: " + processId);
   }


   public void onStop(long processId) {
        if (client.getStartedStrategies().size() == 0) {
            System.exit(0);
        }
   }
   
   public static void printOrder(IOrder o){
      LOGGER.info("OrderID: " +o.getId()
               + " Type: " + o.getOrderCommand().toString()
               + " Amount: " + o.getAmount()
               + " P/L: " + o.getProfitLossInUSD());
      
   }
}


and the strategy

public class PositionManagerStrategy implements IStrategy {
   
   private static final Logger LOGGER = LoggerFactory.getLogger(PositionManagerStrategy.class);
   private IEngine engine;
   private IContext context;

   public void onAccount(IAccount arg0) throws JFException {
   }

   public void onBar(Instrument arg0, Period arg1, IBar arg2, IBar arg3)
         throws JFException {
   }

   public void onMessage(IMessage arg0) throws JFException {
   }

   public void onStart(IContext context) throws JFException {
      this.context = context;
      this.engine = context.getEngine();
      LOGGER.info("PositionStrategyManager OnStart thread: " + Thread.currentThread().getId());
   }

   public void onStop() throws JFException {
   }

   public void onTick(Instrument arg0, ITick arg1) throws JFException {
   }
   
   public List<IOrder> getOrders() throws InterruptedException, ExecutionException{
      LOGGER.info("PositionStrategyManager thread: " + Thread.currentThread().getId());
      Future<List<IOrder>> future = context.executeTask(new Callable<List<IOrder>>() {
           public List<IOrder> call() {
              try {
                 LOGGER.info("Callable thread: " + Thread.currentThread().getId());
                 IEngine engine = context.getEngine();
                   return engine.getOrders();
               } catch (JFException e) {
                  return null;
               }
           }
       });
      return future.get();
   }
   
   public void close(final IOrder o, final double amount) throws JFException{
      
       context.executeTask(new Callable<Object>() {
              public Object call() {
                 try {
                    IEngine engine = context.getEngine();
                       IOrder order = engine.getOrderById(o.getId());
                      order.close(amount);
                  } catch (JFException e) {
                  }
                 return null;
              }
          });
   }

}


I guess, IClient.connect is run in another thread. Is it possible to join this this thread? I mean, I would like to suspend the main thread until connection is established.

Best regards,
Kirilla


 
 Post subject: Re: Standalone JForex API documentation Post rating: 0   Post Posted: Tue 24 Apr, 2012, 12:56 
User avatar

User rating:
Joined: Fri 31 Aug, 2007, 09:17
Posts: 6139
Quote:
I guess, IClient.connect is run in another thread. Is it possible to join this this thread? I mean, I would like to suspend the main thread until connection is established.

The following part of the code is responsible for waiting for the connection to established.
        int i = 10; //wait max ten seconds
        while (i > 0 && !pa.client.isConnected()) {
            Thread.sleep(1000);
            i--;
        }
        if (!pa.client.isConnected()) {
            LOGGER.error("Failed to connect Dukascopy servers");
            System.exit(1);
        }

You should add one thing to the code - subscription to necessary instruments.
To do that add this code in place of 35th line in your code:
        //subscribe to the instruments
        Set<Instrument> instruments = new HashSet<Instrument>();
        instruments.add(Instrument.EURUSD);
        LOGGER.info("Subscribing instruments...");
        client.setSubscribedInstruments(instruments);

For more information on standalone client see https://www.dukascopy.com/wiki/#Standalone_JForex_API


 
 Post subject: Re: Standalone JForex API documentation Post rating: 0   Post Posted: Tue 24 Apr, 2012, 13:09 
User avatar

User rating: 0
Joined: Thu 19 May, 2011, 11:48
Posts: 26
Location: Hungary, Budapest
Thank you. I know that part of code which polls isConnected per sec ten times. Could you help me in my first question too?

"I've made a small standalone client which starts a strategy and I'm looking for a best practice to call strategy's methods from this client. "

Best regards,
Kirilla


 
 Post subject: Re: Standalone JForex API documentation Post rating: 0   Post Posted: Tue 24 Apr, 2012, 13:11 
User avatar

User rating:
Joined: Fri 31 Aug, 2007, 09:17
Posts: 6139
It is described here https://www.dukascopy.com/wiki/#Standalone_JForex_API


 
 Post subject: Re: Standalone JForex API documentation Post rating: 0   Post Posted: Tue 24 Apr, 2012, 13:21 
User avatar

User rating: 0
Joined: Thu 19 May, 2011, 11:48
Posts: 26
Location: Hungary, Budapest
I'm sorry, but I didn't find it. I found only example for setting strategy parameters after instantiating it, but before running it. I mean, calling strategy methods after started. For example closing order by my client using a public strategy method. (see above PositionManagerStrategy getOrders() and close(IOrder, amount) )


 
 Post subject: Re: Standalone JForex API documentation Post rating: 0   Post Posted: Thu 26 Apr, 2012, 16:46 
User avatar

User rating:
Joined: Fri 31 Aug, 2007, 09:17
Posts: 6139
Consider introducing a public interface in your strategy which would serve then as a listener for the program, see example:
https://www.dukascopy.com/wiki/#Standalone_JForex_API/Program_communicating_with_a_strategy


 
 Post subject: Re: Standalone JForex API documentation Post rating: 0   Post Posted: Thu 26 Apr, 2012, 22:22 
User avatar

User rating: 0
Joined: Thu 19 May, 2011, 11:48
Posts: 26
Location: Hungary, Budapest
Thank you. It is a new topic on wiki and I think it's very useful. If I understand well, this works as an observer on the client side and the advantage is that, i can define the handler of this event in the client code. That's nice. But my problem was, getting IOrder information from running strategy worked well when I call it without the executor, but when I tried to submit or close an order without it, I got something JFIllegalThreadException. Example:

Methods in strategy to get and set orders from IClient.
Getting order info
works
 public List<IOrder> getOrders() throws InterruptedException, ExecutionException{
      LOGGER.info("PositionStrategyManager thread: " + Thread.currentThread().getId());
      Future<List<IOrder>> future = context.executeTask(new Callable<List<IOrder>>() {
           public List<IOrder> call() {
              try {
                 LOGGER.info("Callable thread: " + Thread.currentThread().getId());
                 IEngine engine = context.getEngine();
                   return engine.getOrders();
               } catch (JFException e) {
                  return null;
               }
           }
       });
      return future.get();
   }


and this is works too
 public List<IOrder> getOrders(){
                   return engine.getOrders();
   }


Submitting, close or modify order
works
public void close(final IOrder o, final double amount) throws JFException{
       
       context.executeTask(new Callable<Object>() {
              public Object call() {
                 try {
                    IEngine engine = context.getEngine();
                       IOrder order = engine.getOrderById(o.getId());
                      order.close(amount);
                  } catch (JFException e) {
                  }
                 return null;
              }
          });
   }


throws JFIllegalThreadException
public void close(final IOrder o, final double amount){
                      order.close(amount);
   }


Best regards,
Kirilla


 
 Post subject: Re: Standalone JForex API documentation Post rating: 0   Post Posted: Fri 27 Apr, 2012, 15:46 
User avatar

User rating:
Joined: Fri 31 Aug, 2007, 09:17
Posts: 6139
We added another example by following the same pattern, which allows to call order fills from program side, see:
https://www.dukascopy.com/wiki/#Standalone_JForex_API/Client_covers_up_strategy_fills


 

Jump to:  

  © 1998-2026 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