FOREACH variable vector

Repeats the sequence of commands between the FOREACH command and the corresponding END command once for each element in the vector. Each time through the loop, variable takes on the value of successive elements from the second argument, vector.

The vector may be a literal vector and it may have named constants as elements. So the following would be legal:

NAME jan feb mar apr may jun \
     jul aug sep oct nov dec
FOREACH month jan,dec
   . . .'some computation using month
END

You can also use the two or three-term sequence notation to control the FOREACH loop as shown here:

FOREACH n 1,10,0.1
   LOG10 n log10N
   SCORE n Number
   SCORE log10N NaturalLog
END
PRINT table number naturalLog

The above program segment will repeat the commands in the loop with n taking on the values from 1 through 10 in steps of 0.1. That is, the loop will be executed with n equal to 1, then to 1.1, then to 1.2, etc., until it reaches 10 (inclusive).

The three terms of the sequence notation may also be variable names as shown here:

FOREACH n low,high,step
...
END

And the sequence can be reversed to loop from high to low as shown here:

FOREACH n low,high,step
...
END

The step value must always be positive.

See also the BREAK, REPEAT, IF, UNTIL, and WHILE commands.


This program shows the effect of the FOREACH command:

COPY 1,10 Numbers
FOREACH number numbers
   PRODUCT 1,number factorial
   SCORE factorial Factorials
END
PRINT table numbers factorials

This produces:

Numbers       Factorials    	
1             1
2             2
3             6
4             24
5             120
6             720
7             5040
8             40320
9             362880
10            3.6288E06

Here's a more practical application using the FOREACH command. It is a Monte Carlo simulation of investment performance:

'Assume you are retiring and have 1 million dollars to 
'invest and that you are considering investing it in a 
'mutual fund that tracks the NASDAQ index. Assume further 
'that each year you will withdraw $80,000 from the fund for
'living expenses.
'Given the data for the historical annual changes in the NASDAQ 
'index, analyze it to estimate the range of balances  
'within 1 standard deviation of the mean if you invested
'as described.
'Also, calculate the probabilities of having a gain 
'and a loss after 30 years as well as the probability of 
'going broke sometime within the 30 years. Use variables
'for these numbers (1 million dollars, 30 years, $80,000) so
'you can change the assumptions easily to compare scenarios.
'For simplicity, ignore costs, dividends, and inflation.
'Data from:
' http://www.finfacts.com/Private/curency/nasdaqcompositeperformance.htm
'Annual fractional price change of Nasdaq 1930--2006:

DATA (0.1018 0.0173 -0.1733 0.0905 0.2214 \
0.2390 0.3313 -0.1099 0.0553 -0.0924 0.0702 \
0.2284 0.1045 0.0138 -0.0248 0.4553 0.1534 \
0.1135 -0.1850 0.4155 0.0693 -0.0147 0.3166 \
-0.1502 0.2044 0.2312 0.1715 -0.0455 0.2659 \
0.2577 -0.0236 -0.0984 0.2736 0.1718 -0.3106 \
-0.3511 0.2976 0.2610 0.0733 0.1231 0.2811 \
0.3388 -0.0321 0.1867 0.1987 -0.1122 0.3115 \
0.0753 -0.0526 0.1541 0.1926 -0.1780 0.5684 \
0.1545 0.1475 -0.0320 0.3992 0.2271 0.2164 \
0.3963 0.8559 -0.3929 -0.2105 -0.3153 0.5001 \
0.0859 0.0137 -0.0188) nasdaqData

DATA 30 numberOfYears
DATA 1000000 initialInvestment
DATA 80000 annualWithdrawal

NAME 10000 repeatCount
'Add 1 to the gains to get annual gain factors
ADD 1 nasdaqData nasdaqGainFactors
REPEAT repeatCount
   COPY initialInvestment balance
   SAMPLE numberOfYears nasdaqGainFactors sampleHistory
   FOREACH yearlyGain sampleHistory
      MULTIPLY balance yearlyGain balance
      SUBTRACT balance annualWithdrawal balance
      IF balance <= 0
         BREAK        'We're broke, so skip to next history
      END
   END
   SCORE balance FinalBalances
END
'Compute median and 1 std dev below median and 1 above:
PERCENTILE FinalBalances (15.87 50 84.13) oneStdevRangeOfBalances
COUNT FinalBalances <initialInvestment numberOfLosingPeriods
COUNT FinalBalances >initialInvestment numberOfGainingPeriods
COUNT FinalBalances <=0 numberOfBrokePeriods
DIVIDE numberOfLosingPeriods repeatCount probabilityOfLoss
DIVIDE numberOfGainingPeriods repeatCount probabilityOfGain
DIVIDE numberOfBrokePeriods repeatCount probabilityOfGoingBroke
PRINT " " initialInvestment numberOfYears annualWithdrawal
PRINT probabilityOfGain probabilityOfLoss probabilityOfGoingBroke
PRINT oneStdevRangeOfBalances%8.0F