I actually only wrote twice. The topics are old but not been addressed by metatrader updates. I answered one topic then though to write an article but ir was not long enough so I posted it as a new topic and linked it in all the unsolved but yes old topics so that people would find what is, in my humble opinion, a solution. Whether the old topics are seen by the ops or newcomers is of no consequence, surely...
Of couse, if the admins pruned the site more effectively, there would not be the availability to reply to such old topics... but then neither would the longstanding need for a solution be exposed.
Several comments in more rrecent topics that do not have 'valuewhen' in the title are testament to the prolonged need...
![MQL5 - Language of trade strategies built-in the MetaTrader 5 client terminal](https://c.mql5.com/i/registerlandings/logo-2.png)
- Free trading apps
- Over 8,000 signals for copying
- Economic news for exploring financial markets
You agree to website policy and terms of use
Introduction - the problem
When developing an Expert Advisor, or an indicator, it is not uncommon that we want to find the value of a series x when series y last had a value z, or in other words when a condition was last satisfied.
This is so common that other platforms and languages have developed solutions, yet metatrader has not.
The following MT5 forum topics' metadata illustrate the problem:
So despite the obvious early demand for this function there has been no definitive solution in MT4 or MT5.
Edit:
Following the moderator's action - below, the original topics are now unabvailable which is unfortunate since at least one had some half useful code for a 'barssince()' equivalent...
Comparison with other languages
Pine Script on TradingView has a function, valuewhen(condition, source, occurrence), which returns a series of results. The function can be overloaded to process results of source type bool, int, float and color. The condition is any boolean statement which clearly must be indexed the same as the source. Occurrence allows for other instances than the last (occurrence = 0) by passing vaues >= 1 for occurrence.
Python with Pandas has a one line method
which does the same thing using pandas methods.
MetaQuotes has valuewhen(occurrence, condition, source) which does the same, as does Amibroker with ValueWhen(condition,source,occurrence).
Designing the function as a template/include
Since the requirement arises in both EAs and indicators, it makes sense to write a module to be used as an include.
The specifications are as follows:
The condition() and source() arrays should be indexed as series ie from right to left - in contrast to my first version of the code referenced at 3 above.
Managing different operations of relation
The built in functions/methods of other platforms referenced above allow for easy definition of the relation operations defining the condition.
In metatrader we do not have this luxury so for that reason we have to resort to use of the switch operator to determine the relationship being tested, with the addition of a nonnegator boolean switch to reduce the number of cases.
Custom enum types are declared:
The first set is for numeric comparisons, the second for string.
Others could be written to interogate array lengths etc.
In this example we are considering the double type.
One of the comparatord is passed along with a boolean nonnegator, in the parameters:
resulting in the following truth table:
The switch() statement is used in a loop iterating through the condition[] array which looks like this:
Storing and manipulating the required index values, using vector math to avoid one of our loops, retrieving the result
matchindex[] is used in the above loop to store an array of indexes where the required condition is satisfied.
Originally I was then looping through matchindex[] to create the complementary array of indexes.
The idea is to have a list of indexes to access the result from source[], and a list of indexes to determine from where the result[] array should be filled by the value from source. There is no faster way of accessing the values and writing the result[] array than going through the loop that follows the next piece of code, however the generation of the second index list should instinctively be quicker using vector math:
Finally, the function iterates through the shifted copy, obtaing the shifted value; the result[] array is progressively filled from the index position obtained from the shifted vector subtracted from the ArraySize of result with the source[] data obtained with the index from matchindex[], and the result[] finally reversed:
NULL vs NaN
There are areas in the code where, in other languages, NULL would be used, although python/pandas uses NaN. However, the python/pandas solution has no use of either in the calling or coding of the function.
While MQL5 recognises NULL as an input, it is converted to 0.0 in any numeric variable. Given that 0.0 may be a valid result, it is necessary to find an alternative. Thankfully the answer is in the ability to initialise an array of doubles with the value "nan", explicitly typecast to the array type:
This is then returned as nan if not overwritten by the subsequent code.
Unfortunately this will not work with non double arrays, so in the attached code the result[] array is maintained as type double. This allows the correct and useful reporting of the NULL/NaN condition. The important point to remember is that source must be compatable with a double result. The type(s) of condition, uvalue and lvalue must only be compatable with eachother.
Conclusion
This is my attempt to reproduce a useful function, requested and discussed over 17 years ago in the forum, and not discussed in terms of dedicated topics for over 8 years. It draws on the logic from the elegant python/pandas solution, and uses the new vector functionality in MT5.
It explores the way to use and return NaN - a subject poorly documented, in my opinion, hitherto.
The attached include file contains the functions and the global variables that need to be declared to use the code. Other variations to allow different combinations of parameter types are possible, as long as the warnings above are conbsidered.
There will certainly be a better way to do this - I am self taught and this is my first article, so be gentle in your criticism, but I hope you find it useful and would welcome comments.