Class: Statsample::TimeSeries::Series
- Includes:
- Pacf
- Defined in:
- lib/statsample-timeseries/timeseries.rb
Overview
Collection of data indexed by time. The order goes from earliest to latest.
Instance Method Summary collapse
-
#+(series) ⇒ Object
Borrow the operations from Vector, but convert to time series.
- #-(series) ⇒ Object
-
#acf(max_lags = nil) ⇒ Object
Calculates the autocorrelation coefficients of the series.
-
#acvf(demean = true, unbiased = true) ⇒ Object
AutoCovariance Provides autocovariance of timeseries.
-
#ar(n = 1500, k = 1) ⇒ Object
Autoregressive estimation Generates AR(k) series for the calling timeseries by yule walker.
-
#correlate(a, v, mode = 'full') ⇒ Object
Correlation Gives correlation of timeseries.
-
#diff(max_lags = 1) ⇒ Object
Diff Performs the difference of the series.
-
#ema(n = 10, wilder = false) ⇒ Object
Exponential Moving Average Calculates an exponential moving average of the series using a specified parameter.
-
#lag(k = 1) ⇒ Object
Lags the series by k periods.
-
#ma(n = 10) ⇒ Object
Moving Average Calculates the moving average of the series using the provided lookback argument.
-
#macd(fast = 12, slow = 26, signal = 9) ⇒ Object
Moving Average Convergence-Divergence Calculates the MACD (moving average convergence-divergence) of the time series - this is a comparison of a fast EMA with a slow EMA.
-
#pacf(max_lags = nil, method = :yw) ⇒ Object
Partial Autocorrelation Generates partial autocorrelation series for a timeseries ==Parameters * max_lags: integer, optional - provide number of lags * method: string.
- #to_s ⇒ Object
Methods inherited from Vector
Instance Method Details
#+(series) ⇒ Object
Borrow the operations from Vector, but convert to time series
277 278 279 |
# File 'lib/statsample-timeseries/timeseries.rb', line 277 def + series super.to_a.to_ts end |
#-(series) ⇒ Object
281 282 283 |
# File 'lib/statsample-timeseries/timeseries.rb', line 281 def - series super.to_a.to_ts end |
#acf(max_lags = nil) ⇒ Object
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
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/statsample-timeseries/timeseries.rb', line 34 def acf(max_lags = nil) max_lags ||= (10 * Math.log10(size)).to_i (0..max_lags).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 |
#acvf(demean = true, unbiased = true) ⇒ Object
AutoCovariance
Provides autocovariance of timeseries.
Parameters
-
demean = true; optional. Supply false if series is not to be demeaned
-
unbiased = true; optional. true/false for unbiased/biased form of autocovariance
Returns
Autocovariance value
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
# File 'lib/statsample-timeseries/timeseries.rb', line 94 def acvf(demean = true, unbiased = true) #TODO: change parameters list in opts.merge as suggested by John #functionality: computes autocovariance of timeseries data #returns: array of autocovariances if demean demeaned_series = self - self.mean else demeaned_series = self end n = (10 * Math.log10(size)).to_i + 1 m = self.mean if unbiased d = Array.new(self.size, self.size) else d = ((1..self.size).to_a.reverse)[0..n] end 0.upto(n - 1).map do |i| (demeaned_series * (self.lag(i) - m)).sum / d[i] end end |
#ar(n = 1500, k = 1) ⇒ Object
Autoregressive estimation
Generates AR(k) series for the calling timeseries by yule walker.
Parameters
-
n: integer, (default = 1500) number of observations for AR.
-
k: integer, (default = 1) order of AR process.
Returns
Array constituting estimated AR series.
81 82 83 84 85 |
# File 'lib/statsample-timeseries/timeseries.rb', line 81 def ar(n = 1500, k = 1) series = Statsample::TimeSeries.arima #series = Statsample::TimeSeries::ARIMA.new series.yule_walker(self, n, k) end |
#correlate(a, v, mode = 'full') ⇒ Object
Correlation
Gives correlation of timeseries.
120 121 122 123 124 125 126 127 128 129 130 131 132 |
# File 'lib/statsample-timeseries/timeseries.rb', line 120 def correlate(a, v, mode = 'full') #peforms cross-correlation of two series #multiarray.correlate2(a, v, 'full') if a.size < v.size raise("Should have same size!") end ps = a.size + v.size - 1 a_padded = Array.new(ps, 0) a_padded[0...a.size] = a out = (mode.downcase.eql? 'full') ? Array.new(ps) : Array.new(a.size) #ongoing end |
#diff(max_lags = 1) ⇒ Object
Diff
Performs the difference of the series. Note: The first difference of series is X(t) - X(t-1) But, second difference of series is NOT X(t) - X(t-2) It is the first difference of the first difference
> (X(t) - X(t-1)) - (X(t-1) - X(t-2))
Params
-
max_lags: integer, (default: 1), number of differences reqd.
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, ...]
Returns
Timeseries object
179 180 181 182 183 184 185 186 187 |
# File 'lib/statsample-timeseries/timeseries.rb', line 179 def diff(max_lags = 1) ts = self difference = [] max_lags.times do difference = ts - ts.lag ts = difference end difference end |
#ema(n = 10, wilder = false) ⇒ Object
Exponential Moving Average
Calculates an exponential moving average of the series using a specified parameter. If wilder is false (the default) then the EMA uses a smoothing value of 2 / (n + 1), if it is true then it uses the Welles Wilder smoother of 1 / n.
Warning for EMA usage: EMAs are unstable for small series, as they use a lot more than n observations to calculate. The series is stable if the size of the series is >= 3.45 * (n + 1)
Parameters
-
n: integer, (default = 10)
-
wilder: boolean, (default = false), if true, 1/n value is used for smoothing; if false, uses 2/(n+1) value
Usage
ts = (1..100).map { rand }.to_ts
# => [0.69, 0.23, 0.44, 0.71, ...]
# first 9 observations are nil
ts.ema # => [ ... nil, 0.509... , 0.433..., ... ]
Returns
EMA timeseries
236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 |
# File 'lib/statsample-timeseries/timeseries.rb', line 236 def ema(n = 10, wilder = false) smoother = wilder ? 1.0 / n : 2.0 / (n + 1) # need to start everything from the first non-nil observation start = self.data.index { |i| i != nil } # first n - 1 observations are nil base = [nil] * (start + n - 1) # nth observation is just a moving average base << self[start...(start + n)].inject(0.0) { |s, a| a.nil? ? s : s + a } / n (start + n).upto size - 1 do |i| base << self[i] * smoother + (1 - smoother) * base.last end base.to_time_series end |
#lag(k = 1) ⇒ Object
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, ...]
148 149 150 151 152 153 154 155 156 157 158 159 160 161 |
# File 'lib/statsample-timeseries/timeseries.rb', line 148 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 |
#ma(n = 10) ⇒ Object
Moving Average
Calculates the moving average of the series using the provided lookback argument. The lookback defaults to 10 periods.
Parameters
-
n: integer, (default = 10) - loopback argument
Usage
ts = (1..100).map { rand }.to_ts
# => [0.69, 0.23, 0.44, 0.71, ...]
# first 9 observations are nil
ts.ma # => [ ... nil, 0.484... , 0.445... , 0.513 ... , ... ]
Returns
Resulting moving average timeseries object
205 206 207 208 209 210 211 |
# File 'lib/statsample-timeseries/timeseries.rb', line 205 def ma(n = 10) return mean if n >= size ([nil] * (n - 1) + (0..(size - n)).map do |i| self[i...(i + n)].inject(&:+) / n end).to_time_series end |
#macd(fast = 12, slow = 26, signal = 9) ⇒ Object
Moving Average Convergence-Divergence
Calculates the MACD (moving average convergence-divergence) of the time series - this is a comparison of a fast EMA with a slow EMA.
Parameters*:
-
fast: integer, (default = 12) - fast component of MACD
-
slow: integer, (default = 26) - slow component of MACD
-
signal: integer, (default = 9) - signal component of MACD
Usage
ts = (1..100).map { rand }.to_ts
# => [0.69, 0.23, 0.44, 0.71, ...]
ts.macd(13)
Returns
Array of two timeseries - comparison of fast EMA with slow and EMA with signal value
271 272 273 274 |
# File 'lib/statsample-timeseries/timeseries.rb', line 271 def macd(fast = 12, slow = 26, signal = 9) series = ema(fast) - ema(slow) [series, series.ema(signal)] end |
#pacf(max_lags = nil, method = :yw) ⇒ Object
Partial Autocorrelation
Generates partial autocorrelation series for a timeseries
Parameters
-
max_lags: integer, optional - provide number of lags
-
method: string. Default: ‘yw’.
* *yw*: For yule-walker algorithm unbiased approach * *mle*: For Maximum likelihood algorithm approach * *ld*: Forr Levinson-Durbin recursive approach
Returns
array of pacf
60 61 62 63 64 65 66 67 68 69 70 71 72 |
# File 'lib/statsample-timeseries/timeseries.rb', line 60 def pacf(max_lags = nil, method = :yw) method = method.downcase.to_sym max_lags ||= (10 * Math.log10(size)).to_i if method.eql? :yw or method.eql? :mle Pacf::Pacf.pacf_yw(self, max_lags, method.to_s) elsif method == :ld series = self.acvf Pacf::Pacf.levinson_durbin(series, max_lags, true)[2] else raise "Method presents for pacf are 'yw', 'mle' or 'ld'" end end |
#to_s ⇒ Object
285 286 287 288 |
# File 'lib/statsample-timeseries/timeseries.rb', line 285 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 |