OCO Orders

The following strategy creates two opposite limit orders at the specified time. After one of the limit orders is filled, the strategy removes the opposite order, like the OCO (One Cancels Other) orders.

import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.TimeZone;
import com.dukascopy.api.*;
import com.dukascopy.api.IEngine.OrderCommand;

The strategy has 4 configurable parameters:

  • Bar open time when to create orders
  • Bar period
  • Buy Limit Price
  • Sell Limit Price
public class SimulateOCOStrategy implements IStrategy {
    private IEngine engine = null;
    private IHistory history;
    private int counter = 0;
    private SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm"); 
    @Configurable("Trade time GMT")
    public String startTradeTime = "07:10";
    @Configurable("Period")
    public Period selectedPeriod = Period.FIVE_MINS;
    @Configurable("BUY price")
    public double longPrice = 1.3425;
    @Configurable("SELL price")
    public double shortPrice = 1.3435;
    private HashMap<String, IOrder> createdOrders = new HashMap <String, IOrder>();
    private String parsedStartTime ;

    public void onStart(IContext context) throws JFException {
            engine = context.getEngine();
            this.history = context.getHistory(); 
            dateFormat.setTimeZone(TimeZone.getTimeZone("GMT")); 
            parsedStartTime = startTradeTime.replace(":", "");
    }

    public void onStop() throws JFException {
    }

    public void onTick(Instrument instrument, ITick tick) throws JFException  {
    }

If selected period bar start time match specified trade time, then two orders are created. Orders are saved in a map.

    public void onBar(Instrument instrument, Period period, IBar askbar, IBar bidbar) throws JFException {

        if (instrument.equals(Instrument.EURUSD) && period.equals(selectedPeriod) &&
                (isValidOrderTime(history.getNextBarStart(period, askbar.getTime())))) {

            IOrder longOrder = engine.submitOrder(
                    getLabel(instrument),
                    instrument,
                    IEngine.OrderCommand.BUYLIMIT,
                    0.01,
                    longPrice,
                    0,
                    askbar.getLow() - (5 * instrument.getPipValue()),
                    askbar.getHigh() + (5 * instrument.getPipValue()));
            createdOrders.put("long", longOrder);

            IOrder shortOrder = engine.submitOrder(
                    getLabel(instrument),
                    instrument,
                    IEngine.OrderCommand.SELLLIMIT,
                    0.01,
                    shortPrice,
                    0,
                    askbar.getHigh() + (5 * instrument.getPipValue()),
                    askbar.getLow() - (5 * instrument.getPipValue()));
            createdOrders.put("short", shortOrder);
        }
    }

    private boolean isValidOrderTime(long tickTime) {
         String formattedTickTime = dateFormat.format(tickTime); 
         formattedTickTime = formattedTickTime.replace(":", "");

         int tickTimeValue = Integer.parseInt(formattedTickTime);
         int startTimeValue = Integer.parseInt(parsedStartTime);
         return tickTimeValue == startTimeValue;
    }

    protected String getLabel(Instrument instrument) {
                String label = instrument.name();
                label = label + (counter ++);
                label = label.toUpperCase();
                return label;
    }

The onMessage method closes the sell order if the buy order is filled and vice versa.

    public void onMessage(IMessage message) throws JFException {
                if (message.getType().equals(IMessage.Type.ORDER_FILL_OK)) {
                        IOrder order = message.getOrder();
                        if (order.isLong()) {
                                createdOrders.get("short").close();
                        } else {
                                createdOrders.get("long").close();
                        }
                }
    }

    public void onAccount(IAccount account) throws JFException  {
    }
}

SimulateOCOStrategy.java

The information on this web site is provided only as general information, which may be incomplete or outdated. Click here for full disclaimer.