Smart money indicator (using Arrays)
Forums › ProRealTime English forum › ProBuilder support › Smart money indicator (using Arrays)
- This topic has 17 replies, 6 voices, and was last updated 1 year ago by JC_Bywan.
-
-
07/17/2023 at 7:34 PM #217792
Kindly requesting help with my code. I’m trying to create a smart money indicator similar to the ones found on the marketplace.
My goal is to use it for automated trading strategies, so I attempted to make one myself so i can customise it.
Basically, I want to draw rectangles on the chart to mark the gaps.eg where the low is lower than the previous two lows, and vice versa for the highs.
I’m struggling to get anything to show up on the chart. Its always blank.
Beyond the basic Conditional IFs, im a noob with arrays and loops. Ive been trying to learn arrays from the material on the forum. Tried chatgpt aisstance as well.
Here’s what I’ve got so far:
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061DEFPARAM DrawOnLastBarOnly = TrueONCE Elements = 50IF BarIndex = 0 THENFOR i = 0 TO Elements$LowGapsTop[i] = undefined$LowGapsBottom[i] = undefined$HighGapsTop[i] = undefined$HighGapsBottom[i] = undefined$GapStart[i] = undefined$GapEnd[i] = undefined$LowGapFilled[i] = undefined$HighGapFilled[i] = undefinedNEXTENDIF// Identify and store low gapsIF Low < Min(Low[1], Low[2]) THEN$LowGapsTop[LastSet($LowGapsTop) + 1] = Min(Low[1], Low[2])$LowGapsBottom[LastSet($LowGapsBottom) + 1] = Low$GapStart[LastSet($GapStart) + 1] = BarIndex$LowGapFilled[LastSet($LowGapFilled) + 1] = 0ENDIF// Identify and store high gapsIF High > Max(High[1], High[2]) THEN$HighGapsTop[LastSet($HighGapsTop) + 1] = Max(High[1], High[2])$HighGapsBottom[LastSet($HighGapsBottom) + 1] = High$GapStart[LastSet($GapStart) + 1] = BarIndex$HighGapFilled[LastSet($HighGapFilled) + 1] = 0ENDIF// Loop over all identified gaps and draw rectangles if they have not been filledFOR i = 0 TO Elements DO// Check if the low gap has been filledIF IsSet($LowGapsBottom[i]) = 1 and Low < $LowGapsBottom[i] AND $LowGapFilled[i] = 0 THEN$GapEnd[i] = BarIndex$LowGapFilled[i] = 1ENDIF// Check if the high gap has been filledIF IsSet($HighGapsTop[i]) = 1 and High > $HighGapsTop[i] AND $HighGapFilled[i] = 0 THEN$GapEnd[i] = BarIndex$HighGapFilled[i] = 1ENDIF// If the low gap is not filled, draw a rectangleIF IsSet($LowGapsBottom[i]) = 1 and $LowGapFilled[i] = 0 THENDRAWRECTANGLE($GapStart[i], $LowGapsTop[i], BarIndex, $LowGapsBottom[i]) COLOURED(255,0,0,50)ENDIF// If the high gap is not filled, draw a rectangleIF IsSet($HighGapsTop[i]) = 1 and $HighGapFilled[i] = 0 THENDRAWRECTANGLE($GapStart[i], $HighGapsBottom[i], BarIndex, $HighGapsTop[i]) COLOURED(0,255,0,50)ENDIFNEXTRETURNAppreciate any help
07/18/2023 at 4:18 AM #217801Replace (empty) line 33 with:
1Elements = max(LastSet($HighGapsTop),LastSet($LowGapsTop))1 user thanked author for this post.
07/18/2023 at 12:26 PM #217832Thank you Roberto. I add the line of code and it started showing some drawings but not exactly what I wanted.
I still dont understand the logic behind it, if you could explain it I would be very grateful. I have no prev coding knowledge and really want to understand how it works.
Regarding the code. Its drawing the rectangles well before the intended start. Please see attached screenshot.
Greatly appreciate the time you are taking to help me.
07/18/2023 at 1:30 PM #217836It’s because of LastSet, which allows you to add new elemets to an arry without caring about how many elements have already been creted. With that instruction, lines 5-16 are useless, as they build the first 51 elelements, so that when you start adding elemnts they will start from the 52nd, i.e. element 51.
Since you loop through the first 51 elemts in lines 35-59, you will only scan the empty elements created in lines 5-16.
My addition will check what is the highest number of elemnts, so that ALL elements are scanned.
Actually line 35 could be written as:
1FOR i = 50 TO Elements DOjust to skip the first unused elements (or you can get rid of lines 3-16.
I have never used LastSet myself, as I always keep track of how many elements I have created. And I usually prefer using a fixed number of elements.
To keep a fixed number of elements tou would need to change the code quite a lot, to store new elements when need,, but, BEFORE adding a new one you should always shift the last N-1 elelents one place, to make room for the new one.
If you need only the last 50 elements, then create (as you have done) ALL those 50 elements at the very first bar, then use elemenbt 50 as the current one, but before replacing the old data with the new one in element 50, you should shift the first 49 elemnts one place, so that element 2 is copied to element 1 (thus losing the oldest elelemt) until you finish copying elelent 50 to element 49. At that point you can set element 50 with the new datum.
When you scan the whole arrayto be plotted, you will allways plot 50 elements.
07/18/2023 at 2:45 PM #217838You are right, i didnt need to initialise the array.
What is the advantage to not using LASTSET. It seems like a lot of work to keep rearranging the array. I believe i read somewhere on the forum the array can hold 1million values.
If its computation can i just not use – DEFPARAM CalculateOnLastBars
My goal is to first develop the indicator. Than i can try to get the array values eg lowest low in the last 200 bars thats not been filled or something along those lines to develop a strategy.
I think my current code isnt save the barindex on which the value gap is detected. Its drawing the rectangle well into the previous bars.
Any advice how i can can get it too look like this ? ( attached picture)
07/18/2023 at 3:44 PM #217842This is as far as i got.
Its racking my brains.
I managed to get the lower gaps to somewhat work. But the highgaps isnt working at all.
No idea on how to make the boxes smooth.
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455DEFPARAM DrawOnLastBarOnly = falseDEFPARAM CalculateOnLastBars = 200Once Elements = 0// Identify and store low gapsIF Low < Min(Low[1], Low[2]) THEN$LowGapsTop[LastSet($LowGapsTop) + 1] = Min(Low[1], Low[2])$LowGapsBottom[LastSet($LowGapsBottom) + 1] = Low$GapStartLow[LastSet($GapStartLow) + 1] = BarIndex$LowGapFilled[LastSet($LowGapFilled) + 1] = 0ENDIF// Identify and store high gapsIF High > Max(High[1], High[2]) THEN$HighGapsTop[LastSet($HighGapsTop) + 1] = Max(High[1], High[2])$HighGapsBottom[LastSet($HighGapsBottom) + 1] = High$GapStartHigh[LastSet($GapStartHigh) + 1] = BarIndex$HighGapFilled[LastSet($HighGapFilled) + 1] = 0ENDIFElements = max(LastSet($HighGapsTop),LastSet($LowGapsTop))// Loop over all identified gaps and draw rectangles if they have not been filledFOR i = 0 TO Elements DO// Check if the low gap has been filledIF IsSet($LowGapsBottom[i]) = 1 and Low < $LowGapsBottom[i] AND $LowGapFilled[i] = 0 THEN$GapEnd[i] = BarIndex$LowGapFilled[i] = 1ENDIF// Check if the high gap has been filledIF IsSet($HighGapsTop[i]) = 1 and High > $HighGapsTop[i] AND $HighGapFilled[i] = 0 THEN$GapEnd[i] = BarIndex$HighGapFilled[i] = 1ENDIF// If the low gap is not filled, draw a rectangleIF IsSet($LowGapsBottom[i]) = 1 and $LowGapFilled[i] = 0 THENDRAWRECTANGLE($GapStartLow[i], min(low,$LowGapsTop[i]), BarIndex, $LowGapsBottom[i]) coloured("blue",80) bordercolor("black")ENDIF// If the high gap is not filled, draw a rectangleIF IsSet($HighGapsTop[i]) = 1 and $HighGapFilled[i] = 0 THENDRAWRECTANGLE($GapStartHigh[i], $HighGapsBottom[i], BarIndex, $HighGapsTop[i]) coloured("red",80) bordercolor("black")ENDIFNEXTRETURN07/19/2023 at 4:16 AM #217857Spent a few hours but i managed to make something that sort of resembles what I wanted.
I cant waste anymore time or brain power on this. Im gonna shelf it for the time being and work on it another time.
Please if any expert coders could help me out. This indicator is a useful leanring exp for anyone starting and could be a good addition to the library.
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091DEFPARAM DrawOnLastBarOnly = trueDEFPARAM CalculateOnLastBars = 2000// Identify and store high gapsIF High > Max(High[1], High[2]) THEN$HighGapsTop[LastSet($HighGapsTop) + 1] = Max(High[1], High[2])$HighGapsBottom[LastSet($HighGapsBottom) + 1] = High$GapStartHigh[LastSet($GapStartHigh) + 1] = BarIndex$HighGapStatus[LastSet($HighGapStatus) + 1] = 0$GapEndHigh[LastSet($GapEndHigh) + 1] = 0$GapFilledHigh[LastSet($GapFilledHigh) + 1] = 0ENDIF// Identify and store low gapsIF Low < Min(Low[1], Low[2]) THEN$LowGapsTop[LastSet($LowGapsTop) + 1] = Min(Low[1], Low[2])$LowGapsBottom[LastSet($LowGapsBottom) + 1] = Low$GapStartLow[LastSet($GapStartLow) + 1] = BarIndex$LowGapStatus[LastSet($LowGapStatus) + 1] = 0$GapEndLow[LastSet($GapEndLow) + 1] = 0$GapFilledLow[LastSet($GapFilledLow) + 1] = 0ENDIF// GAP status// 0 for not filled// 1 for filled upwards (High crosses over $HighGapsTop[i] and Low < $HighGapsBottom[i])// 2 for filled downwards (Low crosses under $HighGapsBottom[i] and High > $HighGapsTop[i])// 3 for partially filled upwards (High > $HighGapsBottom[i] and High < $HighGapsTop[i])// 4 for partially filled downwards (Low > $HighGapsBottom[i] and Low < $HighGapsTop[i])// 5 for filled upwards (Low crosses under $LowGapsBottom[i] and High > $LowGapsTop[i])// 6 for filled downwards (High crosses over $LowGapsTop[i] and Low < $LowGapsBottom[i])// 7 for partially filled upwards (Low > $LowGapsBottom[i] and Low < $LowGapsTop[i])// 8 for partially filled downwards (High > $LowGapsBottom[i] and High < $LowGapsTop[i])Elements = max(LastSet($LowGapsTop), LastSet($LowGapsTop))// Loop over all identified gaps and draw rectangles if they have not been filledFOR i = 0 TO Elements DO// High gapsIF High > $HighGapsTop[i] AND Low < $HighGapsBottom[i] AND $GapFilledHigh[i] = 0 THEN // Gap Status 1$GapFilledHigh[i] = 1$HighGapStatus[i] = 1$GapEndHigh[i] = BarIndexELSIF Low < $HighGapsBottom[i] AND High > $HighGapsTop[i] AND $GapFilledHigh[i] = 0 THEN // Gap Status 2$GapFilledHigh[i] = 1$HighGapStatus[i] = 2$GapEndHigh[i] = BarIndexELSIF High > $HighGapsBottom[i] AND High < $HighGapsTop[i] AND $GapFilledHigh[i] = 0 THEN // Gap Status 3barhigh = High$HighGapsTop[i] = Max(High, barhigh)$HighGapStatus[i] = 3$GapEndHigh[i] = BarIndexELSIF Low > $HighGapsBottom[i] AND Low < $HighGapsTop[i] AND $GapFilledHigh[i] = 0 THEN // Gap Status 4barlow = Low$HighGapsBottom[i] = Min(Low, barlow)$HighGapStatus[i] = 4$GapEndHigh[i] = BarIndexENDIF// Low gapsIF Low < $LowGapsBottom[i] AND High > $LowGapsTop[i] AND $GapFilledLow[i] = 0 THEN // Gap Status 5$LowGapStatus[i] = 5$GapEndLow[i] = BarIndex$GapFilledLow[i] = 1ELSIF High > $LowGapsTop[i] AND Low < $LowGapsBottom[i] AND $GapFilledLow[i] = 0 THEN // Gap Status 6$LowGapStatus[i] = 6$GapEndLow[i] = BarIndex$GapFilledLow[i] = 1ELSIF Low > $LowGapsBottom[i] AND Low < $LowGapsTop[i] AND $GapFilledLow[i] = 0 THEN // Gap Status 7barlow = Low$LowGapsTop[i] = Min(Low, barlow)$LowGapStatus[i] = 7$GapEndLow[i] = BarIndexELSIF High > $LowGapsBottom[i] AND High < $LowGapsTop[i] AND $GapFilledLow[i] = 0 THEN // Gap Status 8barhigh = High$LowGapsBottom[i] = Max(High, barhigh)$LowGapStatus[i] = 8$GapEndLow[i] = BarIndexENDIFIF $HighGapStatus[i] <> 0 THENDRAWRECTANGLE($GapStartHigh[i], $HighGapsTop[i], $GapEndHigh[i], $HighGapsBottom[i]) coloured("red", 20) bordercolor("black", 20)ENDIFIF $LowGapStatus[i] <> 0 THENDRAWRECTANGLE($GapStartLow[i], $LowGapsTop[i], $GapEndLow[i], $LowGapsBottom[i]) coloured("blue", 20) bordercolor("black", 20)ENDIFNEXTRETURNAny help greatly appreciated.
07/19/2023 at 3:56 PM #217882I guess nobody wanted to help me with the coding in this. Curious if its because its a conflict of interest as there is a smart money indicator selling on the marketplace??
But anyway, i’m proud to say i’ve managed to crack this indicator (i think) by myself.
Here it is for free. Saves you paying 50-100 bucks for it on the marketplace. PLUS you can easily in coperate it into your auto trading, customise it etc.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293DEFPARAM DrawOnLastBarOnly = trueDEFPARAM CalculateOnLastBars = 2000ONCE GapsIndex = 0// Identify and store high gapsIF High > Max(High[1], High[2]) THEN$HighGapsTop[GapsIndex] = High$HighGapsBottom[GapsIndex] = Max(High[1], High[2])$GapStartHigh[GapsIndex] = BarIndex$HighGapStatus[GapsIndex] = 0$GapEndHigh[GapsIndex] = barindex$GapFilledHigh[GapsIndex] = 0GapsIndex = GapsIndex + 1ENDIF// Identify and store low gapsIF Low < Min(Low[1], Low[2]) THEN$LowGapsTop[GapsIndex] = Min(Low[1], Low[2])$LowGapsBottom[GapsIndex] = Low$GapStartLow[GapsIndex] = BarIndex$LowGapStatus[GapsIndex] = 0$GapEndLow[GapsIndex] = barindex$GapFilledLow[GapsIndex] = 0GapsIndex = GapsIndex + 1ENDIF// GAP status// 0 for not filled// 1 for filled upwards (High crosses over $HighGapsTop[i] and Low < $HighGapsBottom[i])// 2 for filled downwards (Low crosses under $HighGapsBottom[i] and High > $HighGapsTop[i])// 3 for partially filled upwards (High > $HighGapsBottom[i] and High < $HighGapsTop[i])// 4 for partially filled downwards (Low > $HighGapsBottom[i] and Low < $HighGapsTop[i])// 5 for filled upwards (Low crosses under $LowGapsBottom[i] and High > $LowGapsTop[i])// 6 for filled downwards (High crosses over $LowGapsTop[i] and Low < $LowGapsBottom[i])// 7 for partially filled upwards (Low > $LowGapsBottom[i] and Low < $LowGapsTop[i])// 8 for partially filled downwards (High > $LowGapsBottom[i] and High < $LowGapsTop[i])// Loop over all identified gaps and draw rectangles if they have not been filledFOR i = 1 TO GapsIndex-1 DO// High gapsIF High > $HighGapsTop[i] AND Low < $HighGapsBottom[i] AND $GapFilledHigh[i] = 0 THEN // Gap Status 1$GapFilledHigh[i] = 1$HighGapStatus[i] = 1$GapEndHigh[i] = BarIndexELSIF Low < $HighGapsBottom[i] AND High > $HighGapsTop[i] AND $GapFilledHigh[i] = 0 THEN // Gap Status 2$GapFilledHigh[i] = 1$HighGapStatus[i] = 2$GapEndHigh[i] = BarIndexELSIF High > $HighGapsBottom[i] AND High < $HighGapsTop[i] AND $GapFilledHigh[i] = 0 THEN // Gap Status 3$HighGapsBottom[i] = high$HighGapStatus[i] = 3ELSIF Low > $HighGapsBottom[i] AND Low < $HighGapsTop[i] AND $GapFilledHigh[i] = 0 THEN // Gap Status 4$HighGapsTop[i] = low$HighGapStatus[i] = 4ENDIFIF $HighGapStatus[i] <> 0 AND $GapFilledHigh[i] = 1 THENDRAWRECTANGLE($GapStartHigh[i], $HighGapsTop[i], $GapEndHigh[i], $HighGapsBottom[i]) coloured("red", 20) bordercolor("black", 20)ELSIF $HighGapStatus[i] <> 0 AND $GapFilledHigh[i] = 0 THENDRAWRECTANGLE($GapStartHigh[i], $HighGapsTop[i], barindex, $HighGapsBottom[i]) coloured("red", 20) bordercolor("black", 20)ENDIF// Low gapsIF Low < $LowGapsBottom[i] AND High > $LowGapsTop[i] AND $GapFilledLow[i] = 0 THEN // Gap Status 5$LowGapStatus[i] = 5$GapEndLow[i] = BarIndex$GapFilledLow[i] = 1ELSIF High > $LowGapsTop[i] AND Low < $LowGapsBottom[i] AND $GapFilledLow[i] = 0 THEN // Gap Status 6$LowGapStatus[i] = 6$GapEndLow[i] = BarIndex$GapFilledLow[i] = 1ELSIF Low > $LowGapsBottom[i] AND Low < $LowGapsTop[i] AND $GapFilledLow[i] = 0 THEN // Gap Status 7$LowGapsTop[i] = low$LowGapStatus[i] = 7ELSIF High > $LowGapsBottom[i] AND High < $LowGapsTop[i] AND $GapFilledLow[i] = 0 THEN // Gap Status 8$LowGapsBottom[i] = high$LowGapStatus[i] = 8ENDIFIF $LowGapStatus[i] <> 0 AND $GapFilledLow[i] = 1 THENDRAWRECTANGLE($GapStartLow[i], $LowGapsTop[i], $GapEndLow[i], $LowGapsBottom[i]) coloured("blue", 20) bordercolor("black", 20)ELSIF $LowGapStatus[i] <> 0 AND $GapFilledLow[i] = 0 THENDRAWRECTANGLE($GapStartLow[i], $LowGapsTop[i], barindex, $LowGapsBottom[i]) coloured("blue", 20) bordercolor("black", 20)ENDIFNEXTRETURNNext step is to make it multi timeframe (for another day, unless someone whats to work on it with me?)
4 users thanked author for this post.
07/21/2023 at 9:34 AM #217979No, it’s because you are not the only one needing help!
07/21/2023 at 11:58 AM #217984No, it’s because you are not the only one needing help!
I know :p , I meant it purely in jest.
I do appreciate all the help you give in this forum though.
This indicator is quite slow, do you think theres anything to make it faster? or a more optimum way to code it?
1 user thanked author for this post.
07/21/2023 at 3:12 PM #217991I tried to make a System / Algo out of it, but gave up as it took too long to run when trying anything … even when fixed values were entered, it still took far too long to load / display (for me anyway).
Pity, as you have put a lot of work into it, so it would be good to see it make money?
07/21/2023 at 4:47 PM #217993If you backtest it, it loops through the array each bar. As the array gets bigger the loop gets bigger.
I think this is the issue. Wild guess , as i dont fully understand how arrays work.
It might make it faster if we could reset the array after the price has been filled. So it only loops through unfilled arrays. Unset($array) dosent work.
I am unable to conceptulise the process.
You could probably replicate the indicator by just using loops. But then i dont know how you would save the values so we can build strategies on it. Thats a whole different code.
Hopefully the more experienced coders here can advise us.
07/21/2023 at 5:26 PM #217994You could try this and see if it makes it any faster.
I havent started coding any strategy yet so cant test on backtest
1FOR i = max(0,GapsIndex-50) TO GapsIndex DOI dont think we would need more than the last 50 values of the array
1 user thanked author for this post.
07/22/2023 at 12:32 AM #217998You are right, i didnt need to initialise the array. What is the advantage to not using LASTSET. It seems like a lot of work to keep rearranging the array. I believe i read somewhere on the forum the array can hold 1million values.
I think you understand very well what the issue is hence what needs to be solved in order to get some speed into it. But I can tell you, for someone like me (call me a die hard coder) the way to deal with arrays in PRT is so much against any nature I am used to, that I simply can’t wrap my brains around it.
The solution should be something like working with chunks of past data (shift that each 100 bars or so), so that it remains fast and independent of the size of the backtest. But instead of focusing on the functional solution, all we’d do is (indeed) rack our brains on the technical solution because of how PRT (-coding) works. This is just not for me at all.Meanwhile a hats of to you for how far you got with it.
PS: I never saw a solution in the forum, working with arrays which was workable – always for the same reason : it is infinitely too slow. Arrays in PRT are too slow to begin with, but the solutions with them always depict huge redundancy in the processing. You saw that very correctly …
2 users thanked author for this post.
07/22/2023 at 11:59 AM #218004Ditto, Monochrome has done well!!
PRT is good but has limited support and programming has it’s own challenges.
-
AuthorPosts