main.java.robot.GUIModeChartTypes.java Source code

Java tutorial

Introduction

Here is the source code for main.java.robot.GUIModeChartTypes.java

Source

/*
 * Copyright (c) 2009 Dukascopy (Suisse) SA. All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * -Redistribution of source code must retain the above copyright notice, this
 *  list of conditions and the following disclaimer.
 *
 * -Redistribution in binary form must reproduce the above copyright notice,
 *  this list of conditions and the following disclaimer in the documentation
 *  and/or other materials provided with the distribution.
 * 
 * Neither the name of Dukascopy (Suisse) SA or the names of contributors may
 * be used to endorse or promote products derived from this software without
 * specific prior written permission.
 *
 * This software is provided "AS IS," without a warranty of any kind. ALL
 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
 * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
 * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. DUKASCOPY (SUISSE) SA ("DUKASCOPY")
 * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
 * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
 * DERIVATIVES. IN NO EVENT WILL DUKASCOPY OR ITS LICENSORS BE LIABLE FOR ANY LOST
 * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
 * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
 * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
 * EVEN IF DUKASCOPY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 */
package main.java.robot;

import com.dukascopy.api.*;
import com.dukascopy.api.feed.FeedDescriptor;
import com.dukascopy.api.feed.IFeedDescriptor;
import com.dukascopy.api.system.ISystemListener;
import com.dukascopy.api.system.ITesterClient;
import com.dukascopy.api.system.TesterFactory;
import com.dukascopy.api.system.tester.*;
import main.java.jforex.TooSimple;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Future;

import static com.dukascopy.api.DataType.*;
import static com.dukascopy.api.Instrument.*;
import static com.dukascopy.api.PriceRange.*;
import static com.dukascopy.api.TickBarSize.*;

/**
 * This small program demonstrates how to initialize Dukascopy tester and start a strategy in GUI mode
 */
@SuppressWarnings("serial")
public class GUIModeChartTypes extends JFrame implements ITesterUserInterface, ITesterExecution {
    private static final Logger LOGGER = LoggerFactory.getLogger(GUIModeChartTypes.class);

    private final int frameWidth = 1000;
    private final int frameHeight = 600;
    private final int controlPanelHeight = 40;

    private JPanel currentChartPanel = null;
    private ITesterExecutionControl executionControl = null;

    private JPanel controlPanel = null;
    private JButton startStrategyButton = null;
    private JButton pauseButton = null;
    private JButton continueButton = null;
    private JButton cancelButton = null;

    private FeedDescriptorPanel feedDescriptorPanel;
    private ITesterChartController chartController;
    private IChart currentChart;
    private IFeedDescriptor feedDescriptor = new FeedDescriptor();

    //url of the DEMO jnlp
    private static String jnlpUrl = "https://www.dukascopy.com/client/demo/jclient/jforex.jnlp";
    //user name
    private static String userName = "DEMO2FSehY";
    //password
    private static String password = "FSehY";

    public GUIModeChartTypes() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        getContentPane().setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS));
    }

    @Override
    public void setChartPanels(Map<IChart, ITesterGui> chartPanels) {
        if (chartPanels != null && chartPanels.size() > 0) {

            IChart chart = chartPanels.keySet().iterator().next();

            //Note we assume we work with only one chart;
            currentChart = chart;
            chartController = chartPanels.get(chart).getTesterChartController();

            setTitle("Chart type example");

            chartController.setFeedDescriptor(feedDescriptor);
            JPanel chartPanel = chartPanels.get(chart).getChartPanel();
            addChartPanel(chartPanel);
        }
    }

    @Override
    public void setExecutionControl(ITesterExecutionControl executionControl) {
        this.executionControl = executionControl;
    }

    public void startStrategy() 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);
                updateButtons();
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }

            @Override
            public void onStop(long processId) {
                LOGGER.info("Strategy stopped: " + processId);
                resetButtons();

                File reportFile = new File("C:\\report.html");
                try {
                    client.createReport(processId, reportFile);
                } catch (Exception e) {
                    LOGGER.error(e.getMessage(), e);
                }
                if (client.getStartedStrategies().size() == 0) {
                    //Do nothing
                }
            }

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

            @Override
            public void onDisconnect() {
                //tester doesn't disconnect
            }
        });

        DateTimeFormatter dtf = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm");
        DateTime from = DateTime.parse("2015-06-10 00:00", dtf);
        DateTime to = DateTime.parse("2015-06-10 11:00", dtf);

        client.setDataInterval(Period.TICK, OfferSide.BID, ITesterClient.InterpolationMethod.OPEN_TICK,
                from.getMillis(), to.getMillis());

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

        //set instruments that will be used in testing
        final Set<Instrument> instruments = new HashSet<Instrument>();
        instruments.add(Instrument.EURUSD);

        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();
        //start the strategy
        LOGGER.info("Starting strategy");

        client.startStrategy(new TooSimple(), new LoadingProgressListener() {
            @Override
            public void dataLoaded(long startTime, long endTime, long currentTime, String information) {
                LOGGER.info("dataLoaded " + information);
            }

            @Override
            public void loadingFinished(boolean allDataLoaded, long startTime, long endTime, long currentTime) {
                LOGGER.info("loadingFinished " + allDataLoaded);
            }

            @Override
            public boolean stopJob() {
                return false;
            }
        }, this, this);
        //now it's running

        //In the current implementation it takes prolonged time for some chart types to load (e.g. range bars, renko),
        //so we hold up execution for maximum 5 minutes till the chart gets loaded.
        //For quicker loading please manually decrease chart's horizontal scale - it gets printed every second.
        Runnable r2 = new Runnable() {
            public void run() {
                try {
                    int waitTimeSecs = 300;
                    LOGGER.info("Pause execution for max " + waitTimeSecs + " secs till chart gets loaded. "
                            + "For quicker loading please decrease currentChart.getBarsCount() - manually decrease chart's horizontal scale.");
                    executionControl.pauseExecution();
                    updateButtons();
                    long startTime = System.currentTimeMillis();
                    try {
                        while ((currentChart == null || Math.abs(currentChart.priceMin(0)) < 0.00001)
                                && System.currentTimeMillis() - startTime < waitTimeSecs * 1000) {
                            if (currentChart != null) {
                                int secsLeft = (int) (waitTimeSecs
                                        - (System.currentTimeMillis() - startTime) / 1000);
                                LOGGER.info(
                                        String.format("Min price=%.5f, bar count on chart=%s, time left=%s secs",
                                                currentChart.priceMin(0), currentChart.getBarsCount(), secsLeft));
                            }
                            Thread.sleep(1000);
                        }
                    } catch (Exception e2) {
                        LOGGER.error(e2.getMessage(), e2);
                        e2.printStackTrace();
                    }

                    LOGGER.info("Chart loaded after " + ((System.currentTimeMillis() - startTime) / 1000)
                            + " secs. Please press continue.");
                } catch (Exception e2) {
                    LOGGER.error(e2.getMessage(), e2);
                    e2.printStackTrace();
                }
            }
        };
        Thread t2 = new Thread(r2);
        t2.start();

    }

    private class FeedDescriptorPanel extends JPanel {

        private JComboBox comboBoxDataType;
        private JComboBox comboBoxInstrument;
        private JComboBox comboBoxOfferSide;
        private JComboBox comboBoxFilter;
        private JComboBox comboBoxPeriod;
        private JComboBox comboBoxPriceRange;
        private JComboBox comboBoxReversalAmount;
        private JComboBox comboBoxTickBarSize;
        private JButton buttonApplyChanges;

        public FeedDescriptorPanel() {

            this.setLayout(new FlowLayout(FlowLayout.LEFT));

            comboBoxDataType = setupComboBox(DataType.values(), "Data type", DataType.TIME_PERIOD_AGGREGATION);
            comboBoxInstrument = setupComboBox(new Instrument[] { EURUSD, USDJPY, USDCAD }, "Instrument", EURUSD);
            comboBoxOfferSide = setupComboBox(OfferSide.values(), "Offer Side", OfferSide.BID);
            comboBoxFilter = setupComboBox(Filter.values(), "Filter", Filter.NO_FILTER);
            comboBoxPeriod = setupComboBox(Period.values(), "Period", Period.TEN_MINS);
            comboBoxPriceRange = setupComboBox(
                    new PriceRange[] { ONE_PIP, TWO_PIPS, THREE_PIPS, FOUR_PIPS, FIVE_PIPS, SIX_PIPS },
                    "Price Range", TWO_PIPS);
            comboBoxReversalAmount = setupComboBox(
                    new ReversalAmount[] { ReversalAmount.ONE, ReversalAmount.TWO, ReversalAmount.THREE },
                    "Reversal Amount", ReversalAmount.TWO);
            comboBoxTickBarSize = setupComboBox(new TickBarSize[] { TWO, THREE, FOUR, FIVE }, "Tick Bar Size",
                    THREE);

            add(comboBoxDataType);
            add(comboBoxPeriod);
            add(comboBoxInstrument);
            add(comboBoxOfferSide);
            add(comboBoxFilter);
            add(comboBoxPriceRange);
            add(comboBoxReversalAmount);
            add(comboBoxTickBarSize);

            buttonApplyChanges = new JButton("Apply changes");
            buttonApplyChanges.addActionListener(new ActionListener() {

                @Override
                public void actionPerformed(ActionEvent e) {
                    updateFeedDesciptor();

                }

            });

            add(buttonApplyChanges);

            updateFeedDesciptor();
            updateComboBoxes();
        }

        private JComboBox setupComboBox(final Object items[], String name, Object defaultValue) {
            JComboBox comboBox = new JComboBox(items);
            comboBox.setSelectedItem(defaultValue);
            comboBox.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    updateComboBoxes();
                }

            });
            comboBox.setToolTipText(name);
            return comboBox;
        }

        private void updateComboBoxes() {

            DataType dataType = (DataType) comboBoxDataType.getSelectedItem();

            //visibility conditions according to IFeedDescription interface documentation
            comboBoxDataType.setVisible(true);
            comboBoxInstrument.setVisible(true);
            comboBoxOfferSide.setVisible(dataType != TICKS);
            comboBoxFilter.setVisible(dataType == TIME_PERIOD_AGGREGATION);
            comboBoxPeriod.setVisible(dataType == TIME_PERIOD_AGGREGATION);
            comboBoxPriceRange.setVisible(
                    dataType == PRICE_RANGE_AGGREGATION || dataType == POINT_AND_FIGURE || dataType == RENKO);
            comboBoxReversalAmount.setVisible(dataType == POINT_AND_FIGURE);
            comboBoxTickBarSize.setVisible(dataType == TICK_BAR);

        }

        private void updateFeedDesciptor() {

            feedDescriptor.setDataType((DataType) comboBoxDataType.getSelectedItem());
            feedDescriptor.setInstrument((Instrument) comboBoxInstrument.getSelectedItem());
            feedDescriptor.setPeriod((Period) comboBoxPeriod.getSelectedItem());
            feedDescriptor.setOfferSide((OfferSide) comboBoxOfferSide.getSelectedItem());
            feedDescriptor.setFilter((Filter) comboBoxFilter.getSelectedItem());
            feedDescriptor.setPriceRange((PriceRange) comboBoxPriceRange.getSelectedItem());
            feedDescriptor.setReversalAmount((ReversalAmount) comboBoxReversalAmount.getSelectedItem());
            feedDescriptor.setTickBarSize((TickBarSize) comboBoxTickBarSize.getSelectedItem());

            if (chartController != null)
                chartController.setFeedDescriptor(feedDescriptor);
        }

    }

    /**
     * Center a frame on the screen
     */
    private void centerFrame() {
        Toolkit tk = Toolkit.getDefaultToolkit();
        Dimension screenSize = tk.getScreenSize();
        int screenHeight = screenSize.height;
        int screenWidth = screenSize.width;
        setSize(screenWidth / 4, screenHeight / 2);
        setLocation(200, screenHeight / 4);
    }

    /**
     * Add chart panel to the frame
     * @param chartPanel panel
     */
    private void addChartPanel(JPanel chartPanel) {
        removecurrentChartPanel();

        this.currentChartPanel = chartPanel;
        chartPanel.setPreferredSize(new Dimension(frameWidth, frameHeight - controlPanelHeight));
        chartPanel.setMinimumSize(new Dimension(frameWidth, 200));
        chartPanel.setMaximumSize(new Dimension(Short.MAX_VALUE, Short.MAX_VALUE));
        getContentPane().add(chartPanel);
        this.validate();
        chartPanel.repaint();
    }

    /**
     * Add buttons to start/pause/continue/cancel actions
     */
    private void addControlPanel() {

        controlPanel = new JPanel();
        FlowLayout flowLayout = new FlowLayout(FlowLayout.LEFT);
        controlPanel.setLayout(flowLayout);
        controlPanel.setPreferredSize(new Dimension(frameWidth, controlPanelHeight));
        controlPanel.setMinimumSize(new Dimension(frameWidth, controlPanelHeight));
        controlPanel.setMaximumSize(new Dimension(Short.MAX_VALUE, controlPanelHeight));

        startStrategyButton = new JButton("Start strategy");
        startStrategyButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                startStrategyButton.setEnabled(false);
                Runnable r = new Runnable() {
                    public void run() {
                        try {
                            startStrategy();
                        } catch (Exception e2) {
                            LOGGER.error(e2.getMessage(), e2);
                            e2.printStackTrace();
                            resetButtons();
                        }
                    }
                };
                Thread t = new Thread(r);
                t.start();

            }
        });

        pauseButton = new JButton("Pause");
        pauseButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (executionControl != null) {
                    executionControl.pauseExecution();
                    updateButtons();
                }
            }
        });

        continueButton = new JButton("Continue");
        continueButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (executionControl != null) {
                    executionControl.continueExecution();
                    updateButtons();
                }
            }
        });

        cancelButton = new JButton("Cancel");
        cancelButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (executionControl != null) {
                    executionControl.cancelExecution();
                    updateButtons();
                }
            }
        });

        controlPanel.add(startStrategyButton);
        controlPanel.add(pauseButton);
        controlPanel.add(continueButton);
        controlPanel.add(cancelButton);
        getContentPane().add(controlPanel);
        feedDescriptorPanel = new FeedDescriptorPanel();
        getContentPane().add(feedDescriptorPanel);

        pauseButton.setEnabled(false);
        continueButton.setEnabled(false);
        cancelButton.setEnabled(false);
    }

    private void updateButtons() {
        if (executionControl != null) {
            startStrategyButton.setEnabled(executionControl.isExecutionCanceled());
            pauseButton
                    .setEnabled(!executionControl.isExecutionPaused() && !executionControl.isExecutionCanceled());
            cancelButton.setEnabled(!executionControl.isExecutionCanceled());
            continueButton.setEnabled(executionControl.isExecutionPaused());
        }
    }

    private void resetButtons() {
        startStrategyButton.setEnabled(true);
        pauseButton.setEnabled(false);
        continueButton.setEnabled(false);
        cancelButton.setEnabled(false);
    }

    private void removecurrentChartPanel() {
        if (this.currentChartPanel != null) {
            try {
                SwingUtilities.invokeAndWait(new Runnable() {
                    @Override
                    public void run() {
                        GUIModeChartTypes.this.getContentPane().remove(GUIModeChartTypes.this.currentChartPanel);
                        GUIModeChartTypes.this.getContentPane().repaint();
                    }
                });
            } catch (Exception e) {
                LOGGER.error(e.getMessage(), e);
            }
        }
    }

    public void showChartFrame() {
        setSize(frameWidth, frameHeight);
        centerFrame();
        addControlPanel();
        setVisible(true);
    }

    public static void main(String[] args) throws Exception {
        GUIModeChartTypes testerMainGUI = new GUIModeChartTypes();
        testerMainGUI.showChartFrame();
    }
}