You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

从Morningstar下载股票价格数据时出现错误及代码求助

错误排查与解决办法

嘿,我来帮你搞定这个从Morningstar下载股票数据的问题!看了你的代码和描述,这里有几个核心问题和对应的解决思路:

一、最关键的错误原因:Morningstar数据源已失效

首先,pandas_datareader里的morningstar数据源早就不能用了——Morningstar在几年前就关闭了公开的API接口,所以你调用web.DataReader(stock, 'morningstar', ...)肯定会抛出连接错误或者数据不存在的异常,这是导致你失败的核心原因。

除此之外,你的代码还有几个小问题:

  • 最后一行temp=f['C...明显没写完,应该是要取收盘价(比如Close列),语法不完整会直接报错;
  • 嵌套循环每年只取单天数据,不仅效率低,还容易触发请求限制,而且如果5月1日是节假日(美股休市),也会因为没有数据报错;
  • CSV读取用dataa.extend(i)可能会把每行的所有列都塞进列表,如果你的CSV是每行一个股票代码,应该用append取第一列,不然会混入无关数据。

二、具体解决办法

1. 替换成可用的数据源

既然Morningstar凉了,推荐用Yahoo Finance作为替代,现在可以通过yfinance库来对接,步骤如下:
首先安装依赖:

pip install yfinance pandas-datareader

然后在代码里添加接口修复:

import yfinance as yf
yf.pdr_override()  # 让pandas_datareader能用Yahoo的数据源

之后把原来的'morningstar'改成'yahoo'就行:

f = web.DataReader(stock, 'yahoo', start, end)

如果需要更稳定的数据源,也可以试试Alpha Vantage(需要免费API密钥),不过有请求次数限制,适合小批量数据获取。

2. 修复代码逻辑与语法

  • 补全截断的代码:如果要取单天收盘价,应该写成temp = f['Close'].iloc[0](因为单天数据只有一行,用iloc[0]提取);
  • 优化循环逻辑:不用每年循环,直接指定时间范围,然后筛选每年5月1日的数据,这样更高效:
    # 直接设置总时间范围
    start = datetime(2010, 5, 1)
    end = datetime(2019, 5, 1)
    for stock in dataa[2:100]:
        try:
            df = web.DataReader(stock, 'yahoo', start, end)
            # 筛选所有5月1日的数据
            may_1_data = df[(df.index.month == 5) & (df.index.day == 1)]
            for date, price in may_1_data['Close'].items():
                Dates.append(date)
                Prices.append(price)
                Tick.append(stock)
        except Exception as e:
            print(f"获取{stock}数据失败: {e}")
    
  • 修复CSV读取:如果你的CSV是每行一个股票代码,前两行是表头/无关数据,改成这样更靠谱:
    with open('sp500const.csv', newline='') as File:
        reader = csv.reader(File)
        # 跳过前两行
        next(reader)
        next(reader)
        dataa = [row[0] for row in reader if row]  # 跳过空行,只取第一列的股票代码
    

3. 增加异常处理

一定要加try-except块,不然单个股票获取失败会导致整个程序崩溃,还能打印错误信息帮你排查问题。

三、完整可运行的示例代码

import math
import pandas_datareader.data as web
import matplotlib.pyplot as plt
from datetime import datetime
from matplotlib import style
import csv
import yfinance as yf

# 修复pandas_datareader与Yahoo Finance的对接
yf.pdr_override()
style.use('ggplot')

# 读取股票代码CSV
dataa = []
with open('sp500const.csv', newline='') as File:
    reader = csv.reader(File)
    # 跳过前两行(根据你的CSV结构调整)
    next(reader)
    next(reader)
    for row in reader:
        if row:  # 跳过空行
            dataa.append(row[0])

Dates = []
Prices = []
Tick = []

# 设置时间范围
start_date = datetime(2010, 5, 1)
end_date = datetime(2019, 5, 1)

for stock in dataa[:98]:  # 对应原代码的dataa[2:100]
    try:
        # 获取股票数据
        df = web.DataReader(stock, 'yahoo', start_date, end_date)
        # 筛选每年5月1日的数据
        target_dates = df[(df.index.month == 5) & (df.index.day == 1)]
        if not target_dates.empty:
            for idx, row in target_dates.iterrows():
                Dates.append(idx)
                Prices.append(row['Close'])
                Tick.append(stock)
        else:
            print(f"{stock}在2010-2019年的5月1日无交易数据")
    except Exception as e:
        print(f"处理{stock}时出错: {str(e)}")

# 输出结果统计
print(f"数据获取完成,共获取{len(Prices)}条有效记录")

内容的提问来源于stack exchange,提问作者AlexandrosB

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 03:31:35