This is a remarkably simple question for which I was not able to find an answer in the documentation.

For concreteness, suppose that we have some time series data, such as this (example taken straight from the Mathematica documentation):

ts = TimeSeries[FinancialData["MSFT", "Jan. 1, 2008"]];

...which we can plot with


...to get this

Mathematica graphics

Now, I can generate a linear fit to this data (which will be pretty lame, of course) with

fit = FindFit[ts, a + b t, {a, b}, t]

{a -> -526.325, b -> 1.58402*10^-7}

My question is: how do I superimpose the line corresponding to this linear approximation on top of the DateListPlot shown above?

Is there a simple way to do this?

NB: In case it matters, I'm interested in solutions that can be extrapolated beyond the data's original range. For example, I'd like to superimpose the line fit above over the curve shown below, so that the domain of the fit extends over all of the horizontal PlotRange (through the end of 2020):

DateListPlot[ts, PlotRange -> {{Automatic, {2020, 12, 31}}, {0, 150}}]

Mathematica graphics

(* set end date *)
With[{tend = {2020, 12, 31}},
  (* timings *)
  With[{times = ts["Times"], extension = Rest[DateRange[ts["LastTime"], AbsoluteTime[tend]]]},
    (* localize vars *)
    Block[{lmf, abst, est, ext, y, t, lts, xlts},
      (* linear fit *) 
      lmf = LinearModelFit[ts, abst, abst];
      (* linear est *)
      est = lmf["Response"] - lmf["FitResiduals"];
      (* linear ts over sample *)
      lts = TimeSeries[est, {times}, DateFunction :> (DateList[#] &)];
      (* out-of-sample est *)
      ext = lmf["Function"] /@ extension;
      (* out-of-sample ts *)
      xlts = TimeSeries[ext, {extension}, DateFunction :> (DateList[#] &)];
      (* prepare output plot *)
        {ts, lts, xlts},
        PlotRange -> {{Automatic, tend}, {0, 150}},
        PlotLegends -> Placed[
          {TimeSeries, LinearModelFit, Row[{LinearModelFit , , out , , of, , sample}]}, Below]

enter image description here


This might work. It is important to put DateListPlot first into Show in order to get appropriate coordinate axes.

ts = TimeSeries[FinancialData["MSFT", "Jan. 1, 2008"]];
fit = FindFit[ts, a + b t, {a, b}, t];
f = t \[Function] Evaluate[ b t + a /. fit];
ts2 = Transpose[{ts["Times"], Map[f, ts["Times"]]}];
 ListLinePlot[ts2, PlotStyle -> ColorData[97][2]]

enter image description here


You can just use the fit as an epilog if you appropriately extract the times from your data. First define fit as a function:

fit[t_] = a + b t /. FindFit[ts, a + b t, {a, b}, t];

and then make a line as an epilog to your DateListPlot:

Module[{firstlast = ts["Times"][[{1, -1}]]}, 
 DateListPlot[ts, Epilog -> Line[{#, fit@#} & /@ firstlast]

plot of dates with line


I was also trying to do something similar, but in Mathematica 12, the above code doesn't work. It gives you this error: "FindFit::ivar: Dataset [<<4>>] is not a valid variable." I'm very new to Mathematica and didn't find that particularly helpful.

To make it work you have to enable the "Legacy" switch when you get the data:

 ts = TimeSeries[FinancialData["MSFT", "Jan. 1, 2008", Method -> "Legacy"]];

Once you do this, the rest of it works as before.

  • $\begingroup$ Legacy drops the currency unit.To avoid that, don't use Legacy and do this instead: FindFit[ts["Path"], a + b t, {a, b}, t] $\endgroup$ – Rohit Namjoshi May 27 '19 at 21:32
  • $\begingroup$ That is very helpful. Thank you. Would you mind explaining why that works? I spent a good deal of this afternoon trying to do what I anticipated would be a very simple thing and found zero help in the documentation. When you get the FinancialData data structure back, there doesn't seem to be a way to look at how it is structured (or the data). I'm coming from an R and MATLAB background where you can peek at the actual data in any given structure and I'm struggling to understand how Mathematica structures are put together or otherwise get meaningful information about them. Thanks! $\endgroup$ – tunit May 27 '19 at 21:42
  • $\begingroup$ Take a look at the "Details and Options" section of the TimeSeries docs. It describes the properties that can be used to introspect/extract information. If you want to look at the symbolic representation of ts try FullForm@ts. That representation may change in future versions, but you can drill in. To get the internal QuantityArray: First@Cases[ts, _StructuredArray, Infinity]. Hope that helps. $\endgroup$ – Rohit Namjoshi May 27 '19 at 23:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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