joshday / OnlineStats.jl

⚡ Single-pass algorithms for statistics
https://joshday.github.io/OnlineStats.jl/latest/
MIT License
831 stars 62 forks source link

Using StatLag without depending on OnlineStats (just OnlineStatsBase) #273

Closed femtotrader closed 8 months ago

femtotrader commented 8 months ago

Hello,

I'd like to use StatLag in my code without depending on OnlineStats (I just want my code depends on OnlineStatsBase).

I copied StatLag code in IncTA.jl (same MIT license)

"""
    StatLag(stat, b)

Track a moving window (previous `b` copies) of `stat`.

# Example

    fit!(StatLag(Mean(), 10), 1:20)
"""
struct StatLag{T, O<:OnlineStat{T}} <: OnlineStatsBase.StatWrapper{T}
    lag::CircBuff{O}
    stat::O
end
function StatLag(stat::O, b::Integer) where {T, O<:OnlineStat{T}}
    StatLag{T,O}(CircBuff(O,b), stat)
end
function _fit!(o::StatLag, y)
    _fit!(o.stat, y)
    _fit!(o.lag, copy(o.stat))
end
function Base.show(io::IO, o::StatLag)
    print(io, name(o, false, false), ": ")
    print(io, "n=", nobs(o))
    print(io, " | stat_values_old_to_new= ")
    show(IOContext(io, :compact => true), value.(value(o.lag)))
end

I exported StatLag to use it in my unit test

but when I run my unit tests I get

MethodError: no method matching _fit!(::StatLag{OHLCV{Missing, Float64, Float64}, BOP{OHLCV{Missing, Float64, Float64}, Float64}}, ::OHLCV{Missing, Float64, Float64})

and many others MethodError.

I tried adding this method

function _fit!(o::StatLag, i::Type{I}, data) where {I <: TechnicalIndicator}
    println(o, i, data)
    fit!(o.stat, data)
end

but I'm still getting same errors.

I wonder what I'm missing here.

Some help will be nice.

Kind regards

joshday commented 8 months ago

This is too much stuff. Do you have a MWE?

femtotrader commented 8 months ago

Thanks @joshday for this nice projet and for your answer.

Here is a MWE

using OnlineStatsBase
using OnlineStats: StatLag

mutable struct MyMean <: OnlineStat{Number}
    value::Float64
    n::Int
    MyMean() = new(0.0, 0)
end
function OnlineStatsBase._fit!(o::MyMean, y)
    o.n += 1
    o.value += (1 / o.n) * (y - o.value)
end

y = Float64[10, 11, 12, 13, 14, 15]
println(y)

o = MyMean()
o = StatLag(o, 3)

fit!(o, y)
println(value(o))
println(value(o.lag[end-1]))
println(value(o.lag[end-2]))

and a MNWE

using OnlineStatsBase

"""
    StatLag(stat, b)

Track a moving window (previous `b` copies) of `stat`.

# Example

    fit!(StatLag(Mean(), 10), 1:20)
"""
struct StatLag{T, O<:OnlineStat{T}} <: OnlineStatsBase.StatWrapper{T}
    lag::CircBuff{O}
    stat::O
end
function StatLag(stat::O, b::Integer) where {T, O<:OnlineStat{T}}
    StatLag{T,O}(CircBuff(O,b), stat)
end
function _fit!(o::StatLag, y)
    _fit!(o.stat, y)
    _fit!(o.lag, copy(o.stat))
end
function Base.show(io::IO, o::StatLag)
    print(io, name(o, false, false), ": ")
    print(io, "n=", nobs(o))
    print(io, " | stat_values_old_to_new= ")
    show(IOContext(io, :compact => true), value.(value(o.lag)))
end

mutable struct MyMean <: OnlineStat{Number}
    value::Float64
    n::Int
    MyMean() = new(0.0, 0)
end
function OnlineStatsBase._fit!(o::MyMean, y)
    o.n += 1
    o.value += (1 / o.n) * (y - o.value)
end

y = Float64[10, 11, 12, 13, 14, 15]
println(y)

o = MyMean()
o = StatLag(o, 3)

fit!(o, y)
println(value(o))
println(value(o.lag[end-1]))
println(value(o.lag[end-2]))

this one raises

ERROR: LoadError: MethodError: no method matching _fit!(::StatLag{Number, MyMean}, ::Float64)
joshday commented 8 months ago

Looks like you're missing a OnlineStatsBase. here:

function _fit!(o::StatLag, y)
    _fit!(o.stat, y)
    _fit!(o.lag, copy(o.stat))
end
femtotrader commented 8 months ago

Thanks @joshday

I got it

using OnlineStatsBase

"""
    StatLag(stat, b)

Track a moving window (previous `b` copies) of `stat`.

# Example

    fit!(StatLag(Mean(), 10), 1:20)
"""
struct StatLag{T, O<:OnlineStat{T}} <: OnlineStatsBase.StatWrapper{T}
    lag::CircBuff{O}
    stat::O
end
function StatLag(stat::O, b::Integer) where {T, O<:OnlineStat{T}}
    StatLag{T,O}(CircBuff(O,b), stat)
end
function OnlineStatsBase._fit!(o::StatLag, y)
    OnlineStatsBase._fit!(o.stat, y)
    OnlineStatsBase._fit!(o.lag, copy(o.stat))
end
function Base.show(io::IO, o::StatLag)
    print(io, name(o, false, false), ": ")
    print(io, "n=", nobs(o))
    print(io, " | stat_values_old_to_new= ")
    show(IOContext(io, :compact => true), value.(value(o.lag)))
end

mutable struct MyMean <: OnlineStat{Number}
    value::Float64
    n::Int
    MyMean() = new(0.0, 0)
end
function OnlineStatsBase._fit!(o::MyMean, y)
    o.n += 1
    o.value += (1 / o.n) * (y - o.value)
end

y = Float64[10, 11, 12, 13, 14, 15]
println(y)

o = MyMean()
o = StatLag(o, 3)

fit!(o, y)
println(value(o))
println(value(o.lag[end-1]))
println(value(o.lag[end-2]))