com.jgoetsch.tradeframework.marketdata.HistoricalMarketDataFeed.java Source code

Java tutorial

Introduction

Here is the source code for com.jgoetsch.tradeframework.marketdata.HistoricalMarketDataFeed.java

Source

/*
 * Copyright (c) 2012 Jeremy Goetsch
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.jgoetsch.tradeframework.marketdata;

import java.io.IOException;
import java.util.Date;

import org.joda.time.DateTime;
import org.joda.time.DateTimeConstants;
import org.joda.time.DateTimeZone;
import org.joda.time.LocalTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.jgoetsch.tradeframework.Contract;
import com.jgoetsch.tradeframework.InvalidContractException;
import com.jgoetsch.tradeframework.OHLC;
import com.jgoetsch.tradeframework.TFUtils;
import com.jgoetsch.tradeframework.data.HistoricalDataSource;
import com.jgoetsch.tradeframework.data.DataUnavailableException;
import com.jgoetsch.tradeframework.data.HistoricalDataUtils;

public class HistoricalMarketDataFeed extends SimulatedMarketDataFeed {

    private final Logger log = LoggerFactory.getLogger(HistoricalMarketDataFeed.class);

    private final HistoricalDataSource historicalDataSource;
    private final Contract contract;
    private final int dataPeriod;
    private final int bufferLength;

    private long curTimestamp;
    private long bufferEndTime;
    private OHLC[] data;
    private int dataIndex;

    public HistoricalMarketDataFeed(Contract contract, HistoricalDataSource historicalDataSource, int period,
            int bufferLength) {
        this.contract = contract;
        this.historicalDataSource = historicalDataSource;
        this.dataPeriod = period;
        this.bufferLength = bufferLength;
    }

    @Override
    protected final MarketData retrieveNextTick() throws IOException, InvalidContractException {
        if (curTimestamp == 0)
            throw new IllegalStateException("Time not initialized");
        boolean newTime = (data == null);

        while (data == null || dataIndex >= data.length) {
            try {
                bufferEndTime = adjustTimestampToRTH(bufferEndTime, contract);
                bufferEndTime += HistoricalDataUtils.getPeriodDurationInMillis(dataPeriod) * bufferLength;
                if (log.isDebugEnabled())
                    log.debug("Requesting historical data for " + contract + " from " + TFUtils.getDateFormat()
                            .print(bufferEndTime
                                    - HistoricalDataUtils.getPeriodDurationInMillis(dataPeriod) * bufferLength)
                            + " to " + TFUtils.getDateFormat().print(bufferEndTime));
                data = historicalDataSource.getHistoricalData(contract, new Date(bufferEndTime), bufferLength,
                        dataPeriod);
            } catch (DataUnavailableException e) {
                return null;
            }
            if (data == null)
                return null;
            if (log.isTraceEnabled())
                log.trace("Received historical data for " + contract + " from "
                        + TFUtils.getDateFormat().print(data[0].getDate().getTime()) + " to "
                        + TFUtils.getDateFormat().print(data[data.length - 1].getDate().getTime())
                        + ", starting at " + TFUtils.getDateFormat().print(curTimestamp));

            dataIndex = 0;
            while (dataIndex < data.length && data[dataIndex].getDate().getTime() <= curTimestamp)
                dataIndex++;
            if (newTime && dataIndex > 0)
                dataIndex--;
        }

        MarketData mkd = marketDataFromBar(data[dataIndex++]);
        curTimestamp = mkd.getTimestamp();
        return mkd;
    }

    @Override
    public final void advanceTo(long timestamp) throws IOException, InvalidContractException {
        if (timestamp > curTimestamp) {
            data = null;
            curTimestamp = timestamp;
            bufferEndTime = curTimestamp;
            reset();
            setLastTick(retrieveNextTick());
        }
    }

    protected MarketData marketDataFromBar(OHLC ohlc) {
        SimpleMarketData mkd = new SimpleMarketData();
        mkd.setLast(ohlc.getOpen());
        mkd.setBid(mkd.getLast() - 0.00);
        mkd.setAsk(mkd.getLast() + 0.00);
        mkd.setBidSize(10000);
        mkd.setAskSize(10000);
        mkd.setTimestamp(ohlc.getDate().getTime());
        mkd.setLastTimestamp(ohlc.getDate().getTime());
        return mkd;
    }

    /**
     * Overridable method to adjust a timestamp to the next regular trading session
     * of the given contract if it falls outside of the contract's regular trading hours.
     * 
     * @param timestamp
     * @param contract
     * @return millisecond timestamp adjusted up to a regular trading session.
     */
    protected long adjustTimestampToRTH(long timestamp, Contract contract) {
        if ("STK".equals(contract.getType()) && "USD".equals(contract.getCurrency())) {
            DateTime dt = new DateTime(timestamp, DateTimeZone.forID("America/New_York"));
            LocalTime time = new LocalTime(dt);
            if (time.compareTo(new LocalTime(9, 30)) < 0)
                dt = dt.withHourOfDay(9).withMinuteOfHour(30);
            else if (time.compareTo(new LocalTime(16, 0)) >= 0) {
                dt = dt.plusDays(1).withHourOfDay(9).withMinuteOfHour(30);
            }
            if (dt.getDayOfWeek() == DateTimeConstants.SATURDAY)
                dt = dt.plusDays(2);
            else if (dt.getDayOfWeek() == DateTimeConstants.SUNDAY)
                dt = dt.plusDays(1);
            return dt.getMillis();
        } else if ("FUT".equals(contract.getType()) && "USD".equals(contract.getCurrency())) {
            DateTime dt = new DateTime(timestamp, DateTimeZone.forID("America/Chicago"));
            if (dt.getDayOfWeek() == DateTimeConstants.SATURDAY)
                dt = dt.plusDays(2).withHourOfDay(9).withMinuteOfHour(0);
            else if (dt.getDayOfWeek() == DateTimeConstants.SUNDAY)
                dt = dt.plusDays(1).withHourOfDay(9).withMinuteOfHour(0);
            return dt.getMillis();
        } else
            return timestamp;
    }

    public final void close() throws IOException {
        data = null;
    }

}