You signed in with another tab or window.Reload to refresh your session.You signed out in another tab or window.Reload to refresh your session.You switched accounts on another tab or window.Reload to refresh your session.Dismiss alert
The purpose offinstr package is to create an environment for reproducible financial statement analysis. The package will not cover specific types of analysis (except in examples and package vignettes) but will provide a domain language to write them. With other functions in basic R and existing R packages it anables users to store, share, reuse and reproduce the results of their analitic work.
For now it is offering:
1. Data structure for financial statements
Reading from data parsed with XBRL package
Statements in tidy format with accounting taxonomy concepts as columns
Encapsulates calculation hierarchy of variables
Default printing in transposed format and with visible hierarchy
2. Statement calculation validation
Calculation of higher order elements
Check if calculated values match original values
3. Merge statements
Merge different periods of equal statement type
Merge statements of a different type
4. Calculate and reveal
Custom financial ratio calculations definitions
Exposing data by rearranging the statament hierarchy
Time lagged difference
Installation
To install finstr from github useinstall_github from devtools package:
library(devtools)install_github("bergant/finstr")
Get data
Use XBRL package to parse XBRL files. For example:
Recalculate higher order concepts from basic values and check for errors.
check<- check_statement(balance_sheet2014)check#> Number of errors: 0#> Number of elements in errors: 0
In case of error the numbers with errors will be presented along with elements:
check_statement( within(balance_sheet2014,InventoryNet<-InventoryNet*2))#> Number of errors: 2#> Number of elements in errors: 1#>#> Element: AssetsCurrent = + CashAndCashEquivalentsAtCarryingValue + AvailableForSaleSecuritiesCurrent + AccountsReceivableNetCurrent + InventoryNet + DeferredTaxAssetsNetCurrent + NontradeReceivablesCurrent + OtherAssetsCurrent#> date original calculated error#> 3 2013-09-28 7.3286e+10 7.5050e+10 -1.764e+09#> 4 2014-09-27 6.8531e+10 7.0642e+10 -2.111e+09
Validation returns all calculation results in a readable data frame. Lets check only operating income from income statement:
check<- check_statement(income2014,element_id="OperatingIncomeLoss")check#> Number of errors: 0#> Number of elements in errors: 0check$expression[1]#> [1] "+ GrossProfit - OperatingExpenses"check$calculated/10^6#> [1] 55241 48999 52503
Merge statements from different periods
Usemerge function to create single financial statement data from two statements.
The structure of merged balance sheets may differ if XBRL taxonomy changes. Functionmerge takes care of it by expanding the elements hierarchy to fit both statements. The values of any missing elements in different periods is set to 0.
To merge all statements fromstatements object use merge on statements objects:
# merge all statementsst_all<- merge(st2013,st2014 )# check if balance sheets are merged:balance_sheet<-st_all$StatementOfFinancialPositionClassifiedbalance_sheet$endDate#> [1] "2012-09-29" "2013-09-28" "2014-09-27"
Merge different types of statements
If there are no matching elements between the two statementsmerge joins statements by matching their periods. For some financial ratio calculations the combined statement may bea better starting point.
Statement object (in our casebalance_sheet) is also a data frame object with statement elements as columns and time periods as rows. It is possible then to use statement as a data frame.
Lets calculate current ratio which is defined by
$$ Current Ratio = \frac{Current Assets}{Current Liabilities} $$
With dplyr package we can usemutate,select ortransmute functions:
By usingfinstr::calculate function we can achieve the same result but don't have to handle the date field and there is a rounding parameter. Lets calculate for example two ratios:
If we need a period average value we can use alag function. For example, to calculateDSO (days sales outstanding) over longer periods the average of account receivable is compared to net sales.
In this case we need to connect two type of statements: balance sheets and income statements. With matching reporting periods it can be accomplished with joining two data frames:
The leading dot instructs the calculate function to hide the value. In our case only DaysSalesOutstanding is selected in final result. Usedigits parameter to control rounding.
Reusing calculations
When running same calculation for different statements, define the calculation withcalculation and callcalculate with argumentcalculations:
# define calculationprofit_margins<- calculation(Gross_Margin= (SalesRevenueNet-CostOfGoodsAndServicesSold)/SalesRevenueNet,Operating_Margin=OperatingIncomeLoss/SalesRevenueNet,Net_Margin=NetIncomeLoss/SalesRevenueNet )# run profit margins for two different statementsincome2013 %>% calculate(calculations=profit_margins,digits=2)#> date Gross_Margin Operating_Margin Net_Margin#> 1 2011-09-24 0.40 0.31 0.24#> 2 2012-09-29 0.44 0.35 0.27#> 3 2013-09-28 0.38 0.29 0.22income2014 %>% calculate(calculations=profit_margins,digits=2)#> date Gross_Margin Operating_Margin Net_Margin#> 1 2012-09-29 0.44 0.35 0.27#> 2 2013-09-28 0.38 0.29 0.22#> 3 2014-09-27 0.39 0.29 0.22
Rearranging statement hierarchy
Calculations gives us freedom to use any formula with any data from financial statements. Most of the time this is not necessary as we can get useful information just by regrouping calculation hierarchy.
There are many additional reasons why is rearranging statements useful step before actual calculations:
We can avoid errors in formulas with many variables
Accounting taxonomies do change and using many formulas on original statement is harder to support than using custom hierarchy for analysis starting point
When sharing analysis it is much easier to print 6 values instead of 30
To rearrange the statement to simple 2-level hierarchy useexpose function.
Balance sheet stays divided byAssets andLiabilities and Equity. For the second level we are exposingcurrent assets fromnoncurrent and similar is done for theliabilities. We choose to separateequity.
Functionexpose expects a list of vectors with element names. Functionother helps us identify elements without enumerating every single element. Usingother reduces a lot of potential errors as the function "knows" which elements are not specified and keeps the balance sheet complete.
Sometimes it is easier to define a complement than a list of elements. In this case we can use the%without% operator. Lets expose for exampletangible and thenintangible assets:
The only way to visualize a balance sheet is by exposing a limited number of values. The first step is then to aggregate a balance sheet by selected concepts. We can useexpose to specify these groups of elements. For example: