This is the Personal Stock Monitor scripting developers forum.
Subscribe to RSS Feed
Developing Custom Stock Market Software using PSM -> Request for changed behavior in ticker object
Not logged in.
2010-12-01 17:33:57
1 of 7
#2618

When I request Historical data for a ticker, if the data does not exist locally, why doesn't PSM automatically download it for me and return it? Why does MY code need to check local history itself, download the data if it does not exist, and then read through the entire history file for the ticker to find the ONE date I need?

In other words, I would expect to write the following code to get a single historical price ...

HistoryStartDate = "7/20/10"
HistoryEndDate   = "7/20/10"
ticker.SetProperty "HistoryStart", HistoryStartDate
ticker.SetProperty "HistoryEnd",   HistoryEndDate

' The following Set should return ONE record if StartDate = EndDate, AND the
' date is a valid trading date (stock was available for trading, not a weekend
' and not a market holiday). If the dates are different, then multiple records
' would be returned.

Set HistoryRecs = ticker.HistoryData

If HistoryRecs.Count = 0 Then
   MsgBox "No History data for requested date.", vbOKOnly, "Test"
Else
   MsgBox "HistoryRecs.Count = " & HistoryRecs.Count, vbOKOnly, "Test"
'  Code to process the SINGLE Historical data record for the ONE date requested
'  ...
End If


HOWEVER, that doesn't work.

The code that seems to be REQUIRED is the following -- as MY code must first check to see if the data exists locally or not (ticker.HistoryData), and when it does not exist, my code must then download it (ticker.DownloadHistoryData HistoryStartDate, HistoryEndDate), re-Set ticker.HistoryData, and then loop through ALL of the local history data to locate the ONE date I want ...

HistoryStartDate = "7/20/10"
HistoryEndDate   = "7/20/10"
ticker.SetProperty "HistoryStart", HistoryStartDate
ticker.SetProperty "HistoryEnd",   HistoryEndDate

Set HistoryRecs = ticker.HistoryData

Continue = 1

If ( (HistoryRecs.Count > 0) And (HistoryRecs.Count < 3) ) Then
  ' (Can't use = 1 because it returns 2 when it should be 1)
  ' We got the record we need ...
    Continue     = 0  ' (False/No)
    HistoryRecNo = 0
    HistoryPrice = HistoryRecs.Item(HistoryRecNo).GetProperty("Close")
    MsgBox "On-file HistoryPrice: " & HistoryPrice, vbOKOnly, "Test"

ElseIf HistoryRecs.Count = 0 Then
  ' There are NO history records in this ticker, we need to download them ...
    MsgBox "Downloading history data...", vbOKOnly, "Test"
    On Error Resume Next
      ticker.DownloadHistoryData HistoryStartDate, HistoryEndDate
    On Error Goto 0

    Set HistoryRecs = ticker.HistoryData  ' Set this again since we just downloaded data
    MsgBox "HistoryRecs.Count: " & HistoryRecs.Count, vbOKOnly, "Test"

    ' Check the download results ...
      If Not ticker.HistoryData.Count > 0 Then
        ' History download failed ...
          MsgBox "Unable to download historical data for " _
                & ticker.GetProperty("Symbol") _
                & ". This ticker will be skipped!", vbOKOnly, "Test"
          Set HistoryRecs = Nothing
          HistoryPrice    = 0
          Continue        = 0  ' (False/No)
          rtnCode         = 1  ' (True/Yes there was an error)
      End If  ' History download failed
End If        ' (HistoryRecs.Count > 0) And (HistoryRecs.Count < 3)

If Continue = 1 Then
  ' We have history records to look through ...
    MsgBox "Do Loop - HistoryRecs.Count: " & HistoryRecs.Count, vbOKOnly, "Test"

  ' Loop through the history data looking for the ONE date we want ...
    i = 0
    Do Until HistoryRecs.Item(i).GetProperty("Date") = HistoryStartDate
      ' MsgBox "Date: " & HistoryRecs.Item(i).GetProperty("Date"), vbOKOnly, "Test"
      i = i + 1
      If i > HistoryRecs.Count Then
        MsgBox "A history record for Ticker " & ticker.GetProperty("Symbol") _
             & "  on Date " & HistoryStartDate _
             & " cannot be located in the History records." _
             & "  This Ticker will be skipped.", vbOKOnly, "Test"
        HistoryPrice = -99  ' (Set it to an invalid number for later checking)
        Continue     = 0    ' (False/No)
        Exit Do
      End If
    Loop

    If HistoryPrice => 0 Then
      HistoryRecNo  = i
      HistoryPrice  = HistoryRecs.Item(HistoryRecNo).GetProperty("Close")
      MsgBox "Do Loop HistoryPrice: " & HistoryPrice, vbOKOnly, "Test"
      rtnCode = 0  ' (False/No error)
    Else
      ' There is no history record for the date we want ...
        Set HistoryRecs = Nothing
        HistoryPrice    = 0
        rtnCode         = 1  ' (True/Yes there was an error)
    End If  ' HistoryPrice => 0

End If  ' We have history records to process (Continue = 1)

This just seems like a lot of code to simply get ONE historical price.

Thank you,

-Don

Posted by: dgoyette
2010-12-02 11:16:10
2 of 7
#2629
in reply to #2618
That behavior can not be changed right now. However the code to limit the data loaded should be working, as I mentioned in my other reply. So I'm not sure why it's not working for you, assuming the data is in the local database.
Posted by: Anatoly
2010-12-02 21:42:55
3 of 7
#2635
in reply to #2629
This request is for historical data that is NOT available locally. I wrote, "... if the data does not exist locally, why doesn't PSM automatically download it for me and return it?"

My code requires only ONE price from history that does not exist locally. There doesn't seem to be any way to get this ONE price, since HistoryData has to be re-loaded after calling DownloadHistoryData, thus returning the entire contents of this ticker's history file. If there IS a way to code what I need, please provide some example code.

I'm asking for PSM's built-in ticker.HistoryData to automatically call the DownloadHistoryData Method IF data needs to be downloaded. Instead of us users having to hard-code the entire download process in our scripts / extensions.
Posted by: dgoyette
2010-12-03 00:37:32
4 of 7
#2642
in reply to #2635
I understand what you're asking for, but since these are essentially wrapper functions encapsulate a lot of internal code that can not be changed at this point, the behavior can not be changed either. I'm sorry this causes inconvenience for you in this case, but that is the current design of the interface. We have to live with it too in our scripts.
Posted by: Anatoly
2010-12-03 02:27:51
5 of 7
#2650
in reply to #2642
So, you are saying the many, many lines of code I listed above is the only way to get history data that doesn't reside locally?

Is there a simpler object-oriented way of coding this? Remember, I'm an old-school procedural programmer (COBOL, BASIC) and new to this O-O model. I appreciate any suggestions you can provide, Anatoly.

I'm sorry to hear the existing code can't be modified or improved upon in any way.

My thought was that since the chart display function (right-click, Chart/History) already does an automatic history update if necessary, that it would be a simple case of adding a few lines of code to ticker.HistoryData in order to use the existing Chart/History update code.

Would you at least consider adding my request to a future enhancement list?

Thank you Anatoly.

-Don
Posted by: dgoyette
2010-12-03 07:48:39
6 of 7
#2657
in reply to #2650
Nope, it's not that simple. The chart code is in a separate plugin, and yes it has to look for gaps and request data as necessary.

You could certainly encapsulate the code to do what you want in a reusable function or class.
Posted by: Anatoly
2010-12-03 19:44:45
7 of 7
#2680
in reply to #2657
It never is "simple" to do things, is it (LOL)?

Yes, I already have the code in a separate function and will make into something that I can "simply" paste into any new extensions I write that need it.

Thank you Anatoly
Posted by: dgoyette