FORALL (Optional)

The only construct not included in the XMIM language but which may be specified in a macro is the FORALL statement. The format is:

FORALL
    Conditions
ENDFOR

This statement simply loops over the values in the database. If the DEFINED OVER statement has also been specified in the macro, FORALL will loop over the defined period of time. If DEFINED OVER has not been specified, FORALL will loop back from the beginning of time to today.

Following are some example macros which demonstrate using different macro parameter types.

An example of a macro with the simplest possible form is:

COLUNM MACRO Range ( SECURITY Sec )
RETURN
    High of Sec - Low of Sec
ENDMACRO

The following examples have ATTR and PERIOD parameters and demonstrate defining a macro that simply calls a built-in and thus is very efficient yet can subsequently be used in places where the built-in would not be allowed (e.g., the MovingAvg macro could be used in a nested manner so as to take an average of an average).

ATTR MACRO MovingAvg ( ATTR Series, PERIOD TimePeriod )
RETURN
    TimePeriod average of Series
ENDMACRO  
ATTR MACRO Movement ( ATTR Series, PERIOD TimePeriod : FROM INCLUSIVE TO TODAY )
RETURN
    TimePeriod move of Series
ENDMACRO

Note that INCLUSIVE is used for the PERIOD argument such that if the macro was involved with TimePeriod being 3 days, then that would be taken to mean from 3 days ago to today, thus, actually spanning 4 days.

An OFFSET argument is used in the next example:

ATTR MACRO RateOfChange ( ATTR Series, OFFSET TimeOffset )
RETURN
    Series / Series TimeOffset
ENDMACRO 

A CONSTANT argument is used in the next example. Note that an attribute can be a constant thus the ATTR type subsumes the CONSTANT type.

ATTR MACRO Percentage ( ATTR Series, CONSTANT Percent)
RETURN
    Series * Percent / 100
ENDMACRO 

The following examples demonstrate four different ways to create the same macro.

Example 1:

ATTR MACRO Summation (ATTR Series)
VARS
    Total
INITIALIZE
    FORALL
        Total := Total + Series
    ENDFOR
RETURN
    Total
ENDMACRO

The macro above is incorrect because the Series can be undefined (i.e., no value).

Example 2:

ATTR MACRO Summation (ATTR Series, PERIOD TimePeriod)
DEFINED OVER TimePeriod
VARS
    Total
INITIALIZE
    FORALL
        Series is defined
    AND
        Total := Total + Series
    ENDFOR
RETURN
    Total
ENDMACRO 

Example 2 macro corrects the problem in Example 1.

The is defined as well as DEFINED OVER statements have been added, but will be very slow.

Example 3:

ATTR MACRO Summation (ATTR Series, PERIOD TimePeriod)
DEFINE
    ATTR MACRO Summation1 (ATTR Series)
        DEFINED OVER TimePeriod, ELSE 0.0
    RETURN
        if Series is defined
            then Series
            else 0
         endif + Summation1 ( Series ) 1 unit ago
    ENDMACRO
RETURN
    Summation1 (Series)
ENDMACRO 

The above macro is correct, but is rather confusing and will still be slow. This example, however, shows nested and recursive macros as well as DEFINED OVER for sub-macros. You cannot use recursion in the top level macro because each unit ago would create a new TimePeriod, hence, a new DEFINED OVER range. Therefore, the general rule is do not use time period arguments in the recursive part of a macro if using the DEFINED OVER statement.

Example 4:

ATTR MACRO Summation (ATTR Series, PERIOD TimePeriod)
RETURN
    TimePeriod Sum of Series
ENDMACRO

Example 4 is the best way to write this macro. It uses the built-in SUM to perform the required task and, thus, is fast and simple to understand.