array variables availability in ProRealTime – examples and discussions
02/06/2020 at 10:17 AM #118804
The variable arrays will arrive soon in ProRealTime, they will be available in the coming weeks in version 11, with other instructions which I will detail in this topic.
I consider this to be a major addition to the ProBuilder language and a radical change in the way we program and for this reason, I think that a topic in the forum is much more suitable for offering examples and discuss.
Do not hesitate to ask your questions if things do not seem clear to you at first, I will try to answer as best I can.
I will add concrete examples to this topic for future reference.
As soon as these new features are deployed in public, you can also come here to offer your examples and your questions in the event of necessary debugging concerning variable arrays. There are so many new possibilities now, that
I have been testing for 2 weeks and apart from a few small concerns that have been brought up and corrected since, I must say that I was impressed by the quality and precision of the new instructions offered, thank you IT-Finance and ProRealTime, the year 2020 will be an amazing year for coders! 🙂
In the introduction, I would like to recall what array variable is and why it is so important to be able to use it in programming.
An array is a special variable, which can hold more than one value at a time.
If you have a list of values (a list of recent highest high, for example), storing them in single variables could look like this:123456789101112period = 5if high[period] >= highest[(period)*2+1](high) then //new highest highif hh1=0 thenhh1 = high[period]elsif hh2=0 thenhh2 = high[period]elsif hh3=0 thenhh3 = high[period]endifendifreturn hh1,hh2,hh3
However, what if you want to loop through the highest high and find a specific one? And what if you had not 3 highest high to store, but 300?
The solution is to create an array!
An array can hold many values under a single name, and you can access the values by referring to an index number.
In ProBuilder, variables array are declared with $ sign before their names, so following our previous example, our 3 variables could now be stored like this:123456789101112period = 5if high[period] >= highest[(5)*2+1](high) then //new highest highif not isset($hh) then$hh = high[period]elsif not isset($hh) then$hh = high[period]elsif not isset($hh) then$hh = high[period]endifendifreturn $hh,$hh,$hh
Note that an array always begin at 0.
This is how you should represent how the values are stored in an array:
Each index represent a column of the table where you put a value that you will be able to access anytime and anywhere in your code.
An index which hasn’t received any value yet is equal to 0.
More dynamically, we could store values in an array like this:12345period = 5if high[period] >= highest[(period)*2+1](high) then //new highest high$hh[myindex] = high[period] //store highest highmyindex=myindex+1 //increase the index of the array for next highest high storeendif
In this example, each time a new highest high is detected, we store its new value into a new column of the array. By using the instruction lastset(), we retrieve the last known column of the array, so by adding 1 to this number, we add dynamically a new column in order to store a new value. Don’t worry about the size of the array, it can handle 1 million index! Easy!
Ready for our first example? See below.02/06/2020 at 10:42 AM #118817
List of all examples available in this topic:
- Example #1: support and resistance example, based on fractals points
- Example #2: probability cone
- Example #3: separate buy/sell volumes on the same candle
- Example #4: previous days pivot point
- Example #5: tag exact time and price of an event (2 MA cross over) in real time, during the same bar
- Example #6: Flat base triangle aka double top/bottom
- Example #7: calculate the Average Daily Range (ADR)
Example #1: support and resistance example, based on fractals points
This example calculate dynamically support and resistance zones based on 2 fractals found within a defined distance in percentage of price.
Each time a new fractal is found, the code stores the value and the barindex in 2 separate arrays (2 variables for tops and 2 other variables for bottoms).
On the last bar of the price chart, the code makes a loop through each index of the array, it selects the first index to compare it with all the other ones and if the distance in percentage is within the allowed threshold, then a new support or resistance zone is created. Then it moves to the next index and repeat and continue the loop. Note that I used nested loops in order to make the comparison.
The code embed these new instructions:
LastSet : Returns the last index of the array defined by the code. If no index was previously defined, the function returns -1.
IsSet : Returns 1 if the index of the array has already been set in the code, otherwise returns 0.
DrawPoint:Draws a point on the chart.
Example: DRAWPOINT (x,y,size) COLOURED (R,V,B,a) BORDERCOLOR (R,V,B,a)
You can also notice that it is now possible to plot in the future of the chart (at the right of the curent price) by using BARINDEX+x (or with DateToBarIndex )123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869// https://www.prorealcode.com/topic/array-variables-availability-in-prorealtime/// (please do not remove the link above for future reference)// Example #1: support and resistance example, based on fractals pointsdefparam drawonlastbaronly=true// --- settingsfractalP = 10percent = 0.5barlimit = 500// --- end of settings//fractalscp=fractalPif high[cp] >= highest[(cp)*2+1](high) then //new fractal high found$TOPy[lastset($TOPy)+1] = high[cp] //store fractal value$TOPx[lastset($TOPx)+1] = barindex[cp] //store fractal barindexendifif low[cp] <= lowest[(cp)*2+1](low) then //new fractal low found$BOTy[lastset($BOTy)+1] = low[cp] //store fractal value$BOTx[lastset($BOTx)+1] = barindex[cp] //stire fractal barindexendifif(islastbarupdate and isset($topy) and isset($boty)) then//check points in a range of X percentfor i = 0 to lastset($TOPy) do //loop through the topsfor y = 0 to lastset($TOPy) do //check first top with other topschange=abs(($topy[y]-$topy[i])/$topy[i]) //percent range between the 2 topsif change<=percent/100 and barindex-$TOPx[y]<barlimit and $topx[i]<>$topx[y] thenif close>min($topy[y],$topy[i]) then //define the colorr=0g=255elser=255g=0endif//plot points at each topsDRAWPOINT($topx[i],$topy[i],2) COLOURED (r,g,0) BORDERCOLOR (r,g,0)DRAWPOINT($topx[y],$topy[y],2) COLOURED (r,g,0) BORDERCOLOR (r,g,0)midlevel=($topy[i]+$topy[y])/2//display the mid level priceDRAWTEXT("#midlevel#", barindex+8, midlevel, monospaced, standard, 14)//plot the zonedrawrectangle(min($topx[y],$topx[i]),$topy[y],barindex,$topy[i]) coloured(r,g,50,50) bordercolor(r,g,0)endifnextnextfor i = 0 to lastset($BOTy) do //loop through the bottomsfor y = 0 to lastset($BOTy) do //check first bottom with other bottomschange=abs(($boty[y]-$boty[i])/$boty[i]) //percent range between the 2 bottomsif change<=percent/100 and barindex-$BOTx[y]<barlimit and $BOTx[i]<>$BOTx[y] thenif close<max($boty[y],$boty[i]) then //define the colorr=255g=0elser=0g=255endifDRAWPOINT($botx[i],$boty[i],2) COLOURED (r,g,0) BORDERCOLOR (r,g,0)DRAWPOINT($botx[y],$boty[y],2) COLOURED (r,g,0) BORDERCOLOR (r,g,0)midlevel=($boty[i]+$boty[y])/2DRAWTEXT("#midlevel#", barindex+8, midlevel, monospaced, standard, 14)drawrectangle(min($botx[y],$botx[i]),$boty[y],barindex,$boty[i]) coloured(r,g,50,50) bordercolor(r,g,0)endifnextnextendifreturn
Feel free to fork the above code for your own needs (and please share it! 😉 ). The code is also attached below as an ITF file for convenience.
Very nice fork of this code, by stefou102 can also be found here: Support and resistance zones with variables arrays02/06/2020 at 10:43 AM #118818
Example #2: probability cone
In this second example I created a probability cone with values stored in 2 separated variables array.
The cone is plotted into the future of the price by using the 2 arrays. The start of the probability cone can be adjusted to start in the past (decay).
Note that the arrays $u and $d are populated dynamically directly in a loop on the current candlestick.
The code is continuously plotting the median high and median low values of the cone by using outside the loop the arraymin and arraymax instructions of $u and $d.12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152// https://www.prorealcode.com/topic/array-variables-availability-in-prorealtime/// (please do not remove the link above for future reference)// Example #2: probability conedefparam drawonlastbaronly=true// --- settingsPriceField = 1 //1=customclose ; 0=high/lowvol = 0.025 //Assumed Volatility (ideally based on volTyp)BarsFuture = 20 //No. of days aheadstdPer = 2 //Std. Dev. quantitydecay = 12 //decay the cone at the previous X bar// --- end of settingsPrice = customclosehh=undefinedll=undefinedif(islastbarupdate) thenfor i = 0 to BarsFuture do//cone calculationStdDev = StdPer * Price * Vol * sqrt( i / 365 )if( PriceField ) then$u[i] = high[decay] + stdDev$d[i] = low[decay] - stdDevelse$u[i] = Price[decay] + stdDev$d[i] = Price[decay] - stdDevendifif i>0 then//upper conedrawsegment(barindex[decay]+i,$u[i],barindex[decay]+i-1,$u[i-1]) coloured(0,255,0)drawpoint(barindex[decay]+i,$u[i],1) coloured(0,255,0)//lower conedrawsegment(barindex[decay]+i,$d[i],barindex[decay]+i-1,$d[i-1]) coloured(255,0,0)drawpoint(barindex[decay]+i,$d[i],1) coloured(255,0,0)//filling the zonedrawtriangle(barindex[decay]+i,$u[i],barindex[decay]+i-1,$u[i-1],barindex[decay]+i,$d[i]) coloured(150,150,150,50) bordercolor(150,150,150,0)drawtriangle(barindex[decay]+i-1,$d[i-1],barindex[decay]+i,$d[i],barindex[decay]+i-1,$u[i-1]) coloured(150,150,150,50) bordercolor(150,150,150,0)endifnext//plot the middle linedrawsegment(barindex[decay],($u+$d)/2,barindex[decay]+BarsFuture,($u+$d)/2) style(dottedline)//plot the highest and lowest boundaries of the conehh=(arraymax($u)+arraymin($u))/2ll=(arraymax($d)+arraymin($d))/2endifreturn hh, ll
It was not really necessary to use arrays to plot the cone because we do it in the loop on each iteration, but the purpose of the example was to show how to populate arrays inside a loop and use their values outside of it.
The “vol” variable should be set with implied volatility of the instrument, but you can also use either historic volatility or even average true range factorized.02/06/2020 at 10:46 AM #118819
Example #3: separate buy/sell volumes on the same candle
With variable array, it is now possible to store values and to re-use it inside the same bar. Previously, it was not possible to refer to the last value because variables were reset on each new tick received from the market.
IMPORTANT: arrays are not historized, they are decorrelated from the BARINDEX, it means that the arrays value from X bars ago is not saved in memory. It is not a drawback since you can save up to 1 million index which is the maximum of data history allowed now with version 11. Also, you can save your index into a normal variable and refer to it with its barindex offset (see example below, the ‘delta’ variable is used to store the difference of the 2 arrays, so that we can use it to compute an average over the last X periods!).
In this example, we use only 1 index / value for each variable array, to benefit from their “memories” on the current bar, in order to “separate” the bullish from the bearish volumes. By making the difference between the 2 arrays, we can make a sort of accurate cumulative delta and usable in any timeframe from ticks to daily and beyond.123456789101112131415161718192021// https://www.prorealcode.com/topic/array-variables-availability-in-prorealtime/// (please do not remove the link above for future reference)// Example #3: separate buy/sell volumes on the same candleif not isset($upvol) then$upvol = 0$dnvol = 0endifif islastbarupdate thenif close>$lastclosethen$upvol=$upvol+volumeelsif close<$lastclose then$dnvol=$dnvol+volumeendif$lastclose=closedelta=($upvol-$dnvol)endifavg=average(delta)return $upvol coloured(0,255,255) style(histogram) as "up volumes", -$dnvol coloured(255,0,0) style(histogram) as "down volumes", delta style(line,3), avg02/07/2020 at 7:04 AM #118905
In the probability cone example (Example 2) an error occurs on lines 25, 26, 28, 29 and 30. A null error.
It would seem like a very useful indicator if I could make it work.
Perhaps this has not been implemented yet.
Rory.02/07/2020 at 8:35 AM #11891102/07/2020 at 10:14 AM #118920
Indeed, this topic was created to prepare coders before the official public release of arrays 🙂
I think that it is necessary to set milestones so that people take ownership of this new way of programming, which is not easy to define for those who have never programmed with variables arrays before. I may not have chosen the simplest examples, I will try to add others a little more accessible.02/07/2020 at 11:56 AM #118929
Example #4: previous days pivot point
In this simple example, the code is storing the daily pivot points values into an array. Each new day, the current pivot points is put into a new index of the table. That way, we can get at any time and without making new calculation, the X previous day(s) pivot points value (with DaysBack setting). It is as if we are creating our own constants that we can reuse at any time later in our code, therefore the possibilities are numerous!store the pivot point values into an array123456789101112131415161718// https://www.prorealcode.com/topic/array-variables-availability-in-prorealtime/// (please do not remove the link above for future reference)// Example #4: previous days pivot point// --- settingsDaysBack = 3// --- end of settingsif dclose(1)<>lastclose then //new day beginindex = lastset($pp)+1 //increment the index to save the current day pivot point$pp[index] = (dhigh(1)+dlow(1)+dclose(1))/3 //save the pivot point of the day in new index of the arraylastclose = dclose(1) //save the current Dclose(1) value to future check of new dayendif//get the pivot point for the Y previous day before nowmypivot = $pp[max(0,index-DaysBack)] //added MAX keyword to verify the result of the subscract is not inferior to 0RETURN mypivot style(line,3)
In the attached picture, the “mypivot” line (thick white line) is plotting the pivot point from 2 days ago (DaysBack = 2).02/07/2020 at 5:14 PM #11895802/13/2020 at 5:39 PM #119591
Hello Nicolas, Thank you very much for your feedback on the upcoming arrival of the arrays and the possibilities they will offer. I’m going to read it calmly and calmly tomorrow morning but after a first scan of your messages, it really looks very promising!02/13/2020 at 5:49 PM #11960002/19/2020 at 10:24 AM #11992502/20/2020 at 11:11 AM #120021
Hello everyone, hello Nicolas,
1. I have read and understood your examples, very interesting, thank you very much
2. Do you know what will be the date of the release which will allow us to have arrays
3. Do you know if there will be instructions to facilitate the manipulation of arrays :
– Ex1: rank array in ascending or descending order (trier un tableau)
– Ex2: merge 2 arrays
Point 3 is not very important since it will always be possible to do this “by hand” with a few loops …
Thank you02/20/2020 at 11:29 AM #12002402/26/2020 at 8:55 AM #120531
This topic on the tables to come seems super interesting, and risks revolutionizing our indicators (support / resistance – trend lines / number of times affected … etc) do you have any news concerning this long awaited shift?
Thanking you in advance,