The data object
Data is split between reported data and user generated data,
both are stored in the data object.
Reported data is the data retrieved from our third party providers such as
financialmodelingprep.com.User data is data generated by using the
computeor thesetfunctions.
data.compute()
Calculates values based on specified formulas and stores them in the
data object. The formulas can reference other keys, either for
reported data or user data, and can include mathematical operations and
specialized functions. Let’s take an example.
Example
# Computing Benjamin Graham's number
data.compute({
"#bookValue": "balance:totalStockholdersEquity / income:weightedAverageShsOut",
"#intermediaryVariable": f"#bookValue * income:eps * {assumptions.get('graham_multiplier')}",
"#grahamNumber": "function:sqrt:#intermediaryVariable",
"%revenueGrowthRate": "function:growth:income:revenue",
})
Breaking down the example
Formulas are evaluated from top to bottom and starting from the earliest year available all the way until the end. For the sake of this example, let’s say the earliest year available is 2000.
1. ``#bookValue``
The first evaluated key is #bookValue.
The framework starts by fetching the total stockholders’ equity
totalStockholdersEquity from the balance sheet in year 2000 and the
number of shares outstanding weightedAverageShsOut from the income
statement also in year 2000.
Calculates the #bookValue per share for year 2000 by dividing the
total stockholders’ equity by the weighted average shares outstanding.
2. ``#intermediaryVariable``
Since the value for #bookValue has just been calculated, the
framework can now evaluate the second key #intermediaryVariable.
Note: Assumptions can be used within string formulas. One simple way is to use the following python string format:
f"{assumptions.get('graham_multiplier')}"
3. ``#grahamNumber``
The third evaluated key is #grahamNumber, which uses the square root
function function:sqrt.
Note: The formula could also be written without a special function,
using the power operator **. But it could result in complex numbers.
"#grahamNumber": "#intermediaryVariable ** 0.5",
4. ``%revenueGrowthRate``
The fourth and last evaluated key is %revenueGrowthRate, which uses
another function called function:growth
Key Types
Notice that there are multiple types of keys, this is to keep the model organized and the framework can format the values in millions or thousands depending on the key type.
Keys that start with “#” are indicating that its values are either standalone units like ratios or “per share” items.
Keys that start with “%” are indicating that its values are percentages.
Keys that start with anything else, will be considered formattable to millions or thousands.
Examples
Price to Earnings ratio can be named something like “#priceToEarnings”
The tax rate can be named “%taxRate”
The key for forecasted revenue can be named just “forecastedRevenue”. The values will be then formatted to millions or thousands in the rendering table or chart, depending on your rendering preferences.
Forecasting Values
Forecasting values allows you to project future financial metrics based on historical data and specified growth rates. This is particularly useful for estimating performance over a defined period.
Storing Projection Years as an Assumption
To make the model more interactive and allow control over the number of
projected years, you can store the projection duration as an assumption.
Use the assumptions.init() method to initialize the
"projection_years" key before performing any forecasts:
# Initialize assumptions for projection years
assumptions.init({
"projection_years": 5 # Adjust this value to specify how many years to project
})
Using data.compute for Forecasting
You can now use the data.compute() function to calculate projected
values. Below is an example of how to compute projected revenues based
on a annual growth rate of 10%.
# Compute projected revenues using a growth rate
data.compute({
"income:revenue": f"income:revenue:-1 * (1 + 0.1)", # Projecting a 10% growth rate
}, forecast=assumptions.get("projection_years"))
Note: Feel free to make the revenue growth an assumption as well.
Example of Forecasting
Here’s a complete example that initializes assumptions, computes projected revenue, and displays the results in a table:
# Initialize assumptions
assumptions.init({
"projection_years": 5, # Set the number of years to project
"%revenue_growth_rate": "10%"
})
# Compute projected revenues at a 10% growth rate
data.compute({
"income:revenue": f"income:revenue:-1 * (1 + {assumptions.get('%revenue_growth_rate')})",
}, forecast=assumptions.get("projection_years"))
# Render a table to display the projected revenues
model.render_table({
"data": {
"income:revenue": "Projected Revenue",
},
"start": 1, # Start from the next year
"end": assumptions.get("projection_years"), # End at the projected years
"properties": {
"title": "Projected Revenues",
"number_format": "M", # Display figures in millions
"order": "ascending", # Show projected years in order
},
})
The LTM Period and the ltm_as_year Property
One for the LTM period
One from the 2024 annual report
By default, the LTM figure is ignored, and forecasting starts from the 2024 value.
ltm_as_year property becomes useful.If
"ltm_as_year": True, forecasting begins from the LTM value (e.g., LTM revenue grows by 5%).If not specified, or set to
"ltm_as_year": False, forecasting uses the most recent full-year figure (e.g., 2024 revenue).
Working Example of ltm_as_year
# Initialize assumptions
assumptions.init({
"projection_years": 5, # Number of years to forecast
"%revenue_growth_rate": "10%"
})
# Compute projected revenues using the LTM value as the base
data.compute({
"income:revenue": f"income:revenue:-1 * (1 + {assumptions.get('%revenue_growth_rate')})",
},
forecast=assumptions.get("projection_years"),
properties={"ltm_as_year": True}
)
# Render a table to display the projected revenues
model.render_table({
"data": {
"income:revenue": "Projected Revenue",
},
"start": 1, # Start from next year
"end": assumptions.get("projection_years"), # End at the last forecast year
"properties": {
"title": "Projected Revenues",
"number_format": "M", # Format numbers in millions
"order": "ascending", # Show years in forward order
},
})
Available Functions in data.compute()
function:growth
(current - previous) / previous.Example: "function:growth:income:netIncome"
Note: The growth function only accepts keys, not values.
function:discount
Discounts a key or value using compound interest to adjust a future value to its present value.
Example #1: Discounting forecasted flow:freeCashFlow at 10%:
"function:discount:flow:freeCashFlow rate:0.1"
Example #2: Discounting forecasted flow:freeCashFlow at 10%
continuously:
"function:discount:flow:freeCashFlow rate:0.1 continuous:true"
Required parameters
rate:The annual discount rate used to discount future cash flow or other figures to present value.
Optional parameters
offset:[..., -2, -1, ...]Shifts the time period used in discounting by a set number of years. The default value is
offset:0
continuous:[true, false]Can be configured for continuous time by setting
continuous:true
Note: Setting continuous:true will discount the next year’s
flow:freeCashFlow to present value accounting for the days left
until the fiscal year ends.
discount rate = ((1 + rate) ** days difference / 365)
function:compound
Compounds a key or value using compound interest.
Example: "function:compound:1 rate:0.1 offset:-1"
Required parameters
rateThe annual rate used to compound the given value.
Optional parameters
offset:[..., -2, -1, ...]Shifts the time period used in compounding by a set number of years. The default value is
offset:0
continuous:[true, false]Can be configured for continuous time by setting
continuous:true
function:linear_regression
Example:
"function:linear_regression:income:revenue start:-5 end:0"
Optional parameters
start:[..., -2, -1, ...]Sets the regression start relative to LTM. The default starting period is the first available historical period.
end:[..., 0, 1, ...]Sets the regression end relative to LTM. The default ending period is the last available period.
Range Functions
The following functions support range selection and share the same optional parameters:
function:averageCalculates the average of values over a specified range of periods.
function:sumorfunction:addReturns the total sum of values over a specified period. Synonymous aliases:
sum,add.
function:maxorfunction:maximumReturns the maximum value in the specified range. Synonymous aliases:
max,maximum.
function:minorfunction:minimumReturns the minimum value in the specified range. Synonymous aliases:
min,minimum.
function:multiplyReturns the product of values over the specified range. Useful for chaining multipliers over time.
Example #1: Averaging the last 3 years. -
"function:average:exampleKey period:3"
Example #2: Using range selection to select the last 3 years. -
"function:average:exampleKey:-2->0"
Optional parameters - alternatives to range selection
period:[1, 2, ...]Selects the specified number of periods. This is just an alternative to
function:average:x->0, wherex = (-1)*(periods - 1).
start:[..., -2, -1, ...]Sets the start relative to LTM. The default starting period is the first available historical period.
end:[..., 0, 1, ...]Sets the end relative to LTM. The default ending period is the last available period.
function:sqrt
Example: "function:sqrt:16" returns 4.0
function:pow
Raises the value to the power specified in raised_to parameter.
Example: "function:pow:2 raised_to:3" returns 8.0
Required parameters
rateThe annual discount rate used to discount future cash flow to present value.
function:log
Example: "function:log:10 base:10" returns 1.0
Required parameters
rateThe annual discount rate used to discount future cash flow to present value.
function:exp
Example: "function:exp:1" returns approximately 2.718
Available Operations in data.compute()
Here are all the available operations allowed within data.compute()
Arithmetic Operations
- Addition:
+Adds two numbers.Example:3 + 2results in5 - Subtraction:
-Subtracts the right number from the left.Example:5 - 2results in3 - Multiplication:
*Multiplies two numbers.Example:4 * 3results in12 - Division:
/Divides the left number by the right. Returns a float.Example:10 / 4results in2.5 - Floor Division:
//Divides and rounds down to the nearest integer.Example:10 // 4results in2 - Exponentiation:
**Raises the left number to the power of the right.Example:2 ** 3results in8 - Modulus:
%Returns the remainder of the division.Example:10 % 3results in1
Boolean Operations
1 if the condition is True and
0 if the condition is False.- Equal to:
==Checks if two values are equal.Example #1:5 == 5results in1Example #2:5 == 6results in0 - Not equal to:
!=Checks if two values are not equal.Example:5 != 3results in1 - Less than:
<Example:3 < 5results in1 - Greater than:
>Example:7 > 4results in1 - Less than or equal to:
<=Example:4 <= 4results in1 - Greater than or equal to:
>=Example:6 >= 3results in1
Grouping
Parentheses:
()Used to control the order of operations. Example:2 * (3 + 4)results in14
data.set()
The data.set() function allows you to set values in the stored data.
You can set a single key-value pair or multiple pairs at once.
Example of using data.set()
data.set("income:netIncome:1", 1000000) # Set future net income, not overwriting
data.set({
"income:revenue:1": 5000000,
"income:costOfRevenue:1": 3000000
}, overwrite=True) # Set multiple values overwriting any existing values
data.get()
Retrieves a value from the stored data. You can specify a key and optionally define a default value if the key is not found.
Example of using data.get()
ltm_eps = data.get("income:eps") # Retrieves the last twelve months EPS from the income statement
previous_year_eps = data.get("income:eps:-1") # Retrieves the previous year's EPS
Range selection using data.get()
You can also select a range of values. For instance, to get the EPS values over the last 5 years plus LTM, you would use:
historical_eps = data.get("income:eps:-5->0")
data.min()
Calculates the minimum value for a given key, ignoring None values.
Example of using data.min()
min_eps = data.min("income:eps:-10->0") # Minimum EPS over the last 10 years including LTM
data.max()
Calculates the maximum value for a given key, similar to the min()
function.
Example of using data.max()
max_revenue = data.max("income:revenue:-5->-1") # Maximum revenue over the last 5 years, excluding LTM
data.average()
Calculates the average of values for a given key, ignoring None.
Example of using data.average()
average_eps = data.average("income:eps:-10->0") # Average EPS over the last 10 years, including LTM
data.sum()
Calculates the sum of values for a specified key.
Example of using data.sum()
total_revenue = data.sum("income:revenue:-5->-1") # Total revenue over the last 5 years, excluding LTM
data.count()
This function counts the number of entries for the specified key, excluding specified values if needed.
Example of using data.count()
count_dividends = data.count("dividend:adjDividend:*", properties={"except_values": [None, 0]}) # Count non-zero dividends