Python 数据分析与可视化:金融量化基础与双均线策略
本文介绍金融基础知识、常用金融工具及分析方法。重点讲解如何使用 Tushare 获取股票数据,并基于 Python 实现双均线量化策略,包括金叉买入、死叉卖出的逻辑与回测收益计算。内容涵盖 K 线图解读、均线系统原理以及完整的量化交易代码实现。

本文介绍金融基础知识、常用金融工具及分析方法。重点讲解如何使用 Tushare 获取股票数据,并基于 Python 实现双均线量化策略,包括金叉买入、死叉卖出的逻辑与回测收益计算。内容涵盖 K 线图解读、均线系统原理以及完整的量化交易代码实现。

金融是对现有资源进行重新整合之后,实现价值和利润的等效流通。例如投资者将资金投资于有增值潜力的项目,若项目成功,资金随之增长。
在金融市场中可交易的金融资产,主要分为股票、期货、黄金、外汇、基金、债券等。投资本质为低价买入,高价卖出。
现货指现有的物品。例如发电厂预估煤炭价格会上涨,会大量囤积煤炭自用或转卖赚取差价。 期货指规定期限的货物,是以某种大众产品(如棉花、大豆、石油)及金融资产(如股票、债券)为标的的标准化可交易合约。标的物可以是商品也可以是金融工具。 期货建立在买卖双方对商品未来价值不同期望的基础上。一方看涨,一方看跌,才能达成合约。例如农户预期玉米价格下跌,提前卖给厂商;厂商预期价格上涨,签订收购合约。收割后若价格上涨,厂商赚取差价。
物以稀为贵,黄金是硬通货。早期美元与黄金挂钩,美国曾占全球存储量 70%。后因黄金存储有限,美元改为与石油挂钩,通过控制石油供应来调节美元发行量。
外汇是货币行政当局持有的在国际收支逆差时可使用的债权。汇率波动可用于赚取差额,但个人获利空间小,多由贸易公司或行政当局用于抵消经济波动影响。
投资基金通过公开发售基金份额募集资本,投资于证券。由基金管理人管理,托管人托管,以资产组合方式进行证券投资活动。私自募集资金违法,基金管理人需不断调整投资组合比例以适应市场变化。
股票是股份公司发给出资人的凭证,持有者即股东。投资股票赚取上涨差额。上市(IPO)是企业通过证券交易所公开增发股票筹募资金。若外部资本流入过多,可能稀释内部股份,影响决策。国内对大型公司上市有严格监管要求。
按分类可分为蓝筹股(股价稳定)、成长股(发展潜力大)、ST 股(财政报告有问题)。按上市地区分为 A 股(大陆人民币)、B 股(大陆外币)、H 股(香港)、N 股(纽约)、S 股(新加坡)。A 股受政府调控波动较小,其他市场波动较大。
股票市场构成包括上市公司、证监会、证券业协会、交易所及中介机构。上海证券交易所只有主板;深圳证券交易所有主板、中小板、创业板。
影响股票的因素包括公司自身因素、行业因素、市场因素、政治因素、经济因素及心理因素。
A 股买卖规则:
包括行业分析、公司分析(财务数据、业绩报告)、宏观经济面分析(财政政策、货币政策)。
类似于箱线图。红色代表涨,绿色代表跌(国外相反)。
红色箱线图中线顶端为当日最高点,底端为最低点,箱子最低处为开盘价,最高处为收盘价。K 线图分为日 K、周 K、月 K 等。
均线为算术移动平均线。MA5 是以 5 天为一个间隔计算平均值。常见周期中,MA5、MA10 为短期(日均线),MA30-MA60 为中期(季均线),MA120-MA240 为长期(年均线)。
MACD(指数平滑移动平均线)、KDJ(随机指标)、RSI、BOLL 等。
量化交易利用计算机技术从历史数据中选出带来超额收益的'大概率'事件来制定策略,效率远高于传统人工分析。
Tushare Pro 是一个 Python 财经数据接口包,实现对股票等金融数据的采集、清洗、存储。返回数据多为 pandas DataFrame 格式,便于分析和可视化。
pip install tushare
访问 https://tushare.pro/ 注册并获取接口 TOKEN。
建立接口链接,上海证券交易所后缀为.SH,深圳证券交易所后缀为.SZ。
import tushare as ts
import pandas as pd
# 设置 TOKEN,请替换为你自己的 token
ts.set_token('YOUR_TOKEN')
pro = ts.pro_api()
# 获取五粮液 (000858.SZ) 历史行情
df = pro.daily(ts_code='000858.SZ', start_date='20100101', end_date='20211231')
# 解析日期列
df['trade_date'] = pd.to_datetime(df['trade_date'])
df.set_index('trade_date', inplace=True)
# 保留关键列
df = df[['open', 'close', 'high', 'low']]
print(df.head())
只保留需要开盘、收盘、最高、最低值列。输出该股票收盘比开盘上涨 3% 以上的日期。
# 计算涨跌幅条件
up_days = df[df['close'] > df['open'] * 1.03]
print(up_days)
输出开盘比收盘跌幅 2% 以上的日期;输出开盘比昨日收盘跌幅 2% 以上的日期。
# 开盘比收盘跌幅 2%
down_close = df[df['open'] < df['close'] * 0.98]
# 开盘比昨日收盘跌幅 2%
df['prev_close'] = df['close'].shift(1)
down_prev = df[df['open'] < df['prev_close'] * 0.98]
从 2010 年 1 月 1 日开始,每月第一个交易日买入 1 手(100 股),每年最后一个交易日卖出所有股票。
# 重采样为每月一次
df_monthly = df.resample('M').last()
# 计算收益逻辑(简化版)
capital = 100000 # 初始资金
shares = 0
for date, row in df_monthly.iterrows():
if date.day == 1 or (date.month == 1 and date.day == 1):
buy_price = row['close']
if capital >= buy_price * 100:
count = int(capital / buy_price / 100) * 100
shares += count
capital -= count * buy_price
else:
sell_price = row['close']
if shares > 0:
capital += shares * sell_price
shares = 0
print(f'最终资金:{capital}')
对于每一个交易日,计算前 N 天的移动平均值连成一条线,即 N 日移动平均线。常用 MA5, MA10, MA30, MA60 等。
短期均线上穿长期均线,为买入信号。一般比较 MA5 和 MA30 的值。
短期均线下穿长期均线,为卖出信号。
实现步骤如下:
import matplotlib.pyplot as plt
import numpy as np
# 1. 获取数据 (同上)
# 2. 计算均线
df['ma5'] = df['close'].rolling(window=5).mean()
df['ma30'] = df['close'].rolling(window=30).mean()
# 3. 可视化
plt.figure(figsize=(14, 7))
plt.plot(df.index, df['close'], label='Close Price', alpha=0.6)
plt.plot(df.index, df['ma5'], label='MA5', color='orange')
plt.plot(df.index, df['ma30'], label='MA30', color='green')
plt.title('Stock Price & Moving Averages')
plt.legend()
plt.grid(True)
plt.show()
# 4. 寻找金叉和死叉
df['signal'] = 0
df.loc[df['ma5'] > df['ma30'], 'signal'] = 1
df.loc[df['ma5'] < df['ma30'], 'signal'] = -1
# 金叉:信号从 -1 变为 1
golden_cross = df[(df['signal'] == 1) & (df['signal'].shift(1) == -1)]
# 死叉:信号从 1 变为 -1
death_cross = df[(df['signal'] == -1) & (df['signal'].shift(1) == 1)]
print('Golden Cross Dates:', golden_cross.index.tolist())
print('Death Cross Dates:', death_cross.index.tolist())
# 5. 模拟交易
initial_capital = 100000
current_capital = initial_capital
position = 0 # 持仓数量
trades = []
for i in range(1, len(df)):
date = df.index[i]
price = df['close'][i]
# 金叉买入
if df['signal'].iloc[i] == 1 and df['signal'].iloc[i-1] == -1:
if current_capital > 0:
buy_shares = int(current_capital / price / 100) * 100
if buy_shares > 0:
cost = buy_shares * price
current_capital -= cost
position += buy_shares
trades.append((date, 'Buy', price, buy_shares))
# 死叉卖出
elif df['signal'].iloc[i] == -1 and df['signal'].iloc[i-1] == 1:
if position > 0:
sell_value = position * price
current_capital += sell_value
trades.append((date, 'Sell', price, position))
position = 0
final_capital = current_capital + (position * df['close'].iloc[-1])
return_rate = (final_capital - initial_capital) / initial_capital
print(f'Final Capital: {final_capital}')
print(f'Return Rate: {return_rate:.2%}')
通过上述代码,可以完整实现从数据获取、指标计算、可视化到策略回测的全过程。

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online