Download software Tutorial videos
Subscription & data-feed pricing Class schedule


New account application Trading resources
Margin rates Stock & option commissions

Attention: Discussion forums are read-only for extended maintenance until further notice.
Welcome Guest, please sign in to participate in a discussion. Search | Active Topics |

How Many Days Back Did the High Occur? Rate this Topic:
Previous Topic · Next Topic Watch this topic · Print this topic ·
jfh123
Posted : Tuesday, September 30, 2008 12:21:59 PM
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.
Bruce_L
Posted : Tuesday, September 30, 2008 12:54:40 PM


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
jas0501
Posted : Tuesday, September 30, 2008 4:33:16 PM
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

jfh123
Posted : Tuesday, September 30, 2008 5:11:23 PM
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
jas0501
Posted : Tuesday, September 30, 2008 5:32:34 PM
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.

jas0501
Posted : Tuesday, September 30, 2008 5:40:51 PM
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. 

jfh123
Posted : Tuesday, September 30, 2008 9:18:50 PM
Registered User
Joined: 12/17/2004
Posts: 143
Awesome.  Thanks so much.
Bruce_L
Posted : Wednesday, October 1, 2008 11:34:01 AM


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
jas0501
Posted : Wednesday, October 1, 2008 2:55:00 PM
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.


 

jas0501
Posted : Wednesday, October 1, 2008 4:17:57 PM
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 


Bruce_L
Posted : Wednesday, October 1, 2008 4:22:33 PM


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
Users browsing this topic
Guest-1

Forum Jump
You cannot post new topics in this forum.
You cannot reply to topics in this forum.
You cannot delete your posts in this forum.
You cannot edit your posts in this forum.
You cannot create polls in this forum.
You cannot vote in polls in this forum.