使用python 3.5从yahoo finance下载股票价格历史

时间:2016-09-01 00:18:32

标签: python

我目前正在寻找一种方法来加载雅虎财经的多年股价历史。我将有100多个自动收报机符号,我将从1985年下载数据到当前日期。我想将Open,High,Low,Close,Adj Close,Volume加载到单个DataFrames(pandas)中,并将数据框的名称命名为当前股票代码。

我的问题是我的变量自动收报机不起作用,即使它确实有效,我怎样才能存储这些数据?

import csv
import pandas as pd
import pandas_datareader.data as web
import datetime


#This represents the start and end date for the data
start = datetime.datetime(1985, 1, 1)
end = datetime.datetime(2016, 1, 27)

ticker = ['aapl','tvix','ugaz']

i= 0

while i < len(ticker):

f = web.DataReader(ticker, 'yahoo', start, end)
print(f)
i+=1

我希望能够永久存储所有这些数据,例如,如果我今天为100个股票代码加载30年的价格历史,那么明天我只需追加一天的数据而不是全部30年。数据帧似乎是组织数据的最有效方式,但我不太确定,但我想做机器学习和数据分析。

1 个答案:

答案 0 :(得分:6)

如果雅虎上有数据,您可以使用pandas_datareader模块下载所需的数据。您可以pip install或以您喜欢的任何其他方式安装它。

以下是获取一小部分符号数据的示例脚本:

from pandas_datareader import data as dreader

symbols = ['GOOG', 'AAPL', 'MMM', 'ACN', 'A', 'ADP']

pnls = {i:dreader.DataReader(i,'yahoo','1985-01-01','2016-09-01') for i in symbols}

这将数据保存在python词典中,允许您使用.get方法访问数据。

例如,如果您想获取GOOG的数据,可以执行以下操作:

print(pnls.get('GOOG').head())

这将得到以下结果:

                  Open        High         Low       Close    Volume  \
Date                                                                   
2004-08-19  100.000168  104.060182   95.960165  100.340176  44871300   
2004-08-20  101.010175  109.080187  100.500174  108.310183  22942800   
2004-08-23  110.750191  113.480193  109.050183  109.400185  18342800   
2004-08-24  111.240189  111.600192  103.570177  104.870176  15319700   
2004-08-25  104.960181  108.000187  103.880180  106.000184   9232100   

            Adj Close  
Date                   
2004-08-19  50.119968  
2004-08-20  54.100990  
2004-08-23  54.645447  
2004-08-24  52.382705  
2004-08-25  52.947145

请记住,如果给定的代码报告器没有时间间隔的数据,则返回的数据将省略这些年份或天数(显然)。

编辑:

您的脚本(以及许多其他内容)的主要问题是您多次(len(ticker)次)进行相同的调用,并且一次又一次地返回相同的输出。这是因为DataReader()函数在提供list时将会出现并获取list中每个元素的data.frame。所以,当你写:

i = 0
while i < len(ticker):
    f = web.DataReader(ticker, 'yahoo', start, end)
    print(f)
    i+=1

您基本上是这样说的:对于i = 0,我希望您继续进行web.DataReader(ticker, 'yahoo', start, end)调用并获取相同的数据,然后将其打印直到(通过递增)i的值达到我的代码清单的长度。你可以用f = web.DataReader(ticker, 'yahoo', start, end)得到同样的东西。但即便如此,你也不会知道哪个data.frame是哪个自动收报机。

另外,我发现另一件令人震惊的事情是,当你处理100多个代码时,你想要命名每个返回的数据框。为什么在 上帝的绿色地球 你想要在命名空间中拥有100多个名字?您可以非常轻松地将所有这些名称集中到一个dictionary(就像我上面推荐的那样),并随时使用.get()并提供代码来访问任何data.frame。

回顾:1)不需要while-loop。 2)如果您只是向DataReader()函数提供整个代码列表,则无法知道哪个data.frame适用于哪个代码。 3)您不希望命名100+ data.frames。

建议:通过使用字典(代码是keys并且返回的数据将是values)和列表理解来循环遍历代码并获取其数据来简化整个事情。我怀疑,这可以使你的脚本更容易阅读和缩短。

编辑2:

这是尝试提供一个解决方案,希望运行一次作业,然后每天使用最新的价格增加数据。这不是唯一的方法,但我认为这是一个好方法。首先,您需要制作一个脚本,从1985年到昨天获取所有代码的数据。此脚本需要在市场营业时间(或深夜)之后运行以捕获最新价格。这可能与我上面的脚本非常相似。您需要添加的唯一内容是将几行代码保存在当前工作目录中的计算机上。以下应该做:

from pandas_datareader import data as dreader
symbols = ['GOOG', 'AAPL', 'MMM', 'ACN', 'A', 'ADP']

pnls = {i:dreader.DataReader(i,'yahoo','1985-01-01','2016-09-01') for i in symbols}

for df_name in pnls:
    pnls.get(df_name).to_csv("{}_data.csv".format(df_name), index=True, header=True)

然后,你可以编写另一个脚本,它只是抓取今天相同代码的数据。它也需要在夜间(午夜之前)运行,以便它可以从今天捕获数据。

from datetime import datetime
from pandas_datareader import data as dreader
from pandas_datareader._utils import RemoteDataError

symbols = ['GOOG', 'AAPL', 'MMM', 'ACN', 'A', 'ADP']

try:
    pnls = {i:dreader.DataReader(i,'yahoo',datetime.today(),datetime.today()) for i in symbols}
except RemoteDataError:
    pnls = None

if pnls is not None:
    for df_name in pnls:
        with open("{}_data.csv".format(df_name),"a") as outfile:
            pnls.get(df_name).to_csv(outfile,header=False)
else:
    print("No data available yet. Please run later.")

第二个脚本应该使用第一个脚本将最新价格附加到先前保存的每个数据文件中。

请注意,我正在假设雅虎(或任何其他数据源)只要市场在任何地方关闭,即可获得当天的价格。

我希望这会有所帮助。