At 6:00 a.m. on the third Wednesday of every month, a COBOL batch job awakens at the Social Security Administration's data center in Woodlawn, Maryland. Over the next four hours, it will calculate and authorize benefit payments for approximately 67...
In This Chapter
- Part VII - COBOL in Financial Systems
- Opening Vignette: The Quiet Engine of the Safety Net
- 35.1 The Insurance Industry and COBOL
- 35.2 Insurance Policy Administration
- 35.3 Premium Calculation Engines
- 35.4 Claims Processing Workflows
- 35.5 Actuarial Computations in COBOL
- 35.6 Batch Processing Patterns in Insurance
- 35.7 Government Benefits Administration
- 35.8 Tax Processing Systems
- 35.9 Regulatory Compliance Reporting
- 35.10 HIPAA and Data Privacy Considerations
- 35.11 Real-Time Policy Queries
- 35.12 Government Payment Processing
- 35.13 Medicare and Health Benefits Processing
- 35.14 Connecting the Concepts
- What You Have Learned
Chapter 35: Insurance and Government Systems
Part VII - COBOL in Financial Systems
Opening Vignette: The Quiet Engine of the Safety Net
At 6:00 a.m. on the third Wednesday of every month, a COBOL batch job awakens at the Social Security Administration's data center in Woodlawn, Maryland. Over the next four hours, it will calculate and authorize benefit payments for approximately 67 million Americans -- retirees drawing pensions they earned over decades of work, disabled individuals who depend on monthly checks for their survival, and surviving spouses and children of workers who died too young. The total: more than $100 billion in a single payment cycle. Every dollar must be calculated correctly. Every payment must reach the right account. Every deduction for Medicare premiums, tax withholding, and garnishments must be applied precisely as federal law requires.
Three hundred miles south, at a major property and casualty insurer's mainframe facility in Richmond, Virginia, the nightly batch cycle processes 400,000 auto insurance premium calculations. Each one involves dozens of rating factors: the driver's age, the vehicle's safety rating, the territory where the car is garaged, the policyholder's claims history over the past five years, multi-car discounts, good student discounts, and state-mandated minimum and maximum premium constraints. A single error in the rating algorithm could mean underpricing risk for an entire state, exposing the company to catastrophic losses, or overcharging policyholders in violation of the rates filed with the state insurance commissioner.
These two worlds -- insurance and government -- may seem different on the surface. One is a private industry driven by actuarial science and competitive markets; the other is a network of public agencies governed by statute and regulation. Yet they share a common technological foundation: massive COBOL systems that process enormous volumes of financial transactions with decimal precision, rigorous audit trails, and unwavering reliability.
Insurance companies and government agencies were among the earliest adopters of COBOL. The insurance industry needed a language that could handle complex premium calculations involving dozens of rating factors, table lookups, and rounding rules specified by state regulators. Government agencies needed a language that could process millions of benefit payments, tax returns, and eligibility determinations according to rules defined by thousands of pages of federal statute. COBOL delivered on both counts, and today, more than six decades after the language was created, it remains the backbone of both sectors.
In this chapter, you will learn how COBOL powers insurance policy administration systems, premium calculation engines, claims processing workflows, and actuarial computations. You will also explore how government agencies use COBOL for Social Security benefit administration, Medicare processing, tax computation, and regulatory compliance. By the end of this chapter, you will understand the data structures, processing patterns, and business logic that make these systems work, and you will be equipped to read, maintain, and extend the COBOL programs that millions of people depend on every day.
35.1 The Insurance Industry and COBOL
35.1.1 Why Insurance Runs on COBOL
The insurance industry processes staggering volumes of data. A large property and casualty insurer may maintain 30 million active policies, process 5 million claims annually, and calculate premiums using rating algorithms that involve hundreds of variables. A major life insurer may administer policies with coverage amounts totaling trillions of dollars, calculating reserves, cash values, and dividend allocations that must be accurate to the penny for regulatory reporting.
COBOL dominates insurance for several reasons that parallel those discussed in Chapter 34 for banking systems:
Decimal arithmetic precision: Insurance premiums, claim payments, reserves, and commissions all involve currency calculations where floating-point rounding errors are unacceptable. As covered in Chapter 33, COBOL's native support for packed decimal and display numeric data types eliminates the rounding errors that plague languages using IEEE 754 floating-point arithmetic. When a state insurance commissioner approves a rate of $347.52 per year for a particular coverage, the system must charge exactly $347.52 -- not $347.5199999999.
Table-driven processing: Insurance rating is fundamentally a table-lookup operation. Base rates vary by territory, coverage type, and policy form. Rating factors adjust for age, gender, claims history, vehicle type, building construction, and dozens of other variables. COBOL's table handling capabilities -- OCCURS clauses, INDEXED BY, SEARCH, and SEARCH ALL -- map naturally to these requirements.
High-volume batch processing: Insurance companies process enormous batch runs: nightly premium billing, monthly commission calculations, quarterly reserve valuations, and annual policy renewals. COBOL's sequential file processing, combined with SORT/MERGE and JCL-orchestrated job streams, handles these volumes efficiently.
Regulatory compliance: Insurance is regulated at the state level in the United States, meaning that a national insurer must comply with 50 different sets of rules. COBOL programs encode these rules explicitly in readable, auditable code that regulators and actuaries can review.
Long system lifetimes: An insurance policy can span decades. A whole life insurance policy purchased in 1975 may still be in force today, and the COBOL programs that administer it must faithfully execute business rules that were defined nearly fifty years ago while simultaneously applying current regulatory requirements. COBOL's backward compatibility makes this possible.
35.1.2 Insurance System Architecture
A typical insurance company's technology landscape includes the following core systems:
Policy Administration System (PAS): The system of record for all policies. It handles new business issuance, endorsements (mid-term changes), renewals, cancellations, and reinstatements. The PAS maintains the policy master file, which contains the definitive record of every policy the company has issued.
Rating Engine: The subsystem that calculates premiums. Given a set of risk characteristics (the "risk profile"), the rating engine applies base rates, rating factors, discounts, surcharges, and state-mandated limits to produce a premium. Rating engines may operate in batch mode (for renewal processing) or real-time mode (for online quoting).
Claims Processing System: Manages the lifecycle of insurance claims from first notice of loss through investigation, adjustment, payment, and closure. Claims systems are among the most complex applications in insurance, involving medical coding, litigation tracking, reserve estimation, and fraud detection.
Billing System: Generates premium invoices, processes payments, tracks delinquencies, and manages payment plans. Billing systems must handle multiple payment frequencies (annual, semi-annual, quarterly, monthly) and payment methods (direct bill, agency bill, payroll deduction, electronic funds transfer).
Reinsurance System: Manages the company's reinsurance treaties and facultative placements. When an insurer writes a policy with a coverage amount that exceeds its retention limit, it cedes a portion of the risk to reinsurers. The reinsurance system calculates ceded premiums, recoverable amounts on claims, and treaty balances.
Actuarial and Reserving Systems: Calculate the reserves that the company must hold to pay future claims. Reserve calculations involve complex actuarial formulas, loss development triangles, and statistical projections. These systems feed directly into regulatory filings and financial statements.
35.2 Insurance Policy Administration
Policy administration is the heart of an insurance company's operations. Every policy goes through a lifecycle: it is quoted, bound, issued, endorsed, renewed, and eventually cancelled or expired. The policy administration system manages each of these transitions, maintaining a complete history of every change.
35.2.1 The Policy Master Record
The policy master record is the most important data structure in an insurance system. It must store everything the company needs to know about a policy: who is insured, what is covered, when coverage begins and ends, how much premium is charged, who sold the policy, and how it has changed over time.
The following record layout, from Example 01 in this chapter's code directory, illustrates a typical policy master record for a multi-line insurance company. Notice how it uses level-88 condition names extensively to make the code self-documenting:
01 POLICY-MASTER-RECORD.
05 PM-POLICY-NUMBER PIC X(12).
05 PM-POLICY-STATUS-CODE PIC X(02).
88 PM-STATUS-ACTIVE VALUE 'AC'.
88 PM-STATUS-PENDING VALUE 'PE'.
88 PM-STATUS-CANCELLED VALUE 'CA'.
88 PM-STATUS-EXPIRED VALUE 'EX'.
88 PM-STATUS-LAPSED VALUE 'LA'.
88 PM-STATUS-SUSPENDED VALUE 'SU'.
05 PM-LINE-OF-BUSINESS PIC X(03).
88 PM-LOB-AUTO VALUE 'AUT'.
88 PM-LOB-HOME VALUE 'HOM'.
88 PM-LOB-LIFE VALUE 'LIF'.
88 PM-LOB-HEALTH VALUE 'HLT'.
88 PM-LOB-COMMERCIAL VALUE 'COM'.
05 PM-INSURED-INFO.
10 PM-INSURED-SSN PIC X(09).
10 PM-INSURED-LAST-NAME PIC X(25).
10 PM-INSURED-FIRST-NAME PIC X(15).
10 PM-INSURED-MI PIC X(01).
10 PM-INSURED-DOB PIC 9(08).
10 PM-INSURED-GENDER PIC X(01).
10 PM-INSURED-ADDRESS.
15 PM-STREET-ADDR PIC X(30).
15 PM-CITY PIC X(20).
15 PM-STATE PIC X(02).
15 PM-ZIP-CODE PIC X(05).
15 PM-ZIP-PLUS4 PIC 9(04).
05 PM-POLICY-DATES.
10 PM-EFFECTIVE-DATE PIC 9(08).
10 PM-EXPIRATION-DATE PIC 9(08).
10 PM-ORIG-ISSUE-DATE PIC 9(08).
10 PM-LAST-RENEWAL-DATE PIC 9(08).
10 PM-CANCEL-DATE PIC 9(08).
05 PM-COVERAGE-INFO.
10 PM-COVERAGE-AMOUNT PIC 9(09)V99.
10 PM-DEDUCTIBLE-AMT PIC 9(07)V99.
10 PM-ANNUAL-PREMIUM PIC 9(07)V99.
10 PM-PREMIUM-FREQUENCY PIC X(01).
88 PM-FREQ-ANNUAL VALUE 'A'.
88 PM-FREQ-SEMI VALUE 'S'.
88 PM-FREQ-QUARTERLY VALUE 'Q'.
88 PM-FREQ-MONTHLY VALUE 'M'.
10 PM-PAYMENT-METHOD PIC X(01).
88 PM-PAY-DIRECT VALUE 'D'.
88 PM-PAY-AGENCY VALUE 'A'.
88 PM-PAY-PAYROLL VALUE 'P'.
05 PM-AGENT-INFO.
10 PM-AGENT-CODE PIC X(08).
10 PM-AGENT-COMM-PCT PIC 9V9999.
05 PM-ENDORSEMENT-COUNT PIC 9(03).
05 PM-RENEWAL-COUNT PIC 9(02).
05 PM-CLAIMS-COUNT PIC 9(03).
05 PM-LAST-ACTIVITY-DATE PIC 9(08).
05 PM-UNDERWRITING-CLASS PIC X(02).
88 PM-UW-PREFERRED VALUE 'PF'.
88 PM-UW-STANDARD VALUE 'ST'.
88 PM-UW-SUBSTANDARD VALUE 'SS'.
88 PM-UW-DECLINED VALUE 'DC'.
05 PM-TERRITORY-CODE PIC X(04).
05 PM-RISK-SCORE PIC 9(03).
05 FILLER PIC X(169).
Several design decisions in this record layout deserve attention:
Policy number as primary key: The 12-character policy number (PM-POLICY-NUMBER) serves as the VSAM KSDS primary key. Insurance policy numbers typically encode information: the first two characters might indicate the line of business, the next two the state of issue, and the remaining eight a sequential number. This encoding allows range-based retrieval -- reading all auto policies issued in California, for example.
Alternate key on SSN: The Social Security number is defined as an alternate key WITH DUPLICATES, allowing the system to retrieve all policies for a given insured person. This is essential for household-level processing, cross-selling, and multi-policy discounts.
Status codes with condition names: The six status codes (AC, PE, CA, EX, LA, SU) cover the complete policy lifecycle. The level-88 condition names make PROCEDURE DIVISION logic readable: IF PM-STATUS-ACTIVE is far clearer than IF PM-POLICY-STATUS-CODE = 'AC'.
Separated date fields: Each date uses PIC 9(08) in YYYYMMDD format, which supports the FUNCTION INTEGER-OF-DATE intrinsic for date arithmetic. Keeping effective, expiration, original issue, last renewal, and cancellation dates as separate fields (rather than in an array) improves code readability and simplifies date validation.
FILLER for future expansion: The 169-byte FILLER at the end of the record reserves space for future fields without changing the record length. This is a standard practice in COBOL file design, as discussed in Chapter 12 on indexed files.
35.2.2 Transaction-Driven Policy Processing
Insurance policy administration follows a transaction-driven model. External events -- a new application, a change request, a renewal notice, a cancellation letter -- are encoded as transaction records and applied against the policy master file. The policy administration program in Example 01 demonstrates this pattern using an EVALUATE statement to dispatch transactions:
2000-PROCESS-TRANSACTIONS.
ADD 1 TO WS-TRANS-READ
SET VALID-TRANS TO TRUE
EVALUATE TRUE
WHEN TR-CREATE
PERFORM 3000-CREATE-POLICY
WHEN TR-MODIFY
PERFORM 4000-MODIFY-POLICY
WHEN TR-RENEW
PERFORM 5000-RENEW-POLICY
WHEN TR-CANCEL
PERFORM 6000-CANCEL-POLICY
WHEN OTHER
MOVE 'INVALID TRANSACTION CODE'
TO WS-ERROR-MSG
PERFORM 8000-WRITE-ERROR
ADD 1 TO WS-ERRORS
END-EVALUATE
PERFORM 2100-READ-TRANSACTION
.
This is the classic COBOL transaction processing pattern: read a transaction, determine its type, dispatch to the appropriate processing paragraph, and read the next transaction. The EVALUATE TRUE construct with level-88 conditions (TR-CREATE, TR-MODIFY, TR-RENEW, TR-CANCEL) is the idiomatic COBOL equivalent of a switch statement, and it produces code that reads almost like English.
35.2.3 Policy Creation
Creating a new policy is the most data-intensive transaction. The create paragraph must validate that the policy does not already exist, populate every field in the master record, calculate the expiration date, and write the new record to the VSAM file. Here is the create logic from Example 01:
3000-CREATE-POLICY.
* Create a new policy from application data.
* Validates that policy does not already exist.
MOVE TR-POLICY-NUMBER TO PM-POLICY-NUMBER
READ POLICY-MASTER
INVALID KEY CONTINUE
NOT INVALID KEY
MOVE 'POLICY ALREADY EXISTS - CANNOT CREATE'
TO WS-ERROR-MSG
PERFORM 8000-WRITE-ERROR
ADD 1 TO WS-ERRORS
GO TO 3000-EXIT
END-READ
INITIALIZE POLICY-MASTER-RECORD
MOVE TR-POLICY-NUMBER TO PM-POLICY-NUMBER
SET PM-STATUS-ACTIVE TO TRUE
MOVE TR-LINE-OF-BUSINESS TO PM-LINE-OF-BUSINESS
MOVE TR-INSURED-SSN TO PM-INSURED-SSN
MOVE TR-INSURED-LAST-NAME TO PM-INSURED-LAST-NAME
MOVE TR-INSURED-FIRST-NAME TO PM-INSURED-FIRST-NAME
MOVE TR-INSURED-MI TO PM-INSURED-MI
MOVE TR-INSURED-DOB TO PM-INSURED-DOB
MOVE TR-INSURED-GENDER TO PM-INSURED-GENDER
MOVE TR-STREET-ADDR TO PM-STREET-ADDR
MOVE TR-CITY TO PM-CITY
MOVE TR-STATE TO PM-STATE
MOVE TR-ZIP-CODE TO PM-ZIP-CODE
MOVE TR-ZIP-PLUS4 TO PM-ZIP-PLUS4
MOVE TR-EFFECTIVE-DATE TO PM-EFFECTIVE-DATE
MOVE TR-EFFECTIVE-DATE TO PM-ORIG-ISSUE-DATE
* Calculate expiration date (1 year from effective)
MOVE TR-EFFECTIVE-DATE TO WS-DATE-WORK
ADD 1 TO WS-WORK-YYYY
STRING WS-WORK-YYYY WS-WORK-MM WS-WORK-DD
DELIMITED BY SIZE
INTO PM-EXPIRATION-DATE
MOVE TR-COVERAGE-AMOUNT TO PM-COVERAGE-AMOUNT
MOVE TR-DEDUCTIBLE-AMT TO PM-DEDUCTIBLE-AMT
MOVE TR-ANNUAL-PREMIUM TO PM-ANNUAL-PREMIUM
MOVE TR-PREMIUM-FREQUENCY TO PM-PREMIUM-FREQUENCY
MOVE TR-AGENT-CODE TO PM-AGENT-CODE
MOVE 0.1000 TO PM-AGENT-COMM-PCT
MOVE 0 TO PM-ENDORSEMENT-COUNT
MOVE 0 TO PM-RENEWAL-COUNT
MOVE 0 TO PM-CLAIMS-COUNT
MOVE WS-CURRENT-DATE TO PM-LAST-ACTIVITY-DATE
MOVE TR-UW-CLASS TO PM-UNDERWRITING-CLASS
MOVE TR-TERRITORY-CODE TO PM-TERRITORY-CODE
MOVE 500 TO PM-RISK-SCORE
WRITE POLICY-MASTER-RECORD
IF WS-POLICY-STATUS = '00'
ADD 1 TO WS-CREATES-OK
MOVE 'CR' TO WS-AD-TRANS-CODE
MOVE PM-POLICY-NUMBER TO WS-AD-POLICY-NUM
MOVE 'CREATE' TO WS-AD-ACTION
MOVE PM-EFFECTIVE-DATE TO WS-AD-EFF-DATE
MOVE PM-ANNUAL-PREMIUM TO WS-AD-PREMIUM
MOVE 'ACTIVE' TO WS-AD-STATUS
MOVE 'NEW POLICY ISSUED'
TO WS-AD-DESCRIPTION
WRITE AUDIT-LINE FROM WS-AUDIT-DETAIL
ELSE
STRING 'WRITE ERROR ON POLICY CREATE: '
WS-POLICY-STATUS
DELIMITED BY SIZE INTO WS-ERROR-MSG
PERFORM 8000-WRITE-ERROR
ADD 1 TO WS-ERRORS
END-IF
.
3000-EXIT.
EXIT
.
The duplicate-check pattern at the top is important: before writing a new record, the program attempts to read the policy number from the master file. If the read succeeds (NOT INVALID KEY), it means the policy already exists, and the create must be rejected. Only if the read fails (INVALID KEY) does the program proceed with the creation. This defensive pattern prevents the accidental overwriting of existing policies.
Note also the audit trail: every successful transaction writes a detail line to the audit report. In insurance systems, audit trails are not optional. State regulators and internal auditors require a complete record of every change to every policy, including who made the change, when, and why.
35.2.4 Endorsements and Policy Modifications
An endorsement is a mid-term change to a policy. Common endorsements include address changes, coverage increases or decreases, deductible changes, and the addition or removal of drivers or vehicles. The modification paragraph from Example 01 handles endorsements using a secondary EVALUATE:
4000-MODIFY-POLICY.
* Modify an existing policy (endorsement processing).
* Supports address change, coverage change, deductible change.
MOVE TR-POLICY-NUMBER TO PM-POLICY-NUMBER
READ POLICY-MASTER
INVALID KEY
MOVE 'POLICY NOT FOUND FOR MODIFY'
TO WS-ERROR-MSG
PERFORM 8000-WRITE-ERROR
ADD 1 TO WS-ERRORS
GO TO 4000-EXIT
END-READ
IF NOT PM-STATUS-ACTIVE
MOVE 'POLICY NOT ACTIVE - CANNOT MODIFY'
TO WS-ERROR-MSG
PERFORM 8000-WRITE-ERROR
ADD 1 TO WS-ERRORS
GO TO 4000-EXIT
END-IF
EVALUATE TRUE
WHEN TR-MOD-ADDRESS
MOVE TR-STREET-ADDR TO PM-STREET-ADDR
MOVE TR-CITY TO PM-CITY
MOVE TR-STATE TO PM-STATE
MOVE TR-ZIP-CODE TO PM-ZIP-CODE
MOVE TR-ZIP-PLUS4 TO PM-ZIP-PLUS4
MOVE 'ADDRESS CHANGE ENDORSEMENT'
TO WS-AD-DESCRIPTION
WHEN TR-MOD-COVERAGE
MOVE TR-COVERAGE-AMOUNT TO PM-COVERAGE-AMOUNT
MOVE TR-ANNUAL-PREMIUM TO PM-ANNUAL-PREMIUM
MOVE 'COVERAGE CHANGE ENDORSEMENT'
TO WS-AD-DESCRIPTION
WHEN TR-MOD-DEDUCTIBLE
MOVE TR-DEDUCTIBLE-AMT TO PM-DEDUCTIBLE-AMT
MOVE TR-ANNUAL-PREMIUM TO PM-ANNUAL-PREMIUM
MOVE 'DEDUCTIBLE CHANGE ENDORSEMENT'
TO WS-AD-DESCRIPTION
WHEN OTHER
MOVE 'INVALID MODIFY FIELD CODE'
TO WS-ERROR-MSG
PERFORM 8000-WRITE-ERROR
ADD 1 TO WS-ERRORS
GO TO 4000-EXIT
END-EVALUATE
ADD 1 TO PM-ENDORSEMENT-COUNT
MOVE WS-CURRENT-DATE TO PM-LAST-ACTIVITY-DATE
REWRITE POLICY-MASTER-RECORD
.
The dual validation -- first checking that the policy exists, then checking that it is active -- is characteristic of insurance processing. A policy that is cancelled, expired, lapsed, or suspended cannot be endorsed. The endorsement count is incremented on every successful modification, providing a running total that auditors can use to identify policies with unusual levels of activity.
35.2.5 Cancellation and Refund Calculation
Policy cancellation is more complex than it first appears, because the refund calculation depends on who initiated the cancellation. Insurance uses two refund methods:
Pro-rata cancellation: When the insured requests cancellation, they receive a refund proportional to the remaining days in the policy term. If a policyholder cancels a $1,200 annual policy six months into the term, the pro-rata refund is $600 (half the premium for half the remaining term).
Short-rate cancellation: When the company initiates the cancellation (for non-payment, underwriting reasons, or other cause), the company retains a penalty -- typically 10 percent of the unearned premium. Using the same example, the short-rate refund would be $540 ($600 pro-rata minus a 10 percent penalty).
No refund: Cancellations due to fraud result in no refund at all.
The refund calculation logic from Example 01 illustrates these rules:
6100-CALCULATE-REFUND.
* Calculate refund based on cancellation type.
* Pro-rata: insured-requested cancellations
* Short-rate: company-initiated cancellations
* No refund: fraud cancellations
MOVE 0 TO WS-REFUND-AMOUNT
IF TR-CANCEL-FRAUD
MOVE 0 TO WS-REFUND-AMOUNT
GO TO 6100-EXIT
END-IF
* Determine months used in term
COMPUTE WS-DAYS-IN-TERM =
FUNCTION INTEGER-OF-DATE(PM-EXPIRATION-DATE) -
FUNCTION INTEGER-OF-DATE(PM-EFFECTIVE-DATE)
COMPUTE WS-DAYS-USED =
FUNCTION INTEGER-OF-DATE(TR-EFFECTIVE-DATE) -
FUNCTION INTEGER-OF-DATE(PM-EFFECTIVE-DATE)
IF WS-DAYS-USED >= WS-DAYS-IN-TERM
MOVE 0 TO WS-REFUND-AMOUNT
GO TO 6100-EXIT
END-IF
COMPUTE WS-DAYS-REMAINING =
WS-DAYS-IN-TERM - WS-DAYS-USED
IF TR-CANCEL-INSURED-REQ
* Pro-rata refund for insured-requested cancellation
COMPUTE WS-REFUND-AMOUNT ROUNDED =
PM-ANNUAL-PREMIUM *
(WS-DAYS-REMAINING / WS-DAYS-IN-TERM)
ELSE
* Short-rate refund (company keeps a penalty)
COMPUTE WS-PRO-RATA-REFUND ROUNDED =
PM-ANNUAL-PREMIUM *
(WS-DAYS-REMAINING / WS-DAYS-IN-TERM)
* Apply 10% short-rate penalty
COMPUTE WS-REFUND-AMOUNT ROUNDED =
WS-PRO-RATA-REFUND * 0.90
END-IF
.
6100-EXIT.
EXIT
.
This code uses FUNCTION INTEGER-OF-DATE to convert YYYYMMDD dates into integer day numbers, enabling exact day-level arithmetic. The ROUNDED keyword ensures that the refund amount is properly rounded to the nearest penny, following the financial arithmetic principles covered in Chapter 33.
35.3 Premium Calculation Engines
35.3.1 The Rating Process
Premium calculation -- called "rating" in insurance terminology -- is the process of determining the price of an insurance policy. Rating is inherently a table-driven, factor-based computation. The basic formula is:
Final Premium = Base Rate
x Age Factor
x Vehicle Factor
x Deductible Factor
x Risk Class Factor
- Discounts
+ Surcharges
Each factor is looked up from a table based on characteristics of the insured, the property being insured, or the coverage being purchased. The tables themselves are filed with state insurance regulators and must be applied exactly as filed. Any deviation -- even a rounding difference -- can result in regulatory penalties.
35.3.2 Table-Driven Rating in COBOL
Example 02 in this chapter's code directory implements a complete premium calculation engine for auto insurance. The program demonstrates several table structures that are representative of production rating systems.
The territory base rate table stores base rates for each combination of territory and coverage type:
01 WS-TERRITORY-RATE-TABLE.
05 WS-TERR-ENTRY OCCURS 20 TIMES
INDEXED BY WS-TERR-IDX.
10 WS-TERR-CODE PIC X(04).
10 WS-TERR-LI-RATE PIC 9(05)V99.
10 WS-TERR-CO-RATE PIC 9(05)V99.
10 WS-TERR-CP-RATE PIC 9(05)V99.
10 WS-TERR-MD-RATE PIC 9(05)V99.
10 WS-TERR-UM-RATE PIC 9(05)V99.
In production, this table would be loaded from an external file or a DB2 table at program initialization. The example loads rates from a sequential file during the initialization phase:
1100-LOAD-RATE-TABLES.
* Load territory base rates from external rate table file.
MOVE 0 TO WS-TERR-COUNT
PERFORM UNTIL WS-TBL-STATUS NOT = '00'
READ RATE-TABLE-FILE
AT END
CONTINUE
NOT AT END
ADD 1 TO WS-TERR-COUNT
MOVE RATE-TABLE-RECORD(1:4)
TO WS-TERR-CODE(WS-TERR-COUNT)
MOVE RATE-TABLE-RECORD(5:9)
TO WS-TERR-LI-RATE(WS-TERR-COUNT)
MOVE RATE-TABLE-RECORD(14:9)
TO WS-TERR-CO-RATE(WS-TERR-COUNT)
MOVE RATE-TABLE-RECORD(23:9)
TO WS-TERR-CP-RATE(WS-TERR-COUNT)
MOVE RATE-TABLE-RECORD(32:9)
TO WS-TERR-MD-RATE(WS-TERR-COUNT)
MOVE RATE-TABLE-RECORD(41:9)
TO WS-TERR-UM-RATE(WS-TERR-COUNT)
END-READ
END-PERFORM
.
The age rating factor table uses a threshold approach. Instead of storing a factor for every possible age, it stores age limits and applies the corresponding factor to any insured whose age falls at or below that threshold:
01 WS-AGE-FACTOR-TABLE.
05 FILLER PIC X(10) VALUE '016 1.7500'.
05 FILLER PIC X(10) VALUE '017 1.6500'.
05 FILLER PIC X(10) VALUE '018 1.5500'.
05 FILLER PIC X(10) VALUE '019 1.4500'.
05 FILLER PIC X(10) VALUE '020 1.3500'.
05 FILLER PIC X(10) VALUE '021 1.2500'.
05 FILLER PIC X(10) VALUE '025 1.1000'.
05 FILLER PIC X(10) VALUE '030 1.0000'.
05 FILLER PIC X(10) VALUE '040 0.9500'.
05 FILLER PIC X(10) VALUE '050 0.9000'.
05 FILLER PIC X(10) VALUE '055 0.9500'.
05 FILLER PIC X(10) VALUE '060 1.0000'.
05 FILLER PIC X(10) VALUE '065 1.1000'.
05 FILLER PIC X(10) VALUE '070 1.2500'.
05 FILLER PIC X(10) VALUE '075 1.4000'.
05 FILLER PIC X(10) VALUE '999 1.5000'.
01 WS-AGE-TBL REDEFINES WS-AGE-FACTOR-TABLE.
05 WS-AGE-ENTRY OCCURS 16 TIMES
INDEXED BY WS-AGE-IDX.
10 WS-AGE-LIMIT PIC 9(03).
10 FILLER PIC X(01).
10 WS-AGE-RATE-FACTOR PIC 9V9999.
10 FILLER PIC X(01).
This REDEFINES technique -- defining a table as FILLER values for readability and then redefining it as indexed entries for processing -- is a classic COBOL pattern that you will encounter in virtually every insurance rating system. The threshold approach is efficient because it avoids the need for a separate entry for every possible age from 16 to 100+. A 35-year-old driver falls into the "030-040" range and receives the 0.9500 factor.
35.3.3 The Multi-Step Rating Algorithm
The premium calculation in Example 02 follows a ten-step pipeline that is representative of production rating engines:
2000-PROCESS-REQUESTS.
ADD 1 TO WS-REQUESTS-READ
INITIALIZE WS-CALC-FIELDS
* Step 1: Calculate insured age
PERFORM 3000-CALCULATE-AGE
* Step 2: Look up territory base rate
PERFORM 3100-LOOKUP-BASE-RATE
* Step 3: Apply age rating factor
PERFORM 3200-APPLY-AGE-FACTOR
* Step 4: Apply vehicle symbol factor
PERFORM 3300-APPLY-VEHICLE-FACTOR
* Step 5: Apply deductible factor
PERFORM 3400-APPLY-DEDUCTIBLE-FACTOR
* Step 6: Apply risk class factor
PERFORM 3500-APPLY-RISK-FACTOR
* Step 7: Calculate rated premium
COMPUTE WS-COMBINED-FACTOR ROUNDED =
WS-AGE-FACTOR *
WS-VEHICLE-FACTOR *
WS-DEDUCTIBLE-FACTOR *
WS-RISK-FACTOR
COMPUTE WS-RATED-PREMIUM ROUNDED =
WS-BASE-PREMIUM * WS-COMBINED-FACTOR
* Step 8: Apply discounts
PERFORM 3600-CALCULATE-DISCOUNTS
* Step 9: Apply surcharges
PERFORM 3700-CALCULATE-SURCHARGES
* Step 10: Calculate final premium
COMPUTE WS-FINAL-PREMIUM ROUNDED =
WS-RATED-PREMIUM -
WS-DISCOUNT-AMOUNT +
WS-SURCHARGE-AMOUNT
* Step 11: Apply state min/max rules
PERFORM 3800-APPLY-STATE-LIMITS
* Step 12: Write output
PERFORM 4000-WRITE-OUTPUT
.
Each step is isolated in its own paragraph, making the algorithm easy to trace, test, and modify. When a state regulator changes the age rating table, only the table data and the 3200-APPLY-AGE-FACTOR paragraph need to be reviewed. When a new discount is approved, only 3600-CALCULATE-DISCOUNTS needs to change.
35.3.4 Discounts and Surcharges
The discount calculation in Example 02 demonstrates a pattern where multiple independent discounts are accumulated and then capped at a maximum percentage:
3600-CALCULATE-DISCOUNTS.
* Apply applicable discounts with cap at maximum.
MOVE 0 TO WS-DISCOUNT-AMOUNT
MOVE 1 TO WS-FACTOR-POS
MOVE SPACES TO WS-FACTORS-STRING
IF RR-MULTI-CAR
COMPUTE WS-DISCOUNT-AMOUNT ROUNDED =
WS-DISCOUNT-AMOUNT +
(WS-RATED-PREMIUM * WS-MULTI-CAR-DISC-PCT)
STRING 'MC ' DELIMITED BY SIZE
INTO WS-FACTORS-STRING
WITH POINTER WS-FACTOR-POS
END-IF
IF RR-MULTI-POLICY
COMPUTE WS-DISCOUNT-AMOUNT ROUNDED =
WS-DISCOUNT-AMOUNT +
(WS-RATED-PREMIUM * WS-MULTI-POL-DISC-PCT)
STRING 'MP ' DELIMITED BY SIZE
INTO WS-FACTORS-STRING
WITH POINTER WS-FACTOR-POS
END-IF
IF RR-GOOD-STUDENT
COMPUTE WS-DISCOUNT-AMOUNT ROUNDED =
WS-DISCOUNT-AMOUNT +
(WS-RATED-PREMIUM * WS-GOOD-STUDENT-DISC-PCT)
STRING 'GS ' DELIMITED BY SIZE
INTO WS-FACTORS-STRING
WITH POINTER WS-FACTOR-POS
END-IF
IF RR-SAFE-DRIVER
COMPUTE WS-DISCOUNT-AMOUNT ROUNDED =
WS-DISCOUNT-AMOUNT +
(WS-RATED-PREMIUM * WS-SAFE-DRIVER-DISC-PCT)
STRING 'SD ' DELIMITED BY SIZE
INTO WS-FACTORS-STRING
WITH POINTER WS-FACTOR-POS
END-IF
* Cap discount at maximum percentage
IF WS-DISCOUNT-AMOUNT >
(WS-RATED-PREMIUM * WS-MAX-DISCOUNT-PCT)
COMPUTE WS-DISCOUNT-AMOUNT ROUNDED =
WS-RATED-PREMIUM * WS-MAX-DISCOUNT-PCT
END-IF
.
The discount cap is a regulatory requirement: insurance regulators typically limit the total discount that can be applied to prevent premiums from falling below actuarially sound levels. The WS-FACTORS-STRING field accumulates two-character codes (MC, MP, GS, SD) that record which discounts were applied. This provides an audit trail for regulatory examinations and makes it easy to explain to a policyholder why their premium is what it is.
35.3.5 State Minimum and Maximum Premiums
Every state sets minimum and maximum premiums for each line of insurance. These limits prevent insurers from charging too little (which would indicate insufficient rates to pay claims) or too much (which would constitute price gouging). The state limit enforcement from Example 02 is straightforward:
3800-APPLY-STATE-LIMITS.
* Enforce state minimum and maximum premium rules.
MOVE 00000.00 TO WS-STATE-MIN
MOVE 99999.99 TO WS-STATE-MAX
PERFORM VARYING WS-ST-IDX FROM 1 BY 1
UNTIL WS-ST-IDX > WS-NUM-STATE-ENTRIES
IF WS-ST-CODE(WS-ST-IDX) = RR-STATE-CODE
MOVE WS-ST-MIN-PREM(WS-ST-IDX)
TO WS-STATE-MIN
MOVE WS-ST-MAX-PREM(WS-ST-IDX)
TO WS-STATE-MAX
SET WS-ST-IDX TO WS-NUM-STATE-ENTRIES
END-IF
END-PERFORM
IF WS-FINAL-PREMIUM < WS-STATE-MIN
MOVE WS-STATE-MIN TO WS-FINAL-PREMIUM
END-IF
IF WS-FINAL-PREMIUM > WS-STATE-MAX
MOVE WS-STATE-MAX TO WS-FINAL-PREMIUM
END-IF
.
If the calculated premium falls below the state minimum, it is raised to the minimum. If it exceeds the state maximum, it is reduced to the maximum. These adjustments must be recorded in the audit trail, because regulators frequently review cases where minimum or maximum premiums were applied.
35.4 Claims Processing Workflows
35.4.1 The Claims Lifecycle
Claims processing is the most complex workflow in insurance. A claim begins when a policyholder reports a loss (a car accident, a house fire, a medical procedure) and progresses through multiple stages: first notice of loss, investigation, coverage verification, damage assessment, reserve estimation, negotiation, payment, and closure. Some claims close within days; complex liability claims may remain open for years.
The following COBOL data structure represents a typical claims master record:
01 CLAIMS-MASTER-RECORD.
05 CL-CLAIM-NUMBER PIC X(15).
05 CL-POLICY-NUMBER PIC X(12).
05 CL-CLAIM-STATUS PIC X(02).
88 CL-STATUS-OPEN VALUE 'OP'.
88 CL-STATUS-PENDING VALUE 'PN'.
88 CL-STATUS-APPROVED VALUE 'AP'.
88 CL-STATUS-DENIED VALUE 'DN'.
88 CL-STATUS-CLOSED VALUE 'CL'.
88 CL-STATUS-REOPENED VALUE 'RO'.
88 CL-STATUS-LITIGATION VALUE 'LT'.
05 CL-LINE-OF-BUSINESS PIC X(03).
05 CL-LOSS-DATE PIC 9(08).
05 CL-REPORT-DATE PIC 9(08).
05 CL-CLOSE-DATE PIC 9(08).
05 CL-LOSS-TYPE-CODE PIC X(04).
05 CL-LOSS-DESCRIPTION PIC X(80).
05 CL-CLAIMANT-INFO.
10 CL-CLAIMANT-NAME PIC X(40).
10 CL-CLAIMANT-PHONE PIC X(10).
10 CL-CLAIMANT-RELATION PIC X(02).
88 CL-INSURED VALUE 'IN'.
88 CL-SPOUSE VALUE 'SP'.
88 CL-THIRD-PARTY VALUE 'TP'.
05 CL-ADJUSTER-CODE PIC X(08).
05 CL-FINANCIAL-DATA.
10 CL-RESERVE-AMOUNT PIC 9(09)V99.
10 CL-PAID-AMOUNT PIC 9(09)V99.
10 CL-RECOVERED-AMOUNT PIC 9(09)V99.
10 CL-DEDUCTIBLE-APPLIED PIC 9(07)V99.
10 CL-COVERAGE-LIMIT PIC 9(09)V99.
05 CL-PAYMENT-COUNT PIC 9(03).
05 CL-LAST-ACTIVITY-DATE PIC 9(08).
05 CL-LITIGATION-FLAG PIC X(01).
88 CL-IN-LITIGATION VALUE 'Y'.
05 CL-FRAUD-FLAG PIC X(01).
88 CL-FRAUD-SUSPECTED VALUE 'Y'.
05 CL-CATASTROPHE-CODE PIC X(06).
05 FILLER PIC X(98).
The financial fields in the claims record deserve explanation:
- CL-RESERVE-AMOUNT: The estimated total cost of the claim. Reserves are set when a claim is opened and adjusted as more information becomes available. Aggregate reserves directly affect the company's financial statements.
- CL-PAID-AMOUNT: The total amount paid to date on the claim, including all partial payments.
- CL-RECOVERED-AMOUNT: Money recovered through subrogation (recovering from the at-fault party) or salvage (selling damaged property).
- CL-DEDUCTIBLE-APPLIED: The portion of the loss borne by the policyholder.
- CL-COVERAGE-LIMIT: The maximum the insurer will pay on this claim, drawn from the policy's coverage terms.
35.4.2 Claims Payment Processing
Claims payments are typically processed in batch, with payments accumulated during the day and released in a nightly payment run. The following program demonstrates a claims payment batch process:
IDENTIFICATION DIVISION.
PROGRAM-ID. CLMPAYMT.
*================================================================*
* CLAIMS PAYMENT BATCH PROCESSING *
* Reads approved payment transactions, validates against *
* claims master and policy master, issues payments, and *
* updates reserves. *
*================================================================*
DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-PAYMENT-WORK.
05 WS-NET-PAYMENT PIC 9(09)V99.
05 WS-REMAINING-RESERVE PIC 9(09)V99.
05 WS-TOTAL-PAID-TO-DATE PIC 9(09)V99.
05 WS-COVERAGE-REMAINING PIC 9(09)V99.
PROCEDURE DIVISION.
3000-PROCESS-PAYMENT.
* Validate the claim exists and is open
MOVE PT-CLAIM-NUMBER TO CL-CLAIM-NUMBER
READ CLAIMS-MASTER
INVALID KEY
MOVE 'CLAIM NOT FOUND' TO WS-ERROR-MSG
PERFORM 8000-WRITE-ERROR
GO TO 3000-EXIT
END-READ
IF NOT CL-STATUS-OPEN AND
NOT CL-STATUS-APPROVED AND
NOT CL-STATUS-REOPENED
MOVE 'CLAIM NOT IN PAYABLE STATUS'
TO WS-ERROR-MSG
PERFORM 8000-WRITE-ERROR
GO TO 3000-EXIT
END-IF
* Check coverage limit
COMPUTE WS-TOTAL-PAID-TO-DATE =
CL-PAID-AMOUNT + PT-PAYMENT-AMOUNT
COMPUTE WS-COVERAGE-REMAINING =
CL-COVERAGE-LIMIT - CL-PAID-AMOUNT
IF PT-PAYMENT-AMOUNT > WS-COVERAGE-REMAINING
MOVE WS-COVERAGE-REMAINING
TO WS-NET-PAYMENT
ELSE
MOVE PT-PAYMENT-AMOUNT
TO WS-NET-PAYMENT
END-IF
* Apply deductible on first payment
IF CL-PAYMENT-COUNT = 0 AND
CL-DEDUCTIBLE-APPLIED = 0
IF WS-NET-PAYMENT > PM-DEDUCTIBLE-AMT
SUBTRACT PM-DEDUCTIBLE-AMT
FROM WS-NET-PAYMENT
MOVE PM-DEDUCTIBLE-AMT
TO CL-DEDUCTIBLE-APPLIED
ELSE
MOVE WS-NET-PAYMENT
TO CL-DEDUCTIBLE-APPLIED
MOVE 0 TO WS-NET-PAYMENT
END-IF
END-IF
* Update claim record
ADD WS-NET-PAYMENT TO CL-PAID-AMOUNT
ADD 1 TO CL-PAYMENT-COUNT
* Adjust reserve downward by payment amount
IF CL-RESERVE-AMOUNT > WS-NET-PAYMENT
SUBTRACT WS-NET-PAYMENT FROM CL-RESERVE-AMOUNT
ELSE
MOVE 0 TO CL-RESERVE-AMOUNT
END-IF
MOVE WS-CURRENT-DATE TO CL-LAST-ACTIVITY-DATE
REWRITE CLAIMS-MASTER-RECORD
.
3000-EXIT.
EXIT
.
This payment processing logic enforces several business rules that are common across the insurance industry. The coverage limit check ensures that total payments on a claim never exceed the policy's coverage amount. The deductible is applied on the first payment, reducing the amount the insurer actually pays. The reserve is reduced by the payment amount, keeping the claim's financial picture accurate.
35.5 Actuarial Computations in COBOL
35.5.1 Loss Ratio Calculations
Actuaries evaluate the performance of an insurance portfolio by computing loss ratios -- the ratio of claims paid to premiums earned. A loss ratio above 1.0 means the company is paying more in claims than it is collecting in premiums, which is unsustainable.
The following COBOL code computes loss ratios by line of business:
01 WS-LOSS-RATIO-TABLE.
05 WS-LR-ENTRY OCCURS 5 TIMES.
10 WS-LR-LOB PIC X(03).
10 WS-LR-EARNED-PREM PIC 9(11)V99.
10 WS-LR-INCURRED-LOSS PIC 9(11)V99.
10 WS-LR-LOSS-RATIO PIC 9(01)V9999.
10 WS-LR-EXPENSE-RATIO PIC 9(01)V9999.
10 WS-LR-COMBINED-RATIO PIC 9(01)V9999.
5000-CALCULATE-LOSS-RATIOS.
PERFORM VARYING WS-LR-IDX FROM 1 BY 1
UNTIL WS-LR-IDX > 5
IF WS-LR-EARNED-PREM(WS-LR-IDX) > 0
COMPUTE WS-LR-LOSS-RATIO(WS-LR-IDX) ROUNDED =
WS-LR-INCURRED-LOSS(WS-LR-IDX) /
WS-LR-EARNED-PREM(WS-LR-IDX)
COMPUTE WS-LR-COMBINED-RATIO(WS-LR-IDX)
ROUNDED =
WS-LR-LOSS-RATIO(WS-LR-IDX) +
WS-LR-EXPENSE-RATIO(WS-LR-IDX)
ELSE
MOVE 0 TO WS-LR-LOSS-RATIO(WS-LR-IDX)
MOVE 0 TO WS-LR-COMBINED-RATIO(WS-LR-IDX)
END-IF
END-PERFORM
.
The combined ratio -- loss ratio plus expense ratio -- is the single most important metric in property and casualty insurance. A combined ratio below 1.0 indicates underwriting profit; above 1.0 indicates underwriting loss. These calculations appear in quarterly financial statements, regulatory filings, and reinsurance treaty renewals.
35.5.2 Reserve Development Triangles
Loss reserve development is a core actuarial process. Actuaries track how reserves change over time using a triangular matrix where each row represents an accident year and each column represents a development period. COBOL is well-suited to constructing these triangles because of its two-dimensional table capabilities:
01 WS-LOSS-TRIANGLE.
05 WS-ACCIDENT-YEAR OCCURS 10 TIMES.
10 WS-DEV-PERIOD OCCURS 10 TIMES.
15 WS-CUMULATIVE-PAID PIC 9(11)V99.
15 WS-CUMULATIVE-INCUR PIC 9(11)V99.
15 WS-DEV-FACTOR PIC 9(03)V9999.
01 WS-TRIANGLE-WORK.
05 WS-AY-IDX PIC 9(02).
05 WS-DP-IDX PIC 9(02).
05 WS-IBNR-RESERVE PIC 9(11)V99.
05 WS-ULTIMATE-LOSS PIC 9(11)V99.
5500-CALCULATE-DEVELOPMENT-FACTORS.
* Compute age-to-age development factors
PERFORM VARYING WS-DP-IDX FROM 1 BY 1
UNTIL WS-DP-IDX > 9
MOVE 0 TO WS-FACTOR-SUM
MOVE 0 TO WS-FACTOR-COUNT
PERFORM VARYING WS-AY-IDX FROM 1 BY 1
UNTIL WS-AY-IDX > (10 - WS-DP-IDX)
IF WS-CUMULATIVE-PAID(WS-AY-IDX,
WS-DP-IDX) > 0
COMPUTE WS-DEV-FACTOR(WS-AY-IDX,
WS-DP-IDX) ROUNDED =
WS-CUMULATIVE-PAID(WS-AY-IDX,
WS-DP-IDX + 1) /
WS-CUMULATIVE-PAID(WS-AY-IDX,
WS-DP-IDX)
ADD WS-DEV-FACTOR(WS-AY-IDX,
WS-DP-IDX) TO WS-FACTOR-SUM
ADD 1 TO WS-FACTOR-COUNT
END-IF
END-PERFORM
END-PERFORM
.
The development factor calculation is fundamental to actuarial science. By analyzing how claims develop over time (mature), actuaries can project the ultimate cost of claims that have been reported but not yet fully settled, and estimate reserves for claims that have been incurred but not yet reported (IBNR). These calculations, performed in COBOL batch programs, directly determine the reserves that appear on the company's balance sheet.
35.6 Batch Processing Patterns in Insurance
35.6.1 The Insurance Batch Cycle
Insurance companies rely on extensive batch processing to manage their operations. The typical nightly batch cycle includes:
- Transaction intake: Loading transactions from agents, web portals, and call centers
- Validation: Editing and validating all input transactions
- Policy processing: Applying new business, endorsements, renewals, and cancellations
- Premium billing: Generating invoices and processing payments
- Claims processing: Processing new claims, payments, and reserve changes
- Commission calculation: Computing agent commissions
- Reporting: Generating management reports and regulatory filings
The JCL for Example 01 shows a typical batch job stream for policy administration:
//POLIADMN JOB (ACCT),'POLICY ADMIN',CLASS=A,MSGCLASS=X,
// MSGLEVEL=(1,1),NOTIFY=&SYSUID
//*================================================================*
//* INSURANCE POLICY ADMINISTRATION SYSTEM *
//* EXAMPLE 01 - CHAPTER 35 *
//* *
//* STEP 1: SORT TRANSACTION FILE BY POLICY NUMBER *
//* STEP 2: BACKUP POLICY MASTER FILE *
//* STEP 3: RUN POLICY ADMINISTRATION PROGRAM *
//*================================================================*
//*
//*------------------------------------------------------------*
//* STEP 1: SORT TRANSACTIONS BY POLICY NUMBER *
//*------------------------------------------------------------*
//SORT EXEC PGM=SORT
//SYSOUT DD SYSOUT=*
//SORTIN DD DSN=INSUR.DAILY.TRANS.INPUT,DISP=SHR
//SORTOUT DD DSN=&&SORTRANS,DISP=(NEW,PASS),
// SPACE=(CYL,(5,2)),
// DCB=(RECFM=FB,LRECL=300,BLKSIZE=27000)
//SORTWK01 DD SPACE=(CYL,(10,5))
//SORTWK02 DD SPACE=(CYL,(10,5))
//SORTWK03 DD SPACE=(CYL,(10,5))
//SYSIN DD *
SORT FIELDS=(3,12,CH,A)
INCLUDE COND=(1,2,CH,EQ,C'CR',OR,
1,2,CH,EQ,C'MD',OR,
1,2,CH,EQ,C'RN',OR,
1,2,CH,EQ,C'CN')
/*
//*
//*------------------------------------------------------------*
//* STEP 2: BACKUP POLICY MASTER BEFORE PROCESSING *
//*------------------------------------------------------------*
//BACKUP EXEC PGM=IDCAMS
//SYSPRINT DD SYSOUT=*
//SYSIN DD *
REPRO INFILE(INDD) OUTFILE(OUTDD)
/*
//INDD DD DSN=INSUR.POLICY.MASTER,DISP=SHR
//OUTDD DD DSN=INSUR.POLICY.MASTER.BACKUP,
// DISP=(NEW,CATLG,DELETE),
// SPACE=(CYL,(50,10)),
// DCB=(RECFM=FB,LRECL=500,BLKSIZE=27500)
//*
//*------------------------------------------------------------*
//* STEP 3: RUN POLICY ADMINISTRATION PROGRAM *
//*------------------------------------------------------------*
//POLIADM EXEC PGM=POLIADMN,REGION=64M
//STEPLIB DD DSN=INSUR.PROD.LOADLIB,DISP=SHR
//POLMAST DD DSN=INSUR.POLICY.MASTER,DISP=OLD
//TRANSIN DD DSN=&&SORTRANS,DISP=(OLD,DELETE)
//AUDITRPT DD DSN=INSUR.DAILY.POLIADM.AUDIT,
// DISP=(NEW,CATLG,DELETE),
// SPACE=(CYL,(2,1)),
// DCB=(RECFM=FB,LRECL=132,BLKSIZE=27984)
//ERRRPT DD DSN=INSUR.DAILY.POLIADM.ERRORS,
// DISP=(NEW,CATLG,DELETE),
// SPACE=(CYL,(1,1)),
// DCB=(RECFM=FB,LRECL=132,BLKSIZE=27984)
//SYSOUT DD SYSOUT=*
//SYSPRINT DD SYSOUT=*
//SYSUDUMP DD SYSOUT=*
//*
//*------------------------------------------------------------*
//* STEP 4: PRINT AUDIT REPORT *
//*------------------------------------------------------------*
//PRINT EXEC PGM=IEBGENER
//SYSUT1 DD DSN=INSUR.DAILY.POLIADM.AUDIT,DISP=SHR
//SYSUT2 DD SYSOUT=*,DCB=(RECFM=FBA,LRECL=133)
//SYSIN DD DUMMY
//SYSPRINT DD SYSOUT=*
//
This JCL stream illustrates several important batch processing practices discussed in Chapter 28:
Pre-sort of transactions: The SORT step sorts transactions by policy number and filters for valid transaction types. Sorting by policy number is essential when the COBOL program accesses the VSAM master file in key sequence, which provides optimal I/O performance.
Backup before update: The IDCAMS REPRO step creates a complete backup of the policy master file before any updates are applied. If the update job fails halfway through, the backup allows the operations team to restore the master file to its pre-run state and reprocess.
DISP=OLD for exclusive access: The POLMAST DD statement specifies DISP=OLD, which grants the job exclusive access to the policy master file. This prevents any other job from reading or writing the file during processing, ensuring data integrity.
Temporary dataset for sorted transactions: The sorted transaction file uses a temporary dataset name (&&SORTRANS), which is automatically deleted when the job completes. This avoids cluttering the catalog with intermediate files.
35.6.2 Checkpoint and Restart
Long-running batch jobs in insurance often implement checkpoint and restart logic. If a job that is processing 500,000 renewal transactions fails after processing 300,000, the operations team should be able to restart at transaction 300,001 rather than reprocessing the entire file. The following pattern shows a basic checkpoint mechanism:
01 WS-CHECKPOINT-FIELDS.
05 WS-CHECKPOINT-INTERVAL PIC 9(05) VALUE 10000.
05 WS-RECORDS-SINCE-CKPT PIC 9(05) VALUE 0.
05 WS-LAST-KEY-PROCESSED PIC X(12).
05 WS-CHECKPOINT-COUNT PIC 9(03) VALUE 0.
2000-PROCESS-TRANSACTIONS.
ADD 1 TO WS-RECORDS-SINCE-CKPT
IF WS-RECORDS-SINCE-CKPT >= WS-CHECKPOINT-INTERVAL
PERFORM 2500-TAKE-CHECKPOINT
MOVE 0 TO WS-RECORDS-SINCE-CKPT
END-IF
MOVE TR-POLICY-NUMBER TO WS-LAST-KEY-PROCESSED
.
2500-TAKE-CHECKPOINT.
ADD 1 TO WS-CHECKPOINT-COUNT
DISPLAY 'CHECKPOINT ' WS-CHECKPOINT-COUNT
' AT RECORD ' WS-TRANS-READ
' KEY: ' WS-LAST-KEY-PROCESSED
* In production, this would write a checkpoint
* record to a VSAM file or DB2 table and
* commit any pending database changes.
.
Every 10,000 records, the program records the last key processed. On restart, the program reads the checkpoint file, positions the input file to the next record after the checkpoint, and resumes processing. This pattern is critical for large-scale insurance batch processing where job windows are tight and reruns are expensive.
35.7 Government Benefits Administration
35.7.1 The Scale of Government Systems
The federal government operates some of the largest COBOL systems in the world. The Social Security Administration processes benefits for over 70 million Americans. The Internal Revenue Service processes more than 150 million individual tax returns annually. The Centers for Medicare and Medicaid Services administers health coverage for over 150 million people. State governments run their own massive COBOL systems for unemployment insurance, motor vehicle registration, and vital records.
These systems share characteristics that make COBOL an ideal fit:
- Rule-based processing: Government benefits are determined by statutes that encode complex eligibility rules. COBOL's verbose, explicit syntax maps naturally to statutory language.
- Audit requirements: Government systems must maintain complete audit trails. Every decision -- why a benefit was approved, denied, or adjusted -- must be documented and traceable.
- Massive volumes: Government agencies process transactions measured in the hundreds of millions. Batch processing with COBOL and JCL is the proven approach for these volumes.
- Extreme reliability: Government payment systems cannot fail. Missing a Social Security payment can leave a retiree unable to pay rent. These systems must run without interruption, month after month, year after year.
35.7.2 Social Security Benefit Calculation
Social Security benefits are calculated using a formula defined by federal law. The computation involves determining a worker's Average Indexed Monthly Earnings (AIME) based on their highest 35 years of earnings, then applying a progressive benefit formula to produce the Primary Insurance Amount (PIA).
The following COBOL program demonstrates the PIA calculation:
IDENTIFICATION DIVISION.
PROGRAM-ID. SSACALC.
*================================================================*
* SOCIAL SECURITY BENEFIT CALCULATION *
* Computes Primary Insurance Amount (PIA) from earnings history. *
* Implements the SSA benefit formula with bend points. *
*================================================================*
DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-EARNINGS-HISTORY.
05 WS-ANNUAL-EARNINGS OCCURS 45 TIMES.
10 WS-EARN-YEAR PIC 9(04).
10 WS-EARN-AMOUNT PIC 9(07)V99.
10 WS-EARN-INDEX-FACTOR PIC 9(02)V9999.
10 WS-INDEXED-EARNINGS PIC 9(09)V99.
05 WS-YEARS-OF-EARNINGS PIC 9(02).
01 WS-BENEFIT-CALCULATION.
05 WS-TOP-35-TOTAL PIC 9(11)V99.
05 WS-AIME PIC 9(05)V99.
05 WS-PIA-AMOUNT PIC 9(05)V99.
05 WS-MONTHLY-BENEFIT PIC 9(05)V99.
* 2024 Bend Points (adjusted annually for wage growth)
01 WS-BEND-POINTS.
05 WS-BEND-POINT-1 PIC 9(05)V99
VALUE 01174.00.
05 WS-BEND-POINT-2 PIC 9(05)V99
VALUE 07078.00.
05 WS-PIA-FACTOR-1 PIC 9V9999
VALUE 0.9000.
05 WS-PIA-FACTOR-2 PIC 9V9999
VALUE 0.3200.
05 WS-PIA-FACTOR-3 PIC 9V9999
VALUE 0.1500.
01 WS-SORT-WORK.
05 WS-SORT-TEMP PIC 9(09)V99.
05 WS-SORT-I PIC 9(02).
05 WS-SORT-J PIC 9(02).
05 WS-SORTED-EARNINGS PIC 9(09)V99
OCCURS 45 TIMES.
01 WS-PIA-WORK.
05 WS-PIA-TIER-1 PIC 9(05)V99.
05 WS-PIA-TIER-2 PIC 9(05)V99.
05 WS-PIA-TIER-3 PIC 9(05)V99.
05 WS-REMAINING-AIME PIC 9(05)V99.
PROCEDURE DIVISION.
1000-CALCULATE-PIA.
* Step 1: Index earnings to account for wage growth
PERFORM 1100-INDEX-EARNINGS
* Step 2: Select highest 35 years of indexed earnings
PERFORM 1200-SELECT-TOP-35
* Step 3: Calculate AIME
COMPUTE WS-AIME ROUNDED =
WS-TOP-35-TOTAL / 420
* (35 years x 12 months = 420 months)
* Step 4: Apply PIA formula with bend points
PERFORM 1300-APPLY-BEND-POINTS
* Step 5: Round PIA down to next lower dime
COMPUTE WS-PIA-AMOUNT =
FUNCTION INTEGER(WS-PIA-AMOUNT * 10) / 10
MOVE WS-PIA-AMOUNT TO WS-MONTHLY-BENEFIT
.
1100-INDEX-EARNINGS.
* Multiply each year's earnings by the indexing factor
* to adjust for wage growth since that year.
PERFORM VARYING WS-SORT-I FROM 1 BY 1
UNTIL WS-SORT-I > WS-YEARS-OF-EARNINGS
COMPUTE WS-INDEXED-EARNINGS(WS-SORT-I) ROUNDED =
WS-EARN-AMOUNT(WS-SORT-I) *
WS-EARN-INDEX-FACTOR(WS-SORT-I)
END-PERFORM
.
1200-SELECT-TOP-35.
* Sort indexed earnings in descending order
* and sum the top 35 years.
PERFORM VARYING WS-SORT-I FROM 1 BY 1
UNTIL WS-SORT-I > WS-YEARS-OF-EARNINGS
MOVE WS-INDEXED-EARNINGS(WS-SORT-I)
TO WS-SORTED-EARNINGS(WS-SORT-I)
END-PERFORM
* Simple bubble sort (small table)
PERFORM VARYING WS-SORT-I FROM 1 BY 1
UNTIL WS-SORT-I >= WS-YEARS-OF-EARNINGS
PERFORM VARYING WS-SORT-J FROM 1 BY 1
UNTIL WS-SORT-J >=
WS-YEARS-OF-EARNINGS
IF WS-SORTED-EARNINGS(WS-SORT-J) <
WS-SORTED-EARNINGS(WS-SORT-J + 1)
MOVE WS-SORTED-EARNINGS(WS-SORT-J)
TO WS-SORT-TEMP
MOVE WS-SORTED-EARNINGS(
WS-SORT-J + 1)
TO WS-SORTED-EARNINGS(WS-SORT-J)
MOVE WS-SORT-TEMP
TO WS-SORTED-EARNINGS(
WS-SORT-J + 1)
END-IF
END-PERFORM
END-PERFORM
* Sum the top 35 years
MOVE 0 TO WS-TOP-35-TOTAL
PERFORM VARYING WS-SORT-I FROM 1 BY 1
UNTIL WS-SORT-I > 35 OR
WS-SORT-I > WS-YEARS-OF-EARNINGS
ADD WS-SORTED-EARNINGS(WS-SORT-I)
TO WS-TOP-35-TOTAL
END-PERFORM
.
1300-APPLY-BEND-POINTS.
* The PIA formula is progressive:
* 90% of AIME up to first bend point
* 32% of AIME between first and second bend points
* 15% of AIME above second bend point
MOVE 0 TO WS-PIA-TIER-1
WS-PIA-TIER-2
WS-PIA-TIER-3
IF WS-AIME <= WS-BEND-POINT-1
COMPUTE WS-PIA-TIER-1 ROUNDED =
WS-AIME * WS-PIA-FACTOR-1
ELSE
COMPUTE WS-PIA-TIER-1 ROUNDED =
WS-BEND-POINT-1 * WS-PIA-FACTOR-1
COMPUTE WS-REMAINING-AIME =
WS-AIME - WS-BEND-POINT-1
IF WS-REMAINING-AIME <=
(WS-BEND-POINT-2 - WS-BEND-POINT-1)
COMPUTE WS-PIA-TIER-2 ROUNDED =
WS-REMAINING-AIME *
WS-PIA-FACTOR-2
ELSE
COMPUTE WS-PIA-TIER-2 ROUNDED =
(WS-BEND-POINT-2 -
WS-BEND-POINT-1) *
WS-PIA-FACTOR-2
COMPUTE WS-PIA-TIER-3 ROUNDED =
(WS-AIME - WS-BEND-POINT-2) *
WS-PIA-FACTOR-3
END-IF
END-IF
COMPUTE WS-PIA-AMOUNT ROUNDED =
WS-PIA-TIER-1 +
WS-PIA-TIER-2 +
WS-PIA-TIER-3
.
The Social Security PIA formula is a classic example of government-mandated computation that must be implemented exactly as specified in law. The three-tier progressive formula -- 90 percent of the first $1,174 of AIME, 32 percent of AIME between $1,174 and $7,078, and 15 percent of AIME above $7,078 (using 2024 bend points) -- cannot be approximated or rounded differently than the statute prescribes. The final PIA is rounded down to the next lower dime, not rounded to the nearest cent. This kind of specific rounding rule is common in government systems and is naturally expressed in COBOL.
35.7.3 Benefits Eligibility Determination
Government benefit programs require complex eligibility logic. A typical program must evaluate income, family size, age, disability status, citizenship, residency, and dozens of other criteria. The following code illustrates eligibility determination for a government benefits program:
01 WS-ELIGIBILITY-RECORD.
05 WS-ELIG-APPLICANT-ID PIC X(10).
05 WS-ELIG-AGE PIC 9(03).
05 WS-ELIG-HOUSEHOLD-SIZE PIC 9(02).
05 WS-ELIG-MONTHLY-INCOME PIC 9(07)V99.
05 WS-ELIG-ASSETS PIC 9(09)V99.
05 WS-ELIG-CITIZENSHIP PIC X(01).
88 WS-US-CITIZEN VALUE 'C'.
88 WS-LEGAL-RESIDENT VALUE 'R'.
88 WS-NON-CITIZEN VALUE 'N'.
05 WS-ELIG-DISABILITY-FLAG PIC X(01).
88 WS-DISABLED VALUE 'Y'.
05 WS-ELIG-VETERAN-FLAG PIC X(01).
88 WS-VETERAN VALUE 'Y'.
05 WS-ELIG-STATE-CODE PIC X(02).
01 WS-ELIG-RESULT.
05 WS-ELIGIBLE-FLAG PIC X(01).
88 WS-IS-ELIGIBLE VALUE 'Y'.
88 WS-NOT-ELIGIBLE VALUE 'N'.
05 WS-DENIAL-REASON PIC X(04).
88 WS-DENY-INCOME VALUE 'INC '.
88 WS-DENY-ASSETS VALUE 'ASST'.
88 WS-DENY-CITIZEN VALUE 'CTZN'.
88 WS-DENY-AGE VALUE 'AGE '.
05 WS-BENEFIT-AMOUNT PIC 9(05)V99.
* Federal Poverty Level table (monthly, by household size)
01 WS-FPL-TABLE.
05 FILLER PIC 9(07)V99 VALUE 01255.00.
05 FILLER PIC 9(07)V99 VALUE 01703.33.
05 FILLER PIC 9(07)V99 VALUE 02151.67.
05 FILLER PIC 9(07)V99 VALUE 02600.00.
05 FILLER PIC 9(07)V99 VALUE 03048.33.
05 FILLER PIC 9(07)V99 VALUE 03496.67.
05 FILLER PIC 9(07)V99 VALUE 03945.00.
05 FILLER PIC 9(07)V99 VALUE 04393.33.
01 WS-FPL-TBL REDEFINES WS-FPL-TABLE.
05 WS-FPL-AMOUNT PIC 9(07)V99 OCCURS 8 TIMES.
01 WS-INCOME-LIMIT PIC 9(07)V99.
01 WS-ASSET-LIMIT PIC 9(09)V99
VALUE 2000.00.
01 WS-ASSET-LIMIT-DISABLED PIC 9(09)V99
VALUE 3500.00.
4000-DETERMINE-ELIGIBILITY.
SET WS-IS-ELIGIBLE TO TRUE
MOVE SPACES TO WS-DENIAL-REASON
* Rule 1: Citizenship requirement
IF WS-NON-CITIZEN
SET WS-NOT-ELIGIBLE TO TRUE
SET WS-DENY-CITIZEN TO TRUE
GO TO 4000-EXIT
END-IF
* Rule 2: Income test (130% of Federal Poverty Level)
IF WS-ELIG-HOUSEHOLD-SIZE > 0 AND
WS-ELIG-HOUSEHOLD-SIZE <= 8
COMPUTE WS-INCOME-LIMIT ROUNDED =
WS-FPL-AMOUNT(WS-ELIG-HOUSEHOLD-SIZE)
* 1.30
ELSE
COMPUTE WS-INCOME-LIMIT ROUNDED =
WS-FPL-AMOUNT(8) +
((WS-ELIG-HOUSEHOLD-SIZE - 8) *
448.33 * 1.30)
END-IF
IF WS-ELIG-MONTHLY-INCOME > WS-INCOME-LIMIT
SET WS-NOT-ELIGIBLE TO TRUE
SET WS-DENY-INCOME TO TRUE
GO TO 4000-EXIT
END-IF
* Rule 3: Asset test
IF WS-DISABLED
IF WS-ELIG-ASSETS > WS-ASSET-LIMIT-DISABLED
SET WS-NOT-ELIGIBLE TO TRUE
SET WS-DENY-ASSETS TO TRUE
GO TO 4000-EXIT
END-IF
ELSE
IF WS-ELIG-ASSETS > WS-ASSET-LIMIT
SET WS-NOT-ELIGIBLE TO TRUE
SET WS-DENY-ASSETS TO TRUE
GO TO 4000-EXIT
END-IF
END-IF
* Rule 4: Calculate benefit amount
PERFORM 4100-CALCULATE-BENEFIT
.
4000-EXIT.
EXIT
.
4100-CALCULATE-BENEFIT.
* Benefit amount is the difference between the
* income limit and the household's countable income,
* divided by a state-specific factor.
COMPUTE WS-BENEFIT-AMOUNT ROUNDED =
(WS-INCOME-LIMIT - WS-ELIG-MONTHLY-INCOME)
* 0.30
IF WS-BENEFIT-AMOUNT < 23.00
MOVE 23.00 TO WS-BENEFIT-AMOUNT
END-IF
.
This eligibility determination code demonstrates several patterns common in government COBOL systems. The rules are applied in a specific order, with early exits for disqualifying conditions. The Federal Poverty Level table is used to calculate income limits that vary by household size. Asset limits differ for disabled and non-disabled applicants. The minimum benefit amount of $23.00 is a statutory floor. Every one of these rules traces directly to a section of federal or state law, and COBOL's explicit, self-documenting style makes it straightforward for policy analysts and auditors to verify that the program correctly implements the statute.
35.8 Tax Processing Systems
35.8.1 Tax Calculation in COBOL
The Internal Revenue Service and state tax agencies use COBOL extensively for tax return processing. Tax computation involves bracket-based calculations, deduction phaseouts, credit limitations, and alternative minimum tax computations. The following code demonstrates a federal income tax calculation using the bracket structure:
01 WS-TAX-BRACKETS.
05 WS-BRACKET OCCURS 7 TIMES.
10 WS-BRACKET-LOW PIC 9(07)V99.
10 WS-BRACKET-HIGH PIC 9(07)V99.
10 WS-BRACKET-RATE PIC 9V9999.
10 WS-BRACKET-BASE-TAX PIC 9(07)V99.
01 WS-TAX-WORK.
05 WS-TAXABLE-INCOME PIC 9(09)V99.
05 WS-GROSS-TAX PIC 9(09)V99.
05 WS-TAX-IN-BRACKET PIC 9(09)V99.
05 WS-INCOME-IN-BRACKET PIC 9(09)V99.
05 WS-BRACKET-IDX PIC 9(01).
5000-CALCULATE-FEDERAL-TAX.
MOVE 0 TO WS-GROSS-TAX
PERFORM VARYING WS-BRACKET-IDX FROM 1 BY 1
UNTIL WS-BRACKET-IDX > 7
IF WS-TAXABLE-INCOME >
WS-BRACKET-LOW(WS-BRACKET-IDX)
IF WS-TAXABLE-INCOME <=
WS-BRACKET-HIGH(WS-BRACKET-IDX)
* Income falls within this bracket
COMPUTE WS-INCOME-IN-BRACKET =
WS-TAXABLE-INCOME -
WS-BRACKET-LOW(WS-BRACKET-IDX)
ELSE
* Income exceeds this bracket
COMPUTE WS-INCOME-IN-BRACKET =
WS-BRACKET-HIGH(WS-BRACKET-IDX) -
WS-BRACKET-LOW(WS-BRACKET-IDX)
END-IF
COMPUTE WS-TAX-IN-BRACKET ROUNDED =
WS-INCOME-IN-BRACKET *
WS-BRACKET-RATE(WS-BRACKET-IDX)
ADD WS-TAX-IN-BRACKET TO WS-GROSS-TAX
END-IF
END-PERFORM
.
The progressive tax bracket computation iterates through each bracket, calculating the tax owed on the portion of income that falls within that bracket. This pattern parallels the Social Security PIA calculation -- both are progressive formulas mandated by law. The use of ROUNDED on the tax-in-bracket computation ensures proper cent-level precision, a requirement for tax processing as discussed in Chapter 33.
35.8.2 Withholding and Reporting
Government agencies also process employer-submitted W-2 and 1099 forms, matching reported income against tax returns. This matching program pattern is a classic batch COBOL application:
01 WS-MATCH-COUNTERS.
05 WS-RETURNS-READ PIC 9(09) VALUE 0.
05 WS-W2S-READ PIC 9(09) VALUE 0.
05 WS-MATCHED PIC 9(09) VALUE 0.
05 WS-UNMATCHED-RETURNS PIC 9(09) VALUE 0.
05 WS-UNMATCHED-W2S PIC 9(09) VALUE 0.
05 WS-INCOME-DISCREPANCIES PIC 9(09) VALUE 0.
01 WS-TOLERANCE-AMOUNT PIC 9(05)V99
VALUE 50.00.
6000-MATCH-RETURNS-TO-W2S.
* Both files are sorted by SSN.
* Classic sequential match-merge pattern.
EVALUATE TRUE
WHEN RT-SSN = W2-SSN
* Match found - compare income amounts
COMPUTE WS-INCOME-DIFF =
FUNCTION ABS(
RT-WAGES-REPORTED -
W2-WAGES-REPORTED)
IF WS-INCOME-DIFF > WS-TOLERANCE-AMOUNT
ADD 1 TO WS-INCOME-DISCREPANCIES
PERFORM 6100-WRITE-DISCREPANCY
END-IF
ADD 1 TO WS-MATCHED
PERFORM 6200-READ-RETURN
PERFORM 6300-READ-W2
WHEN RT-SSN < W2-SSN
* Return with no matching W2
ADD 1 TO WS-UNMATCHED-RETURNS
PERFORM 6400-WRITE-UNMATCHED-RETURN
PERFORM 6200-READ-RETURN
WHEN RT-SSN > W2-SSN
* W2 with no matching return
ADD 1 TO WS-UNMATCHED-W2S
PERFORM 6500-WRITE-UNMATCHED-W2
PERFORM 6300-READ-W2
END-EVALUATE
.
This sequential match-merge is a foundational batch processing pattern. Both files must be sorted by the same key (SSN in this case). The program compares keys from each file, advances the file with the lower key, and identifies matches, unmatched returns, and unmatched W-2 forms. The IRS uses this technique to identify tax returns where reported income does not match the income reported by employers, triggering correspondence and potential audits. This merge-matching pattern was also covered in the context of banking reconciliation in Chapter 34.
35.9 Regulatory Compliance Reporting
35.9.1 Insurance Regulatory Filings
Insurance companies must file extensive reports with state insurance departments and the National Association of Insurance Commissioners (NAIC). The most important filing is the Annual Statement, a standardized financial report that includes:
- Balance sheet (assets, liabilities, surplus)
- Income statement (premiums, losses, expenses)
- Schedule of investments
- Loss development triangles by line of business
- Reinsurance summaries
- Risk-based capital calculations
COBOL batch programs extract data from policy, claims, billing, and financial systems and format it according to NAIC specifications. The following excerpt shows how a regulatory report line is constructed:
01 WS-NAIC-SCHEDULE-P.
05 WS-SP-LINE OCCURS 25 TIMES.
10 WS-SP-LOB-CODE PIC X(03).
10 WS-SP-YEAR PIC 9(04).
10 WS-SP-PREM-WRITTEN PIC S9(11)V99.
10 WS-SP-PREM-EARNED PIC S9(11)V99.
10 WS-SP-LOSS-PAID PIC S9(11)V99.
10 WS-SP-LOSS-RESERVE PIC S9(11)V99.
10 WS-SP-LOSS-INCURRED PIC S9(11)V99.
10 WS-SP-EXPENSE PIC S9(11)V99.
7000-GENERATE-SCHEDULE-P.
PERFORM VARYING WS-SP-IDX FROM 1 BY 1
UNTIL WS-SP-IDX > 25
COMPUTE WS-SP-LOSS-INCURRED(WS-SP-IDX) =
WS-SP-LOSS-PAID(WS-SP-IDX) +
WS-SP-LOSS-RESERVE(WS-SP-IDX)
MOVE WS-SP-LOB-CODE(WS-SP-IDX)
TO WS-RPT-LOB
MOVE WS-SP-YEAR(WS-SP-IDX)
TO WS-RPT-YEAR
MOVE WS-SP-PREM-EARNED(WS-SP-IDX)
TO WS-RPT-EARNED-PREM
MOVE WS-SP-LOSS-INCURRED(WS-SP-IDX)
TO WS-RPT-INCURRED-LOSS
* Calculate loss ratio for this line/year
IF WS-SP-PREM-EARNED(WS-SP-IDX) > 0
COMPUTE WS-RPT-LOSS-RATIO ROUNDED =
WS-SP-LOSS-INCURRED(WS-SP-IDX) /
WS-SP-PREM-EARNED(WS-SP-IDX)
END-IF
PERFORM 7100-WRITE-SCHEDULE-P-LINE
END-PERFORM
.
Note the use of signed numeric fields (S9(11)V99) in the regulatory report. Incurred losses can be negative in cases where reserves are reduced or subrogation recoveries exceed paid losses. The signed PICTURE clause ensures that negative values are properly represented in the output.
35.9.2 Government Compliance Standards
Government agencies maintain their own extensive compliance frameworks. Programs processing tax data must comply with IRS Publication 1075, which governs the safeguarding of Federal Tax Information (FTI). Programs processing health data must comply with HIPAA. Programs processing benefits data must comply with the Privacy Act of 1974. Each of these frameworks imposes requirements on how data is stored, accessed, transmitted, and logged.
From a COBOL programming perspective, compliance requirements manifest in several concrete coding practices:
Access logging: Every access to a sensitive record must be logged with the user ID, timestamp, record accessed, and action taken. COBOL programs achieve this by writing to an audit file or calling a logging subprogram after every file I/O operation on protected data.
Data masking: When displaying or printing sensitive data, programs must mask all but the last four digits of Social Security numbers, all but the last four digits of account numbers, and all but the last four characters of policy numbers. The following utility paragraph demonstrates this pattern:
8500-MASK-SSN.
* Mask SSN for display: 123-45-6789 -> ***-**-6789
MOVE '***-**-' TO WS-MASKED-SSN(1:7)
MOVE WS-RAW-SSN(6:4) TO WS-MASKED-SSN(8:4)
.
Encryption at rest: Sensitive fields in COBOL files may be encrypted using calls to system encryption services. On z/OS, this typically involves calling the Integrated Cryptographic Service Facility (ICSF) through a COBOL CALL statement.
35.10 HIPAA and Data Privacy Considerations
35.10.1 HIPAA in Insurance Systems
The Health Insurance Portability and Accountability Act (HIPAA) imposes strict requirements on any system that processes Protected Health Information (PHI). Health insurance COBOL systems must comply with both the Privacy Rule (who can access PHI) and the Security Rule (how PHI must be protected).
In COBOL programs, HIPAA compliance affects system design at multiple levels:
Transaction code sets: HIPAA mandates the use of standard electronic transaction formats for health insurance claims (837), remittance advice (835), eligibility inquiries (270/271), and claim status inquiries (276/277). These are ANSI X12 EDI transactions that COBOL programs must generate and parse. A typical 837 claim transaction might contain hundreds of segments, each with specific formatting rules:
01 WS-837-CLAIM-SEGMENT.
05 WS-837-SEGMENT-ID PIC X(03).
05 WS-837-ELEMENT-SEP PIC X(01) VALUE '*'.
05 WS-837-CLAIM-ID PIC X(20).
05 WS-837-CHARGE-AMOUNT PIC 9(07)V99.
05 WS-837-PLACE-OF-SERVICE PIC X(02).
05 WS-837-DIAGNOSIS-CODE PIC X(08).
05 WS-837-PROCEDURE-CODE PIC X(05).
05 WS-837-MODIFIER PIC X(02).
05 WS-837-SERVICE-DATE PIC 9(08).
05 WS-837-PROVIDER-NPI PIC X(10).
9000-BUILD-837-CLM-SEGMENT.
MOVE 'CLM' TO WS-837-SEGMENT-ID
STRING
WS-837-SEGMENT-ID
WS-837-ELEMENT-SEP
WS-837-CLAIM-ID
WS-837-ELEMENT-SEP
WS-837-CHARGE-AMOUNT
WS-837-ELEMENT-SEP
WS-837-PLACE-OF-SERVICE
DELIMITED BY SIZE
INTO WS-OUTPUT-SEGMENT
.
Minimum necessary standard: HIPAA requires that programs access only the minimum PHI necessary to perform their function. In practice, this means that a COBOL billing program should not read diagnostic codes or treatment details that are irrelevant to billing. System designers enforce this through separate copybooks: a billing copybook exposes only billing-relevant fields, while clinical fields are defined in a separate copybook used only by claims adjudication programs.
Audit trail requirements: HIPAA requires that every access to PHI be logged. Insurance COBOL systems typically implement this through a centralized audit logging subprogram:
8800-LOG-PHI-ACCESS.
MOVE WS-USER-ID TO AL-USER-ID
MOVE WS-PROGRAM-ID TO AL-PROGRAM-ID
MOVE WS-CURRENT-TS TO AL-TIMESTAMP
MOVE CL-CLAIM-NUMBER TO AL-RECORD-KEY
MOVE 'READ' TO AL-ACTION-TYPE
MOVE 'CLAIMS-MASTER' TO AL-FILE-NAME
CALL 'AUDITLOG' USING AUDIT-LOG-RECORD
.
35.10.2 Data Retention and Disposal
Both insurance and government systems must comply with data retention requirements. Insurance policies and claims must be retained for periods ranging from five to thirty years, depending on the line of business and the jurisdiction. Government records have their own retention schedules mandated by the National Archives and Records Administration (NARA).
COBOL batch programs that purge expired records must verify retention requirements before deleting data. A typical purge program checks the record date against the retention period for that record type and writes purged records to an archive file before deletion:
01 WS-RETENTION-TABLE.
05 WS-RET-ENTRY OCCURS 10 TIMES.
10 WS-RET-RECORD-TYPE PIC X(02).
10 WS-RET-YEARS PIC 9(02).
7500-CHECK-RETENTION.
PERFORM VARYING WS-RET-IDX FROM 1 BY 1
UNTIL WS-RET-IDX > 10
IF WS-RET-RECORD-TYPE(WS-RET-IDX) =
WS-RECORD-TYPE
COMPUTE WS-RETAIN-UNTIL =
FUNCTION INTEGER-OF-DATE(
WS-RECORD-DATE) +
(WS-RET-YEARS(WS-RET-IDX) * 365)
IF FUNCTION INTEGER-OF-DATE(
WS-CURRENT-DATE) > WS-RETAIN-UNTIL
SET WS-OK-TO-PURGE TO TRUE
ELSE
SET WS-NOT-OK-TO-PURGE TO TRUE
END-IF
SET WS-RET-IDX TO 10
END-IF
END-PERFORM
.
35.11 Real-Time Policy Queries
35.11.1 CICS Online Inquiry
While the batch processing described in previous sections handles the high-volume operations, insurance companies also need real-time access to policy and claims information. Customer service representatives, agents, and adjusters need to look up policy details, check claim status, and verify coverage in real time. As discussed in Chapters 24 and 25, CICS provides the online transaction processing environment for these inquiries.
The following CICS program demonstrates a real-time policy inquiry:
IDENTIFICATION DIVISION.
PROGRAM-ID. POLINQ.
*================================================================*
* ONLINE POLICY INQUIRY - CICS TRANSACTION *
* Retrieves policy information for display on a 3270 terminal *
* or a web service request. *
*================================================================*
DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-COMMAREA.
05 WS-CA-POLICY-NUMBER PIC X(12).
05 WS-CA-RETURN-CODE PIC 9(02).
88 WS-CA-SUCCESS VALUE 00.
88 WS-CA-NOT-FOUND VALUE 10.
88 WS-CA-ERROR VALUE 99.
01 WS-POLICY-DISPLAY.
05 WS-PD-POLICY-NUM PIC X(12).
05 WS-PD-STATUS PIC X(10).
05 WS-PD-INSURED-NAME PIC X(41).
05 WS-PD-LOB PIC X(12).
05 WS-PD-EFF-DATE PIC X(10).
05 WS-PD-EXP-DATE PIC X(10).
05 WS-PD-COVERAGE PIC $$$,$$$, MATH1 $,$$$,$$9.99.
05 WS-PD-DEDUCTIBLE PIC $$$,$$9.99.
05 WS-PD-AGENT PIC X(08).
05 WS-PD-CLAIMS-COUNT PIC ZZ9.
PROCEDURE DIVISION.
0000-MAIN.
EXEC CICS READ
DATASET('POLMAST')
INTO(POLICY-MASTER-RECORD)
RIDFLD(WS-CA-POLICY-NUMBER)
RESP(WS-CICS-RESP)
END-EXEC
EVALUATE WS-CICS-RESP
WHEN DFHRESP(NORMAL)
PERFORM 1000-FORMAT-DISPLAY
SET WS-CA-SUCCESS TO TRUE
WHEN DFHRESP(NOTFND)
SET WS-CA-NOT-FOUND TO TRUE
WHEN OTHER
SET WS-CA-ERROR TO TRUE
END-EVALUATE
EXEC CICS RETURN
TRANSID('POLQ')
COMMAREA(WS-COMMAREA)
END-EXEC
.
1000-FORMAT-DISPLAY.
MOVE PM-POLICY-NUMBER TO WS-PD-POLICY-NUM
EVALUATE TRUE
WHEN PM-STATUS-ACTIVE
MOVE 'ACTIVE' TO WS-PD-STATUS
WHEN PM-STATUS-CANCELLED
MOVE 'CANCELLED' TO WS-PD-STATUS
WHEN PM-STATUS-EXPIRED
MOVE 'EXPIRED' TO WS-PD-STATUS
WHEN OTHER
MOVE PM-POLICY-STATUS-CODE
TO WS-PD-STATUS
END-EVALUATE
STRING PM-INSURED-FIRST-NAME DELIMITED BY ' '
' ' DELIMITED BY SIZE
PM-INSURED-LAST-NAME DELIMITED BY ' '
INTO WS-PD-INSURED-NAME
EVALUATE TRUE
WHEN PM-LOB-AUTO
MOVE 'AUTOMOBILE' TO WS-PD-LOB
WHEN PM-LOB-HOME
MOVE 'HOMEOWNERS' TO WS-PD-LOB
WHEN PM-LOB-LIFE
MOVE 'LIFE' TO WS-PD-LOB
WHEN PM-LOB-HEALTH
MOVE 'HEALTH' TO WS-PD-LOB
WHEN PM-LOB-COMMERCIAL
MOVE 'COMMERCIAL' TO WS-PD-LOB
END-EVALUATE
MOVE PM-COVERAGE-AMOUNT TO WS-PD-COVERAGE
MOVE PM-ANNUAL-PREMIUM TO WS-PD-PREMIUM
MOVE PM-DEDUCTIBLE-AMT TO WS-PD-DEDUCTIBLE
MOVE PM-AGENT-CODE TO WS-PD-AGENT
MOVE PM-CLAIMS-COUNT TO WS-PD-CLAIMS-COUNT
.
This CICS program illustrates how the same policy master record used in batch processing (section 35.2) is also accessed in real time. The VSAM file is shared between batch and CICS, with CICS using READ-ONLY access during online hours and batch jobs running during off-peak windows. The display formatting logic translates internal codes into human-readable text -- converting 'AUT' to 'AUTOMOBILE' and 'AC' to 'ACTIVE' -- so that customer service representatives can quickly understand the policy's status.
35.12 Government Payment Processing
35.12.1 Payment File Generation
Government agencies generate massive payment files that are transmitted to the Treasury Department for disbursement. Social Security payments, tax refunds, veterans' benefits, and federal employee salaries all flow through similar payment processing pipelines. The following code demonstrates the generation of an ACH payment file for government benefit disbursements:
01 WS-ACH-BATCH-HEADER.
05 WS-ACH-REC-TYPE PIC X(01) VALUE '5'.
05 WS-ACH-SERVICE-CODE PIC X(03) VALUE '220'.
05 WS-ACH-COMPANY-NAME PIC X(16).
05 WS-ACH-COMPANY-ID PIC X(10).
05 WS-ACH-ENTRY-CLASS PIC X(03) VALUE 'PPD'.
05 WS-ACH-DESCRIPTION PIC X(10).
05 WS-ACH-EFF-DATE PIC X(06).
05 WS-ACH-SETTLE-DATE PIC X(03) VALUE SPACES.
05 WS-ACH-ORIGINATOR-CODE PIC X(01) VALUE '1'.
05 WS-ACH-ORIGIN-DFI PIC X(08).
05 WS-ACH-BATCH-NUMBER PIC 9(07).
01 WS-ACH-ENTRY-DETAIL.
05 WS-ACH-DET-REC-TYPE PIC X(01) VALUE '6'.
05 WS-ACH-DET-TRANS-CODE PIC X(02) VALUE '22'.
05 WS-ACH-DET-ROUTING PIC X(09).
05 WS-ACH-DET-ACCOUNT PIC X(17).
05 WS-ACH-DET-AMOUNT PIC 9(10).
05 WS-ACH-DET-INDIV-ID PIC X(15).
05 WS-ACH-DET-INDIV-NAME PIC X(22).
05 WS-ACH-DET-DISC-DATA PIC X(02) VALUE SPACES.
05 WS-ACH-DET-ADDENDA-IND PIC X(01) VALUE '0'.
05 WS-ACH-DET-TRACE-NUM PIC X(15).
01 WS-PAYMENT-TOTALS.
05 WS-PAY-ENTRY-COUNT PIC 9(08) VALUE 0.
05 WS-PAY-TOTAL-AMOUNT PIC 9(12)V99 VALUE 0.
05 WS-PAY-HASH-TOTAL PIC 9(10) VALUE 0.
8000-GENERATE-ACH-PAYMENT.
MOVE BEN-ROUTING-NUMBER
TO WS-ACH-DET-ROUTING
MOVE BEN-ACCOUNT-NUMBER
TO WS-ACH-DET-ACCOUNT
* ACH amounts are in cents, no decimal
COMPUTE WS-ACH-DET-AMOUNT =
BEN-PAYMENT-AMOUNT * 100
MOVE BEN-SSN TO WS-ACH-DET-INDIV-ID
MOVE BEN-NAME TO WS-ACH-DET-INDIV-NAME
ADD 1 TO WS-PAY-ENTRY-COUNT
ADD BEN-PAYMENT-AMOUNT TO WS-PAY-TOTAL-AMOUNT
* Hash total is sum of routing numbers (for validation)
ADD BEN-ROUTING-NUM-9
TO WS-PAY-HASH-TOTAL
WRITE ACH-RECORD FROM WS-ACH-ENTRY-DETAIL
.
The ACH payment format is standardized by NACHA (the National Automated Clearing House Association) and follows a precise fixed-length record layout -- exactly the kind of fixed-format data that COBOL handles naturally. The hash total, computed as the sum of all routing numbers in the batch, provides a simple but effective validation mechanism: if the receiving bank computes a different hash, the file has been corrupted or tampered with. This pattern mirrors the ACH processing described for the banking context in Chapter 34, but applied here to government benefit disbursement.
35.12.2 Case Management Systems
Government agencies use case management systems to track the lifecycle of individual cases -- benefit applications, tax audits, disability determinations, and appeals. These systems maintain a case record that accumulates activity over time:
01 WS-CASE-RECORD.
05 CS-CASE-NUMBER PIC X(12).
05 CS-CASE-TYPE PIC X(02).
88 CS-TYPE-NEW-CLAIM VALUE 'NC'.
88 CS-TYPE-REVIEW VALUE 'RV'.
88 CS-TYPE-APPEAL VALUE 'AP'.
88 CS-TYPE-OVERPAYMENT VALUE 'OP'.
05 CS-CASE-STATUS PIC X(02).
88 CS-STATUS-OPEN VALUE 'OP'.
88 CS-STATUS-PENDING VALUE 'PD'.
88 CS-STATUS-DECIDED VALUE 'DC'.
88 CS-STATUS-CLOSED VALUE 'CL'.
88 CS-STATUS-APPEALED VALUE 'AP'.
05 CS-APPLICANT-SSN PIC X(09).
05 CS-APPLICANT-NAME PIC X(40).
05 CS-OPEN-DATE PIC 9(08).
05 CS-DECISION-DATE PIC 9(08).
05 CS-CLOSE-DATE PIC 9(08).
05 CS-ASSIGNED-EXAMINER PIC X(08).
05 CS-PRIORITY-CODE PIC X(01).
88 CS-PRIORITY-HIGH VALUE 'H'.
88 CS-PRIORITY-NORMAL VALUE 'N'.
88 CS-PRIORITY-LOW VALUE 'L'.
05 CS-DAYS-OPEN PIC 9(04).
05 CS-ACTION-COUNT PIC 9(03).
05 CS-DECISION-CODE PIC X(02).
88 CS-APPROVED VALUE 'AP'.
88 CS-DENIED VALUE 'DN'.
88 CS-PARTIAL VALUE 'PT'.
05 CS-BENEFIT-AMOUNT PIC 9(07)V99.
05 CS-NOTES-COUNT PIC 9(03).
05 FILLER PIC X(50).
Case management programs generate aging reports that track how long cases have been open. Government agencies are often required by law to make decisions within specified timeframes -- the Social Security Administration, for example, must process initial disability claims within a target period. The aging report helps managers identify cases that are approaching their deadline:
8200-CALCULATE-CASE-AGING.
COMPUTE CS-DAYS-OPEN =
FUNCTION INTEGER-OF-DATE(WS-CURRENT-DATE) -
FUNCTION INTEGER-OF-DATE(CS-OPEN-DATE)
EVALUATE TRUE
WHEN CS-DAYS-OPEN > 180
ADD 1 TO WS-OVER-180-COUNT
PERFORM 8210-FLAG-OVERDUE
WHEN CS-DAYS-OPEN > 90
ADD 1 TO WS-OVER-90-COUNT
WHEN CS-DAYS-OPEN > 60
ADD 1 TO WS-OVER-60-COUNT
WHEN CS-DAYS-OPEN > 30
ADD 1 TO WS-OVER-30-COUNT
WHEN OTHER
ADD 1 TO WS-UNDER-30-COUNT
END-EVALUATE
.
35.13 Medicare and Health Benefits Processing
35.13.1 Medicare Claims Adjudication
Medicare claims processing is one of the largest COBOL applications in the world. The Centers for Medicare and Medicaid Services (CMS) processes over 1 billion claims per year through a network of Medicare Administrative Contractors (MACs), all running COBOL-based claims adjudication systems.
Medicare claims adjudication involves matching procedure codes against coverage rules, applying fee schedules, checking for duplicate claims, coordinating benefits with other insurance, and applying patient cost-sharing (deductibles, coinsurance, and copayments):
01 WS-MEDICARE-CLAIM.
05 MC-CLAIM-NUMBER PIC X(15).
05 MC-BENEFICIARY-HIC PIC X(12).
05 MC-PROVIDER-NPI PIC X(10).
05 MC-SERVICE-DATE PIC 9(08).
05 MC-PROCEDURE-CODE PIC X(05).
05 MC-DIAGNOSIS-CODES.
10 MC-DIAG-CODE PIC X(08)
OCCURS 12 TIMES.
05 MC-BILLED-AMOUNT PIC 9(07)V99.
05 MC-ALLOWED-AMOUNT PIC 9(07)V99.
05 MC-DEDUCTIBLE-APPLIED PIC 9(05)V99.
05 MC-COINSURANCE-AMOUNT PIC 9(05)V99.
05 MC-MEDICARE-PAYS PIC 9(07)V99.
01 WS-PART-B-DEDUCTIBLE PIC 9(05)V99
VALUE 00240.00.
01 WS-PART-B-COINSURANCE PIC 9V99
VALUE 0.20.
01 WS-YTD-DEDUCTIBLE-MET PIC 9(05)V99.
9200-ADJUDICATE-PART-B-CLAIM.
* Look up allowed amount from fee schedule
PERFORM 9210-LOOKUP-FEE-SCHEDULE
* Apply deductible (if not yet met for the year)
IF WS-YTD-DEDUCTIBLE-MET < WS-PART-B-DEDUCTIBLE
COMPUTE MC-DEDUCTIBLE-APPLIED =
FUNCTION MIN(
MC-ALLOWED-AMOUNT,
(WS-PART-B-DEDUCTIBLE -
WS-YTD-DEDUCTIBLE-MET))
ADD MC-DEDUCTIBLE-APPLIED
TO WS-YTD-DEDUCTIBLE-MET
ELSE
MOVE 0 TO MC-DEDUCTIBLE-APPLIED
END-IF
* Calculate coinsurance (20% of allowed amount
* after deductible)
COMPUTE MC-COINSURANCE-AMOUNT ROUNDED =
(MC-ALLOWED-AMOUNT - MC-DEDUCTIBLE-APPLIED)
* WS-PART-B-COINSURANCE
* Medicare payment = Allowed - Deductible - Coinsurance
COMPUTE MC-MEDICARE-PAYS ROUNDED =
MC-ALLOWED-AMOUNT -
MC-DEDUCTIBLE-APPLIED -
MC-COINSURANCE-AMOUNT
IF MC-MEDICARE-PAYS < 0
MOVE 0 TO MC-MEDICARE-PAYS
END-IF
.
This adjudication logic implements the standard Medicare Part B payment formula: the allowed amount (determined by a fee schedule) minus the annual deductible (if not yet met) minus 20 percent coinsurance. The FUNCTION MIN intrinsic ensures that the deductible applied does not exceed the allowed amount -- if a claim's allowed amount is $50 and the beneficiary has $100 of deductible remaining, only $50 of deductible is applied to that claim. These calculations, applied to over a billion claims per year, must be exact to the penny.
35.14 Connecting the Concepts
35.14.1 Shared Patterns Across Insurance and Government
Throughout this chapter, you have encountered several patterns that recur in both insurance and government COBOL systems:
Table-driven processing: Both premium rating (section 35.3) and tax bracket computation (section 35.8) use tables to drive calculations. This approach separates business rules (the table data) from processing logic (the table lookup code), making it easy to update rules without modifying programs.
Progressive formulas: The Social Security PIA formula (section 35.7) and the federal tax bracket computation (section 35.8) both apply different rates to different tiers of a base amount. This progressive structure appears throughout government and insurance systems.
Sequential match-merge: The tax return matching program (section 35.8) uses the same sorted-file match-merge pattern that appears in banking reconciliation (Chapter 34) and insurance claims processing.
Audit trail generation: Every program in this chapter writes audit records. In insurance, audit trails satisfy regulatory examiners. In government, they satisfy both internal auditors and public accountability requirements.
Checkpoint and restart: Long-running batch jobs in both sectors implement checkpoint logic to enable efficient restart after failures, as discussed in section 35.6.
35.14.2 Cross-References to Other Chapters
The topics in this chapter build directly on concepts from earlier chapters:
-
Chapter 33 (Financial Calculations): The decimal arithmetic principles, rounding rules, and COMPUTE statement usage demonstrated throughout this chapter follow directly from the financial calculation techniques covered in Chapter 33. Premium calculations, benefit computations, and tax bracket logic all depend on the precise decimal arithmetic that COBOL provides natively.
-
Chapter 34 (Banking and Payment Systems): The ACH payment generation in section 35.12 uses the same NACHA file format described in Chapter 34. The sequential match-merge pattern used for tax return matching is the same technique used for bank reconciliation. The VSAM file handling patterns in the policy administration system mirror the account master file techniques from banking.
-
Chapter 28 (Batch Processing): The JCL job streams, checkpoint/restart logic, and batch processing patterns in section 35.6 apply the batch processing principles covered in Chapter 28 to the specific requirements of insurance and government systems.
-
Chapters 24-25 (CICS): The online policy inquiry program in section 35.11 applies CICS concepts from Chapters 24 and 25 to the insurance domain, demonstrating how the same data structures serve both batch and online processing.
What You Have Learned
This chapter has covered the extensive use of COBOL in insurance companies and government agencies -- two sectors where the language's strengths in decimal arithmetic, batch processing, and regulatory compliance are indispensable. Here is a summary of the key concepts and skills you have acquired:
Insurance Policy Administration: You learned how policy master records are structured using VSAM KSDS files with indexed access, how transactions drive the policy lifecycle (creation, endorsement, renewal, and cancellation), and how audit trails are maintained for every policy change. You saw how level-88 condition names make policy status checking readable and how the EVALUATE statement dispatches different transaction types to appropriate processing paragraphs.
Premium Calculation Engines: You studied the table-driven rating approach that is the foundation of insurance premium computation. You learned how base rates are looked up by territory and coverage type, how rating factors for age, vehicle, deductible, and risk class are applied multiplicatively, how discounts and surcharges are accumulated with regulatory caps, and how state minimum and maximum premiums are enforced. You saw how the REDEFINES clause enables readable table initialization while supporting efficient indexed access.
Claims Processing: You examined the claims master record structure, the claims payment workflow with coverage limit enforcement and deductible application, and how reserve amounts are adjusted as payments are made. You learned that claims processing involves the most complex business logic in insurance, combining coverage verification, damage assessment, and payment authorization.
Actuarial Computations: You explored loss ratio calculations and reserve development triangles -- two fundamental actuarial tools that COBOL programs compute in batch. You learned how two-dimensional COBOL tables represent development triangles and how age-to-age factors are calculated to project ultimate losses.
Batch Processing Patterns: You studied the insurance batch cycle, including the JCL job stream for policy administration with pre-sort, backup, processing, and reporting steps. You learned the checkpoint and restart pattern that enables recovery from mid-job failures without reprocessing the entire file.
Government Benefits Administration: You implemented the Social Security PIA formula with its three-tier progressive structure and earnings indexing. You built an eligibility determination program that applies income tests, asset tests, and citizenship requirements according to statutory rules. You saw how the Federal Poverty Level table drives income limit calculations.
Tax Processing: You learned how progressive tax bracket computations work in COBOL, iterating through brackets and accumulating tax amounts. You studied the sequential match-merge pattern used to compare tax returns against W-2 forms for income verification.
Regulatory Compliance Reporting: You examined how COBOL programs generate NAIC regulatory filings for insurance companies, including Schedule P loss development data with signed numeric fields for negative values.
HIPAA and Data Privacy: You learned how HIPAA requirements affect COBOL program design in health insurance systems, including ANSI X12 EDI transaction generation, minimum necessary data access through separate copybooks, PHI access audit logging, and data masking for sensitive identifiers.
Real-Time Policy Queries: You saw how CICS programs provide online access to the same policy master records used in batch processing, formatting internal codes into human-readable displays for customer service representatives.
Government Payment Processing: You studied ACH payment file generation for government benefit disbursements, including the fixed-format record layouts mandated by NACHA, hash total validation, and the payment control totals that ensure every dollar is accounted for.
Case Management: You examined government case tracking systems with aging report logic that helps agencies meet statutory decision deadlines.
These insurance and government systems represent some of the most critical COBOL applications in operation today. They process trillions of dollars annually, serve hundreds of millions of people, and must operate with absolute precision and reliability. The patterns you have learned in this chapter -- table-driven rating, progressive benefit formulas, transaction-driven master file updates, batch processing with checkpoint/restart, regulatory compliance reporting, and real-time inquiry -- form the foundation of COBOL programming in these vital sectors. In Chapter 36, you will turn to another major domain of COBOL in financial systems: accounting and general ledger processing, where you will see how the double-entry bookkeeping principles that underpin all financial reporting are implemented in COBOL programs that produce the financial statements on which businesses and regulators depend.