9
$\begingroup$

Alpha Vantage Inc. is a leading provider of free APIs in JSON and CSV formats for real-time and historical stock market data.

With the recent glitch of the Yahoo Finance API, and with FinancialData no longer working, Alpha Vantage is a solid alternative for retrieving financial data for free. It’s definitely worth checking out if you are interested in financial analysis.

Based upon their API documentation, I wrote the following function to retrieve the stock data:

AlphaFinancialData[symbol_, apikey_] := 
  Import[StringJoin[
    "https://www.alphavantage.co/query?function=TIME_SERIES_DAILY", 
    "&symbol=", symbol, "&outputsize=compact", "&apikey=", key]];

AlphaIndicator[symbol_, indicator_, apikey_] := 
  Import[StringJoin["https://www.alphavantage.co/query?function=", 
    indicator,
    "&symbol=", symbol, "&interval=daily", "&series_type=close", 
    "&apikey=", key]]; 

The functions does return stock daily and intraday data in JSON.

My questions are how to use the Mathematica TradingChart and FinancialIndicator functions to do technical analysis on these data:

TradingChart[AlphaFinancialData["MSFT", key]

Is there good reference on how to manipulate these kinds of data?

$\endgroup$
  • 3
    $\begingroup$ What do you mean "FinancialData is no longer working"? It seems to work for me. What about it isn't working? $\endgroup$ – b3m2a1 Sep 14 '17 at 3:54
  • $\begingroup$ Doesn't work for me either. $\endgroup$ – George Wolfe Nov 11 '17 at 4:30
  • $\begingroup$ @david How your experience with Alpha fin data up to now? Is it stable? $\endgroup$ – Lou Nov 14 '17 at 8:48
7
$\begingroup$

Here is something I quickly came up with after a cursory reading of the docs:

$alphaVantageKey = (* insert your API key here *);
alphaVantageTradingChart[symbol_String, opts___] := Module[{daily, meta, msg, raw, series},
     daily = StringTemplate["https://www.alphavantage.co/query?function=TIME_SERIES_DAILY&datatype=json&outputsize=compact&symbol=`sym`&apikey=`key`"];
     raw = Import[daily @ <|"key" -> $alphaVantageKey, "sym" -> symbol|>, "RawJSON"];
     msg = Lookup[raw, "Error Message"];
     If[MissingQ[msg],
        series = KeyValueMap[{DateObject[#1], Interpreter["Number"] /@ Values[#2]} &, 
                             raw @ "Time Series (Daily)"];
        meta = AssociationThread[{"sym", "date", "tz"}, 
                                 MapAt[DateString[#, {"MonthName", " ", "Day", ", ", "Year"}] &, 
                                       Lookup[raw["Meta Data"],
                                              {"2. Symbol", "3. Last Refreshed", "5. Time Zone"}], 2]];
        TradingChart[series, opts,
                     PlotLabel -> Style[StringTemplate["Trading Chart for `sym`\n(last refreshed `date`, `tz` time)"]
                                        @ meta, Small]],
        Failure["API Error", <|"MessageTemplate" -> msg|>]]]

Examples:

alphaVantageTradingChart["MSFT"]

MSFT trading chart

alphaVantageTradingChart["MMM", {"BollingerBands"}]

MMM trading chart with Bollinger bands

$\endgroup$
  • $\begingroup$ You too got sucked in by this! I wasn't sure if I should answer given how straightforward it seemed. But it also seems useful for finance types (although I think the both of us are chemistry types, not finance). $\endgroup$ – b3m2a1 Sep 14 '17 at 4:25
  • 1
    $\begingroup$ @b3m2a1, yes, I am a chemist primarily (but hoping to get into this subject should I ever come into money). :D The docs for the API were well-written enough that I thought "hell, why not write it?" (At least I chose a chemical company as one of the examples.) $\endgroup$ – J. M. is away Sep 14 '17 at 4:27
  • 1
    $\begingroup$ Yeah this is definitely one of those cases where Mathematica showcases the kind of difference such a unified system makes. Well written docs & no hidden surprises, which honestly surprised me. Fun and quick (and it looks cool too, if only I knew what it meant). $\endgroup$ – b3m2a1 Sep 14 '17 at 4:31
  • $\begingroup$ Thank you very much. $\endgroup$ – david Sep 15 '17 at 4:23
5
$\begingroup$

So this is something that can really be answered just by reading the docs, but maybe it'll be generally useful, so I'll put it here.

First I got an API key from those people, then extended your function to be a bit more general:

$AVAPIKey = "0LWSL8V34410G7ZU";
Options[alphaVantageCallBuild] =
  {
   "function" -> "TIME_SERIES_DAILY",
   "symbol" -> "MSFT",
   "datatype" -> "json",
   "interval" -> "60min",
   "outputsize" -> "compact",
   "apikey" -> Automatic
   };
alphaVantageCallBuild[ops : OptionsPattern[]] :=
  HTTPRequest[
   <|
    "Scheme" -> "https",
    "Domain" -> "www.alphavantage.co",
    "Path" -> {"query"},
    "Query" -> {
      "function" -> OptionValue["function"],
      "symbol" -> OptionValue["symbol"],
      "apikey" -> 
       Replace[OptionValue["apikey"], Automatic :> $AVAPIKey],
      "datatype" -> OptionValue["datatype"],
      "interval" -> OptionValue["interval"]
      }
    |>
   ];

Then we'll import some of this stuff:

coreData = Import[alphaVantageCallBuild[], "RawJSON"];
Take[#, 5] & /@ coreData

<|"Meta Data" -> <|"1. Information" -> 
    "Daily Prices (open, high, low, close) and Volumes", 
   "2. Symbol" -> "MSFT", "3. Last Refreshed" -> "2017-09-13", 
   "4. Output Size" -> "Compact", "5. Time Zone" -> "US/Eastern"|>, 
 "Time Series (Daily)" -> <|"2017-09-13" -> <|"1. open" -> "74.9300", 
     "2. high" -> "75.2300", "3. low" -> "74.5500", 
     "4. close" -> "75.2100", "5. volume" -> "13351377"|>, 
   "2017-09-12" -> <|"1. open" -> "74.7600", "2. high" -> "75.2400", 
     "3. low" -> "74.3700", "4. close" -> "74.6800", 
     "5. volume" -> "14003880"|>, 
   "2017-09-11" -> <|"1. open" -> "74.3100", "2. high" -> "74.9400", 
     "3. low" -> "74.3100", "4. close" -> "74.7600", 
     "5. volume" -> "17455115"|>, 
   "2017-09-08" -> <|"1. open" -> "74.3300", "2. high" -> "74.4400", 
     "3. low" -> "73.8400", "4. close" -> "73.9800", 
     "5. volume" -> "14474383"|>, 
   "2017-09-07" -> <|"1. open" -> "73.6800", "2. high" -> "74.6000", 
     "3. low" -> "73.6000", "4. close" -> "74.3400", 
     "5. volume" -> "17165518"|>|>|>

Now you can see this data is kinda funky. They have those weird numeric tags on everything and the values are all strings. So we'll clean all this up:

Clear[alphaVantageTradingChartPrep];
alphaVantageTradingChartPrep[
   data_Association?(Quiet[DateObjectQ@DateObject[First@Keys[#]]] &)
   ] :=

  ToExpression@*KeyMap[StringTrim[#, DigitCharacter ~~ ". "] &] /@ 
   KeyMap[DateObject, data];
alphaVantageTradingChartPrep[data_Association] :=

  alphaVantageTradingChartPrep@
   SelectFirst[data, Quiet[DateObjectQ@DateObject[First@Keys[#]]] &];

timeSeries =
  alphaVantageTradingChartPrep@coreData;
timeSeries~Take~5

<|DateObject[{2017, 9, 13}, "Day", 
   "Gregorian", -7.] -> <|"open" -> 74.93, "high" -> 75.23, 
   "low" -> 74.55, "close" -> 75.21, "volume" -> 13351377|>, 
 DateObject[{2017, 9, 12}, "Day", 
   "Gregorian", -7.] -> <|"open" -> 74.76, "high" -> 75.24, 
   "low" -> 74.37, "close" -> 74.68, "volume" -> 14003880|>, 
 DateObject[{2017, 9, 11}, "Day", 
   "Gregorian", -7.] -> <|"open" -> 74.31, "high" -> 74.94, 
   "low" -> 74.31, "close" -> 74.76, "volume" -> 17455115|>, 
 DateObject[{2017, 9, 8}, "Day", 
   "Gregorian", -7.] -> <|"open" -> 74.33, "high" -> 74.44, 
   "low" -> 73.84, "close" -> 73.98, "volume" -> 14474383|>, 
 DateObject[{2017, 9, 7}, "Day", 
   "Gregorian", -7.] -> <|"open" -> 73.68, "high" -> 74.6, 
   "low" -> 73.6, "close" -> 74.34, "volume" -> 17165518|>|>

Then we just make it look how TradingChart wants it:

tradingChartData =
  KeyValueMap[
   {#, Lookup[#2, {"open", "high", "low", "close", "volume"}]} &,
   timeSeries];
tradingChartData // TradingChart

trading chart

And here's the same with the FinancialIndicator from the examples:

TradingChart[
 tradingChartData,
 {FinancialIndicator["SimpleMovingAverage", 50]}
 ]

financial indicator

$\endgroup$
  • $\begingroup$ Thank you so much for your very detailed answers. It is very helpful for everyone who would like to use the functions in the future. $\endgroup$ – david Sep 15 '17 at 4:22
  • $\begingroup$ the API has been very stable and thank you very much for the great work. $\endgroup$ – david Nov 15 '17 at 9:36

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.