11
$\begingroup$

I have a family of functions that require two TimeSeries (A and B). As a trivial example, imagine a function called beta[tsA_,tsB_] that determines the slope of the linear regression line for the changes in TimeSeries A relative to changes in TimeSeries B. It is easy to apply such a function to the entire series, but what if I want to apply it on a rolling basis?

MovingMap[] is no help because it allows only one TimeSeries as an argument. MapThread[] works but requires sacrificing all of MovingMap[]'s sophistication about TimeSeries.

Any suggestions?

$\endgroup$

2 Answers 2

6
$\begingroup$

You can create a time series with multiple values and apply an arbitrary function.

dates = DateRange[{2015, 10, 1}, DatePlus[{2015, 10, 1}, 29]];
data = RandomInteger[{1, 5}, {Length[dates], 2}];
tsdata = TimeSeries[data, {dates}];

Now, you can apply MovingMap on the function of your choice:

rollstd = MovingMap[StandardDeviation, tsdata, Quantity[4, "Days"]]
DateListPlot[rollstd, PlotTheme -> "Detailed"]

enter image description here

Further, you can define a function betafun as Covariance[series1,series2]/Variance[series2] and use this function on the time series.

betafun = N[Apply[Covariance, Transpose[#]]/Last[MapAt[Variance, Transpose[#], 2]]] &;
rollbeta = MovingMap[betafun, tsdata, Quantity[4, "Days"]];
DateListPlot[rollbeta]

enter image description here

$\endgroup$
2
$\begingroup$

This is an interesting question!

The short answer is that there doesn't seem to be any built-in that could perform the required task, something which is already alluded to in the question,

There is, however, a way to use MovingMap on any number of series in a way reminiscent of using MapThread on ordinary expressions.

The idea is to first bundle the series in a single TemporalObject with appropriate ValueDimensions and then feed it to MovingMap.

Such a solution has the downside that one needs to pick the series apart and put them back together again. It could also be argued that if it comes down to extracting "Paths" and/or "Values" from the series, one can simply then use ListConvolve or probably Partition to get the job done without having to reconstruct a new TimeSeries in order to feed it to MovingMap.

Even though this doesn't sound altogether unreasonable, it wouldn't seem completely useless to attempt a solution along the lines of 'solving a TimeSeries problem using TimeSeries', even in a somewhat roundabout way:

(* one series, two paths *)
bundle = TemporalData[{tsA, tsB}, ResamplingMethod -> None]; 

(* resample using avail t-val pairs *)
union = TimeSeriesResample[bundle, "Union"]

(* take the 'ResamplingMethod' value with a grain of salt *)
tsopts = {ResamplingMethod -> {None, None}, ValueDimensions -> 2,
  MissingDataMethod -> {"Interpolation", InterpolationOrder -> 0}};

(* one series, vector-valued single path *)
tsx = TimeSeries[Transpose[union["Values", All]], {union["Times"]},
  Apply[Sequence][tsopts]]

finally,

MovingMap[f[Differences[#]] &, tsx, Quantity[30, "Events"]]

should do the trick. Obviously, Quantity[30, "Events"] can be replaced with any other desirable wspec and f is used as a stand-in for an appropriate fitting function; probably Differences is something that can be incorporated later into f, too.

$\endgroup$
2
  • $\begingroup$ Do you find that you can use this in real-life /production code? imho TimeSeriesResample is very slow $\endgroup$ May 17, 2023 at 9:12
  • $\begingroup$ @IntroductionToProbability If I have to be completely honest, I don't think I have ever managed to write really fast Mathematica code; however, "real-life" or "production code" varies with the user; also, as far as I'm concerned, I prefer having code I know is correct even if it is somewhat slow, whatever 'slow' means; now, if we have to be specific about the particular code in the answer, I would be interested to know the dimensions of the problem instances you have encountered speed or performance issues with $\endgroup$
    – user42582
    May 24, 2023 at 16:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.