如何利用Python轻松下载股票历史数据并做技术指标分析

企业微信

为什么用Python搞股票数据

散户想验证一个交易想法,手动翻K线图太慢。用Python写几行代码,几秒钟就能拉出十年的日线数据,还能自动算好均线、RSI、MACD。免费、灵活、可复现,这是量化交易的入门基本功。

准备工作:安装三个库

打开命令行,敲下这行命令:


pip install yfinance pandas ta

yfinance负责从雅虎财经拉数据,pandas负责表格处理,ta负责技术指标计算。三个库都是纯免费,不需要注册任何账号。

如何利用Python轻松下载股票历史数据并做技术指标分析

下载股票历史数据


import yfinance as yf

# 下载苹果公司2020年1月1日到2023年12月31日的日线数据

df = yf.download('AAPL', start='2020-01-01', end='2023-12-31')

print(df.head())

运行后你会看到一张表格,包含开盘价、最高价、最低价、收盘价、成交量和调整后收盘价。yfinance自动处理了拆股和分红,数据可以直接用于回测。

A股数据怎么办?yfinance也支持,代码改成yf.download('600519.SS', start='2020-01-01', end='2023-12-31'),600519.SS代表上海证券交易所的贵州茅台。深圳股票用.SZ后缀。

想批量下载多只股票?传入列表即可:


tickers = ['AAPL', 'MSFT', 'GOOG']

df_multi = yf.download(tickers, start='2020-01-01', end='2023-12-31')

返回的是多层列索引,用df_multi['Close']['AAPL']就能取到苹果的收盘价序列。

计算常用技术指标

拿到数据后,用ta库算指标,几行代码搞定。

移动平均线


import pandas as pd

from ta.trend import SMAIndicator

# 计算20日和60日简单移动平均

df['SMA_20'] = SMAIndicator(df['Close'], window=20).sma_indicator()

df['SMA_60'] = SMAIndicator(df['Close'], window=60).sma_indicator()

SMA_20上穿SMA_60,俗称金叉,传统技术分析视为买入信号。反过来叫死叉。

相对强弱指数RSI


from ta.momentum import RSIIndicator

df['RSI'] = RSIIndicator(df['Close'], window=14).rsi()

RSI高于70通常认为超买,低于30认为超卖。震荡市里这个指标很管用,单边趋势里容易钝化,别死守一个阈值。

MACD


from ta.trend import MACD

macd = MACD(df['Close'])

df['MACD'] = macd.macd()

df['MACD_signal'] = macd.macd_signal()

df['MACD_diff'] = macd.macd_diff()

MACD_diff是柱状图,由负转正代表短期动能增强。很多量化策略用MACD_diff上穿零轴作为开仓条件。

数据清洗与缺失值处理

yfinance返回的数据偶尔有缺失,比如停牌日没有成交量。用pandas直接处理:


df = df.dropna()  # 删掉空值行

df = df[df['Volume'] > 0]  # 过滤掉零成交量的异常日

如果要做日内回测,需要分钟级数据。yfinance支持interval='1m',但只能取最近7天的数据。历史分钟数据要花钱买,免费方案里yfinance算够用的。

简单回测:双均线策略

把信号写出来,统计一下历史表现。


df['Signal'] = 0

df.loc[df['SMA_20'] > df['SMA_60'], 'Signal'] = 1

df.loc[df['SMA_20'] <= df['SMA_60'], 'Signal'] = 0

df['Position'] = df['Signal'].shift(1)  # 避免未来函数

df['Returns'] = df['Close'].pct_change()

df['Strategy_Returns'] = df['Position'] * df['Returns']

cumulative_strategy = (1 + df['Strategy_Returns']).cumprod()

cumulative_market = (1 + df['Returns']).cumprod()

print(f"策略累计收益: {cumulative_strategy.iloc[-1]:.2f}")

print(f"买入持有收益: {cumulative_market.iloc[-1]:.2f}")

这段代码把每天的信号滞后一天执行,防止用到未来数据。cumprod()计算复利累计收益。跑完你会发现,双均线在趋势行情里能跑赢大盘,震荡市里反复打脸。

期货数据也能这么玩

期货主力连续合约在yfinance里代码不同,比如原油是CL=F,黄金是GC=F,标普500期货是ES=F。下载方式和股票一模一样。


cl = yf.download('CL=F', start='2020-01-01', end='2023-12-31')

期货数据没有调整后收盘价,直接用收盘价算指标就行。注意期货有换月跳空,yfinance返回的连续合约已经做了前复权处理,回测时不用额外调整。

可视化检查

画个图,肉眼确认指标和价格的关系。


import matplotlib.pyplot as plt

fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(12, 8))

ax1.plot(df.index, df['Close'], label='Close')

ax1.plot(df.index, df['SMA_20'], label='SMA 20')

ax1.plot(df.index, df['SMA_60'], label='SMA 60')

ax1.legend()

ax1.set_title('Price and Moving Averages')

ax2.plot(df.index, df['RSI'])

ax2.axhline(70, color='r', linestyle='--')

ax2.axhline(30, color='g', linestyle='--')

ax2.set_title('RSI')

plt.tight_layout()

plt.show()

图表能帮你快速发现指标在哪些阶段失效。比如2022年苹果的RSI长期在30到50之间徘徊,超卖信号根本不准。

保存数据到本地

每次跑都联网下载太慢,存成CSV文件。


df.to_csv('AAPL_with_indicators.csv')

# 下次直接读取

df = pd.read_csv('AAPL_with_indicators.csv', index_col='Date', parse_dates=True)

index_col和parse_dates保证日期列被正确解析为时间索引,方便后续按时间切片。

避坑指南

yfinance偶尔会抽风,返回空数据。加个重试逻辑:


import time

def download_with_retry(ticker, start, end, retries=3):

    for i in range(retries):

        try:

            data = yf.download(ticker, start=start, end=end)

            if not data.empty:

                return data

        except Exception as e:

            print(f"第{i+1}次失败: {e}")

            time.sleep(2)

    raise ValueError(f"无法下载{ticker}的数据")

免费数据源有延迟,日线数据当天收盘后几小时才更新。做实时交易得用券商API,那是另一个话题了。

下一步可以做什么

把上面的代码拼起来,你已经有了一个能跑通的数据管道。接下来可以加更多指标,比如布林带、ATR,或者把策略改成多因子打分。回测框架推荐backtrader或vectorbt,比手动算收益规范得多。期货数据注意合约乘数和保证金,股票回测不涉及这些,但期货杠杆会放大盈亏,代码里要算清楚。

整套流程下来,从拉数据到出策略信号,半小时足够。动手敲一遍,比看十篇文章管用。

转载请注明出处:https://www.lianghuajiaoyi.top/wenzhang/Python-gupiao-lishishuju-781.html