Tutorial, Part 2¶
Directory Structure¶
The modeling framework is self-contained and (once setup is complete) everything it needs can be found within its own directory structure.
\.idea
This directory contains various PyCharm project files. It serves two main functions:
Indicates that this directory contains a PyCharm project, and can be opened in PyCharm as a project.
Defines project parameters, including things like directory structure, interpreter options, run configurations, etc…
Note
If you’ve used Visual Studio before, this directory is analogous to Visual Studio’s *.msproj file.
\docs
Contains source files, images, and other resources used to compile this documentation.
\install
Contains the requirements.txt file, which contains a list of 3rd party Python module dependencies. The requirements.txt file can be used by pip to install dependencies.
\log
Holds log files for each model run, generated at runtime.
\output
Holds model output, generated at runtime.
\resource
Holds model input files, like:
Model points
Economic scenarios
Model assumptions
\src
This is the meat and potatoes of the modeling framework. It contains:
Modeling framework logic and source code.
Models and model logic built on top of the modeling framework.
\venv
Contains the Python virtual environment created in step 5 of the installation instructions.
Object Model¶
The modeling framework consists of four core building blocks, built using classes:
![digraph {
edge [dir="back"];
node [fontname="Arial", shape="Box"];
"(4) Projection" -> "(2) Projection Entity";
"(3) Projection Values" -> "(1) Data Sources" [style=dashed];
"(2) Projection Entity" -> "(1) Data Sources" [style=dashed];
"(2) Projection Entity" -> "(3) Projection Values";
}](_images/graphviz-f45471ded43b6d68fc424013dee142ee40f1bef1.png)
About classes...
The Object Model is implemented in Python using classes. Classes are programming constructs that serve as blueprints for objects.
Here’s a simple class that models a bank account:
1class Account:
2
3 _balance: float # Declare the data type for the "_balance" attribute
4
5 def __init__(
6 self
7 ):
8
9 self._balance = 0.0 # Declare the "_balance" attribute and set the initial value to zero
10
11 def deposit(
12 self,
13 amount: float
14 ) -> None:
15
16 self._balance += amount # Increment the "_balance" attribute by the "amount"
The Account class consists of two attributes:
Line 9,
_balance- An account balance.Line 11,
deposit- A function (or method) calleddepositthat increases the_balanceby a givenamount.
Note that the class is a blueprint for an object. To use the class, we have to create an instance of the class. For example:
chase_account = Account()
wells_fargo_account = Account()
bank_of_america_account = Account()
In the code block above, we’ve created three different accounts using the Account blueprint,
where each account can maintain and track its own balance. The difference between a class and an
instance is analogous to the difference between a blueprint of a house and an actual, physical
house. One blueprint may yield many different houses.
Once we’ve created an instance, we can access attributes using “dot” notation. For example, to
call the deposit method and deposit $500.00 to the Chase account:
chase_account.deposit(
amount=500.0
)
Lastly, some additional notes on classes:
The __init__ method in line 5 is a type of special method called a constructor. It is automatically called whenever a new instance is created. This special method is often used to set initial values for any instance attributes.
The
selfkeyword denotes that an attribute is unique for each instance of a class, or operates on attributes that are unique for each instance of a class.
Classes are an invaluable tool for developers and we’ve only covered the basics here. There are many, many more class mechanics and nuances that are outside the scope of this tutorial.
(1) Data Sources
A
data sourceis a definition that provides access to external model data. For example:Model points, contained in a *.csv file.
Model assumptions, contained in a *.json file.
Market data, contained in a Snowflake database.
It provides this functionality in two ways:
![digraph {
node [fontname="Arial"];
rankdir="LR";
ExternalData [label="External Data" shape="folder"];
Cache [shape="cylinder"];
my_access_cache_method [shape="none" fontname="consolas"];
my_other_access_cache_method [shape="none" fontname="consolas"];
ExternalData -> Cache;
Cache -> my_access_cache_method;
Cache -> my_other_access_cache_method;
}](_images/graphviz-8b14e64921056c2d5a175f9c6fe58d3ee7fe9d10.png)
When the model runs, data for each data source is loaded into an internal cache.
The model developer defines methods to access data from the cache. This allows other objects in the object model to access the cache without having to navigate the internal structure of the cache.
Passing multiple data sources throughout the model is cumbersome, so the model developer aggregates individual data sources into a single
data sources rootobject, which is then passed around the model:![digraph {
node [fontname="Arial"];
rankdir="LR";
DataSourcesRoot [shape="folder"];
DataSource1 [shape="cylinder"];
DataSource2 [shape="cylinder"];
DataSource3 [shape="cylinder"];
DataSource1 -> DataSourcesRoot;
DataSource2 -> DataSourcesRoot;
DataSource3 -> DataSourcesRoot;
}](_images/graphviz-bddc9ca92cfc272a995dfc23392be883c52a7598.png)
Data sources can also be nested using
namespacesandcollections. That is, data sources can contain other data sources. For example:A model point data source might contain data sources for individual people and contracts.
A market data data source might contain data sources that point to external feeds, like Bloomberg or Treasury.gov.
Data sources are typically used:
To set initial values for projection values within projection entities.
To provide data for projection entities while a projection is running.
(2) Projection Entities
A
projection entityis anything that can be projected forwards in time. For example:An insurance contract.
A person.
Projection entities contain (3) projection values.
Projection valuestrack and store the future states of a projection entity. For example:- An insurance contract might have:
A premium payment.
A cash surrender value.
- A person might have:
An attained age.
A marital status.
Projection entities also define methods that operate on projection values. For example:
- An insurance contract might define:
A premium payment method, which adds a premium payment to the contract.
A surrender method, which triggers a surrender calculation and benefit release.
- A person might define:
A death method, which triggers a death benefit calculation and benefit release on a life insurance product.
A marriage method, which alters the marital status.
Projection entities can also be nested. That is, projection entities can contain other projection entities. For example:
- An insurance contract might have:
Riders.
Sub-accounts.
- A person might have:
A cat.
(4) Projections
A
projectionis composed of projection entities. For example, a life insurance projection might consist of:A life insurance contract.
A covered person.
An economic index that drives the life insurance contract’s account value growth.
A projection connects projection entities together, defining a logical sequence of projection entity method calls within a single time period.
The projection will then execute the sequence over and over again across a specified number of time periods, calculating and updating projection values as it goes along.
Once the projection completes, it will print all projection values.