20namespace metric_detail {
24 std::size_t count_{0};
29 bool constant_{
false};
43 const Scalar count = parts.present_.sum();
44 result.count_ =
static_cast<std::size_t
>(count);
45 if (result.count_ == 0) {
48 result.mean_ = parts.values_.sum() / count;
49 result.squared_ = (parts.values_ - result.mean_ * parts.present_).squaredNorm();
50 if (result.count_ >= 2) {
51 const Scalar deviation = std::sqrt(result.squared_ /
static_cast<Scalar>(result.count_ - 1));
52 result.constant_ = constant_detail::rounded_constant(
53 deviation, result.mean_, result.count_, parts.values_, parts.present_, 0, parts.values_.size()
88 std::size_t observations = 0;
89 for (
math::Index row = 0; row < levels.size(); ++row) {
94 if (peak_row < 0 || peak < levels[row]) {
101 const Scalar decline = (peak - levels[row]) / peak;
128 const auto summary = metric_detail::summarize(period_returns);
129 if (summary.count_ < 2) {
133 std::sqrt(summary.squared_ /
static_cast<Scalar>(summary.count_ - 1));
134 if (deviation ==
Scalar{0} || summary.constant_) {
139 return (summary.mean_ - risk_free) / deviation;
154 std::size_t count = 0;
155 std::size_t below = 0;
158 for (
math::Index row = 0; row < period_returns.size(); ++row) {
159 const Scalar value = period_returns[row];
165 if (value < target) {
167 const Scalar gap = target - value;
168 shortfall += gap * gap;
183 const Scalar downside = std::sqrt(shortfall /
static_cast<Scalar>(count));
184 if (downside ==
Scalar{0}) {
187 return (sum /
static_cast<Scalar>(count) - target) / downside;
201 if (!(periods_per_year >
Scalar{0})) {
202 throw std::invalid_argument(
"periods per year must be positive");
204 return observed(ratio) ? ratio * std::sqrt(periods_per_year) : ratio;
232 (weights.array() == weights.array()).select(weights,
Scalar{0});
234 for (
math::Index row = 0; row < held.rows(); ++row) {
239 result[row] =
Scalar{0.5} * held.row(0).cwiseAbs().sum();
242 result[row] =
Scalar{0.5} * (held.row(row) - held.row(row - 1)).cwiseAbs().sum();
Returns, rolling statistics, indicators and performance metrics over numeric series.
bool observed(Scalar value)
Tests whether a value is an observation; see math::observed.
math::Vector one_way_turnover(math::MatrixView weights, TurnoverStart start=TurnoverStart::FROM_CASH)
Computes the one-way turnover of each period, 0.5 * sum(|w[i] - w[i - 1]|).
TurnoverStart
How turnover treats the first period.
@ FROM_CASH
Row 0 measures the first positions against an all-cash start. Use it to cost one strategy.
@ SKIP
Row 0 is missing(). Use it to compare strategies whose histories start on different dates.
Scalar sortino(math::SeriesView period_returns, Scalar target=Scalar{0})
Computes the per-period Sortino ratio, (mean(returns) - target) / downside_deviation.
Scalar annualize_ratio(Scalar ratio, Scalar periods_per_year)
Annualizes a per-period ratio by multiplying it by sqrt(periods_per_year).
math::Vector two_way_turnover(math::MatrixView weights, TurnoverStart start=TurnoverStart::FROM_CASH)
Computes the two-way turnover of each period, sum(|w[i] - w[i - 1]|).
MaxDrawdown max_drawdown(math::SeriesView levels)
Finds the worst peak-to-trough decline of a level series.
Scalar missing()
Returns the value that stands for "no observation"; see math::missing.
Scalar sharpe(math::SeriesView period_returns, Scalar risk_free=Scalar{0})
Computes the per-period Sharpe ratio, (mean(returns) - risk_free) / stdev(returns).
Observed observed_parts(SeriesView values)
Splits a series into zero-filled values and a presence mask.
double Scalar
The floating-point type the analytics and math layers compute in (double).
Eigen::Matrix< Scalar, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor > Matrix
A dense, column-major matrix of Scalar.
Eigen::Index Index
The signed index type of rows and columns.
Scalar undefined()
Returns the value that stands for "the data was there, but the statistic does not exist".
Vector unobserved(std::size_t count)
Makes a vector filled with missing().
Eigen::Ref< const Matrix > MatrixView
A read-only reference to a whole matrix.
Eigen::Matrix< Scalar, Eigen::Dynamic, 1 > Vector
A dense column vector of Scalar.
Eigen::Ref< const Vector > SeriesView
A read-only reference to one series.
The library: broker-neutral types (core), and the modules below.
Re-exports math::Scalar, math::missing and math::observed into analytics.
The worst peak-to-trough decline of a level series, and where it happened.
math::Index peak_row_
The row of the peak the decline fell from, or -1 if there is none.
math::Index trough_row_
The row of the low the decline reached, or -1 if there is none.
Scalar magnitude_
The decline as a non-negative fraction of the peak (0.2 is 20% below it).