SDK Client

IClient interface is used for working with realtime data and ITesterClient inherits its functionality for working with historical data. This article provides examples of major IClient features. The examples are based upon the Main.java example located in the JForex SDK project. Thus in order to test attachment-less snippets one should simply integrate them in the Main.java example program.

Connect

One gets an instance of IClient by using ClientFactory.getDefaultInstance(). One connects to dukascopy servers by using the connect method, for example:

client.connect("http://platform.dukascopy.com/demo/jforex.jnlp", "username", "password");

For connecting to LIVE servers see here.

System listener

ISystemListener interface allows the user to execute some business logic on system connects and disconnects as well as on start and stop of every strategy. System listener gets added to IClient by using the setSystemListener method, for instance:

        client.setSystemListener(new ISystemListener() {
            private int lightReconnects = 3;

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

            @Override
            public void onStop(long processId) {
                LOGGER.info("Strategy stopped: " + processId);
                if (client.getStartedStrategies().size() == 0) {
                    System.exit(0);
                }
            }

            @Override
            public void onConnect() {
                LOGGER.info("Connected");
                lightReconnects = 3;
            }

            @Override
            public void onDisconnect() {
                Runnable runnable = new Runnable() {
                    @Override
                    public void run() {
                        if (lightReconnects > 0) {
                            client.reconnect();
                            --lightReconnects;
                        } else {
                            do {
                                try {
                                    Thread.sleep(60 * 1000);
                                } catch (InterruptedException e) {
                                }
                                try {
                                    if(client.isConnected()) {
                                        break;
                                    }
                                    client.connect(jnlpUrl, userName, password);
                                } catch (Exception e) {
                                    LOGGER.error(e.getMessage(), e);
                                }
                            } while(!client.isConnected());
                        }
                    }
                };
                new Thread(runnable).start();
            }
        });

Subscribing to instruments

Unlike in JForex client, in Standalone API one always has to explicitly subscribe to all instruments that his strategy is going to use. This can be done by using the IClient.setSubscribedInstruments method. Note that the subscription is asynchronous, thus if the in it is advised to subscribe in the following way:

Set<Instrument> instruments = new HashSet<Instrument>();
instruments.add(Instrument.EURSEK);
instruments.add(Instrument.AUDUSD);

//subscribe to the instruments
Set<Instrument> instruments = new HashSet<Instrument>();
instruments.add(Instrument.EURUSD);
LOGGER.info("Subscribing instruments...");
client.setSubscribedInstruments(instruments);

Running strategies

Strategy can be started by passing it to IClient.startStrategy, for instance:

client.startStrategy(new MA_Play());

It is also possible to run multiple strategies. For instance, it is possible to run two instances of the same strategy but with different parameters:

StrategySimple strategy1 = new StrategySimple();
StrategySimple strategy2 = new StrategySimple();
strategy1.amount = 0.01;
strategy1.stopLossPips = 20;
strategy1.takeProfitPips = 10;
strategy2.amount = 0.02;
strategy2.stopLossPips = 60;
strategy2.takeProfitPips = 60;

client.startStrategy(strategy1);
client.startStrategy(strategy2);

Running remote strategies

It is possible run a remote strategy by calling the IClient.getRemoteStrategyManager().startStrategy method. For other remote strategy management methods see IStrategyManager . Consider an example program which is runs and manages remote strategies:

File jfxFile = new File("src/singlejartest/MA_Play.jfx");
if (!jfxFile.exists()) {
    LOGGER.error(jfxFile + " does not exist! Please compile the strategy or choose another path.");
    System.exit(1);
}

final IRemoteStrategyManager remoteManager = client.getRemoteStrategyManager();

remoteManager.addStrategyListener(new RemoteStrategyListener() {

    public void onStrategyRun(IRemoteStrategyDescriptor descriptor) {
        LOGGER.info("remote startegy launched: " + descriptor);
        if (!descriptor.getId().equals(myStrategyId)) {
            LOGGER.info("Not our designated remote strategy - stop it!");
            remoteManager.stopStrategy(descriptor.getId());
        }
    };

    public void onStrategyStop(IRemoteStrategyDescriptor descriptor) {
        LOGGER.info("remote startegy stopped: " + descriptor);
    };
});

// start a strategy without fetching the id
remoteManager.startStrategy(jfxFile, true);

// start and fetch the id
IStrategyResponse<UUID> startResponse = remoteManager.startStrategy(jfxFile, true).get();
if (startResponse.isError()) {
    LOGGER.error("Remote strategy failed to start: " + startResponse.getErrorMessage());
} else {
    myStrategyId = startResponse.getResult();
    LOGGER.info("Remote strategy successfully started: " + myStrategyId);
}

Set<IRemoteStrategyDescriptor> strategyDescriptors = remoteManager.getStartedStrategies().get().getResult();
LOGGER.info("Remotely started " + strategyDescriptors.size() + " strategies: ");
for (IStrategyDescriptor strategyDescriptor : strategyDescriptors) {
    LOGGER.info(strategyDescriptor.toString());
}

MainRemote.java

Please note that remote strategies must follow the rules described in section Remote Run.

Stopping strategy

One retrieves strategy process id from IClient.startStrategy, which afterwards can be used to stop the strategy by using the IClient.stopStrategy method. Consider a program which starts an anonymous strategy and checks every second if the user has typed in the console "stop", if so then the program stops the strategy.

final long strategyId = client.startStrategy(new IStrategy(){
    public Instrument instrument = Instrument.EURUSD;
    private IConsole console;

    public void onStart(IContext context) throws JFException {        
        console = context.getConsole();    
    }
    public void onBar(Instrument instrument, Period period, IBar askBar, IBar bidBar) throws JFException {
        if ( instrument == this.instrument){
            console.getOut().println(" bar: " + period  + " " + askBar);
        }
    }
    public void onTick(Instrument instrument, ITick tick) throws JFException {    }
    public void onMessage(IMessage message) throws JFException {    }
    public void onAccount(IAccount account) throws JFException {    }
    public void onStop() throws JFException {    }
});
//now it's running

//every second check if "stop" had been typed in the console - if so - then stop the strategy
Thread thread = new Thread(new Runnable() {
    @Override
    public void run() {                
        Scanner s = new Scanner(System.in);                
        while(true){
            while(s.hasNext()){
                String str = s.next();
                if(str.equalsIgnoreCase("stop")){
                    System.out.println("Strategy stop by console command.");
                    client.stopStrategy(strategyId);
                    break;
                }
            }
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    });
thread.start();

MainStopFromConsole.java

Stopping strategy

One retrieves strategy process id from IClient.startStrategy, which afterwards can be used to stop the strategy by using the IClient.stopStrategy method. Consider a program which starts an anonymous strategy and checks every second if the user has typed in the console "stop", if so then the program stops the strategy.

final long strategyId = client.startStrategy(new IStrategy(){
    public Instrument instrument = Instrument.EURUSD;
    private IConsole console;

    public void onStart(IContext context) throws JFException {        
        console = context.getConsole();    
    }
    public void onBar(Instrument instrument, Period period, IBar askBar, IBar bidBar) throws JFException {
        if ( instrument == this.instrument){
            console.getOut().println(" bar: " + period  + " " + askBar);
        }
    }
    public void onTick(Instrument instrument, ITick tick) throws JFException {    }
    public void onMessage(IMessage message) throws JFException {    }
    public void onAccount(IAccount account) throws JFException {    }
    public void onStop() throws JFException {    }
});
//now it's running

//every second check if "stop" had been typed in the console - if so - then stop the strategy
Thread thread = new Thread(new Runnable() {
    @Override
    public void run() {                
        Scanner s = new Scanner(System.in);                
        while(true){
            while(s.hasNext()){
                String str = s.next();
                if(str.equalsIgnoreCase("stop")){
                    System.out.println("Strategy stop by console command.");
                    client.stopStrategy(strategyId);
                    break;
                }
            }
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    });
thread.start();

MainStopFromConsole.java

Work with charts

There are two ways how one can open a chart:

  1. IClient.openChart is used to open a chart without running a strategy.
  2. IClient.addClientGUIListener adds a listener for the program to handle IContext.openChart and IContext.closeChart events.

Open a chart from IClient

Consider opening multiple charts - for each instrument in an array instrArr:

for(Instrument instrument : instrArr){
    IFeedDescriptor feedDescriptor = new TicksFeedDescriptor(instrument);
    feedDescriptor.setOfferSide(OfferSide.BID);// need to set due to platform requirements
    IChart chart = client.openChart(feedDescriptor);
    final IClientGUI clientGUI = client.getClientGUI(chart);
    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            ChartFrame frame = new ChartFrame(clientGUI, client.getSubscribedInstruments());
            chartFrameMap.put(clientGUI.getChart(), frame);
            //Handle manual close - we need to call IClient.closeChart for strategy to know that the chart is no more there
            frame.addWindowListener(new WindowAdapter(){
                public void windowClosing(WindowEvent e) {
                    LOGGER.info("Chart manually closed, removing the chart from the strategy context");
                    client.closeChart(clientGUI.getChart());
                    chartFrameMap.remove(clientGUI.getChart());
                    if(chartFrameMap.isEmpty()){
                        LOGGER.info("All charts closed, stopping the program");
                        System.exit(0);
                    }
                }
            });
        }
    });
}

MainOpenChart.java

Handle IContext.openChart

Consider a program which opens a chart whenever the strategy calls IContext.openChart and closes a chart whenever the strategy call IContext.closeChart:

client.addClientGUIListener(new IClientGUIListener() {  

    @Override
    public void onOpenChart(final IClientGUI clientGUI) {
        LOGGER.info("Chart opened from a startegy " + clientGUI.getChart().getFeedDescriptor());
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                ChartFrame frame = new ChartFrame(clientGUI, client.getSubscribedInstruments());
                chartFrameMap.put(clientGUI.getChart(), frame);
                //Handle manual close - we need to call IClient.closeChart for strategy to know that the chart is no more there
                frame.addWindowListener(new WindowAdapter(){
                    public void windowClosing(WindowEvent e) {
                        LOGGER.info("Chart manually closed, removing the chart from the strategy context");
                        client.closeChart(clientGUI.getChart());
                        updateOnClose(clientGUI.getChart());
                    }
                });
            }
        });
    }

    @Override
    public void onCloseChart(IChart chart) {
        LOGGER.info("Chart closed from a startegy " + chart.getFeedDescriptor());
        //we need to take care of closing the frame ourselves in gui
        ChartFrame frame = chartFrameMap.get(chart);
        frame.dispose();
        updateOnClose(chart);
    }

    private void updateOnClose(IChart chart){
        chartFrameMap.remove(chart);
        if(chartFrameMap.isEmpty()){
            LOGGER.info("All charts closed, stopping the program");
            System.exit(0);
        }
    }
});

MainHandleStrategyOpenChart.java

Add chart objects

One can not only plot chart objects from within a strategy, but also from the program running IClient. Consider creating a button panel which receives an IChart from IClientGUI.getChart():

@SuppressWarnings("serial")
private class ChartObjectPanel extends JPanel {

    private final IChart chart;
    private ChartObjectPanel(IChart chart){
        this.chart = chart;
        addButtons();
    }

    private void addButtons(){            
        JButton btnVLine = new JButton("Add VLine");
        btnVLine.addActionListener(new ActionListener(){
            @Override
            public void actionPerformed(ActionEvent e) {
                //draw the line at the time of the last drawn feed element on the chart
                ITimedData[] chartData = chart.getLastRequestedData();
                long time = chartData[chartData.length - 1].getTime();
                IChartObject obj = chart.getChartObjectFactory().createVerticalLine("vLine", time);
                obj.setColor(Color.RED);
                chart.add(obj);
            }});
        add(btnVLine);            
        JButton btnHLine = new JButton("Add HLine");
        btnHLine.addActionListener(new ActionListener(){
            @Override
            public void actionPerformed(ActionEvent e) {    
                //draw the line in the chart price axis midpoint
                double price = chart.getMinPrice() + (chart.getMaxPrice() - chart.getMinPrice()) / 2;
                System.out.println(String.format("%.5f", price));                    
                IChartObject obj = chart.getChartObjectFactory().createHorizontalLine("hLine", price);
                obj.setColor(Color.GREEN);
                chart.add(obj);
            }});
        add(btnHLine);
    }

}

MainOpenChartAddChartObject.java

Change chart theme

IChartTheme represents a chart theme, it can be retrieved and set to a chart by using the getTheme and setTheme methods of the IClientChartPresentationManager interface. Consider changing chart's background and tick/candle colors:

chartPresentationManager.setTheme(
    chartPresentationManager.getTheme()
        .setName("Custom tick/candle color theme")
        .setColor(ColoredElement.BACKGROUND, new Color(254, 244, 214))
        .setColor(ColoredElement.CANDLE_BEAR, Color.CYAN)
        .setColor(ColoredElement.CANDLE_BULL, Color.ORANGE)
        .setColor(ColoredElement.ASK, Color.YELLOW.darker())
        .setColor(ColoredElement.BID, Color.PINK.darker())
);

One can retrieve a predefined theme by calling the IClientChartPresentationManager.getPredefinedTheme method. Consider setting a predefined theme to a chart:

chartPresentationManager.setTheme(chartPresentationManager.getPredefinedTheme(IChartTheme.Predefined.BLUE_BLACK_ON_GRAY));


For full usage example look up the cmbChartTheme combo box in: MainOpenChart.java

Program communicating with a strategy

By defining a listener (in the means of public interface) within a strategy one can implement some client side logic on strategy events.

Client action on order fill and close

Consider that from the program you wish to do some extra logging on both order fill and close. And also you wish to set order stop loss:

client.startStrategy(new StrategyPublicMethods(new StrategyPublicMethods.ClientActions() {

    @Override
    public void onOrderFill(IOrder order) {
        LOGGER.info("Order filled, execute here some logic on client side, say set stop loss if the order is long");
        if(order.isLong()){
            try {
                order.setStopLossPrice(order.getOpenPrice() - order.getInstrument().getPipValue() * 10);
            } catch (JFException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void onOrderClose(IOrder order) {
        LOGGER.info("Order closed, execute here some logic on client side");                                    
    }
}));

Consider introducing an interface in a strategy which would serve as an order fill and close listener. Implementation of the interface would get passed from the IClient program:

public class StrategyPublicMethods implements IStrategy {

    private IConsole console; 
    private IEngine engine;
    private StrategyPublicMethods.ClientActions clientActions;

    public interface ClientActions {
        void onOrderClose(IOrder order);
        void onOrderFill(IOrder order);
    }  

    //for the launch from standalone
    public StrategyPublicMethods (StrategyPublicMethods.ClientActions clientActions){
        this.clientActions = clientActions;
    }

    //...
}

Then on every order fill and close execute the logic that has been passed from the IClient program:

@Override
public void onMessage(IMessage message) throws JFException {
    if(message.getType() == IMessage.Type.ORDER_FILL_OK){
        clientActions.onOrderFill(message.getOrder());
    }
    if(message.getType() == IMessage.Type.ORDER_CLOSE_OK){
        clientActions.onOrderClose(message.getOrder());
    }
}

StrategyPublicMethods.java MainPublicMethods.java

Client covers up strategy fills

Consider another example of the same pattern - a client program that covers-up each order created by the staregy:

client.startStrategy(new StrategyWithFillListener(new StrategyWithFillListener.ClientActions() {

    @Override
    public void onOrderFill(IOrder order, IEngine engine) {
        LOGGER.info("Order filled, open cover-up order from client side.");
        try {
            //we can't open next order sooner than 1 sec after the previous one for the same instrument
            Thread.sleep(1000);
            //opposite direction order with the same amount
            OrderCommand cmd = order.isLong() ? OrderCommand.SELL : OrderCommand.BUY;
            engine.submitOrder("orderClient" + ++counter, order.getInstrument(), cmd, order.getAmount());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}));

In this case the listener intrerface only includes one method:

public class StrategyWithFillListener implements IStrategy {
    //...
    public interface ClientActions {
        void onOrderFill(IOrder order, IEngine engine);
    }  

    //for the launch from standalone
    public StrategyWithFillListener (StrategyWithFillListener.ClientActions clientActions){
        this.clientActions = clientActions;
    }
    //...
}

Then on every order fill execute the logic that has been passed from the IClient program:

@Override
public void onMessage(IMessage message) throws JFException {
    if(message.getType() == IMessage.Type.ORDER_FILL_OK){
        clientActions.onOrderFill(message.getOrder(), engine);
    }
}

StrategyFillListener.java ProgramFillCover.java

News and Calendar

In order to receive news and/or calendar messages in a strategy, one has to apply NewsFilter and/or CalendarFilter to IClient before the run of strategy in the following way:

NewsFilter newsFilter = new NewsFilter();
//all today's news
newsFilter.setTimeFrame(NewsFilter.TimeFrame.TODAY);
client.addNewsFilter(newsFilter);

Note: NewsFilter only works with live-data, meaning that you can't use it while back-testing - no news messages in strategy will arrive.

Time frame

Available time frames are defined by TimeFrame enum. One can retrieve news for the following time frames:

  • Online - strategy will receive news as they arrive.
  • Last 10 minutes - strategy right after its start will receive news for the last 10 minutes, from then on it news filter will behave as Online.
  • Last 30 minutes, Last hour, Today - function the same way as Last 10 minutes just over a different period of time.
  • Specific date - strategy right after its start will receive news for the specific date, from then on it news filter will behave as Online. To enable this one needs to call NewsFilter.setFrom with the particular date.

Filter parameters

One may filter news by the following parameters:

Parameter sets act like OR conditions, meaning that:

  • Application of no parameters will result of receiving all news messages.
  • Application of one parameter StockIndex.NYSE will result in strategy receiving ONLY news that are related to NYSE stock index.
  • Application of multiple parameters Country.FR and StockIndex.NYSE will result in strategy receiving ONLY news that are related to NYSE stock index or that are related to France.

Filter keywords

Keyword filtering can be perceived as an extra filter on top of parameter filtering, since it drops from parameter filtering results the ones that don't match the given text string criteria.

News filter example

Consider filtering all today's news related to NYSE stock index or DJI stock index or USA or France. On top of that, take only news that contain words "Profit" and "Loss":

NewsFilter newsFilter = new NewsFilter();
newsFilter.setTimeFrame(NewsFilter.TimeFrame.TODAY);

//filter indicies
newsFilter.getStockIndicies().add(INewsFilter.StockIndex.NYSE);
newsFilter.getStockIndicies().add(INewsFilter.StockIndex.DJI);

//filter countries and regions
newsFilter.getCountries().add(INewsFilter.Country.US);
newsFilter.getCountries().add(INewsFilter.Country.FR);

//filter keywords
newsFilter.getKeywords().add("Profit");
newsFilter.getKeywords().add("Loss");

client.addNewsFilter(newsFilter);

NewsFilterMain.java NewsStrategyNoTrades.java

Calendar filter example

Consider filtering calendar events over 11th March of 2011 that are related to G7 countries. On top of that, take only events that contain one of the three keywords: "Treasury", "GDP", "trade":

CalendarFilter calendarFilter = new CalendarFilter();
calendarFilter.setTimeFrame(NewsFilter.TimeFrame.SPECIFIC_DATE);

// custom historical interval
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
Date dateFrom = dateFormat.parse("2011-03-11");
calendarFilter.setFrom(dateFrom);       

//filter countries and regions
newsFilter.getCountries().add(INewsFilter.Country.G7);

//filter keywords
calendarFilter.getKeywords().add("Treasury");
calendarFilter.getKeywords().add("GDP");
calendarFilter.getKeywords().add("trade");

client.addNewsFilter(calendarFilter);

NewsFilterMain.java NewsStrategyNoTrades.java

Compile a strategy to a jfx file

By using the IClient.compileStrategy method, one can compile a strategy from his standalone program. For instance:

client.compileStrategy(new File("C:/temp/MyStrategy.java"), false);
The information on this web site is provided only as general information, which may be incomplete or outdated. Click here for full disclaimer.