股票基本特征计算绘图

import akshare as ak
from numba.core.event import end_event
import pandas as pd
import numpy as np
import time
import os

# 尝试获取数据,添加错误处理
max_retries = 3
retry_count = 0
stock_data = None

data_file = 'stock_data.csv'

# 检查是否已有数据文件
if os.path.exists(data_file):
    print(f"从本地文件 {data_file} 加载数据...")
    try:
        stock_data = pd.read_csv(data_file, encoding='utf-8')
        print("数据加载成功!")
    except Exception as e:
        print(f"加载本地数据失败: {e}")
        stock_data = None

# 如果没有本地数据,尝试从akshare获取
while retry_count < max_retries and stock_data is None:
    try:
        print(f"尝试第 {retry_count+1}/{max_retries} 次获取股票数据...")
        stock_data = ak.stock_zh_a_hist(
            symbol="000937",  # 股票代码
            start_date="20230101",  # 开始日期
            end_date="20250801",  # 结束日期
            adjust="qfq"  # 前复权
        )
        # 保存数据到本地,以便下次使用
        stock_data.to_csv(data_file, index=False, encoding='utf-8')
        print("数据获取并保存成功!")
    except Exception as e:
        print(f"获取数据失败: {e}")
        retry_count += 1
        if retry_count < max_retries:
            print(f"{5}秒后重试...")
            time.sleep(5)

if stock_data is None:
    print("多次尝试获取数据失败,请检查网络连接后再试。")
    exit(1)

# 移除缺失值
stock_data = stock_data.dropna()
print(stock_data.head())

# 暂时注释掉实时行情获取,避免额外的网络请求
# # 获取A股所有股票实时行情
# real_time_data = ak.stock_zh_a_spot_em()
# 
# # 筛选特定股票
# stock_code = "000937"
# filtered_data = real_time_data[real_time_data["代码"] == stock_code]
# print(filtered_data.head())
# 计算移动平均线(MA)
stock_data['MA5'] = stock_data['收盘'].rolling(window=5).mean()  # 5日均线
stock_data['MA10'] = stock_data['收盘'].rolling(window=10).mean()  # 10日均线
stock_data['MA20'] = stock_data['收盘'].rolling(window=20).mean()  # 20日均线

# 计算MACD指标
stock_data['EMA12'] = stock_data['收盘'].ewm(span=12, adjust=False).mean()
stock_data['EMA26'] = stock_data['收盘'].ewm(span=26, adjust=False).mean()
stock_data['DIF'] = stock_data['EMA12'] - stock_data['EMA26']
stock_data['DEA'] = stock_data['DIF'].ewm(span=9, adjust=False).mean()
stock_data['MACD'] = (stock_data['DIF'] - stock_data['DEA']) * 2

# 计算相对强弱指数(RSI)
delta = stock_data['收盘'].diff(1)
gain = (delta.where(delta > 0, 0)).rolling(window=14).mean()
loss = (-delta.where(delta < 0, 0)).rolling(window=14).mean()
stock_data['RSI'] = 100 - (100 / (1 + gain / loss))

# 计算布林带
stock_data['BB_MID'] = stock_data['收盘'].rolling(window=20).mean()
stock_data['BB_UP'] = stock_data['BB_MID'] + 2 * stock_data['收盘'].rolling(window=20).std()
stock_data['BB_LOW'] = stock_data['BB_MID'] - 2 * stock_data['收盘'].rolling(window=20).std()

#. 波动率特征
# 计算日收益率
stock_data['return'] = stock_data['收盘'].pct_change()

# 计算波动率(标准差)
stock_data['volatility_5d'] = stock_data['return'].rolling(window=5).std() * np.sqrt(5)
stock_data['volatility_20d'] = stock_data['return'].rolling(window=20).std() * np.sqrt(20)
## . 量价关系特征
# 计算量比
stock_data['volume_ratio'] = stock_data['成交量'] / stock_data['成交量'].rolling(window=5).mean()
# 计算成交额
stock_data['amount'] = stock_data['收盘'] * stock_data['成交量']
# 计算资金流向(简易版)
stock_data['money_flow'] = (stock_data['收盘'] - stock_data['开盘']) * stock_data['成交量']
# 基本面特征
# 4. 可视化特征指标
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
from matplotlib.ticker import MaxNLocator

# 设置中文显示
plt.rcParams["font.family"] = ["SimHei", "WenQuanYi Micro Hei", "Heiti TC"]
plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题

# 创建画布和子图
fig, axes = plt.subplots(4, 1, figsize=(12, 16), sharex=True)

# 1. 绘制价格和移动平均线
ax1 = axes[0]
ax1.plot(stock_data['日期'], stock_data['收盘'], label='收盘价', color='blue')
ax1.plot(stock_data['日期'], stock_data['MA5'], label='MA5', color='red')
ax1.plot(stock_data['日期'], stock_data['MA10'], label='MA10', color='green')
ax1.plot(stock_data['日期'], stock_data['MA20'], label='MA20', color='orange')
ax1.set_title('股票价格与移动平均线')
ax1.set_ylabel('价格')
ax1.legend()
ax1.grid(True)

# 2. 绘制MACD
ax2 = axes[1]
ax2.plot(stock_data['日期'], stock_data['DIF'], label='DIF', color='blue')
ax2.plot(stock_data['日期'], stock_data['DEA'], label='DEA', color='red')
ax2.bar(stock_data['日期'], stock_data['MACD'], label='MACD', color='green', alpha=0.5)
ax2.set_title('MACD指标')
ax2.set_ylabel('值')
ax2.legend()
ax2.grid(True)

# 3. 绘制RSI
ax3 = axes[2]
ax3.plot(stock_data['日期'], stock_data['RSI'], label='RSI', color='purple')
ax3.axhline(y=70, color='red', linestyle='--', label='超买线(70)')
ax3.axhline(y=30, color='green', linestyle='--', label='超卖线(30)')
ax3.set_title('相对强弱指数(RSI)')
ax3.set_ylabel('RSI值')
ax3.set_ylim(0, 100)
ax3.legend()
ax3.grid(True)

# 4. 绘制布林带
ax4 = axes[3]
ax4.plot(stock_data['日期'], stock_data['收盘'], label='收盘价', color='blue')
ax4.plot(stock_data['日期'], stock_data['BB_MID'], label='中轨', color='black')
ax4.plot(stock_data['日期'], stock_data['BB_UP'], label='上轨', color='red', linestyle='--')
ax4.plot(stock_data['日期'], stock_data['BB_LOW'], label='下轨', color='green', linestyle='--')
ax4.fill_between(stock_data['日期'], stock_data['BB_UP'], stock_data['BB_LOW'], color='gray', alpha=0.1)
ax4.set_title('布林带指标')
ax4.set_xlabel('日期')
ax4.set_ylabel('价格')
ax4.legend()
ax4.grid(True)

# 设置x轴日期格式
for ax in axes:
    ax.xaxis.set_major_locator(MaxNLocator(prune='both', nbins=10))
    ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))
    plt.setp(ax.get_xticklabels(), rotation=45)

plt.tight_layout()
plt.savefig('stock_indicators.png', dpi=300, bbox_inches='tight')
print("指标图形已保存为 stock_indicators.png")
plt.show()

# 5. 保存特征数据
# 使用UTF-8编码保存CSV文件
stock_data.to_csv('stock_features.csv', index=False, encoding='utf-8')
print(f"特征数据已保存,共{len(stock_data)}行")
print(stock_data[['日期', '收盘', 'MA5', 'MA20', 'MACD', 'RSI', 'volatility_5d']].head())

# """
# 用户输入不完整,无法确定具体需求。但从工作区存在stock_basic_features.py等股票相关文件推测,可能与股票指标学习有关。我需要先查看stock_basic_features.py文件内容,了解其中涉及的指标,以便提供对应学习资料。

# stock_basic_features.py 2 - 200

# 以下是对stock_basic_features.py文件中涉及的股票技术指标的学习资料整理:

# ### 移动平均线(MA)
# - 概念 :移动平均线是将一定时期内的股票价格加以平均,连成一条线,用以观察股价变动趋势的技术指标。
# - 文件中的实现 :代码计算了MA5(5日均线)、MA10(10日均线)和MA20(20日均线)。
# - 学习建议 :理解不同周期均线的意义,如短期均线(5日、10日)反映短期趋势,中长期均线(20日、60日)反映中长期趋势。学习均线金叉、死叉、多头排列、空头排列等形态。
# ### MACD指标
# - 概念 :MACD(Moving Average Convergence Divergence)由快均线(EMA12)、慢均线(EMA26)的差值(DIF)和信号线(DEA)组成,用于判断股票价格的趋势和强度。
# - 文件中的实现 :计算了EMA12、EMA26、DIF、DEA和MACD值((DIF-DEA)*2)。
# - 学习建议 :掌握MACD的零轴穿越、金叉死叉、背离等形态的判断和应用。
# ### 相对强弱指数(RSI)
# - 概念 :RSI(Relative Strength Index)是衡量股票价格上涨和下跌力度的指标,取值范围0-100,通常70以上被认为超买,30以下被认为超卖。
# - 文件中的实现 :使用14日周期计算RSI。
# - 学习建议 :了解RSI的计算原理,学习超买超卖区域的判断,以及RSI背离现象的应用。
# ### 布林带(BOLL)
# - 概念 :布林带由中轨(BB_MID)、上轨(BB_UP)和下轨(BB_LOW)组成,用于衡量股价的波动性和趋势。
# - 文件中的实现 :中轨为20日均线,上轨和下轨分别为中轨加减2倍标准差。
# - 学习建议 :掌握布林带的开口、收缩形态,以及股价触碰上下轨的含义。
# ### 波动率
# - 概念 :波动率衡量股票价格的波动程度,通常用收益率的标准差表示。
# - 文件中的实现 :计算了5日和20日波动率(volatility_5d, volatility_20d)。
# - 学习建议 :了解波动率在风险评估和交易策略中的应用,如高波动率通常意味着高风险高收益。
# ### 量价关系特征
# - 概念 :量价关系研究成交量和价格之间的关系,帮助判断市场趋势的强度。
# - 文件中的实现 :计算了量比(volume_ratio)、成交额(amount)和简易资金流向(money_flow)。
# - 学习建议 :学习量价配合(如价升量增)和量价背离(如价升量减)的形态及其市场含义。
# ### 学习资源推荐
# 1. 1.
#    书籍:《期货市场技术分析》(约翰·墨菲)、《日本蜡烛图技术》(史蒂夫·尼森)
# 2. 2.
#    在线课程:可以通过平台如Coursera、Udemy查找技术分析相关课程
# 3. 3.
#    实践:结合实际股票数据(如文件中生成的stock_features.csv)进行分析和验证
# 通过以上指标的学习,可以帮助理解股票价格的短期波动和长期趋势,为投资决策提供参考。
# """