Moving Averages

Date: 198x
Type: Program
Platform(s): TS 2068

This program performs time-series analysis using the moving averages method, reading a dataset of 36 observations and a period length of 12 from DATA statements. It computes centred moving averages, automatically applying a second-pass averaging step when the period is even (to re-centre the result), then prints each period’s observation, smoothed value, and ratio in a tabular layout. The user can interactively change the base period, apply a second moving average to the already-smoothed series, or quit. Intermediate results are stored in arrays V() and U() of dimension N, with the smoothed series being fed back into V() for a second-pass calculation.


Program Analysis

Program Structure

The program is divided into clearly labelled sections indicated by REM statements and line-number ranges referenced in the opening documentation block (lines 2–9). Execution flows as follows:

  1. Documentation display (lines 2–9): Prints a variable glossary, pauses, then clears.
  2. Title display (lines 20–50): Clears the screen and prints a title banner.
  3. Data input (lines 70–130): READs N (number of periods) and P (window size) from DATA, then READs all observations into array V().
  4. Moving average calculation (lines 190–260): An outer loop over start positions and an inner summation loop compute raw moving averages into U().
  5. Even-period centring (lines 330–370): If P is even, a second pass averages adjacent U() values to produce a properly centred result.
  6. Results display (lines 380–430): Prints each period index, observation, smoothed value, and ratio in a fixed-column tabular layout.
  7. User menu (lines 450–540): Allows changing the base period, chaining a second moving average, or quitting.
  8. DATA (lines 600–650): 36 observations (12 per year, suggesting monthly data over three years), with a period of 12.

Moving Average Algorithm

The core calculation (lines 190–260) computes a simple P-point moving average. For each starting index I from 1 to M = N − P + 1, it sums V(I) through V(I+P−1) and divides by P, storing the truncated (not rounded) two-decimal result in U(I) via INT(100*(T/P))/100.

When P is even (tested at line 330 using the standard P <> 2*INT(P/2) odd/even idiom), the result would be offset by half a period. Lines 350–370 correct this by averaging each pair of consecutive U(K) values, reducing the usable count by one (hence M1 = M − 1). The ratio R at line 390 expresses each original observation as a proportion of its centred moving average, useful for identifying seasonal factors.

Interactive Chaining of Smoothing Passes

Option 2 (line 481) allows the user to apply a second moving average to the already-smoothed series. Lines 500–530 reassign N = M1, copy U(I) back into V(I), and zero out U(), before branching back to line 150. The counter C1 is incremented (line 490) and displayed in the heading at line 280, letting the user track which pass they are viewing. This reuse of existing arrays avoids any need to DIMension new storage.

Notable BASIC Idioms and Techniques

  • Truncation to two decimal places: INT(100*x)/100 is used throughout (lines 250, 360, 390) instead of rounding, which can introduce small systematic downward bias.
  • Odd/even test: P <> 2*INT(P/2) at line 330 is the canonical BASIC modulo-2 check, equivalent to P MOD 2 <> 0.
  • TAB-based column alignment: Lines 400–410 use TAB(2), TAB(5), TAB(16), and TAB(28) to align four columns without any string formatting routines.
  • DATA-driven input: All 36 observations and both parameters are supplied via DATA lines, making it straightforward to substitute a different dataset by editing only lines 600–650.
  • PAUSE 340 at line 20: Provides approximately a 17-second display of the variable glossary before auto-clearing — a common documentation technique.

Data Set

LineContent
600N = 36 (total observations)
610P = 12 (period window — monthly seasonality)
620–65036 floating-point values across three years

Bugs and Anomalies

  • Array reuse without re-DIM: When chaining a second pass (option 2), N is reduced to M1 but the arrays V() and U() retain their original size N. This is safe — the extra elements are simply ignored — but could produce confusing output if the user attempted a third or further pass with a large P, as M could become zero or negative.
  • Truncation vs. rounding: The use of INT truncates rather than rounds, so a value like 1.999 displays as 1.99 rather than 2.00. This is a minor accuracy concern for a statistical tool.
  • Option 1 (“change base period”) does not prompt for a new P: Branching to line 150 simply reruns the calculation with the same P and the same data. The REM at line 60 (“DATA INPUT”) is bypassed, so the only way to change P is to edit line 610 directly.

Content

Appears On

The foundation of Tony Willing's numbered library series — play Breakout, write documents in a 64-column word processor, morph a triangle into a square with flicker-free animation, or run a complete fig-FORTH system. Fifty programs covering every category.

Related Products

Related Articles

Related Content

Image Gallery

Moving Averages

Source Code

    2 REM "MOV AVGS"
    4 PRINT " VARIABLES:": PRINT : PRINT 
    5 PRINT "N  NUMBER OF PERIODS OBSERVED      -Line 600"
    6 PRINT "P  RANGE OF PERIODS FOR THE MOVING AVERAGES-  Line 610"
    7 PRINT "R  RATIO OF AVERAGE TO ORIGINAL    OBSERVATION"
    8 PRINT "V(I)  OBSERVATION FOR   PERIOD I   -Line 620 to end"
    9 PRINT "U(I) MOVING AVERAGE FOR PERIOD I"
   10 REM 
   20 PAUSE 340: CLS : PRINT : PRINT 
   30 PRINT "TIME-SERIES ANALYSIS"
   40 PRINT "BY MOVING AVERAGES"
   50 PRINT "-------------------------------"
   60 REM DATA INPUT
   70 READ N,P
   80 DIM V(N): DIM U(N)
  100 FOR I=1 TO N
  120 READ V(I)
  130 NEXT I
  140 LET C1=1
  150 PRINT 
  160 PRINT "MOVING AVERAGE CALCULATION"
  180 REM   CALCULATION OF AVERAGES
  190 LET M=N-P+1
  200 FOR I=1 TO M
  210 LET T=0
  220 FOR J=1 TO P
  230 LET T=T+V(I+J-1)
  240 NEXT J
  250 LET U(I)=INT (100*(T/P))/100
  260 NEXT I
  270 PRINT : PRINT 
  280 PRINT "CALCULATION #";C1;" BASED ON          ";P; "   PERIODS"
  290 PRINT "-------------------------------"
  300 PRINT "PER  OBSERM  SMOOTHED VALUE  RATIO"
  310 PRINT "-------------------------------"
  320 LET M1=M
  330 IF P<>2*INT (P/2) THEN GO TO 380
  340 LET M1=M-1
  350 FOR K=1 TO M1
  360 LET U(K)=INT (100*(U(K)+U(K+1))/2)/100
  370 NEXT K
  380 FOR K=1 TO M1
  390 LET R=INT (100*(V(K+INT (P/2))/U(K)))/100
  400 PRINT TAB ( 2);K+INT (P/2);TAB ( 5);V(K+INT (P/2));
  410 PRINT TAB ( 16);U(K);TAB ( 28);R
  420 NEXT K
  430 PRINT "-------------------------------"
  440 PRINT : PRINT : PRINT 
  450 PRINT "CHANGE THE BASE PERIOD===> TYPE <1>"
  460 PRINT "CALCULATE A SECOND"
  465 PRINT "   MOVING AVERAGE    ==> TYPE <2>"
  467 PRINT 
  470 INPUT "QUIT                 ===> TYPE <3>  ? ";C
  480 IF C=1 THEN GO TO 150
  481 IF C=2 THEN GO TO 490
  482 IF C=3 THEN GO TO 550
  490 LET C1=C1+1
  500 LET N=M1
  510 FOR I=1 TO N
  520 LET V(I)=U(I): LET U(I)=0
  530 NEXT I
  540 GO TO 150
  550 STOP 
  600 DATA 36
  610 DATA 12
  620 DATA 144.02,125.17,142.15,153.08,152.27,131.12,139.43,136.73,136.94,151.28
  630 DATA 172.20,187.55,141.48,178.47,127.19,142.19,148.43,149.43,141.18,135.64
  640 DATA 144.69,171.95,153.60,188.92,128.93,137.30,159.05,154.75,138.11,140.96
  650 DATA 126.49,152.18,149.19,137.01,191.35,187.35

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

People

No people associated with this content.

Scroll to Top