diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 6464c2f..e251acc 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -24,7 +24,7 @@ jobs: matrix: version: - '1.10' - - '1.6' + #- '1.6' - 'nightly' os: - ubuntu-latest diff --git a/examples/notebooks/teardown.jl b/examples/notebooks/teardown.jl index 94fdb2d..41fdc0e 100644 --- a/examples/notebooks/teardown.jl +++ b/examples/notebooks/teardown.jl @@ -6,45 +6,51 @@ using InteractiveUtils # ╔═╡ a1861f50-046e-11ef-348b-cb9f60ea0d1b begin - import Pkg - Pkg.activate(mktempdir()) - Pkg.add([ - Pkg.PackageSpec(url = "https://github.com/femtotrader/OnlinePortfolioAnalytics.jl"), - ]) - using TSFrames - using DataFrames - using Dates - using Random - using Plots - using OnlinePortfolioAnalytics + import Pkg + Pkg.activate(mktempdir()) + Pkg.add([ + Pkg.PackageSpec(url = "https://github.com/femtotrader/OnlinePortfolioAnalytics.jl"), + ]) + using TSFrames + using DataFrames + using Dates + using Random + using Plots + using OnlinePortfolioAnalytics end # ╔═╡ accbd5bc-4976-48cf-91c1-e12b62a94edf -function random_data(rng::AbstractRNG = Random.GLOBAL_RNG; - start = Dates.Date(2010, 1, 1), - step = Dates.Day(1), - stop = Dates.Date(2023, 1, 1) - Dates.Day(1), - price_init = nothing, - price_init_min = 1.00, - price_init_step = 0.01, - price_init_max = 1000.00, - price_var_min = -5.0, - price_var_step = 0.1, - price_var_max = 5.0, +function random_data( + rng::AbstractRNG = Random.GLOBAL_RNG; + start = Dates.Date(2010, 1, 1), + step = Dates.Day(1), + stop = Dates.Date(2023, 1, 1) - Dates.Day(1), + price_init = nothing, + price_init_min = 1.00, + price_init_step = 0.01, + price_init_max = 1000.00, + price_var_min = -5.0, + price_var_step = 0.1, + price_var_max = 5.0, ) - idx = range(start, stop = stop, step = step) - n = length(idx) - if isnothing(price_init) - price_init = rand(rng, price_init_min:price_init_step:price_init_max) - end - return TSFrame(DataFrame(Index=collect(idx), - STOCK1=price_init .+ cumsum(rand(rng, price_var_min:price_var_step:price_var_max, n)))) + idx = range(start, stop = stop, step = step) + n = length(idx) + if isnothing(price_init) + price_init = rand(rng, price_init_min:price_init_step:price_init_max) + end + return TSFrame( + DataFrame( + Index = collect(idx), + STOCK1 = price_init .+ + cumsum(rand(rng, price_var_min:price_var_step:price_var_max, n)), + ), + ) end # ╔═╡ da790f5a-874b-4c65-9c7d-4243d3852859 begin - Random.seed!(123) - ts = random_data() + Random.seed!(123) + ts = random_data() end # ╔═╡ 21600f87-228d-4cd0-8f24-ec821de8ef8c @@ -52,12 +58,12 @@ plot(ts) # ╔═╡ c0fd125c-70d3-4e42-a0a5-4daff44a2c96 begin - returns = SimpleAssetReturn(ts) - #returns = dropmissing(returns.coredata) |> TSFrame - #replace(returns.coredata, missing => 0) - returns.coredata.STOCK1[ismissing.(returns.coredata.STOCK1)] .= 0 - returns = dropmissing(returns.coredata) |> TSFrame - returns + returns = SimpleAssetReturn(ts) + #returns = dropmissing(returns.coredata) |> TSFrame + #replace(returns.coredata, missing => 0) + returns.coredata.STOCK1[ismissing.(returns.coredata.STOCK1)] .= 0 + returns = dropmissing(returns.coredata) |> TSFrame + returns end # ╔═╡ b0e1d632-1b86-4259-8f28-464e0af0c3e0 @@ -65,25 +71,33 @@ cum_returns = CumulativeReturn(returns) # ╔═╡ a208fb00-cfe1-46d9-9751-e9e5f423f8fb begin - plot(cum_returns, title="Cumulative returns", color=:green) - hline!([1.0], color=:green, linestyle=:dashdot, label="") + plot(cum_returns, title = "Cumulative returns", color = :green) + hline!([1.0], color = :green, linestyle = :dashdot, label = "") end # ╔═╡ 2d92945c-1ad5-4ef6-8c6e-1d77b23698f6 begin - dd = DrawDowns(returns) - dd.coredata.STOCK1 = dd.coredata.STOCK1 .* 100.0 + dd = DrawDowns(returns) + dd.coredata.STOCK1 = dd.coredata.STOCK1 .* 100.0 end # ╔═╡ ac56bb3d-0732-4536-bb81-594643c31935 begin - plot(dd, title="Drawdowns (%)", color=:red, fillcolor=:red, fillrange=0, fillalpha=0.35) + plot( + dd, + title = "Drawdowns (%)", + color = :red, + fillcolor = :red, + fillrange = 0, + fillalpha = 0.35, + ) end # ╔═╡ c61cb98d-b0ea-4bf5-a0b4-11b925b18e0d begin - returns.coredata[!, :Year] = map(dt -> year(dt), returns.coredata[!, :Index]) - returns.coredata[!, :Month] = map(dt -> Dates.Date(year(dt), month(dt), 1), returns.coredata[!, :Index]) + returns.coredata[!, :Year] = map(dt -> year(dt), returns.coredata[!, :Index]) + returns.coredata[!, :Month] = + map(dt -> Dates.Date(year(dt), month(dt), 1), returns.coredata[!, :Index]) end # ╔═╡ 04894092-b9c4-42d8-87b2-b530de95736c diff --git a/src/sample_data.jl b/src/sample_data.jl index b3f441b..042ca2c 100644 --- a/src/sample_data.jl +++ b/src/sample_data.jl @@ -50,4 +50,4 @@ const MSFT = [ ] const weights = [0.4, 0.4, 0.2] -end \ No newline at end of file +end diff --git a/src/sharpe.jl b/src/sharpe.jl index df270c1..0e3cd53 100644 --- a/src/sharpe.jl +++ b/src/sharpe.jl @@ -39,5 +39,5 @@ function Base.empty!(stat::Sharpe{T}) where {T} stat.value = zero(T) stat.n = 0 stat.mean = Mean(T) - stat.stddev = StdDev(T) + stat.stddev = StdDev{T}() end diff --git a/src/sortino.jl b/src/sortino.jl index 205824d..15e08f6 100644 --- a/src/sortino.jl +++ b/src/sortino.jl @@ -36,3 +36,10 @@ function OnlineStatsBase._fit!(stat::Sortino, ret) sortino = sqrt(stat.period) * (mean_return - stat.risk_free) / stddev_neg_return stat.value = sortino end + +function Base.empty!(stat::Sortino{T}) where {T} + stat.value = zero(T) + stat.n = 0 + stat.mean_ret = Mean(T) + stat.stddev_neg_ret = StdDev{T}() +end diff --git a/test/runtests.jl b/test/runtests.jl index 2016d68..d89d460 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -396,11 +396,11 @@ const ATOL = 0.0001 @test isapprox(sharpes[end], 0.2886, atol = ATOL) - #empty!(_sharpe) - #@test _sharpe.n == 0 - #@test value(_sharpe) == 0.0 - #@test _sharpe.mean == Mean() - #@test _sharpe.stddev == StdDev() + empty!(_sharpe) + @test _sharpe.n == 0 + @test value(_sharpe) == 0.0 + @test _sharpe.mean == Mean() + @test value(_sharpe.stddev) == 1 end @testset "Sortino" begin @@ -426,11 +426,11 @@ const ATOL = 0.0001 @test isapprox(sortinos[end], 11.4992, atol = ATOL) - #empty!(_sortino) - #@test _sortino.n == 0 - #@test value(_sortino) == 0.0 - #@test _sortino.mean == Mean() - #@test _sortino.stddev == StdDev() + empty!(_sortino) + @test _sortino.n == 0 + @test value(_sortino) == 0.0 + @test _sortino.mean_ret == Mean() + @test value(_sortino.stddev_neg_ret) == 1 end end @@ -528,7 +528,7 @@ const ATOL = 0.0001 @test isapprox(sharpe.coredata[end, [:TSLA]][1], 0.2886, atol = ATOL) # Calculate Sortino ratio (from returns) sortino = Sortino(returns) - @test isapprox(sortino.coredata[end, [:TSLA]][1], 11.4992, atol = ATOL) + @test isapprox(sortino.coredata[end, [:TSLA]][1], 11.4992, atol = ATOL) end end end