Welcome Guest, please sign in to participate in a discussion. | Search | Active Topics | |
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
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
|
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.
|
|
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!
|
|
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
|
|
Guest-1 |