Making Factor Construction Simple with Quotient
Factors are the key driver for active quantitative investment research. Factors are derived data items. The raw data item used to generate factors can be technical price and trading volume data, and fundamental data including financial statements and non-GAAP items provided by specific industries, e.g., same store sales provided by retailers. Factors can also be generated from new alternative data sources such as satellite images of retailer parking lots as proxy for retail store traffic or internet search trends for retailer specific addresses, again a proxy for retail store traffic.
Quotient makes factor construction easy. Quotient uses Python code to implement factor construction. Quotient simplifies factor construction by accessing complex data sources, sometimes with very complex structured query language SQL statements, and returning the data to Quotient in much more simplified construct, what we call Qubles. See our Introduction to Qubles blog for more information.
The following 9 Python code statements example is used to illustrate construction of a sales to enterprise value factor in Quotient. The following statements are as would be actual coded in Quotient minus the statement number, which is being used to refer to specific statements for this illustration.
The Python statements 1 & 2 determine how handle to missing values. The first statement tells Quotient to exclude observations with missing values after a multiplication or division operation. The second statement tells Quotient to include observations with missing values after an addition or subtraction operation.
(1) RootLib().set_control('ignore_mult', False)
(2) RootLib().set_control('ignore_add', 'right')
Statements 3 & 4 load the data source libraries. Each of these data source libraries are loaded through a Quotient Data Mapper. The Data Mapper informs Quotient on how to access the data from each data source. More information on the Data Mapper will be the subject of a future blog. The first statement loads data from the Datastream technical data source. The second statement loads the Reuters fundamental data source. A nice feature of Quotient’s factor construction is the ability to easily switch data sources for every raw data element of the same type, i.e., technical or fundamental, used in a factor. For example, in order to switch from Reuters fundamental data source to Reuters point-in-time fundamental data source, the Rootlib statement would be modified from 'Reuters Fnd (CFT)’ to 'Reuters Fnd (CFT PIT).' For more information on the advantages of using point-in-time fundamental data, see our blog on point-in-time fundamental data.
(3) ds = RootLib()['Datastream']
(4) rf = RootLib()['Reuters Fnd (CFT)']
Statement 5 sums the last 4 quarter of sales from the Reuters fundamental data source. The ‘rf’ statement after ‘=’ sign is instructing Quotient to use the Reuters fundamental data source as loaded in the statement 4. The ‘msum1d(4, 'Fiscal')’ statement retrieves that last 4 quarters of sales and sums them. This statement is a Quble method with 2 parameters provided. The ‘4’ parameter instructs Quotient to retrieve 4 quarter periods.
(5) sales_sum4q = rf['SALES_FI'].msum1d(4, 'Fiscal')
Statement 6 is retrieving shares outstanding and monthly closing stock price from Datastream to compute monthly market value ‘mkt_val.’ Since we have told Quotient to exclude missing values after a multiplication or division operation in statement 1, market value ‘mkt_val’ will be displayed as missing if either shares outstanding 'NUM_SHARES_M’ or monthly closing stock price 'CLOSE_M' is missing.
(6) mkt_val = 0.001 * ds['NUM_SHARES_M'] * ds['CLOSE_M']
Statement 7 combines the Datastream data sourced market value ‘mkt_val’ derived in statement 6 with long term debt and cash on hand from Reuters to derive enterprise value. Since we have told Quotient to ignore missing values after an addition or subtraction operation in statement 2, enterprise value ‘ev’ will be displayed as the sum of market value ‘mkt_val’ regardless of whether long term debt ‘LTD_FI’ and/or cash ‘CASH_FI’ is available.
(7) ev = mkt_val + rf['LTD_FI'] - rf['CASH_FI']
Statement 8 divides last 4 quarter sales ‘sales_sum4q’ by enterprise value ‘ev’ to compute sales to enterprise ‘sales2ev.’ Like statement 6, sales to enterprise value will be displayed as missing if enterprise value ‘ev’, or really market value ‘mkt_val,’ is missing due to the statement 1. Can you follow the program logic of why if really only market value ‘mkt_val’ is missing will sales to enterprise ‘sales2ev’ be displayed as missing? Hint: Look back at the logic in statement 7.
(8) sales2ev = sales_sum4q / ev
This final statement tells Quotient to return a Quble named sales2ev. For more on Qubles, see our Introduction to Qubles blog.
(9) return sales2ev