Vision Tutorial 5: Using Dates and TimeSeries


Reminder!
To run these examples, you should first start a new session then load the sample database using:
  "/localvision/samples/general/sample.load" asFileContents evaluate ; 
Any other files referenced can be read from the /localvision/samples/general/ directory.

Note: The sample.load file runs by default on a Unix environment. If you are using a Windows NT platform, this location may be prefixed by a drive and optional path (e.g. d:/visiondb/localvision/samples/general/sample.load). Check with your Vision Administrator for further details.



Basic Access

Execute the following:

    Named Company GM sales
You will see:
    101781.00
When you ask for the value of an item that is tracked over time, by default you access the value that was most recently updated on or before the current date. Now type the following:
    Named Company GM :sales asOf: 19891231
You should see the value 102813.00 .

The : preceding the message sales indicates to Vision that you wish to access the entire time series for sales instead of the most recent value. This time series responds to the asOf: 19891231 message by accessing the value of the time series that was in effect as of December 31, 1989.

The parameter for the message asOf: must be a Date object or an Integer in one of the following forms:

    Form          Definition        Examples       Date
    YYYYMMDD FullDate 19871231 Dec. 31, 1987 19870430 Apr. 30, 1987 19870215 Feb. 15, 1987 YYMM Month-end 8712 Dec. 31, 1987 8704 Apr. 30, 1987 8702 Feb. 28, 1987 YY Year-end Date 87 Dec. 31, 1987 86 Dec. 31, 1986
The expressions:
    Named Company GM :sales asOf: 89 
    
    Named Company GM :sales asOf: 8912
and
    Named Company GM :sales asOf: 19891231
are all equivalent and return the value of GM's sales that was in effect as of December 31, 1989.

Pictorially, the sales time series for GM can be viewed as a time line of three values:

              sales time series structure
If you request data as of a date that is not in the time series, the value before that date will be returned. For example:
    Named Company GM :sales asOf: 19890630
returns the value 96371.63. Since no value is explicitly stored on June 30, 1989, the first value prior to this date is returned. In this case, the value is the value as of 12/31/1988, the first value to the left of the 6/89 in the time line. If your "as of" date is earlier than the first available date, the value NA will be returned. For example:
    Named Company GM :sales asOf: 87
returns the value NA, since there is no time point on or before this date. If your "as of" date is later than the last available date, the value of the last point in the time series is returned. For example:
    Named Company GM :sales asOf: 91
returns the 1990 value, the last value in the time series. The message displayAll can be sent to a time series to display all its points. For example:
    Named Company GM :sales displayAll ;
displays:
    12/31/1988      96371.63 
    12/31/1989     102813.00 
    12/31/1990     101781.00 

Creating And Updating Time Series Data

The message define: 'itemname' is used to create a new property that can be tracked over time. For example, suppose that each month you assign a valuation score for the companies you follow. To track this information in Vision, you would first need to define a new time series property for the the class Company. The expression:

    Company define: 'score' ;
defines a new property at Company that can be used to record scores for individual companies over time. To access a company's score, type:
    Named Company GM score
You should see the answer NA (not available). Since you have not yet assigned any scores for GM, this is the correct answer. To specify that GM's score on January 31, 1990 is 7, type:
    Named Company GM :score asOf: 19900131 put: 7
Remember that the : preceding the item name indicates to Vision that you wish to access the entire time series instead of the most recent value. TimeSeries objects respond to the message asOf:put: by storing the supplied value as of the supplied date. To confirm that the value was stored, type:
    Named Company GM :score asOf: 19900131
You should see:
    7
Now type:
    Named Company GM score
This expression also returns the value 7. Since the value stored for January 31, 1990 is the most recent relative to the current date, this is the value that is returned.

Update GM's score for February 28, 1990 as shown below:

    Named Company GM :score asOf: 900228 put: 9
Now type:
    Named Company GM score
You should see the value 9. Since February 28, 1990 represents the date closest to the current date, the value from this date is returned. The asOf:put message will modify an existing value if the date already exists. For Example:
    Named Company GM :score asOf: 900228 put: 10

To look at all the values that have been stored in your time series type the following:

    Named Company GM :score displayAll
You should see:
    1/31/1990         7
    2/28/1990        10
Now type the following:
    Named Company IBM :score displayAll
You should see no output. A time series responds to the displayAll by printing out all dates and values that have been assigned into the time series. The report is blank for IBM, since no data has been stored for IBM's score. A time series will respond to the message count by displaying the number of points that have been stored in the time series. The expression:
    Named Company GM :score count
produces the result:
    2
The expression:
    Named Company IBM :score count
produces the result:
    0
To determine the first date for which you have recorded information into your time series, the expression:
    Named Company GM :score firstDate
produces the result:
    1/31/1990
The expression:
    Named Company GM :score lastDate
produces the result:
    2/28/1990
The first date that you stored data for GM's score was January 31, 1990. Try accessing GM's score for a date prior to this. For example, type:
    Named Company GM :score asOf: 86
The value NA should be displayed in the Output Window since no value was in effect for this date.

When you store a value into a time series as of a specific date, the value is assumed to go into effect on that date. It remains in effect until a value is stored at a later date. Two messages are available to determine the interval over which a value is in effect. Type the following:

    Named Company GM :score effectiveDateAsOf: 19900215
You should see:
    1/31/1990
This indicates that the value you are retrieving for February 15, 1990 was really stored on January 31, 1990. Now type:
    Named Company GM :score nextDateAsOf: 19900215
You should see:
    2/28/1990
This indicates that the first update date after February 15 was February 28, 1990.

One additional TimeSeries message is useful to learn at this time. The delete: message is used to delete a value as of a specific date. For example, to delete GM's score for February 28, type:

    Named Company GM :score delete: 19900228
Try using the other messages described in this section to confirm that this point no longer exists in the time series.

The Default Date And Date Ranges

You have seen that you can explicitly access time series data as of any point in time by sending the asOf: message to the whole time series. Suppose you wanted to print the value for GM's sales and earnings per share as of December 31, 1989. Type the Vision statements:

    Named Company GM :sales asOf: 19891231 . print; 
    
    Named Company GM :earningsPerShare asOf: 19891231 . print;
producing the result:
    102813.00      4.11
As you can see, this code accesses the correct information; however, you have to specifically tell each time series to return the data as of the same date.

Vision provides a more compact way for performing this operation. Type the following:

    19891231 evaluate: 
    [ 
     Named Company GM sales print; 
     Named Company GM earningsPerShare print; 
    ]; 
This code produces the same results as the previous example. The evaluate: message will access all data as of the date supplied (in this case 19891231). This date becomes the default date used for all operations contained inside of the brackets. You can eliminate the duplicate references to GM using the do: message:
    19891231 evaluate: 
    [ 
     Named Company GM 
     do: [ sales print ; 
           earningsPerShare print ;
         ] ; 
    ] ;
This program also produces the same result. In other words, the use of the do: message does not change the evaluation date.

If you do not explicitly override it, Vision uses the current date as the default date. The message ^today can be used to specify the current date. For example, the expressions:

    Named Company GM sales print; 
    
    Named Company GM :sales asOf: ^today . print;
and
    ^today evaluate: 
    [ 
     Named Company GM sales print; 
    ]; 
are all equivalent and return the value of GM's sales that is in effect as of the current date.

The message ^date can be used to access the default date that is in effect. By default, the value of ^date is the current date (i.e., "^today"). For example:

    ^today print;
Displays the current date, as does the expression:
    ^date print;
Now type:
    89 evaluate: 
       [ 
        ^today printNL ; 
        ^date printNL ; 
       ]; 
Notice that the value for current date (^today) does not change, but the value for the default date (^date) reflects the override you supplied, in this case 12/31/89.

Many of the TimeSeries messages have variations designed to use the default date including:

General Message Default Date Equivalent
asOf: put: put:
effectiveDateAsOf: effectiveDate
nextDateAsOf: nextDate

Instead of supplying an explicit date as a parameter, the messages in the second column use the current value of ^date as the date.

For example, assume that you wanted to update the scores for several companies as of February 28, 1990. You could explicitly update this point for each company as shown below:

    Named Company IBM :score asOf: 19900228 put: 8; 
    Named Company XON :score asOf: 19900228 put: 3; 
    Named Company C :score asOf: 19900228 put: 6; 
Alternatively, you could use the following:
    19900228 evaluate: 
    [ 
     Named Company IBM :score put: 8; 
     Named Company XON :score put: 3; 
     Named Company C :score put: 6; 
    ] ; 
The put: message updates the time series by storing the value as of the default date, in this case February 28, 1990.

The <- message is used to change the value on or before the default date. For example, the expression:

    ^today evaluate: 
    [ Named Company IBM :score <- 9 ; 
    ] ; 
changes the value of IBM's most recent score. The following expressions are equivalent to this one:
    Named Company IBM :score asOf: ^today assign: 9 ; 
    
    Named Company IBM :score <- 9 ; 
These expressions all change the value for IBM's last score, relative to the current date, in this case the February 28, 1990 value.

It is often useful to perform analyses over a range of dates. For example, suppose you wanted to access GM's year-end sales value from 1988 through 1990. You can explicitly ask for each point as illustrated below:

    Named Company GM :sales asOf: 88 . printNL ; 
    Named Company GM :sales asOf: 89 . printNL ; 
    Named Company GM :sales asOf: 90 . printNL ; 
Vision provides a more compact way for performing this operation. Type the following:
    88 to: 90 by: 1 yearEnds . 
    evaluate: 
    [ 
     Named Company GM sales printNL ; 
    ]; 
The first part of this program creates a date range. Date ranges respond to the evaluate: [ ] message by executing the steps inside the square brackets, once for each point in the date range.

Three components are needed to construct a date range: the initial date, a final date, and an offset. In the preceding example, the initial date is 12/31/88, the final date is 12/31/90, and the offset is 1 yearEnds. Starting with the initial date, Vision increments the evaluation date by the offset provided (i.e., 1 yearEnds) until the final date is crossed.

Date ranges can be executed in reverse order as well. Try reversing the dates in the previous example, as shown below:

    90 to: 88 by: 1 yearEnds . 
    evaluate: 
    [ 
     Named Company GM sales printNL ; 
    ]; 
Since the initial date is later than the final date, Vision will decrement the evaluation date by the offset provided (i.e., 1 yearEnds) until the final date is crossed.

To print the date along with the sales, modify the previous example as shown below:

    90 to: 88 by: 1 yearEnds . 
    evaluate: 
    [ 
     ^date print ; 
     Named Company GM sales print: 10 ; 
     newLine print; 
    ]; 
You should see a report that contains a date and value on each line. To display the date, sales, and earnings per share on one line, modify the code as follows:
    90 to: 88 by: 1 yearEnds . 
    evaluate: 
    [ 
     Named Company GM 
     do: [ ^date print ; 
           sales print: 10 ; 
           earningsPerShare print ;
           newLine print ; 
         ] ; 
    ]; 
You should see the following report:
    12/31/1990       101781.00       5.03 
    12/31/1989       102813.00       4.11 
    12/31/1988        96371.63       6.14 
To display this same information with dates across the page instead of down the side, try the following:
    ### First create a variable representing the date range 
        !dr <- 88 to: 90 by: 1 yearEnds ; 
    
    ### Print just the dates across the page 
        dr evaluate: [ ^date print: -12 ] ; 
    
    ### New Line after row of dates has been printed 
        newLine print; 
    
    ### Print a row of sales values 
        dr evaluate: [ Named Company GM sales print: 12 ] ; 
        newLine print; 
    
    ### Now the eps values 
        dr evaluate: [ Named Company GM earningsPerShare print: 12 ] ; 
        newLine print; 
You should see:
    12/31/1988         12/31/1989           12/31/1990
      96371.63          102813.00           101781.00
          6.14               4.11                5.03
Three other messages are useful to know when working with dates. All dates respond to the messages year, month, and day. To fix the format on the previous example, modify the code to display just the year as shown below:
    !dr <- 88 to: 90 by: 1 yearEnds; 
    ### change this line to request ^date year 
    dr evaluate: [ ^date year print: 12 ] ; 
    newLine print;
    
    dr evaluate: [ Named Company GM sales print: 12 ] ; 
    newLine print; 
    
    dr evaluate: [ Named Company GM earningsPerShare print: 12 ]; 
    newLine print; 
You should see the following modified report:
        1988         1989           1990
    96371.63    102813.00      101781.00 
        6.14         4.11           5.03
If your date range includes a date that is earlier than the first available date, the value NA will be returned. For example:
    90 to: 87 by: 1 yearEnds . 
    evaluate: 
     [ 
      Named Company GM 
      do: [^date print ; 
            sales print: 10 ; 
            earningsPerShare print ;
            newLine print; 
          ] ; 
     ]; 
produces the result:
    12/31/1990     101781.00     5.03
    12/31/1989     102813.00     4.11
    12/31/1988      96371.63     6.14
    12/31/1987        NA         NA
Because no data has been stored prior to 1988, the value NA is displayed for both data items. If your date range includes a date that is not in the time series, the value on or before this date is returned. As a result, if you ask for data as of a date that is after the last available date, you will access the last data point. For example:
    91 to: 87 by: 1 yearEnds . 
    evaluate: 
     [ 
      Named Company GM 
      do: [ ^date print; 
            sales print: 10 ; 
            earningsPerShare print;
            newLine print; 
          ] ; 
     ]; 
produces the result:
    12/31/1991   101781.00   5.03
    12/31/1990   101781.00   5.03 
    12/31/1989   102813.00   4.11 
    12/31/1988    96371.63   6.14
    12/31/1987        NA       NA
Notice that the 1990 and 1991 values are identical. Since the 12/31/1990 value is the last point in the time series, it is the value that is returned as of 12/31/1991 as well.

Vision can be used with offsets other than years. The following offsets are valid:

    years           yearEnds           yearBeginnings 
    quarters        quarterEnds        quarterBeginnings 
    months          monthEnds          monthBeginnings
    days            businessDays
For example, try the following:
    8903 to: 9012 by: 1 quarterEnds . 
    evaluate: 
    [ 
     Named Company GM 
     do: [ ^date print: 10 ; 
           sales print: 10 ; 
           earningsPerShare print; 
           newLine print; 
         ] ; 
    ]; 
You should see:
    03/31/1989     96371.63      6.14
    06/30/1989     96371.63      6.14
    09/30/1989     96371.63      6.14
    12/31/1989    102813.00      4.11
    03/31/1990    102813.00      4.11
    06/30/1990    102813.00      4.11
    09/30/1990    102813.00      4.11
    12/31/1990    101781.00      5.03 
Although you have accessed the data on a quarterly basis, the actual information only changes at year-end. As a result, the values retrieved for March, June, and September represent the prior year-end values.

Now update the month-end scores for GM:

    Named Company GM 
    do: [ :score asOf: 9001 put: 7 ; 
          :score asOf: 9002 put: 10 ; 
          :score asOf: 9003 put: 9 ; 
          :score asOf: 9004 put: 7 ; 
          :score asOf: 9005 put: 7 ; 
          :score asOf: 9006 put: 8 ; 
          :score asOf: 9007 put: 9 ; 
          :score asOf: 9008 put: 6 ; 
          :score asOf: 9009 put: 8 ; 
          :score asOf: 9010 put: 9 ; 
          :score asOf: 9011 put: 9 ; 
          :score asOf: 9012 put: 9 ; 
        ] ; 
and execute:
    9003 to: 9012 by: 1 quarterEnds . 
    evaluate: 
    [ 
     ^date print: 10 ; 
     Named Company GM score printNL ; 
    ]; 
You should see
    3/31/1990       9 
    6/30/1990       8 
    9/30/1990       8 
    12/31/1990      9 
This example displays quarter-end scores for GM in 1990. You can access data of different frequencies in the same evaluate: program. As always, the value on or before the default date is accessed. For example, the expression:
    9002 to: 9012 by: 2 monthEnds . 
    evaluate: 
    [ 
     Named Company GM 
     do: [ ^date print: 12 ; 
           :sales effectiveDate print: 12 ; 
           sales print: 10 ; 
           score print ; 
           newLine print ; 
         ] ; 
    ] ; 
produces the result:
    02/28/1990  12/31/1989   102813.00  10 
    04/30/1990  12/31/1989   102813.00   7 
    06/30/1990  12/31/1989   102813.00   8
    08/31/1990  12/31/1989   102813.00   6
    10/31/1990  12/31/1989   102813.00   9
    12/31/1990  12/31/1990   101781.00   9
This program displays the bi-monthly sales and score for GM in 1990. The sales value for the first 5 dates all retrieve the value as of 12/31/89. Calculations involving data of different frequencies work in a similar fashion. For example, you could modify the previous program to display the sum of the score and the sales value:
    9002 to: 9012 by: 2 monthEnds . 
    evaluate: 
    [ 
     Named Company GM 
     do: [ ^date print: 12 ; 
           :sales effectiveDate print:12 ; 
           sales print: 10 ; 
           score print ; 
           sales + score print: 15 ;
           newLine print ; 
         ] ; 
    ] ; 
You should see:
    02/28/1990     12/31/1989     102813.00   10      102823.00 
    04/30/1990     12/31/1989     102813.00   7       102820.00 
    06/30/1990     12/31/1989     102813.00   8       102821.00 
    08/31/1990     12/31/1989     102813.00   6       102819.00 
    10/31/1990     12/31/1989     102813.00   9       102822.00 
    12/31/1990     12/31/1990     101781.00   9       101790.00 

Access Using Relative Dates

The examples in the previous section describe how to access data as of different points in time using explicit dates. It is often useful to be able to access data as of a date relative to some base date. Vision provides you with many tools for working with relative dates.

Suppose you wanted to access GM's sales as of last year-end. If the current date is January 15, 1993 you could type:

    Named Company GM :sales asOf: 92
If you wish to save this expression as a part of a program that you run each year, you would have to modify the program each time you use it, to reflect the correct date. Alternatively, you could specify the date you want to use relative to the current date as illustrated below:
    Named Company GM :sales asOf: ^today - 1 yearEnds
This expression determines the "as of" date by calculating the year-end date that occurred prior to the current date.

You can use any of the date offsets defined in the last section to compute new dates. For example (assuming today's date is May 15, 1987):

Expression Returns
^today 5/15/1987
^today - 1 days 5/14/1987
^today - 7 days 5/8/1987
^today + 7 days 5/22/1987
^today - 1 businessDays 5/14/1987
^today + 1 businessDays 5/18/1987
^today + 5 businessDays 5/22/1987
^today - 1 months 4/15/1987
^today + 1 months 6/15/1987
^today - 1 monthEnds 4/30/1987
^today + 1 monthEnds 6/30/1987
^today + 0 monthEnds 5/31/1987
^today - 1 monthBeginnings 4/1/1987
^today + 1 monthBeginnings 6/1/1987
^today + 0 monthBeginnings 5/1/1987
^today -1 quarters 2/15/1987
^today + 1 quarters 8/15/1987
^today - 1 quarterEnds 3/31/1987
^today + 1 quarterEnds 9/30/1987
^today + 0 quarterEnds 6/30/1987
^today - 1 quarterBeginnings 1/1/1987
^today + 1 quarterBeginnings 7/1/1987
^today + 0 quarterBeginnings 4/1/1987
^today -1 years 5/15/1986
^today + 1 years 5/15/1988
^today - 1 yearEnds 12/31/1986
^today + 1 yearEnds 12/31/1988
^today + 0 yearEnds 12/31/1987
^today - 1 yearBeginnings 1/1/1986
^today + 1 yearBeginnings 1/1/1988
^today + 0 yearBeginnings 1/1/1987
^today - 1 monthEnds + 3 days 5/3/1987 # third day of the month

Try experimenting with different date computations.

Date calculations need not be relative to the current date. For example, to compute the quarter-end date following May 28, 1987, type the following:

    19870528 asDate + 0 quarterEnds
Note that date offsets can only be added to and subtracted from dates. The asDate message is used to indicate that you wish to view the number 19870528 as a date, not an integer.

You can use a computed date any place you normally would use a date. For example, to access the last 5 years of GM's sales, you could use:

    ^today - 1 yearEnds to: ^today - 5 yearEnds by: 1 yearEnds .
    evaluate: 
    [ 
     ^date print: 12 ; 
     Named Company GM sales printNL ; 
    ] ; 
In this example, the initial and last dates in you date range are computed relative to the current date instead of explicitly stated.

You can also compute dates relative to the default date. For example, to print the dates 1, 3, 6, and 12 months after December 31, 1989, type the following:

    19891231 evaluate: 
    [ 
     ^date print: 12; 
     ^date + 1 monthEnds print: 12; 
     ^date + 3 monthEnds print: 12; 
     ^date + 6 monthEnds print: 12; 
     ^date + 12 monthEnds print: 12; 
    ]; 
The following example can be used to access GM's score as of May 31, 1990 as well as the scores 1 month prior and 3 months after this date:
    9005 evaluate: 
    [ 
     Named Company GM 
     do:[score print ;                                    # 5/31/90 
         :score asOf: ^date - 2 monthEnds . print ;       # 3/31/90 
         :score asOf: ^date + 1 quarterEnds . print ;       # 9/30/90 
        ] ; 
    ] ; 
producing the result:
    7       9      8

The lag: message can be used to automatically subtract the date offset from the default date. The lead: message can be used to automatically add the date offset to the default date. The program below produces identical results to the previous example:

    9005 evaluate: 
    [ 
     Named Company GM 
     do: [ score print ;                                   # 5/31/90 
           :score lag: 2 monthEnds . print ;               # 3/31/90 
           :score lead: 1 quarterEnds . print ;            # 9/30/90 
         ] ; 
    ] ; 
Suppose you wanted to compute the change in value between two points in time. For example, to find the difference between GM's score in May and June 1990 type:
    Named Company GM 
    do: [ (:score asOf: 9006) - (:score asOf: 9005) print: 10 ; 
        ] ; 
or
    9006 evaluate:  
     [ 
      Named Company GM 
      do: [ score - (:score lag: 1 monthEnds) print: 10 ; 
          ] ; 
     ] ; 
The message changeLag: provides a more streamlined way for requesting the same information. The expression:
    9006 evaluate: 
    [ 
     Named Company GM :score changeLag: 1 monthEnds . print:10 ; 
    ] ; 
produces the same result as the previous two versions. Likewise, the message pctChangeLag: can be used to compute the percent change in a value. The following two programs can both be used to find the 2-month score percent change relative to April 30, 1990:
    9004 evaluate: 
    [ 
     Named Company GM 
     do: [ 100 * (score / ( :score lag: 2 monthEnds) - 1) print:10 ; 
         ] ; 
    ] ; 
or
    9004 evaluate: 
    [ 
     Named Company GM :score pctChangeLag: 2 monthEnds . print:10;
    ] ; 
Time series and lists can be used together. For example, to find the companies in fullList (defined in Tutorial 4: Using Lists) that have grown by more than 15 percent between 1989 and 1990, you could use the program:
    90 evaluate: 
    [ fullList select: [ :sales pctChangeLag: 1 yearEnds . > 15 ] .
      do: [ ticker print: 10 ; 
            sales print: 10 ; 
            :sales lag: 1 yearEnds . print: 10 ; 
            newLine print ; 
          ] 
    ] ; 
producing the result:
    C       26276.51        22586.30
    CCI     27988.01        23496.00
    DEC      9389.44         7590.32
    DOW     13377.00        11113.00
    EK      13305.00        11550.00
    PEP     11485.20         9290.79
    WMT     11909.00         8451.46
This program selects all companies whose 1 year percent change in sales as of 1990 is more than 15% and displays the 1990 and prior year end sales for each company passing this screen. This program can be executed for a range of dates as well:
    89 to: 90 by: 1 yearEnds . evaluate: 
    [ "Sales Growth Report As Of: " print ; ^date year printNL; 
      fullList select: [ :sales pctChangeLag: 1 yearEnds . > 15 ] . 
      do: [ ticker print: 10 ; 
            sales print: 10 ; 
            :sales lag: 1 yearEnds . print: 10 ; 
            newLine print ; 
          ] 
    ] ; 
You should see:
    Sales Growth Report As Of:  1989 
    BA            16341.00      13636.00 
    F             62715.72      52774.31 
    GE            35211.01      28285.01 
    PEP            9290.79       8056.65 
    MO            20681.00      12149.00 
    WMT            8451.46       6400.85 
    Sales Growth Report As Of: 1990 
    C             26276.51      22586.30
    CCI           27988.01      23496.00 
    DEC            9389.44       7590.32
    DOW           13377.00      11113.00
    EK            13305.00      11550.00
    PEP           11485.20       9290.79
    WMT           11909.00       8451.46
This program displays the sales growth report for each date in the date range.

Additional Access Methods

The previous sections have described techniques for accessing and updating specific points in a time series. You may also wish to analyze and display information for each point in the time series. Several of the messages defined for the List class are applicable to the TimeSeries class as well.

The do: message can be used to perform one or more operations on an element in the time series. For example:

    Named Company GM :score 
    do: [ ^date print ; 
          printNL ; 
        ] ;
    
produces the result:
    1/31/1990      7 
    2/28/1990     10 
    3/31/1990      9 
    4/30/1990      7 
    5/31/1990      7 
    6/30/1990      8 
    7/31/1990      9 
    8/31/1990      6 
    9/30/1990      8 
    10/31/1990     9 
    11/30/1990     9 
    12/31/1990     9
    
This program displays the date and the value for each point in the time series. In fact, this is the implementation for the displayAll method. Inside the do: program, all messages are evaluated for the current point in the time series. The ^date message returns the date associated with the current point in the time series. The messages select:, extendBy:, rankUp:, rankDown:, runningTotal:, and send: are all defined to work for the class TimeSeries in the same manner as they are defined to work for the class List. For example, you could select the points in the score time series that are between May and July 1990 using:
    Named Company GM :score 
    select: [ ^date >= 9005 asDate && ^date <= 9007 asDate ] . 
    do: [ ^date print: 10 ; 
          printNL ; 
        ] ; 
producing the result:
    5/31/1990       7    
    6/30/1990       8 
    7/31/1990       9 
The various sort messages are also defined to work with time series; however, the returned object will be a list not a time series. It is sometimes useful to be able to convert a time series to a list object so that the other List class messages can be applied to it. The toList message performs this operation. For example, the expression:
    Named Company GM :sales toList
returns a list of 3 elements corresponding to the 3 year-end sales values.

The message extractForDateRange: returns a new time series that has a point for each point in the supplied date range based on the initial time series. For example, the expression:

    !extractTS <- Named Company GM :sales 
          extractForDateRange: (8903 to: 9012 by: 1 quarterEnds ) ; 
creates a time series with quarter-end points in it and saves this time series using the name extractTS. To display the values and associated dates you can use:
    extractTS displayAll
or
    extractTS do: [ ^date print ; printNL ] ;
producing the result:
    3/31/1989         96371.63
    6/30/1989         96371.63
    9/30/1989         96371.63
    12/31/1989       102813.00 
    3/31/1990        102813.00
    6/30/1990        102813.00
    9/30/1990        102813.00
    12/31/1990       101781.00 
Notice the following:

1. The extractTS contains 8 points. There is a value for each of the 8 points in the date range. These values are the values as of the quarter-end date.

2. You do not need to put the : in front of the extractTS message. This is because the extractForDateRange: message returns an object that is already a time series object.


Summary Statistics

Various messages are available to provide summary statistics about a time series. For example, type:

    Named Company GM :score average

The average of all scores that have been stored for GM will be displayed. To find the average score for a particular range of dates, type:

    Named Company GM :score 
      select: [ ^date >= 9004 asDate && ^date <= 9006 asDate ] . average 
or
    Named Company GM :score 
      extractForDateRange: ( 9004 to: 9006 by: 1 monthEnds ). average 
or
    Named Company GM :score 
      aveForDateRange: (9004 to: 9006 by: 1 monthEnds) 
Similar messages are defined for other statistics

One final variation is available for some of these messages. The messages average:, total:, min:, max:, median:, and stdDev: all require a single parameter that provides a program which can be evaluated for each element in the time series to compute the appropriate statistic. For example, to find the average of the log of each sales value, you could use:

    Named Company GM :sales average: [ log ]

Related Topics