The hardware and bandwidth for this mirror is donated by METANET, the Webhosting and Full Service-Cloud Provider.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]metanet.ch.
sharpeTesting() and msharpeTesting(). Both
replaced the observed difference by Δ̂ - d and then centred
the bootstrap draws on that quantity, so the reference distribution was
shifted by the hypothesised value d instead of being
centred on the estimate. The test statistic itself was correct, so the
default d = 0 was never affected; but the automatic
block-length selectors pass the observed difference as d,
so every rejection rate in their calibration loop was computed from a
mis-centred distribution and bBoot = 0 returned an
essentially arbitrary block length. The draws are now centred on the
estimateminObsPi is enforced on each focal fund’s final count
of valid peers, in the cross-group path as well as the within-group one;
cross-group screening previously ignored it, and unbalanced panels could
give results that depended on the order of the columnsalphaTesting() estimates both reported alphas on the
same concordant sample as the difference it tests. They were previously
fitted on each fund’s own available observations, so the two reported
alphas need not have differed by the reported dalphadsharpe and dmsharpe hold raw ratio
differences in all screening paths. With the default
ttype = 2 the screenings stored the cross-multiplied
statistic under a field named as a difference, while the pairwise tests
returned the raw difference – the same name meant two different things.
The tests continue to use the product statistic internallybootIndices()
drew floor(T / bBoot) blocks, so the last
T %% bBoot indices of every bootstrap sample kept their
initial value of zero; because the callers remap indices with
1 + ids %% T, each of those zeros silently selected the
first observation. At T = 50 and bBoot = 6
this over-sampled observation 1 by a factor of about three and biased
the bootstrap null distribution, with no error or NA to
signal it. The routine now draws ceiling(T / bBoot) blocks
and keeps the first T indices. Results are unchanged when
bBoot divides T, and the default
bBoot = 1 was never affectedinfoFund() called lm() on every column, so an
all-NA fund stopped the whole run with “0 (non-NA) cases”
even though the pairwise stage handles such a column correctly. Its
summary statistics are now returned as NAis.na() and is.nan(), so an
Inf counted as an observation and the fit then failed with
“NA/NaN/Inf in ‘y’”. Inf and NaN are now
normalised to NA on entry, and a series containing one
gives exactly the result it would give with NA in the same
positionbBoot = 0 (data-driven block length) works on series
containing NA in sharpeTesting() and
msharpeTesting(): the block-length routines were passed the
raw series rather than the concordant observations the test itself uses,
so they returned NA and the bootstrap then failed with a
subscript errorscreen_beta screening or
alphaTesting(). summary(lm) omits inestimable
coefficients, so indexing its table by position over-ran it and could
read a neighbouring coefficient; coefficients are now matched by name
and inestimable ones are reported as NAcontrol$fastAdjust (default
FALSE): the truncated-normal bias correction of
pi0 inverts its monotone map for the whole vector at once
(vectorised bisection) instead of one uniroot() call per
value. This is the dominant cost of a screening with a data-driven
lambda – a 100-fund alphaScreening() drops
from about 19s to about 4.5s (4.2x). The bisection locates the root to
about 1e-12; because uniroot stops at its own tolerance
(about 1.2e-4), the two paths typically differ by a few 1e-5, the fast
path being the more accurate. The original code path remains the default
so that published results reproduce exactly. Bootstrap indices are now
built only for the bootstrap test (type = 2), so the
asymptotic path no longer depends on bBootbBoot > 1);
pairs shorter than the block length are left untested; balanced panels
are unaffected. All randomness stays in the master, so seeded results do
not depend on nCorenCore = 1 (the default) now runs serially without
creating a PSOCK cluster, removing the per-call cluster overhead
(noticeable in rollScreening’s window loop); results are
identical to the cluster path>=, consistent with the modified Sharpe test (ties have
probability zero for continuous returns)alphaScreening
clarified; the gammaPos/gammaNeg counting
rules are stated explicitly; misleading “bootstrap and HAC” example
headers fixed (hac is ignored when type = 2);
summary documents that win/loss counts are within-group
onlyon.exit() so workers are not leaked on error;
processControl requires the count-like controls
(nBoot, bBoot, nCore,
minObs, minObsPi) to be whole numbers and
rejects a bootstrap block length exceeding the sample size; within-group
screening and cross-group screening now stop with a clear message on
degenerate inputs (a single fund, an empty peer group)alphaScreening/alphaTesting now enforce
minObs on the factor complete-case sample (factor
NAs were previously ignored), and
alphaTesting(screen_beta = TRUE, hac = TRUE) now returns
the alpha component as a coefficient-by-fund matrix,
consistent with the non-HAC path (the print method reports
the alpha row)confint is now tested for all three ratios
(pipos/pizero/pineg)confint method for SCREENING
objects: nonparametric peer (pairwise) bootstrap confidence intervals
for the peer performance ratios
(pipos/pizero/pineg)system.file("scripts", "validation.R", package = "PeerPerformance")):
checks the near-unbiasedness of pizero under the
equal-performance null and the size/power of the modified Sharpe
equality testpkgdown configuration, and a
package CITATION entryprocessControl now validates that scalar
control values are single finite numbers / logicals;
computePi checks the lambda length;
targetPeerPerformance rejects non-whole funds;
rollScreening validates by and only flags
screen_beta for the alpha screen with factors; output fund
names are preserved in as.data.frame and
targetPeerPerformancesharpeScreening/msharpeScreening on unbalanced
panels: the focal fund’s returns were indexed with the first peer’s
missing-value mask (X[idx[, k], 1]) instead of the current
pair’s (X[idx[, k], k]), which could inject
NAs and yield NaN p-values for some pairs
(reported by GitHub user NenoJo)targetPeerPerformance() (contributed by Murilo
Andre Peres Pereira): screens a selected subset of funds against the
whole universe; a convenience wrapper over the cross-group screening
(*Screening(X[, funds], Y = X))summary method for SCREENING
objects (contributed by Murilo Andre Peres Pereira): ranked table,
distribution of the measure, win/loss counts and top fundsrollScreening(): rolling-window screening
returning the time series of cross-sectionally averaged ratios (per
factor when screen_beta = TRUE), with a plot
method – the dynamic design of Ardia et al. (2022, 2023)plot on a cross-group screening omits the
(within-group) percentile-rank diagonal; a single focal fund is shown as
one stacked barscreen_beta can now also be set through
control (e.g.
control = list(screen_beta = TRUE)); the function argument
still works and takes precedencealphaScreening,
sharpeScreening and msharpeScreening gain a
Y argument to screen each fund in X against a
second peer group Y (a single focal fund versus a group is
X a vector); columns of Y identical to the
focal fund are excluded automaticallyas.data.frame method for SCREENING
objects (tidy, one row per fund, or per fund/coefficient with
screen_beta = TRUE)screen_beta = TRUE output now labels the coefficient
rows (alpha + factor names), and exposureHeterogeneity()
aggregates them into the factor exposure heterogeneity measure of Ardia
et al. (2023), with a plot methodprint methods for the TESTING and
SCREENING objects, and a plot method for the
SCREENING object that reproduces the peer performance
screening plot of Ardia and Boudt (2018)gammaPos and gammaNeg (default 0.4 and
0.6) are now exposed in the control list of the screening
functions, controlling the one-sided thresholds used for the out- and
underperformance countsnBoot = 499) when an empty control list is
suppliedsharpeBlockSize, msharpeBlockSize):
the lagged cross term in the second equation now uses the correct
seriessharpe() now counts observations with
is.finite(), consistent with the other moment computations,
when NA/NaN are presentDepends to
ImportsalphaTesting return values)These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.