Welcome Guest, please sign in to participate in a discussion. | Search | Active Topics | |
Registered User Joined: 12/17/2004 Posts: 143
|
Is there a way Blocks (now called StockFiner) can tell me when the high of the last 20 days ocurred (was it today, 20 days back, 4 days back), without (close to) 20 if then statements? I need an atomated answer, not something involving using the ponter feature. Thanks.
|
|
Worden Trainer
Joined: 10/7/2004 Posts: 65,138
|
I doubt it is the most efficient way to do this (I'm not a programmer), but I think the following RealCode Indicator should return the desired Value:
'# Period = UserInput.Integer = 20
If Period >= 2 Then
Static Max As Single
Static Count As Integer
Static Since As Integer
If Price.High > Max OrElse CurrentIndex = 0 Then
Max = Price.High
Count = 1
Since = 0
Else If Max = Price.High
Count += 1
Since = 0
End If
If CurrentIndex >= Period Then
If Price.High(Period) = Max Then Count -= 1
If Count = 0 Then
Max = Price.High(Period-1)
Count = 1
Since = Period-1
For i As Integer = Period-2 To 0 Step -1
If Price.High(i) > Max Then
Max = Price.High(i)
Count = 1
Since = i
Else If Price.High(i) = Max Then
Count += 1
Since = i
End If
Next
End If
End If
If CurrentIndex >= Period-1 Then
Plot = Since
Else
Plot = Single.NaN
End If
Since += 1
Else
Plot = 0
End If
-Bruce Personal Criteria Formulas TC2000 Support Articles
|
|
Registered User Joined: 12/31/2005 Posts: 2,499
|
Here is duplicate logic written a little differently:
'# period = userinput.integer = 20
Static sinceMaxH As Integer
If isfirstbar Then
sinceMaxH = 0
End If
‘
‘ check To see If the max high expired or handle
' the maxh calc for time before price.maxHigh is avaialble
‘
If price.maxhigh(period) < price.maxhigh(period,1) Or _
CurrentIndex <= Period Then
‘
‘ New H, need To find out When it occurred
‘
sinceMaxH = getSinceMaxH(period)
Else If price.high >= price.maxhigh(period-1,1) Then
sincemaxH = 0
Else
sinceMaxH += 1
End If
Plot = SinceMaxH
=========================
function getSinceMaxH(period as integer) as integer
Dim I As Integer
Dim Target As Single
Target = Single.MinValue
For I = period-1 To 0 Step -1
If price.high(i) >= target Then
getsinceMaxH = i
target = price.High(i)
End If
Next i
End Function
|
|
Registered User Joined: 12/17/2004 Posts: 143
|
Jas0501,
This seems to use fewer lines (as many of your lines are only explanatory, right?). Thaks for providing it also.
Below, I've tried editing your code to find the Low of the past 32 days. How would I further edit it to make the analyzed dates start 8 days back instead of today?
J
'# period = userinput.integer = 32
Static sinceMinL As Integer If isfirstbar Then
sinceMinL = 0
End If
If price.minLow(period) < price.maxhigh(period,1) Or _
CurrentIndex <= Period Then
sinceMinL = getSinceMinL(period)
Else If price.low <= price.minLow(period-1,1) Then
sinceminL = 0
Else
sinceMinL += 1
End If
Plot = SinceMinL
|
|
Registered User Joined: 12/31/2005 Posts: 2,499
|
QUOTE (jfh123) Jas0501,
This seems to use fewer lines (as many of your lines are only explanatory, right?). Thaks for providing it also.
Below, I've tried editing your code to find the Low of the past 32 days. How would I further edit it to make the analyzed dates start 8 days back instead of today?
J
'# period = userinput.integer = 32
Static sinceMinL As Integer
If isfirstbar Then
sinceMinL = 0
End If
If price.minLow(period) < price.maxhigh(period,1) Or _
CurrentIndex <= Period Then
sinceMinL = getSinceMinL(period)
Else If price.low <= price.minLow(period-1,1) Then
sinceminL = 0
Else
sinceMinL += 1
End If
Plot = SinceMinL
You forgot to change one MaxHigh.
---------------------------------------------------------------
These indicators plot the count so you could just drag and drop the indicator in another indicator are reference
'# sinceCount = indicator.sinceH
if sinceCount.value(8) whatever...
otherwise you could edit the code with an additional input call offset
'# offset = userinput.integer = 0
...
... skipped lines
...
If price.minLow(period,offset) < price.maxlow(period,offset+1) Or _
CurrentIndex <= Period Then
sinceMinL = getSinceMinL(period,offset)
Else If price.low(offset) <= price.minLow(period-1,offset+1) Then
sinceminL = 0
Else
sinceMinL += 1
End If
...
... skipped lines
...
=========================
function getSinceMaxH(period as integer, offset as integer) as integer
Dim I As Integer
Dim Target As Single
Target = Single.MinValue
For I = period-1 To 0 Step -1
If price.high(offset+i) >= target Then
getsinceMaxH = i
target = price.High(offset+i)
End If
Next i
End Function
The offset approach would be plotting the count as of "offset days ago" today on the chart.
Assuming and offset of 8, in English the value of 7 today would mean 8 days ago the min low had occurred 7 days prior or 15 days from today.
|
|
Registered User Joined: 12/31/2005 Posts: 2,499
|
2 corrections
...
... skipped lines
...
If price.minLow(period,offset) < price.Minlow(period,offset+1) Or _
CurrentIndex <= Period + offset Then
sinceMinL = getSinceMinL(period,offset)
...
... skipped lines
...
This period + offset correction is required as price.minlow(period,X) will not return a value for the first period days. That is why getSinceMinL is used.
|
|
Registered User Joined: 12/17/2004 Posts: 143
|
Awesome. Thanks so much.
|
|
Worden Trainer
Joined: 10/7/2004 Posts: 65,138
|
QUOTE (jas0501) Here is duplicate logic written a little differently
I'd like to thank you for providing the alternate RealCode as jfh123 seemed to find it more understandable and easier to alter.
The main difference I see between your algorithm and my algorithm is that I calculate the Maximum or Minimum and you use the built in Price.MaxHigh() or Price.MinLow(). This allows my RealCode to calculate Since during the loop that is re-calculating the Maximum or Minimum when they expire while your code needs to make a loop after the Maximum or Minimum is re-calculated when they expire. While I don't know the algorithm used for Price.MaxHigh() and Price.MinLow(), I would suspect it needs to make its own loop, resulting in two loops for each expiration instead of one (even if all of the loops for calculating the Maximum or Minimum happen before your explicit loops - assuming Price.MaxHigh() or Price.MinLow() is pre-calculated).
I'm not sure if the above speculation is the reason or not, but the longer RealCode seems to run a bit quicker on my computer. Try adding both RealCode Indicators to the Chart and setting the Period to something high (like 500 - although the effect is visible on my computer even when the Period is 20). The longer version that I wrote appears to update more quickly when switching symbols. You can see this effect more clearly if you Drag and Drop both Indicators from the Chart to create Watchlist Columns displaying the Raw Value (without Sorting). You can then page down through the Watchlist and see how long it takes to update each symbol.
QUOTE (jfh123) I've tried editing your code to find the Low of the past 32 days. How would I further edit it to make the analyzed dates start 8 days back instead of today?
Just in case you are interested, here's one way to alter the version I posted to do this (the alterations are quite similar to those required for jas0501's RealCode):
'# Period = UserInput.Integer = 32
'# Offset = UserInput.integer = 8
If Period >= 2 AndAlso Offset >= 0 Then
Static Min As Single
Static Count As Integer
Static Since As Integer
If CurrentIndex >= Offset AndAlso CurrentIndex >= 0 Then
If Price.Low(Offset) < Min OrElse CurrentIndex = Offset Then
Min = Price.Low(Offset)
Count = 1
Since = 0
Else If Min = Price.Low(Offset)
Count += 1
Since = 0
End If
If CurrentIndex >= Period+Offset Then
If Price.Low(Period+Offset) = Min Then Count -= 1
If Count = 0 Then
Min = Price.Low(Period+Offset-1)
Count = 1
Since = Period-1
For i As Integer = Period+Offset-2 To Offset Step -1
If Price.Low(i) < Min Then
Min = Price.Low(i)
Count = 1
Since = i-Offset
Else If Price.Low(i) = Min Then
Count += 1
Since = i-Offset
End If
Next
End If
End If
End If
If CurrentIndex >= Period+Offset-1 Then
Plot = Since
Else
Plot = Single.NaN
End If
Since += 1
Else
Plot = 0
End If
-Bruce Personal Criteria Formulas TC2000 Support Articles
|
|
Registered User Joined: 12/31/2005 Posts: 2,499
|
The speed difference could be as you described. I asume the first reference to price.maxhigh(period,offset) computes the set and future references just index into the array. If so there is one possible way to improve my implementation. I use two periods, price.maxhigh(period) and price.maxhigh(period-1).
If price.maxhigh(period) < price.maxhigh(period,1) Or _
CurrentIndex <= Period Then
‘
‘ New H, need To find out When it occurred
‘
sinceMaxH = getSinceMaxH(period)
Else If price.high >= price.maxhigh(period-1,1) Then
sincemaxH = 0
Else
sinceMaxH += 1
End If
Adjusting the code so that only a single maxhigh() period is needed woud eliminate one complete set of maxhigh calculations by Blocks. This can be done by remembering yesterdays max high
'# period = userinput.integer = 20
Static sinceMaxH As Integer
Static YesterdaysValue as single
If isfirstbar Then
sinceMaxH = 0
YesterdaysValue = 0
End If
‘
‘ check To see If the max high expired or handle
' the maxh calc for time before price.maxHigh is avaialble
‘
If price.maxhigh(period) < price.maxhigh(period,1) Or _
CurrentIndex <= Period Then
‘
‘ New H, need To find out When it occurred
‘
sinceMaxH = getSinceMaxH(period)
Else If price.high >= yesterdaysValueThen
sincemaxH = 0
Else
sinceMaxH += 1
End If
yesterdaysValue = price.maxhigh(period)
Plot = SinceMaxH
This may improve the performance a bit.
The key in both Bruce's and my implementation is avoiding the lookback as often as possible. When a new High is encountered one needs to look to see when it occurred, otherwise just increment the count.
--------------------------
One other performance improvment would be to pass the new MaxHigh to the getSinceMaxH() and change the lookback. This would avoid looking at the entire range, exiting once the most recent occurrence is found. I avoided this in the first implementation as the value to pass with currentindex < period was not straight forward.
function getSinceMaxH(period as integer,target as single) as integer
Dim I As Integer
For i = 0 to period-1
If price.high(i) = target Then
getsinceMaxH = i
exit function
End If
Next i
End Function
============================
'# period = userinput.integer = 20
Static sinceMaxH As Integer
Static YesterdaysValue as single
If isfirstbar Then
sinceMaxH = 0
YesterdaysValue = 0
End If
‘
‘ check To see If the max high expired or handle
' the maxh calc for time before price.maxHigh is avaialble
‘
If price.maxhigh(period) < price.maxhigh(period,1) Or _
CurrentIndex <= Period Then
‘
‘ New H, need To find out When it occurred
‘
dim valueToPass as single
if CurrentIndex > Period then
valueToPass = price.maxhigh(period)
else if price.high > yesterdaysValue then
valueToPass = price.high
else
value = yesterdaysValue
end if
sinceMaxH = getSinceMaxH(period,valueToPass )
Else If price.high >= yesterdaysValueThen
sincemaxH = 0
Else
sinceMaxH += 1
End If
yesterdaysValue = price.maxhigh(period)
Plot = SinceMaxH
One can see that the changes made to the code to make it faster don't make it clearer. When developing code it is always better to make the code produce the correct answer first and then adjust the alogithm to make it faster, rather than make the algorith fast and then get the code to produce the correct answer.
My effort at coding this algorithm had the advantage of Bruce's implementation. I displayed both and the plotted a cummulative difference any bugs in my code displayed as a difference.
Note the above changes have not been compiled or tested. Think of them as proposals for impovement.
|
|
Registered User Joined: 12/31/2005 Posts: 2,499
|
There may only be 3 people on the planet who are interested this continued thread. That said my previous post has an error
...
... skipped line
...
else
value = yesterdaysValue
end if
...
... skipped lines
...
should be:
else
valueToPass = yesterdaysValue
end if
|
|
Worden Trainer
Joined: 10/7/2004 Posts: 65,138
|
jas0501,
You never know how many people might actually be interested. Most topics are read by far more people than actually participate and sometimes a topic might get posts after months of inactivity. That's part of the beauty of the forum format. It leverages questions, answers and discussions in a way that many more people can benefit than from a topic than are directly involved in its creation.
-Bruce Personal Criteria Formulas TC2000 Support Articles
|
|
Guest-1 |