## Fama French type summary tables

Eugene Fama and Kenneth French popularized the use of summary tables in empirical asset pricing research. For example, in their influential 2015 paper “A Five-Factor Asset Pricing Model”, they present Table 2 showing the average returns of portfolios formed on size, book-to-market equity (B/M), profitability, and investment.

Fama-French form these portfolios by sorting stocks into groups based on characteristics like size and B/M. The table shows the average monthly returns of the portfolios over the sample period, allowing analysis of how returns vary across sorts. This helps identify patterns like the size effect, value effect, profitability effect, and investment effect documented by Fama-French.

We can replicate similar portfolio sorting and return analysis in Stata using the `crosstab`

command, that is part of the asdocx package. The syntax for `crosstab`

is simple:

## Syntax

`asdocx crosstab row col, returns(varname) [weight(varname) time(varname)`

`rowtotal coltotal ]`

The main program is `asdocx`

which handles exporting Stata tables to Word or Excel formats.

The first argument to `asdocx`

is the crosstab command that generates the table to export. After `crosstab`

, the first word is the *row* variable. This variable must be grouped into categories like tertiles, quartiles, quintiles etc. The second word after crosstab is the *column* variable. Like the row variable, this must also be grouped into categories.

The `ret()`

option specifies which variable contains the stock returns to calculate statistics on. For example, `ret(mret)`

calculates statistics like the mean on the `mret`

variable.

The last four options are optional. The `time()`

option takes a date variable that identifies the time period like month or year. For example, `time(mdate)`

would calculate monthly period returns based on the `mdate`

variable. The `weight()`

option allows weighting the calculated statistics like the mean. For example, `weight(MCAP)`

would take a variable MCAP containing market capitalization values to calculate value-weighted mean returns.

Options `rowtotal`

and `coltotal`

can be used to report row and column totals.

## Use of value labels

It is recommended to assign value labels to the different categories of the row and column variables before creating the table. This will make the table more readable and understandable for the reader. The following code snippet shows how to create quintiles of the BEME and MCAP variables and assign value labels to them. The size quintiles are labeled as Small, 2, 3, 4, Large, and the book-to-market quintiles are labeled as Low, 2, 3, 4, High.

`* Load an example dataset`

use https://asdocx.com/portfolios.dta, clear

* First create 5 groups of size and book-to-market in each year

bys year: astile bm5 = BEME, nq(5)

bys year: astile sz5 = MCAP, nq(5)

* Assign value and variable labels for better readability

label define bmlabel 1 "Low" 2 "2" 3 "3" 4 "4" 5 "High"

label values bm5 bmlabel

label var bm5 "Book-to-market"

* similarly assign labels to the size variable

label define szlabel 1 "Small" 2 "2" 3 "3" 4 "4" 5 "Large"

label values sz5 szlabel

label var sz5 "Size"

### Example 1: Weighted means in crosstabs

In the following examples, we shall create 5 groups of book-to-market and 5 groups of size in each year using the astile program, which can be downloaded from the SSC by typing: `ssc install astile`

`* Report size in rows and BEME in rows, use MCAP as a weighting variable`

* mdate is the monthly date and mret are monthly returnsasdocx crosstab sz5 bm5, ret(mret) time(mdate) weight(MCAP) ///

`title(Table 1: Average Returns of Portfolios, by size and book-to-market)`

**\text{Table\; 1:\; Average\; returns\; of\; portfolios,\; by\; size\; and\; book\; to\; market}**

\text{Book-to-market} | ||||||
---|---|---|---|---|---|---|

\text{Size} |
Low | 2 | 3 | 4 | \text{ High} | \text{ High-Low} |

\text{ Small } | \text{ 1.270} | 0.625 | 1.052 | 0.147 | 0.966 | -0.304 |

2 | 0.583 | 0.931 | 0.614 | 0.038 | 0.627 | 0.044 |

3 | 0.683 | 0.553 | 0.324 | 0.646 | 0.575 | -0.108 |

4 | 0.324 | 0.538 | 0.439 | 0.462 | 0.566 | 0.242 |

\text{ Large} | 0.449 | 0.769 | 0.412 | 0.363 | 1.035 | 0.5860** |

\text{High-Low} | -0.82** | 0.144 | -0.64*** | 0.216 | 0.069 | |

*** p<0.01, ** p<.05, * p<00.1 |

## Formulas

### Average of averages by time

The `timevar()`

option can be utilized to weight reported averages by a time variable. For instance, if we have monthly data and our monthly date variable is named `mdate`

, the `timevar(mdate)`

option will calculate a weighted average of the statistics variable for each month. It will then report the average of these monthly averages in a table at the intersection of the specified row and column variables. Thus, the results presented in Table 1 are based on the following equation:

### \bar R = \dfrac{1}{m}\sum_{t=1}^m \dfrac{\sum_{j,k=1}^{n} W_{jkt} \cdot R_{jkt}}{n},

where \bar R refers to the weighted average of the monthly averages of stock returns. The outermost summation runs over all months from 1 to m. Each $t$ corresponds to a specific month within the time period under consideration. The innermost summation runs over all observations within a particular month, where two characteristics are considered:

- j represents the book-to-market ratio for an observation.
- k represents the size for an observation.

R_{jk,t} denotes the stock return for the particular observation with the given j and k in month t. W_{jk,t} is the weight for observation j,k in month t.

n represents the number of stocks in a given month for a given pair of j and k.

m is the total number of months.

**When to use the timevar() option?**

The `timevar()`

option is used to indicate that the data is at the stock level (just like the `portfolios.dta`

dataset that we used in Example 1 above). If you have already calculated the weighted portfolio returns for each pair of j and k, then you should drop the `timevar()`

option. However, if your data is still at the stock level, you should use the `timevar()`

option.

### Example 2: Equal weighted returns

To calculate returns where each stock contributes equally regardless of its weight in the portfolio, you can omit the `weight()`

option. This will calculate returns for each portfolio by giving equal weight to all stocks.

`* Equally-weighted portfolio returns`

asdocx crosstab sz5 bm5, ret(mret) time(mdate) ///

`title(Table 2: Average Returns of Portfolios, by size and book-to-market)`

**\text{Table 2: Equally-weighted portfolio returns by size and book-to-market}**

\text{Book-to-market} | ||||||
---|---|---|---|---|---|---|

\text{Size} |
\text{ Low} | 2 | 3 | 4 | \text{ High} | \text{ High-Low} |

\text{ Small} | 1.237 | 0.601 | 0.922 | 0.228 | 1.013 | -0.224 |

2 | 0.654 | 0.951 | 0.616 | 0.007 | 0.672 | 0.018 |

3 | 0.691 | 0.578 | 0.407 | 0.629 | 0.590 | -0.101 |

4 | 0.381 | 0.590 | 0.392 | 0.523 | 0.549 | 0.168 |

\text{ Large} | 0.439 | 0.629 | 0.354 | 0.441 | 1.024 | 0.5851* * |

\text{ High-Low} | -0.79** | 0.028 | -0.56*** | 0.214 | 0.011 | |

*** p<0.01, ** p<0.05, * p<0.10 |

### Example 3: Report row and column totals

The `rowtotal`

and `coltotal`

options can be used to add row and column totals to a table. These options are useful for summarizing data and identifying trends, such as total returns across rows and columns.

`* Add row total and column totals`

asdocx crosstab sz5 bm5, ret(mret) time(mdate) rowtal coltotal w(MCAP)

**Table 3: Report row and column totals**

Book-to-market | |||||||
---|---|---|---|---|---|---|---|

Size |
Low | 2 | 3 | 4 | High | Total | High-Low |

Small | 1.270 | 0.625 | 1.052 | 0.147 | 0.966 | 0.692 | -0.304 |

2 | 0.583 | 0.931 | 0.614 | 0.038 | 0.627 | 0.562 | 0.044 |

3 | 0.683 | 0.553 | 0.324 | 0.646 | 0.575 | 0.556 | -0.108 |

4 | 0.324 | 0.538 | 0.439 | 0.462 | 0.566 | 0.472 | 0.242 |

Large | 0.449 | 0.769 | 0.412 | 0.363 | 1.035 | 0.512 | 0.5860** |

Total | 0.460 | 0.673 | 0.440 | 0.358 | 0.765 | ||

High-Low | -0.8211** | 0.144 | -0.6408*** | 0.216 | 0.069 | ||

*** p<0.01, ** p<0.05, * p<0.10 |

### See also

- tabulate, tab1, tab2 – Stata official tabulation commands
- tabmany – Table of multiple coded answers
- mrtab – One- and two-way tables of multiple responses
- tabcount – tabulates frequencies for up to 7 variables
- fre – univariate tabulations
- tab3way – Three way table of frequencies and percentages
- missings – Various utilities for managing missing values
- pctab – report percentages in cross-tabulations

### Order asdocx

Yearly license of asdocx is available at $9.99. Its life-time license is available at $49.99. With the asdocx membership, you get :

- Life-time license to use
- All future updates
- All premium templates / plugins.