What's the sanest way to access a completed bar?

Created at 31 Mar 2020, 08:41
How’s your experience with the cTrader Platform?
Your feedback is crucial to cTrader's development. Please take a few seconds to share your opinion and help us improve your trading experience. Thanks!
nmaxcom's avatar

nmaxcom

Joined 23.05.2016

What's the sanest way to access a completed bar?
31 Mar 2020, 08:41


Because OnBar() gets called right when a new bar appears, all its data (OHLC) will have the same number.

If I use LastValue that's what I'll get, nothing really usable. So, this is the way I think I should reason about when working with bars:

protected override void OnBar()
        {
            Print("T: " + Bars.OpenTimes.Last(1).ToLocalTime() + " \tO: " + Bars.OpenPrices.Last(1) + "  \tH: " + Bars.HighPrices.Last(1) + "  \tL: " + Bars.LowPrices.Last(1) + "  \tC:" + Bars.ClosePrices.Last(1));
        }

But all those Last(1) makes me think I'm doing something wrong. Maybe I'm approaching this the wrong way? I also used Bars[Bars.Count-2] but I can't say it's a cleaner way to do this.  Even if I assign it to a local variable and use that as an index.

I'm simply looking for a sane way of working with bars, complete bars, otherwise, OHLC will have the same price.


@nmaxcom
Replies

PanagiotisCharalampous
31 Mar 2020, 09:10

Hi nmaxcom,

I don't understand what is the problem with Last(1). Can you please explain?

Best Regards,

Panagiotis 

Join us on Telegram

 


@PanagiotisCharalampous

nmaxcom
31 Mar 2020, 10:25

RE:

PanagiotisCharalampous said:

Hi nmaxcom,

I don't understand what is the problem with Last(1). Can you please explain?

Best Regards,

Panagiotis 

Join us on Telegram

 

 

I'm pretty sure I'm being a little finicky here, but it doesn't seem natural to have a method that is called for each new bar, only to have to add Last(1) or similar options to get to the complete bar you are really after.

I concede "OnBar" makes sense with the fact that all OHLC values are the same. What I'm questioning here is the usefulness of such a method, versus something along the lines of  "OnBarClosed" for example. That would allow a developer to reason more simply about the bars we want to extract conclusions from and order a market buy or sell.

I've looked up the Bars events and there's only for when a bar opens, not when a bar closes.  Again, when a bar opens there's nothing that useful to do with it, except knowing the current time. Because the bar is still ticking, TickVolume value isn't there yet, OHLC values aren't there yet.

Working like this would make much more sense to me:

protected override void OnCompletedBar(Bar bar)
        {
            Print("Last complete bar closed at " + bar.Close);
            Print("And its predecesor closed at " + bar.Close.Last(1));
        }

Wouldn't it? 1) The bar is provided and 2) it's a completed bar one can work with.

So the actual code I posted before:

protected override void OnBar()
        {
            Print("T: " + Bars.OpenTimes.Last(1).ToLocalTime() + " \tO: " + Bars.OpenPrices.Last(1) + "  \tH: " + Bars.HighPrices.Last(1) + "  \tL: " + Bars.LowPrices.Last(1) + "  \tC:" + Bars.ClosePrices.Last(1));
        }

Would look like this:

protected override void OnCompletedBar(Bar bar)
        {
            Print("T: " + bar.OpenTime.ToLocalTime() + " \tO: " + bar.Open + "  \tH: " + bar.High + "  \tL: " + bar.Low + "  \tC:" + bar.Close);
        }

Isn't this more sensible?


@nmaxcom

PanagiotisCharalampous
31 Mar 2020, 10:32

Hi nmaxcom,

OnBar() is called whenever a bar is closed and a new bar is created. It is a simultaneous event, there is no in between situation. Last(0) represents the current bar and Last(1) the bar before. It is just a convention that you need to get used to it. 

Best Regards,

Panagiotis 

Join us on Telegram


@PanagiotisCharalampous

nmaxcom
01 Apr 2020, 21:54

RE:

PanagiotisCharalampous said:

Hi nmaxcom,

OnBar() is called whenever a bar is closed and a new bar is created. It is a simultaneous event, there is no in between situation. Last(0) represents the current bar and Last(1) the bar before. It is just a convention that you need to get used to it. 

Best Regards,

Panagiotis 

Join us on Telegram

Gotcha, not great fans of constructive criticism.

While on the OnBar() topic, isn't it called every tick just like OnTick()? At least it does in my system.


@nmaxcom

PanagiotisCharalampous
02 Apr 2020, 08:47

Hi nmaxcom,

I am not really sure what are you trying to achieve here but obviously it works in a specific way and we cannot change something that works and thousands of cBots are built on it. OnBar() is called every time a bar changes only.

Best Regards,

Panagiotis 

Join us on Telegram


@PanagiotisCharalampous

nmaxcom
02 Apr 2020, 11:19

RE:

PanagiotisCharalampous said:

I am not really sure what are you trying to achieve here

I am just giving my opinion on what seems to me, a very obvious pointer in a particular part of the API design. My point  was that this:

        protected override void OnBar(Bar bar) {
            if (bar.Open > bar.Close) Print("Bullish bar!");
        }

is much more natural than this:

        protected override void OnBar() {
            if (Bars.OpenPrices.Last(1) > Bars.ClosePrices.Last(1)) Print("Bullish bar!");
        }

And that's just providing the simplest of examples. The more elaborated one gets developing a bot, for example, the messy it looks. And even though sometimes we forget who the code is for, the code is for humans, not for machines. And C# is a tremendous human-designed language versus, say, C. Great choice of language, improvable API design.

It's my subjective opinion. I'm not expecting anyone going nuts and get angry but just taking a note for possible future improvement. I understand you've based the series on IEnumerables

I also wanted to open a new thread to propose opening up the API documentation so users can contribute with better explanations and examples. Right now has a few outdated info, very little information, and fewer examples. You'd make that part less difficult on yourselves and users would understand the API way better and therefore lessen the load on the forums and increase cTrader's appeal to automation.

 


@nmaxcom

karatedog
12 Aug 2024, 14:31

RE: What's the sanest way to access a completed bar?

PanagiotisCharalampous said: 

…we cannot change something that works and thousands of cBots are built on it…

Though this post is a bit old, I disagree with the statement as I see the opposite being true all the time.

You are not really changing something that has thousands of working code relying on it, you create a new one and cleverly separate the two so people have time to adapt to the new version (and you give help and hints on the way to assist them). Otherwise you are locking yourself to a fixed path and I'm sure what was good and mainstream 10 years ago is outdated today. You cannot maintain v1.0 compatibility forever.

Most of the programming languages do this between major versions but Python is a good example with its change between v2.x and v3.x. As a trading language example Tradingview uses code version annotation in their Pine script to allow them completely revamp the code if they want to.


@karatedog

PanagiotisCharalampous
13 Aug 2024, 05:05

RE: RE: What's the sanest way to access a completed bar?

karatedog said: 

PanagiotisCharalampous said: 

…we cannot change something that works and thousands of cBots are built on it…

Though this post is a bit old, I disagree with the statement as I see the opposite being true all the time.

You are not really changing something that has thousands of working code relying on it, you create a new one and cleverly separate the two so people have time to adapt to the new version (and you give help and hints on the way to assist them). Otherwise you are locking yourself to a fixed path and I'm sure what was good and mainstream 10 years ago is outdated today. You cannot maintain v1.0 compatibility forever.

Most of the programming languages do this between major versions but Python is a good example with its change between v2.x and v3.x. As a trading language example Tradingview uses code version annotation in their Pine script to allow them completely revamp the code if they want to.

Hi there,

The argument was about changing OnBar() method, not adding something new. Since then we have added OnBarClosed() method for this purpose.

Best regards,

Panagiotis


@PanagiotisCharalampous

karatedog
22 Aug 2024, 22:15

RE: RE: RE: What's the sanest way to access a completed bar?

PanagiotisCharalampous said: 

Hi there,

The argument was about changing OnBar() method, not adding something new. Since then we have added OnBarClosed() method for this purpose.

Best regards,

Panagiotis

Exactly. The argument was about changing the Onbar() method. You argued that it cannot be changed as a lot of code relies on that. So I showed an example how others do it, like versioning the programming API or - as Python did - doing something extreme, if that makes the overall experience better.

Now you have added OnBarClosed() which kinda solves the problem, but this means you wanted to maintain “v1.0” compatibility so instead of modifying OnBar() (and put it into a new namespace/API version or throw it away if it is not used at all in this current form), you created another API endpoint. This is a design decision which yours to make but there is a good reason programming languages chose not to do this as you will very likely end up with a lot of bastardized OnBarClosedWhenCertainConditionsAreMet() kind of methods in 10 years and newbies like me will just encounter a very steep learning curve.

I'm a newbie with the cTrader language API (coming from Pinescript) as I expected a lot more flexibility with the language (that I got), but I also stumbled into a high level of complexity which looks like a baggage from the past being afraid to throw away what is not working well. 

So I'm new here, I didn't want to kick in the door and tell around what to do, I've just got experience with domain specific languages which try to follow the “principle of least surprise” (POLS) paradigm, and part of that is not to be afraid to change something drastically if it gets better. People will learn the new rules and follow up.

Just an example, I work a lot with the current closed bar's open and close price. In Pinescript I wrote “open” and “close” to access those values. Here I do Bars.OpenPrices.LastValue and Bars.ClosePrices.LastValue. (if there are easier solutions, I was not able to find it in the Help). I'm not advocating Pine here, but for the former keywords I would not have to know anything about the classes and methods (which I cannot even search for, as I have no idea what to even look for) even a wild guess would have worked. For the latter, I have to know the proper classes and read a good amount to even start.

Best regards,
Laz


@karatedog