ProRealCode - Trading & Coding with ProRealTime™
Been AWOL from PRT & PRC for a while and now looking at what i was last working on.
The idea of the Mini Window was motivated because my low res laptop wasn’t practicable when multiple visible charts open for multiple time frames.
This code is an early version which was a proof of concept and made possible with the DRAW – ANCHOR option of fixed pixel drawing. It allowed the last ‘n’ bars could be displayed while the main chart was scrolled etc, or a different time frame if enough bars there to calculate. I initially used several modified code files for different time frames with offset of drawing positions.
The project turned into solving or getting around problems by adding different features in later versions, which I’ll post as i look through them. As i recalled I worked on config variables to aid if multiple indicator used, adding basic indicator’s and avoiding issues thrown up by the developed.
Hopefully it may be of use, I don’t know much about the web and mobile versions but monitoring several time frames at the same time was helpful option to me for a quick way to monitor different time frames without changing the main chart or polling different charts windows.
Regards.
defparam drawonlastbaronly = true
//timeframe(15minutes)
if islastbarupdate then // skip historic bars
LB = 40 // lookback ( no. of mini window candles +1 )
winX = (5*(LB+4)) // width of window in pixels
winY = 250 // height of window in pixels
loRef= min(lowest[LB](low),low) // lowest from LB bars
HiRef= max(highest[LB](high),high) // highest from LB bars
hiLoRng = HiRef-LoRef // range over LB bars
ref = (winY-20)/hilorng // y axis scale multiplier
// ------------------------------------------ rectangle
// ------------------ absolute (a)
ax1 = 40 // offset from LHS of chart frame
ax2 = ax1 + winX// 300
ay1 = -40 // offset ftom top of chart frame
ay2 = ay1 - winY//-300
// ------------------------------------------ mini window rectangle box
x1 = 0 + ax1 // position left inc offset
x2 = x1 + winX // position from left to right
y1 = 0 + ay2 // position top inc offset
y2 = y1 + winY // position from top to bottom
drawrectangle(x1,y1,x2,y2)anchor(topleft,xshift,yshift) // mini window box border
/*
drawtext("x1y1",x1,y1)coloured("red")anchor(topleft,xshift,yshift) // ref: box corner coordinate's
drawtext("x2y2",x2,y2)coloured("red")anchor(topleft,xshift,yshift) // "
drawtext("x1y2",x1,y2)coloured("red")anchor(topleft,xshift,yshift) // "
drawtext("x2y1",x2,y1)coloured("red")anchor(topleft,xshift,yshift) // "
*/
// ------------------------------------------- candle construction
t = LB
for i = 0 to LB
os = 10
start = ax1+os // offset from chart left edge
width = 3 // candle width
gap = 5 // gap between candles, may be senter's
op = os+ay2+((open [t-i]-loref)*ref)
hi = os+ay2+((high [t-i]-loref)*ref)
lo = os+ay2+((low [t-i]-loref)*ref)
cl = os+ay2+((close[t-i]-loref)*ref)
x1 = (gap * i) + start
x2 = x1 + width
y1 = op
y2 = cl
if op>cl then // bear candle body
drawrectangle(x1,y1,x2,y2)anchor(topLeft,xshift,yshift)coloured(255,0,0,155)bordercolor(255,255,255,100)
else // bull candle body
drawrectangle(x1,y1,x2,y2)anchor(topLeft,xshift,yshift)coloured(0,255,0,155)bordercolor(255,255,255,100)
endif
// candle wicks
drawsegment(x1 + 1,hi,x1+1, lo)anchor(topLeft,xshift,yshift)coloured(255,255,255,155)
next
endif // skip historic bars
return
Hi Druby,
Thanks for sharing this code, very useful. Do you have any screenshot of how it looks on your chart?
Hi Nicolas, I realised that when i posted and when used the EDIT feature to add a image, on SUBMIT, the post vanished from the editor and after wondering what had happened I noticed a label that the subject had been treated as SPAM.
Both post have had the image copied into the text frame, either directly or with edit and images do not appear. Not sure why, maybe there’s been a change.
I don’t have my original PRT account so I’m having to build back manually with the ‘Export my personal data’ files. I abandoned development and here’s a image from the last version which showed some added indicators, used several CALL’ed file’s, multiple instances. So I’m hoping to continue when I’m back up to date and understood how it works.
Now the mini window shows the candles, the next step is to add the indicators you may have on a full chart to aid reference of the bars. Here I take a Simple Moving Average and add to the window.
The main structure stay similar barring some variable names and equation changes, but the major change is the determining the higher high and lower low elements in the window..
In the prior version, this was done with the candle high and low, but, ‘indicator(s)’ could be higher and/or lower than the candles. Two arrays hold the value from each element to be displayed, and there is an extra section to find the highest and lowest from them. Though open and close are not needed, I’m treating them all as if there were indicator outputs.
There is a section to draw the indicator line using segments, which is from the bar centrers of the previous point to the new point.
Also note, most of code is inside a isLastBarUpdate block but the ‘Average’ keyword is outside. The OHLC values are embedded constants in PRT so when using inside isLastBarUpdate, (to skip historic bars,) all there values exist for each bar. But for Average , this is not the same and its output values are calculated on each bar. So, though code could be written to look back at the appropriate close values to get the Average LB bar output values, they would have to be stored in an array for later use. Here the simple solution is to put it outside the isLastBarUpdate and assume that the performance difference between the stock Average code running on all bars is faster than a custom code on a select number of bars.. Keeping it simple also allows stock/custom indicators to be usable and avoid re-inventing the wheel for each indicator/type.
defparam drawonlastbaronly = true
//timeframe(15minutes)
avg = average[50](close) // got to be outside of islastbarupdate
// to populate prior bar values
if islastbarupdate then
LB = 40-1 // lookback bars 0-39
sizeBar = 5 // frame bar size pixels
winX = max(sizeBar*LB,250) // width of frame
winy = min(winX,350) // height of frame
// ------------------ absolute coords
ax1 = 40 // indent from left chart edge to left frame edge
ax2 = ax1 + winX // right frame edge
ay1 = -40 // indent from top chart edge to top frame edge
ay2 = ay1 - winY // bottom frame edge
// ------------------OHLC
// ------------------ lowest & highest over LB bars
$indL[0] = min(lowest[LB](open),open) // max of open
$indH[0] = max(highest[LB](open),open) // min of open
$indL[1] = min(lowest[LB](low),low) // max of low
$indH[1] = max(highest[LB](low),low) // min of low
$indL[2] = min(lowest[LB](high),high) // max of high
$indH[2] = max(highest[LB](high),high) // min of high
$indL[3] = min(lowest[LB](close),close) // max of close
$indH[3] = max(highest[LB](close),close) // min of close
// ------------------ indicators
$indL[4] = min(lowest[LB](avg),avg) // max of close
$indH[4] = max(highest[LB](avg),avg) // min of close
// ---------------------------------------------------------------- candle range
// find the HH/LL of all items, $indL[] and $indH[].
for i = 0 to lastset($indH)
if i = 0 then
LL = $indL[i] // start at a default, 1st in list!
HH = $indH[i]
elsif $indL[i] < LL then // further LL
LL = $indL[i]
elsif $indH[i] > HH then // further HH
HH = $indH[i]
endif
next
loRef= LL // lowest low from LB bars of $indL[]
HiRef= HH // highest high from LB bars of $indH[]
hiLoRng = HiRef-LoRef // vertical range over LB bars
ref = (winY)/hilorng // point to pixels conversion constant
// ---------------------------------------------------------------- candle display
for i = 0 to LB
xref = ax1 + (sizeBar * i) // reference to center of bar
op = ay2+((open [LB-i]-loref)*ref) // pixel conversions
hi = ay2+((high [LB-i]-loref)*ref) // take the difference between the current ohlc values
lo = ay2+((low [LB-i]-loref)*ref) // and the lowest low. LB-1 reverses the index to i.
cl = ay2+((close[LB-i]-loref)*ref) // multiply by constant. reference all to frame bottom edge.
x1 = xref
x2 = xref
y1 = op
y2 = cl
// ------------------------------------------------ draw candles body
if op>cl then // bear candle
drawrectangle(x1-1,y1,x2+1,y2)anchor(topLeft,xshift,yshift)coloured("red",155)bordercolor("white",100)
else // bull candle
drawrectangle(x1-1,y1,x2+1,y2)anchor(topLeft,xshift,yshift)coloured("lime",155)bordercolor("white",100)
endif
// ------------------------------------------------ draw candles wicks
y1 = hi
y2 = lo
drawsegment(x1,y1,x2,y2)anchor(topLeft,xshift,yshift)coloured("white",155)
next
// ---------------------------------------------------------------- draw line
for i = 0 to LB
xref = ax1 + (sizeBar * i) // reference to center of bar
av = ay2+((avg[LB-i] -loref)*ref)
av1 = ay2+((avg[LB-i+1]-loref)*ref) // +1 for prior position
x1 = xref-5 // -5 is so the segment is draw from the last position to the new position
x2 = xref
y1 = av1
y2 = av
drawsegment(x1,y1,x2,y2)anchor(topLeft,xshift,yshift)coloured("yellow",255)
next
// ---------------------------------------------------------------- rectangle border
indent = 10 // outside of frame
x1 = ax1 - indent
x2 = ax1 + (LB*sizeBar ) +indent // max left width
y1 = 0 + ay2 - indent // max top height
y2 = y1 + winY + (2 * indent)
drawrectangle(x1,y1,x2,y2)anchor(topleft,xshift,yshift)style(dottedline,1)
// corner references
a=100
drawtext("x1y1",x1,y1)coloured("red",a)anchor(topleft,xshift,yshift)
drawtext("x2y2",x2,y2)coloured("red",a)anchor(topleft,xshift,yshift)
drawtext("x1y2",x1,y2)coloured("red",a)anchor(topleft,xshift,yshift)
drawtext("x2y1",x2,y1)coloured("red",a)anchor(topleft,xshift,yshift)
endif // skip historic bars
return
The story goes that, data is stored in memory, data is referenced by a variable, and a variable has to have a unique name which you use to access it. If you have lots of data, then a array allows those values to be stored under a single name, with access to each element via a index value, which intern can be manipulated with some Math wizardry.
Beyond that are multidimensional arrays which allow several series of data to be stored and accessed with several index values, one per dimension. A single dimension array is like a list of values while a multidimensional array is like a table where several lists of different data are linked in like rows and columns in a basic sense. Unfortunately in Probuilder there is only a one dimensional array with a 1 million index address from 0 To 999999.
The code below is a attempt to create a multidimensional array to hold all the data from the indicators in blocks, under one array name. Maniplication is via the index value as normal but having a block offset value to get to the correct block of data within the array. This is so additional indicators could be easily added to the array and also later accessed.
The other elements of the program allow visually to see the effect of ” drawonlastbaronly, calculationlastbars, islastbarupdate’ to be evaluated depending on if commented out or not, setting values etc. This is because of compromisers and between limitations which affect performance and taxing the cpu.
The ind0 = open etc is to decouple the origin value source from the multidimensional array loading.
The displayed table uses the extracted values from the array which is in itself a good way to display values.
This multidimensional array technique is going to appear in later mini window versions but i thought its worth pointing out what’s going on with it.
defparam drawonlastbaronly = true
defparam calculateonlastbars = 200
//if islastbarupdate then
LB = 10
SZ=LB-1
// ------------------ indicators
ind0 = open
ind1 = high
ind2 = low
ind3 = close
ind4 = average[50](close)
//call "calculateonlastbars" // this is ok here, but dont work if isolated
if islastbarupdate then
for i = 0 to SZ // when i=0 thats current bar
// arrayName i = index + ( LB = data per block * block offset )
$ind[i+(LB*0)] = ind0[i] // 0-9
$ind[i+(LB*1)] = ind1[i] // 10-19
$ind[i+(LB*2)] = ind2[i] // 20-29
$ind[i+(LB*3)] = ind3[i] // 30-39
$ind[i+(LB*4)] = ind4[i] // 40-49
next
DRAWTEXT/*
*/("index open high low close average",150,30) /*
*/anchor(middle,xshift,yshift)
for i = 0 to SZ // when i=0 thats current bar
drawtext(i,-100,0+(i*-15))anchor(middle,xshift,yshift)
drawtext($ind[i+(LB*0)], 0,0+(i*-15))anchor(middle,xshift,yshift)
drawtext($ind[i+(LB*1)],100,0+(i*-15))anchor(middle,xshift,yshift)
drawtext($ind[i+(LB*2)],200,0+(i*-15))anchor(middle,xshift,yshift)
drawtext($ind[i+(LB*3)],300,0+(i*-15))anchor(middle,xshift,yshift)
drawtext($ind[i+(LB*4)],400,0+(i*-15))anchor(middle,xshift,yshift)
next
endif
//endif
return ind0
// need this if splitting code line with the / and * block comments !
// make sure this is done first or all hell breaks loose!
/**/
To circle back from multidimensional arrays, in memory, its probably stored in a equivalent 1 dimensional lump of memory where certain blocks of the lump are the different dimension data value. Hopefully you can see the similar pattern.
This version uses the MD array and allows a format to add several indicators. This through up a problem regarding ‘colour’ to differentiate the indicator lines. I created a array of RGBa value in a decimal format and used some wizardry to decode later so i could get away with one DRAWSEGMENT line for all the indicator lines. The loop a lines up with the 4 corresponding array value with RGBa and indicators to help in the loop cycle.
There are some subtle changes to names etc from prior version and I’ve added some Config Settings Variables to change the number of bars which also alters the width, also the height and position of the window.
In its current state, you can set a hard coded Time Frame for the window, but a 2nd one if needed , it needs its own indicator file for the different time frame. This is where the position variables come in, to handle the position of the other(s) without hard coding a different position etc. Best way to setup multiple TF files is to duplicate the indicator, change the TF and file name edits.
I think this version probably sits on the line between functionality/performance. Depending on you machine spec, one or two instances may be ok , but more may move over the/your line.
/* Config Settings Variables:
bars integer 40
height integer 250
osX integer 0
osY integer 0
*/
defparam drawonlastbaronly = true
//timeframe(15minutes)
// ----------------------------------------------------------------------- variables
if barindex = 0 then
LB = abs(bars) // lookback bars 0-40=41
SZ=LB-1 // sz = 40-1
SZbar = 5 // frame bar size pixels
winX = max(SZBar*LB,50) // width of frame
winY = max(height,50) // height of frame
endif
// ----------------------------------------------------------------------- indicators
ind0 = open // list of indicators
ind1 = high
ind2 = low
ind3 = close
ind4 = average[50](close)
ind5 = average[100](close)
ind6 = average[200](close)
ind7 = Supertrend[3,10]
if islastbarupdate then
// ----------------------------------------------------------------------- absolute coords
ax1 = 40+abs(osX) // indent from left chart edge to left frame edge
ax2 = ax1 + winX // right frame edge
ay1 = -40-abs(osY) // indent from top chart edge to top frame edge
ay2 = ay1 - winY // bottom frame edge
//------------------------------------------------------ encode rgb.a array
$rgba[0]= 255000000.255 // red
$rgba[1]= 255128192.255 // pink
$rgba[2]= 050050220.255 // blue
$rgba[3]= 255128192.255 // pink
$rgba[4]= 255255000.150 // yellow
$rgba[5]= 255192064.100 // dark yellow
$rgba[6]= 000255000.050 // green
$rgba[7]= 255255255.150 // white
// ----------------------------------------------------------------------- encode indicators
for i = 0 to SZ // when i=0 thats current bar
$ind[i+(LB*0)] = ind0[i]
$ind[i+(LB*1)] = ind1[i]
$ind[i+(LB*2)] = ind2[i]
$ind[i+(LB*3)] = ind3[i]
$ind[i+(LB*4)] = ind4[i] // multi dimentional array to hold last 'n' data points
$ind[i+(LB*5)] = ind5[i] // from every indicator for mini display
$ind[i+(LB*6)] = ind6[i]
$ind[i+(LB*7)] = ind7[i]
next
// ----------------------------------------------------------------------- Find HH LL for window
HH = $ind[0] // defaults for
LL = $ind[0] // this loop through
for i = 1 to lastset($ind)
// highest high
if $ind[i] > HH then
HH = $ind[i]
endif
// lowest low
if $ind[i] < LL then
LL = $ind[i]
endif
next
// ---------------------------------------------------------------- candle range
loRef= LL // lowest low from $ind[], of LB bars, of all items
HiRef= HH // highest high from $ind[], of LB bars of all items
hiLoRng = HiRef-LoRef // range LL to HH over LB bars
ref = (winY)/hilorng // points to pixels conversion constant
// ---------------------------------------------------------------- candle display
for i = 0 to SZ
xref = ax1 + (SZbar * (SZ-i)) // reference to center of bar reversed
op = ay2+(($ind[i+(LB*0)]-loref)*ref)
hi = ay2+(($ind[i+(LB*1)]-loref)*ref)
lo = ay2+(($ind[i+(LB*2)]-loref)*ref)
cl = ay2+(($ind[i+(LB*3)]-loref)*ref)
x1 = xref
x2 = xref
y1 = op
y2 = cl
// ------------------------------------------------ draw candles body
if op>cl then // bear candle
drawrectangle(x1-1,y1,x2+1,y2)anchor(topLeft,xshift,yshift)coloured("red",155)bordercolor("white",100)
else // bull candle
drawrectangle(x1-1,y1,x2+1,y2)anchor(topLeft,xshift,yshift)coloured("lime",155)bordercolor("white",100)
endif
// ------------------------------------------------ draw candles wicks
y1 = hi
y2 = lo
drawsegment(x1,y1,x2,y2)anchor(topLeft,xshift,yshift)coloured("white",155)
next
// ---------------------------------------------------------------- display line(s)
for j = 4 to lastset($ind)
for i = 0 to SZ-1 // -1 to avoid drawing line to point earlier than in array
xref = ax1 + (SZbar * (SZ-i)) // reference to center of bar reversed
av = ay2+(($ind[i+(LB*j)]-loRef)*ref)
av1 = ay2+(($ind[(i+1)+(LB*j)]-loRef)*ref)
x1 = xref-5
x2 = xref
y1 = av1
y2 = av
if i = 0 then
//------------------------------------------------------ decode rgba
rgba= $rgba[j]
rgb = round(rgba)
a = round((rgba-rgb)*1000)
r = round(rgb/1000000)
g = round((rgb - (r*1000000))/1000)
b = rgb - (r*1000000) - (g*1000)
endif
drawsegment(x1,y1,x2,y2)anchor(topLeft,xshift,yshift)coloured(r,g,b,a)
next
next
// ---------------------------------------------------------------- rectangle border
indent = 10 // outside of frame
x1 = ax1 - indent
x2 = ax1 + (sz*SZBar ) +indent // max left width
y1 = 0 + ay2 - indent // max top height
y2 = y1 + winY + (2 * indent)
drawrectangle(x1,y1,x2,y2)anchor(topleft,xshift,yshift)style(dottedline,1)
// corner references
a=100
drawtext("x1y1",x1,y1)coloured("red",a)anchor(topleft,xshift,yshift)
drawtext("x2y2",x2,y2)coloured("red",a)anchor(topleft,xshift,yshift)
drawtext("x1y2",x1,y2)coloured("red",a)anchor(topleft,xshift,yshift)
drawtext("x2y1",x2,y1)coloured("red",a)anchor(topleft,xshift,yshift)
// ----------------------------------------------------------------
endif
return
/**/
This version is basically the same as the previous version. The changes are:
It worth noting that keeping the code simple and specific for the task in hand is the best policy in PRT. The following versions kind of throw that out the window and explore different concept and techniques to see what can be done got away with, were the limits may lie and what it looks like stood on the edge. Be warned you may be surprised or shocked, it won’t look pretty.
The design philosophy at the start was ‘ get something working and see if its possible’ then if it was possible, ‘ Solve and refine all the problems it created in its wake’. This is so you don’t spend time refining the idea to then find its not possible. Also, if it is possible you can evaluate it to see if its a benefit or not and again use that the see if it worth pursuing. Which ever way it goes its usually a win win scenario because you mostly learn something along the way. This bring us up to were the development halted.
This version comprises of 5 files, 1 Main file, 1 settings file and 3 utility files. All files need to be imported, but only the V1.14 is needed to be run on a chart. All the file’s are in ‘work in progress’ state and none are finished or fully tested but serve as a learning platform to see what can be achieved.
‘Main’ file does most of the heavy lifting. This has change quite a lot from last version mainly because of using the ‘call’ ed files.In addition to those, the grid display block of code, currently disabled, briefly was a look at adding drawn lines and objects to the mini window as a further development path.
‘Settings’ file shows how setting could be changed regarding each indicator element used and possible be extended to do some general settings. In the same way as changing Config settings variable change the operation of a indicator, so does changing values in a call file when re-run. The changes ripple through to all the files used to call it.
‘ig’ file is a utility based on creating a form of ‘enumeration’ facility. If initially came about because i was looking into a more understandable way of programming logic. I stead of using 0, 1, -1 etc i used bear, bull, on, off, tru, fal, yes, no , zero, etc and ‘ig’ let me do that but also allowing me to set those variables on 1 or less lines in the editor. Also i was making some indicators which required manually assigning a lot of array elements which this utility helped again to do it in less lines of code. In the mini window its used to assign several variables on less lines, and the reason several are used is because some use the output from the early ones. This all does make it difficult to keep track of, and if lines need comments then this gain isn’t as good, but hey!
RGBA file holds a list of decimal code value which can be used by choosing the appropriate index value. The array is re-built locally to use. So the list could grow and be used in other projects if required. That’s the thinking.
The Setting / ig / RGBA files all run as a one shot event when barindex = 0. No need to repeat calling these.
TF file is used to allow different time frame to be set from the config settings window. There are a selection of time frames set in ‘TF’ and if not there, can be easily added following the design structure. One thing to note is that if you run this file, you get a error, ignore it because the way I have used it avoids that error appearing if you break the TF rule by setting a TF below the chart time frame. Currently if a TF is not listed the window stays blank. And if you change to a chart TF which invalidates a mini window TF then the mini window defaults to chart TF. If the chart TF is changed to re-validate mini window, then it returns with is prior settings. This avoids the normal process of the chart dumping the indicator for a in-valid TF and then having to put it back and change any settings you altered.
The mini-window in its current WIP form does appear to be stable and you can easily setup several MW by first adding 1 MW then using the copy button in the Chart settings for indicators and then using the osX to set a pixel offset value to move position along with Xmul to multiply depending on how many MY you have.
Performance can degrade in several ways, the number of units and/or MW’s used can take time to finish rendering. Also, you can get to a point where you may get close to the memory limit. And as well as making the cpu work and fans spin up.
Now going forward, there are several options to refine but the biggest dint on performance is the loading of all candle/indicator values and number crunching then only requiring a fraction. The gets worse when multiple windows used and the distance from the default TF and highest TF used. For candles the data needs only to cover the require set of bars. But with indicators like AVERAGE etc, you need more to create the oldest displayed average. Also, some indicators may need even more to get correctly positioned like supertrend on higher TF’s.
Files to follow…
Reminder…
This version comprises of 5 files, 1 Main file, 1 settings file and 3 utility files. All files need to be imported, but only the V1.14 is needed to be run on a chart. All the file’s are in ‘work in progress’ state and none are finished or fully tested but serve as a learning platform to see what can be achieved.
One more thought for today, make sure you keep the same file names because the ‘CALL’ lines will be looking for them!
Just noticed that the attachment files has inserted ‘-‘ in the file names where they originally used a space. This name change will affect the calling of those files.
Beau travail, belle réussite.
Great work, great success.
Describe what this topic is trying to build, in plain English, and ProRealAI writes the ProRealTime™ indicator, screener or system for you.
Indicator: Mini window for multi-timeframe charts
This topic contains 15 replies,
has 4 voices, and was last updated by robert123
2 weeks, 1 day ago.
| Forum: | ProBuilder: Indicators & Custom Tools |
| Language: | English |
| Started: | 09/23/2026 |
| Status: | Active |
| Attachments: | 17 files |
The information collected on this form is stored in a computer file by ProRealCode to create and access your ProRealCode profile. This data is kept in a secure database for the duration of the member's membership. They will be kept as long as you use our services and will be automatically deleted after 3 years of inactivity. Your personal data is used to create your private profile on ProRealCode. This data is maintained by SAS ProRealCode, 407 rue Freycinet, 59151 Arleux, France. If you subscribe to our newsletters, your email address is provided to our service provider "MailChimp" located in the United States, with whom we have signed a confidentiality agreement. This company is also compliant with the EU/Swiss Privacy Shield, and the GDPR. For any request for correction or deletion concerning your data, you can directly contact the ProRealCode team by email at privacy@prorealcode.com If you would like to lodge a complaint regarding the use of your personal data, you can contact your data protection supervisory authority.