[ File # csp9666250, License # 2222627 ]
Licensed through http://www.canstockphoto.com in accordance with the End User License Agreement (http://www.canstockphoto.com/legal.php)
(c) Can Stock Photo Inc. / bbbar
Este programa permite descargar cualquier serie de precios disponible
Yahoo Finanzas directamente a Excel con solo conocer el símbolo de la acción. Antes de comenzar es importante adicionar la referencia Microsoft XML en el módulo VBA accediendo con el método abreviado Alt+F11, luego haciendo click en Tools + Reference y buscar la referencia (ver imagen) la cuál permite importar y manipular archivos en formato XML.
La macro central de este programa se compone de varios elementos. El primero es la subrutina que genera la consulta llamada GetYahooFinanceTable (ver código a continuación).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
|
Sub GetYahooFinanceTable() Dim s1 As Worksheet Set s1 = Sheets(ActiveSheet.Index) Range("A:I").Select Selection.ClearContents Range("A1").Select Dim sURL As String, sResult As String Dim oResult As Variant, oData As Variant, r As Long, C As Long sURL = "http://ichart.finance.yahoo.com/table.txt?s=" & LCase(s1.Cells(2, 10)) Debug.Print "URL: " & sURL sResult = GetHTTPResult(sURL) oResult = Split(sResult, vbLf) Debug.Print "Lines of result: " & UBound(oResult) For r = 0 To UBound(oResult) oData = Split(oResult(r), ",") For C = 0 To UBound(oData) ActiveSheet.Cells(r + 1, C + 1) = oData(C) Next Next Set oResult = Nothing Range("A1").Select Selection.End(xlDown).Select Dim l As Long l = Selection.Row ActiveWorkbook.Worksheets(s1.Name).Sort.SortFields.Add Key:=Range("A1"), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal With ActiveWorkbook.Worksheets(s1.Name).Sort .SetRange Range(Cells(2, 1), Cells(l, 7)) .Header = xlNo .MatchCase = False .Orientation = xlTopToBottom .SortMethod = xlPinYin .Apply End With Range("A1").Select Call UpdatePriceData(True, 9, 10) MsgBox ("Ok!") End Sub |
La macro obtiene la información utilizando APIs de Yahoo Finanzas (lea aquí el wiki de los APIs de Yahoo finanzas). Un API que traducido al español significa Interfaz de programación de aplicaciones, es un conjunto de subrutinas predefinidas que puede ser utilizado por otro software de manera abreviada (Wikipedia API) en este caso para descargar datos de Yahoo (lea aquí un blog sobre como utilizar el API de Yahoo finanzas para archivos CSV).
Para utilizar el API simplemente construimos el query con los parámetros deseados, en este caso solamente necesitamos el código de la acción almacenado en la celda J2 (2, 10). Utilizemos como ejemplo la acción de 3M (MMM). El comando requerido por el API será http://ichart.finance.yahoo.com/table.txt?s=mmm. Si usted introduce este código en su explorador podrá descargar un archivo de texto con el histórico de precios.
GetYahooFinanceTable ejecuta a su vez la función GetHTTPResult y la subrutina UpdatePriceData. La función permite crear la consulta (query) en formato XMLHTTP y lanzarla a la web.
|
Function GetHTTPResult(sURL As String) As String Dim XMLHTTP As Variant, sResult As String Set XMLHTTP = CreateObject("WinHttp.WinHttpRequest.5.1") XMLHTTP.Open "GET", sURL, False XMLHTTP.send Debug.Print "Status: " & XMLHTTP.Status & " - " & XMLHTTP.statusText sResult = XMLHTTP.responseText Debug.Print "Length of response: " & Len(sResult) Set XMLHTTP = Nothing GetHTTPResult = sResult End Function |
La subrutina UpdatePriceData prepara y llena los vectores con el resultado de la consulta. Para ello llama a la función GetQuoteXmlFromWeb y la subrutina GetQuoteFromXml.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
|
Sub UpdatePriceData(Optional manageCalcStatus As Boolean = True, Optional r As Integer = 2, Optional cc As Integer = 1) Dim stockXml As MSXML2.IXMLDOMNode Dim stockData(5) As Double ' Open, High, Low, Current/Close, Volume Dim stockDate As Date ' Last Trade Date Dim stockTime As Date ' Last Trade time sbState = Application.DisplayStatusBar Application.DisplayStatusBar = True Application.StatusBar = "Preparing quote request..." If manageCalcStatus Then appCalcStatus = Application.Calculation Application.Calculation = xlCalculationManual End If Range(Cells(r - 1, cc), Cells(r - 1, cc)).Select Selection.End(xlDown).Select iRowLast = ActiveCell.Row For i = r To iRowLast Range(Cells(i, cc), Cells(i, cc)).Select Application.StatusBar = "Get quote for: " & ActiveCell.Value Set stockXml = GetQuoteXmlFromWeb(ActiveCell.Value) If stockXml Is Nothing Then For n = 0 To UBound(stockData) - 1 stockData(n) = 0 Next n stockDate = Date stockTime = 0 Else stockData(0) = Val(GetQuoteFromXml(stockXml, "Open")) stockData(1) = Val(GetQuoteFromXml(stockXml, "DaysHigh")) stockData(2) = Val(GetQuoteFromXml(stockXml, "DaysLow")) stockData(3) = Val(GetQuoteFromXml(stockXml, "LastTradePriceOnly")) stockData(4) = Val(GetQuoteFromXml(stockXml, "Volume")) stockDate = CDate(GetQuoteFromXml(stockXml, "LastTradeDate")) stockTime = TimeValue(GetQuoteFromXml(stockXml, "LastTradeTime")) stockName = (GetQuoteFromXml(stockXml, "Name")) Application.StatusBar = "Get quote for: " & ActiveCell.Value End If For n = 0 To UBound(stockData) - 1 Cells(i, cc + n + 1) = stockData(n) Next n Cells(i, cc + n + 1) = stockDate Cells(i, cc + n + 2) = stockTime Cells(i, cc + n + 3) = stockName Next i If manageCalcStatus Then Application.StatusBar = "Resetting calculation state..." Application.Calculation = appCalcStatus End If Application.StatusBar = False Application.DisplayStatusBar = sbState End Sub |
La función GetQuoteXmlFromWeb es la que descarga la información en archivo XML y lo traduce. Un archivo XML es una estructura anidada de datos (padre e hijo) lo que permite manipular múltiples dimensiones y gran cantidad de información. Desafortunadamente no es tan simple descifrar la estructura por lo que utilizamos una función para descifrar la relación jerárquica de datos (ver función FindChildNodeName al final).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
|
Function GetQuoteXmlFromWeb(stockSymbol As String) As MSXML2.IXMLDOMNode Dim QuoteXMLstream As MSXML2.DOMDocument Dim QuoteXMLHttp As MSXML2.XMLHTTP60 Dim oChild As MSXML2.IXMLDOMNode Dim fSuccess As Boolean Dim URL As String On Error GoTo HandleErr ' create the URL that requests the XML stream from Yahoo Finance URL = "http://query.yahooapis.com/v1/public/yql?q=SELECT%20*%20FROM%20yahoo.finance.quotes%20WHERE%20symbol%3D'" & Trim(stockSymbol) & "'" URL = URL & "&diagnostics=false&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys" ' pull in the XML stream Set QuoteXMLHttp = New MSXML2.XMLHTTP60 With QuoteXMLHttp Call .Open("GET", URL, False) Call .send End With fSuccess = QuoteXMLHttp.Status If Not fSuccess Then MsgBox "error loading Yahoo Finance XML stream" Exit Function End If ' Turn it into an XML document Set QuoteXMLstream = New MSXML2.DOMDocument fSuccsss = QuoteXMLstream.LoadXML(QuoteXMLHttp.responseText) If Not fSuccess Then ' quit on failure MsgBox "error parsing Yahoo Finance XML stream" Exit Function End If ' Structure is: query.results.quote (3 children in) to get to our quote params Set oChild = FindChildNodeName(QuoteXMLstream.ChildNodes, "query") If oChild Is Nothing Then MsgBox "error loading Yahoo Finance XML stream: cannot find 'query'" Exit Function End If Set oChild = FindChildNodeName(oChild.ChildNodes, "results") If oChild Is Nothing Then MsgBox "error loading Yahoo Finance XML stream: cannot find 'results'" Exit Function End If ' If this works, we will have the XML quote data node -- our target Set oChild = FindChildNodeName(oChild.ChildNodes, "quote") Set GetQuoteXmlFromWeb = oChild ' Either the node or NOTHING ' error handlers ExitHere: Exit Function HandleErr: MsgBox "GetQuoteXmlFromWeb Error " & Err.Number & ": " & Err.Description Resume ExitHere End Function |
|
Function FindChildNodeName(xmlChildren As MSXML2.IXMLDOMNodeList, childName As String) As MSXML2.IXMLDOMNode Dim oChild As MSXML2.IXMLDOMNode Dim childResult As MSXML2.IXMLDOMNode Set childResult = Nothing For i = 1 To xmlChildren.Length Set oChild = xmlChildren.Item(i - 1) ' 0-based index If oChild.nodeName = childName Then Set childResult = oChild Exit For End If Next Set FindChildNodeName = childResult End Function |
Finalmente, la función GetQuoteFromXml es una adición que bien puede ser opcional. Su utilidad es lanzar una nueva consulta que permite conocer los datos básicos de la acción, como el nombre, el último volumen transado, el mayor y menor valor de transacción del día, el último valor de transacción y la última hora de actualización. Si bien una buena parte de la información se encuentra en la serie de precios, esta función es útil cuando se tiene el símbolo y no se conoce el nombre exacto, o cuando se lanza la consulta y los mercados están aún abiertos por tanto no se conoce el precio de cierre de la acción. La siguiente es la función:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
|
Function GetQuoteFromXml(stockXml As MSXML2.IXMLDOMNode, Optional QuoteParameter As String = "LastTradePriceOnly", Optional statusText As String = "") As String Dim oChild As MSXML2.IXMLDOMNode Dim sText As String On Error GoTo HandleErr If statusText <> "" Then sText = statusText & " - " & QuoteParameter Else sText = "" End If For Each oChild In stockXml.ChildNodes If sText <> "" Then Application.StatusBar = sText & " (found " & oChild.nodeName & ")" End If If oChild.nodeName = QuoteParameter Then s = oChild.Text GetQuoteFromXml = s If sText <> "" Then Application.StatusBar = sText Exit Function End If Next oChild If sText <> "" Then Application.StatusBar = sText & " not found!" ' error handlers ExitHere: Exit Function HandleErr: MsgBox "GetQuoteFromXml Error " & Err.Number & ": " & Err.Description Resume ExitHere Resume End Function |
Lo demás es estético y a gusto del usuario, una vez la serie se carga en la hoja de cálculo se pueden crear gráficos, estadísticas y demás. Usted puede descargar una versión comprimida de esta macro con algunas adiciones en el siguiente link. Una vez funcional la macro usted tendrá un reporte como el presentado a continuación.
Comentarios finales:
Like this:
Like Loading...