Dukascopy
 
 
Wiki JStore Search Login

Attention! Read the forum rules carefully before posting a topic.

    Try to find an answer in Wiki before asking a question.
    Submit programming questions in this forum only.
    Off topics are strictly forbidden.

Any topics which do not satisfy these rules will be deleted.

bars generated locally or at server?
 Post subject: bars generated locally or at server? Post rating: 0   Post Posted: Tue 28 Jun, 2011, 09:54 
User avatar

User rating: 6
Joined: Thu 19 May, 2011, 11:14
Posts: 235
Location: South Africa,
If the client misses some ticks that would have influenced a bar, will it just provide an incomplete IBar (constructed from received ticks) to onBar, or will it get the correct bar from the server?


 
 Post subject: Re: bars generated locally or at server? Post rating: 0   Post Posted: Tue 28 Jun, 2011, 12:24 
User avatar

User rating:
Joined: Fri 31 Aug, 2007, 09:17
Posts: 6139
bars get assembled from ticks on server side.


 
 Post subject: Re: bars generated locally or at server? Post rating: 0   Post Posted: Wed 29 Jun, 2011, 13:07 
User avatar

User rating: 6
Joined: Thu 19 May, 2011, 11:14
Posts: 235
Location: South Africa,
Please pardon my asking, but are you sure?
(that live bars are always assembled server-side?)

This may not seem so important but for my implementation it would be very useful to know if live bars are assembled client-side.

Here is one of the reasons I doubt that bars are assembled server side:

In viewtopic.php?f=5&t=4840&hilit=OnBar+Called
Support wrote:
Function onBar() is called when a first tick of the next candle has arrived. If there isn't new ticks, then the onBar() is called after 1 second when the last tick came for the last candle.
If the bars are being sent from the server, then why is there a timeout based on tick arrivals? Suppose the bar from the server is lost on the way, and the one second timeout elapses, so onBar is called; what bar is passed into onBar then?

I have noticed that, when I slow down my connection, there is a tendency for onTick arrivals to lag behind onBar arrivals, but never the reverse. I.e. They can arrive too late for the IBar object, but the IBar object never arrives too late for the surrounding ticks. To provide you with some concrete data, I ran the following strategy, which provides information when a tick or bar arrives at the strategy out of logical sequence:
package jforex;

import java.util.*;
import java.io.*;
import java.util.TimeZone;
import java.text.SimpleDateFormat;

import com.dukascopy.api.*;

public class TestEventSequence implements IStrategy {
   private IEngine engine;
   private IConsole console;
   private IHistory history;
   private IContext context;
   private IIndicators indicators;
   private IUserInterface userInterface;
   
    private PrintStream out;
    private SimpleDateFormat sdf;
     
    private long lastTickTime;
    private long lastBarGenTime;
    private double lastTickBid = Double.NaN;
    private double lastBarCloseBid = Double.NaN;
   
   public void onStart(IContext context) throws JFException {
      this.engine = context.getEngine();
      this.console = context.getConsole();
      this.history = context.getHistory();
      this.context = context;
      this.indicators = context.getIndicators();
      this.userInterface = context.getUserInterface();
        out = console.getOut();
        out.println("starting");
        sdf = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss.SSS") {{setTimeZone(TimeZone.getTimeZone("GMT"));}};
   }

   public void onAccount(IAccount account) throws JFException {
   }

   public void onMessage(IMessage message) throws JFException {
   }

   public void onStop() throws JFException {
        out.println("stopping");
   }

   public void onTick(Instrument instrument, ITick tick) throws JFException {
        if(instrument != Instrument.EURUSD)
            return;
           
        long time = tick.getTime();
        if(time < lastBarGenTime){
            out.println("onTick(" + sdf.format(time) + ") called after onBar(" + sdf.format(lastBarGenTime) + ")");
            out.println("...tick bid == " + tick.getBid() + " and last bar close == " + lastBarCloseBid + " and last tick bid == " + lastTickBid);
        }
       
        lastTickBid = tick.getBid();
        lastTickTime = time;
   }
   
    public void onBar(Instrument instrument, Period period, IBar askBar, IBar bidBar) throws JFException {
        if(instrument != Instrument.EURUSD || period != Period.TEN_SECS)
            return;
           
        long time = bidBar.getTime() + period.getInterval();
        if(time < lastTickTime){
            out.println("onBar(" + sdf.format(time) + ") called after onTick(" + sdf.format(lastTickTime) + ")");
            out.println("...close bid == " + bidBar.getClose() + " and last tick bid == " + lastTickBid);
        }

        lastBarCloseBid = bidBar.getClose();
        lastBarGenTime = time;
    }
}
Under normal circumstances, it prints nothing as expected. However, when I slowed down my internet connection, it printed this output (note that it is reversed, and I have added coloring for clarity):
10:41:10 stopping
10:41:04 ...tick bid == 1.44072 and last bar close == 1.44071 and last tick bid == 1.4407
10:41:04 onTick(2011.06.29 10:40:56.767) called after onBar(2011.06.29 10:41:00.000)
10:41:04 ...tick bid == 1.4407 and last bar close == 1.44071 and last tick bid == 1.44071
10:41:04 onTick(2011.06.29 10:40:56.216) called after onBar(2011.06.29 10:41:00.000)
10:40:51 ...tick bid == 1.44081 and last bar close == 1.4408 and last tick bid == 1.4408
10:40:51 onTick(2011.06.29 10:40:48.186) called after onBar(2011.06.29 10:40:50.000)
10:40:51 ...tick bid == 1.4408 and last bar close == 1.4408 and last tick bid == 1.4408
10:40:51 onTick(2011.06.29 10:40:47.265) called after onBar(2011.06.29 10:40:50.000)
10:39:31 ...tick bid == 1.44016 and last bar close == 1.4402 and last tick bid == 1.44017
10:39:31 onTick(2011.06.29 10:39:29.998) called after onBar(2011.06.29 10:39:30.000)
10:39:31 ...tick bid == 1.44017 and last bar close == 1.4402 and last tick bid == 1.44017
10:39:31 onTick(2011.06.29 10:39:29.456) called after onBar(2011.06.29 10:39:30.000)
10:39:31 ...tick bid == 1.44017 and last bar close == 1.4402 and last tick bid == 1.44019
10:39:31 onTick(2011.06.29 10:39:28.896) called after onBar(2011.06.29 10:39:30.000)
10:39:31 ...tick bid == 1.44019 and last bar close == 1.4402 and last tick bid == 1.4402
10:39:31 onTick(2011.06.29 10:39:28.565) called after onBar(2011.06.29 10:39:30.000)
10:38:03 ...tick bid == 1.44006 and last bar close == 1.44005 and last tick bid == 1.44005
10:38:03 onTick(2011.06.29 10:37:59.011) called after onBar(2011.06.29 10:38:00.000)
10:38:03 ...tick bid == 1.44005 and last bar close == 1.44005 and last tick bid == 1.44005
10:38:03 onTick(2011.06.29 10:37:58.351) called after onBar(2011.06.29 10:38:00.000)
10:37:30 starting

You can see from the log that if the ticks are delayed, we get a bar with close price based on the last tick received by the client at the time the bar is generated. If the bars are assembled server-side, then why is the close price wrong?


 
 Post subject: Re: bars generated locally or at server? Post rating: 0   Post Posted: Wed 29 Jun, 2011, 13:50 
User avatar

User rating:
Joined: Fri 31 Aug, 2007, 09:17
Posts: 6139
History bars are being generated by server. All other bars are being generated by a client.


 
 Post subject: Re: bars generated locally or at server? Post rating: 0   Post Posted: Sat 16 Jul, 2011, 11:47 
User avatar

User rating: 6
Joined: Thu 19 May, 2011, 11:14
Posts: 235
Location: South Africa,
I need to confirm that my understanding is correct. To be clear, I will express my understanding in 3 different ways. You can respond to any one of the 3 that makes the most sense, because all 3 are meant to say the same thing.

1.
It is always possible for the user's strategy to construct its own bars from the received ticks, such that its own bars are identical to the bars received from the platform, regardless of ticks that were lost.
  • In the case of back-testing, this is true because the client first downloads complete historical tick data, and so the strategy will not miss out on any ticks and the bars will be perfect.
  • In the case of live/demo testing, this is true because the client is generating the bars from the same ticks that it is passing to the strategy. So any ticks that are not received by the strategy were not received by the client either, and therefore the onBar events are still consistent with the ticks actually received.

2.
The information coming from the onBar events is always implicit in (i.e. derived entirely from) the information that is already available in the onTick events, even if some ticks went missing.

3.
A strategy that ignores the onBar events (preferring to make its own bars from ticks) has no "information disadvantage" compared to a strategy that uses onBar events, even if some ticks went missing.

Is my understanding correct?


 
 Post subject: Re: bars generated locally or at server? Post rating: 0   Post Posted: Mon 18 Jul, 2011, 12:51 
User avatar

User rating:
Joined: Fri 31 Aug, 2007, 09:17
Posts: 6139
Isak wrote:
It is always possible for the user's strategy to construct its own bars from the received ticks, such that its own bars are identical to the bars received from the platform, regardless of ticks that were lost.
No, consider an example strategy (it is derived from the example at https://www.dukascopy.com/wiki/index.php ... ion_policy) which sleeps for 9 seconds in onTick - the close price of the TEN_SEC bar is the one that of the later on historically retrieved tick (the last of the bar interval) - not the one of the last non-skipped tick.
package jforex.strategies.test;

import java.text.SimpleDateFormat;
import java.util.List;
import java.util.TimeZone;

import com.dukascopy.api.*;


public class BarsVsHistoricalBars implements IStrategy {

   private IConsole console;
   private IHistory history;

   private Instrument instrument = Instrument.EURUSD;
   private Period period = Period.TEN_SECS;

   private SimpleDateFormat sdf;
   private int printedTickCount;
   private long lastTickHistoryPrint;

   @Override
   public void onStart(IContext context) throws JFException {

      this.console = context.getConsole();
      this.history = context.getHistory();

      String DATE_FORMAT_NOW = "yyyy-MM-dd HH:mm:ss SSS";
      sdf = new SimpleDateFormat(DATE_FORMAT_NOW);
      sdf.setTimeZone(TimeZone.getTimeZone("GMT"));

      print("Start");
      lastTickHistoryPrint = System.currentTimeMillis();

   }

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

      if (!instrument.equals(this.instrument))
         return;

      printedTickCount++;
      print(" TICK time: " + sdf.format(tick.getTime()) + ", current time: " + sdf.format(System.currentTimeMillis()) + " " + tick);

      //sleep on every 2nd tick
      if (printedTickCount % 2 == 0) {
         try {
            Thread.sleep(9000);
            print("slept for 9 seconds, current time: " + sdf.format(System.currentTimeMillis()));
         } catch (InterruptedException e) {
            print(e.getMessage());
         }
      }
      
      //full list of ticks on every 5th printed tick
      if (printedTickCount % 5 == 0) {
         //effectively rounds up the time to 10 secs
         long barPeriodFrom = (lastTickHistoryPrint / period.getInterval()) * period.getInterval();
         long barPeriodTo = (tick.getTime() / period.getInterval()) * period.getInterval();
         printHistoricalTicksAndBars(history.getTicks(instrument, lastTickHistoryPrint, tick.getTime()),
               history.getBars(instrument, Period.TEN_SECS,OfferSide.BID, barPeriodFrom, barPeriodTo));
         lastTickHistoryPrint = tick.getTime();
      }
   }

   @Override
   public void onBar(Instrument instrument, Period period, IBar askBar, IBar bidBar) throws JFException {
      if (!instrument.equals(this.instrument) || period != Period.TEN_SECS)
         return;

      print(" _BAR time: " + sdf.format(askBar.getTime()) + ", current time: " + sdf.format(System.currentTimeMillis())
            + " " + bidBar);

   }
   

   private void print(Object message) {
      console.getOut().println(message);
   }

   private void printHistoricalTicksAndBars(List<ITick> tickList, List<IBar> barList) {
      print("TICK HISTORY");
      for (ITick tick : tickList) {
         print(sdf.format(tick.getTime()) + " " + tick);
      }
      print("_BAR HISTORY");
      for (IBar bar : barList) {
         print(sdf.format(bar.getTime()) + " " + bar);
      }
      print("HISTORY END");
   }

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

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

   @Override
   public void onStop() throws JFException {}


}


 
 Post subject: Re: bars generated locally or at server? Post rating: 0   Post Posted: Mon 18 Jul, 2011, 16:16 
User avatar

User rating: 6
Joined: Thu 19 May, 2011, 11:14
Posts: 235
Location: South Africa,
Thank you!
And if the strategy never sleeps, but always returns quickly when it is called?


 
 Post subject: Re: bars generated locally or at server? Post rating: 0   Post Posted: Tue 19 Jul, 2011, 08:55 
User avatar

User rating:
Joined: Fri 31 Aug, 2007, 09:17
Posts: 6139
Sleep here, of course, is an abstraction of some prolonged execution (e.g. load of tick history over the last hour) to demonstrate what happens if some ticks here get skipped. As long as you are sure to receive all the ticks (see cases when ticks get skipped: https://www.dukascopy.com/wiki/index.php ... ion_policy), your own assembled bar data should match the data received in onBar.
And you can always check your assumptions by running similar tests - in this case, for example, you can change the sleep time to 1 second and call sleep on every 4th tick.


 

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