@@ -498,9 +498,7 @@ function cagr(returns::AbstractVector, periods_per_year::Real; method::Symbol=:s
498498 n == 0 && return 0.0
499499 ppy = float (periods_per_year)
500500 (! isfinite (ppy) || ppy <= 0 ) && throw (
501- ArgumentError (
502- " periods_per_year must be positive and finite (got $(periods_per_year) )." ,
503- ),
501+ ArgumentError (" periods_per_year must be positive and finite (got $(periods_per_year) )." )
504502 )
505503 years = n / ppy
506504 T = promote_type (eltype (returns), Float64)
@@ -522,3 +520,40 @@ function cagr(returns::AbstractVector, periods_per_year::Real; method::Symbol=:s
522520
523521 throw (ArgumentError (" Invalid method $(method) . Use :simple or :log." ))
524522end
523+
524+ """
525+ annualized_return(returns::AbstractVector, periods_per_year::Real)
526+
527+ Compute the arithmetic annualized return by scaling the average periodic return.
528+ This matches the common "expected annual return" metric on fact sheets where the
529+ per-period arithmetic mean is multiplied by the observation frequency.
530+
531+ # Arguments
532+ - `returns`: Vector of periodic simple (arithmetic) returns.
533+ - `periods_per_year`: Number of periods per calendar year (e.g. 252, 12, 52).
534+
535+ # Formula
536+
537+ Let `μ = mean(returns)` and `k = periods_per_year`. Then
538+
539+ ``AnnualizedReturn = μ × k``
540+
541+ # Edge Cases
542+ - Returns `0.0` if `returns` is empty.
543+ - Throws `ArgumentError` when `periods_per_year` is non-positive or non-finite.
544+ """
545+ function annualized_return (returns:: AbstractVector , periods_per_year:: Real )
546+ n = length (returns)
547+ n == 0 && return 0.0
548+ ppy = float (periods_per_year)
549+ (! isfinite (ppy) || ppy <= 0 ) && throw (
550+ ArgumentError (" periods_per_year must be positive and finite (got $(periods_per_year) )." )
551+ )
552+ T = promote_type (eltype (returns), Float64)
553+ s = zero (T)
554+ @inbounds for r in returns
555+ s += T (r)
556+ end
557+ μ = s / T (n)
558+ μ * T (ppy)
559+ end
0 commit comments