## Set of R functions for Sharpe ratio testing

#@name .alphaTesting
#@description See alphaTesting
# .alphaTesting <- function(x, y, factors=NULL, control=list()){
# 	X <- cbind(x, y)
# 	screen <- alphaScreening(X, factors, control)
# 	out <- list(n = screen$n[[1]], alpha = screen$alpha, dalpha = screen$dalpha[1,2],
# 				tstat = screen$tstat[1,2], pval = screen$pval[1,2])
# 	class(out) <- "TESTING"
# 	return(out)
# }

.alphaTesting <- function(x, y, factors=NULL, control=list(), screen_beta=NULL){
	# process control
	ctr <- processControl(control)
	hac <- ctr$hac
	# screen_beta: argument takes precedence, else fall back to control
	if (is.null(screen_beta)) {
		screen_beta <- ctr$screen_beta
	}
	# screen_beta only makes sense with factors
	if (isTRUE(screen_beta) && is.null(factors)) {
		warning("'screen_beta = TRUE' requires 'factors'; it is ignored.")
		screen_beta <- FALSE
	}
	X <- as.matrix(x)
	Y <- as.matrix(y)
	dXY <- X - Y
	# usable observations = rows where the return differential and (when
	# supplied) the factors are all observed
	if (is.null(factors)) {
		ok <- stats::complete.cases(dXY)
	} else {
		ok <- stats::complete.cases(dXY, factors)
	}
	nObs <- sum(ok)
	if (nObs < ctr$minObs) {
		stop("fewer than 'control$minObs' usable observations to compare the two funds")
	}
	N <- 2


	if (screen_beta & !is.null(factors)) {
		n_coef <- ncol(factors) + 1
		row_return <- 1:n_coef
	} else {
		row_return <- 1
	}

	if (is.null(factors)) {
		fit <- stats::lm(dXY ~ 1, na.action = stats::na.omit)
		fitX <- stats::lm(X ~ 1, na.action = stats::na.omit)
		fitY <- stats::lm(Y ~ 1, na.action = stats::na.omit)
	} else {
		beta <- factors
		fit <- stats::lm(dXY ~ 1 + beta, na.action = stats::na.omit)
		fitX <- stats::lm(X ~ 1 + beta, na.action = stats::na.omit)
		fitY <- stats::lm(Y ~ 1 + beta, na.action = stats::na.omit)
	} # end of factors/no factors

	# HAC within loop.
	if (!hac) {
		sumfit <- summary(fit)
		sumfitX <- summary(fitX)
		sumfitY <- summary(fitY)
		alpha <- cbind(sumfitX$coef[row_return,1], sumfitY$coef[row_return,1])
		pval <- sumfit$coef[row_return, 4]
		dalpha <- sumfit$coef[row_return, 1]
		tstat <- sumfit$coef[row_return, 3]
	} else {
		sumfit <- lmtest::coeftest(fit, vcov. = sandwich::vcovHAC(fit))
		sumfitX <- lmtest::coeftest(fitX, vcov. = sandwich::vcovHAC(fitX))
		sumfitY <- lmtest::coeftest(fitY, vcov. = sandwich::vcovHAC(fitY))
		alpha <- cbind(sumfitX[row_return,1], sumfitY[row_return,1])
		pval <- sumfit[row_return, 4]
		dalpha <- sumfit[row_return, 1]
		tstat <- sumfit[row_return, 3]
	}

	out <- list(n = nObs,
				alpha = alpha,
				dalpha = dalpha,
				tstat = tstat,
				pval = pval,
				screen_beta = screen_beta)
	class(out) <- "TESTING"
	return(out)
}

#' @name alphaTesting
#' @title Testing the difference of alpha outperformance ratios
#' @description Function which performs the testing of the difference of alpha outperformance ratios.
#' @details The alpha measure (Treynor and Black 1973, Carhart 1997, Fung and Hsieh
#' 2004) is one industry standard for measuring the absolute risk adjusted
#' performance of hedge funds. This function performs
#' the testing of alpha outperformance ratio difference for two funds.
#'
#' For the testing, only the intersection of non-\code{NA} observations for the
#' two funds are used.
#'
##' The argument \code{control} is a list that can supply any of the following
#' components:
#' \itemize{
#' \item \code{'hac'} Heteroscedastic-autocorrelation consistent
#' standard errors. Default: \code{hac = FALSE}.
#' }
#' @param x Vector (of length \eqn{T}) of returns for the first fund. \code{NA}
#' values are allowed.
#' @param y Vector (of length \eqn{T}) returns for the second fund. \code{NA}
#' values are allowed.
#' @param factors Matrix \eqn{(T \times K)}{(TxK)} of \eqn{T} returns for the
#' \eqn{K} factors. \code{NA} values are allowed.
#' @param screen_beta Boolean to screen all factors' coefficients (beta).
#' Default: \code{screen_beta = NULL}, in which case the value is taken from
#' \code{control$screen_beta} (itself defaulting to \code{FALSE}). When supplied
#' directly, the argument takes precedence. \code{screen_beta = TRUE} requires
#' \code{factors}.
#' @param control Control parameters (see *Details*).
#' @return A list with the following components:\cr
#'
#' \code{n}: Number of non-\code{NA} concordant observations.\cr
#'
#' \code{alpha}: Vector (of length 2) of the two funds' unconditional alphas.\cr
#'
#' \code{dalpha}: Difference of the two funds' alphas.\cr
#'
#' \code{tstat}: t-stat of the alpha difference.\cr
#'
#' \code{pval}: p-value of the test of equal alpha.\cr
#'
#' When \code{screen_beta = TRUE}, \code{alpha} is a matrix (one row per
#' coefficient, the first being the alpha) and \code{dalpha}, \code{tstat} and
#' \code{pval} are vectors with one entry per coefficient; the \code{print}
#' method reports the alpha (first) coefficient only.
#' @note Further details on the methodology with an application to the hedge
#' fund industry is given in Ardia and Boudt (2018).
#'
#' Some internal functions where adapted from Michael Wolf MATLAB code.
#' @author David Ardia and Kris Boudt.
#' @seealso \code{\link{alphaScreening}}.
#' @references
#' Ardia, D., Boudt, K. (2015).
#' Testing equality of modified Sharpe ratios.
#' \emph{Finance Research Letters} \bold{13}, 97--104.
#'
#' Ardia, D., Boudt, K. (2018).
#' The peer performance ratios of hedge funds.
#' \emph{Journal of Banking and Finance} \bold{87}, 351--368.
#'
#' Barras, L., Scaillet, O., Wermers, R. (2010).
#' False discoveries in mutual fund performance: Measuring luck in estimated alphas.
#' \emph{Journal of Finance} \bold{65}(1), 179--216.
#'
#' Sharpe, W.F. (1994).
#' The Sharpe ratio.
#' \emph{Journal of Portfolio Management} \bold{21}(1), 49--58.
#'
#' Ledoit, O., Wolf, M. (2008).
#' Robust performance hypothesis testing with the Sharpe ratio.
#' \emph{Journal of Empirical Finance} \bold{15}(5), 850--859.
#'
#' Storey, J. (2002).
#' A direct approach to false discovery rates.
#' \emph{Journal of the Royal Statistical Society B} \bold{64}(3), 479--498.
#' @keywords htest
#' @examples
#' ## Load the data (randomized data of monthly hedge fund returns)
#' data("hfdata")
#' x = hfdata[,1]
#' y = hfdata[,2]
#'
#' ## Run alpha testing
#' alphaTesting(x, y)

#' @export
#' @importFrom compiler cmpfun
alphaTesting <- compiler::cmpfun(.alphaTesting)
