History bars

There are three main ways how one can retrieve bar data:

  • by shift,
  • by candle interval,
  • by time interval.

This can be done both synchronously and asynchronously.

Note: methods given in the article work both with standard and custom periods starting with JForex-API 2.6.49, with earlier versions only standard period history is available.

Synchronous methods

Methods that load their data in the same thread synchronously start with the get prefix: getBar, getTicks, getBars. Even if the method requires time to access the server, download history files in the local cache, it will all be done in the same thread blocking strategy execution for some time. Also methods getBars and getTicks return a List of bars and ticks correspondingly, thus taking some amount of the memory. It is not recommended to call these methods knowing that it could return thousands or even millions of ticks or bars and cause OutOfMemoryException. Though normally it is ok to call getBar with shift parameter in 0-10 range, since it is very unlikely it will require server access to get the data.

long prevBarTime = history.getPreviousBarStart(Period.TEN_SECS, tick.getTime());
List<IBar> bars = history.getBars(instrument, Period.TEN_SECS, OfferSide.BID, history.getTimeForNBarsBack(Period.TEN_SECS, prevBarTime, 10), prevBarTime);

GetBarsExample.java

Bars by shift

The getBar method returns an IBar by shift. Shift of value 0 refers to the current candle that's not is not yet fully formed, 1 - latest fully formed candle, 2 - second to last candle. Consider retrieving previous 1 hour bar for EUR/USD:

int shift = 1;
IBar prevBar = history.getBar(Instrument.EURUSD, Period.ONE_HOUR, OfferSide.BID, shift);
console.getOut().println(prevBar);

HistoryBarsSynch.java

Bars by time interval

The getBars method with from and to parameters loads a list of IBars within the given time interval. Both from and to have to divisible by bar period (e.g. if one loads 1 hour bars, then from and to need to be round hours). Consider retrieving five previous 1 hour bars for EUR/USD:

long prevBarTime = history.getPreviousBarStart(Period.ONE_HOUR, history.getLastTick(Instrument.EURUSD).getTime());
long startTime =  history.getTimeForNBarsBack(Period.ONE_HOUR, prevBarTime, 5);  
List<IBar> bars = history.getBars(Instrument.EURUSD, Period.ONE_HOUR, OfferSide.BID, startTime, prevBarTime);
int last = bars.size() - 1;
console.getOut().println(String.format(
    "Previous bar close price=%.5f; 4th to previous bar close price=%.5f", 
    bars.get(last).getClose(), bars.get(0).getClose()));

HistoryBarsSynch.java

Now consider loading daily bars information over period of 05/10/2008 - 04/10/2010:

SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyy HH:mm:ss"); 
dateFormat.setTimeZone(TimeZone.getTimeZone("GMT")); 
try { 
    Date dateFrom = dateFormat.parse("05/10/2008 00:00:00"); 
    Date dateTo = dateFormat.parse("04/10/2010 00:00:00");
} catch (ParseException e) {
    e.printStackTrace();
}    
List<IBar> bars = history.getBars(Instrument.EURUSD, Period.DAILY, OfferSide.ASK, dateFrom.getTime(), dateTo.getTime());

Bars by candle interval

The getBars method with numberOfCandlesBefore and numberOfCandlesAfter parameters loads a list of IBars within the given candle interval around the given point in time. Consider retrieving five previous 1 hour bars for EUR/USD:

long prevBarTime = history.getPreviousBarStart(Period.ONE_HOUR, history.getLastTick(Instrument.EURUSD).getTime());
List<IBar> bars = history.getBars(Instrument.EURUSD, Period.ONE_HOUR, OfferSide.BID, Filter.NO_FILTER, 5, prevBarTime, 0);
int last = bars.size() - 1;
console.getOut().println(String.format(
    "Previous bar close price=%.5f; 4th to previous bar close price=%.5f", 
    bars.get(last).getClose(), bars.get(0).getClose()));

HistoryBarsSynch.java

Asynchronous methods

Historical data gets read from local cache, if the data is not in the local cache, it gets downloaded from the server, which is a more time consuming operation. Thus, when loading significant historical data amount synchronously from server, it takes longer than if the data is already in the local cache. So if there is a significant amount of data which will be needed later, then the asynchronous methods can load this data without blocking other strategy logic execution. And afterwards the data can be read by synchronous methods.

Asynchronous methods start with "read" prefix and require a bit more coding. In order to use them one needs to implement two listeners that get called from another thread which passes in ticks or bars and notifies when data loading is complete. This method will return immediately after execution most likely before any data is received in listeners. This is useful when the following logic doesn't require the data requested, or when the logic can be separated and executed after listener is notified of data loading completion.

history.readBars(Instrument.EURUSD, Period.TEN_SECS, OfferSide.BID,
        history.getBarStart(Period.DAILY, tick.getTime()) - Period.DAILY.getInterval(), // yesterday start
        history.getBarStart(Period.DAILY, tick.getTime()) - Period.TEN_SECS.getInterval(), // yesterday end
        new LoadingDataListener() {
            public void newTick(Instrument instrument, long time, double ask, double bid, double askVol, double bidVol) {
                //no ticks expected, because we are loading bars
            }
            public void newBar(Instrument instrument, Period period, OfferSide side, long time, double open, double close, double low, double high, double vol) {
                ++numberOfBarsLoaded;
            }
        }, new LoadingProgressListener() {
            public void dataLoaded(long startTime, long endTime, long currentTime, String information) {
                console.getOut().println(information);
            }
            public void loadingFinished(boolean allDataLoaded, long startTime, long endTime, long currentTime) {
                if (allDataLoaded) {
                    console.getOut().println("All data loaded succesfully, number of bars loaded: " + numberOfBarsLoaded);
                    context.stop();
                } else {
                    console.getOut().println("For some reason loading failed or was canceled by the user");
                    context.stop();
                }
            }
            public boolean stopJob() {
                return false;
        }
});

ReadBarsExample.java

Filter usage

Bar filters are defined by Filter enum, which gets used as a parameter in the following methods:

  • IHistory.getBars by candle interval,
  • IHistory.getBars by time interval with filter parameter.

The methods which don't have Filter as parameter use Filter.NO_FILTER:

  • IHistory.getBar by shift,
  • IHistory.getBars by time interval without filter parameter.

Consider a small example strategy which prints one hour bars over the last week:

  • bars with applied Filter.WEEKEND,
  • bars with applied Filter.NO_FILTER,
  • subtraction of the first two sets.
@Override
public void onStart(IContext context) throws JFException {
    console = context.getConsole();
    history = context.getHistory();
    context.setSubscribedInstruments(java.util.Collections.singleton(Instrument.EURUSD), true);

    IBar weeklyCurr = history.getBar(Instrument.EURUSD, Period.WEEKLY, OfferSide.BID, 0);
    IBar weeklyPrev = history.getBar(Instrument.EURUSD, Period.WEEKLY, OfferSide.BID, 1);
    List<IBar> barsNoWeekends = history.getBars(Instrument.EURUSD, Period.ONE_HOUR, OfferSide.BID, Filter.WEEKENDS, weeklyPrev.getTime(), weeklyCurr.getTime());
    List<IBar> barsNoFilter = history.getBars(Instrument.EURUSD, Period.ONE_HOUR, OfferSide.BID, Filter.NO_FILTER, weeklyPrev.getTime(), weeklyCurr.getTime());
    print(String.format("No-weekend bar count: %s, No-filter bar count: %s", barsNoWeekends.size(), barsNoFilter.size()));
    for(IBar bar : barsNoWeekends){
        print("No-weekend bar: " + bar);
    }        
    for(IBar bar : barsNoFilter){
        print("No-filter bar: " + bar);
    }
    barsNoFilter.removeAll(barsNoWeekends);
    for(IBar bar : barsNoFilter){
        print("Weekend-only bar: " + bar);
    }
}

HistoryBarsFilter1Week.java

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