For some reason, the CPU seems to be on overdrive after I modified an indicator. There are complex segments and I would probably need to write the code in a better way. But in general, I want to know how the past indicator values are read - whether by calculation or by internal memory. To give an example, let's say that the values are calculated as follows:
for (i = 0; i >= 600; i++)
// calculation begins
// calculation involves 15 operations and
indicator1 [i] = value1;
indicator2 [i] = value2;
Subsequently, after another bunch of code, I compare past values:
if (indicator1 > indicator2
//then do something
Would you please review this line again? for (i = 0; i >= 600; i++)
; while i >= 600 ; ???
"At this point, how does the indicator values of bar 30 are derived? Does MT4 read from the internal buffer which has values for 600 bars or does it calculate the values afresh going through the 15 operations?"
you use two index buffers and these are loaded via your for loop - no recalcs.
Also, even if that second 'bunch of code' was within the for loop, no recalcs either. Remember - just refs to array elements... no built in behind the scenes machinations (worrying if there was :)
Oh yes, cannot go through the 15 operations again can it? Not until cpu code execution passes that way again, yes? ie, when start() is recalled... (unless of course your going to now say that the for loop and the second bunch is within another loop....!)
sometimes an indicator is doing calcs EVERY data tick for bars waaaay back in time - is it that needed?
certainly not for many. and even more so for hidden inds that are called via iCustom().
Basically, labor intensive code blocks iterated over 100's of times for what? - when maybe just as good result available for the most recent 50 bars or so...
Just thoughts. But I've reduced cpu overheads from nearly 50% down to under 5% by just 'limitiing' the number of for loop reps done by an indicator on each data tick... and without any loss of, well... anything actually!
Of course is a case by case decision but worth bearing in mind!
Thanks fbj. Well, the 600 is definitely better than "Bars" which go all the way back to history limit!
That said, I understand your point of the necessity for calculating for a huge number of bars. I look at 15M charts and at 600 bars, this represents 6 days of data and I would probably need that. But I suspect the indicator itself is not well written and hence the cpu load. There is a big differnce in writing good code to get your job done vs writing some code to get your job done. I am not a programmer by default and hence the challenge!
Let me ask another question on best practice. In the 2 code segments below, which is better for the cpu? (From execution result perspective, I don't see a difference between the two)
if ((a == b) && (b > c) && (d == 0))
if (a == b)
if (b > c)
if (d == 0)
Have you heard about early exit during left to right (taking into condsideration precedences of operators) boolean expression evaluation?
You know about break, continue in looping constructs. Here, you code the early exit manually (course continue is not 100% loop exit, just says 'stop what doing now, go to top and start new interation') whereas break is 'stop NOW and go to first instruction after loop body'
Well, given above, then your method.1 is analogous to continue in MQL4 in that "a==b" may well be false but MQL actually keeps going rightwards seeing AND and then onto "b>c",... UNTIL terminal )
Strange? well, that is where the idea of early exit comes into play. ie, analogous to break idea.
MQL does not support early exit. It just ploughs rightwards until terminal ).
Now, your method.2 is the best fit we can do with MQL to be analogous to break idea.
The first if condition is tested resulting in true|false.
If false, execution jumps to the end of this first if condition, ie, it's closing } and that is just like the break idea, yes?
Given above, method.2 speed would appear better because in method.1 the complete if is executed - regardless of it being apparent that during the left to right travels the final result is false.
Additionally, you must be aware of 'knock on' or side effects of having complex condtionals. What? Well, in an early exit environment, you might have a function call or an expression that relies on certain data states which have been 'vetted' in tests to the left. These states can be effectively filtered by conditions leftwards of the function call or expression [either/both may use the datums]
Filtered/vetted because let's say "a==b" is false. What happens if we change "b>c" to "fred(a)" and fred() relies on the truth that "a==b".
See what happens? Without early exit OR your method.2 break analogy - fred(a) is executed and BOOM maybe runtime error! [course if fred() was totally well made, it would validate ALL it's inputs and effectively be bullet proof!]
Additionally, what if fred() was one big dude that did massive resource intensive tasks - all for no purpose in this case since a<>b.
With early exit evaluation of conditional expressions, fred() would never be called.
Just ideas, your method.2 is what many clued in coders use, because (1) eliminate side effects and (2) emulate early exit and (3) potential for increased speed with ref. to (2)
I say potential because no warranty that early exit would happen until the leftmost term is evaluated, yes?
A well layed out multi-part conditional, say multiLined with comments //... against each is perfectly clear and readable and the //.. can even have pseudo codeSpeak to enhance readability.
On the other hand, method.2 is effectively the same idea and given that MQL has no early exit/minimal evaluation ability, well... "buyer beware"!!!
have looksee: "Common usage: Deliberate omission of meaningless second test" which shows side effects issues IF no early exit (they say it better than me :)