MovingMap maps to second level unexpectedly

4

1

I'm trying to build a financial indicator in mathematica. I import some historical data

 Data = FinancialData["^GSPC", "OHLCV", {2009}];
 Data[[1;;5]]

 {{{2009, 1, 2}, {902.99, 934.73, 899.35, 931.8, 4048270000}}, 
  {{2009, 1, 5}, {929.17, 936.63, 919.53, 927.45, 5413910000}}, 
  {{2009, 1, 6}, {931.17, 943.85, 927.28, 934.7, 5392620000}}, 
  {{2009, 1, 7}, {927.45, 927.45, 902.37, 906.65, 4704940000}}, 
  {{2009, 1, 8}, {905.73, 910., 896.81, 909.73, 4991550000}}}

Now I want to apply a function to a moving window of the data:

 MovingMap[foo[#] &, Data, 5]

However, MovingMap does something unexpected it maps over the second entry in each list:

{{3440361600, 
  foo[{{902.99, 934.73, 899.35, 931.8, 4048270000}, 
       {929.17, 936.63, 919.53, 927.45, 5413910000}, 
       {931.17, 943.85, 927.28, 934.7, 5392620000}, 
       {927.45, 927.45, 902.37, 906.65, 4704940000}, 
       {905.73, 910., 896.81, 909.73, 4991550000}}]},
       {3440448000, 
       foo[{{929.17, 936.63, 919.53, 927.45, 5413910000}, 
            {931.17, 943.85, 927.28, 934.7, 5392620000}, 
            {927.45, 927.45, 902.37, 906.65, 4704940000}, 
            {905.73, 910., 896.81, 909.73, 4991550000}, 
            {909.91, 911.93, 888.31, 890.35, 4716500000}}]}, ...}

I was expecting something like a moving window through the list:

  foo[{{{date}, {O, H, L, C, V}},
       {{date}, {O, H, L, C, V}},
       {{date}, {O, H, L, C, V}},
       {{date}, {O, H, L, C, V}}, ...}]

What have I misunderstood or done wrong here?

Just to be thorough

 MovingMap[foo &, dowData[[1 ;; 200]], {20, "Day"}]

Produces this output:

{{3441484800, foo}, 
 {3441571200, foo}, 
 {3441657600, foo},...}

EDIT: It seems when given a time series like that which FinancialData returns MovingMap will Map over the data for you. Removing the need to deal with the dates yourself. Poorly documented, but convenient if you know about this behaviour.

However, my indicator is calling FinancialIndicator itself, which seems to need the full date/OHLCV time series. Is there any way to have this work as one might expect?

Example of what I'm trying to do:

 intraTotal[ts_] := Total[FinancialIndicator["TrueRange" ][ts]];

 periodRange[ts_] := Max[Map[ #[[2, 2]] &, ts]] - Min[Map[ #[[2, 3]] &, ts]];

 FracDim[ts_, period_] := intraTotal[Take[ts, -period]]/periodRange[Take[ts, -period]];

user4860

Posted 2015-03-14T00:47:26.577

Reputation:

MovingMap[foo, Data, {5, "Day"}] – Dr. belisarius – 2015-03-14T01:05:08.133

Still shows the same behaviour. – None – 2015-03-14T01:08:12.350

You can just rewrite your FracDim to work similar to the FinancialIndicators. Something like fracDim[ts_, period_] := Table[ intraTotal[ts[[s ;; s + period]]]/ periodRange[ts[[s ;; s + period]]], {s, Length@ts - period}];. – Karsten 7. – 2015-03-14T04:22:48.417

That would work in the small. But it stops me from writing indicators which rely on other indicators to do part of the work. and this seems like exactly the sort of use case MovingMap was designed for. – None – 2015-03-14T04:38:21.967

Answers

6

MovingMap is doing, what it is supposed to do.
Evaluating

AbsoluteTime /@ (Data[[1 ;; 5]][[All, 1]])

{3439843200, 3440102400, 3440188800, 3440275200, 3440361600}

gives the timestamps for the first five data points in absolute time.
The output of

MovingMap[foo[#] &, Data, 5]

or simpler

MovingMap[foo[#] &, Data[[1 ;; 5]], 5]
{{3440361600, 
  foo[{{902.99, 934.73, 899.35, 931.8, 4048270000}, 
       {929.17, 936.63, 919.53, 927.45, 5413910000}, 
       {931.17, 943.85, 927.28, 934.7, 5392620000}, 
       {927.45, 927.45, 902.37, 906.65, 4704940000}, 
       {905.73, 910., 896.81, 909.73, 4991550000}}]}}

shows that foo is applied to the values of the first five data points and gets combined with the timestamps of the fifth data point.


How to make a FinancialIndicator work within MovingMap

I didn't test all, but it seems like no FinancialIndicator is actually using the timestamps and I can't see a reason why any should. Therefore you only need to create the expected input structure.
For your example:

intraTotal[ts_] := 
 Total[FinancialIndicator["TrueRange"][Transpose[{ConstantArray[{}, Length@ts], ts}]]]

Now

MovingMap[intraTotal[#] &, data, 5]

will work as you had expected.

Karsten 7.

Posted 2015-03-14T00:47:26.577

Reputation: 26 728

Yeah, that's it – Dr. belisarius – 2015-03-14T01:12:22.483

Okay, the documentation isn't clear on this then. You're right that it IS mentioned that it understands time series, but only much farther down the page. Passing in these naked OHLCV lists causes problems using FinancialIndicator within the functions. – None – 2015-03-14T01:30:18.703

@Steven Most FinancialIndicators have time frame as a parameter (most with a default value) and already do some kind of moving mapping. Therefore they don't seem to be build to work together with MovingMap. – Karsten 7. – 2015-03-14T02:54:11.453

I understand that, I'm using a FinancialIndicator inside of my own indicator which I'd be using MovingMap to calculate. So moving MovingMap is losing me information that FinancialIndicator needs. – None – 2015-03-14T03:56:44.483

@Steven To the end of my answer I added a way how you can make FinancialIndicator work together with MovingMap. Does this solve your problems? – Karsten 7. – 2015-03-20T08:04:03.490

@Steven The other two functions in your example probably should be periodRange[ts_] := Max[ts[[All, 2]]] - Min[ts[[All, 3]]] and fracDim[ts_] := intraTotal[ts]/periodRange[ts]. – Karsten 7. – 2015-03-20T08:09:46.787

Karsten that solves the problem nicely. Thanks! Though Wolfram probably want to either update moving map or make things clear farther up in the documentation. – None – 2015-03-22T01:47:40.143