Case Study 2: Social Security Benefits Calculation

Background

The Social Security Administration (SSA) maintains one of the largest and most consequential COBOL systems in the world. The agency processes benefit calculations for over 70 million Americans receiving retirement, disability, and survivor benefits, disbursing more than $1.4 trillion annually. The core benefit computation engine, running on IBM z/OS mainframes, determines the exact monthly payment for every beneficiary based on their lifetime earnings history.

The Social Security benefit calculation is one of the most complex financial computations performed by any government system. It involves indexing decades of historical earnings to account for wage growth, selecting the highest-earning years, computing a weighted average, and applying a progressive formula with "bend points" that change annually. The calculation must then be adjusted for the age at which the worker begins receiving benefits, with reductions for early retirement and credits for delayed retirement.

This case study implements a complete Social Security retirement benefit calculator in COBOL, covering the computation of Average Indexed Monthly Earnings (AIME), the Primary Insurance Amount (PIA) using bend points, and early/late retirement adjustment factors. The program demonstrates how COBOL's packed-decimal arithmetic handles the precise, rule-driven calculations that determine benefits for millions of Americans.

Business Requirements

The Social Security benefit calculator must implement the following:

  1. Earnings indexing: Adjust each year's earnings by a wage index factor to express past earnings in terms of current wage levels. Earnings are indexed to the worker's age 60, using the national average wage index.

  2. AIME calculation: Select the highest 35 years of indexed earnings, sum them, and divide by 420 (35 years * 12 months) to produce the Average Indexed Monthly Earnings. Drop fractions from the result.

  3. PIA calculation: Apply the PIA formula using two "bend points" that create a progressive benefit structure: - 90% of the first bend point amount of AIME - 32% of AIME between the first and second bend points - 15% of AIME above the second bend point

The PIA is rounded down to the next lower dime (10 cents).

  1. Early retirement reduction: For workers claiming before their Full Retirement Age (FRA), reduce the PIA by 5/9 of 1% per month for the first 36 months early, and 5/12 of 1% per month for each additional month beyond 36.

  2. Delayed retirement credits: For workers claiming after their FRA, increase the PIA by 2/3 of 1% per month (8% per year) for each month of delay, up to age 70.

The Social Security Benefit Formula

The Social Security benefit formula was designed to be progressive: workers with lower lifetime earnings receive a higher percentage of their earnings as benefits than higher-earning workers. This is accomplished through the bend point structure of the PIA formula.

For a worker turning 62 in 2024, the bend points are: - First bend point: $1,174 - Second bend point: $7,078

These bend points are adjusted annually based on changes in the national average wage index. The formula applies three different replacement rates to three segments of the AIME:

  • 90% of the first $1,174 of AIME = maximum $1,056.60 from this segment
  • 32% of AIME between $1,174 and $7,078 = maximum $1,889.28 from this segment
  • 15% of AIME above $7,078

The sum of these three components is the PIA, which represents the monthly benefit at Full Retirement Age.

Complete COBOL Program

       IDENTIFICATION DIVISION.
       PROGRAM-ID.  SSABENCALC.
       AUTHOR.      SSA BENEFIT SYSTEMS.
       DATE-WRITTEN. 2024-09-01.
      *================================================================*
      * PROGRAM: SSABENCALC - SOCIAL SECURITY BENEFIT CALCULATOR       *
      *                                                                *
      * PURPOSE: Calculate Social Security retirement benefits using   *
      *          the AIME/PIA formula with bend points and             *
      *          early/late retirement adjustments.                    *
      *                                                                *
      * PROCESSING:                                                    *
      *   1. Read worker earnings history                              *
      *   2. Index earnings to age-60 wage levels                      *
      *   3. Select highest 35 years of indexed earnings               *
      *   4. Calculate AIME (Average Indexed Monthly Earnings)         *
      *   5. Calculate PIA (Primary Insurance Amount)                  *
      *   6. Apply early/late retirement adjustment                    *
      *   7. Produce benefit computation report                        *
      *                                                                *
      * INPUT:  EARNHIST - Worker earnings history file                *
      * OUTPUT: BENCALC  - Benefit computation report                  *
      *================================================================*

       ENVIRONMENT DIVISION.
       CONFIGURATION SECTION.
       REPOSITORY.
           FUNCTION ALL INTRINSIC.

       INPUT-OUTPUT SECTION.
       FILE-CONTROL.
           SELECT EARNINGS-HISTORY
               ASSIGN TO EARNHIST
               ORGANIZATION IS LINE SEQUENTIAL
               FILE STATUS IS WS-EARN-STATUS.

           SELECT BENEFIT-REPORT
               ASSIGN TO BENCALC
               ORGANIZATION IS LINE SEQUENTIAL
               FILE STATUS IS WS-RPT-STATUS.

       DATA DIVISION.
       FILE SECTION.

       FD  EARNINGS-HISTORY
           RECORDING MODE IS F
           RECORD CONTAINS 80 CHARACTERS.
       01  EARNINGS-INPUT-REC.
           05  EI-SSN                 PIC X(09).
           05  EI-WORKER-NAME        PIC X(25).
           05  EI-BIRTH-YEAR         PIC 9(04).
           05  EI-CLAIM-AGE          PIC 9(02).
           05  EI-FRA-AGE-YEARS      PIC 9(02).
           05  EI-FRA-AGE-MONTHS     PIC 9(02).
           05  EI-RECORD-TYPE        PIC X(01).
               88  EI-HEADER-REC     VALUE 'H'.
               88  EI-EARNINGS-REC   VALUE 'E'.
               88  EI-TRAILER-REC    VALUE 'T'.
           05  EI-EARN-YEAR          PIC 9(04).
           05  EI-ACTUAL-EARNINGS    PIC 9(07)V99.
           05  EI-WAGE-INDEX         PIC 9(03)V9(06).
           05  EI-SS-MAX-EARNINGS    PIC 9(07)V99.
           05  FILLER                PIC X(08).

       FD  BENEFIT-REPORT
           RECORDING MODE IS F
           RECORD CONTAINS 132 CHARACTERS.
       01  REPORT-LINE                PIC X(132).

       WORKING-STORAGE SECTION.

      *----------------------------------------------------------------*
      * FILE STATUS                                                    *
      *----------------------------------------------------------------*
       01  WS-FILE-STATUS.
           05  WS-EARN-STATUS         PIC X(02).
           05  WS-RPT-STATUS          PIC X(02).

       01  WS-FLAGS.
           05  WS-EOF-FLAG            PIC X(01) VALUE 'N'.
               88  END-OF-FILE        VALUE 'Y'.
               88  NOT-END-OF-FILE    VALUE 'N'.
           05  WS-PROCESSING          PIC X(01) VALUE 'N'.
               88  PROCESSING-WORKER  VALUE 'Y'.
               88  NOT-PROCESSING     VALUE 'N'.

      *----------------------------------------------------------------*
      * WORKER IDENTIFICATION                                          *
      *----------------------------------------------------------------*
       01  WS-WORKER-INFO.
           05  WS-SSN                 PIC X(09).
           05  WS-WORKER-NAME         PIC X(25).
           05  WS-BIRTH-YEAR          PIC 9(04).
           05  WS-CLAIM-AGE           PIC 9(02).
           05  WS-FRA-AGE-YEARS       PIC 9(02).
           05  WS-FRA-AGE-MONTHS      PIC 9(02).

      *----------------------------------------------------------------*
      * EARNINGS HISTORY TABLE                                         *
      * Stores up to 50 years of earnings records                      *
      *----------------------------------------------------------------*
       01  WS-EARNINGS-TABLE.
           05  WS-EARN-COUNT          PIC 9(02) VALUE ZEROS.
           05  WS-EARN-ENTRY OCCURS 50 TIMES.
               10  WS-ET-YEAR         PIC 9(04).
               10  WS-ET-ACTUAL       PIC S9(07)V99 COMP-3.
               10  WS-ET-CAPPED       PIC S9(07)V99 COMP-3.
               10  WS-ET-WAGE-INDEX   PIC S9(03)V9(06) COMP-3.
               10  WS-ET-INDEXED      PIC S9(09)V99 COMP-3.
               10  WS-ET-SS-MAX       PIC S9(07)V99 COMP-3.
               10  WS-ET-SELECTED     PIC X(01).
                   88  ET-SELECTED    VALUE 'Y'.
                   88  ET-NOT-SELECTED VALUE 'N'.

      *----------------------------------------------------------------*
      * INDEXING CALCULATION FIELDS                                    *
      *----------------------------------------------------------------*
       01  WS-INDEX-FIELDS.
           05  WS-AGE60-YEAR          PIC 9(04).
           05  WS-AGE60-WAGE-INDEX    PIC S9(03)V9(06) COMP-3.
           05  WS-INDEX-FACTOR        PIC S9(05)V9(08) COMP-3.
           05  WS-IDX-COUNTER         PIC 9(02).

      *----------------------------------------------------------------*
      * AIME CALCULATION FIELDS                                        *
      *----------------------------------------------------------------*
       01  WS-AIME-FIELDS.
           05  WS-TOP35-TOTAL         PIC S9(11)V99 COMP-3
                                      VALUE ZEROS.
           05  WS-AIME                PIC S9(07)    COMP-3.
           05  WS-YEARS-SELECTED      PIC 9(02)     VALUE ZEROS.
           05  WS-COMPUTATION-YEARS   PIC 9(02)     VALUE 35.

      *----------------------------------------------------------------*
      * PIA CALCULATION FIELDS                                         *
      *----------------------------------------------------------------*
       01  WS-PIA-FIELDS.
           05  WS-BEND-POINT-1        PIC S9(05)    COMP-3
                                      VALUE 1174.
           05  WS-BEND-POINT-2        PIC S9(05)    COMP-3
                                      VALUE 7078.
           05  WS-PIA-SEGMENT-1       PIC S9(07)V99 COMP-3.
           05  WS-PIA-SEGMENT-2       PIC S9(07)V99 COMP-3.
           05  WS-PIA-SEGMENT-3       PIC S9(07)V99 COMP-3.
           05  WS-PIA-RAW             PIC S9(07)V99 COMP-3.
           05  WS-PIA-ROUNDED         PIC S9(07)V9  COMP-3.
           05  WS-PIA-FINAL           PIC S9(07)V99 COMP-3.

      *----------------------------------------------------------------*
      * RETIREMENT ADJUSTMENT FIELDS                                   *
      *----------------------------------------------------------------*
       01  WS-RETIRE-FIELDS.
           05  WS-FRA-TOTAL-MONTHS    PIC S9(04) COMP-3.
           05  WS-CLAIM-TOTAL-MONTHS  PIC S9(04) COMP-3.
           05  WS-MONTHS-DIFF         PIC S9(04) COMP-3.
           05  WS-MONTHS-EARLY        PIC S9(04) COMP-3.
           05  WS-MONTHS-LATE         PIC S9(04) COMP-3.
           05  WS-EARLY-REDUCTION     PIC S9V9(06) COMP-3.
           05  WS-EARLY-FIRST-36      PIC S9(04) COMP-3.
           05  WS-EARLY-OVER-36       PIC S9(04) COMP-3.
           05  WS-LATE-CREDIT         PIC S9V9(06) COMP-3.
           05  WS-ADJUSTED-BENEFIT    PIC S9(07)V99 COMP-3.
           05  WS-ADJUSTMENT-DESC     PIC X(30).

      *----------------------------------------------------------------*
      * SORTING FIELDS FOR TOP-35 SELECTION                            *
      *----------------------------------------------------------------*
       01  WS-SORT-FIELDS.
           05  WS-SORT-IDX-1          PIC 9(02).
           05  WS-SORT-IDX-2          PIC 9(02).
           05  WS-SORT-TEMP-EARN      PIC S9(09)V99 COMP-3.
           05  WS-SORT-TEMP-YEAR      PIC 9(04).
           05  WS-SORT-TEMP-INDEX     PIC S9(03)V9(06) COMP-3.
           05  WS-SORT-TEMP-ACTUAL    PIC S9(07)V99 COMP-3.
           05  WS-SORT-TEMP-CAPPED    PIC S9(07)V99 COMP-3.
           05  WS-SORT-TEMP-MAX       PIC S9(07)V99 COMP-3.
           05  WS-SORT-TEMP-SEL       PIC X(01).

      *----------------------------------------------------------------*
      * COUNTERS                                                       *
      *----------------------------------------------------------------*
       01  WS-WORKERS-PROCESSED       PIC 9(05) VALUE ZEROS.

      *----------------------------------------------------------------*
      * REPORT LINES                                                   *
      *----------------------------------------------------------------*
       01  WS-RPT-TITLE.
           05  FILLER                 PIC X(01) VALUE SPACE.
           05  FILLER                 PIC X(80)
               VALUE 'SOCIAL SECURITY ADMINISTRATION - '
                     'RETIREMENT BENEFIT COMPUTATION'.
           05  FILLER                 PIC X(51) VALUE SPACES.

       01  WS-RPT-SEPARATOR.
           05  FILLER                 PIC X(132) VALUE ALL '='.

       01  WS-RPT-WORKER-HDR.
           05  FILLER                 PIC X(01) VALUE SPACE.
           05  FILLER                 PIC X(06) VALUE 'SSN: '.
           05  WWH-SSN               PIC X(09).
           05  FILLER                 PIC X(05) VALUE SPACES.
           05  FILLER                 PIC X(07) VALUE 'NAME: '.
           05  WWH-NAME              PIC X(25).
           05  FILLER                 PIC X(05) VALUE SPACES.
           05  FILLER                 PIC X(13) VALUE 'BIRTH YEAR: '.
           05  WWH-BIRTH-YEAR        PIC 9(04).
           05  FILLER                 PIC X(05) VALUE SPACES.
           05  FILLER                 PIC X(12) VALUE 'CLAIM AGE: '.
           05  WWH-CLAIM-AGE         PIC Z9.
           05  FILLER                 PIC X(38) VALUE SPACES.

       01  WS-RPT-FRA-LINE.
           05  FILLER                 PIC X(01) VALUE SPACE.
           05  FILLER                 PIC X(28)
               VALUE 'FULL RETIREMENT AGE (FRA): '.
           05  WFRA-YEARS            PIC Z9.
           05  FILLER                 PIC X(17)
               VALUE ' YEARS AND      '.
           05  WFRA-MONTHS           PIC Z9.
           05  FILLER                 PIC X(07) VALUE ' MONTHS'.
           05  FILLER                 PIC X(71) VALUE SPACES.

       01  WS-RPT-BLANK              PIC X(132) VALUE SPACES.

       01  WS-RPT-EARN-HDR.
           05  FILLER                 PIC X(01) VALUE SPACE.
           05  FILLER                 PIC X(06) VALUE 'YEAR  '.
           05  FILLER                 PIC X(18)
               VALUE '  ACTUAL EARNINGS '.
           05  FILLER                 PIC X(18)
               VALUE '  CAPPED EARNINGS '.
           05  FILLER                 PIC X(14)
               VALUE '  WAGE INDEX  '.
           05  FILLER                 PIC X(14)
               VALUE ' INDEX FACTOR '.
           05  FILLER                 PIC X(18)
               VALUE ' INDEXED EARNINGS '.
           05  FILLER                 PIC X(10)
               VALUE ' SELECTED '.
           05  FILLER                 PIC X(33) VALUE SPACES.

       01  WS-RPT-EARN-DASH.
           05  FILLER                 PIC X(01) VALUE SPACE.
           05  FILLER                 PIC X(06) VALUE '------'.
           05  FILLER                 PIC X(18) VALUE ALL '-'.
           05  FILLER                 PIC X(18) VALUE ALL '-'.
           05  FILLER                 PIC X(14) VALUE ALL '-'.
           05  FILLER                 PIC X(14) VALUE ALL '-'.
           05  FILLER                 PIC X(18) VALUE ALL '-'.
           05  FILLER                 PIC X(10) VALUE ALL '-'.
           05  FILLER                 PIC X(33) VALUE SPACES.

       01  WS-RPT-EARN-LINE.
           05  FILLER                 PIC X(01) VALUE SPACE.
           05  WEL-YEAR              PIC 9(04).
           05  FILLER                 PIC X(02) VALUE SPACES.
           05  WEL-ACTUAL            PIC $ZZZ,ZZ9.99.
           05  FILLER                 PIC X(02) VALUE SPACES.
           05  WEL-CAPPED            PIC $ZZZ,ZZ9.99.
           05  FILLER                 PIC X(02) VALUE SPACES.
           05  WEL-WAGE-IDX          PIC ZZ9.999999.
           05  FILLER                 PIC X(02) VALUE SPACES.
           05  WEL-IDX-FACTOR        PIC Z9.999999.
           05  FILLER                 PIC X(02) VALUE SPACES.
           05  WEL-INDEXED           PIC $Z,ZZZ,ZZ9.99.
           05  FILLER                 PIC X(02) VALUE SPACES.
           05  WEL-SELECTED          PIC X(03).
           05  FILLER                 PIC X(36) VALUE SPACES.

       01  WS-RPT-AIME-LINE.
           05  FILLER                 PIC X(01) VALUE SPACE.
           05  FILLER                 PIC X(45)
               VALUE 'AVERAGE INDEXED MONTHLY EARNINGS (AIME): $'.
           05  WAIME-AMOUNT          PIC ZZZ,ZZ9.
           05  FILLER                 PIC X(79) VALUE SPACES.

       01  WS-RPT-PIA-HDR.
           05  FILLER                 PIC X(01) VALUE SPACE.
           05  FILLER                 PIC X(50)
               VALUE 'PRIMARY INSURANCE AMOUNT (PIA) CALCULATION:'.
           05  FILLER                 PIC X(81) VALUE SPACES.

       01  WS-RPT-PIA-SEGMENT.
           05  FILLER                 PIC X(01) VALUE SPACE.
           05  WPS-DESC              PIC X(55).
           05  FILLER                 PIC X(02) VALUE '$ '.
           05  WPS-AMOUNT            PIC Z,ZZ9.99.
           05  FILLER                 PIC X(65) VALUE SPACES.

       01  WS-RPT-BENEFIT-LINE.
           05  FILLER                 PIC X(01) VALUE SPACE.
           05  WBL-DESC              PIC X(55).
           05  FILLER                 PIC X(02) VALUE '$ '.
           05  WBL-AMOUNT            PIC Z,ZZ9.99.
           05  FILLER                 PIC X(65) VALUE SPACES.

       PROCEDURE DIVISION.

      *================================================================*
      * MAIN CONTROL                                                   *
      *================================================================*
       0000-MAIN-CONTROL.
           PERFORM 1000-INITIALIZE
           PERFORM 2000-PROCESS-WORKERS
               UNTIL END-OF-FILE
           PERFORM 9000-FINALIZE
           STOP RUN
           .

      *================================================================*
      * INITIALIZE - OPEN FILES                                        *
      *================================================================*
       1000-INITIALIZE.
           OPEN INPUT  EARNINGS-HISTORY
           OPEN OUTPUT BENEFIT-REPORT

           IF WS-EARN-STATUS NOT = '00'
               DISPLAY 'ERROR OPENING EARNINGS FILE: '
                   WS-EARN-STATUS
               SET END-OF-FILE TO TRUE
           END-IF

      *    Write report title
           WRITE REPORT-LINE FROM WS-RPT-TITLE
           WRITE REPORT-LINE FROM WS-RPT-SEPARATOR

           PERFORM 8000-READ-EARNINGS
           .

      *================================================================*
      * PROCESS EACH WORKER                                            *
      *================================================================*
       2000-PROCESS-WORKERS.
      *    Expect a header record first
           IF EI-HEADER-REC
               ADD 1 TO WS-WORKERS-PROCESSED
               PERFORM 2100-LOAD-WORKER-HEADER
               PERFORM 2200-LOAD-EARNINGS
               PERFORM 3000-INDEX-EARNINGS
               PERFORM 4000-SELECT-TOP-35
               PERFORM 5000-CALCULATE-AIME
               PERFORM 6000-CALCULATE-PIA
               PERFORM 7000-APPLY-RETIREMENT-ADJ
               PERFORM 7500-WRITE-REPORT
           ELSE
               PERFORM 8000-READ-EARNINGS
           END-IF
           .

      *================================================================*
      * LOAD WORKER HEADER INFORMATION                                 *
      *================================================================*
       2100-LOAD-WORKER-HEADER.
           MOVE EI-SSN               TO WS-SSN
           MOVE EI-WORKER-NAME       TO WS-WORKER-NAME
           MOVE EI-BIRTH-YEAR        TO WS-BIRTH-YEAR
           MOVE EI-CLAIM-AGE         TO WS-CLAIM-AGE
           MOVE EI-FRA-AGE-YEARS     TO WS-FRA-AGE-YEARS
           MOVE EI-FRA-AGE-MONTHS    TO WS-FRA-AGE-MONTHS

      *    Calculate age-60 year for indexing
           COMPUTE WS-AGE60-YEAR = WS-BIRTH-YEAR + 60

      *    Reset earnings table
           MOVE ZEROS TO WS-EARN-COUNT
           MOVE ZEROS TO WS-TOP35-TOTAL
           MOVE ZEROS TO WS-YEARS-SELECTED

           PERFORM 8000-READ-EARNINGS
           .

      *================================================================*
      * LOAD ALL EARNINGS RECORDS FOR THIS WORKER                      *
      *================================================================*
       2200-LOAD-EARNINGS.
           PERFORM UNTIL NOT EI-EARNINGS-REC
               OR END-OF-FILE
               ADD 1 TO WS-EARN-COUNT

               MOVE EI-EARN-YEAR     TO
                   WS-ET-YEAR(WS-EARN-COUNT)
               MOVE EI-ACTUAL-EARNINGS TO
                   WS-ET-ACTUAL(WS-EARN-COUNT)
               MOVE EI-WAGE-INDEX    TO
                   WS-ET-WAGE-INDEX(WS-EARN-COUNT)
               MOVE EI-SS-MAX-EARNINGS TO
                   WS-ET-SS-MAX(WS-EARN-COUNT)

      *        Cap earnings at the Social Security maximum
      *        for that year
               IF WS-ET-ACTUAL(WS-EARN-COUNT) >
                   WS-ET-SS-MAX(WS-EARN-COUNT)
                   MOVE WS-ET-SS-MAX(WS-EARN-COUNT) TO
                       WS-ET-CAPPED(WS-EARN-COUNT)
               ELSE
                   MOVE WS-ET-ACTUAL(WS-EARN-COUNT) TO
                       WS-ET-CAPPED(WS-EARN-COUNT)
               END-IF

               SET ET-NOT-SELECTED(WS-EARN-COUNT) TO TRUE

               PERFORM 8000-READ-EARNINGS
           END-PERFORM

      *    If we hit a trailer record, read past it
           IF EI-TRAILER-REC
               PERFORM 8000-READ-EARNINGS
           END-IF
           .

      *================================================================*
      * INDEX EARNINGS TO AGE-60 WAGE LEVELS                           *
      *                                                                *
      * Each year's capped earnings are multiplied by the ratio of     *
      * the national average wage index in the worker's age-60 year    *
      * to the national average wage index in the earnings year.       *
      *                                                                *
      * Indexed Earnings = Capped Earnings * (Age60 Index / Year Index)*
      *                                                                *
      * Earnings in years at or after age 60 are not indexed; they     *
      * are used at their actual (capped) amount.                      *
      *================================================================*
       3000-INDEX-EARNINGS.
      *    Find the wage index for the age-60 year
      *    (the last entry with year <= age-60 year)
           MOVE ZEROS TO WS-AGE60-WAGE-INDEX
           PERFORM VARYING WS-IDX-COUNTER FROM 1 BY 1
               UNTIL WS-IDX-COUNTER > WS-EARN-COUNT
               IF WS-ET-YEAR(WS-IDX-COUNTER) = WS-AGE60-YEAR
                   MOVE WS-ET-WAGE-INDEX(WS-IDX-COUNTER)
                       TO WS-AGE60-WAGE-INDEX
               END-IF
           END-PERFORM

      *    If age-60 index not found, use the closest prior year
           IF WS-AGE60-WAGE-INDEX = ZEROS
               PERFORM VARYING WS-IDX-COUNTER
                   FROM WS-EARN-COUNT BY -1
                   UNTIL WS-IDX-COUNTER < 1
                   OR WS-AGE60-WAGE-INDEX > ZEROS
                   IF WS-ET-YEAR(WS-IDX-COUNTER)
                       < WS-AGE60-YEAR
                       MOVE WS-ET-WAGE-INDEX(WS-IDX-COUNTER)
                           TO WS-AGE60-WAGE-INDEX
                   END-IF
               END-PERFORM
           END-IF

      *    Index each year's earnings
           PERFORM VARYING WS-IDX-COUNTER FROM 1 BY 1
               UNTIL WS-IDX-COUNTER > WS-EARN-COUNT

               IF WS-ET-YEAR(WS-IDX-COUNTER) < WS-AGE60-YEAR
      *            Index earnings for years before age 60
                   IF WS-ET-WAGE-INDEX(WS-IDX-COUNTER) > ZEROS
                       COMPUTE WS-INDEX-FACTOR =
                           WS-AGE60-WAGE-INDEX /
                           WS-ET-WAGE-INDEX(WS-IDX-COUNTER)
                       COMPUTE
                           WS-ET-INDEXED(WS-IDX-COUNTER)
                           ROUNDED =
                           WS-ET-CAPPED(WS-IDX-COUNTER)
                           * WS-INDEX-FACTOR
                           ON SIZE ERROR
                               DISPLAY 'SIZE ERROR INDEXING'
                                   ' YEAR '
                                   WS-ET-YEAR(WS-IDX-COUNTER)
                       END-COMPUTE
                   ELSE
                       MOVE WS-ET-CAPPED(WS-IDX-COUNTER)
                           TO WS-ET-INDEXED(WS-IDX-COUNTER)
                   END-IF
               ELSE
      *            Earnings at or after age 60: use actual
      *            (capped) amount without indexing
                   MOVE WS-ET-CAPPED(WS-IDX-COUNTER)
                       TO WS-ET-INDEXED(WS-IDX-COUNTER)
               END-IF
           END-PERFORM
           .

      *================================================================*
      * SELECT THE HIGHEST 35 YEARS OF INDEXED EARNINGS                *
      *                                                                *
      * Sort the earnings table by indexed earnings in descending      *
      * order, then select the top 35 entries. If fewer than 35        *
      * years have earnings, the missing years count as zero,          *
      * reducing the AIME.                                             *
      *================================================================*
       4000-SELECT-TOP-35.
      *    Sort earnings by indexed amount (descending)
      *    Using simple bubble sort for clarity
           PERFORM VARYING WS-SORT-IDX-1 FROM 1 BY 1
               UNTIL WS-SORT-IDX-1 >= WS-EARN-COUNT

               COMPUTE WS-SORT-IDX-2 =
                   WS-SORT-IDX-1 + 1

               PERFORM VARYING WS-SORT-IDX-2
                   FROM WS-SORT-IDX-2 BY 1
                   UNTIL WS-SORT-IDX-2 > WS-EARN-COUNT

                   IF WS-ET-INDEXED(WS-SORT-IDX-2) >
                       WS-ET-INDEXED(WS-SORT-IDX-1)

      *                Swap all fields for the two entries
                       MOVE WS-ET-INDEXED(WS-SORT-IDX-1)
                           TO WS-SORT-TEMP-EARN
                       MOVE WS-ET-INDEXED(WS-SORT-IDX-2)
                           TO WS-ET-INDEXED(WS-SORT-IDX-1)
                       MOVE WS-SORT-TEMP-EARN
                           TO WS-ET-INDEXED(WS-SORT-IDX-2)

                       MOVE WS-ET-YEAR(WS-SORT-IDX-1)
                           TO WS-SORT-TEMP-YEAR
                       MOVE WS-ET-YEAR(WS-SORT-IDX-2)
                           TO WS-ET-YEAR(WS-SORT-IDX-1)
                       MOVE WS-SORT-TEMP-YEAR
                           TO WS-ET-YEAR(WS-SORT-IDX-2)

                       MOVE WS-ET-ACTUAL(WS-SORT-IDX-1)
                           TO WS-SORT-TEMP-ACTUAL
                       MOVE WS-ET-ACTUAL(WS-SORT-IDX-2)
                           TO WS-ET-ACTUAL(WS-SORT-IDX-1)
                       MOVE WS-SORT-TEMP-ACTUAL
                           TO WS-ET-ACTUAL(WS-SORT-IDX-2)

                       MOVE WS-ET-CAPPED(WS-SORT-IDX-1)
                           TO WS-SORT-TEMP-CAPPED
                       MOVE WS-ET-CAPPED(WS-SORT-IDX-2)
                           TO WS-ET-CAPPED(WS-SORT-IDX-1)
                       MOVE WS-SORT-TEMP-CAPPED
                           TO WS-ET-CAPPED(WS-SORT-IDX-2)

                       MOVE WS-ET-WAGE-INDEX(WS-SORT-IDX-1)
                           TO WS-SORT-TEMP-INDEX
                       MOVE WS-ET-WAGE-INDEX(WS-SORT-IDX-2)
                           TO WS-ET-WAGE-INDEX(WS-SORT-IDX-1)
                       MOVE WS-SORT-TEMP-INDEX
                           TO WS-ET-WAGE-INDEX(WS-SORT-IDX-2)

                       MOVE WS-ET-SS-MAX(WS-SORT-IDX-1)
                           TO WS-SORT-TEMP-MAX
                       MOVE WS-ET-SS-MAX(WS-SORT-IDX-2)
                           TO WS-ET-SS-MAX(WS-SORT-IDX-1)
                       MOVE WS-SORT-TEMP-MAX
                           TO WS-ET-SS-MAX(WS-SORT-IDX-2)
                   END-IF
               END-PERFORM
           END-PERFORM

      *    Select the top 35 years
           MOVE ZEROS TO WS-YEARS-SELECTED
           PERFORM VARYING WS-IDX-COUNTER FROM 1 BY 1
               UNTIL WS-IDX-COUNTER > WS-EARN-COUNT
               OR WS-YEARS-SELECTED >= WS-COMPUTATION-YEARS

               SET ET-SELECTED(WS-IDX-COUNTER) TO TRUE
               ADD 1 TO WS-YEARS-SELECTED
               ADD WS-ET-INDEXED(WS-IDX-COUNTER)
                   TO WS-TOP35-TOTAL
           END-PERFORM
           .

      *================================================================*
      * CALCULATE AIME (AVERAGE INDEXED MONTHLY EARNINGS)              *
      *                                                                *
      * AIME = Total of highest 35 years / 420 (35 * 12)              *
      * The result is truncated (not rounded) to a whole dollar.       *
      *================================================================*
       5000-CALCULATE-AIME.
      *    Divide total by 420 months and truncate
      *    (SSA rules: drop cents from AIME)
           COMPUTE WS-AIME =
               WS-TOP35-TOTAL / 420
           .

      *================================================================*
      * CALCULATE PIA (PRIMARY INSURANCE AMOUNT)                       *
      *                                                                *
      * PIA formula with 2024 bend points:                             *
      *   90% of first $1,174 of AIME                                 *
      *   + 32% of AIME between $1,174 and $7,078                     *
      *   + 15% of AIME above $7,078                                  *
      *                                                                *
      * The PIA is rounded down to the next lower dime.                *
      *================================================================*
       6000-CALCULATE-PIA.
      *    Segment 1: 90% of AIME up to first bend point
           IF WS-AIME > WS-BEND-POINT-1
               COMPUTE WS-PIA-SEGMENT-1 ROUNDED =
                   WS-BEND-POINT-1 * 0.90
                   ON SIZE ERROR
                       DISPLAY 'SIZE ERROR: PIA SEG 1'
               END-COMPUTE
           ELSE
               COMPUTE WS-PIA-SEGMENT-1 ROUNDED =
                   WS-AIME * 0.90
                   ON SIZE ERROR
                       DISPLAY 'SIZE ERROR: PIA SEG 1'
               END-COMPUTE
           END-IF

      *    Segment 2: 32% of AIME between bend points
           IF WS-AIME > WS-BEND-POINT-2
               COMPUTE WS-PIA-SEGMENT-2 ROUNDED =
                   (WS-BEND-POINT-2 - WS-BEND-POINT-1)
                   * 0.32
                   ON SIZE ERROR
                       DISPLAY 'SIZE ERROR: PIA SEG 2'
               END-COMPUTE
           ELSE IF WS-AIME > WS-BEND-POINT-1
               COMPUTE WS-PIA-SEGMENT-2 ROUNDED =
                   (WS-AIME - WS-BEND-POINT-1) * 0.32
                   ON SIZE ERROR
                       DISPLAY 'SIZE ERROR: PIA SEG 2'
               END-COMPUTE
           ELSE
               MOVE ZEROS TO WS-PIA-SEGMENT-2
           END-IF

      *    Segment 3: 15% of AIME above second bend point
           IF WS-AIME > WS-BEND-POINT-2
               COMPUTE WS-PIA-SEGMENT-3 ROUNDED =
                   (WS-AIME - WS-BEND-POINT-2) * 0.15
                   ON SIZE ERROR
                       DISPLAY 'SIZE ERROR: PIA SEG 3'
               END-COMPUTE
           ELSE
               MOVE ZEROS TO WS-PIA-SEGMENT-3
           END-IF

      *    Sum the three segments
           COMPUTE WS-PIA-RAW =
               WS-PIA-SEGMENT-1 + WS-PIA-SEGMENT-2
               + WS-PIA-SEGMENT-3

      *    Round DOWN to the next lower dime (SSA rules)
      *    Multiply by 10, truncate to integer, divide by 10
           COMPUTE WS-PIA-ROUNDED =
               FUNCTION INTEGER(WS-PIA-RAW * 10) / 10

           MOVE WS-PIA-ROUNDED TO WS-PIA-FINAL
           .

      *================================================================*
      * APPLY EARLY/LATE RETIREMENT ADJUSTMENT                         *
      *                                                                *
      * EARLY RETIREMENT (before FRA):                                 *
      *   First 36 months early: reduce by 5/9 of 1% per month        *
      *   Each additional month: reduce by 5/12 of 1% per month       *
      *                                                                *
      * DELAYED RETIREMENT (after FRA):                                *
      *   Increase by 2/3 of 1% per month (8% per year)               *
      *   Maximum delay until age 70                                   *
      *================================================================*
       7000-APPLY-RETIREMENT-ADJ.
      *    Convert FRA and claim age to total months
      *    FRA example: 67 years 0 months = 804 months
           COMPUTE WS-FRA-TOTAL-MONTHS =
               (WS-FRA-AGE-YEARS * 12) + WS-FRA-AGE-MONTHS

      *    Claim age in months (assuming claiming at beginning
      *    of the claim-age year, i.e., 0 additional months)
           COMPUTE WS-CLAIM-TOTAL-MONTHS =
               WS-CLAIM-AGE * 12

      *    Calculate difference
           COMPUTE WS-MONTHS-DIFF =
               WS-FRA-TOTAL-MONTHS - WS-CLAIM-TOTAL-MONTHS

           IF WS-MONTHS-DIFF > 0
      *        EARLY RETIREMENT
               MOVE WS-MONTHS-DIFF TO WS-MONTHS-EARLY
               MOVE ZEROS TO WS-MONTHS-LATE

      *        First 36 months: 5/9 of 1% per month
               IF WS-MONTHS-EARLY > 36
                   MOVE 36 TO WS-EARLY-FIRST-36
                   COMPUTE WS-EARLY-OVER-36 =
                       WS-MONTHS-EARLY - 36
               ELSE
                   MOVE WS-MONTHS-EARLY TO WS-EARLY-FIRST-36
                   MOVE ZEROS TO WS-EARLY-OVER-36
               END-IF

      *        Calculate total reduction factor
      *        5/9 of 1% = 0.005556 per month for first 36
      *        5/12 of 1% = 0.004167 per month beyond 36
               COMPUTE WS-EARLY-REDUCTION =
                   (WS-EARLY-FIRST-36 * 5 / 9 / 100) +
                   (WS-EARLY-OVER-36 * 5 / 12 / 100)

      *        Apply reduction
               COMPUTE WS-ADJUSTED-BENEFIT ROUNDED =
                   WS-PIA-FINAL * (1 - WS-EARLY-REDUCTION)
                   ON SIZE ERROR
                       DISPLAY 'SIZE ERROR: EARLY ADJ'
               END-COMPUTE

               MOVE 'EARLY RETIREMENT REDUCTION'
                   TO WS-ADJUSTMENT-DESC

           ELSE IF WS-MONTHS-DIFF < 0
      *        DELAYED RETIREMENT
               COMPUTE WS-MONTHS-LATE =
                   0 - WS-MONTHS-DIFF
               MOVE ZEROS TO WS-MONTHS-EARLY

      *        Cap delay at age 70
               COMPUTE WS-IDX-COUNTER =
                   (70 * 12) - WS-FRA-TOTAL-MONTHS
               IF WS-MONTHS-LATE > WS-IDX-COUNTER
                   MOVE WS-IDX-COUNTER TO WS-MONTHS-LATE
               END-IF

      *        2/3 of 1% per month = 0.006667 per month
               COMPUTE WS-LATE-CREDIT =
                   WS-MONTHS-LATE * 2 / 3 / 100

      *        Apply delayed retirement credits
               COMPUTE WS-ADJUSTED-BENEFIT ROUNDED =
                   WS-PIA-FINAL * (1 + WS-LATE-CREDIT)
                   ON SIZE ERROR
                       DISPLAY 'SIZE ERROR: DELAY ADJ'
               END-COMPUTE

               MOVE 'DELAYED RETIREMENT CREDIT'
                   TO WS-ADJUSTMENT-DESC

           ELSE
      *        Claiming at exactly FRA
               MOVE WS-PIA-FINAL TO WS-ADJUSTED-BENEFIT
               MOVE 'AT FULL RETIREMENT AGE'
                   TO WS-ADJUSTMENT-DESC
           END-IF

      *    Round to nearest penny (benefit amounts are
      *    rounded down to next lower dime by SSA rules,
      *    but the adjusted amount is truncated to dollars)
           COMPUTE WS-ADJUSTED-BENEFIT =
               FUNCTION INTEGER(WS-ADJUSTED-BENEFIT * 10)
               / 10
           .

      *================================================================*
      * WRITE COMPLETE BENEFIT COMPUTATION REPORT                      *
      *================================================================*
       7500-WRITE-REPORT.
           WRITE REPORT-LINE FROM WS-RPT-BLANK

      *    Worker identification
           MOVE WS-SSN TO WWH-SSN
           MOVE WS-WORKER-NAME TO WWH-NAME
           MOVE WS-BIRTH-YEAR TO WWH-BIRTH-YEAR
           MOVE WS-CLAIM-AGE TO WWH-CLAIM-AGE
           WRITE REPORT-LINE FROM WS-RPT-WORKER-HDR

      *    FRA information
           MOVE WS-FRA-AGE-YEARS TO WFRA-YEARS
           MOVE WS-FRA-AGE-MONTHS TO WFRA-MONTHS
           WRITE REPORT-LINE FROM WS-RPT-FRA-LINE
           WRITE REPORT-LINE FROM WS-RPT-BLANK

      *    Earnings history table
           WRITE REPORT-LINE FROM WS-RPT-EARN-HDR
           WRITE REPORT-LINE FROM WS-RPT-EARN-DASH

           PERFORM VARYING WS-IDX-COUNTER FROM 1 BY 1
               UNTIL WS-IDX-COUNTER > WS-EARN-COUNT

               MOVE WS-ET-YEAR(WS-IDX-COUNTER)
                   TO WEL-YEAR
               MOVE WS-ET-ACTUAL(WS-IDX-COUNTER)
                   TO WEL-ACTUAL
               MOVE WS-ET-CAPPED(WS-IDX-COUNTER)
                   TO WEL-CAPPED
               MOVE WS-ET-WAGE-INDEX(WS-IDX-COUNTER)
                   TO WEL-WAGE-IDX

      *        Calculate and display the index factor
               IF WS-ET-YEAR(WS-IDX-COUNTER) < WS-AGE60-YEAR
                   AND WS-ET-WAGE-INDEX(WS-IDX-COUNTER) > 0
                   COMPUTE WEL-IDX-FACTOR =
                       WS-AGE60-WAGE-INDEX /
                       WS-ET-WAGE-INDEX(WS-IDX-COUNTER)
               ELSE
                   MOVE 1.000000 TO WEL-IDX-FACTOR
               END-IF

               MOVE WS-ET-INDEXED(WS-IDX-COUNTER)
                   TO WEL-INDEXED

               IF ET-SELECTED(WS-IDX-COUNTER)
                   MOVE 'YES' TO WEL-SELECTED
               ELSE
                   MOVE '   ' TO WEL-SELECTED
               END-IF

               WRITE REPORT-LINE FROM WS-RPT-EARN-LINE
           END-PERFORM

           WRITE REPORT-LINE FROM WS-RPT-EARN-DASH
           WRITE REPORT-LINE FROM WS-RPT-BLANK

      *    AIME
           MOVE WS-AIME TO WAIME-AMOUNT
           WRITE REPORT-LINE FROM WS-RPT-AIME-LINE
           WRITE REPORT-LINE FROM WS-RPT-BLANK

      *    PIA calculation detail
           WRITE REPORT-LINE FROM WS-RPT-PIA-HDR

           MOVE '  90% OF FIRST $1,174 OF AIME'
               TO WPS-DESC
           MOVE WS-PIA-SEGMENT-1 TO WPS-AMOUNT
           WRITE REPORT-LINE FROM WS-RPT-PIA-SEGMENT

           MOVE '  32% OF AIME FROM $1,174 TO $7,078'
               TO WPS-DESC
           MOVE WS-PIA-SEGMENT-2 TO WPS-AMOUNT
           WRITE REPORT-LINE FROM WS-RPT-PIA-SEGMENT

           MOVE '  15% OF AIME ABOVE $7,078'
               TO WPS-DESC
           MOVE WS-PIA-SEGMENT-3 TO WPS-AMOUNT
           WRITE REPORT-LINE FROM WS-RPT-PIA-SEGMENT

           MOVE '  PIA (ROUNDED DOWN TO DIME)'
               TO WPS-DESC
           MOVE WS-PIA-FINAL TO WPS-AMOUNT
           WRITE REPORT-LINE FROM WS-RPT-PIA-SEGMENT

           WRITE REPORT-LINE FROM WS-RPT-BLANK

      *    Retirement adjustment
           MOVE WS-ADJUSTMENT-DESC TO WBL-DESC
           MOVE WS-ADJUSTED-BENEFIT TO WBL-AMOUNT
           WRITE REPORT-LINE FROM WS-RPT-BENEFIT-LINE

           IF WS-MONTHS-EARLY > 0
               MOVE '  MONTHS BEFORE FRA:'
                   TO WBL-DESC
               COMPUTE WBL-AMOUNT = WS-MONTHS-EARLY
               WRITE REPORT-LINE FROM WS-RPT-BENEFIT-LINE
           END-IF

           IF WS-MONTHS-LATE > 0
               MOVE '  MONTHS AFTER FRA:'
                   TO WBL-DESC
               COMPUTE WBL-AMOUNT = WS-MONTHS-LATE
               WRITE REPORT-LINE FROM WS-RPT-BENEFIT-LINE
           END-IF

      *    Final monthly benefit
           WRITE REPORT-LINE FROM WS-RPT-BLANK
           MOVE 'MONTHLY RETIREMENT BENEFIT'
               TO WBL-DESC
           MOVE WS-ADJUSTED-BENEFIT TO WBL-AMOUNT
           WRITE REPORT-LINE FROM WS-RPT-BENEFIT-LINE

      *    Annual benefit
           MOVE 'ESTIMATED ANNUAL BENEFIT'
               TO WBL-DESC
           COMPUTE WBL-AMOUNT ROUNDED =
               WS-ADJUSTED-BENEFIT * 12
           WRITE REPORT-LINE FROM WS-RPT-BENEFIT-LINE

           WRITE REPORT-LINE FROM WS-RPT-SEPARATOR
           .

      *================================================================*
      * READ NEXT EARNINGS RECORD                                      *
      *================================================================*
       8000-READ-EARNINGS.
           READ EARNINGS-HISTORY
               AT END
                   SET END-OF-FILE TO TRUE
           END-READ
           .

      *================================================================*
      * FINALIZE AND CLOSE FILES                                       *
      *================================================================*
       9000-FINALIZE.
           CLOSE EARNINGS-HISTORY
                 BENEFIT-REPORT

           DISPLAY 'BENEFIT CALCULATION COMPLETE'
           DISPLAY '  WORKERS PROCESSED: '
               WS-WORKERS-PROCESSED
           .

The JCL to execute the benefit calculator follows:

//SSACALC  JOB (ACCT),'SSA BENEFIT CALC',CLASS=A,
//         MSGCLASS=X,NOTIFY=&SYSUID
//*
//*================================================================*
//* SOCIAL SECURITY BENEFIT CALCULATION                            *
//*================================================================*
//*
//STEP01   EXEC PGM=SSABENCALC
//STEPLIB  DD   DSN=SSA.BENEFIT.LOADLIB,DISP=SHR
//EARNHIST DD   DSN=SSA.EARNINGS.HISTORY,DISP=SHR
//BENCALC  DD   DSN=SSA.BENEFIT.REPORT,DISP=(NEW,CATLG,DELETE),
//         SPACE=(CYL,(10,5),RLSE),
//         DCB=(RECFM=FB,LRECL=132,BLKSIZE=0)
//SYSOUT   DD   SYSOUT=*

How the Program Works

Earnings Indexing (3000-INDEX-EARNINGS)

The most conceptually significant step is earnings indexing. Wages earned in 1990 had a different purchasing power than wages earned in 2020. To make earnings from different years comparable, SSA adjusts each year's earnings by the ratio of the national average wage index in the worker's age-60 year to the index in the earnings year.

For example, if the age-60 wage index is 60,575.07 and the 1990 wage index was 21,027.98, the index factor is 60,575.07 / 21,027.98 = 2.880. Earnings of $30,000 in 1990 become $86,400 in indexed terms. This ensures that a worker who earned a middle-class income in 1990 is not penalized relative to a worker earning a middle-class income in 2020.

Earnings in years at or after age 60 are not indexed -- they are used at their actual capped amount. This is because the wage index used for indexing is the age-60 index, so indexing would be meaningless for those years.

Top-35 Selection (4000-SELECT-TOP-35)

After indexing, the program sorts all earnings years by indexed amount in descending order using a bubble sort. The top 35 years are then selected. If a worker has fewer than 35 years of earnings, the missing years are effectively counted as zero, which reduces the AIME. This is why years with zero earnings significantly impact the final benefit.

The sort uses a straightforward bubble sort for clarity. In a production system processing millions of records, a more efficient sorting algorithm or the COBOL SORT verb might be used, but for a 50-element table, bubble sort is adequate.

AIME Calculation (5000-CALCULATE-AIME)

The AIME is simply the sum of the top 35 years of indexed earnings divided by 420 (35 years * 12 months). The critical detail is that the result is truncated to a whole dollar -- not rounded. SSA rules specify truncation, and this must be implemented exactly. Using ROUNDED here would produce an incorrect AIME for roughly half of all workers, potentially resulting in a PIA that is $0.10 to $1.00 too high or too low per month. Over decades of benefit payments, this matters.

PIA Calculation (6000-CALCULATE-PIA)

The PIA formula applies three replacement rates to three segments of the AIME, separated by the bend points. The progressive structure means low-income workers receive a higher percentage of their earnings as benefits:

  • A worker with an AIME of $1,000 gets 90% = $900/month
  • A worker with an AIME of $5,000 gets 90% of $1,174 + 32% of $3,826 = $1,056.60 + $1,224.32 = $2,280.92/month (45.6% of AIME)
  • A worker with an AIME of $10,000 gets all three segments totaling approximately $3,418/month (34.2% of AIME)

The PIA is rounded down to the next lower dime, not to the nearest dime. This is another SSA-specific rounding rule that must be implemented precisely.

Retirement Adjustment (7000-APPLY-RETIREMENT-ADJ)

The adjustment for early or late retirement is among the most intricate parts of the calculation:

Early retirement: The reduction is not uniform. The first 36 months before FRA are penalized at 5/9 of 1% per month (approximately 6.67% per year). Months beyond 36 are penalized at 5/12 of 1% per month (5% per year). For a worker with an FRA of 67 claiming at 62 (60 months early), the reduction is: (36 * 5/9/100) + (24 * 5/12/100) = 0.20 + 0.10 = 0.30, or a 30% reduction.

Delayed retirement: Credits of 2/3 of 1% per month (8% per year) are added for each month of delay past FRA, up to age 70. A worker with FRA 67 who delays to 70 gets 36 months of credits = 24% increase.

Precision Considerations

The Social Security benefit calculation has several unique precision requirements:

  1. Earnings are capped annually: Before indexing, each year's earnings are limited to the Social Security taxable maximum for that year. This cap changes annually.

  2. AIME is truncated to whole dollars: Unlike most financial calculations where rounding to the nearest cent is appropriate, the AIME specifically requires truncation.

  3. PIA is rounded down to the next lower dime: The PIA uses an unusual rounding rule that drops to the next lower 10-cent increment, not the nearest dime.

  4. Index factors require extended decimal precision: The ratio of two wage index values can produce a factor with many significant digits (e.g., 2.879856...). The index factor field uses PIC S9(05)V9(08) to carry 8 decimal places.

  5. Early retirement reduction uses fractional arithmetic: The 5/9 and 5/12 fractions produce repeating decimals. Computing these precisely requires sufficient decimal places in the intermediate fields.

Discussion Questions

  1. Why does SSA index earnings to the worker's age-60 year rather than to the current year? What impact would indexing to the current year have on benefit amounts?

  2. The AIME is truncated to whole dollars rather than rounded. How much difference could this make to a retiree's monthly benefit over 20 years of benefit receipt?

  3. Why is the PIA formula progressive (higher replacement rates for lower earnings)? What policy goal does this serve?

  4. A worker has 30 years of earnings and 5 years of zero earnings in the top-35 computation. How do the zero years affect the AIME, and what strategies might a worker use to mitigate this?

  5. The early retirement reduction rates (5/9 of 1% for the first 36 months, 5/12 of 1% thereafter) create a non-linear reduction. Why is the penalty steeper for the months closest to FRA?

Connection to Chapter Concepts

This case study directly applies these Chapter 35 concepts:

  • Government benefit formulas: The AIME/PIA formula demonstrates the complex, rule-driven calculations typical of government entitlement systems (Section 35.4).
  • Table-driven parameters: Bend points, wage indexes, and earnings caps are stored in tables that change annually (Section 35.4).
  • COMP-3 for all monetary calculations: All earnings, index factors, and benefit amounts use packed decimal (Section 35.1).
  • Specialized rounding rules: SSA's truncation-to-whole-dollar (AIME) and round-down-to-dime (PIA) requirements differ from standard financial rounding (Section 35.4).
  • COBOL intrinsic functions: INTEGER is used for truncation, demonstrating how COBOL's built-in functions implement non-standard rounding rules (Section 35.4).
  • Batch processing architecture: The program reads sequential earnings records and produces formatted reports, following the standard government batch processing pattern (Section 35.5).
  • OCCURS for earnings history: The earnings table stores up to 50 years of data, accessed by subscript during indexing and sorting (Section 35.1).
  • ON SIZE ERROR: Overflow protection on all indexed earnings calculations guards against corrupted data or extreme index factors (Section 35.2).