Basic demo of TSFrames using financial data
Create a TSFrame object for IBM historical data
To load the IBM historical data, we will use the MarketData.yahoo
function from MarketData.jl, which returns the data in the form of a TimeArray
. We just simply pass this on to the TSFrame
constructor.
julia> using TSFrames, MarketData, Plots, Statistics
julia> ibm_ts = TSFrame(MarketData.yahoo(:IBM))
13137×6 TSFrame with Date Index Index Open High Low Close AdjClose Volume Date Float64 Float64 Float64 Float64 Float64 Float64 ────────────────────────────────────────────────────────────────────────────── 1971-02-08 16.0851 16.336 15.8939 16.2882 3.75666 719648.0 1971-02-09 16.2882 16.3121 16.1687 16.1807 3.73186 673624.0 1971-02-10 16.1568 16.1568 15.9775 16.1209 3.71808 648520.0 1971-02-11 16.1209 16.2285 16.097 16.1926 3.73461 579484.0 1971-02-12 16.1926 16.2285 16.1329 16.2285 3.74289 382836.0 1971-02-16 16.2285 16.4197 16.1926 16.3301 3.76631 684084.0 1971-02-17 16.2703 16.2703 16.0492 16.0851 3.70981 652704.0 1971-02-18 16.0851 16.1209 15.7385 15.7385 3.62988 822156.0 ⋮ ⋮ ⋮ ⋮ ⋮ ⋮ ⋮ 2023-03-02 128.39 129.22 127.71 128.93 128.93 3.3401e6 2023-03-03 129.35 129.91 128.77 129.64 129.64 2.8592e6 2023-03-06 129.64 130.86 129.59 130.19 130.19 3.1312e6 2023-03-07 130.28 130.42 128.19 128.25 128.25 3.5304e6 2023-03-08 128.48 128.74 127.55 128.05 128.05 2.7788e6 2023-03-09 128.3 128.53 125.98 126.16 126.16 5.4783e6 2023-03-10 126.12 127.29 125.13 125.45 125.45 5.9902e6 13122 rows omitted
Create TSFrame object for AAPL
Similarly, we can create a TSFrame
object for the AAPL data.
julia> aapl_ts = TSFrame(MarketData.yahoo(:AAPL))
10650×6 TSFrame with Date Index Index Open High Low Close AdjClose Volum ⋯ Date Float64 Float64 Float64 Float64 Float64 Float ⋯ ──────────────────────────────────────────────────────────────────────────────── 1980-12-12 0.128348 0.128906 0.128348 0.128348 0.099722 4.690 ⋯ 1980-12-15 0.12221 0.12221 0.121652 0.121652 0.094519 1.758 1980-12-16 0.113281 0.113281 0.112723 0.112723 0.087582 1.057 1980-12-17 0.115513 0.116071 0.115513 0.115513 0.089749 8.644 1980-12-18 0.118862 0.11942 0.118862 0.118862 0.092351 7.344 ⋯ 1980-12-19 0.126116 0.126674 0.126116 0.126116 0.097987 4.863 1980-12-22 0.132254 0.132813 0.132254 0.132254 0.102756 3.736 1980-12-23 0.137835 0.138393 0.137835 0.137835 0.107093 4.695 ⋮ ⋮ ⋮ ⋮ ⋮ ⋮ ⋮ ⋱ 2023-03-02 144.38 146.71 143.9 145.91 145.91 5.223 ⋯ 2023-03-03 148.04 151.11 147.33 151.03 151.03 7.066 2023-03-06 153.79 156.3 153.46 153.83 153.83 8.755 2023-03-07 153.7 154.03 151.13 151.6 151.6 5.618 2023-03-08 152.81 153.47 151.83 152.87 152.87 4.720 ⋯ 2023-03-09 153.56 154.54 150.23 150.59 150.59 5.383 2023-03-10 150.21 150.94 147.61 148.5 148.5 6.852 1 column and 10635 rows omitted
Create a 6-month subset of stock data
We would like to compare the stock returns for both the stocks for 6 months starting from June 1, 2021 till December 31, 2021. We use TSFrames.subset
method to create new objects which contain the specified duration of data.
julia> date_from = Date(2021, 06, 01);
julia> date_to = Date(2021, 12, 31);
julia> ibm = TSFrames.subset(ibm_ts, date_from, date_to)
150×6 TSFrame with Date Index Index Open High Low Close AdjClose Volume Date Float64 Float64 Float64 Float64 Float64 Float64 ───────────────────────────────────────────────────────────────────── 2021-06-01 138.623 139.417 137.428 137.849 126.576 2.5287e6 2021-06-02 138.26 139.34 137.772 139.312 127.919 2.9151e6 2021-06-03 138.537 139.465 137.706 139.149 127.77 4.32061e6 2021-06-04 139.579 141.061 139.35 140.937 129.411 3.26132e6 2021-06-07 141.061 142.199 140.698 141.511 129.938 3.62198e6 2021-06-08 141.606 143.595 141.606 142.514 130.86 5.31378e6 2021-06-09 142.476 144.426 142.275 144.044 132.264 5.54725e6 2021-06-10 144.809 146.119 143.174 143.92 132.15 4.97739e6 ⋮ ⋮ ⋮ ⋮ ⋮ ⋮ ⋮ 2021-12-22 129.06 129.79 127.6 129.75 122.119 3.9232e6 2021-12-23 130.0 130.96 129.52 130.63 122.947 3.649e6 2021-12-27 130.63 131.65 129.95 131.62 123.879 4.2939e6 2021-12-28 131.6 133.22 131.59 132.63 124.83 3.4452e6 2021-12-29 132.4 134.21 132.3 133.35 125.507 4.2399e6 2021-12-30 133.75 134.37 133.33 133.91 126.034 3.1581e6 2021-12-31 134.0 134.99 133.61 133.66 125.799 3.3621e6 135 rows omitted
julia> aapl = TSFrames.subset(aapl_ts, date_from, date_to)
150×6 TSFrame with Date Index Index Open High Low Close AdjClose Volume Date Float64 Float64 Float64 Float64 Float64 Float64 ───────────────────────────────────────────────────────────────────── 2021-06-01 125.08 125.35 123.94 124.28 123.01 6.76371e7 2021-06-02 124.28 125.24 124.05 125.06 123.782 5.92789e7 2021-06-03 124.68 124.85 123.13 123.54 122.278 7.62292e7 2021-06-04 124.07 126.16 123.85 125.89 124.604 7.51693e7 2021-06-07 126.17 126.32 124.83 125.9 124.614 7.10576e7 2021-06-08 126.6 128.46 126.21 126.74 125.445 7.44038e7 2021-06-09 127.21 127.75 126.52 127.13 125.831 5.68779e7 2021-06-10 127.02 128.19 125.94 126.11 124.822 7.11864e7 ⋮ ⋮ ⋮ ⋮ ⋮ ⋮ ⋮ 2021-12-22 173.04 175.86 172.15 175.64 174.36 9.21353e7 2021-12-23 175.85 176.85 175.27 176.28 174.996 6.83566e7 2021-12-27 177.09 180.42 177.07 180.33 179.016 7.49196e7 2021-12-28 180.16 181.33 178.53 179.29 177.984 7.91443e7 2021-12-29 179.33 180.63 178.14 179.38 178.073 6.23489e7 2021-12-30 179.47 180.57 178.09 178.2 176.902 5.9773e7 2021-12-31 178.09 179.23 177.26 177.57 176.276 6.40623e7 135 rows omitted
Combine adjusted closing prices of both stocks into one object
We now join (cbind) both the stocks' data into a single object for further analysis. We use TSFrames.join
to create two columns containing adjusted closing prices of both the stocks. The join happens by comparing the Index
values (dates) of the two objects. The resulting object contains two columns with exactly the same dates for which both the objects have data, all the other rows are omitted from the result.
julia> ibm_aapl = TSFrames.join(ibm[:, ["AdjClose"]], aapl[:, ["AdjClose"]]; jointype=:JoinBoth)
150×2 TSFrame with Date Index Index AdjClose AdjClose_1 Date Float64 Float64 ────────────────────────────────── 2021-06-01 126.576 123.01 2021-06-02 127.919 123.782 2021-06-03 127.77 122.278 2021-06-04 129.411 124.604 2021-06-07 129.938 124.614 2021-06-08 130.86 125.445 2021-06-09 132.264 125.831 2021-06-10 132.15 124.822 ⋮ ⋮ ⋮ 2021-12-22 122.119 174.36 2021-12-23 122.947 174.996 2021-12-27 123.879 179.016 2021-12-28 124.83 177.984 2021-12-29 125.507 178.073 2021-12-30 126.034 176.902 2021-12-31 125.799 176.276 135 rows omitted
julia> TSFrames.rename!(ibm_aapl, [:IBM, :AAPL])
150×2 TSFrame with Date Index Index IBM AAPL Date Float64 Float64 ────────────────────────────── 2021-06-01 126.576 123.01 2021-06-02 127.919 123.782 2021-06-03 127.77 122.278 2021-06-04 129.411 124.604 2021-06-07 129.938 124.614 2021-06-08 130.86 125.445 2021-06-09 132.264 125.831 2021-06-10 132.15 124.822 ⋮ ⋮ ⋮ 2021-12-22 122.119 174.36 2021-12-23 122.947 174.996 2021-12-27 123.879 179.016 2021-12-28 124.83 177.984 2021-12-29 125.507 178.073 2021-12-30 126.034 176.902 2021-12-31 125.799 176.276 135 rows omitted
After the join
operation the column names are modified because we merged two same-named columns (AdjClose
) so we use TSFrames.rename!()
method to rename the columns to easily remembered stock names.
Convert data into weekly frequency using last values
Here, we convert daily stock data into weekly frequency by taking the value with which the trading closed on the last day of the week as the week's price.
julia> ibm_aapl_weekly = to_weekly(ibm_aapl)
31×2 TSFrame with Date Index Index IBM AAPL Date Float64 Float64 ────────────────────────────── 2021-06-04 129.411 124.604 2021-06-11 132.8 126.049 2021-06-18 125.637 129.127 2021-06-25 128.902 131.75 2021-07-02 122.915 138.53 2021-07-09 124.232 143.628 2021-07-16 121.932 144.895 2021-07-23 124.074 147.042 ⋮ ⋮ ⋮ 2021-11-19 109.225 159.38 2021-11-26 108.999 155.667 2021-12-03 111.851 160.661 2021-12-10 116.792 178.143 2021-12-17 119.907 169.893 2021-12-23 122.947 174.996 2021-12-31 125.799 176.276 16 rows omitted
Compute weekly returns using the familiar log
and diff
functions
julia> ibm_aapl_weekly_returns = diff(log.(ibm_aapl_weekly))
31×2 TSFrame with Date Index Index IBM_log AAPL_log Date Float64? Float64? ──────────────────────────────────────────────── 2021-06-04 missing missing 2021-06-11 0.0258467 0.0115306 2021-06-18 -0.0554489 0.0241274 2021-06-25 0.0256601 0.0201092 2021-07-02 -0.0475583 0.050181 2021-07-09 0.0106559 0.0361353 2021-07-16 -0.0186871 0.00878231 2021-07-23 0.0174144 0.0147145 ⋮ ⋮ ⋮ 2021-11-19 -0.0247661 0.0680366 2021-11-26 -0.00207027 -0.0235705 2021-12-03 0.0258271 0.0315732 2021-12-10 0.0432291 0.103289 2021-12-17 0.0263246 -0.0474148 2021-12-23 0.0250372 0.0295916 2021-12-31 0.0229304 0.00729139 16 rows omitted
julia> TSFrames.rename!(ibm_aapl_weekly_returns, [:IBM, :AAPL])
31×2 TSFrame with Date Index Index IBM AAPL Date Float64? Float64? ──────────────────────────────────────────────── 2021-06-04 missing missing 2021-06-11 0.0258467 0.0115306 2021-06-18 -0.0554489 0.0241274 2021-06-25 0.0256601 0.0201092 2021-07-02 -0.0475583 0.050181 2021-07-09 0.0106559 0.0361353 2021-07-16 -0.0186871 0.00878231 2021-07-23 0.0174144 0.0147145 ⋮ ⋮ ⋮ 2021-11-19 -0.0247661 0.0680366 2021-11-26 -0.00207027 -0.0235705 2021-12-03 0.0258271 0.0315732 2021-12-10 0.0432291 0.103289 2021-12-17 0.0263246 -0.0474148 2021-12-23 0.0250372 0.0295916 2021-12-31 0.0229304 0.00729139 16 rows omitted
Compute standard deviation of weekly returns
Computing standard deviation is done using the std
function from Statistics
package. The skipmissing
is used to skip missing values which may have been generated while computing log returns or were already present in the data.
julia> ibm_std = std(skipmissing(ibm_aapl_weekly_returns[:, :IBM]))
0.03407927976075671
julia> aapl_std = std(skipmissing(ibm_aapl_weekly_returns[:, :AAPL]))
0.030582287537208864
Scatter plot of AAPL and IBM
Here, we use the Plots package to create a scatter plot with IBM weekly returns on the x-axis and Apple weekly returns on the y-axis.
plot(ibm_aapl_weekly_returns[:, :AAPL],
ibm_aapl_weekly_returns[:, :IBM],
seriestype = :scatter;
xlabel = "AAPL",
ylabel = "IBM",
legend = false)