diff --git a/src/OnlinePortfolioAnalytics.jl b/src/OnlinePortfolioAnalytics.jl index f83138c..d35eef7 100644 --- a/src/OnlinePortfolioAnalytics.jl +++ b/src/OnlinePortfolioAnalytics.jl @@ -1,10 +1,11 @@ module OnlinePortfolioAnalytics using OnlineStatsBase -using OnlineStats: GeometricMean +#using OnlineStats: GeometricMean export SimpleAssetReturn, LogAssetReturn -export Mean, GeometricMean +export Mean # from OnlineStatsBase +export GeometricMeanReturn # different from OnlineStats: GeometricMean export StdDev export CumulativeReturn @@ -13,6 +14,7 @@ export fit!, value abstract type PortfolioAnalytics{T} <: OnlineStat{T} end include("asset_return.jl") +include("mean_return.jl") include("cumulative_return.jl") include("std_dev.jl") diff --git a/src/mean_return.jl b/src/mean_return.jl new file mode 100644 index 0000000..5057087 --- /dev/null +++ b/src/mean_return.jl @@ -0,0 +1,36 @@ +""" + Prod(T::Type = Float64) + +Track the overall prod. +""" +mutable struct Prod{T} <: OnlineStat{Number} + prod::T + n::Int +end +Prod(T::Type = Float64) = Prod(T(1), 0) +Base.prod(o::Prod) = o.prod +OnlineStatsBase._fit!(o::Prod{T}, x::Real) where {T<:AbstractFloat} = (o.prod *= convert(T, x); o.n += 1) +OnlineStatsBase._fit!(o::Prod{T}, x::Real) where {T<:Integer} = (o.prod *= round(T, x); o.n += 1) +OnlineStatsBase._fit!(o::Prod{T}, x::Real, n) where {T<:AbstractFloat} = (o.prod *= convert(T, x * n); o.n += n) +OnlineStatsBase._fit!(o::Prod{T}, x::Real, n) where {T<:Integer} = (o.prod *= round(T, x * n); o.n += n) +OnlineStatsBase._merge!(o::T, o2::T) where {T <: Prod} = (o.prod *= o2.prod; o.n += o2.n; o) + +# https://github.com/joshday/OnlineStatsBase.jl/issues/41 + +mutable struct GeometricMeanReturn{T} <: PortfolioAnalytics{T} + value::T + n::Int + + prod::Prod + + function GeometricMeanReturn{T}() where {T} + p = Prod() + new{T}(T(0), 0, p) + end +end + +function OnlineStatsBase._fit!(stat::GeometricMeanReturn, data) + fit!(stat.prod, 1 + data) + stat.n += 1 + stat.value = value(stat.prod) ^ (1 / stat.n) - 1 +end diff --git a/test/runtests.jl b/test/runtests.jl index de498f4..a61137f 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -169,9 +169,8 @@ const weights = [0.4, 0.4, 0.2] @testset "GeometricMeanReturn" begin source = from(TSLA) - #= _ret = SimpleAssetReturn{Float64}() - _mean = GeometricMean() + _mean = GeometricMeanReturn{Float64}() mapped_source = source |> map( @@ -189,14 +188,9 @@ const weights = [0.4, 0.4, 0.2] end subscribe!(mapped_source, observer) @test isapprox(mean_returns[end], 0.0342, atol = ATOL) - =# end @testset "CumulativeReturn" begin - #cum_ret = CumulativeReturn{Float64}() - #fit!(cum_ret, TSLA) - #@test isapprox(value(cum_ret), 265.9177, atol=ATOL) - source = from(TSLA) ret = SimpleAssetReturn{Float64}() cum_ret = CumulativeReturn{Float64}()