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 |

Price Alerts - realcode sample Rate this Topic:
Previous Topic · Next Topic Watch this topic · Print this topic ·
Flash99
Posted : Friday, January 22, 2010 7:52:58 PM
Platinum Customer Platinum Customer

Joined: 7/16/2009
Posts: 411
In case you are a new SF5 user and are tired of switching between applications, SF5 and whatever else you use for price alerts, the sample code below will help you implement a basic price alert solution in SF5.

This is what you have to do in order to make it work:
1. Create a file Alerts.txt ( contains the price alerts)
Fields (mandatory):
- symbol
- price
- message (displayed when price alert is triggered)
Field are separated by + (you may change it, make sure you change the import code as well)
File Location: ...\StockFinder5\DataFiles\PriceAlerts\Alerts.txt
You may use an Excel spreadsheet, or anything else that might help you manage the data, .... whatever you do, you will have to create a text file from your source.
I personally use an application to manage the data, and create the text file directly from the app.

2. Create a new realcode condition using the code below.
You can customize it, do whatever you want with it. I know for sure I am missing some validations...

3. Create a new filter/scan with the realcode condition.
Recommended time frame: 2 or 5 minutes
If it's longer than 5 minutes, and you have a stock trading in range => price alert triggered again and again.

And now the 'legal' (LOL)... stuff:
I am just a user, not associated with Worden in any way; this sample is provided to new users just to give an idea ... so... use it at your own risk, AS IS, blah, blah... Please note, I am not a VB programmer, so probably things could have been done much better. Cheers.

Public Partial Class RealCodeCondition
    Inherits RealCodeCondition_base

    Public Overrides Sub CallUserCode()
        '|*****************************************************************|
        '|*** StockFinder RealCode Condition - Version 4.9 www.worden.com
        '|*** Copy and paste this header and code into StockFinder *********
        '|*** Condition:Price Alerts
        '|******************************************************************
       
        Dim barsCount As Integer = Price.Bar.Count - 1
        Dim priceHigh As Single = 0.00
        Dim priceLow As Single = 0.00
        Dim prevBarClose As Single = 0.00
        Dim prevBarHour As Integer = 0
           
        Static alerts As New System.Collections.Generic.List(Of Alert)
        ' TODO: check file timestamp & pickup new version
        ' Static uploadDateTime As System.DateTime
       
        If alerts.Count < 1 Then
            alerts = loadAlerts()
        End If
       
        If isLastBar Then
            prevBarClose = Price.Bar.Value((barsCount - 1))
            priceHigh = Price.Bar.HighValue(barsCount)
            priceLow = Price.Bar.LowValue(barsCount)
       
            If ( Price.Bar.DateValue(barsCount - 1).Hour = 16) Then
                priceHigh = Math.Max(priceHigh, prevBarClose)
                priceLow = Math.Min(priceLow, prevBarClose)
            End If
       
       
            Dim results As System.Collections.Generic.List(Of Alert) = alerts.FindAll(AddressOf FindAlert)
            If (results IsNot Nothing) Then
                For Each item As Alert In results
                    If item.price >= priceLow AndAlso item.price <= priceHigh Then
                        log.info("--- Alert --- " & Me.CurrentSymbol & " " & item.price & " " & item.message)
                    End If
                Next
            End If
        End If
       
    End Sub

    Public Function loadAlerts() As System.Collections.Generic.List(Of Alert)
        Dim reader As New RealCodeFileReader("PriceAlerts\Alerts.txt")
        loadAlerts = New System.Collections.Generic.List(Of Alert)
        Try
            reader.open
            While reader.EndOfFile = False
                Dim line As String = reader.readline
                Dim values() As String = line.split("+")

                Dim alert As Alert
                alert.symbol = values(0).Trim
                alert.price = Convert.ToSingle(values(1))
                alert.message = values(2).Trim
               
                loadAlerts.Add(alert)
            End While
        Catch ex As System.Exception
            Me.log.info("--- Read alerts file failed", ex)
        Finally
            reader.close
        end try
       
    End Function

    Public Structure Alert
        Public symbol As String
        Public price As Single
        Public message As String
    End Structure

    Private Function FindAlert(ByVal alert As Alert) As Boolean
        If alert.symbol = Me.CurrentSymbol Then
            Return True
        Else
            Return False
        End If
    End Function

End Class
jas0501
Posted : Saturday, January 23, 2010 5:24:54 PM
Registered User
Joined: 12/31/2005
Posts: 2,499
2 quick comments:
1. Using AUTOLOOP = FALSE would improve performance as there would be only 1 call. You would not need to do a islastbar check, just look at the last few bars to draw your conclusions.
2. You could address the modification date by having you alert data prep app encode the time stamp in as the  first record. Granted you would need to open the file, but would not need to read the whole thing. Just track the time stamp and shortcircuit the alert read it the same as last time.

Item 2 is a kludge. Looking forward to the day when standard IO operations are supported.

 
Flash99
Posted : Saturday, January 23, 2010 10:57:23 PM
Platinum Customer Platinum Customer

Joined: 7/16/2009
Posts: 411
QUOTE (jas0501)
2 quick comments:
1. Using AUTOLOOP = FALSE would improve performance as there would be only 1 call. You would not need to do a islastbar check, just look at the last few bars to draw your conclusions.

My impression from other tests (not for this sample) is that autoloop true with isLastBar test is faster than autoloop false. Not sure why.
QUOTE

2. You could address the modification date by having you alert data prep app encode the time stamp in as the  first record. Granted you would need to open the file, but would not need to read the whole thing. Just track the time stamp and shortcircuit the alert read it the same as last time.

Item 2 is a kludge. Looking forward to the day when standard IO operations are supported.

 

Kuf confirmed will get access to IO operations after the release.
jas0501
Posted : Sunday, January 24, 2010 12:06:29 AM
Registered User
Joined: 12/31/2005
Posts: 2,499
QUOTE (Flash99)
QUOTE (jas0501)
2 quick comments:
1. Using AUTOLOOP = FALSE would improve performance as there would be only 1 call. You would not need to do a islastbar check, just look at the last few bars to draw your conclusions.

My impression from other tests (not for this sample) is that autoloop true with isLastBar test is faster than autoloop false. Not sure why.
QUOTE

2. You could address the modification date by having you alert data prep app encode the time stamp in as the  first record. Granted you would need to open the file, but would not need to read the whole thing. Just track the time stamp and shortcircuit the alert read it the same as last time.

Item 2 is a kludge. Looking forward to the day when standard IO operations are supported.

 

Kuf confirmed will get access to IO operations after the release.


Autoloop = False will cause  the routine to be called only once vs. barcount times. In your case you only care about the latest bars so I can't imagine that it wouldn't perform significanly faster.
Flash99
Posted : Wednesday, January 27, 2010 2:11:02 PM
Platinum Customer Platinum Customer

Joined: 7/16/2009
Posts: 411
QUOTE (jas0501)

Autoloop = False will cause  the routine to be called only once vs. barcount times. In your case you only care about the latest bars so I can't imagine that it wouldn't perform significanly faster.

Jas0501, your statement makes perfect sense. It's logical, and I thought the same thing for a while.
Unfortunately, I can confirm 100% that when Autoloop is False the code is re-executed 3 or 4 times.
If you want to try it, then direct the output results to the debug log, otherwise it's hard to detect it.
In the end Autoloop=False is slower.
I reported this issue at least 2 times, but so far it hasn't been fixed. I will report it again when Beta is out.
wwrightjuly4
Posted : Wednesday, January 27, 2010 3:10:56 PM
Gold Customer Gold Customer

Joined: 4/10/2006
Posts: 954

Question:
    So the output is to the LOG file?  Can you output to any other file? i.e. fh = file.open( "fname", write)

I suppose you could have a cron job  that monitors the log file and emails you the alert or SMS.

Nice.

Interesting stuff,  Thanks.
Kuf
Posted : Wednesday, January 27, 2010 4:15:29 PM


Administration

Joined: 9/18/2004
Posts: 3,522
AutoLoop = false is faster. Always. It doesn't have to perform any interpolation.  The reason you get 3 to 4 executions of your code is becuase it might get asked to calculate more than once per symbol/timeframe change.   You might not see this in a non-autoloop code because it gets cancelled before it ever reaches your code.

Here's a simple test. Run this on a short list like the Nasdaq 100

Condition A:

System.threading.thread.sleep(10)
pass



Condition B:

    Sub New
        autoloop = False
    End Sub
    Public Overrides Sub CallUserCode()
        system.threading.thread.sleep(10)
        MyBase.addtoOutput(price.bar.datevalue(price.bar.count - 1), True)
  
end sub



Notice the difference in speed? Condition A pauses 10 miliseconds on every data point, while condition B only pauses once per symbol.

Bottom line, you set autoloop to false and your code will run much faster than using autoloop.

Ken Gilb (Kuf)
Chief Software Engineer - Worden Brothers Inc.
Try/Catch - My RealCode Blog
Flash99
Posted : Wednesday, January 27, 2010 4:32:16 PM
Platinum Customer Platinum Customer

Joined: 7/16/2009
Posts: 411
QUOTE (wwrightjuly4)

Question:
    So the output is to the LOG file?  Can you output to any other file? i.e. fh = file.open( "fname", write)

You may use a message box to popup an alert. I don't like it because I end up clicking OK button all day long. Cannot output to another file, IO is not yet allowed in SF5, but it will soon.

QUOTE (Kuf)

Bottom line, you set autoloop to false and your code will run much faster than using autoloop.

Thank you. Maybe this kind of information could be in the documentation - a "Best Practices" chapter.
jas0501
Posted : Wednesday, January 27, 2010 6:21:40 PM
Registered User
Joined: 12/31/2005
Posts: 2,499
QUOTE (Flash99)
[QUOTE=wwrightjuly4]
Question:
    So the output is to the LOG file?  Can you output to any other file? i.e. fh = file.open( "fname", write)

You may use a message box to popup an alert. I don't like it because I end up clicking OK button all day long. Cannot output to another file, IO is not yet allowed in SF5, but it will soon.

QUOTE (Kuf)

Bottom line, you set autoloop to false and your code will run much faster than using autoloop.

Thank you. Maybe this kind of information could be in the documentation - a "Best Practices" chapter.[/QUOTE]
It would be nice but few would benifit. That's about equivalent to providing the spark plug gap settings in a car owner's manual. Most user's just want put the thing in drive to press the gas pedal! 

Kuf
Posted : Thursday, January 28, 2010 6:20:18 PM


Administration

Joined: 9/18/2004
Posts: 3,522
I'll be writing either a white paper, or a book post release about Performance optimizing and speed tips and tricks for StockFinder.


Ken Gilb (Kuf)
Chief Software Engineer - Worden Brothers Inc.
Try/Catch - My RealCode Blog
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.