MR Fortran Finance Library (MRFFL)
Primary Documentation
| Author: | Mitch Richling |
| Updated: | 2025-11-06 09:22:50 |
| Generated: | 2025-11-06 09:22:52 |
Copyright © 2025 Mitch Richling. All rights reserved.
Table of Contents
1. Introduciton
The functionality powering the programs published in the FortranFinance repository is contained in the MR Fortran Finance Library (MRFFL). MRFFL is a collection of Fortran modules that include advanced TVM solver computations, cashflow stream analysis, US tax calculations, and some monte carlo capabilities (US interest rates & US stock market returns).
API documentation may be found here: MR Fortran Finance Library (MRFFL) API Documentation
The TVM solvers differs from other TVM software I've used in that both annuities (level/geometric/arithmatic) and lump sums are generalized. Annuity payments can stop and start on arbitrary period boundaries within the term. Similarly, lump sums can occur at any payment boundary. This means the solvers can handle a variety of lump sum & annuity types (due, ordinary, delayed, early ending). Together this allows one to solve some difficult, non-standard TVM problems.
The cashflow stream module uses a similar generalization in that cashflows can be placed at any period boundary. This eliminates the need to treat the cashflow at time zero as special. It also eliminates the need to bother with that BEGIN or END mode nonsense. Without these complications we can group cashflow sequences together without worry about the mode of each or period alignment issues that plague some other cashflow software. The module includes cashflow series builders using the same notation and variables as the TVM solvers allowing one to use the TVM solvers to find necessary values, and then use the same variables to populate a cashflow that can be further analyzed or printed.
2. MRFFL (MR Fortran Finance Library) Modules
- Financial applications
mrffl_config- Contains parameters used to configure the rest of the modules.
mrffl_cashflows- TVM problems involving cash flows.
mrffl_life_table- Life table computations and some US life table data.
mrffl_percentages- Working with percentages
mrffl_tvm12- Classic financial calculator style TVM solver and amortization.
mrffl_tvm- TVM solvers for: deferred lump sums and generalized level/geometric/arithmatic annuities.
mrffl_us_inflation- Historical US inflation data. Adjust values across years. Random inflation generation via resampling.
mrffl_us_markets- Historical stock market annual return data. Includes random return generation via resampling.
mrffl_us_taxes- Basic US tax information and computation for filing joint or single.
mrffl_prt_sets- Constants to specify things to print (used by
*_printroutines) mrffl_var_sets- Constants to specify variables (used by TVM solvers to specify unknown variables)
- Support Modules
mrffl_solver- Solves equations using bisection – used by the TVM solvers in the
tvm&tvm12modules. mrffl_stats- Statistics stuff – resamplers, random variables (gamma & log-gamma), etc…
mrffl_bitset- Bitsets used by TVM solvers for unknown variables.
3. Example Programs
You will find several programs, most of which use MRFFL, in various directories at the base of the FortranFinance repository:
- Examples:
cashflows- Some simple MRFFL cashflow examples.
loans- Illustrates how to use MRFFL TVM solvers in combination with cashflow series.
monte_carlo- Illustrates basic resampling monte carlo for inflation and stock market returns.
retirement- Some TVM based retirement computations.
retirement_simulation- A comprehensive simulator for a married couple's retirement
In addition, the unit & functional tests in the MRFFL directory can provide some insight into the usage of MRFFL:
- Tests:
MRFFL/functional_tests- Functional tests for MRFFL. While these are basic MRFFL tests, they also demonstrate the API.
MRFFL/unit_tests- Unit (well unit-like) tests for MRFFL. These also demonstrate the API; however, they can be a bit complex.
I keep my development environment pretty generic. On Linux & MSYS2 I use the native package manager to install development tools in the standard directories
whenever possible. For commercial compilers I use the vendor provided installer with the default settings. I suspect the GNU Make build system provided with
MRFFL may work out of the box on many systems. In particular, it may be entirely possible for someone on Linux or MSYS2 using GNU Fortran (gfortran), to
build examples with something like this:
cd cashflows/ # Change directory into one of the example directories (cashflows/ in this instance) make all # Build everything
If the above doesn't work, then some manual configuration may be necessary.
The compiler can be changed to one of flang, gfortran, ifx, lfortran, or nvfortran by setting the FCOMP variable. For example, we can use the
Intel compiler like this:
cd cashflows/ # Change directory into one of the example directories (cashflows/ in this instance) make FCOMP=ifx all # Build everything
See the section on setup configuration for a more persistent method of setting the compiler than providing it on the command line every time.
4. Build & R Setup
The project uses a couple of central configuration files to set some global behavior:
- Files:
setup.R- Configure R
- Load R packages
- Decide if generated images should be displayed in an image viewer
- Set preferred image viewer
setup.mk- Configure GNU Make (the build system)
- Configure the semi-automatic fortran compiler setup system and run it
- Manually configure the fortran compiler
- Configure MRFFL targets to make it easy to compile & link with MRFFL
4.1. GNU Make
The file setup.mk found in the project root directory is included by all make
files in the repository and thus makes for a nice place to configure things globally. The file is pretty short:
## The root directory for this project FF_PROJ_ROOT := $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) ## Use 'setup_fortran.mk' to setup variables. Set FCOMP=NONE to manually set AR, FC, FFLAGS, & FSHFLG below. FCOMP = gfortran FCOMP_STD = 2023 FCOMP_OPT_XSTACK = FCOMP_OPT_WARN = T FCOMP_OPT_XWARN = T FCOMP_OPT_OMP = FCOMP_OPT_OPT = T include $(FF_PROJ_ROOT)/setup_fortran_gmake/setup_fortran.mk ## Manually configure the compiler. #AR = --Command For Library Archive Tool-- #FC = --Command for Fortran compiler-- #FFLAGS = --Compile flags/options for fortran compiler-- #FSHFLG = --Shared library flags/options for fortran compiler-- ## Create rules and targets for the MRFFL library include $(FF_PROJ_ROOT)/MRFFL/src/include.mk
If the setup_fortran.mk include can't configure fortran on your system, then you may have to do that manually. This involves setting FCOMP to NONE, and then
setting AR, FC, FFLAG, and FSHFLG to something appropriate. Here is an example for nvfortran:
AR := ar FC := nvfortran FFLAGS := -O3 -Wall -W -Xlinker -z -Xlinker execstack FSHFLG = -o $(MRFFL_SHARED_LIB_FILE) -shared $(MRFFL_OBJ_FILES)
The only tricky one is the FSHFLG variable. Luckily you only need the FSHFLG variable if you plan on building a shared library. The shared library is
completely unnecessary for making full use of the modules, so you you can safely ignore that one unless you really, really want to use a shared library. ;)
4.2. GNU R
The file setup.R found in the project root directory is included by all R code in the repository and thus makes for a nice place to configure things globally. The file is pretty short:
# Load required packages suppressPackageStartupMessages(library('dplyr')) suppressPackageStartupMessages(library('ggplot2')) suppressPackageStartupMessages(library('scales')) suppressPackageStartupMessages(library('data.table')) # Set this to your favorite image viewer, or TRUE to attempt to find one automatically, or FALSE to not load images imageV <- TRUE # Try and find an image viewer if (imageV == TRUE) { if (.Platform$OS == "windows") { imageV <- "explorer" } else { for(piv in c("/usr/bin/display", "/usr/bin/eog", "/usr/bin/pqiv", "/usr/bin/nomacs")) if(file.exists(piv)) imageV <- piv } }
5. Using MRFFL (MR Fortran Finance Library) Modules
5.1. The Hard Way
All of the code is in the module source files with no external dependencies at all. So you just need to call the modules from your code, and then compile/link everything together.
5.2. Reuse MRFFL's setup.mk file
To simplify matters, you can use the same global setup used in the example makefiles. In this case your makefile will look something like this:
#------------------------------------------------------------------------------------------------------------ # Set Global Variables. include /path/to/MRFFL/repository/setup.mk #------------------------------------------------------------------------------------------------------------ your_program : your_program.f90 $(MRFFL_OBJ_FILES) $(FC) $(FFLAGS) $^ -o $@
Note the rule in the makefile above takes the lazy approach of adding every MRFFL module as a dependency regardless of if your program actually needs them all. This is how most people use the modules because it's simple. The cost might be a couple seconds of extra compile time. You can explicitly list out the modules in the makefile if you wish. Such a rule might look like the following:
your_program : your_program.f90 mrffl_config$(OBJ_SUFFIX) mrffl_tvm$(OBJ_SUFFIX) mrffl_solver$(OBJ_SUFFIX) $(FC) $(FFLAGS) $^ -o $@
6. Details: include.mk
6.1. Useful Variables
MRFFL_MOD_FILES- All the module (
.mod) files. These will appear in your build directory. MRFFL_OBJ_FILES- All the object (
.objor.o) files. These will appear in your build directory. MRFFL_STATIC_LIB_FILE- The name of the static library file. It's not created by default. It will appear in your build directory if it is listed as a dependency on one of your targets.
MRFFL_SHARED_LIB_FILE- The name of the shared library file. It's not created by default. It will appear in your build directory if it is listed as a dependency on one of your targets.
6.2. Useful Targets
all_mrffl_lib- Builds the library files.
all_mrffl_mod- Builds the module (
.mod) files all_mrffl_obj- Builds the object (
.objor.o) files clean_mrffl_mod- Deletes all the MRFFL module (
.mod) files in the build directory. clean_mrffl_obj- Deletes all the MRFFL object (
.objor.o) files in the build directory. clean_mrffl_lib- Deletes all the library files in the build directory.
clean_mrffl- Simply calls the following targets:
clean_mrffl_mod,clean_mrffl_obj, &clean_mrffl_lib clean_multi_mrffl- The previous clean targets will only remove products from the current platform. For example, the
clean_mrffl_objtarget will delete object files with an extension of.objon windows and an extension of.oon UNIX'ish platforms. I use the same directories to build for all platforms, so I sometimes want to clean up the build products from all platforms at once. That's what this target will do.
6.3. Static Library
A rule to make a static library is included in include.mk. A build rule like the following should build that library and link it to your executable. Note
I'm just including the library file on the command line instead of linker like options (i.e. -L and -l for GNU compilers). That's because simply including
the library on the command line is broadly supported across more compilers – this way I don't have to document how to do the same thing for each one. ;)
your_program : your_program.f90 $(MRFFL_STATIC_LIB_FILE) $(FC) $(FFLAGS) $^ $(MRFFL_STATIC_LIB_FILE) -o $@
6.4. Dynamic Library (.so and .dll files)
A rule to make a static library is included in include.mk. You can build it with the target clean_mrffl_lib, or by using $(MRFFL_SHARED_LIB_FILE) as a
dependency in your build rule. As the options to link to a shared library differ wildly across platforms and compilers/linkers, I don't provide an example of
how to do that.
7. Details: setup_fortran.mk
7.1. Names of files
- File extensions on Windows (outside of WSL)
- Executable files use
.exe - Shared libraries use
.dll - Object files will
.obj
- Executable files use
- On UNIX systems (not including MSYS2)
- Executable files have no extension
- Shared libraries use
.so - Object files will use
.o