% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/compute_portfolio_returns.R
\name{compute_portfolio_returns}
\alias{compute_portfolio_returns}
\title{Compute Portfolio Returns}
\usage{
compute_portfolio_returns(
  data,
  sorting_variables,
  sorting_method,
  rebalancing_month = NULL,
  breakpoint_options_main,
  breakpoint_options_secondary = NULL,
  breakpoint_function_main = compute_breakpoints,
  breakpoint_function_secondary = compute_breakpoints,
  min_portfolio_size = 1L,
  cap_weight = 0.8,
  data_options = NULL,
  quiet = FALSE
)
}
\arguments{
\item{data}{A data frame containing the dataset for portfolio assignment
and return computation. The panel data must include individual stock
identifiers and the time point. It must contain columns for the sorting
variables and excess returns. Additionally, lagged market capitalization
is required for value-weighted returns (see parameter \code{data_options}).}

\item{sorting_variables}{A character vector specifying the column names in
\code{data} to be used for sorting and determining portfolio assignments. For
univariate sorts, provide a single variable. For bivariate sorts, provide
two variables, where the first string refers to the main variable and the
second string refers to the secondary ("control") variable.}

\item{sorting_method}{A string specifying the sorting method to be used.
Possible values are:
\itemize{
\item \code{"univariate"}: For a single sorting variable.
\item \code{"bivariate-dependent"}: For two sorting variables, where the
main sort depends on the secondary variable.
\item \code{"bivariate-independent"}: For two independent sorting variables.
}
For bivariate sorts, the portfolio returns are averaged over the
controlling sorting variable (i.e., the second sorting variable), and only
portfolio returns for the main sorting variable (given as the first
element of \code{sorting_variables}) are returned.}

\item{rebalancing_month}{An integer between 1 and 12 specifying the month
in which to form portfolios that are held constant for one year. For
example, setting it to \code{7} creates portfolios in July that are held
constant until June of the following year. The default \code{NULL} corresponds
to periodic rebalancing.}

\item{breakpoint_options_main}{A named list of \code{\link[=breakpoint_options]{breakpoint_options()}}
passed to \code{breakpoint_function_main} for the main sorting variable.}

\item{breakpoint_options_secondary}{An optional named list of
\code{\link[=breakpoint_options]{breakpoint_options()}} passed to \code{breakpoint_function_secondary}.}

\item{breakpoint_function_main}{A function to compute the breakpoints for
the main sorting variable. The default is set to \code{\link[=compute_breakpoints]{compute_breakpoints()}}.}

\item{breakpoint_function_secondary}{A function to compute the breakpoints
for the secondary sorting variable. The default is set to
\code{\link[=compute_breakpoints]{compute_breakpoints()}}.}

\item{min_portfolio_size}{An integer specifying the minimum number of
firms required in the reported portfolio cross-section on a given date
(default \code{1L}, i.e. at least one observation per reported portfolio).
For both univariate and bivariate sorts the threshold is applied to the
firm count per \verb{(portfolio, date)} of the reported cross-section: for
univariate sorts that is firms per portfolio-date; for bivariate sorts
that is firms per main-portfolio-date summed across the secondary
buckets. Cross-sections below the threshold have their returns set to
\code{NA}. A typical value is \code{5L} (the Fama-French convention). Set to \code{0L}
to deactivate the check entirely.}

\item{cap_weight}{A numeric value between 0 and 1 specifying the percentile
at which market capitalization is capped per date when computing capped
value-weighted excess returns (i.e., \code{ret_excess_vw_capped}). Defaults to
\code{0.8}.}

\item{data_options}{A list of class \code{tidyfinance_data_options} (created via
\code{\link[=data_options]{data_options()}}) specifying column name mappings. The \code{id} element is
used to specify the entity (i.e., firm), \code{date} is used to specify the
date column, \code{ret_excess} is used to specify the excess return column, and
\code{mktcap_lag} is used to specify the market capitalization. Uses
\code{\link[=data_options]{data_options()}} default if \code{NULL}: \code{"id" = "permno"},
\code{"date" = "date"}, \code{"ret_excess" = "ret_excess"}, and
\code{"mktcap_lag" = "mktcap_lag"}.}

\item{quiet}{A logical value indicating whether to suppress informational
messages about missing values in the output panel (default is \code{FALSE}).}
}
\value{
A data frame with computed portfolio returns as a complete panel
(all portfolio-date combinations), containing the following columns:
\itemize{
\item \code{portfolio}: The portfolio identifier.
\item \code{date}: The date of the portfolio return.
\item \code{ret_excess_vw}: The value-weighted excess return of the
portfolio (only computed if \code{data} contains a lagged market
capitalization column specified by \code{data_options()}, which defaults
to \code{mktcap_lag}). \code{NA} if insufficient observations for that
portfolio-date.
\item \code{ret_excess_ew}: The equal-weighted excess return of the
portfolio. \code{NA} if insufficient observations for that portfolio-date.
\item \code{ret_excess_vw_capped}: The capped value-weighted excess return
of the portfolio (only computed if \code{data} contains a lagged market
capitalization column specified by \code{data_options()}, which defaults
to \code{mktcap_lag}). Weights are computed using market capitalization
capped at the \code{cap_weight} percentile per date. \code{NA} if insufficient
observations for that portfolio-date.
}
}
\description{
Computes individual portfolio returns based on specified sorting variables
and sorting methods. The portfolios can be rebalanced every period or on an
annual frequency by specifying a rebalancing month, which is only applicable
at a monthly return frequency. The function supports univariate and
bivariate sorts, with the latter supporting dependent and independent
sorting methods.
}
\details{
The function checks for consistency in the provided arguments. For
univariate sorts, a single sorting variable and a corresponding number of
portfolios must be provided. For bivariate sorts, two sorting variables and
two corresponding numbers of portfolios (or percentiles) are required. The
sorting method determines how portfolios are assigned and how returns are
computed. The function handles missing and extreme values appropriately
based on the specified sorting method and rebalancing frequency.
}
\note{
Ensure that \code{data} contains all required columns: the specified
sorting variables and excess returns (see options and defaults set in
\code{data_options}). The function will stop and throw an error if any required
columns are missing.
}
\examples{
set.seed(42)
# Univariate sorting with periodic rebalancing
data <- data.frame(
  permno = 1:500,
  date = rep(
    seq.Date(
      from = as.Date("2020-01-01"),
      by = "month",
      length.out = 100
    ),
    each = 10
  ),
  mktcap_lag = runif(500, 100, 1000),
  ret_excess = rnorm(500),
  size = runif(500, 50, 150)
)

compute_portfolio_returns(
  data, "size", "univariate",
  breakpoint_options_main = breakpoint_options(n_portfolios = 5)
)

# Bivariate dependent sorting with annual rebalancing
compute_portfolio_returns(
  data, c("size", "mktcap_lag"), "bivariate-dependent", 7,
  breakpoint_options_main = breakpoint_options(n_portfolios = 5),
  breakpoint_options_secondary = breakpoint_options(n_portfolios = 3),
)

}
\seealso{
Other portfolio functions: 
\code{\link{assign_portfolio}()},
\code{\link{breakpoint_options}()},
\code{\link{compute_breakpoints}()},
\code{\link{compute_long_short_returns}()},
\code{\link{data_options}()},
\code{\link{filter_options}()},
\code{\link{filter_sorting_data}()},
\code{\link{implement_portfolio_sort}()},
\code{\link{portfolio_sort_options}()}
}
\concept{portfolio functions}
