ch.algotrader.service.algo.VWAPOrderServiceTest.java Source code

Java tutorial

Introduction

Here is the source code for ch.algotrader.service.algo.VWAPOrderServiceTest.java

Source

/***********************************************************************************
 * AlgoTrader Enterprise Trading Framework
 *
 * Copyright (C) 2015 AlgoTrader GmbH - All rights reserved
 *
 * All information contained herein is, and remains the property of AlgoTrader GmbH.
 * The intellectual and technical concepts contained herein are proprietary to
 * AlgoTrader GmbH. Modification, translation, reverse engineering, decompilation,
 * disassembly or reproduction of this material is strictly forbidden unless prior
 * written permission is obtained from AlgoTrader GmbH
 *
 * Fur detailed terms and conditions consult the file LICENSE.txt or contact
 *
 * AlgoTrader GmbH
 * Aeschstrasse 6
 * 8834 Schindellegi
 ***********************************************************************************/
package ch.algotrader.service.algo;

import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;
import java.util.TreeMap;

import org.apache.commons.lang.time.DateUtils;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.context.ApplicationContext;

import ch.algotrader.entity.exchange.Exchange;
import ch.algotrader.entity.marketData.Bar;
import ch.algotrader.entity.security.Security;
import ch.algotrader.entity.security.SecurityFamily;
import ch.algotrader.entity.security.Stock;
import ch.algotrader.entity.strategy.Strategy;
import ch.algotrader.entity.trade.Fill;
import ch.algotrader.entity.trade.OrderStatus;
import ch.algotrader.entity.trade.OrderStatusVO;
import ch.algotrader.entity.trade.OrderStatusVOBuilder;
import ch.algotrader.entity.trade.OrderValidationException;
import ch.algotrader.entity.trade.SimpleOrder;
import ch.algotrader.entity.trade.algo.VWAPOrder;
import ch.algotrader.enumeration.Currency;
import ch.algotrader.enumeration.Duration;
import ch.algotrader.enumeration.MarketDataEventType;
import ch.algotrader.enumeration.Side;
import ch.algotrader.enumeration.Status;
import ch.algotrader.enumeration.TimePeriod;
import ch.algotrader.service.CalendarService;
import ch.algotrader.service.HistoricalDataService;
import ch.algotrader.service.OrderExecutionService;
import ch.algotrader.service.SimpleOrderService;
import ch.algotrader.util.BeanUtil;
import ch.algotrader.util.DateUtil;

/**
 * @author <a href="mailto:aflury@algotrader.ch">Andy Flury</a>
 */
@RunWith(MockitoJUnitRunner.class)
public class VWAPOrderServiceTest {

    @Mock
    private OrderExecutionService orderExecutionService;

    @Mock
    private SimpleOrderService simpleOrderService;

    @Mock
    private HistoricalDataService historicalDataService;

    @Mock
    private CalendarService calendarService;

    @Mock
    private ApplicationContext applicationContext;

    private VWAPOrderService vwapOrderService;

    private Security security;
    private Strategy strategy;
    private Exchange exchange;
    private String intId = "XYZ";
    private List<Bar> historicalBars;
    private Duration bucketSize = Duration.MIN_15;
    private int lookBackDays = 1;

    @Before
    public void setup() {

        this.vwapOrderService = new VWAPOrderService(this.orderExecutionService, this.calendarService,
                this.simpleOrderService);
        this.vwapOrderService.setApplicationContext(this.applicationContext);

        Mockito.when(this.applicationContext.getBean(HistoricalDataService.class))
                .thenReturn(this.historicalDataService);

        this.exchange = Exchange.Factory.newInstance("TEST_EXCHANGE", TimeZone.getDefault().toString());
        this.exchange.setId(1);

        SecurityFamily family = SecurityFamily.Factory.newInstance("", Currency.USD, 1, 2, "0<0.01", true, false);
        family.setExchange(this.exchange);

        this.security = Stock.Factory.newInstance(family);
        this.security.setSymbol("TEST_SECURITY");
        this.security.setId(1);

        this.strategy = Strategy.Factory.newInstance("TEST_STRATEGY", false);

        this.historicalBars = new ArrayList<Bar>();
        this.historicalBars.add(Bar.Factory.newInstance(DateUtil.dateForYMDHMS(2016, 1, 1, 9, 0, 0), null,
                this.security, Duration.MIN_15, null, null, null, null, 9123));
        this.historicalBars.add(Bar.Factory.newInstance(DateUtil.dateForYMDHMS(2016, 1, 1, 9, 15, 0), null,
                this.security, Duration.MIN_15, null, null, null, null, 7061));
        this.historicalBars.add(Bar.Factory.newInstance(DateUtil.dateForYMDHMS(2016, 1, 1, 9, 30, 0), null,
                this.security, Duration.MIN_15, null, null, null, null, 7635));
        this.historicalBars.add(Bar.Factory.newInstance(DateUtil.dateForYMDHMS(2016, 1, 1, 9, 45, 0), null,
                this.security, Duration.MIN_15, null, null, null, null, 6984));
        this.historicalBars.add(Bar.Factory.newInstance(DateUtil.dateForYMDHMS(2016, 1, 1, 10, 0, 0), null,
                this.security, Duration.MIN_15, null, null, null, null, 8671));
        this.historicalBars.add(Bar.Factory.newInstance(DateUtil.dateForYMDHMS(2016, 1, 1, 10, 15, 0), null,
                this.security, Duration.MIN_15, null, null, null, null, 7703));
        this.historicalBars.add(Bar.Factory.newInstance(DateUtil.dateForYMDHMS(2016, 1, 1, 10, 30, 0), null,
                this.security, Duration.MIN_15, null, null, null, null, 6531));
        this.historicalBars.add(Bar.Factory.newInstance(DateUtil.dateForYMDHMS(2016, 1, 1, 10, 45, 0), null,
                this.security, Duration.MIN_15, null, null, null, null, 8234));
        this.historicalBars.add(Bar.Factory.newInstance(DateUtil.dateForYMDHMS(2016, 1, 1, 11, 0, 0), null,
                this.security, Duration.MIN_15, null, null, null, null, 5930));
        this.historicalBars.add(Bar.Factory.newInstance(DateUtil.dateForYMDHMS(2016, 1, 1, 11, 15, 0), null,
                this.security, Duration.MIN_15, null, null, null, null, 8151));
        this.historicalBars.add(Bar.Factory.newInstance(DateUtil.dateForYMDHMS(2016, 1, 1, 11, 30, 0), null,
                this.security, Duration.MIN_15, null, null, null, null, 6053));
        this.historicalBars.add(Bar.Factory.newInstance(DateUtil.dateForYMDHMS(2016, 1, 1, 11, 45, 0), null,
                this.security, Duration.MIN_15, null, null, null, null, 7192));
        this.historicalBars.add(Bar.Factory.newInstance(DateUtil.dateForYMDHMS(2016, 1, 1, 12, 0, 0), null,
                this.security, Duration.MIN_15, null, null, null, null, 6314));
        this.historicalBars.add(Bar.Factory.newInstance(DateUtil.dateForYMDHMS(2016, 1, 1, 12, 15, 0), null,
                this.security, Duration.MIN_15, null, null, null, null, 6391));
        this.historicalBars.add(Bar.Factory.newInstance(DateUtil.dateForYMDHMS(2016, 1, 1, 12, 30, 0), null,
                this.security, Duration.MIN_15, null, null, null, null, 5838));
        this.historicalBars.add(Bar.Factory.newInstance(DateUtil.dateForYMDHMS(2016, 1, 1, 12, 45, 0), null,
                this.security, Duration.MIN_15, null, null, null, null, 6128));
        this.historicalBars.add(Bar.Factory.newInstance(DateUtil.dateForYMDHMS(2016, 1, 1, 13, 0, 0), null,
                this.security, Duration.MIN_15, null, null, null, null, 6249));
        this.historicalBars.add(Bar.Factory.newInstance(DateUtil.dateForYMDHMS(2016, 1, 1, 13, 15, 0), null,
                this.security, Duration.MIN_15, null, null, null, null, 7025));
        this.historicalBars.add(Bar.Factory.newInstance(DateUtil.dateForYMDHMS(2016, 1, 1, 13, 30, 0), null,
                this.security, Duration.MIN_15, null, null, null, null, 5997));
        this.historicalBars.add(Bar.Factory.newInstance(DateUtil.dateForYMDHMS(2016, 1, 1, 13, 45, 0), null,
                this.security, Duration.MIN_15, null, null, null, null, 6658));
        this.historicalBars.add(Bar.Factory.newInstance(DateUtil.dateForYMDHMS(2016, 1, 1, 14, 0, 0), null,
                this.security, Duration.MIN_15, null, null, null, null, 6946));
        this.historicalBars.add(Bar.Factory.newInstance(DateUtil.dateForYMDHMS(2016, 1, 1, 14, 15, 0), null,
                this.security, Duration.MIN_15, null, null, null, null, 4920));
        this.historicalBars.add(Bar.Factory.newInstance(DateUtil.dateForYMDHMS(2016, 1, 1, 14, 30, 0), null,
                this.security, Duration.MIN_15, null, null, null, null, 5094));
        this.historicalBars.add(Bar.Factory.newInstance(DateUtil.dateForYMDHMS(2016, 1, 1, 14, 45, 0), null,
                this.security, Duration.MIN_15, null, null, null, null, 7601));
        this.historicalBars.add(Bar.Factory.newInstance(DateUtil.dateForYMDHMS(2016, 1, 1, 15, 0, 0), null,
                this.security, Duration.MIN_15, null, null, null, null, 7192));
        this.historicalBars.add(Bar.Factory.newInstance(DateUtil.dateForYMDHMS(2016, 1, 1, 15, 15, 0), null,
                this.security, Duration.MIN_15, null, null, null, null, 7482));
        this.historicalBars.add(Bar.Factory.newInstance(DateUtil.dateForYMDHMS(2016, 1, 1, 15, 30, 0), null,
                this.security, Duration.MIN_15, null, null, null, null, 7393));
        this.historicalBars.add(Bar.Factory.newInstance(DateUtil.dateForYMDHMS(2016, 1, 1, 15, 45, 0), null,
                this.security, Duration.MIN_15, null, null, null, null, 6295));
        this.historicalBars.add(Bar.Factory.newInstance(DateUtil.dateForYMDHMS(2016, 1, 1, 16, 0, 0), null,
                this.security, Duration.MIN_15, null, null, null, null, 5955));
        this.historicalBars.add(Bar.Factory.newInstance(DateUtil.dateForYMDHMS(2016, 1, 1, 16, 15, 0), null,
                this.security, Duration.MIN_15, null, null, null, null, 8821));
        this.historicalBars.add(Bar.Factory.newInstance(DateUtil.dateForYMDHMS(2016, 1, 1, 16, 30, 0), null,
                this.security, Duration.MIN_15, null, null, null, null, 7751));
        this.historicalBars.add(Bar.Factory.newInstance(DateUtil.dateForYMDHMS(2016, 1, 1, 16, 45, 0), null,
                this.security, Duration.MIN_15, null, null, null, null, 7976));
        this.historicalBars.add(Bar.Factory.newInstance(DateUtil.dateForYMDHMS(2016, 1, 1, 17, 0, 0), null,
                this.security, Duration.MIN_15, null, null, null, null, 9067));
        this.historicalBars.add(Bar.Factory.newInstance(DateUtil.dateForYMDHMS(2016, 1, 1, 17, 15, 0), null,
                this.security, Duration.MIN_15, null, null, null, null, 10569));

        Mockito.when(this.historicalDataService.getHistoricalBars(this.security.getId(), //
                DateUtils.truncate(new Date(), Calendar.DATE), //
                this.lookBackDays, //
                TimePeriod.DAY, //
                this.bucketSize, //
                MarketDataEventType.TRADES, //
                Collections.emptyMap())).thenReturn(this.historicalBars);

        Mockito.when(this.calendarService.isOpen(this.exchange.getId())).thenReturn(false);

        Mockito.when(this.calendarService.getNextOpenTime(this.exchange.getId()))
                .thenReturn(DateUtil.dateForYMDHMS(2016, 1, 1, 9, 00, 0));

        Mockito.when(this.calendarService.getNextCloseTime(this.exchange.getId()))
                .thenReturn(DateUtil.dateForYMDHMS(2016, 1, 1, 17, 30, 0));
    }

    @Test
    public void testPopulate() throws IllegalAccessException, InvocationTargetException, OrderValidationException {

        VWAPOrder order = new VWAPOrder();

        String nameValues = "side=BUY,quantity=2,bucketSize=MIN_15,lookbackDays=20,minInterval=60,maxInterval=129";

        Map<String, String> properties = new HashMap<>();
        for (String nameValue : nameValues.split(",")) {
            properties.put(nameValue.split("=")[0], nameValue.split("=")[1]);
        }

        BeanUtil.populate(order, properties);
    }

    @Test(expected = OrderValidationException.class)
    public void testValidateFail() throws OrderValidationException {

        VWAPOrder order = new VWAPOrder();

        order.validate();
    }

    @Test()
    public void testValidate() throws OrderValidationException {

        VWAPOrder order = createOrder();
        order.setQuantity(50000);
        order.setBucketSize(Duration.MIN_15);
        order.setLookbackPeriod(1);
        order.setMinInterval(60);
        order.setMaxInterval(60);

        order.validate();
    }

    @Test
    public void testCreateOrderState() throws OrderValidationException {

        VWAPOrder vwapOrder = createOrder();

        vwapOrder.setQuantity(50000);
        vwapOrder.setBucketSize(this.bucketSize);
        vwapOrder.setLookbackPeriod(this.lookBackDays);
        vwapOrder.setMinInterval(60);
        vwapOrder.setMaxInterval(60);
        vwapOrder.setStartTime(DateUtil.dateForYMDHMS(2016, 1, 1, 11, 0, 0));
        vwapOrder.setEndTime(DateUtil.dateForYMDHMS(2016, 1, 1, 15, 0, 0));

        VWAPOrderStateVO orderState = this.vwapOrderService.createAlgoOrderState(vwapOrder,
                DateUtil.dateForYMDHMS(2016, 1, 1, 10, 0, 0));

        Assert.assertEquals(0.4878, orderState.getParticipation(), 0.001);
    }

    @Test
    public void testSendOrderNoStartEndTime() throws OrderValidationException {

        VWAPOrder vwapOrder = createOrder();

        vwapOrder.setQuantity(50000);
        vwapOrder.setBucketSize(this.bucketSize);
        vwapOrder.setLookbackPeriod(this.lookBackDays);
        vwapOrder.setMinInterval(60);
        vwapOrder.setMaxInterval(60);

        VWAPOrderStateVO orderState = this.vwapOrderService.createAlgoOrderState(vwapOrder,
                DateUtil.dateForYMDHMS(2016, 1, 1, 9, 0, 0));

        Assert.assertEquals(510, vwapOrder.getDuration());

        Assert.assertEquals(0.2058, orderState.getParticipation(), 0.001);
    }

    @Test
    public void testSendOrderOddStartAndEnd() throws OrderValidationException {

        VWAPOrder vwapOrder = createOrder();

        vwapOrder.setQuantity(25000);
        vwapOrder.setBucketSize(this.bucketSize);
        vwapOrder.setLookbackPeriod(this.lookBackDays);
        vwapOrder.setMinInterval(60);
        vwapOrder.setMaxInterval(60);
        vwapOrder.setStartTime(DateUtil.dateForYMDHMS(2016, 1, 1, 11, 5, 0));
        vwapOrder.setEndTime(DateUtil.dateForYMDHMS(2016, 1, 1, 14, 52, 30));

        VWAPOrderStateVO orderState = this.vwapOrderService.createAlgoOrderState(vwapOrder,
                DateUtil.dateForYMDHMS(2016, 1, 1, 10, 0, 0));

        Assert.assertEquals(0.2585, orderState.getParticipation(), 0.001);
    }

    @Test
    public void testNextOrder() throws Exception {

        VWAPOrder vwapOrder = createOrder();

        vwapOrder.setQuantity(50000);
        vwapOrder.setBucketSize(this.bucketSize);
        vwapOrder.setLookbackPeriod(this.lookBackDays);
        vwapOrder.setMinInterval(60);
        vwapOrder.setMaxInterval(60);

        OrderStatusVO orderStatus = OrderStatusVOBuilder.create().setRemainingQuantity(1000).build();
        Mockito.when(this.orderExecutionService.getStatusByIntId(vwapOrder.getIntId())).thenReturn(orderStatus);

        Date dateTime = DateUtil.dateForYMDHMS(2016, 1, 1, 9, 0, 0);

        VWAPOrderStateVO orderState = this.vwapOrderService.createAlgoOrderState(vwapOrder, dateTime);
        this.vwapOrderService.sendNextOrder(vwapOrder, orderState, dateTime);

        ArgumentCaptor<SimpleOrder> argument = ArgumentCaptor.forClass(SimpleOrder.class);
        Mockito.verify(this.simpleOrderService, Mockito.times(1)).sendOrder(argument.capture());
        SimpleOrder childOrder = argument.getValue();

        Assert.assertEquals(125, childOrder.getQuantity());
    }

    @Test
    public void testReporting() {

        VWAPOrder vwapOrder = createOrder();

        vwapOrder.setQuantity(50000);
        vwapOrder.setBucketSize(this.bucketSize);
        vwapOrder.setLookbackPeriod(this.lookBackDays);
        vwapOrder.setMinInterval(60);
        vwapOrder.setMaxInterval(60);
        vwapOrder.setStartTime(DateUtil.dateForYMDHMS(2016, 1, 1, 11, 0, 0));
        vwapOrder.setEndTime(DateUtil.dateForYMDHMS(2016, 1, 1, 11, 10, 0));

        OrderStatus orderStatus = OrderStatus.Factory.newInstance();
        orderStatus.setOrder(vwapOrder);
        orderStatus.setStatus(Status.EXECUTED);

        List<Bar> oneMinuteBars = new ArrayList<>();
        oneMinuteBars.add(Bar.Factory.newInstance(DateUtil.dateForYMDHMS(2016, 1, 1, 11, 0, 0), null, this.security,
                Duration.MIN_15, null, null, null, null, 9, new BigDecimal("69.7716")));
        oneMinuteBars.add(Bar.Factory.newInstance(DateUtil.dateForYMDHMS(2016, 1, 1, 11, 1, 0), null, this.security,
                Duration.MIN_15, null, null, null, null, 21, new BigDecimal("69.7756")));
        oneMinuteBars.add(Bar.Factory.newInstance(DateUtil.dateForYMDHMS(2016, 1, 1, 11, 2, 0), null, this.security,
                Duration.MIN_15, null, null, null, null, 8, new BigDecimal("70.2361")));
        oneMinuteBars.add(Bar.Factory.newInstance(DateUtil.dateForYMDHMS(2016, 1, 1, 11, 3, 0), null, this.security,
                Duration.MIN_15, null, null, null, null, 13, new BigDecimal("70.0253")));
        oneMinuteBars.add(Bar.Factory.newInstance(DateUtil.dateForYMDHMS(2016, 1, 1, 11, 4, 0), null, this.security,
                Duration.MIN_15, null, null, null, null, 14, new BigDecimal("69.6608")));
        oneMinuteBars.add(Bar.Factory.newInstance(DateUtil.dateForYMDHMS(2016, 1, 1, 11, 5, 0), null, this.security,
                Duration.MIN_15, null, null, null, null, 35, new BigDecimal("69.8594")));
        oneMinuteBars.add(Bar.Factory.newInstance(DateUtil.dateForYMDHMS(2016, 1, 1, 11, 6, 0), null, this.security,
                Duration.MIN_15, null, null, null, null, 8, new BigDecimal("70.1897")));
        oneMinuteBars.add(Bar.Factory.newInstance(DateUtil.dateForYMDHMS(2016, 1, 1, 11, 7, 0), null, this.security,
                Duration.MIN_15, null, null, null, null, 13, new BigDecimal("69.846")));
        oneMinuteBars.add(Bar.Factory.newInstance(DateUtil.dateForYMDHMS(2016, 1, 1, 11, 8, 0), null, this.security,
                Duration.MIN_15, null, null, null, null, 12, new BigDecimal("70.3035")));
        oneMinuteBars.add(Bar.Factory.newInstance(DateUtil.dateForYMDHMS(2016, 1, 1, 11, 9, 0), null, this.security,
                Duration.MIN_15, null, null, null, null, 11, new BigDecimal("70.0386")));

        Mockito.when(this.historicalDataService.getHistoricalBars(Mockito.eq(this.security.getId()), //
                Mockito.any(), //
                Mockito.any(int.class), //
                Mockito.eq(TimePeriod.SEC), //
                Mockito.eq(Duration.MIN_1), //
                Mockito.eq(MarketDataEventType.TRADES), //
                Mockito.any())).thenReturn(oneMinuteBars);

        VWAPOrderStateVO algoOrderState = new VWAPOrderStateVO(.5, new TreeMap<>());
        algoOrderState.storeFill(createFill(9, "69.7716"));
        algoOrderState.storeFill(createFill(21, "69.7756"));
        algoOrderState.storeFill(createFill(8, "70.2361"));
        algoOrderState.storeFill(createFill(13, "70.0253"));
        algoOrderState.storeFill(createFill(14, "69.6608"));
        algoOrderState.storeFill(createFill(35, "69.8594"));
        algoOrderState.storeFill(createFill(8, "70.1897"));
        algoOrderState.storeFill(createFill(13, "69.846"));
        algoOrderState.storeFill(createFill(12, "70.3035"));
        algoOrderState.storeFill(createFill(11, "70.0386"));

        Map<String, Object> results = this.vwapOrderService.getResults(vwapOrder, algoOrderState,
                DateUtil.dateForYMDHMS(2016, 1, 1, 11, 10, 0));

        Assert.assertEquals(3, results.size());
        Assert.assertEquals(new BigDecimal("69.93"), results.get("price"));
        Assert.assertEquals(new BigDecimal("69.93"), results.get("benchmarkPrice"));
    }

    private VWAPOrder createOrder() {

        VWAPOrder vwapOrder = new VWAPOrder();
        vwapOrder.setIntId(this.intId);
        vwapOrder.setSecurity(this.security);
        vwapOrder.setStrategy(this.strategy);
        vwapOrder.setSide(Side.BUY);
        return vwapOrder;
    }

    private Fill createFill(int qty, String price) {
        Fill fill = new Fill();
        fill.setPrice(new BigDecimal(price));
        fill.setQuantity(qty);
        return fill;
    }

}