Time Series
This is a module for working with discrete floating point time series. It is designed so that every operation is very fast, typically much faster than with other generic code, e.g., Python lists of doubles or even NumPy arrays. The semantics of time series is more similar to Python lists of doubles than Sage real double vectors or NumPy 1-D arrays. In particular, time series are not endowed with much algebraic structure and are always mutable.
Note
NumPy arrays are faster at slicing, since slices return references, and NumPy arrays have strides. However, this speed at slicing makes NumPy slower at certain other operations.
EXAMPLES:
sage: set_random_seed(1)
sage: t = finance.TimeSeries([random()-0.5 for _ in xrange(10)]); t
[0.3294, 0.0959, -0.0706, -0.4646, 0.4311, 0.2275, -0.3840, -0.3528, -0.4119, -0.2933]
sage: t.sums()
[0.3294, 0.4253, 0.3547, -0.1099, 0.3212, 0.5487, 0.1647, -0.1882, -0.6001, -0.8933]
sage: t.exponential_moving_average(0.7)
[0.0000, 0.3294, 0.1660, 0.0003, -0.3251, 0.2042, 0.2205, -0.2027, -0.3078, -0.3807]
sage: t.standard_deviation()
0.33729638212891383
sage: t.mean()
-0.08933425506929439
sage: t.variance()
0.1137688493972542...
AUTHOR:
Bases: object
Initialize new time series.
INPUT:
EXAMPLES:
This implicitly calls init:
sage: finance.TimeSeries([pi, 3, 18.2])
[3.1416, 3.0000, 18.2000]
Conversion from a NumPy 1-D array, which is very fast:
sage: v = finance.TimeSeries([1..5])
sage: w = v.numpy()
sage: finance.TimeSeries(w)
[1.0000, 2.0000, 3.0000, 4.0000, 5.0000]
Conversion from an n-dimensional NumPy array also works:
sage: import numpy
sage: v = numpy.array([[1,2], [3,4]], dtype=float); v
array([[ 1., 2.],
[ 3., 4.]])
sage: finance.TimeSeries(v)
[1.0000, 2.0000, 3.0000, 4.0000]
sage: finance.TimeSeries(v[:,0])
[1.0000, 3.0000]
sage: u = numpy.array([[1,2],[3,4]])
sage: finance.TimeSeries(u)
[1.0000, 2.0000, 3.0000, 4.0000]
For speed purposes we don’t initialize (so value is garbage):
sage: t = finance.TimeSeries(10, initialize=False)
Return new time series got by replacing all entries of self by their absolute value.
OUTPUT:
A new time series.
EXAMPLES:
sage: v = finance.TimeSeries([1,3.1908439,-4,5.93932])
sage: v
[1.0000, 3.1908, -4.0000, 5.9393]
sage: v.abs()
[1.0000, 3.1908, 4.0000, 5.9393]
Add corresponding entries of self and t together, extending either self or t by 0’s if they do not have the same length.
Note
To add a single number to the entries of a time series, use the add_scalar method.
INPUT:
OUTPUT:
A time series with length the maxima of the lengths of self and t.
EXAMPLES:
sage: v = finance.TimeSeries([1,2,-5]); v
[1.0000, 2.0000, -5.0000]
sage: v.add_entries([3,4])
[4.0000, 6.0000, -5.0000]
sage: v.add_entries(v)
[2.0000, 4.0000, -10.0000]
sage: v.add_entries([3,4,7,18.5])
[4.0000, 6.0000, 2.0000, 18.5000]
Return new time series obtained by adding a scalar to every value in the series.
Note
To add componentwise, use the add_entries method.
INPUT:
OUTPUT:
A new time series with s added to all values.
EXAMPLES:
sage: v = finance.TimeSeries([5,4,1.3,2,8,10,3,-5]); v
[5.0000, 4.0000, 1.3000, 2.0000, 8.0000, 10.0000, 3.0000, -5.0000]
sage: v.add_scalar(0.5)
[5.5000, 4.5000, 1.8000, 2.5000, 8.5000, 10.5000, 3.5000, -4.5000]
Return the k-th sample autocorrelation of this time series
.
Let be the sample mean. Then the sample autocorrelation
function is
Note that the variance must be nonzero or you will get a ZeroDivisionError.
INPUT:
OUTPUT:
A time series.
EXAMPLE:
sage: v = finance.TimeSeries([13,8,15,4,4,12,11,7,14,12])
sage: v.autocorrelation()
-0.1875
sage: v.autocorrelation(1)
-0.1875
sage: v.autocorrelation(0)
1.0
sage: v.autocorrelation(2)
-0.20138888888888887
sage: v.autocorrelation(3)
0.18055555555555555
sage: finance.TimeSeries([1..1000]).autocorrelation()
0.997
Return the k-th autocovariance function of self.
This is the covariance of self with self shifted by
, i.e.,
where is the length of self.
Note the denominator of , which gives a “better” sample
estimator.
INPUT:
OUTPUT:
A float.
EXAMPLES:
sage: v = finance.TimeSeries([13,8,15,4,4,12,11,7,14,12])
sage: v.autocovariance(0)
14.4
sage: mu = v.mean(); sum([(a-mu)^2 for a in v])/len(v)
14.4
sage: v.autocovariance(1)
-2.7
sage: mu = v.mean(); sum([(v[i]-mu)*(v[i+1]-mu) for i in range(len(v)-1)])/len(v)
-2.7
sage: v.autocovariance(1)
-2.7
We illustrate with a random sample that an independently and
identically distributed distribution with zero mean and
variance has autocovariance function
with
and
for
.
sage: set_random_seed(0)
sage: v = finance.TimeSeries(10^6)
sage: v.randomize('normal', 0, 5)
[3.3835, -2.0055, 1.7882, -2.9319, -4.6827 ... -5.1868, 9.2613, 0.9274, -6.2282, -8.7652]
sage: v.autocovariance(0)
24.95410689...
sage: v.autocovariance(1)
-0.00508390...
sage: v.autocovariance(2)
0.022056325...
sage: v.autocovariance(3)
-0.01902000...
This method fits the time series to an autoregressive process
of order M. That is, we assume the process is given by
where
is the mean of the process and
is noise.
This method returns estimates for
.
The method works by solving the Yule-Walker equations
, where
,
with
the autocovariance of lag
and
.
Warning
The input sequence is assumed to be stationary, which
means that the autocovariance depends
only on the difference
.
INPUT:
OUTPUT:
A time series – the coefficients of the autoregressive process.
EXAMPLES:
sage: set_random_seed(0)
sage: v = finance.TimeSeries(10^4).randomize('normal').sums()
sage: F = v.autoregressive_fit(100)
sage: v
[0.6767, 0.2756, 0.6332, 0.0469, -0.8897 ... 87.6759, 87.6825, 87.4120, 87.6639, 86.3194]
sage: v.autoregressive_forecast(F)
86.0177285042...
sage: F
[1.0148, -0.0029, -0.0105, 0.0067, -0.0232 ... -0.0106, -0.0068, 0.0085, -0.0131, 0.0092]
sage: set_random_seed(0)
sage: t=finance.TimeSeries(2000)
sage: z=finance.TimeSeries(2000)
sage: z.randomize('normal',1)
[1.6767, 0.5989, 1.3576, 0.4136, 0.0635 ... 1.0057, -1.1467, 1.2809, 1.5705, 1.1095]
sage: t[0]=1
sage: t[1]=2
sage: for i in range(2,2000):
... t[i]=t[i-1]-0.5*t[i-2]+z[i]
...
sage: c=t[0:-1].autoregressive_fit(2) #recovers recurrence relation
sage: c #should be close to [1,-0.5]
[1.0371, -0.5199]
Given the autoregression coefficients as outputted by the autoregressive_fit command, compute the forecast for the next term in the series.
INPUT:
EXAMPLES:
sage: set_random_seed(0)
sage: v = finance.TimeSeries(100).randomize('normal').sums()
sage: F = v[:-1].autoregressive_fit(5); F
[1.0019, -0.0524, -0.0643, 0.1323, -0.0539]
sage: v.autoregressive_forecast(F)
11.7820298611...
sage: v
[0.6767, 0.2756, 0.6332, 0.0469, -0.8897 ... 9.2447, 9.6709, 10.4037, 10.4836, 12.1960]
Return the k-th central moment of self, which is just the mean of the k-th powers of the differences self[i] - mu, where mu is the mean of self.
INPUT:
OUTPUT:
A double.
EXAMPLES:
sage: v = finance.TimeSeries([1,2,3])
sage: v.central_moment(2)
0.6666666666666666
Note that the central moment is different from the moment
here, since the mean is not :
sage: v.moment(2) # doesn't subtract off mean
4.666666666666667
We compute the central moment directly:
sage: mu = v.mean(); mu
2.0
sage: ((1-mu)^2 + (2-mu)^2 + (3-mu)^2) / 3
0.6666666666666666
Return new time series obtained from self by removing all values that are less than or equal to a certain minimum value or greater than or equal to a certain maximum.
INPUT:
OUTPUT:
A time series.
EXAMPLES:
sage: v = finance.TimeSeries([1..10])
sage: v.clip_remove(3,7)
[3.0000, 4.0000, 5.0000, 6.0000, 7.0000]
sage: v.clip_remove(3)
[3.0000, 4.0000, 5.0000, 6.0000, 7.0000, 8.0000, 9.0000, 10.0000]
sage: v.clip_remove(max=7)
[1.0000, 2.0000, 3.0000, 4.0000, 5.0000, 6.0000, 7.0000]
Return the correlation of self and other, which is the covariance of self and other divided by the product of their standard deviation.
INPUT:
Whichever time series has more terms is truncated.
EXAMPLES:
sage: v = finance.TimeSeries([1,-2,3]); w = finance.TimeSeries([4,5,-10])
sage: v.correlation(w)
-0.558041609...
sage: v.covariance(w)/(v.standard_deviation() * w.standard_deviation())
-0.558041609...
Return the covariance of the time series self and other.
INPUT:
Whichever time series has more terms is truncated.
EXAMPLES:
sage: v = finance.TimeSeries([1,-2,3]); w = finance.TimeSeries([4,5,-10])
sage: v.covariance(w)
-11.777777777777779
Return the new time series got by taking the differences of
successive terms in the time series. So if self is the time
series , then this function outputs the
series
. The output series has one
less term than the input series. If the optional parameter
is given, return
.
INPUT:
OUTPUT:
A new time series.
EXAMPLES:
sage: v = finance.TimeSeries([5,4,1.3,2,8]); v
[5.0000, 4.0000, 1.3000, 2.0000, 8.0000]
sage: v.diffs()
[-1.0000, -2.7000, 0.7000, 6.0000]
Return new time series got by applying the exponential map to all the terms in the time series.
OUTPUT:
A new time series.
EXAMPLES:
sage: v = finance.TimeSeries([1..5]); v
[1.0000, 2.0000, 3.0000, 4.0000, 5.0000]
sage: v.exp()
[2.7183, 7.3891, 20.0855, 54.5982, 148.4132]
sage: v.exp().log()
[1.0000, 2.0000, 3.0000, 4.0000, 5.0000]
Return the exponential moving average time series. Assumes the input time series was constant with its starting value for negative time. The t-th step of the output is the sum of the previous k-1 steps of self and the k-th step divided by k.
The 0-th term is formally undefined, so we define it to be 0, and we define the first term to be self[0].
INPUT:
OUTPUT:
A time series with the same number of steps as self.
EXAMPLES:
sage: v = finance.TimeSeries([1,1,1,2,3]); v
[1.0000, 1.0000, 1.0000, 2.0000, 3.0000]
sage: v.exponential_moving_average(0)
[0.0000, 1.0000, 1.0000, 1.0000, 1.0000]
sage: v.exponential_moving_average(1)
[0.0000, 1.0000, 1.0000, 1.0000, 2.0000]
sage: v.exponential_moving_average(0.5)
[0.0000, 1.0000, 1.0000, 1.0000, 1.5000]
Some more examples:
sage: v = finance.TimeSeries([1,2,3,4,5])
sage: v.exponential_moving_average(1)
[0.0000, 1.0000, 2.0000, 3.0000, 4.0000]
sage: v.exponential_moving_average(0)
[0.0000, 1.0000, 1.0000, 1.0000, 1.0000]
Extend this time series by appending elements from the iterable right.
INPUT:
EXAMPLES:
sage: v = finance.TimeSeries([1,2,-5]); v
[1.0000, 2.0000, -5.0000]
sage: v.extend([-3.5, 2])
sage: v
[1.0000, 2.0000, -5.0000, -3.5000, 2.0000]
Return the real discrete fast Fourier transform of self, as a real time series:
where
for . Note that
.
EXAMPLES:
sage: v = finance.TimeSeries([1..9]); v
[1.0000, 2.0000, 3.0000, 4.0000, 5.0000, 6.0000, 7.0000, 8.0000, 9.0000]
sage: w = v.fft(); w
[45.0000, -4.5000, 12.3636, -4.5000, 5.3629, -4.5000, 2.5981, -4.5000, 0.7935]
We get just the series of real parts of
sage: finance.TimeSeries([w[0]]) + w[1:].scale_time(2)
[45.0000, -4.5000, -4.5000, -4.5000, -4.5000]
An example with an even number of terms:
sage: v = finance.TimeSeries([1..10]); v
[1.0000, 2.0000, 3.0000, 4.0000, 5.0000, 6.0000, 7.0000, 8.0000, 9.0000, 10.0000]
sage: w = v.fft(); w
[55.0000, -5.0000, 15.3884, -5.0000, 6.8819, -5.0000, 3.6327, -5.0000, 1.6246, -5.0000]
sage: v.fft().ifft()
[1.0000, 2.0000, 3.0000, 4.0000, 5.0000, 6.0000, 7.0000, 8.0000, 9.0000, 10.0000]
Return the frequency histogram of the values in this time series divided up into the given number of bins.
INPUT:
OUTPUT:
EXAMPLES:
sage: v = finance.TimeSeries([5,4,1.3,2,8,10,3,-5]); v
[5.0000, 4.0000, 1.3000, 2.0000, 8.0000, 10.0000, 3.0000, -5.0000]
sage: v.histogram(3)
([1, 4, 3], [(-5.0, 0.0), (0.0, 5.0), (5.0, 10.0)])
Returns an estimate of the Hurst exponent of this time series. We use the algorithm from pages 61 – 63 of [Peteres, Fractal Market Analysis (1994); see Google Books].
We define the Hurst exponent of a constant time series to be 1.
EXAMPLES:
The Hurst exponent of Brownian motion is 1/2. We approximate it with some specific samples. Note that the estimator is biased and slightly overestimates.
sage: set_random_seed(0)
sage: bm = finance.TimeSeries(10^5).randomize('normal').sums(); bm
[0.6767, 0.2756, 0.6332, 0.0469, -0.8897 ... 152.2437, 151.5327, 152.7629, 152.9169, 152.9084]
sage: bm.hurst_exponent()
0.527450972...
We compute the Hurst exponent of a simulated fractional Brownian motion with Hurst parameter 0.7. This function estimates the Hurst exponent as 0.706511951...
sage: set_random_seed(0)
sage: fbm = finance.fractional_brownian_motion_simulation(0.7,0.1,10^5,1)[0]
sage: fbm.hurst_exponent()
0.706511951...
Another example with small Hurst exponent (notice the overestimation).
sage: fbm = finance.fractional_brownian_motion_simulation(0.2,0.1,10^5,1)[0]
sage: fbm.hurst_exponent()
0.278997441...
We compute the mean Hurst exponent of 100 simulated multifractal cascade random walks:
sage: set_random_seed(0)
sage: y = finance.multifractal_cascade_random_walk_simulation(3700,0.02,0.01,0.01,1000,100)
sage: finance.TimeSeries([z.hurst_exponent() for z in y]).mean()
0.57984822577934...
We compute the mean Hurst exponent of 100 simulated Markov switching multifractal time series. The Hurst exponent is quite small.
sage: set_random_seed(0)
sage: msm = finance.MarkovSwitchingMultifractal(8,1.4,0.5,0.95,3)
sage: y = msm.simulations(1000,100)
sage: finance.TimeSeries([z.hurst_exponent() for z in y]).mean()
0.286102325623705...
Return the real discrete inverse fast Fourier transform of self, which is also a real time series.
This is the inverse of fft().
The returned real array contains
where for is even
and for is odd
where denotes complex conjugate of preceding expression.
EXAMPLES:
sage: v = finance.TimeSeries([1..10]); v
[1.0000, 2.0000, 3.0000, 4.0000, 5.0000, 6.0000, 7.0000, 8.0000, 9.0000, 10.0000]
sage: v.ifft()
[5.1000, -5.6876, 1.4764, -1.0774, 0.4249, -0.1000, -0.2249, 0.6663, -1.2764, 1.6988]
sage: v.ifft().fft()
[1.0000, 2.0000, 3.0000, 4.0000, 5.0000, 6.0000, 7.0000, 8.0000, 9.0000, 10.0000]
Return list of elements of self.
EXAMPLES:
sage: v = finance.TimeSeries([1,-4,3,-2.5,-4,3])
sage: v.list()
[1.0, -4.0, 3.0, -2.5, -4.0, 3.0]
Return new time series got by taking the logarithms of all the terms in the time series.
OUTPUT:
A new time series.
EXAMPLES:
We exponentiate then log a time series and get back the original series:
sage: v = finance.TimeSeries([1,-4,3,-2.5,-4,3]); v
[1.0000, -4.0000, 3.0000, -2.5000, -4.0000, 3.0000]
sage: v.exp()
[2.7183, 0.0183, 20.0855, 0.0821, 0.0183, 20.0855]
sage: v.exp().log()
[1.0000, -4.0000, 3.0000, -2.5000, -4.0000, 3.0000]
Log of 0 gives -inf:
sage: finance.TimeSeries([1,0,3]).log()[1]
-inf
Return the largest value in this time series. If this series has length 0 we raise a ValueError.
INPUT:
OUTPUT:
EXAMPLES:
sage: v = finance.TimeSeries([1,-4,3,-2.5,-4,3])
sage: v.max()
3.0
sage: v.max(index=True)
(3.0, 2)
Return the mean (average) of the elements of self.
OUTPUT:
A double.
EXAMPLES:
sage: v = finance.TimeSeries([1,1,1,2,3]); v
[1.0000, 1.0000, 1.0000, 2.0000, 3.0000]
sage: v.mean()
1.6
Return the smallest value in this time series. If this series has length 0 we raise a ValueError.
INPUT:
OUTPUT:
EXAMPLES:
sage: v = finance.TimeSeries([1,-4,3,-2.5,-4])
sage: v.min()
-4.0
sage: v.min(index=True)
(-4.0, 1)
Return the k-th moment of self, which is just the mean of the k-th powers of the elements of self.
INPUT:
OUTPUT:
A double.
EXAMPLES:
sage: v = finance.TimeSeries([1,1,1,2,3]); v
[1.0000, 1.0000, 1.0000, 2.0000, 3.0000]
sage: v.moment(1)
1.6
sage: v.moment(2)
3.2
Return a NumPy version of this time series.
Note
If copy is False, return a NumPy 1-D array reference to exactly the same block of memory as this time series. This is very, very fast and makes it easy to quickly use all NumPy/SciPy functionality on self. However, it is dangerous because when this time series goes out of scope and is garbage collected, the corresponding NumPy reference object will point to garbage.
INPUT:
OUTPUT:
A numpy 1-D array.
EXAMPLES:
sage: v = finance.TimeSeries([1,-3,4.5,-2])
sage: w = v.numpy(copy=False); w
array([ 1. , -3. , 4.5, -2. ])
sage: type(w)
<type 'numpy.ndarray'>
sage: w.shape
(4,)
Notice that changing w also changes v too!
sage: w[0] = 20
sage: w
array([ 20. , -3. , 4.5, -2. ])
sage: v
[20.0000, -3.0000, 4.5000, -2.0000]
If you want a separate copy do not give the copy=False option.
sage: z = v.numpy(); z
array([ 20. , -3. , 4.5, -2. ])
sage: z[0] = -10
sage: v
[20.0000, -3.0000, 4.5000, -2.0000]
Return a plot of this time series as a line or points through
, where
ranges over nonnegative integers up to the
length of self.
INPUT:
EXAMPLES:
sage: v = finance.TimeSeries([5,4,1.3,2,8,10,3,-5]); v
[5.0000, 4.0000, 1.3000, 2.0000, 8.0000, 10.0000, 3.0000, -5.0000]
sage: v.plot()
sage: v.plot(points=True)
sage: v.plot() + v.plot(points=True, rgbcolor='red')
sage: v.plot() + v.plot(points=True, rgbcolor='red', pointsize=50)
Return a candlestick plot of this time series with the given number of bins.
A candlestick plot is a style of bar-chart used to view open, high, low, and close stock data. At each bin, the line represents the high / low range. The bar represents the open / close range. The interval is colored blue if the open for that bin is less than the close. If the close is less than the open, then that bin is colored red instead.
INPUT:
OUTPUT:
A candlestick plot.
EXAMPLES:
Here we look at the candlestick plot for Brownian motion:
sage: v = finance.TimeSeries(1000).randomize()
sage: v.plot_candlestick(bins=20)
Return histogram plot of this time series with given number of bins.
INPUT:
OUTPUT:
A histogram plot.
EXAMPLES:
sage: v = finance.TimeSeries([1..50])
sage: v.plot_histogram(bins=10)
sage: v.plot_histogram(bins=3,normalize=False,aspect_ratio=1)
Return a new time series with every elements of self raised to the k-th power.
INPUT:
OUTPUT:
A time series.
EXAMPLES:
sage: v = finance.TimeSeries([1,1,1,2,3]); v
[1.0000, 1.0000, 1.0000, 2.0000, 3.0000]
sage: v.pow(2)
[1.0000, 1.0000, 1.0000, 4.0000, 9.0000]
Return the product of all the entries of self. If self has length 0, returns 1.
OUTPUT:
A double.
EXAMPLES:
sage: v = finance.TimeSeries([1,1,1,2,3]); v
[1.0000, 1.0000, 1.0000, 2.0000, 3.0000]
sage: v.prod()
6.0
Randomize the entries in this time series, and return a reference to self. Thus this function both changes self in place, and returns a copy of self, for convenience.
INPUT:
Note
All random numbers are generated using algorithms that build on the high quality GMP random number function gmp_urandomb_ui. Thus this function fully respects the Sage set_random_state command. It’s not quite as fast as the C library random number generator, but is of course much better quality, and is platform independent.
EXAMPLES:
We generate 5 uniform random numbers in the interval [0,1]:
sage: set_random_seed(0)
sage: finance.TimeSeries(5).randomize()
[0.8685, 0.2816, 0.0229, 0.1456, 0.7314]
We generate 5 uniform random numbers from 5 to :
sage: set_random_seed(0)
sage: finance.TimeSeries(10).randomize('uniform', 5, 2)
[6.7369, 5.5632, 5.0459, 5.2911, 6.4628, 5.2412, 5.2010, 5.2761, 5.5813, 5.5439]
We generate 5 normal random values with mean 0 and variance 1.
sage: set_random_seed(0)
sage: finance.TimeSeries(5).randomize('normal')
[0.6767, -0.4011, 0.3576, -0.5864, -0.9365]
We generate 10 normal random values with mean 5 and variance 2.
sage: set_random_seed(0)
sage: finance.TimeSeries(10).randomize('normal', 5, 2)
[6.3534, 4.1978, 5.7153, 3.8273, 3.1269, 2.9598, 3.7484, 6.7472, 3.8986, 4.6271]
We generate 5 values using the semicircle distribution.
sage: set_random_seed(0)
sage: finance.TimeSeries(5).randomize('semicircle')
[0.7369, -0.9541, 0.4628, -0.7990, -0.4187]
We generate 1 million normal random values and create a frequency histogram.
sage: set_random_seed(0)
sage: a = finance.TimeSeries(10^6).randomize('normal')
sage: a.histogram(10)[0]
[36, 1148, 19604, 130699, 340054, 347870, 137953, 21290, 1311, 35]
We take the above values, and compute the proportion that lie within 1, 2, 3, 5, and 6 standard deviations of the mean (0):
sage: s = a.standard_deviation()
sage: len(a.clip_remove(-s,s))/float(len(a))
0.683094
sage: len(a.clip_remove(-2*s,2*s))/float(len(a))
0.954559
sage: len(a.clip_remove(-3*s,3*s))/float(len(a))
0.997228
sage: len(a.clip_remove(-5*s,5*s))/float(len(a))
0.999998
There were no “six sigma events”:
sage: len(a.clip_remove(-6*s,6*s))/float(len(a))
1.0
Return the rescaled range statistic of self, which is
defined as follows (see Hurst 1951). If the optional
parameter b is given, return the average of
range
statistics of disjoint blocks of size b.
Let be the standard deviation of the sequence of
differences of self, and let
be the k-th term of self.
Let
be the number of terms of self, and set
. Then
where the max and min are over all .
Basically replacing
by
allows us to measure
the difference from the line from the origin to
.
INPUT:
OUTPUT:
A float.
EXAMPLES:
Notice that if we make a Brownian motion random walk, there is no difference if we change the standard deviation.
sage: set_random_seed(0); finance.TimeSeries(10^6).randomize('normal').sums().range_statistic()
1897.8392602...
sage: set_random_seed(0); finance.TimeSeries(10^6).randomize('normal',0,100).sums().range_statistic()
1897.8392602...
Change self by multiplying every value in the series by s.
INPUT:
EXAMPLES:
sage: v = finance.TimeSeries([5,4,1.3,2,8,10,3,-5]); v
[5.0000, 4.0000, 1.3000, 2.0000, 8.0000, 10.0000, 3.0000, -5.0000]
sage: v.rescale(0.5)
sage: v
[2.5000, 2.0000, 0.6500, 1.0000, 4.0000, 5.0000, 1.5000, -2.5000]
Return new time series obtain from this time series by reversing the order of the entries in this time series.
OUTPUT:
A time series.
EXAMPLES:
sage: v = finance.TimeSeries([1..5])
sage: v.reversed()
[5.0000, 4.0000, 3.0000, 2.0000, 1.0000]
Return new time series obtained by multiplying every value in the series by s.
INPUT:
OUTPUT:
A new time series with all values multiplied by s.
EXAMPLES:
sage: v = finance.TimeSeries([5,4,1.3,2,8,10,3,-5]); v
[5.0000, 4.0000, 1.3000, 2.0000, 8.0000, 10.0000, 3.0000, -5.0000]
sage: v.scale(0.5)
[2.5000, 2.0000, 0.6500, 1.0000, 4.0000, 5.0000, 1.5000, -2.5000]
Return the new time series at scale k. If the input
time series is , then this function
returns the shorter time series
.
INPUT:
OUTPUT:
A new time series.
EXAMPLES:
sage: v = finance.TimeSeries([5,4,1.3,2,8,10,3,-5]); v
[5.0000, 4.0000, 1.3000, 2.0000, 8.0000, 10.0000, 3.0000, -5.0000]
sage: v.scale_time(1)
[5.0000, 4.0000, 1.3000, 2.0000, 8.0000, 10.0000, 3.0000, -5.0000]
sage: v.scale_time(2)
[5.0000, 1.3000, 8.0000, 3.0000]
sage: v.scale_time(3)
[5.0000, 2.0000]
sage: v.scale_time(10)
[]
A series of odd length:
sage: v = finance.TimeSeries([1..5]); v
[1.0000, 2.0000, 3.0000, 4.0000, 5.0000]
sage: v.scale_time(2)
[1.0000, 3.0000, 5.0000]
TESTS:
sage: v.scale_time(0)
Traceback (most recent call last):
...
ValueError: k must be positive
sage: v.scale_time(-1)
Traceback (most recent call last):
...
ValueError: k must be positive
Calls plot and passes all arguments onto the plot function. This is thus just an alias for plot.
EXAMPLES:
Draw a plot of a time series:
sage: finance.TimeSeries([1..10]).show()
Return the moving average time series over the last k time units. Assumes the input time series was constant with its starting value for negative time. The t-th step of the output is the sum of the previous k - 1 steps of self and the k-th step divided by k. Thus k values are averaged at each point.
INPUT:
OUTPUT:
A time series with the same number of steps as self.
EXAMPLES:
sage: v = finance.TimeSeries([1,1,1,2,3]); v
[1.0000, 1.0000, 1.0000, 2.0000, 3.0000]
sage: v.simple_moving_average(0)
[1.0000, 1.0000, 1.0000, 2.0000, 3.0000]
sage: v.simple_moving_average(1)
[1.0000, 1.0000, 1.0000, 2.0000, 3.0000]
sage: v.simple_moving_average(2)
[1.0000, 1.0000, 1.0000, 1.5000, 2.5000]
sage: v.simple_moving_average(3)
[1.0000, 1.0000, 1.0000, 1.3333, 2.0000]
Return the standard deviation of the entries of self.
INPUT:
OUTPUT:
A double.
EXAMPLES:
sage: v = finance.TimeSeries([1,1,1,2,3]); v
[1.0000, 1.0000, 1.0000, 2.0000, 3.0000]
sage: v.standard_deviation()
0.8944271909...
sage: v.standard_deviation(bias=True)
0.8
TESTS:
sage: finance.TimeSeries([1]).standard_deviation()
0.0
sage: finance.TimeSeries([]).standard_deviation()
0.0
Return the sum of all the entries of self. If self has length 0, returns 0.
OUTPUT:
A double.
EXAMPLES:
sage: v = finance.TimeSeries([1,1,1,2,3]); v
[1.0000, 1.0000, 1.0000, 2.0000, 3.0000]
sage: v.sum()
8.0
Return the new time series got by taking the running partial sums of the terms of this time series.
INPUT:
OUTPUT:
A time series.
EXAMPLES:
sage: v = finance.TimeSeries([1,1,1,2,3]); v
[1.0000, 1.0000, 1.0000, 2.0000, 3.0000]
sage: v.sums()
[1.0000, 2.0000, 3.0000, 5.0000, 8.0000]
Return the variance of the elements of self, which is the mean of the squares of the differences from the mean.
INPUT:
OUTPUT:
A double.
EXAMPLE:
sage: v = finance.TimeSeries([1,1,1,2,3]); v
[1.0000, 1.0000, 1.0000, 2.0000, 3.0000]
sage: v.variance()
0.8
sage: v.variance(bias=True)
0.64
TESTS:
sage: finance.TimeSeries([1]).variance()
0.0
sage: finance.TimeSeries([]).variance()
0.0
Return real double vector whose entries are the values of this time series. This is useful since vectors have standard algebraic structure and play well with matrices.
OUTPUT:
A real double vector.
EXAMPLES:
sage: v = finance.TimeSeries([1..10])
sage: v.vector()
(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0)
Given a sequence of lagged autocovariances of length produce
so that the first
autocovariance coefficients
of the autoregressive processes
are the same as the input sequence.
The function works by solving the Yule-Walker equations
, where
,
, with
the autocovariance of lag
and
.
EXAMPLES:
In this example we consider the multifractal cascade random walk of length 1000, and use simulations to estimate the expected first few autocovariance parameters for this model, then use them to construct a linear filter that works vastly better than a linear filter constructed from the same data but not using this model. The Monte-Carlo method illustrated below should work for predicting one “time step” into the future for any model that can be simulated. To predict k time steps into the future would require using a similar technique but would require scaling time by k.
We create 100 simulations of a multifractal random walk. This models the logarithms of a stock price sequence.
sage: set_random_seed(0)
sage: y = finance.multifractal_cascade_random_walk_simulation(3700,0.02,0.01,0.01,1000,100)
For each walk below we replace the walk by the walk but where each step size is replaced by its absolute value – this is what we expect to be able to predict given the model, which is only a model for predicting volatility. We compute the first 200 autocovariance values for every random walk:
sage: c = [[a.diffs().abs().sums().autocovariance(i) for a in y] for i in range(200)]
We make a time series out of the expected values of the autocovariances:
sage: ac = finance.TimeSeries([finance.TimeSeries(z).mean() for z in c])
sage: ac
[3.9962, 3.9842, 3.9722, 3.9601, 3.9481 ... 1.7144, 1.7033, 1.6922, 1.6812, 1.6701]
Note
ac looks like a line – one could best fit it to yield a lot more approximate autocovariances.
We compute the autoregression coefficients matching the above autocovariances:
sage: F = finance.autoregressive_fit(ac); F
[0.9982, -0.0002, -0.0002, 0.0003, 0.0001 ... 0.0002, -0.0002, -0.0000, -0.0002, -0.0014]
Note that the sum is close to 1:
sage: sum(F)
0.99593284089454...
Now we make up an ‘out of sample’ sequence:
sage: y2 = finance.multifractal_cascade_random_walk_simulation(3700,0.02,0.01,0.01,1000,1)[0].diffs().abs().sums()
sage: y2
[0.0013, 0.0059, 0.0066, 0.0068, 0.0184 ... 6.8004, 6.8009, 6.8063, 6.8090, 6.8339]
And we forecast the very last value using our linear filter; the forecast is close:
sage: y2[:-1].autoregressive_forecast(F)
6.7836741372407...
In fact it is closer than we would get by forecasting using a linear filter made from all the autocovariances of our sequence:
sage: y2[:-1].autoregressive_forecast(y2[:-1].autoregressive_fit(len(y2)))
6.770168705668...
We record the last 20 forecasts, always using all correct values up to the one we are forecasting:
sage: s1 = sum([(y2[:-i].autoregressive_forecast(F)-y2[-i])^2 for i in range(1,20)])
We do the same, but using the autocovariances of the sample sequence:
sage: F2 = y2[:-100].autoregressive_fit(len(F))
sage: s2 = sum([(y2[:-i].autoregressive_forecast(F2)-y2[-i])^2 for i in range(1,20)])
Our model gives us something that is 15 percent better in this case:
sage: s2/s1
1.15464636102...
How does it compare overall? To find out we do 100 simulations and for each we compute the percent that our model beats naively using the autocovariances of the sample:
sage: y_out = finance.multifractal_cascade_random_walk_simulation(3700,0.02,0.01,0.01,1000,100)
sage: s1 = []; s2 = []
sage: for v in y_out:
... s1.append(sum([(v[:-i].autoregressive_forecast(F)-v[-i])^2 for i in range(1,20)]))
... F2 = v[:-len(F)].autoregressive_fit(len(F))
... s2.append(sum([(v[:-i].autoregressive_forecast(F2)-v[-i])^2 for i in range(1,20)]))
...
We find that overall the model beats naive linear forecasting by 35 percent!
sage: s = finance.TimeSeries([s2[i]/s1[i] for i in range(len(s1))])
sage: s.mean()
1.354073591877...
Version 1 unpickle method.
INPUT:
EXAMPLES:
sage: v = finance.TimeSeries([1,2,3])
sage: s = v.__reduce__()[1][0]
sage: type(s)
<type 'str'>
sage: sage.finance.time_series.unpickle_time_series_v1(s,3)
[1.0000, 2.0000, 3.0000]
sage: sage.finance.time_series.unpickle_time_series_v1(s+s,6)
[1.0000, 2.0000, 3.0000, 1.0000, 2.0000, 3.0000]
sage: sage.finance.time_series.unpickle_time_series_v1('',0)
[]