The BEST Framework
Comprehensive guide to financial modelling with modern spreadsheets
The BEST Principles
The foundation of modern financial modeling built on four core principles:
Balanced
Financial modelers must find optimum balance between conflicting priorities.
Efficient
The model must be fast and responsive enough to aid proper decision making.
Stable
The model must remain functional and reliable when users interact with or update the data.
Thorough
The model should not have loose ends, which creates spreadsheet risk.
What the framework focuses on
360ยฐ Overhaul
Complete transformation of financial modeling practices
Dynamic Arrays & LAMBDA
Modern spreadsheet functionality for advanced modeling
Robust Architecture
Design principles for stable and reliable models
Governance Structure
Organization and management of financial models
Testing & Debugging
Methodologies for validating complex models
Audit Techniques
Modern approaches to model auditing
Book Chapters
BEST framework โ Foundation
Introduction to modern financial modeling principles
4 sectionsArchitecting inputs for stability
Building stable input architecture for models
7 sectionsMaking calculations dynamic
Dynamic array referencing and calculations
4 sectionsBuilding reliable Lambdas
Foundation rules and development practices
5 sectionsTesting and debugging
Testing and debugging the “Black Box”
3 sectionsGovernance structure
Organization and governance principles
6 sectionsAuditing dynamic array models
Modern audit approaches and validation
4 sectionsBEST Framework โ Foundation for Modern Financial Modeling
Understanding the paradigm shift from traditional cell-by-cell modeling to dynamic array-powered financial models
Traditional financial modeling in spreadsheets has followed a cell-by-cell, copy-and-paste methodology for decades. While this approach has served the industry well, it comes with inherent limitations: models become unwieldy as they scale, formulas are prone to copy-paste errors, and maintenance becomes increasingly complex as business requirements evolve.
Dynamic arrays (DA) and the LAMBDA functionality fundamentally change this paradigm. Modelers can now create compact, powerful expressions that handle entire datasets as single units. This shift enables financial models to behave more like software applicationsโrobust, scalable, and self-maintaining.
Key Insight: Implementing reliable financial models with dynamic array and Lambdas (DA Model) requires a 360ยฐ overhaul of financial modeling practices that are widely followed.
The Need for a 360ยฐ Approach
A powerful and scalable formula handling complex logic needs a strongโyet friendlyโinput architecture to work reliably. And to ensure there is consistency when the complex logic is reapplied, it must be encapsulated in a LAMBDA function.
However, since the LAMBDA can be argued to create a “black box,” its quality and reliability must be assured. This requires applying strong functional programming design principles and ensuring that the Lambdas are thoroughly tested, validated, and bugs, if any, are identified and fixed before they are used.
But these responsibilities cannot be left to individual modelers. The financial modeling function itself must be reorganized with strong governance and organization structure, transforming it from an individual craft into a disciplined organizational process.
Finally, these changes will count for nothing if third parties cannot rely on the model. This requires that modellers still care about making their models auditable, and that auditors modify their approach to focus on validating functions over checking formulae.
This involves more than learning new functions. It requires a different approach that focuses on cohesion between all the elements to achieve the true potential of DA models with far lesser risk.
This guide provides guidance across these aspects to ensure such cohesion in each of the next few chapters.
The BEST Principles
This guide is built around four foundational principles that form the acronym BEST: Balanced, Efficient, Stable, and Thorough. These principles work synergistically to create models that are both powerful and practical.
Balanced
The Balanced principle recognizes that financial modeling with spreadsheet involves constant trade-offs, such as these:
- Pure technical optimization often conflicts with user experience
- Complete transparency can compromise performance
- Future proofing may increase the time to roll out models
The guidance in this document consistently seeks the optimal balance point for each such decision.
Efficient
Models must open quickly and perform calculations within acceptable timeframes to truly support decision-making. Therefore, this guide favours efficient use of human and computing resources.
It discourages practices that favours simplicity in calculations at the cost of creating bloated files with sluggish performance.
Stable
Stability demands that models remain functional despite common user interactions or events, such as updating data, inserting or deleting rows, or sorting and filtering tables. This guide favours approaches that allow a fully built model to automatically accommodate these changes without breaking, preserving its integrity and reliability.
Extended Definition: Stability in dynamic array models extends beyond formula resilience. It encompasses the stability of the underlying data architecture, the consistency of function libraries, and the predictability of model behaviour across different usage scenarios.
Thorough
A scalable and stable financial model cannot have loose ends that depend on end user actions. Therefore, the financial modelers should be thorough with their approach. Financial modelers should not bypass complexity to merely to avoid effort and exploit the full capabilities of modern spreadsheets to handle such complexities.
The guide clearly segregates a financial modeler from the end user.
How BEST Principles Compare to Other Standards
While standards like FAST, SMART, and the ICAEW Financial Modelling Code provide a crucial foundation for good modeling, they were largely formulated before the advent of Dynamic Arrays and LAMBDA. As a result, they focus on best practices for a legacy, cell-by-cell approach. The BEST framework, in contrast, is built exclusively for the modern DA paradigm.
While we align with the spirit of these standardsโto ensure financial models are reliableโthe context of DA modeling results in significant philosophical and practical deviations. Further, to keep the focus sharp on DA model, we have deliberately ignored topics like use of VBA where we find existing industry practices to be acceptable.
Key Areas of Deviation
Framework for the System and Not the Individual
The key differentiator of BEST framework is that it takes a holistic view of the financial modeling function, treating it as an integrated system of people, processes, and technology. It puts the onus of making the financial model reliable on the system. This is a departure from other standards that focus primarily on the best practices of an individual modeler.
Treats Formula Logic as Sacrosanct and Not Malleable
Legacy standards insist that formulas should be simple enough for any user to understand and modify. The BEST framework takes a starkly different view and insists that a complex formula, especially Lambdas, should not be modified, ever, once approved.
Different Philosophy to Transparency
Other standards place simplicity as the cornerstone of transparency. This guide views transparency as keeping the code accessible and in ensuring that the lambdas are pure i.e. not affected by any value other than what is passed as an argument to it.
Emphasizes Validation over Comprehension
This guide acknowledges that creating formula that satisfy the BEST principles would require writing logics that may be extremely difficult for standard users to comprehend. It emphasizes that standard users and auditors should focus on validating the Lambda by applying it on familiar data sets rather than trying to understand the model logic.
Replaces Ambiguous “Rules” with Clear Prescriptions and Recommendations
Where some standards prescribe a single set of rules that can be broken with justification, the BEST framework provides a clearer, two-tiered framework:
See the BEST Framework in Action
The video below demonstrates the clear difference between traditional approaches and the BEST standard:
Building financial model with Dynamic Array | The BEST framework
Architecting Inputs for Stability
Creating robust input architectures that balance backend stability with frontend usability
Input architecture is an extremely critical part of DA models. The decisions made at this stage determine whether a model can scale efficiently, remain stable under user interactions, and support the advanced calculation techniques discussed in later chapters.
A lack of dynamic front end within spreadsheets makes it extremely difficult to satisfy the dual objective of a robust backend and very friendly front-end. This chapter tries to balance the two so that the compromises neither affect the stability of the model, nor be a major deterrent for user adoption.
Key Insight: The guidance in this chapter focuses specifically on practices where inputs are directly entered into the spreadsheet, balancing robust backend architecture with user-friendly frontend design.
Scope
The guidance in this chapter focuses specifically on practices where inputs are directly entered into the spreadsheet. While this guide encourages importing data directly from source systems and remains open to use of forms and PowerApps, which enhance user experience and control, these topics fall outside the scope of this version.
Certain standard practices for input, including, keeping the input in a separate cell and distinguishing them with different colour codes, continue to be relevant while building financial models with dynamic arrays.
However, certain additional guidelines are relevant for DA models, which are outlined here.
Definitions and Terminologies
In the context of this guide, the input variables are classified into four categories. The terminology that is used, and their meaning are as under:
(i) Scalars:
These variables have only one value and is kept in a single cell. For instance, the WACC variable in most financial models are static across time and is, thus, an example of a scalar input.
(ii) Vectors or one-dimensional data:
These variables have multiple values and are presented as a list of values either in a single row or single column. The size of the list can increase (or, in fewer cases, decrease). For example, when projecting long-term financial data, analysts may apply distinct sales growth rates to each forecasted period.
Exhibit 1: Example of vector data set
| 2XX5 | 2XX6 | 2XX7 | 2XX8 | 2XX9 | |
|---|---|---|---|---|---|
| Sales growth rate | 11% | 10% | 8% | 8% | 8% |
(iii) Multi-dimensional data:
These refers to variables that have two or more dimensions and the data can grow on any of the dimensions. For example, if an analyst needs to input bill of materials (BOM) data for a multi-product company, the input may spread across multiple rows and columns as shown in Exhibit 2.
Exhibit 2: BOM — an example of a multi-dimensional data
| Product | Chem 1 | Chem 2 | Chem 3 | Chem 4 |
|---|---|---|---|---|
| Product A | 150 | 150 | ||
| Product C | 180 | 190 | 150 | |
| Product D | 120 | 110 | ||
| Product E | 170 | |||
| Product F | 60 |
(iv) Single group, mixed nature data:
These are variables that belong to a same group or list, but the nature of one or more-line items in the group varies from the other items. For instance, in a funding schedule, all different source of capital can be visually presented as a list.
Exhibit 3: Funding schedule — an example of single-group-mixed-nature data
| Source | K | Weight |
|---|---|---|
| Debt | 9% | 40% |
| Preferred shares | 12% | 20% |
| Equity | 18% | 40% |
| Total | 13% | 100% |
Structured Tables:
It refers to a range that is marked as a table in the spreadsheet. In MS Excel it is done by marking the area as a “Table” from the insert menu or by using the CTRL + T shortcut key combination. These tables are not just formatted to appear as table for the human eye, but they are recognized by the software as such.
2.1 Architecture for Scalar Input Variables
Prescriptions:
Keep scalar inputs in a separate cell, with proper labels and colour coding
All scalar inputs must be maintained in separate cells with clear labels and consistent color coding for easy identification.
- Ensures centralized updates: Keeping scalar variables in a separate cell ensures that when the values of those variables are changed, such a change is consistently applied across the file without having to repeat the same action again. Further, keeping the values in a separate cell makes it possible to create data tables for performing sensitivity analysis.
- Aligns with current practices: This is in complete alignment with commonly recommended best practice documents such as FAST or SMART.
Recommendations:
Protect scalar input sheets with locked cells
All scalar input should be kept in a separate sheet that should be protected and all cells other than the input cells should be locked for editing. The sheet should not allow deleting of rows or columns.
- Reduces the chance of inadvertent deletion of cells: The main technical risk with a scalar input cell is that it can get deleted and throw #REF! error, in linked cells. Preventing deletion of rows or columns reduces this risk.
Note: Readers should note preventing deletion alone is not fail proof for #REF! error. When a cell that is cut from elsewhere is pasted in an unlocked cell, it causes the same problem.
Lock unit conversion factors in separate cells
Unit conversion factors such as number of months in a year, number of metres per kilometre, should be kept in a separate set of cells but the cells should be locked for editing.
- Reduces ambiguities: Although unit conversion factors themselves do not vary, ambiguities can occur when these values are entered directly into a cell. For instance, multiplying a volume by 12 may not clearly indicate whether monthly figures are being annualised or quantities are being converted from dozens to units. By placing such constants in a separately labelled cell, the purpose becomes clear and transparent to the reader.
- Prohibits unwarranted changes: The purpose of keeping unit conversion factors in a separate protected sheet, away from standard input, is to ensure that people do not inadvertently change their values.
The other alternative is to directly store these values in a name under the Name Manager. Since the names are out of sight, there is less chance of inadvertent changes. But this reduces transparency of the model and does not fail proof any intentional manipulations of the variables.
Name cells with scalar variables
Cells with scalar variables should be named. Such names should be brief, yet descriptive. For instance, a cell containing the WACC value can be named as _WACC.
- Easy access: Cell names can be easily called with help of IntelliSense from any sheet by the modeler without having to navigate to the source sheet.
- Improved readability: When a formula uses a descriptive cell name, it makes it easy for users to understand what the cell represents without having to navigate away to the source sheet and read the labels. For instance, let us say the WACC is in input sheet C8. An end user who is trying to understand the logic can easily understand what
=1/(1+_WACC)is doing without having to navigate to the input sheet and checking what does C8 represent. - Reduces vulnerability in programs: When you are referring to a cell in VBA or Scripts, references to cell names are not vulnerable when rows/columns are inserted or deleted. This improves integrity of the model.
Note: Naming cells has some drawbacks, too; users must follow clear naming conventions to prevent confusion, especially in models with many variables. This version of the document does not cover naming best practices.
2.2 Architecture for Vector Input Variables
Prescriptions:
Organize vector inputs as structured tables
Vector inputs must be organized as a structured table. In the case of time series data, this would involve the timelines to be placed as row heading, flowing from top-to-bottom, while the fields would be placed across columns.
- Dynamic Expansion: Financial models are often updated, increasing the number of items in a vector. Inputs in dynamic array formulas must update automatically as new items are added. Using a structured table ensures all related formulas update when the list expands.
Note: Users, who are mostly accustomed to seeing timelines placed horizontally and line items placed vertically, would need to reorient in the case of table architecture. In Appendix 1, we discuss alternative arrangement involving placing timelines horizontally, along with its pros and cons.
Avoid TRIMRANGE function for vector inputs
Avoid storing vector input in traditional range of cells to be used with TRIMRANGE function or trim operators in formula.
TRIM operators introduce higher level of spreadsheet risks that have been detailed in para P17.
Do not protect sheets with input tables
Sheets with input tables must not be protected with “Protect sheet” feature.
- Prevents dynamic expansion of table: As on the date of last update of this document, structured tables do not expand in protected sheets. Therefore, the sheets should be unprotected to ensure the model is dynamic.
Keep incompatible datasets in separate tables
Data sets that are not compatible across the key dimension should be kept in separate tables. Forceful grouping of incompatible data set in a single table can lead to confusion, inefficient referencing, and errors in dynamic array calculations.
Exhibit 4: Improper grouping of incompatible data in single table
| Year | Sales | Expected growth rate | Gross Profit | Expected margins |
|---|---|---|---|---|
| 2XX3 | 300 | 146 | ||
| 2XX4 | 327 | 152 | ||
| 2XX5 | 8% | 48% | ||
| 2XX6 | 7% | 46% |
- Enhanced Clarity: Each table has a clear purpose, making it easier for users to understand and update specific datasets without navigating unrelated data.
- Improves scalability: Since all columns belong to one group, adding more columns will not disrupt the existing structures or formula dependent on the table. For example, if a table is exclusively used to hold historical income statement data and analyst needs a formula that would return all historical income statement line items for year 2023, it can be written as follows:
=Drop(FILTER(tbl_IS, tbl_IS[Year]=2023),, 1) - Reduces spreadsheet risk: When unrelated data are forced together, it would lead to many blank cells or reference errors, which may lead to incorrect computations. By avoiding such forced grouping, the risk of such error is reduced.
Recommendations:
Give structured tables descriptive names
Structured tables should be given brief and descriptive names replacing the default names given by MS Excel.
- Improves readability: The default names given by MS Excel are non-descriptive. A custom name that is descriptive, therefore, would make it easy to understand a formula. For instance, a cell reference such as
=IS_History[Gross Margin]clearly tells us that we are extracting gross margin from historical period and not forecasts. - Easy access: When the names are descriptive, it is easy to recollect and type the table name directly in a cell, further aided by IntelliSense, without having to manually navigate to each table and select them.
Use validation columns for row-level validation
Modelers are encouraged to use column(s) to perform row level validation of input to check whether all input columns are correctly filled.
For instance, let us say there is an IS_Table with historical financials with nine fields, including one for the timeline and another eight for eight different line items, we may insert a 10th column to check whether all the first 9 columns are filled with a formula such as this:
=COUNT(IS_Table[@Year]:[PAT])=(COLUMNS(IS_Table)-1)
This formula would return TRUE only if all the input columns are duly filled.
๐ Exhibit 5: Input table with a validation column
Manual Insertion Required: Please upload an image showing an input table with validation column implementation.
- Prevents stray rows from affecting calculation: When working with tables it is common that an end user may add additional rows to the table either inadvertently, or intentionally to serve as a place holder. The formulae referring to the table can filter out such stray rows using the validation column.
Use multi-table validation columns
Modelers are encouraged to use additional calculated columns to perform multi-table validations.
For instance, one may add a column in income statement to check whether all columns of balance sheet for the same period have been filled up.
- Allows synchronization of calculations: When a calculation requires data from multiple tables (say asset turnover ratio), the multi-table validation columns allow us to filter out data sets when corresponding data is not available in another data set.
Allow calculated columns in input tables
This guide does not discourage using any calculated columns, which may aid end users in the input process. However, such column shall not be used in core calculation sections.
For instance, a calculated PAT column helps analysts check the accuracy of entered financials by comparing computed number with reported number. Likewise, using a moving average of sales growth can guide arriving at a projection assumption. Including these calculations alongside input data can be beneficial.
- Balances user experience with rigid structure: Allowing calculated columns in input table to allow figures flowing elsewhere improves the end user experience while keying information despite the rigid architecture.
Avoid homogenous data of multiple entities in single table
The guide discourages including homogenous data of multiple entities in a single input table.
For instance, while technically it does not create an issue if all historical data including income statement, balance sheet, and cash flow items are kept in one table, modelers should consider keeping them in separate tables.
- Improves user experience during input: When data of multiple entities are mashed up in a single table, it is likely to be overwhelming to enter the input data in the table.
Note: This specific guidance pertains only to tables where input is fed. It does not concern itself with tables that are imported from external sources using any ETL tools.
2.3 Architecture for Input of Multi-dimensional Data
Multi-dimensional data must also be organized as a structured table. And all the prescriptions and recommendations that applied to organizing vector as a structured table also apply to them. This section lays out additional guidelines that are exclusively relevant for multi-dimensional data.
Prescriptions:
Organize three or more dimensions in long form
Variables that have three or more dimensions must be organized in the long form in a single table. Avoid creating multiple two-dimensional tables.
For instance, a company may provide segmental report with revenue for multiple periods, broken down by geography, which is further broken down by business segments. In annual reports, companies may provide separate table for each geography. However, in dynamic array models, they should be presented in a long form format as shown in Exhibit 6.
Exhibit 6: Illustration of long data format for multi-dimensional data
| Year | Geography | Business | Sales | EBITDA |
|---|---|---|---|---|
| 2XX3 | Americas | Beverage | 300 | 80 |
| 2XX3 | Americas | Snacks | 280 | 75 |
| 2XX3 | APAC | Beverage | 280 | 75 |
| 2XX3 | APAC | Snacks | 220 | 40 |
| 2XX4 | Americas | Beverage | 315 | 78 |
| 2XX4 | Americas | Snacks | 305 | 79 |
| 2XX4 | APAC | Beverage | 240 | 55 |
| 2XX4 | APAC | Snacks | 240 | 55 |
- Scalability: This format would be able to easily fit any additional item added to a given dimension without needing to create a new table. For instance, in the example provided, if the company were to foray into a new region, say Europe, in 2XX5, the segmental data can be easily added as extra rows in the same table for 2XX5.
- Enhanced analytical power: This structure is optimized for data processing and analysis functions in spreadsheets. Numbers from the table can be easily crunched and queried across dimensions using auto filters, SUMIFS, FILTER and many other functions.
- Only viable format for true DA models: In pure DA models, formulae must not be modified once the models are built and published. In this format, since no additional tables are required to be added when a new segment is added, such additions will seamlessly integrate into the file.
Note: In the case of data sets that are not likely to be used in “what-if” analysis i.e. not likely to be changed after entering once, modelers can consider keeping the input in more human friendly format and transforming them into long form format using Power Query or any such transformation tools. However, parametric estimates should always be directly entered into such long form table.
Use appropriate format for two-dimensional variables
Two dimensional variables must be in long form format if the grid size is likely to become too big to eyeball. Cross tab formats, however, should be preferred for data sets that are likely to remain small.
For instance, the BOM table in Exhibit 2 is cross tab format, which is acceptable if the number of output products and input materials are expected to remain constant. However, if the company is like to add many more products need many more other materials, the format must be in long form.
- Human friendly structure: Cross tab format is intuitive when the data size is small. However, they become less user friendly when their size gets larger. For instance, users may find it difficult to identify the correct inter-section cell to input the right value when the grid is large.
- Allows easy eyeballing and in-situ analysis: Long form data can be easily filtered and eyeballed for quick analysis and sanity checks as compared to a large grid.
Recommendations:
Normalize data to reduce redundant input
Normalize data to reduce redundant input by creating reference tables for dimensional data.
For instance, in the segmental data illustration in Exhibit 6, each combination of geographic and business can be given a unique name. Another table can be created which provides details of what geography and business segment are present in the unique name. This is shown in Exhibit 7, where we have one “Segment table” that gives a unique name to segments along with its details. In the segmental data, the user would enter the unique segment name and have the system auto populate the geography and business segments using XLOOKUP.
Exhibit 7: Illustration of normalizing data to avoid redundant input
Segmental data
| Year | Segment | Sales | EBITDA | Geography | Business |
|---|---|---|---|---|---|
| 2XX3 | Am_Bev | 300 | 80 | Americas | Beverage |
| 2XX3 | Am_Snacks | 280 | 75 | Americas | Snacks |
| 2XX3 | APAC_Bev | 280 | 75 | APAC | Beverage |
| 2XX3 | APAC_Snacks | 220 | 40 | APAC | Snacks |
Segment details
| Segment | Geography | Business |
|---|---|---|
| Am_Bev | Americas | Beverage |
| Am_Snacks | Americas | Snacks |
| APAC_Bev | APAC | Beverage |
| APAC_Snacks | APAC | Snacks |
Although the segmental data is not “Normalized” in the strictest sense as it does contain the redundant columns, this approach reduces the redundancy from input perspective.
- Balance user experience with rigid structure: Multi-dimensional data necessarily needs to be in long form format, which is laborious and needs redundant inputs. By normalizing the structure, we reduce the number of redundant input variables that need to be typed.
2.4 Architecture for Single Group of Mixed Nature Data
This situation calls for complex balancing between technically strong design principles and human friendly approach and the possible options fall within a broad spectrum. Therefore, this guide does not prescribe any practice as a must follow practice for this. However, there are certain recommendations.
Recommendations:
Use “Tabulated Scalars” for mixed nature data
When a set of variables belong to a single group but the nature or behaviour of one or more items vary from the others, treat all the individual items as scalars but format them to visually appear in tabulated form (“Tabulated Scalars”).
- Flexibility: Structured Tables have rigid structures and mixed nature data may not fit in easily. Tabulated scalars allow flexibility.
- Allows Intuitive flow: Other technically sound possibilities, such as organizing each nature of data in separate tables may affect intuitive flow for the end users. For instance, in the example in Exhibit 3, debt and preference shares details could have been kept in a structured table, while the weight of equity is calculated elsewhere, outside of the table. However, such an approach would reduce the intuitiveness of the flow, especially if the analyst is trying to optimize weights to minimize WACC.
- Easy to read: Tabulating these scalars together as a group rather than treating them as independent scalar variables make it easy for the readers to understand the variables better.
Important Note: Tabulated scalars do not allow dynamic referencing as well as a Structured table and is more vulnerable to user action such as inserting or deleting rows. The guide, therefore, recommends users to be very selective in choosing to use tabulated scalar structure over a Structured table and treat the structure as an exception than a norm.
Summary
In this chapter, we discussed that a robust input architecture is a critical foundation for building stable, scalable, and efficient Dynamic Array (DA) model. The architectural choices for input directly affect the stability of subsequent calculations.
However, as spreadsheets lack an embedded dynamic front end feature, certain pragmatic compromises need to be made to balance robust architecture with human friendliness.
Key Guidelines
- Primary of structured tables: Input data, other than scalars, must be necessarily organized as a structured table.
- Ensure separation of concerns: Data sets that do not share the same dimension (such as historical financials and forecast assumptions) must not be in the same table.
- Fail proofing with validation columns: Tables should have a calculated validation column to check row level validity and mark stray rows as invalid.
- Use long form for multi-dimensional variables: Variables with 3 or more dimensions must be necessarily in long form. Two dimensional inputs must be captured as a cross tab when the grid size is expected to be small; but they must be organized in long form if the grid size is likely to grow.
- Practices for scalar values are unchanged: Scalar variables should be kept in a separate cell and properly colour coded and preferably, named.
- Mixed nature data should be treated as scalars: Data that belong to single group but have different nature should be treated as a scalar data but they need to be grouped and formatted to appear as a table to human eye.
In the next chapter, we shall discuss how the calculations need to be performed and understand how the input architectures discussed in this chapter play key role in ensuring stable, scalable, and efficient calculation sections.
Making Calculations Dynamic โก
Leveraging Dynamic Arrays and Lambda Functions for Scalable and Auditable Financial Models
Dynamic array and Lambda fundamentally change how calculations are performed in spreadsheets ๐. The following outlines this change:
Key Insight: The calculation approach moves from individual cell-by-cell calculations that are copy-pasted to dynamic array-based expressions, enabling more possibilities that were not possible earlier.
- ๐ Dynamic Arrays: Favors in-memory computations where intermediate steps can be stored in temporary variables rather than storing them in cells.
- ๐ง Custom Functions: Allows creating custom user-defined functions, using spreadsheets’ own formula language within the workbook.
- ๐ Iterative Logic: Enables using iterative and recursive logics in functions.
- โ ๏ธ Risk Reduction: Eliminates circular reference problems and reduces the need for enabling iterative calculations in the workbook.
However, these enhancements create an overwhelming number of choices for performing the same calculation including some that are inherently risky. This chapter offers the guidelines on the appropriate approach that satisfies the BEST principles.
๐ Terminologies and Definitions
In this chapter and other chapters, certain terms are used with specific meaning in the context of this guide.
๐น Lambda(s) vs LAMBDA:
In the context of this guide, the term “Lambdas” refers to any custom function created using the LAMBDA function in spreadsheet. Some part of the guide may also refer to them as custom functions.
The term “LAMBDA” written in all upper case refers to the built-in function in spreadsheet which is used to create the custom functions.
3.1 ๐ฏ Array Referencing Practices
๐ Prescriptions:
๐ Use dynamic array format for referencing
When referring to a dynamic array range, always refer to it using the dynamic array format and avoid using fixed range references.
Example: If a dynamic array in cell B5 spills to B9, reference the result as =B5# instead of =B5:B9. This is critical to ensure the model dynamically updates if the formula in B5 produces larger results.
Rationale:
- ๐ Dynamic expansion: If the referred spilled array expands, dynamic references will automatically consider such additional values. Static references break this adaptability.
๐ฏ Reference array elements, not direct cells
Specific cells or ranges within an array should be referred as an element of array and not through direct cell reference. Functions such as TAKE, DROP, FILTER, XLOOKUP, CHOOSECOL can be used for this purpose.
Example: For instance, let us say we have the previous 20 days stock prices, in ascending order of dates, as a single array spilling from cells B3:B22. Here are the right and wrong approaches:
=DROP(B3#,1)/DROP(B3#,-1) - 1
=B4:B22/B3:B21 - 1
Rationale:
- ๐ง Stable under change: When the size of the array expands or shrinks, array-based reference will automatically adapt, while static references will fail.
๐จ Assign cell references to variables in LET functions
Any reference to a cell or range inside a LET function must be assigned to a variable and used. A particular cell or range must not be referred more than once inside a given LET function.
Example: say cells C15, D15, and E15 have start date, end date, and current date and the let function needs to calculate two variables: (i) Total duration, which is D15 minus C15 and (ii) Lapsed time, which is MIN(E15-C15, D15-C15).
The appropriate way to use these cells is as follows:
=LET(StDt, C15,
EndDt, D15,
CurrentDt, E15,
TotalDur, EndDt - StDt,
LapsedPrd, MIN(CurrentDt - StDt, EndDt - StDt),
...)
Rationale:
- ๐ฏ Centralizes changes in cell reference: If the cell reference needs to be changed, the change will need to be done only once. This reduces the risk of inconsistent changes.
๐ Create “sort proof” references
References to tables and arrays must be in a way that the formula returns correct answer even if the order of the underlying data changes.
Example: Let us say we have SalesTbl with annual sales by year, with the sales for 2025 at the bottom. But sorting can move the year’s data from its original position. To reliably get the sales figure for 2025, regardless of sorting, use a formula such as this:
=XLOOKUP(LookupYr, SalesTbl[Year], SalesTbl[Amt])
Where LookupYr is 2025
Rationale:
- ๐ก๏ธ Increases integrity and stability: User interactions such as sorting the underlying data are very common. Sort proofing ensures output is not affected by such interactions.
๐ซ Filter out invalid or stray rows
Any reference to an input table should anticipate invalid or stray rows and filter them out.
Example: Continuing with the previous example, let us say we need to get the latest year sales from the SalesTbl, which also has an IsValid column โ that returns TRUE only when the row meets the validation criteria. A formula such as the one below would give correct answer even if end users add place holder rows for future periods.
=LET(LatestYr, MAXIFS(SalesTbl[Year], SalesTbl[IsValid], TRUE),
Return, XLOOKUP(LatestYr, SalesTbl[Year], SalesTbl[Amt]),
Return)
Rationale:
- ๐ก๏ธ Avoids unwarranted dynamic expansion: Safeguards the models from being affected by common end user interactions such as including placeholder rows or filling up partial data sets.
๐ Handle external references with ETL tools
External references must always be handled using ETL tools, such as Power Query or SQL, and directly linking a cell to another workbook must be avoided.
Sometimes, a model requires data from another modelโfor example, a Master Budget may need information from various functional budgets, or an industry analysis may need data from individual files for different companies. In MS Excel, Power Query can integrate such data efficiently.
Rationale:
- ๐ Avoids risk of stale values: Data brought through copy-pasting could turn stale when other models are updated.
- ๐ฏ Prevents incorrect references: Live workbook links are vulnerable to changes in cell locations. Importing data from structured export sheets reduces both risks.
๐ก Recommendations:
๐ Use structured referencing for tables
Use structured referencing while referring to Structured tables.
- ๐ Improves readability: Structured reference with clear table and column names are easier to read and modelers can easily refer to tables with IntelliSense.
- ๐ฏ Reduces chances of wrong references: Structured reference ensures table columns are always referred in their entirety and wrong columns can be easily spotted.
Note: Structured references are absolute but act as relative references when dragged right. Users should be aware of this behavior.
๐ท๏ธ Name cells containing spill formulas
Name the cells that contain the spill formula.
- ๐ Improves readability and accessibility: Named references are easier to understand and access than relative references, improving formula readability throughout the guide.
3.2 ๐งฎ Calculations and Calculation Blocks
๐ Prescriptions:
โฑ๏ธ Use model-specific timelines
Timelines in a financial model must be model specific and not schedule or line item specific.
Say a project has a life of 25 years, while the debt taken for it should be repaid in lesser duration of 20 years. If an analyst is projecting cash flows for the full 25 years, the debt schedule must also flow for the entire 25-year period, with a formula that makes all the values in the debt schedule going to zero for years 21 to 25.
However, this guide does not discourage, modelling certain line items at a higher frequency โ than others โ in a separate schedule and aggregating them in a common schedule.
For instance, an analyst may choose to model revenue and operating expenses for every quarter while modelling interest and taxes at an annual level and present all of them on annual level. Such a practice is acceptable provided the quarterly schedules are organized in a separate calculation section.
Rationale:
- ๐ง Prevents fragmentation and errors: Ensuring all arrays are of uniform length ensures that operations on multiple arrays work seamlessly. Different length arrays may cause DA formula errors.
๐ Use dynamic arrays for vector/matrix outputs
All calculations that produce a vector or matrix output must be modeled as a dynamic array and no such item shall be modeled using legacy scalar iterative approach.
Rationale:
- ๐ก๏ธ Ensures integrity of calculations: Since the entire vector/matrix is driven by one formula, there’s no risk of inconsistent formulas within a range.
- ๐ง Reduces dependency on end users: Using only dynamic arrays eliminates manual tasks for end users. Legacy methods require copy-pasting and adjusting formulas, increasing error risk.
โ ๏ธ Important: The spreadsheet risk when legacy approach is mixed with dynamic array is far greater than in a pure legacy approach. This guide recommends using pure legacy approach over mixed approach if modeling any array using dynamic approach is impossible.
๐ซ Avoid enabling iterative calculations
Modelers must avoid enabling iterative calculations in DA models. They must opt for alternative closed form solutions, or iterative/recursive Lambdas.
Rationale:
- โ ๏ธ Avoids unpredictable model behavior: If variables that drive spill array size become circular, they may cause incorrect spilling leading to unpredictable results.
- ๐ Extremely difficult to debug: When external iterative calculations affect in-memory DA computations, bugs are far more difficult to trace and debug.
๐ซ Avoid TRIMRANGE functions
Modelers must not use TRIMRANGE functions or trim operators while referring to a cell as they increase the risk of being affected by stray values.
Rationale:
- โ ๏ธ Inadvertent stray values should not affect calculation: End users may type stray values in what appears to be blank cells, leading to all dependent calculations automatically extending and producing erroneous output.
๐ Avoid using calculated columns in structured tables
Calculated columns in structured tables must not be used for model calculations except in the following circumstances:
- Validation columns, described in recommendation R6 and R7 can be used for filtering out stray or invalid data.
- When the calculations need to be done iteratively across the rows in a table and it is impossible to do it as a dynamic array with acceptable level of performance.
Rationale:
- ๐ฆ Prevent model errors from polluted tables: Although structured tables are also dynamic and expand, they are not fail-proof. For instance, cell in a calculated column can be overwritten, especially when the sheet is unprotected. It makes such calculated columns vulnerable for unauthorized editing.
๐ Avoid stacking multiple variables in one array
Modelers must not stack multiple variables in one array except in the following cases:
- All the variables are inter-related and computed together iteratively, or recursively.
- The stack is used to present the final output of the model โ for display or export.
- The stacking is required as an intermediate step inside a formula, but the formula does not output such a stack.
โ Term loan schedule: Even though you could create one function returning opening balances, interest expense, borrowings, repayments, and closing balance as a single schedule, each of these six variables should be presented as individual vectors.
โ Cash sweep modeling: For a revolver, cash flows, interest, taxes and borrowings are inter-related and must be modeled iteratively using REDUCE – stacking is necessary here.
โ Output sheets: Stacking multiple schedules together is acceptable for output or export sheets if individual vectors aren’t used elsewhere in the model.
Rationale:
- ๐ฏ Improves Accessibility: When each variable is presented in an independent vector, it is easy to refer in all dependent calculations.
- ๐ง Maintains model stability when new line items are added: When variables are stacked, functions like
INDEXorCHOOSEROWSrequire specific row or column references. If the number of items or their order in the stack changes, these functions may return incorrect results.
๐ฌ Include validation schedule to support audit of complex in-memory computation.
When major computations are processed in-memory and intermediate steps are not directly observable, modelers must include validation utilities to verify the output.
๐ Example: If a fund holds hundreds of debentures, a scalable approach would be to model the entire balances, redemptions, and incomes for multiple periods together in a single schedule rather than preparing separate schedules for each debenture and separately aggregating them.
Although these are scalable, auditing or validating them would be extremely difficult.
๐ก Solution: The model should have separate calculation section that allow reviewers to drill down the calculation at individual debt level. This calculation section will serve as a validation utility for the main model.
Rationale:
- โ๏ธ Balances auditability and scalability: In-memory computations are highly scalable and efficient. However, they significantly reduce the transparency of the model. Having a utility that can help validate the calculations, and which are easy to understand will improve the transparency, and hence, the trust on the financial model.
๐ง Ensure that model layout will not create spill error
Calculations and calculation blocks must be positioned in a way that they do not potentially cause a spill error if the dynamic array expands.
๐ Positioning Rules:
- โก๏ธ If a calculation block is expected to expand into more columns, do not place other calculation sections to its right.
- โฌ๏ธ If it is expected to expand across rows, avoid placing anything below it.
- ๐ Totals are best placed above or to the left of such blocks.
Rationale:
- โ ๏ธ Prevents spill errors: Keeping other cells clear along the array’s direction helps avoid spill errors. While these errors are usually fixed by adding rows or columns, they may affect downstream models importing data (until the error is resolved).
๐ก Recommendations:
๐ Show intermediate steps transparently
Modelers should show intermediate steps transparently in the model unless it significantly affects scalability or performance.
Rationale:
- โ๏ธ Balances transparency and scalability: Breaking calculations into intermediate steps makes it easy to follow the model without significantly compromising performance or scale.
โ Use approved Lambdas for complex computations
Complex in-memory computations should be done through approved Lambda rather than as direct formula in the cell. Writing complex logic directly in a cell should be opted only if the modeler wants to protect the IP.
Rationale:
- ๐ก๏ธ Increases reliability: Reviewers and auditors can easily validate an approved Lambda rather than complex multi-line logics written directly in cells.
๐ค Create machine-friendly export sheets
Models should have well-structured and machine friendly set of export sheets that can be used by downstream models to import data.
Rationale:
- ๐ Allows seamless integration: Downstream models can use SQL, Power Query or other methods to easily extract data if the file has well-structured export sheets.
Note: Export sheets are different from output sheets – they are meant for machine reading, not presentation. Appendix 5 suggests best practice for export sheets
๐ Summary
In this chapter we had discussions on how calculation section should be set up and considerations that should be given in choosing a proper calculation approach so that models remain stable, scalable and efficient. ๐ฏ
๐ฏ Key Guidelines
๐ Strict Array Reference Principles:
- Dynamic arrays must always be referred using the # operator and static range reference must be avoided
- Specific cells or ranges within an array should be referred as array elements, not through direct cell reference
- Cell references inside LET function must be assigned to variables and same cell must not be referred more than once
- Structured references and named cell references are preferred over relative cell references
๐๏ธ Calculation Setup Practices:
- Timeline must be model specific and not schedule specific
- Multiple variables must not be stacked together except for certain exceptional cases
๐ก๏ธ Fail-proof Formula Against User Interactions:
- Sort proof financial models
- Prevent stray data and incomplete data updates from causing dynamic expansion
๐ซ Avoid Legacy Practices:
- Legacy approach must not be mixed with dynamic array approach
- Iterative calculation setting must stay disabled
โ๏ธ Balance Memory vs Sheet Storage:
- Intermediate steps should be stored in sheets if it doesn’t cause performance issues
- If performance issues occur, in-memory calculations must be preferred with approved Lambda and validation sections
๐ Next Steps: This chapter guided that complex logic should be handled using approved Lambda. In the next chapter, we shall discuss what process and practice should be followed so that approved Lambdas are more reliable than explicitly written formulae.
Building Reliable, Reusable Lambdas ฮป
Creating functional programming excellence in modern financial modeling
LAMBDA, together with the LET function, in MS Excel enable functional programming in modern spreadsheets ๐. These functions have made spreadsheets near-Turing-complete โ we can perform any calculations that can be described, with the only key limitation being the size of variables that the spreadsheets can handle.
Key Insight: Users working with LET and LAMBDA are essentially entering the functional programming paradigm. Modelers need to follow most of the established software design principles such as the SOLID principles.
This guide adapts such software principles in the context of financial modeling. However, the guide does compromise somewhere on these principles for certain practical reasons.
๐ฏ Lambda Classification: This guide classifies Lambda into two categories based on their scope of use:
- ๐ Global Lambda: Custom functions used across multiple models
- ๐ Local Lambda: Custom functions meant for use in a specific file alone
๐ Terminologies and Definitions
๐ Global Lambda:
These are custom functions that are used across models. This classification is not based on how many can access the Lambda, but it is based on whether the same function is expected to be used in more than one file.
๐ Local Lambda:
These are custom functions that are meant to be used in a specific file alone. These are not expected to be used in another file. If a file is likely to be copied and used in its entirety for another purpose, the Local Lambda in the file should be considered as Global Lambda and follow the guidance given for the same.
Note: This guide recognizes that Local Lambda may be often created with modeler convenience as its key objective. Thus, the guidance for Local Lambdas are less strict for the most part, except that a Local Lambda shall not be used as Global.
4.1 ๐๏ธ Foundation Rules and Design Principles
๐ Prescriptions:
๐ฏ Create each Lambda to handle a single, well-defined task
For complex multi-step operations, create a wrapper function which calls each of the needed Lambdas to perform the set of tasks.
๐ Example: A simplistic projection of sales may involve:
(i) Compute historical growth rates
(ii) Propagate the moving averages of growth rates for future N periods
(iii) Project sales using such moving averages
Each of the three actions should be performed by three separate Lambdas. A fourth, wrapper Lambda can be created to call the three in the right order to get the final output.
Rationale:
This guidance stems from the application of the Separation of Concern principle and has several advantages. The most relevant from the point of financial modelers are as follows:
- ๐ Enhances code reusability: Logic stored in a single Lambda function can be used for multiple purposes. For example, the same moving average calculation can be applied to both sales projections and gross margins without rewriting the code.
- ๐ง Easy to test, debug, and maintain: Since each Lambda does a specific task, it can be independently tested and can be debugged. Any correction in the logic of the Lambda will automatically be incorporated into all the wrapper LAMBDA that uses it.
๐ Global Lambda logic must avoid direct references
Global Lambda logic must avoid direct references to cells, ranges, file locations, websites, or volatile functions like random numbers or current date/time. Instead, use parameters to pass these variables as arguments.
๐ Example: If we have dynamic daily share price data and need a Lambda to auto calculate the 20-day moving average (20 DMA) based on the current date, instead of embedding the TODAY() function directly inside the Lambda’s logic, create a parameter for the current date to be passed in the Lambda by the user. End users can supply TODAY() as the argument for this parameter when calling the Lambda.
โ ๏ธ Exception: A default value can be assigned for optional parameters that are omitted.
Rationale:
- ๐ Promotes transparency and simplifies debugging: Making all variables explicit in the Lambda ensures that calculations depend solely on the arguments (referential transparency), making testing and troubleshooting easier.
Note: Although referential transparency is critical in functional programming context, this guide does not mandate its strict adherence for Local Lambda, as it recognizes that such Local Lambda may be created with user convenience as its objective.
๐ Lambda must work with both column and row vectors
A Lambda that is expected to work with column vectors, should also work with row vectors (and scalar variables), and vice versa, unless the dimension of the vector is rigid in nature or practice.
๐ก Examples: Most vectors, such as timelines, can be oriented horizontally or vertically, though some contexts require a specific direction. For example, fields in tables and eigenvectors are typically column vectors. Calculation requirements may also dictate vector orientation; if sales volume is a row vector, so must be the selling price.
Rationale:
- ๐ง Supports flexible calculation layouts: Users can choose to arrange variables horizontally or vertically, and Lambda functions will operate reliably with either orientation.
๐ Prioritize closed form solutions over recursive
When creating a Lambda to address a problem with circular reference, priority must be given to closed form solutions, followed by iterative solutions. Recursive solution must be used only as a last resort.
Rationale:
- โก Improves efficiency and easy to debug: In terms of performance, closed form solutions are the most efficient, followed by iterative solutions. Recursive Lambdas are the slowest among the three and may fail to perform when number of recursions exceed the limit. Ease of debugging follows the same order.
๐ท๏ธ Avoid naming conflicts in LET functions
Variable names used in a LET function must not be the same as any of named ranges or functions and no range shall be given a name that is same as that of a Lambda.
Rationale:
- โ ๏ธ Prevents conflicts and errors: If a variable name is same as a range name, then the range cannot be referred with the same name in the LET function. Further, when a range is given same name as a Lambda, the action will overwrite the Lambda leading to corruption in the model.
๐ก Recommendations:
ฮป Use Lambda symbol in function names
All Lambda names should end with a sign such as “ฮป” to make it easy to distinguish between custom functions created with Lambda and built-in MS Excel functions.
๐ก Example: A Lambda to calculate the moving average can be named as MovingAvgฮป.
- ๐๏ธ Makes the user aware of the custom nature of the function: The “ฮป” sign in the name makes it clear to the readers that these are custom functions and not prebuilt functions.
- ๐ Reduces name conflicts: Adding the “ฮป” symbol to Lambda functions keeps their names distinct from range names. For example, users can have a Lambda named WACCฮป and a cell named WACC, without creating conflicts.
๐ Use brief, yet descriptive variable names
Variable names used in functions should be brief, yet descriptive. Modelers can also consider using commonly used mathematical notations such as ฮผ and ฯ.
- ๐ Makes it easier to understand the flow of logic: When the variables are descriptive โ such as “Loan”, “Int” โ it is easier to follow the logic in a lengthy function. However, if the variable names are too big, they may result in the cell exceeding the character limit.
๐ค Assign final calculation to a return variable
The final step of the calculation in a LET function should be assigned to a variable name and the variable name should be given as the final return value.
๐ก Example: Let us say a multi-step calculation is performed to calculate the interest expense for a stub-period. The final interest calculation should be assigned to a variable like “Return” or “Output” and these variable names should be mentioned at the end.
- ๐ Helps in debugging: At the time of debugging, the function can be modified to return the intermediate value without having to make major code changes.
๐ Keep Local Lambda relatively simple
Local Lambda should be relatively simple with not more than a few steps.
- ๐๏ธ Easy to audit: Reviewers are likely to have only limited time to review Local Lambdas. Hence, it should be simple and handle only a few steps to facilitate quick and effective audits.
4.2 ๐ฌ Development and Validation
๐ Prescriptions:
๐ All Lambdas must be thoroughly documented
All the Lambdas must be thoroughly documented, and in-line comments must be used to explain any complex line or block of calculations.
๐ Documentation Requirements:
โข Purpose, application and logic of the overall Lambda
โข Meaning of the input parameters
โข Explanation for the codes
โข Use case for the Lambda
๐ ๏ธ Tools: Advanced Formula Environment (AFE) in MS Excel allows adding detailed comments. Modelers can also leverage GitHub repositories that allow LAMBDAs to be stored with inline comments. Google sheets also has inbuilt functionalities to describe the parameters and provide sample input.
Rationale:
- ๐ Improves clarity, and thus, auditability: Lambdas perform many calculations in-memory, where intermediate calculations will not be visible, and, thus, its workings are relatively difficult to understand. Proper documentation and in line comments offer clarity on what a code is meant to do. Such clarity also helps when auditing the function.
- โ Reduces misapplication of function: Documentation of the right use cases will help end users to correctly apply the appropriate function.
โ Global Lambda must be thoroughly tested before approval
A Global Lambda must be thoroughly tested and validated before being approved for use in financial models.
Rationale:
- ๐ก๏ธ Makes the models reliable: End users, often are likely to get the feeling of working with Black Box and may not be able to test its logic or accuracy. However, if the Lambda are pre-tested, it increases the reliability of the Lambda.
๐ก Recommendations:
๐ Document Local Lambdas thoroughly
The documentation practices for Local Lambdas should be at par with Global Lambda, if not better.
- ๐ Easy to inherit / handover: Knowledge of Local Lambda is likely to be limited to the creator of the model. Having quality documentation ensures that other users who take over the file can develop good understanding of the same.
4.3 ๐ Deployment and Maintenance
๐ Prescriptions:
๐ฆ Global Lambda must be available in a common repository
All Global Lambda should be available in a common repository from which they can be imported.
๐ ๏ธ Implementation Options:
โข AFE in MS Excel allows Lambdas to be imported from GitHub
โข Users can copy paste all available Lambda from a notepad file into a module
โข In Google sheets, the repository can be in the form of another Google sheet from which it can be directly imported
Rationale:
- ๐ Allows refreshing and importing new Lambda: A central repository allows users to periodically import the updated list of Lambdas ensuring that the files have access to the latest set of approved Lambdas.
๐ No modifications to Global Lambda after publication
No modifications, including bug fix, must be done to a Global Lambda after it is published for production. However, erroneous Lambdas can be retired, after due process.
โ ๏ธ Important: If a Lambda’s functionality needs to be improved, it must be published as a new Lambda. However, if a published Lambda is found to have serious bugs, it can be retired in its entirety following the due process by the model governance team (refer Chapter 6).
In this context, thorough testing and validation of Global Lambdas before their publishing becomes extremely critical. Otherwise, every iteration of bug fix will lead to overload of too many similar LAMBDAs with minor modifications.
Rationale:
- ๐ Ensures consistency and backward compatibility: Each Lambda maintains its functionality throughout all files, as any changes result in a new function. And reloading Global Lambdas from a central repository poses minimal risk to current calculations.
- ๐ฅ Reduces dependency on individuals: New developers joining the team need not understand the inner workings of existing Lambdas, which ensures that future development will not suffer if original creators of the Lambda leave the organization.
๐ซ Avoid customizing Global Lambda
Users must avoid customizing a Global Lambda to suit the need of a specific model. Any customization should be done either by manipulating the argument passed or through a Local Lambda serving as a wrapper function.
๐ Example: Let us say an organization has created a custom function to calculate the number of weeks between a start and end date:
NWeeksฮป = LAMBDA(StDt, EndDt, [CurrentDt],
LET(_EndDt, IF(EndDt=0, CurrentDt, EndDt),
ROUNDDOWN((_EndDt-StDt+1)/7, 0)))
The Lambda uses the current date as the EndDt in case the end date field is blank or zero. In a separate instance, if we need the function to return “NA” as output if the end date field is blank, instead of changing the NWeeks Lambda, create a Local Lambda:
Local.NWeeksฮป = LAMBDA(StDt, EndDt,
IF(EndDt = 0, "NA", NWeeksฮป(StDt, EndDt)))
Rationale:
- ๐ก๏ธ Retains reliability: Ensuring that a Global Lambda that has been validated is not modified retain the reliability of the said LAMBDA.
๐ก Recommendations:
๐ Regularly reload Global Lambda from repository
Global Lambda must be reloaded from the common repository whenever a user inherits a model or duplicates a file. Modelers should regularly reload Lambda for ongoing models and compare outputs to confirm consistency.
โ ๏ธ Important: If a model’s output changes after reloading, it should be promptly reported to the model governance committee (see Chapter 6). For individual or small-scale operations without such committees, modelers themselves must thoroughly analyse these cases.
Rationale:
- ๐ก๏ธ Minimises risk of Lambda pollution: Spreadsheets offer limited safeguards for protecting a Lambda from unauthorised edits or overwriting. The risk gets significantly reduced when it is reloaded from a central repository.
- ๐ Keeps the file updated with the latest Lambda: Reloading the file regularly ensures that analysts can access all the latest Lambdas.
๐ Summary
This chapter introduces a structured approach to functional programming in spreadsheets, leveraging the LAMBDA and LET functions. It adapts the robust software design principles and applies it in the context of financial modeling with a few pragmatic compromises reflecting certain limitations in spreadsheets. ๐ฏ
๐ฏ Key Guidelines
๐ Scope of Lambda:
- Global Lambdas: Applied in multiple models must be built using rigorous development standards
- Local Lambdas: Used in a single file can prioritize modeler convenience, but must be simple, confined to a single file, and must not compromise on documentation
๐ฏ Single-responsibility Design:
- Each Lambda should perform one well-defined task
- For multi-step workflows, use a wrapper Lambda to orchestrate specialized Lambdas in sequence
- This separation of concerns improves clarity, testing, and reuse
๐ Solution Priority Order:
- Closed form > Iteration > Recursion
- Lambda logic should prioritise closed form solutions over iterative solutions
- Recursive solutions should be used only as a last resort
๐ Immutability:
- Once a Global Lambda is published to a production environment, it must not be altered
- Any necessary improvements should be released as a new function
- Buggy functions should be retired through a formal process
- This prevents breaking existing models
โ Strong Testing and Documentation:
- All Global Lambdas should be thoroughly tested and documented before they are published
- In-line comments must be used to explain complex calculations
- Documentation must focus on purpose, parameters, logic, and use cases
๐ฆ Centralised Distribution:
- Global Lambdas should be stored in and distributed from a common repository
- Modelers are responsible for regularly reloading these functions to ensure their models use the most current and consistent versions
- Especially important when inheriting or duplicating files
๐ Next Steps: Following these guidelines help organisations to build a library of custom functions that are consistent, reliable, and easily reusable, enhancing the integrity of their financial models. This chapter prescribed that Lambdas should be thoroughly tested. In the next chapter, we describe how to test and debug Lambdas and complex in-memory computations.
Testing and Debugging the “Black Box” ๐
Ensuring quality assurance for Dynamic Arrays and Lambda functions in modern financial modeling
While Dynamic Arrays and Lambdas offer immense power, they also demand a new discipline for quality assurance ๐ฏ. Traditional validation methods, designed for cell-by-cell logic, are insufficient for models driven by single, complex array formulas. Auditing now involves scrutinizing compact, powerful expressions rather than tracing scattered precedents.
Key Insight: This chapter provides guidance on the strategies for testing and debugging Lambda within this modern paradigm, ensuring your sophisticated calculations remain reliable and auditable.
The shift from transparent, cell-by-cell logic to powerful in-memory computations requires new testing methodologies and debugging techniques specifically designed for the “black box” nature of modern spreadsheet functions.
5.1 ๐งช Testing the Lambda
The purpose of testing a Lambda is to ensure that it works correctly โ . The ultimate onus for testing lies with the team that is developing the Lambda. However, they may use the help of other teams.
The testing of a Lambda may not take as much time as testing a new system. However, it may still take more time than checking a normal formula. Given that a Global Lambda is likely an IP asset serving the organization in the long run, the additional time spent on testing is justified ๐.
๐ Prescriptions:
๐ Lambda output must be compared with legacy approach computations
Output of a Lambda must be compared with the same computations done using legacy approach and ensure that the outputs are consistent. Such testing must be performed with multiple data sets to increase the reliability.
๐ก Implementation Tip: Organizations that have already built many models can leverage their model banks for such testing. For testing the accuracy of calculations, the input architecture in the scalar models need not be changed.
Rationale:
- โ Validates the output: There may be some bugs or flaws in what appears to be a logically accurate function. Validating it with scalar iterative approach will help uncover or rule out any such bugs.
๐ฏ All Lambda must be tested for edge cases
Edge cases in calculation can arise in plenty of ways including the following:
- ๐ Argument values being very high, low, or blank
- ๐ Arguments in opposite sign i.e. positive values in place of negative and vice versa
- ๐ Large size of underlying data
- ๐ Parameters with different dimensions
Rationale:
- ๐ก๏ธ Tests model stability: This will help test whether the Lambda, and thus the overall model, can be stable under different situations.
- ๐ง Helps design error handling features: Such an edge case testing will help identify scenarios where the Lambda fails. The understanding can then be used to create error handling procedures within the same Lambda.
- ๐ช Increases reliability: When a Lambda is able to handle the edge cases, it increases its reliability.
๐ Note: In Appendix 4, we discuss arguments in favour and against including customized error messages in the case of Lambda.
5.2 ๐ Debugging Lambda and Calculations
Debugging formulae written with LET or LAMBDA function brings a different set of challenges for most financial modelers as most of the computations are handled in-memory ๐ง .
This brings a challenge in terms of identifying and isolating the source of error for further investigation. This guide outlines a set of debugging strategies that financial modelers can use to identify and address the source of bugs ๐.
๐ก Recommendations:
๐ Trace internal calculations step by step
Make a variable in the intermediate step as the output variable and compare its value with manually calculated value or the value of that step in a scalar iterative model.
๐ฏ Method: Tracing is typically done by backtracking from the last step and moving one step backwards till we reach a step where there is no mistake (“last right step”). Then we correct the step that has a mistake and repeat the process until all errors are resolved.
๐ก Pro Tip: The modeler can also consider directly testing an intermediate variable if their intuition points to that as a possible problem step.
Rationale:
- โก Faster to pinpoint the mistake step: It allows to systematically locate the source of bug. Once the last right step is identified, we need not check the prior steps.
- ๐ ๏ธ No special tools required: It uses the inherent functionality of the modern spreadsheets.
๐ข Reduce iterations to 1 and gradually increase
In the case of iterative Lambda, keep the number of iterations to 1 and check the result. If there are no mistakes, increase the number of iterations till an error is encountered. Then decompose the calculation between the two iteration counts.
๐ง Technical Background: SCAN and REDUCE functions in modern spreadsheets allow creating iterative Lambdas. But, it is quite challenging to backtrack the prior steps. When the number of iterations is set to 1, it behaves like a non-iterative Lambda, which makes it possible to backtrack the steps.
If the Lambda produces bug when iteration is more than 1, then decompose the result between the last correct iteration and next iteration to identify the source of bug.
Rationale:
- ๐ Allows tracing internal calculations: It is not possible to backtrack steps in iterative Lambda. However, when number of iterations is set to 1, the function behaves like a non-iterative function, which makes it easy to backtrack.
๐ Replace array parameters with scalar parameters
Replace array parameters with scalar parameters to test (i) logic and (ii) syntax. If the function works correctly with scalar parameters but fails to function with array parameters, it is likely the dimension of the parameter is incorrect.
๐ Example: Let us say we have written a function to calculate the total interest expense pertaining to a portfolio of loans. For the purpose of debugging, we shall test it with the data pertaining to single loan, instead of the entire portfolio.
Rationale:
- ๐ Easy to backtrack complex array calculations: Backtracking steps, when the steps themselves are large arrays can be quite challenging. However, when array parameters/functions are converted to scalar parameters/functions, the size of the intermediate calculations will reduce and, thus, make it easy to check for errors.
- ๐ฏ Separate logical error from dimension error: Certain error may arise because of a problem with the dimension. For instance, if the dimension of the various parameters passed within a MAP function are not uniform, the function will fail. When all parameters are made scalar, this issue will not arise.
๐ Apply binary dissection method to narrow down problematic records
Once an item/record causing an error is identified, isolate it and apply the formula/function for the individual item/record alone and follow the steps outlined earlier, in this section.
๐ Example: Let us say a function meant to calculate total interest expense on a portfolio with 20 loans does not match the calculation done using the legacy model. In this case, we should apply the function on one half of the portfolio (i.e. 10 loans in this case) and identify which half has the error. Once the half with the error is identified, halve it again and repeat the process till we identify the record with the error.
Once the loan with the error is identified, apply the function exclusively for that loan item and trace the internal steps.
โ ๏ธ Note: It is possible that there is more than one item in the array that causes trouble. Once we identify one error item and fix the logic, we may have to repeat the process again, if some other error persists.
Rationale:
- ๐ฏ Easy to identify edge case items that cause trouble: In large arrays, some edge case items may persist for which the logic that applies to all other items may not apply. This technique helps quickly zero down on such edge cases.
๐ Summary
This chapter focused on robust techniques for testing and validating Lambda and in-memory computation ๐ฏ.
๐ Key Guidelines
โ Validate Lambda:
- Compare the results produced by Lambda with results computed using legacy approach
- Use multiple datasets to increase testing reliability
- Leverage existing model banks for comprehensive validation
๐ฏ Stress Test:
- Lambdas should be tested using edge cases to ensure they work correctly
- Test with extreme values, opposite signs, large datasets, and different dimensions
- Design error handling features based on edge case findings
๐ Apply Suitable Debugging Strategies:
The following steps should be taken for debugging Lambdas:
1๏ธโฃ Backward Tracing:
Make the model return each of the intermediate variable in reverse order and find the point at which the model breaks.
2๏ธโฃ Reduce iterations to 1:
To backward trace iterative Lambdas, reduce the iteration count to 1.
3๏ธโฃ Binary dissection:
When working with large array argument(s) systematically halve the arguments over-and-over to quickly narrow down items causing bugs.
4๏ธโฃ Convert vector parameters to scalar:
Once an item causing error is identified, isolate the item and pass it as a scalar argument to the Lambda and subsequently backward trace the error.
๐ Next Steps: The guidance given in this chapter should help financial modelers develop Lambda that are reliable and tackle errors and bugs, if any, effectively. In the next chapter, we shall focus on how organizations should be structured and the governance practice they need to follow to ensure that responsibilities are properly assigned and human errors are avoided.
Governance and Organization Structure ๐๏ธ
Building robust organizational frameworks for dynamic array modeling excellence
The power of dynamic array and Lambda bring in new challenges, if they are not handled responsibly: errors can propagate at scale, abstracted functions can become opaque “black boxes,” and without discipline, complexity can grow unchecked ๐จ.
Key Insight: To harness the power of these functions, it is critical to start treating financial models as an organizational task rather than as an individual task.
This chapter outlines a robust, three-pillar organizational framework designed to instil discipline, ensure quality, and create a scalable, trustworthy financial modeling ecosystem.
๐๏ธ Three-Pillar Organization Structure
This guide recommends splitting the financial modeling team into three separate functions:
- ๐ฌ Lambda creation and testing
- ๐ข Model building
- โ๏ธ Lambda and modeling governance
๐ก Important Note: While the modeling team is split into three functions, it may not necessarily increase the need for higher manpower as pre-built Lambdas will significantly increase the speed at which individual team members would be able to build and update models.
๐ฌ Lambda Creation Team
This team will have end-to-end responsibility towards creation and maintenance of the central Lambda repository/library. This team’s responsibility includes:
- Identifying reusable Lambda that need to be created
- Create the function
- Test it
- Roll it out for production along with documentation
- Maintain the central repository/library
The team may also engage in training end users on the custom functions. ๐
Note: Companies may also choose to outsource this function to an external consulting firm.
๐ข Model Building Team
This team is the core team that will be responsible for building financial models to support the business. This team will be responsible for identifying suitable model architectures and application of the custom functions to deliver financial models that meet business needs.
The model team can also recommend new custom functions that can be created to the Lambda creation team. ๐ก
โ๏ธ Model Governance Team
The Governance team is the independent pillar that provides oversight and enforces the standards that hold the entire framework together. Their role is not to be a bureaucratic roadblock but to be the strategic enabler of quality and consistency.
The main objective of the team is to establish, maintain, and enforce a proper guidance system for the entire modeling framework. This includes defining naming conventions, setting documentation standards, and mandating architectural best practices.
๐ Key Responsibility: The prescriptions laid out in this guide regarding these aspects should be considered the bare minimum; this team is empowered to make them more rigorous and to revise them over time as best practices evolve.
๐ Summary of Responsibilities
| Task | Primary Responsibility |
|---|---|
| Creation/adoption of DA modeling standards | ๐๏ธ Model Governance team |
| Monitoring compliance with the standards | ๐๏ธ Model Governance team |
| Adhering to the standards | ๐ฅ All the teams |
| Identifying the need for a particular Lambda | ๐ฌ Lambda creation team |
| Creating, validating, and testing the Lambdas | ๐ฌ Lambda creation team |
| Updating, monitoring, and managing the library | ๐ค Jointly by Model Governance and Lambda creation teams |
| Escalation related to Lambda issues | ๐ฅ All the teams |
| Retiring erroneous Lambda | ๐๏ธ Model Governance team |
| Building financial model that fits business purpose | ๐ข Model building team |
| Identifying models that can be a template | ๐ข Model building team |
| Approving templates and managing the template library | ๐๏ธ Model Governance team |
๐โโ๏ธ For Small Teams: One-person organizations or small teams are likely to be able to enforce discipline without necessarily splitting their team into three functions. They may neither have the necessary manpower for such segregation. However, within the team, they need to carry out all functions outlined in this guide.
6.1 ๐ Core Model Governance Principles
๐ Prescriptions:
๐ Frame comprehensive policies and practices
The model governance team must frame policies and practices including the following:
- ๐จ Style guides and naming conventions
- ๐ Parameter order
- โ ๏ธ Error handling
- ๐ Documentation best practices
- ๐จ Incidence reporting โ in relation to Lambda or model governance
- ๐๏ธ Retirement of Lambdas
The standards set by the model governance must, at the least, include all the prescriptions in this guide.
Rationale:
- ๐ Increases coding consistency: Consistency in naming conventions, parameter order and error handling practices make it convenient for financial modelers to work with variety of Lambda.
- ๐ Formalises the best practices guidelines: Policies of the model governance will set clear binding guidelines on the best practices to follow for the organization.
โ Implement mandatory approval process
All Global Lambdas and DA models must go through an approval process by the governance team before they are published for common use.
The governance team’s role is strictly restricted to ensure that the respective work adhered to the policies, guidelines and standards. They shall not interfere about the business logic applied in the file.
Rationale:
- โ Ensures compliance with approved practices: The need for approval will reinforce the need to follow correct guidelines for the developer. Further, it also serves as a secondary check to detect and correct any gaps.
๐ก Recommendations:
๐ Verify fresh Lambda reload before approval
Model governance team should check that all Global Lambda from central repository are reloaded afresh before approving a model for external circulation.
Rationale:
- ๐ก๏ธ Ensures that Global Lambdas are not polluted: Reloading the Lambda under the supervision of the governance team reduces the risk of a tampered Lambda being used in the final output.
6.2 ๐ฏ Segregation of Responsibilities
๐ Prescriptions:
๐งช Assign testing responsibility to Lambda creation team
Testing and validation must be the responsibility of the Lambda creation team.
The Lambda creation team can include model builders or members from other teams for end user acceptance testing and to obtain feedback. But the ultimate accountability to ensure that Lambda is accurate shall reside with the Lambda creation team.
Rationale:
- ๐ฏ Clear accountability: Since creation and testing are with the same team, the Lambda creation team will have unambiguous accountability for producing correct Lambda.
๐ซ Restrict Global Lambda creation rights
The model building team must avoid creating or modifying any Global Lambda.
If the model building team needs a Lambda where one does not exist, they should provide that as feedback to Lambda creation team and shall not create one on their own. However, they can create Local Lambda which are not complicated.
Rationale:
- ๐ Prevents proliferation of inconsistent or rogue functions: By ensuring that Lambdas are created by one central team ensures that a given Lambda used by the entire organization is the same.
๐ Control external Lambda procurement
Sourcing Lambdas from external party and validating it must be the responsibility of Lambda creation team, and if such a team is absent, then it should be handled by the model governance team. Model building team should not directly procure Lambdas.
Lambdas procured from external parties need to be tested and validated, which is primarily the responsibility of the Lambda creation team. However, if the entire creation process is outsourced, then the task should be handled by the model governance team, who can validate whether the Lambda meets their internal standards.
Rationale:
- โ Applies quality control for third party Lambdas: Applying same level of quality checks and approval process for externally procured Lambda ensures that all the Lambda used in their models comply with the internal standards.
๐จ Establish incident reporting system
All the teams are responsible for incidence and bugs reporting and these should be reported to the model governance team.
There may be instances where model governance systems have been bypassed, or a user identifies a bug in an approved Lambda or a model template. All such cases should be escalated to the model governance team, who can then take the necessary action.
Rationale:
- ๐ Increases the chances of finding bugs: There is a higher chance of finding issues and bugs and finding them quickly if there are more eyes watching out for them.
- ๐ฏ Ensure single point responsibility for redressals and correction: Assigning redressal responsibility to the model governance team ensures clear accountability for the same.
๐๏ธ Centralize Lambda retirement authority
Model governance team must be exclusively responsible for retiring a published Lambda.
Rationale:
- โ๏ธ It needs careful execution: Retiring an existing Lambda is a far more complicated process as it is likely to affect several existing models and may even affect daily operations. Only the governance team can ensure a proper execution of the task.
6.3 ๐ก๏ธ Operational Safeguards
๐ Prescriptions:
๐พ Maintain secured repository backups
Back up of the central repository must be periodically taken and secured.
Rationale:
- ๐ Supports business continuity plan: Secured backups allow firms to quickly restore the repository should it get corrupt or lost for any reason.
๐ก Recommendations:
๐ค Implement dual approval system
Central repository should have dual approval system: Any update or editing of the repository should require approval from the model governance team and the Lambda creation team.
Rationale:
- ๐ Maintains sanctity of the repository: Requiring the presence and approval of the two teams significantly reduces the chance of unauthorized editing of the repository and maintains its sanctity.
6.4 ๐ฅ Staffing and Training
๐ก Recommendations:
๐ช Staff with financial modeling power users
Most of the Lambda creation team should comprise of financial modelers who are power users and capable of creating Lambdas.
Power users in this context are expert financial modelers who have strong technical skills to develop custom functions using Lambda.
Rationale:
- ๐ Allows rapid development of context driven functions: Power users with deep understanding of business context can develop functions that are more practical and relevant and without needing to spend a lot of time on requirement gathering and specifications.
- ๐ Fixes accountability: Power users can be made accountable for both the purpose, and the design/logic of the function. This ensures that the development process generates a higher return on investment.
๐จโ๐ผ Ensure management has software development expertise
Managerial staff in the team should be well versed with software development principles and frameworks.
Rationale:
- ๐ ๏ธ Reduces use of poor design principles: Managers with strong foundation in software design principles, can correct when Power users โ not being well trained software developers โ deviate from solid design principles.
๐ Provide comprehensive Lambda training
All new joiners should be provided dedicated training on custom built Lambdas. Existing team members should also be given periodic refresher training on the library.
Rationale:
- ๐ Makes teams aware of internal IP: Unlike standard spreadsheet functions, the resources for learning the custom-built Lambdas are not likely to exist outside the organization. Training programs ensure that all team members are aware of such internal IPs.
๐ Summary
This chapter establishes guidelines emphasizing treating financial modeling as a disciplined organizational task, rather than as an individual craft, to mitigate risks of unchecked complexity and dilution of standards ๐ฏ.
๐๏ธ Key Organizational Framework
๐๏ธ Three-Pillar Structure:
Financial modeling function should be split into three functions:
- ๐ฌ Lambda Creation and Testing: This function holds end-to-end responsibility for identifying, creating, validating and publishing the Lambdas.
- ๐ข Model building team: This function comprises of the financial modelers who use the approved, pre-built Lambdas to construct models that serve business needs.
- โ๏ธ Model governance team: This is the oversight function that sets and enforces modeling standards. Their key role is to serve as a gatekeeper, formally approving all Global Lambdas and model templates before they are released for production use.
Note: One-person organizations and small teams need not have three separate teams, but all the three functions need to be present.
๐ฏ Key Guidelines:
Clear Segregation of Duties:
Each function has specific role and should not step into the role of the others:
- Lambda creation and testing is the exclusive domain of the Lambda creation team. Model building team should not create or modify Global Lambdas.
- Applying the right Lambda to the business need is the role of model building team and model governance cannot interfere in it.
- Model governance team sets and implements the standards. Other teams will need to follow it without exception.
๐ Mandatory Approval and Sign-off:
All Global Lambdas and financial models meant for external distribution must pass a formal approval process by the Model Governance Team.
๐ก๏ธ Security and Integrity:
The central repository must be periodically backed up. It is also recommended to require approval from both the Governance and Creation teams before any modifications can be made to the Lambda library, ensuring its sanctity.
๐ Training and Awareness:
All new and existing team members should be trained on the organization’s custom-built Lambdas, treating them as valuable internal intellectual property.
๐ Next Steps: The guide so far focused on the practices that are focused on internal organizational and financial modeling practices to ensure that DA models satisfy all the BEST principles. In the next chapter, we close the loop by providing guidance on auditing practices to be followed by external parties for validating DA models.
Auditing Dynamic Array Models ๐
Paradigm shift in model verification for independent third-party auditing
In the context of this guide, auditing refers to verification of the model’s reliability by an independent third party ๐๏ธ.
Key Insight: One aspect of model audit that will undergo a paradigm change for DA models is testing of formula logic in spreadsheets. Model auditors will need to shift their focus from checking whether the formula logic applied in each cell is accurate to validating the working and integrity of Lambda.
This chapter specifically focuses on this critical aspect of modern financial model auditing.
๐ฏ Approach to Model Audit
The end objective of model audit is to ensure that the financial model is reliable ๐ก๏ธ. In terms of ensuring correct application of formulae and functions, the model auditor should ensure the following:
โ Core Audit Validation Points:
- ๐๏ธ The modeling team has strong model governance practices
- ๐ซ No array has been modelled using legacy approach
- โ๏ธ All complex in-memory computations are performed using Lambda
- ๐ The Lambdas are pure functions with referential transparency
- โ The Lambda works as described
- ๐ฏ The Lambda has been applied in the correct business context
- ๐ Iterative calculations have not been enabled
๐ Important Note: Auditors must continue to follow their legacy approach for simpler expressions used in the cells.
7.1 ๐ Pre-Audit and Audit Planning
๐ Prescriptions:
๐๏ธ Assess governance practices and standards
Auditors should obtain model governance practices and standards from the client and assess the robustness of the system in preventing rogue Lambdas.
๐ Important Context: Often, the Lambdas and the models may not be built by the client directly but by an external consulting firm. In such cases, the audit firm should understand the Lambda governance practices of such external firms.
Rationale:
- โ ๏ธ Assess risk of faulty Lambdas: Understanding the governance practices will help evaluate the risk of faulty Lambdas in the file. This will help plan the effort that needs to be applied for audit.
๐ Obtain comprehensive Lambda documentation
Obtain Lambda documentation to understand its purpose and applications.
Rationale:
- ๐ฏ Helps evaluate contextual fit of Lambda: Documentation helps understand which Lambda should be used for which purpose, which will help understand whether application of a Lambda was correct in the given business context.
๐ Reload Lambda from central repository
Obtain access to the Lambda repository of the client and reload all the Lambda afresh into the model that is being audited.
Rationale:
- ๐ก๏ธ Ensures that there are no unauthorized modifications to the Lambda: Reloading all the Lambda from the common repository eliminates the risk of any willful, or otherwise, modification of the authorized Lambda at the modeler’s end.
7.2 ๐ฌ Lambda Validation
๐ Prescriptions:
๐ Inspect Lambda for referential transparency
Inspect the Lambda code to ensure that it maintains referential transparency i.e. no external variables or values other than values of the parameters passed to the Lambda is used in its calculation.
โ ๏ธ Important: The check needs to be more rigorous if the client does not have proper model governance team or if the controls appear weak.
Rationale:
- ๐ก๏ธ Reduces the risk of rogue Lambdas: Referential transparency ensures that the output of the Lambda is not getting manipulated by any external factors.
โ๏ธ Validate optional parameters and default values
Ensure that all the optional parameters defined in the Lambda are relevant and that the default values assigned to them are appropriate.
๐ก Technical Note: A Lambda that accepts an optional parameter will typically have a default value assigned inside the logic using the ISOMITTED function. If no such default value is applied, then spreadsheet would take their default value as zero.
โ ๏ธ Major Red Flags: An inappropriate optional parameter (that does not fit the business context of the Lambda) or an inappropriate default value assigned to them are major red flags. If auditors encounter such situation, they should significantly increase the level of scrutiny.
Rationale:
- ๐ญ Prevents intentional manipulation: Inappropriate default value for optional parameters is one of the ways to deceitfully manipulate the Lambda outcome.
๐จ Red Flag Example: For instance, the Lambda below, to get average DSCR, uses a smoke screen and returns a DSCR of 2.5, irrespective of the actual number, by misusing the optional parameter:
AvgDSCRฮป = LAMBDA(Cfads, Pmts, [guess],
LET(_guess, IF(ISOMITTED(guess), 2.5, guess),
D_2, AVERAGE(Cfads/Pmts),
Return, D_2*Guess + _guess,
Return)
)
๐งช Test Lambda with proprietary data sets
Apply the Lambda on proprietary data and compare its results with the existing values to ensure that the Lambda works. If there are variances in the results, client must be required to explain the same.
๐ก Best Practice: Many of the audit firms are likely to have a repository of several financial models on a given domain. They can utilise such models to test and validate the Lambda. The firms are also encouraged to think about edge case scenarios and design data sets for the same.
๐ Important Clarification: The firms need not treat all variance as an error. It is possible that some variances are a result of improved calculation capabilities of DA models. Clients should be given an opportunity to respond.
Rationale:
- โก It is faster and more reliable to confirm the correctness: Testing the Lambda on existing data allows audit firms to quickly establish whether the function works correctly as compared to reading through the entire logic and checking the working.
๐ Technical Note: Many Lambdas that are applied directly in the spreadsheet are likely to be wrapper Lambdas that call other Lambdas. From an audit perspective, it is adequate to ensure that the wrapper Lambda, which is directly called in the spreadsheet, works correctly.
๐ Require validation utilities for abstract models
Require validation utilities to be included in the case of highly abstract models. And use the validation utilities to satisfy the accuracy of the calculations.
๐ Reference: As mentioned in para P20, functions that perform all computations in-memory should be accompanied by a validation utility. Auditors should ensure that such utility is available, and they should use those utilities to validate the calculations.
Rationale:
- ๐ฌ Helps validate a Lambda when proprietary data sets don’t exist: A validation utility, in the form of a separate calculation sheet, that allows users to drive down the calculation will help the auditors to validate Lambda output even if they do not have a proprietary data set to test.
๐ฏ Verify contextual appropriateness of Lambda application
Ensure that the function that is called in the model is the appropriate function for a given module.
๐ Example: For instance, a client may have one Lambda that computes amortized interest for a zero-coupon bond and another Lambda for computing amortized interest for a loan with annuity repayment. Auditors would need to ensure that the function that is called for computing the amortized interest is appropriate for the underlying loan type.
Rationale:
- โ๏ธ Ensure contextual application of logic: Lambdas are too abstract, and the Lambda name may not completely reveal the true purpose or the underlying logic. There is a risk that a Lambda meant for a different context is misapplied for another context. Thus, validating that the function called is indeed appropriate for the given context becomes critical.
๐ก Recommendations:
๐ค Leverage AI tools for Lambda evaluation
Use LLMs and AI tools, albeit with caution, to understand and evaluate a Lambda.
๐ Current Capability: As on the date of this version, many of the commonly available LLM and reasoning models have evolved enough to understand and explain the logic of a complex Lambda function or spreadsheet formulae. Such a capability can be utilized to understand the Lambda written by other firms.
โ ๏ธ Caution Required: However, given the probabilistic nature of these models, end users should be cautious while understanding and accepting the response.
Rationale:
- ๐๏ธ Get an additional non-binding perspective: It reduces the chances of failing to spot a mistake, which is inherent in the audit process.
๐ Summary
In this chapter, we discussed that auditing spreadsheet formulae in dynamic array models involves a paradigm shift ๐. Auditors need to shift their focus away from checking the accuracy of the formula logic cell-by-cell to validation of Lambdas.
๐ Key Guidelines
๐๏ธ Evaluate Governance Practice:
Check whether the client has strong governance practice over Lambda, and in their absence, plan for a more stringent scrutiny.
โ Validation over Comprehension:
Model auditors need not understand the logic built inside a Lambda. They should rather focus on the following:
- The Lambda upholds referential transparency
- Does not have misleading default value for optional parameters
- Its results, applied on test data sets with edge cases, matches with the expected results
๐ฏ Test Contextual Fit of Lambda:
Get the documentation of Lambda from the client to understand the purpose and application of Lambdas and check whether correct Lambda has been applied in the given business context.
โ๏ธ Use Legacy Technique for Simpler Expressions:
Several expressions or formulae in DA models are likely to be simpler, albeit using newer functions, and directly typed in the cell. Auditors can review the logical accuracy of such expressions using existing methodologies.
๐ Conclusion: With this chapter, we conclude the guidance on best practices for dynamic array models. In this guide, we established the BEST principles and detailed a 360ยฐ framework encompassing input architecture, model calculations, Lambda designs, testing and debugging, organization structures and governance and guidance on audit techniques for DA models.
๐ Final Note: The prescriptions and recommendations in this guidance, hopefully addresses concerns and questions of financial modelers in relation to adopting dynamic array practices in financial modeling.
๐ What’s Next: In the appendices section, we discuss certain alternative views on some of the critical prescriptions in this guide along with their pros and cons and we also discuss the characteristics of a good export sheet.