Setindex for TSFrame from TSFrames.jl

Hi everyone,

This is my first question so please let me know if I am doing something wrong.

I used the TSFrames.jl package and ran into the following issue.

I have a TSFrame of stock prices:

tsf = DataFrame(timestamp =  Date(2010,1,1):Day(1):Date(2010,1,4), p1 = rand(4),p2 = rand(4)) |> TSFrame

And I now want to build a wealth index (calculate long returns and accumulate them).

Calculating the log returns is easy:

tsf = diff(log.(tsf))

4×2 TSFrame with Date Index
 Index       p1_log          p2_log
 Date        Float64?        Float64?
─────────────────────────────────────────────
 2010-01-01  missing         missing
 2010-01-02        0.522848        0.0317818
 2010-01-03       -0.172255        0.275094
 2010-01-04       -1.04826        -0.266552

Now the first value is missing because no difference can be calculated. But because I want to accumulate to build a wealth index that starts at 0 for log returns or 1 for normal returns I would like to set these missing values to 0. Ideally, I would like to do this in a loop where I reference either the column index or the column names (want to do this for many etc.)

What works is this:

tsf.p1_log[1] = 0.0

What does not work is:

tsf[1,:] .= 0.0
tsf[1,:p1_log] = 0.0
tsf[:,:p1_log][1] = 0.0

I have also tried setindex! which doesn’t work either.

I am doing it in a very hacky way through eval. I think that there must be a simpler way.
What I do now is:

for n in names(tsf)
    eval(Meta.parse("tsf.$(n)[1] = 0.0"))
end

Even worse I need to do this again because there is no implementation for cumsum it seems.
I think this is a bit of an oversight given that it is very common to accumulate log returns to get cumulative returns.
What I do:

for n in names(tsf)
    eval(Meta.parse("tsf.$n[1:end] = cumsum(tsf[:,:$n])"))
end

So I guess my question is does anyone know how to write new values to cells or entire columns in a TSFrame where one can either supply a column index or a column name through a loop?

Thanks

That is a bit odd, maybe just use DataFrames instead?

Anyway if you’re resorting to eval(Meta.parse in some data wrangling code there’s about a 99.7% chance (disclaimer: made up number!) that you’re doing it wrong :tm:

The dot access is just syntactic sugar for a getproperty call, so you should be able to do

for n in names(tsf)
    getproperty(tsf, n)[begin] = 0.0
end

(the begin is more general than [1], I suppose this isn’t an issue for a TSFrame which probably won’t have some sort of offset array as a column)

1 Like

I am specifically trying to show the integration of my package with TSFrames.jl so resorting to DataFrames.jl is not ideal.

I guess I was just assuming to be able to do the same kind of indexing as with DataFrames as it is built on it.

Thanks for your code! With a slight adjustment it works like a charm:

for n in names(tsf)
    getproperty(tsf, Symbol(n))[begin] = 0.0
end

Edit: Should I make yours the solution? or the one that works with the Symbol call?

Mark whichever one you want, there’s no magical internet points for solutions on Discourse :smiley:

And apologies, sometimes I still forget that names returns strings and getproperty operates on symbols only, it’s the memory of the good old days I guess when DataFrames would only accept symbols for column names…

1 Like

TSFrames, currently, does not support setindex() functions. I have created an issue for this here.

Also, created an issue to implement cumsum.

1 Like