Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Added basic TimeSeries object with acf, lag and delta.

  • Loading branch information...
commit aa8ea1333c67a1b40278b43be037fb54cf59bdb1 1 parent c93a4e6
Rob robbrit authored
1  .gitignore
View
@@ -1,3 +1,4 @@
+*.swp
*.rbc
coverage
*~
1  lib/statsample.rb
View
@@ -161,6 +161,7 @@ def self.create_has_library(library)
autoload(:Test, 'statsample/test')
autoload(:Factor, 'statsample/factor')
autoload(:Graph, 'statsample/graph')
+ autoload(:TimeSeries, 'statsample/tseries')
class << self
100 lib/statsample/tseries.rb
View
@@ -0,0 +1,100 @@
+module Statsample::TimeSeriesShorthands
+ # Creates a new Statsample::TimeSeries object
+ # Argument should be equal to TimeSeries.new
+ def to_time_series(*args)
+ Statsample::TimeSeries.new(self, :scale, *args)
+ end
+
+ alias :to_ts :to_time_series
+end
+
+class Array
+ include Statsample::TimeSeriesShorthands
+end
+
+module Statsample
+ module TimeSeries
+ # Collection of data indexed by time.
+ # The order goes from earliest to latest.
+ class TimeSeries < Statsample::Vector
+ # Calculates the autocorrelation coefficients of the series.
+ #
+ # The first element is always 1, since that is the correlation
+ # of the series with itself.
+ #
+ # Usage:
+ #
+ # ts = (1..100).map { rand }.to_time_series
+ #
+ # ts.acf # => array with first 21 autocorrelations
+ # ts.acf 3 # => array with first 3 autocorrelations
+ #
+ def acf maxlags = nil
+ maxlags ||= (10 * Math.log10(size)).to_i
+
+ (0..maxlags).map do |i|
+ if i == 0
+ 1.0
+ else
+ m = self.mean
+
+ # can't use Pearson coefficient since the mean for the lagged series should
+ # be the same as the regular series
+ ((self - m) * (self.lag(i) - m)).sum / self.variance_sample / (self.size - 1)
+ end
+ end
+ end
+
+ # Lags the series by k periods.
+ #
+ # The convention is to set the oldest observations (the first ones
+ # in the series) to nil so that the size of the lagged series is the
+ # same as the original.
+ #
+ # Usage:
+ #
+ # ts = (1..10).map { rand }.to_time_series
+ # # => [0.69, 0.23, 0.44, 0.71, ...]
+ #
+ # ts.lag # => [nil, 0.69, 0.23, 0.44, ...]
+ # ts.lag 2 # => [nil, nil, 0.69, 0.23, ...]
+ #
+ def lag k = 1
+ return self if k == 0
+
+ dup.tap do |lagged|
+ (lagged.size - 1).downto k do |i|
+ lagged[i] = lagged[i - k]
+ end
+
+ (0...k).each do |i|
+ lagged[i] = nil
+ end
+ lagged.set_valid_data
+ end
+ end
+
+ # Performs a first difference of the series.
+ #
+ # The convention is to set the oldest observations (the first ones
+ # in the series) to nil so that the size of the diffed series is the
+ # same as the original.
+ #
+ # Usage:
+ #
+ # ts = (1..10).map { rand }.to_ts
+ # # => [0.69, 0.23, 0.44, 0.71, ...]
+ #
+ # ts.diff # => [nil, -0.46, 0.21, 0.27, ...]
+ #
+ def diff
+ self - self.lag
+ end
+
+ def to_s
+ sprintf("Time Series(type:%s, n:%d)[%s]", @type.to_s, @data.size,
+ @data.collect{|d| d.nil? ? "nil":d}.join(","))
+ end
+ end
+ end
+end
36 test/test_tseries.rb
View
@@ -0,0 +1,36 @@
+require(File.expand_path(File.dirname(__FILE__)+'/helpers_tests.rb'))
+
+class StatsampleTestTimeSeries < MiniTest::Unit::TestCase
+ include Statsample::Shorthand
+
+ def setup
+ # daily closes of iShares XIU on the TSX
+ @xiu = Statsample::TimeSeries::TimeSeries.new [17.28, 17.45, 17.84, 17.74, 17.82, 17.85, 17.36, 17.3, 17.56, 17.49, 17.46, 17.4, 17.03, 17.01,
+ 16.86, 16.86, 16.56, 16.36, 16.66, 16.77], :scale
+ end
+
+ def test_acf
+ acf = @xiu.acf
+
+ assert_equal 14, acf.length
+
+ # test the first few autocorrelations
+ assert_in_delta 1.0, acf[0], 0.0001
+ assert_in_delta 0.852, acf[1], 0.001
+ assert_in_delta 0.669, acf[2], 0.001
+ assert_in_delta 0.486, acf[3], 0.001
+ end
+
+ def test_lag
+ assert_in_delta 16.66, @xiu.lag[@xiu.size - 1], 0.001
+ assert_in_delta 16.36, @xiu.lag(2)[@xiu.size - 1], 0.001
+ end
+
+ def test_delta
+ diff = @xiu.diff
+
+ assert_in_delta 0.11, diff[@xiu.size - 1], 0.001
+ assert_in_delta 0.30, diff[@xiu.size - 2], 0.001
+ assert_in_delta -0.20, diff[@xiu.size - 3], 0.001
+ end
+end
Please sign in to comment.
Something went wrong with that request. Please try again.