OOP Approach to Actuarial Modeling
Object-Oriented Programming ("OOP") is a programming paradigm that is widely adopted by software engineers. OOP has been around for over five decades since the initial concept was invented in 1960s. Nowadays, pretty much all modern programming languages support OOP.
Programming also plays a big part in many actuaries' work. Some actuaries may write VBA(Visual Basic for Application) codes for Excel application or write scripts in a commercial actuarial software. Others may use R or Python to analyze data. However, actuaries don't seem to pay much attention to OOP.
In this article, I will demonstrate how actuaries can apply OOP methodology to life insurance actuarial modeling. In particular, I will explain how we can build complex actuarial models based on the four principles of OOP and why we can benefit from them. The four OOP principles are: Encapsulation, Abstraction, Inheritance, and Polymorphism.
Object in Actuarial Modeling
An Object can be considered as a conceptual entity in a software. A programming solution consists of may objects. Each object has its own characteristics and behaviors. The characteristics of an object are referred to as properties. Different objects interact with each other by passing messages around. An object receives messages via predefined methods and react accordingly. The final solution is the result of interaction and collaboration among all objects.
How do we apply the concept of object to actuarial modeling? An actuarial model consists of many model components, including products, assumptions, policies, reinsurance treaties, etc. We can think of each model component an object with its own characteristics (properties) and behaviors (methods). When they work together in a certain way, they generate model solutions.
When applying OOP to actuarial modeling, effective design and implementation of model component is the most crucial task. The above four principles provide guidance for the best practice.
Principle #1: Encapsulation
Encapsulation principle stipulates that an object shall keep implementation details strictly private within its own definition. No other objects can have direct access to those details. The only way to communicate or interact with an object is via the methods that are made available by that object.
Take modeling of an insurance product as an example. Properties of an insurance product include term of contract, premium rates, commission schedule, benefit structure, etc. These features shall be implemented inside the definition of the product object. No other objects can change those properties directly. The product may provide a method that, when interacting with a policy object, returns the projected premiums, commissions and death benefit during the coverage period of the policy. Since all product features and projection calculation algorithms are encapsulated inside the product object, they are protected from unintended change by other objects. This also guarantees that the same set of business rules of the product will apply everywhere in a consistent manner.
Because implementation details are encapsulated within an object, this allows more focused design and development. In a team environment, encapsulation also facilitates division and specialization of work. For example, team members specialized in products can focus on implementation of product objects, while team members specialized in experience analysis can focus on implementation of assumption objects.
Principle #2: Abstraction
Abstraction principle is an extension of principle #1. With encapsulation, calling a method is the only way to communicate or interact between two objects. Since the implementation details of an object are kept hidden from other objects, the communication interface provided by an exposed method shall be high-level, meaning that an object's ability to call a method shall not rely on any knowledge regarding the internal details of another object. This is called abstraction.
Application of abstraction principle can be illustrated by an example of designing a mortality assumption object. The purpose of mortality assumption is to generate a set of mortality rates based on the risk factors of an insured so that the mortality rates can be used for cash flow projection or reserve calculation. However, inside a mortality assumption object, there can be different ways to model probability of death. It may be based on an attained age mortality table, a select and ultimate mortality table or a continuous survival distribution model. The algorithm for generating mortality rates will vary by the underlying probability model in the assumption. However, as far as cash flow projection or reserve calculation is concerned, the underlying probability model is not important as long as the calculation procedures can obtain proper mortality rates by calling the method provided by the assumption. Therefore, the method provided by the assumption object shall have an interface that is irrelevant to the internal implementation of the assumption.
The biggest benefit of abstraction principle is in management of code changes. An actuarial model can be in a state of constant change due to change in calculation algorithm, code improvement or bug fixing. If a method provided by an object has an external-facing interface that is independent of the object's internal implementation, any code changes inside the object will not likely to change the method interface. Therefore, in case there is any code change in one object, other objects that interact with it can continue calling the same method in the same way without any modification. Adoption of abstraction principle will make the management of code changes a lot more efficient than otherwise.
Principle #3: Inheritance
In the implementation of an actuarial model, we frequently encounter similarities among model components. One of the most common examples is implementation of products. Many insurance products are similar in terms of product features and business rules. Inheritance principle allows us to take advantage of the similarities among objects and reduce codes drastically.
By analyzing the characteristics of a group of modeling components, we are able to identify what logic is common among those objects and what is unique to each of them. We can create a parent-child hierarchical relationship of those objects. We implement the common logic in parent objects and unique logic in child objects. Child objects will automatically inherit common logic from their parents.
Take product implementation as an example. Suppose we want to implement a block of term products consisting of a level term and a decreasing term. Assume that the characteristics of these two products are similar in every way except death benefit. With inheritance, we can implement level term as the parent and make decreasing term the child. When implementing the decreasing term, we only need to write codes to implement the decreasing death benefit. All other features will be automatically inherited from its level term parent. Codes that work for the inherited features and implemented in level term will continue working in decreasing term.
Inheritance principle requires thorough analysis of similarities and differences among model components, but the benefit is enormous. Effective implementation of inheritance relationship will improve code reusability and shorten development time significantly.
Principle #4: Polymorphism
Polymorphism can be literally translated to many forms. In the context of programming, polymorphism means that a procedure has the ability to process different types of objects if an inheritance relationship exists among those objects.
When applying to actuarial modeling, polymorphism can be explained by using the previous term insurance example. Assume that we have a block of term insurance policies consisting of level term and decreasing term. We want to calculate the reserve of each policy. With polymorphism, because the level term and the decreasing term have a parent-child inheritance relationship, we can use one set of codes to calculate the reserves for these two different types of policies. The seriatim calculation will be carried out correctly without knowing which policy is level term and which policy is decreasing term. The programming language automatically takes care of the projection of the right death benefit according to the product type.
Polymorphism allows us to increase code reusability, reduce implementation time and make the modeling process more efficient. In a non-OOP paradigm, the procedures would have been in whole or in part different for different types of objects even if they were similar.
Summary of OOP Benefits
Building a complex actuarial model is a daunting exercise. Object-oriented programming approach can simplify the development and make the modeling process efficient and easy to manage.
Encapsulation, abstraction, inheritance and polymorphism are the four key principles of object-oriented programming approach. Encapsulation and abstraction enable division of work and more focused development. They also make the management of code changes more efficient. All of these benefits are particularly crucial in a teamwork environment.
On the other hand, inheritance and polymorphism can significantly reduce the amount of codes, increase code reusability and shorten development time.
The benefits of the four OOP principles are summarized in the following table:
|OOP Principle||Benefit to Actuarial Modeling|
|Encapsulation & Abstraction|
|Inheritance & Polymorphism|
Choice of Programming Language
I have argued that actuaries can benefit enormously by implementing an object-oriented approach in actuarial modeling from a conceptual perspective. In reality, what programming language shall we use for actuarial modeling?
There is no single answer. Choice of programming language involves both technical and non-technical considerations. Most modern programming languages are OOP capable. Technical considerations include syntax design, performance, operating platforms, etc. Every language has strengths and weaknesses when applying to actuarial modeling. If you are already familiar with one of such languages, your choice will likely be straightforward.
Non-technical considerations are subjective. One of my most important considerations is portability of programming skill. Mastering a programming language requires a lot of effort. In the end, we are actuaries, not professional programmers. We want to learn and use a language that can be applied to as many actuarial practice areas as possible. I have chosen R programming language to develop objected-oriented actuarial models for several years. If you are interested, please see my post explaining why I think that R is an ideal tool for actuarial modeling. (Life Insurance Actuarial Modeling with R)
Actuaries in different situations may have different views. Any choice that suits you well is the right choice.