Articles

Free Download More Info
Here are some articles about developing for Personal Stock Streamer.

You can rss.gif subscribe to this feed with an RSS reader.
  • How to Create a Custom Chart Indicator
    05/02/2005 9:25AM
    This article is a brief description of the implementation of a price relative indicator.  The price relative indicator  compares the price of one security to another, and is often used to compare the performance of a particular stock to a market index such as the S&P 500.  The indicator is drawn on a separate set of axes from the main chart, and the calculation is Price[Ticker]/Price[S&P 500].

    As with any typical chart extension, we will define a handler class to create the chart objects and to recalculate the indicator as necessary.  In particular, an indicator class only requires two functions: Create to create the objects that make up the chart and hook them up to the chart manager, and Recalc to actually calculate the indicator.  However there are a couple tricky parts to this particular indicator:

    • Because this indicator is relative to the price of a second ticker symbol, we first need to make sure the second ticker actually exists in our portfolio, because Personal Stock Streamer will only retrieve historical data for a ticker that is part of a portfolio.  So if the ticker is not present in the current portfolio we need to create an invisible ticker and add it to the portfolio.  Also, if an invisible ticker is created we need to make sure to delete it when the chart is closed.
    • We need to make sure that the secondary ticker has enough historical data to do our calculations, or we need to request that it be retrieved from the data source.  One thing to note here is that normally we would have to set up an OnHistoryUpdated event handler so that our object is notified when the historical data arrives, but for chart indicators we do not need to do that because the chart window already catches that event and automatically calls our Recalc function.

    I'm not going to go through the chart setup because it is relatively straightforward; the setup code is well-commented, so you can read it to see how the various components of the chart are created and hooked up.

    As for the tricky parts, here is the first part of the Recalc function:

    Set AltTicker = Doc.FindTicker(Nothing,
    ChartObject.GetParam(0), 0) ' check if the ticker exists in
    the document If AltTicker
    Is Nothing Then '

    if ticker was not found, create
    temporary ticker Set AltTicker = Doc.CreateTicker Set Portfolio = Doc.CurrentPortfolio If Not AltTicker Is Nothing Then

    AltTicker.SetProp "Symbol", ChartObject.GetParam(0)
    AltTicker.SetProp "Visible", "0"

    Portfolio.Insert -1, AltTicker

    ' set the label on this chart
    MyDataSet.Label = MyDataSet.ID + " (" + ChartObject.GetParam(0) + ") "

    ' make sure this ticker gets deleted when the chart is closed
    ChartObject.DeferDeleteTicker(AltTicker)
    End If
    End If

    What we're doing in the code above is finding the relative ticker (such as the S&P 500) in the document, which is passed as the first parameter in the chart object.  (Programmers start counting at 0, so the first parameter is actually at the 0th location.)  This part of the code handles the case where the ticker does not exist in the docuemnt, so it creates the ticker object, sets the Symbol and Visible properties, and inserts it into the current portfolio.  Because the ticker is invisible it doesn't really matter where you insert it as long as you clean up after yourself, which is what the call to DeferDeleteTicker() does.

    The next part of the code should be pretty straightforward. It gets the data set from the relative ticker or requests it from the application if necessary:

    If Not AltTicker Is Nothing Then
    Set AltCloseDataSet = ChartObject.GetDataSetFromTicker(AltTicker, "Close")

    ...

    ' check for a valid data set
    If AltCloseDataSet Is Nothing Then

    ' if there was no data set, set a dummy value so it will at least display the chart
    MyDataSet.Data(MyDataSet.Size - 1) = 0
    MyDataSet.Label = MyDataSet.ID + " (" + ChartObject.GetParam(0) + ") "

    ' request historical data from the application
    ChartObject.RequestHistoricalDataForTicker(AltTicker)

    Once we have the data for the relative ticker, the next part of the code actually calculates the relative indicator:

    	Else
    ' loop through all of the data and calculate the Price Relative indicator
    For x = 0 To CloseDataSet.Size - 1
    If (CloseDataSet.IsValidData(x) And CloseDataSet.Data(x) > 0) Then
    LastValidCloseData = x

    If (AltCloseDataSet.IsValidData(x) And AltCloseDataSet.Data(x) > 0) Then
    LastValidAltCloseData = x

    MyDataSet.Data(x) = CloseDataSet.Data(x) / AltCloseDataSet.Data(x)
    End If
    End If
    Next

    ...

    ' check data at the end of the range
    If LastValidAltCloseData < LastValidCloseData - 2 Then
    ChartObject.RequestHistoricalDataForTicker(AltTicker)
    End If
    End If
    End If

    Note how we're keeping track of the last valid data for the relative ticker in the LastValidAltCloseData variable. What this allows us to do is to check if perhaps there is some data at the end of our range that is missing for the relative ticker and tries to request it. This handles the case where data for that ticker may not be updated for whatever reason.

    Other than registering our indicator with the system, that's pretty much it.  As we do more of these types of extensions, you will notice that there really isn't that much work involved, and a lot can be accomplished with just a few dozen lines of code.

    The full code for this extension is here, and the complete packaged extension is available for download through the Extension manager under the Tools menu.