Dukascopy
 
 
Wiki JStore Search Login

APICLIENT-78 getBars(..., from, to) has empty gaps during backtest
 Post subject: APICLIENT-78 getBars(..., from, to) has empty gaps during backtest Post rating: 0   New post Posted: Mon 04 Jun, 2012, 14:53 

User rating: 1
Joined: Tue 20 Mar, 2012, 09:03
Posts: 41
With the following sample:
package de.invesdwin.forextrading.sample.bars;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import javax.annotation.concurrent.NotThreadSafe;

import org.apache.commons.lang3.time.FastDateFormat;

import com.dukascopy.api.Filter;
import com.dukascopy.api.IAccount;
import com.dukascopy.api.IBar;
import com.dukascopy.api.IContext;
import com.dukascopy.api.IMessage;
import com.dukascopy.api.IStrategy;
import com.dukascopy.api.ITick;
import com.dukascopy.api.Instrument;
import com.dukascopy.api.JFException;
import com.dukascopy.api.OfferSide;
import com.dukascopy.api.Period;
import com.dukascopy.api.system.ISystemListener;
import com.dukascopy.api.system.ITesterClient;
import com.dukascopy.api.system.TesterFactory;
import com.dukascopy.charts.data.datacache.CandleData;

import de.invesdwin.common.log.Log;
import de.invesdwin.forextrading.ForexProperties;

/**
 * This small program demonstrates how to initialize Dukascopy client and start a strategy
 */
@NotThreadSafe
public final class TimeBarsGapSample {

    //url of the DEMO jnlp

    private static final Log LOGGER = new Log(TimeBarsGapSample.class);
    public static final String FORMAT_ISO_DATE_TIME = "yyyy-MM-dd'T'HH:mm:ss";
    public static final String FORMAT_ISO_DATE_TIME_MS = FORMAT_ISO_DATE_TIME + ".SSS";

    private TimeBarsGapSample() {}

    //CHECKSTYLE:OFF
    public static void main(final String[] args) throws Exception {
        //CHECKSTYLE:ON
        //get the instance of the IClient interface
        final ITesterClient client = TesterFactory.getDefaultInstance();
        //set the listener that will receive system events
        client.setSystemListener(new ISystemListener() {
            private int lightReconnects = 3;

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

            @Override
            public void onStop(final 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() {
                LOGGER.warn("Disconnected");
                if (lightReconnects > 0) {
                    client.reconnect();
                    --lightReconnects;
                } else {
                    try {
                        //sleep for 10 seconds before attempting to reconnect
                        Thread.sleep(10000);
                    } catch (final InterruptedException e) {
                        e.printStackTrace();
                    }
                    try {
                        client.connect(ForexProperties.JFOREX_JNLP_URL.toString(),
                                ForexProperties.JFOREX_JNLP_USERNAME, ForexProperties.JFOREX_JNLP_PASSWORD);
                    } catch (final Exception e) {
                        LOGGER.error(e.getMessage(), e);
                    }
                }
            }
        });

        LOGGER.info("Connecting...");
        //connect to the server using jnlp, user name and password
        client.connect(ForexProperties.JFOREX_JNLP_URL.toString(), ForexProperties.JFOREX_JNLP_USERNAME,
                ForexProperties.JFOREX_JNLP_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);
        }

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

        LOGGER.info("Starting strategy");
        // CHECKSTYLE:OFF
        client.startStrategy(new IStrategy() {
            private IContext context;
            private CandleData lastCurrentBar;
            private CandleData lastPreviousBar;

            @Override
            public void onTick(final Instrument instrument, final ITick tick) throws JFException {
                if (instrument == Instrument.EURUSD) {

                    final JForexTickBarCache cache = new JForexTickBarCache();
                    final List<CandleData> currentBars = cache.getBars(tick.getTime());
                    final CandleData currentBar = currentBars.get(currentBars.size() - 1);
                    final long previousTime = currentBar.getTime() - 1;
                    final List<CandleData> previousBars = cache.getBars(previousTime);
                    final CandleData previousBar = previousBars.get(previousBars.size() - 1);
                    final long previousPreviousTime = previousBar.getTime() - 1;
                    final List<CandleData> previousPreviousBars = cache.getBars(previousPreviousTime);
                    final CandleData previousPreviousBar = previousPreviousBars.get(previousPreviousBars.size() - 1);
                    LOGGER.info(new Date(tick.getTime()) + ": "
                            + new Date(currentBars.get(currentBars.size() - 1).getTime()) + " -> "
                            + new Date(previousBars.get(previousBars.size() - 1).getTime()) + " -> "
                            + new Date(previousPreviousBars.get(previousPreviousBars.size() - 1).getTime()));

                    if (lastCurrentBar == null || lastCurrentBar.getTime() != currentBar.getTime()) {
                        if (lastCurrentBar != null) {
                            if (!(lastCurrentBar.getTime() < currentBar.getTime())) {
                                throw new IllegalArgumentException("!(lastCurrentBar.getTime() < currentBar.getTime())");
                            }
                        }
                        if (lastPreviousBar != null) {
                            if (!(lastPreviousBar.getTime() < previousBar.getTime())) {
                                throw new IllegalArgumentException(
                                        "!(lastPreviousBar.getTime() < previousBar.getTime())");
                            }
                            if (lastPreviousBar.getTime() > previousPreviousBar.getTime()) {
                                throw new IllegalArgumentException(
                                        "lastPreviousBar.getTime() > previousPreviousBar.getTime()");
                            }
                        }
                        lastCurrentBar = currentBar;
                        lastPreviousBar = previousBar;
                    }
                }
            }

            @Override
            public void onStop() throws JFException {}

            @Override
            public void onStart(final IContext context) throws JFException {
                this.context = context;
            }

            @Override
            public void onMessage(final IMessage message) throws JFException {}

            @Override
            public void onBar(final Instrument instrument, final Period period, final IBar askBar, final IBar bidBar)
                    throws JFException {}

            @Override
            public void onAccount(final IAccount account) throws JFException {}

            final class JForexTickBarCache {

                private static final int N_BARS_BACK = 10;
                private final Period period;
                private final long readBackStepMillis;
                private final long maxReadBackMillis;

                public JForexTickBarCache() {
                    this.period = Period.ONE_SEC;
                    this.readBackStepMillis = period.getInterval() * N_BARS_BACK;
                    this.maxReadBackMillis = max(readBackStepMillis * N_BARS_BACK, TimeUnit.DAYS.toMillis(3));
                }

                protected List<CandleData> getBars(final long time) throws JFException {
                    final long barStart = context.getHistory().getBarStart(period, time);
                    System.err.println("time=" + format(time) + " -> barStart=" + format(barStart));
                    long curTo = barStart;
                    long curFrom = curTo - readBackStepMillis;
                    List<IBar> bars;
                    System.err.println("before: curFrom=" + format(curFrom) + " curTo=" + format(curTo));
                    int iters = 0;
                    while (true) {
                        iters++;
                        bars = context.getHistory().getBars(Instrument.EURUSD, period, OfferSide.ASK, Filter.NO_FILTER,
                                curFrom, curTo);
                        if (bars.size() == 0 && time - curFrom > maxReadBackMillis) {
                            return new ArrayList<CandleData>();
                        } else if (bars.size() == 0) {
                            curTo = curFrom;
                            curFrom = curFrom - readBackStepMillis;
                        } else {
                            break;
                        }
                    }
                    System.err.println("after: iters=" + iters + " curFrom=" + format(curFrom) + " curTo="
                            + format(curTo));
                    final List<CandleData> realBars = new ArrayList<CandleData>();
                    for (final IBar bar : bars) {
                        final CandleData paBar = (CandleData) bar;
                        if (paBar.getTime() <= barStart) {
                            System.out.println("--adding " + format(paBar.getTime()));
                            realBars.add(paBar);
                        } else {
                            System.err.println("Skipping bar with endTime=" + format(paBar.getTime())
                                    + " because its after requested time=" + format(barStart));
                        }
                    }
                    return realBars;
                }

            }

            public Long max(final Long time1, final Long time2) {
                if (time1 == null) {
                    return time2;
                } else if (time2 == null) {
                    return time1;
                }

                if (time1 > time2) {
                    return time1;
                } else {
                    return time2;
                }
            }
        });
        //now it's running

    }

    /**
     * Uses Dates.FORMAT_ISO_DATE_TIME_MS as default.
     */
    public static String format(final long time) {
        return format(asDate(time));
    }

    public static String format(final long time, final String format) {
        return format(asDate(time), format);
    }

    /**
     * Uses Dates.FORMAT_ISO_DATE_TIME_MS as default.
     */
    public static String format(final Date date) {
        return format(date, FORMAT_ISO_DATE_TIME_MS);
    }

    public static String format(final Date date, final String format) {
        return FastDateFormat.getInstance(format).format(date);
    }

    public static Date asDate(final Long timeInMillis) {
        if (timeInMillis == null || timeInMillis <= 0) {
            return null;
        }
        return new Date(timeInMillis);
    }
}


You can reproduce the following exception:
2012-06-04 15:47:21,054 [ |StrategyRunner Thre] INFO  d.i.f.sample.bars.TimeBarsGapSample.onTick                   - Fri Jun 01 02:00:07 CEST 2012: Fri Jun 01 02:00:07 CEST 2012 -> Fri Jun 01 02:00:06 CEST 2012 -> Fri Jun 01 02:00:05 CEST 2012
time=2012-06-01T02:00:08.035 -> barStart=2012-06-01T02:00:08.000
before: curFrom=2012-06-01T01:59:58.000 curTo=2012-06-01T02:00:08.000
after: iters=1 curFrom=2012-06-01T01:59:58.000 curTo=2012-06-01T02:00:08.000
--adding 2012-06-01T01:59:58.000
--adding 2012-06-01T01:59:59.000
--adding 2012-06-01T02:00:00.000
--adding 2012-06-01T02:00:01.000
--adding 2012-06-01T02:00:02.000
--adding 2012-06-01T02:00:03.000
--adding 2012-06-01T02:00:04.000
--adding 2012-06-01T02:00:05.000
--adding 2012-06-01T02:00:06.000
--adding 2012-06-01T02:00:07.000
--adding 2012-06-01T02:00:08.000
--adding 2012-06-01T01:59:57.000
--adding 2012-06-01T01:59:58.000
--adding 2012-06-01T01:59:59.000
time=2012-06-01T02:00:07.999 -> barStart=2012-06-01T02:00:07.000
before: curFrom=2012-06-01T01:59:57.000 curTo=2012-06-01T02:00:07.000
after: iters=1 curFrom=2012-06-01T01:59:57.000 curTo=2012-06-01T02:00:07.000
--adding 2012-06-01T02:00:00.000
--adding 2012-06-01T02:00:01.000
--adding 2012-06-01T02:00:02.000
--adding 2012-06-01T02:00:03.000
--adding 2012-06-01T02:00:04.000
--adding 2012-06-01T02:00:05.000
--adding 2012-06-01T02:00:06.000
--adding 2012-06-01T02:00:07.000
time=2012-06-01T02:00:06.999 -> barStart=2012-06-01T02:00:06.000
before: curFrom=2012-06-01T01:59:56.000 curTo=2012-06-01T02:00:06.000
after: iters=1 curFrom=2012-06-01T01:59:56.000 curTo=2012-06-01T02:00:06.000
--adding 2012-06-01T01:59:56.000
--adding 2012-06-01T01:59:57.000
--adding 2012-06-01T01:59:58.000
--adding 2012-06-01T01:59:59.000
--adding 2012-06-01T02:00:00.000
--adding 2012-06-01T02:00:01.000
--adding 2012-06-01T02:00:02.000
--adding 2012-06-01T02:00:03.000
--adding 2012-06-01T02:00:04.000
--adding 2012-06-01T02:00:05.000
--adding 2012-06-01T02:00:06.000
2012-06-04 15:47:21,061 [ |StrategyRunner Thre] INFO  d.i.f.sample.bars.TimeBarsGapSample.onTick                   - Fri Jun 01 02:00:08 CEST 2012: Fri Jun 01 02:00:08 CEST 2012 -> Fri Jun 01 02:00:07 CEST 2012 -> Fri Jun 01 02:00:06 CEST 2012
time=2012-06-01T02:00:19.875 -> barStart=2012-06-01T02:00:19.000
before: curFrom=2012-06-01T02:00:09.000 curTo=2012-06-01T02:00:19.000
after: iters=1 curFrom=2012-06-01T02:00:09.000 curTo=2012-06-01T02:00:19.000
--adding 2012-06-01T02:00:19.000
time=2012-06-01T02:00:18.999 -> barStart=2012-06-01T02:00:18.000
before: curFrom=2012-06-01T02:00:08.000 curTo=2012-06-01T02:00:18.000
after: iters=1 curFrom=2012-06-01T02:00:08.000 curTo=2012-06-01T02:00:18.000
--adding 2012-06-01T02:00:08.000
time=2012-06-01T02:00:07.999 -> barStart=2012-06-01T02:00:07.000
before: curFrom=2012-06-01T01:59:57.000 curTo=2012-06-01T02:00:07.000
after: iters=1 curFrom=2012-06-01T01:59:57.000 curTo=2012-06-01T02:00:07.000
--adding 2012-06-01T01:59:57.000
2012-06-04 15:47:21,071 [ |StrategyRunner Thre] INFO  d.i.f.sample.bars.TimeBarsGapSample.onTick                   - Fri Jun 01 02:00:19 CEST 2012: Fri Jun 01 02:00:19 CEST 2012 -> Fri Jun 01 02:00:08 CEST 2012 -> Fri Jun 01 01:59:57 CEST 2012
2012-06-04 15:47:21,077 [ |StrategyRunner Thre] ERROR c.d.d.g.agent.strategy.tester.StrategyRunner.handleException - lastPreviousBar.getTime() > previousPreviousBar.getTime()
java.lang.IllegalArgumentException: lastPreviousBar.getTime() > previousPreviousBar.getTime()
   at de.invesdwin.forextrading.sample.bars.TimeBarsGapSample$2.onTick(TimeBarsGapSample.java:183) ~[bin/:na]
   at com.dukascopy.dds2.greed.agent.strategy.tester.AbstractStrategyRunner.historicalTickReceived(AbstractStrategyRunner.java:609) ~[greed-common-190.jar:190]
   at com.dukascopy.dds2.greed.agent.strategy.tester.StrategyRunner.run(StrategyRunner.java:469) ~[greed-common-190.jar:190]
   at java.lang.Thread.run(Thread.java:679) [na:1.6.0_24]
Strategy tester: java.lang.IllegalArgumentException: lastPreviousBar.getTime() > previousPreviousBar.getTime() @ de.invesdwin.forextrading.sample.bars.TimeBarsGapSample$2.onTick(TimeBarsGapSample.java:183)
lastPreviousBar.getTime() > previousPreviousBar.getTime(): java.lang.IllegalArgumentException: lastPreviousBar.getTime() > previousPreviousBar.getTime()
   at de.invesdwin.forextrading.sample.bars.TimeBarsGapSample$2.onTick(TimeBarsGapSample.java:183)
   at com.dukascopy.dds2.greed.agent.strategy.tester.AbstractStrategyRunner.historicalTickReceived(AbstractStrategyRunner.java:609)
   at com.dukascopy.dds2.greed.agent.strategy.tester.StrategyRunner.run(StrategyRunner.java:469)
   at java.lang.Thread.run(Thread.java:679)
2012-06-04 15:47:21,082 [ |StrategyRunner Thre] ERROR c.d.a.i.c.TesterClientImpl$DefaultStrategyExceptionHandler.o - Exception thrown while running onTick method: lastPreviousBar.getTime() > previousPreviousBar.getTime()
java.lang.IllegalArgumentException: lastPreviousBar.getTime() > previousPreviousBar.getTime()
   at de.invesdwin.forextrading.sample.bars.TimeBarsGapSample$2.onTick(TimeBarsGapSample.java:183) ~[bin/:na]
   at com.dukascopy.dds2.greed.agent.strategy.tester.AbstractStrategyRunner.historicalTickReceived(AbstractStrategyRunner.java:609) ~[greed-common-190.jar:190]
   at com.dukascopy.dds2.greed.agent.strategy.tester.StrategyRunner.run(StrategyRunner.java:469) ~[greed-common-190.jar:190]
   at java.lang.Thread.run(Thread.java:679) [na:1.6.0_24]


The interesting part is during iterations, the result of getBars seems to have forgotten that already some bars have been retrieved previously between "Fri Jun 01 02:00:08 CEST 2012" and "Fri Jun 01 01:59:57 CEST 2012". Thus instead of "Fri Jun 01 01:59:57 CEST 2012" i would have expected that "Fri Jun 01 02:00:07 CEST 2012" would have been found. The two outputs compare as thus:
2012-06-04 15:47:21,061 [ |StrategyRunner Thre] INFO  d.i.f.sample.bars.TimeBarsGapSample.onTick                   - Fri Jun 01 02:00:08 CEST 2012: Fri Jun 01 02:00:08 CEST 2012 -> Fri Jun 01 02:00:07 CEST 2012 -> Fri Jun 01 02:00:06 CEST 2012
2012-06-04 15:47:21,071 [ |StrategyRunner Thre] INFO  d.i.f.sample.bars.TimeBarsGapSample.onTick                   - Fri Jun 01 02:00:19 CEST 2012: Fri Jun 01 02:00:19 CEST 2012 -> Fri Jun 01 02:00:08 CEST 2012 -> Fri Jun 01 01:59:57 CEST 2012


And right this output of only 1 bar makes me suspicios with only 1 iteration:
time=2012-06-01T02:00:07.999 -> barStart=2012-06-01T02:00:07.000
before: curFrom=2012-06-01T01:59:57.000 curTo=2012-06-01T02:00:07.000
after: iters=1 curFrom=2012-06-01T01:59:57.000 curTo=2012-06-01T02:00:07.000
--adding 2012-06-01T01:59:57.000
Jun 01 02:00:08 CEST 2012: Fri Jun 01 02:00:08 CEST 2012 -> Fri Jun 01 02:00:07 CEST 2012 -> Fri Jun 01 02:00:06 CEST 2012


 
 Post subject: Re: getBars(..., from, to) has empty gaps during backtest Post rating: 0   New post Posted: Mon 04 Jun, 2012, 16:39 
User avatar

User rating:
Joined: Fri 31 Aug, 2007, 09:17
Posts: 6139
The error occurred in 3rd party package

java.lang.IllegalArgumentException: lastPreviousBar.getTime() > previousPreviousBar.getTime()
at de.invesdwin.forextrading.sample.bars.TimeBarsGapSample$2.onTick(TimeBarsGapSample.java:183) ~[bin/:na]


 
 Post subject: Re: getBars(..., from, to) has empty gaps during backtest Post rating: 0   New post Posted: Tue 05 Jun, 2012, 17:06 

User rating: 1
Joined: Tue 20 Mar, 2012, 09:03
Posts: 41
I know that, because I wrote the sample to throw that exception when the api gives a wrong result -.-

The sample is made to highlight that issue via an exception so you can test properly against it...

The exception message tells about the issue i care about in the sample. That is the actual issue you have to consider as a bug and not the Exception i throw to make you see it...

That was not a very intelligent response from you, i've expected more from you...


 
 Post subject: Re: getBars(..., from, to) has empty gaps during backtest Post rating: 0   New post Posted: Tue 05 Jun, 2012, 17:52 

User rating: 1
Joined: Tue 20 Mar, 2012, 09:03
Posts: 41
Here the same sample again without any external dependencies, so you don't have to edit the code to run the sample.
You only have to change the login properties for a demo account of your choice in the static fields.

package de.invesdwin.forextrading.sample.bars;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import com.dukascopy.api.Filter;
import com.dukascopy.api.IAccount;
import com.dukascopy.api.IBar;
import com.dukascopy.api.IContext;
import com.dukascopy.api.IMessage;
import com.dukascopy.api.IStrategy;
import com.dukascopy.api.ITick;
import com.dukascopy.api.Instrument;
import com.dukascopy.api.JFException;
import com.dukascopy.api.OfferSide;
import com.dukascopy.api.Period;
import com.dukascopy.api.system.ISystemListener;
import com.dukascopy.api.system.ITesterClient;
import com.dukascopy.api.system.TesterFactory;
import com.dukascopy.charts.data.datacache.CandleData;

/**
 * This small program demonstrates how to initialize Dukascopy client and start a strategy
 */
//CHECKSTYLE:OFF
//@NotThreadSafe
public final class TimeBarsGapSample {

    //CHANGE THIS IN THE SAMPLE BEFORE RUNNING
    private static final String JNLP_URL = de.invesdwin.forextrading.ForexProperties.JFOREX_JNLP_URL.toString();
    private static final String JNLP_USERNAME = de.invesdwin.forextrading.ForexProperties.JFOREX_JNLP_USERNAME;
    private static final String JNLP_PASSWORD = de.invesdwin.forextrading.ForexProperties.JFOREX_JNLP_PASSWORD;

    private static final String FORMAT_ISO_DATE_TIME = "yyyy-MM-dd'T'HH:mm:ss";
    private static final String FORMAT_ISO_DATE_TIME_MS = FORMAT_ISO_DATE_TIME + ".SSS";

    private TimeBarsGapSample() {}

    public static void main(final String[] args) 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() {
            private int lightReconnects = 3;

            @Override
            public void onStart(final long processId) {
                System.out.println("Strategy started: " + processId);
            }

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

            @Override
            public void onConnect() {
                System.out.println("Connected");
                lightReconnects = 3;
            }

            @Override
            public void onDisconnect() {
                System.err.println("Disconnected");
                if (lightReconnects > 0) {
                    client.reconnect();
                    --lightReconnects;
                } else {
                    try {
                        //sleep for 10 seconds before attempting to reconnect
                        Thread.sleep(10000);
                    } catch (final InterruptedException e) {
                        e.printStackTrace();
                    }
                    try {
                        client.connect(JNLP_URL, JNLP_USERNAME, JNLP_PASSWORD);
                    } catch (final Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        });

        System.out.println("Connecting...");
        //connect to the server using jnlp, user name and password
        client.connect(JNLP_URL, JNLP_USERNAME, JNLP_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()) {
            System.err.println("Failed to connect Dukascopy servers");
            System.exit(1);
        }

        //subscribe to the instruments
        final Set<Instrument> instruments = new HashSet<Instrument>();
        instruments.add(Instrument.EURUSD);
        System.out.println("Subscribing instruments...");
        client.setSubscribedInstruments(instruments);
        //start the strategy
        Thread.sleep(1000);

        System.out.println("Starting strategy");
        client.startStrategy(new IStrategy() {
            private IContext context;
            private CandleData lastCurrentBar;
            private CandleData lastPreviousBar;

            @Override
            public void onTick(final Instrument instrument, final ITick tick) throws JFException {
                if (instrument == Instrument.EURUSD) {

                    final JForexTickBarCache cache = new JForexTickBarCache();
                    final List<CandleData> currentBars = cache.getBars(tick.getTime());
                    final CandleData currentBar = currentBars.get(currentBars.size() - 1);
                    final long previousTime = currentBar.getTime() - 1;
                    final List<CandleData> previousBars = cache.getBars(previousTime);
                    final CandleData previousBar = previousBars.get(previousBars.size() - 1);
                    final long previousPreviousTime = previousBar.getTime() - 1;
                    final List<CandleData> previousPreviousBars = cache.getBars(previousPreviousTime);
                    final CandleData previousPreviousBar = previousPreviousBars.get(previousPreviousBars.size() - 1);
                    System.out.println(new Date(tick.getTime()) + ": "
                            + new Date(currentBars.get(currentBars.size() - 1).getTime()) + " -> "
                            + new Date(previousBars.get(previousBars.size() - 1).getTime()) + " -> "
                            + new Date(previousPreviousBars.get(previousPreviousBars.size() - 1).getTime()));

                    if (lastCurrentBar == null || lastCurrentBar.getTime() != currentBar.getTime()) {
                        if (lastCurrentBar != null) {
                            if (!(lastCurrentBar.getTime() < currentBar.getTime())) {
                                throw new IllegalArgumentException("!(lastCurrentBar.getTime() < currentBar.getTime())");
                            }
                        }
                        if (lastPreviousBar != null) {
                            if (!(lastPreviousBar.getTime() < previousBar.getTime())) {
                                throw new IllegalArgumentException(
                                        "!(lastPreviousBar.getTime() < previousBar.getTime())");
                            }
                            if (lastPreviousBar.getTime() > previousPreviousBar.getTime()) {
                                throw new IllegalArgumentException(
                                        "lastPreviousBar.getTime() > previousPreviousBar.getTime()");
                            }
                        }
                        lastCurrentBar = currentBar;
                        lastPreviousBar = previousBar;
                    }
                }
            }

            @Override
            public void onStop() throws JFException {}

            @Override
            public void onStart(final IContext context) throws JFException {
                this.context = context;
            }

            @Override
            public void onMessage(final IMessage message) throws JFException {}

            @Override
            public void onBar(final Instrument instrument, final Period period, final IBar askBar, final IBar bidBar)
                    throws JFException {}

            @Override
            public void onAccount(final IAccount account) throws JFException {}

            final class JForexTickBarCache {

                private static final int N_BARS_BACK = 10;
                private final Period period;
                private final long readBackStepMillis;
                private final long maxReadBackMillis;

                public JForexTickBarCache() {
                    this.period = Period.ONE_SEC;
                    this.readBackStepMillis = period.getInterval() * N_BARS_BACK;
                    this.maxReadBackMillis = max(readBackStepMillis * N_BARS_BACK, TimeUnit.DAYS.toMillis(3));
                }

                protected List<CandleData> getBars(final long time) throws JFException {
                    final long barStart = context.getHistory().getBarStart(period, time);
                    System.err.println("time=" + format(time) + " -> barStart=" + format(barStart));
                    long curTo = barStart;
                    long curFrom = curTo - readBackStepMillis;
                    List<IBar> bars;
                    System.err.println("before: curFrom=" + format(curFrom) + " curTo=" + format(curTo));
                    int iters = 0;
                    while (true) {
                        iters++;
                        bars = context.getHistory().getBars(Instrument.EURUSD, period, OfferSide.ASK, Filter.NO_FILTER,
                                curFrom, curTo);
                        if (bars.size() == 0 && time - curFrom > maxReadBackMillis) {
                            return new ArrayList<CandleData>();
                        } else if (bars.size() == 0) {
                            curTo = curFrom;
                            curFrom = curFrom - readBackStepMillis;
                        } else {
                            break;
                        }
                    }
                    System.err.println("after: iters=" + iters + " curFrom=" + format(curFrom) + " curTo="
                            + format(curTo));
                    final List<CandleData> realBars = new ArrayList<CandleData>();
                    for (final IBar bar : bars) {
                        final CandleData paBar = (CandleData) bar;
                        if (paBar.getTime() <= barStart) {
                            realBars.add(paBar);
                            System.out.println("--adding " + format(paBar.getTime()));
                        } else {
                            System.err.println("Skipping bar with endTime=" + format(paBar.getTime())
                                    + " because its after requested time=" + format(barStart));
                        }
                    }
                    return realBars;
                }

            }

            public Long max(final Long time1, final Long time2) {
                if (time1 == null) {
                    return time2;
                } else if (time2 == null) {
                    return time1;
                }

                if (time1 > time2) {
                    return time1;
                } else {
                    return time2;
                }
            }
        });
        //now it's running

    }

    /**
     * Uses Dates.FORMAT_ISO_DATE_TIME_MS as default.
     */
    public static String format(final long time) {
        return format(asDate(time));
    }

    public static String format(final long time, final String format) {
        return format(asDate(time), format);
    }

    /**
     * Uses Dates.FORMAT_ISO_DATE_TIME_MS as default.
     */
    public static String format(final Date date) {
        return format(date, FORMAT_ISO_DATE_TIME_MS);
    }

    public static String format(final Date date, final String format) {
        return new SimpleDateFormat(format).format(date);
    }

    public static Date asDate(final Long timeInMillis) {
        if (timeInMillis == null || timeInMillis <= 0) {
            return null;
        }
        return new Date(timeInMillis);
    }
}



 

Jump to:  

  © 1998-2025 Dukascopy® Bank SA
On-line Currency forex trading with Swiss Forex Broker - ECN Forex Brokerage,
Managed Forex Accounts, introducing forex brokers, Currency Forex Data Feed and News
Currency Forex Trading Platform provided on-line by Dukascopy.com