跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像AI 生图工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
PythonAI算法

基于 Ollama 与 Python 的股票技术指标分析及可视化

一种基于 Python 和 Ollama 的股票技术分析系统。系统利用 yfinance 获取市场数据,通过 pandas 计算滚动平均、EMA、RSI 及布林带等技术指标,并将这些指标输入本地运行的 Llama 3 模型,生成自然语言形式的市场趋势解读。最后,使用 Streamlit 构建可视化界面展示实时数据和 AI 分析结果。该方案实现了从数据采集、指标计算到智能分析的自动化流程,适用于量化监控场景。

内存管理发布于 2025/2/7更新于 2026/7/2743 浏览
基于 Ollama 与 Python 的股票技术指标分析及可视化

使用 Ollama 完成股票技术指标的评价

本文介绍了一个结合 Python 数据分析库、本地大模型(Ollama)以及 Streamlit 可视化的股票分析系统。该系统能够实时获取股票数据,计算关键技术指标,并利用 Llama 3 模型对市场行情进行自然语言解读。

核心功能点

  1. 数据获取:使用 yfinance 获取 Apple (AAPL) 和道琼斯指数 (DJI) 的历史行情。
  2. 技术指标计算:计算滚动平均值、动量、RSI、布林带等指标。
  3. AI 分析:通过 Ollama 调用 Llama 3 模型,根据计算出的指标生成市场趋势的自然语言洞察。
  4. 可视化界面:使用 Streamlit 构建交互式前端,展示实时数据和 AI 分析结果。

环境准备

在开始之前,请确保已安装以下 Python 包:

import yfinance as yf
import pandas as pd
import schedule
import time
import ollama
from datetime import datetime, timedelta

同时,确保本地已运行 Ollama 服务并拉取了 llama3 模型:

ollama pull llama3

数据获取与初始化

首先,获取昨日分钟级历史数据作为模拟源。这里以苹果股票和道琼斯指数为例。

stock = yf.Ticker("AAPL")
dow_jones = yf.Ticker("^DJI")
data = stock.history(period="1d", interval="1m")
dow_data = dow_jones.history(period="1d", interval="1m")
print(data.head())

全局变量定义

为了跟踪滚动窗口内的数据和每日市场状态,我们定义以下全局变量:

rolling_window = pd.DataFrame()
dow_rolling_window = pd.DataFrame()
# 用于跟踪每日市场情况
daily_high = float('-inf')
daily_low = float('inf')
buying_momentum = 0
selling_momentum = 0
  • rolling_window 和 dow_rolling_window:存储最近的数据点用于计算移动平均。
  • daily_high / daily_low:记录当日最高价和最低价,初始化为极端值以确保首次更新有效。
  • buying_momentum / selling_momentum:分别累计买入和卖出动量,用于判断市场情绪。
  • 辅助函数实现

    1. 计算市场开盘时长

    该函数用于计算当前时间距离市场开盘(09:30)经过了多少分钟。

    def get_market_open_duration(window):
        # 从窗口的最后一个元素提取当前时间
        current_time = window.index[-1].time()
        
        # 获取上一个交易日日期
        previous_trading_day = datetime.today() - timedelta(days=1)
        
        # 组合日期和时间
        current_datetime = datetime.combine(previous_trading_day, current_time)
        
        # 定义市场开盘时间为 09:30:00
        market_start_time = datetime.combine(
            previous_trading_day, 
            datetime.strptime("09:30:00", "%H:%M:%S").time()
        )
        
        # 计算开盘时长(分钟)
        market_open_duration = (current_datetime - market_start_time).total_seconds() / 60
        return market_open_duration
    

    2. 技术指标详解

    本系统主要关注以下技术指标:

    • 滚动平均值 (Rolling Average):反映短期价格趋势。
    • 指数移动平均线 (EMA):对近期价格赋予更高权重,比简单移动平均更敏感。
    • 相对强弱指数 (RSI):衡量价格变动的速度和变化,通常用于判断超买或超卖状态。
    • 布林带 (Bollinger Bands):由中轨(移动平均)、上轨和下轨组成,用于衡量波动性。

    3. 生成自然语言洞察

    这是系统的核心部分。我们将计算好的指标填入 Prompt,发送给 Ollama 中的 Llama 3 模型,获取专业的市场分析。

    def get_natural_language_insights(
        rolling_avg, ema, rsi, bollinger_upper, bollinger_lower,
        price_change, volume_change, dow_rolling_avg, market_open_duration, 
        dow_price_change, dow_volume_change, daily_high, daily_low, 
        buying_momentum, selling_momentum
    ):
        prompt = f"""
        You are a professional stock broker. Apple's stock has a 5-minute rolling average of {rolling_avg:.2f}.
        The Exponential Moving Average (EMA) is {ema:.2f}, and the Relative Strength Index (RSI) is {rsi:.2f}.
        The Bollinger Bands are set with an upper band of {bollinger_upper:.2f} and a lower band of {bollinger_lower:.2f}.
        The price has changed by {price_change:.2f}, and the volume has shifted by {volume_change}.
        The DOW price has changed by {dow_price_change:.2f}, and the volume has shifted by {dow_volume_change}.
        Meanwhile, the Dow Jones index has a 5-minute rolling average of {dow_rolling_avg:.2f}.
        The market has been open for {market_open_duration:.2f} minutes.
        Today's high was {daily_high:.2f} and low was {daily_low:.2f}.
        The buying momentum is {buying_momentum:.2f} and selling momentum is {selling_momentum:.2f}.
        Based on this data, provide insights into the current stock trend and the general market sentiment.
        The insights should not be longer than 100 words and should not have an introduction.
        """
        response = ollama.chat(
            model="llama3",
            messages=[{"role": "user", "content": prompt}]
        )
        response_text = response['message']['content'].strip()
        print("Natural Language Insight:", response_text)
        return response_text
    

    4. 计算指标逻辑

    此函数负责处理数据窗口,计算所有必要的技术指标。

    def calculate_insights(window, dow_window):
        if len(window) >= 5:
            # 计算收盘价 5 分钟滚动平均值
            rolling_avg = window['Close'].rolling(window=5).mean().iloc[-1]
            
            # 计算价格和成交量变化
            price_change = window['Close'].iloc[-1] - window['Close'].iloc[-2] if len(window) >= 2 else 0
            volume_change = window['Volume'].iloc[-1] - window['Volume'].iloc[-2] if len(window) >= 2 else 0
            
            # 计算道琼斯指数变化
            dow_price_change = dow_window['Close'].iloc[-1] - dow_window['Close'].iloc[-2] if len(dow_window) >= 2 else 0
            dow_volume_change = dow_window['Volume'].iloc[-1] - dow_window['Volume'].iloc[-2] if len(dow_window) >= 2 else 0
                
            # 计算 EMA 和布林带
            ema = window['Close'].ewm(span=5, adjust=False).mean().iloc[-1]
            std = window['Close'].rolling(window=5).std().iloc[-1]
            bollinger_upper = rolling_avg + (2 * std)
            bollinger_lower = rolling_avg - (2 * std)
            
            # 计算 RSI (标准周期为 14)
            delta = window['Close'].diff()
            gain = delta.where(delta > 0, 0)
            loss = -delta.where(delta < 0, 0)
            avg_gain = gain.rolling(window=14, min_periods=1).mean().iloc[-1]
            avg_loss = loss.rolling(window=14, min_periods=1).mean().iloc[-1]
            rs = avg_gain / avg_loss if avg_loss != 0 else float('nan')
            rsi = 100 - (100 / (1 + rs))
            
            # 计算道琼斯滚动平均
            dow_rolling_avg = dow_window['Close'].rolling(window=5).mean().iloc[-1]
                    
            market_open_duration = get_market_open_duration(window)
            
            # 打印计算结果
            print(f"5-minute Rolling Average: {rolling_avg:.2f}")
            print(f"EMA: {ema:.2f}")
            print(f"RSI: {rsi:.2f}")
            print(f"Bollinger Upper Band: {bollinger_upper:.2f}, Lower Band: {bollinger_lower:.2f}")
            print(f"Price Change: {price_change:.2f}")
            print(f"Volume Change: {volume_change}")
            print(f"DOW Price Change: {dow_price_change:.2f}")
            print(f"DOW Volume Change: {dow_volume_change}")
            print(f"Dow Jones 5-minute Rolling Average: {dow_rolling_avg:.2f}")
            print(f"Daily High: {daily_high:.2f}, Daily Low: {daily_low:.2f}")
            print(f"Buying Momentum: {buying_momentum:.2f}, Selling Momentum: {selling_momentum:.2f}")
            print(f"Market has been open for {market_open_duration:.2f} minutes")
                    
            # 每 5 分钟触发一次 LLM 分析
            if int(market_open_duration) % 5 == 0:
                insight = get_natural_language_insights(
                    rolling_avg, ema, rsi, bollinger_upper, bollinger_lower,
                    price_change, volume_change, dow_rolling_avg, market_open_duration, 
                    dow_price_change, dow_volume_change, daily_high, daily_low, 
                    buying_momentum, selling_momentum
                )
                return insight
        return None
    

    5. 处理股票更新

    模拟每分钟接收新的数据点,并更新滚动窗口和动量指标。

    def process_stock_update():
        global rolling_window, data, dow_rolling_window, dow_data
        global daily_high, daily_low, buying_momentum, selling_momentum
        
        if not data.empty and not dow_data.empty:
            # 模拟接收新数据点
            update = data.iloc[0].to_frame().T
            time_str = update.index[0].time()
            print(time_str)
            
            dow_update = dow_data.iloc[0].to_frame().T
            
            # 移除已处理的第一行
            data = data.iloc[1:]
            dow_data = dow_data.iloc[1:]
            
            # 追加到滚动窗口
            rolling_window = pd.concat([rolling_window, update], ignore_index=False)
            dow_rolling_window = pd.concat([dow_rolling_window, dow_update], ignore_index=False)
            
            # 更新每日高低点
            daily_high = max(daily_high, update['Close'].values[0])
            daily_low = min(daily_low, update['Close'].values[0])
            
            # 计算动量
            if len(rolling_window) >= 2:
                price_change = update['Close'].values[0] - rolling_window['Close'].iloc[-2]
                if price_change > 0:
                    buying_momentum += price_change
                else:
                    selling_momentum += abs(price_change)
                            
            # 限制滚动窗口大小为 5 分钟
            if len(rolling_window) > 5:
                rolling_window = rolling_window.iloc[1:]
            if len(dow_rolling_window) > 5:
                dow_rolling_window = dow_rolling_window.iloc[1:]
            
            # 计算洞察
            calculate_insights(rolling_window, dow_rolling_window)
    

    6. 调度任务

    使用 schedule 库模拟每分钟接收更新的场景。

    schedule.every(10).seconds.do(process_stock_update)
    
    print("Starting real-time simulation for AAPL stock updates...")
    while True:
        schedule.run_pending()
        time.sleep(1)
    

    Streamlit 可视化界面

    为了更直观地展示分析结果,我们可以使用 Streamlit 构建一个简单的 Web 界面。以下是完整的 UI 代码示例,包含日志显示和 AI 洞察展示区域。

    import streamlit as st
    
    st.title("AI Stock Advisor")
    
    # 创建空容器用于动态更新
    log_container = st.empty()
    insight_container = st.empty()
    
    # 初始化消息
    initial_msg = "Starting real-time simulation for AAPL stock updates. First update will be processed in 5 minutes..."
    with st.chat_message("assistant"):
        st.write(initial_msg)
    
    # 模拟回调函数更新 UI
    # 在实际应用中,建议将后台线程与 Streamlit 的 rerun 机制解耦
    # 此处演示如何更新日志和洞察内容
    
    def update_ui(last_insight=None):
        log_txt = f"Last Update Time: {datetime.now().strftime('%H:%M:%S')}"
        log_container.caption(log_txt)
        
        if last_insight:
            with st.chat_message("assistant"):
                st.markdown(last_insight)
        else:
            with st.chat_message("assistant"):
                st.write("Waiting for next analysis cycle...")
    
    # 注意:Streamlit 脚本每次交互都会重新运行,因此实际部署时
    # 需配合 threading 模块将定时任务放入后台线程,并通过 st.session_state 共享数据
    # 以下为简化版结构示意
    if __name__ == "__main__":
        # 启动后台调度线程的逻辑应在此处封装
        pass
    

    总结

    本教程展示了一个完整的技术栈整合方案:

    1. 数据层:利用 yfinance 获取金融数据。
    2. 计算层:使用 pandas 高效计算 RSI、EMA、布林带等技术指标。
    3. 智能层:通过 ollama 调用本地 Llama 3 模型,将结构化数据转化为自然语言的市场观点。
    4. 展示层:使用 Streamlit 快速搭建可视化面板。

    这种架构不仅适用于股票分析,也可扩展至加密货币、外汇等其他金融市场的量化监控场景。通过本地部署大模型,用户可以在保护数据隐私的前提下享受 AI 带来的分析便利。

    目录

    1. 使用 Ollama 完成股票技术指标的评价
    2. 核心功能点
    3. 环境准备
    4. 数据获取与初始化
    5. 全局变量定义
    6. 用于跟踪每日市场情况
    7. 辅助函数实现
    8. 1. 计算市场开盘时长
    9. 2. 技术指标详解
    10. 3. 生成自然语言洞察
    11. 4. 计算指标逻辑
    12. 5. 处理股票更新
    13. 6. 调度任务
    14. Streamlit 可视化界面
    15. 创建空容器用于动态更新
    16. 初始化消息
    17. 模拟回调函数更新 UI
    18. 在实际应用中,建议将后台线程与 Streamlit 的 rerun 机制解耦
    19. 此处演示如何更新日志和洞察内容
    20. 注意:Streamlit 脚本每次交互都会重新运行,因此实际部署时
    21. 需配合 threading 模块将定时任务放入后台线程,并通过 st.session_state 共享数据
    22. 以下为简化版结构示意
    23. 总结
    • 免费图片AI生成工具免费生成了解详情
    • Magick API 一键接入全球大模型注册送1000万token查看
    • 免费图片视频在线生成30秒,将你的创意变成现实开始设计
    • X/Twitter免费视频下载器免登陆无限额度免费视频解析下载了解详情
    • 100+免费在线小游戏爽一把
    极客日志微信公众号二维码

    微信扫一扫,关注极客日志

    微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

    更多推荐文章

    查看全部
    • 2026 AI视频生成器新手避坑指南:99%人都踩过的雷
    • 2026 年协作机器人十大品牌技术解析与选型指南
    • Awesome OpenClaw Skills:为本地 AI 助手构建超级技能市场
    • Vivado 安装教程:从官网下载至完成配置
    • Spring Security 自定义 UserDetailsService 实现用户认证
    • Open-R1:DeepSeek-R1 的完全开源复现项目解析
    • 7 天用 Electron 开发跨平台桌面应用实战指南
    • Linux 下安装 libwebkit2gtk-4.1-0 的方法与作用
    • OpenClaw、MaxClaw、KimiClaw 与 Molili 四大 AI Agent 横向评测
    • DeerFlow 2.0 实战:生产级 AI Agent 框架的 Docker 部署与并行编排
    • Ubuntu 22.04 部署 Claude Code CLI 及 VSCode 集成指南
    • Krita AI 绘画插件本地部署与配置教程
    • AIGC 工具助力 2D 游戏美术全流程
    • LeetCode 739 每日温度:从暴力枚举到单调栈线性最优解
    • AutoDL 服务器系统盘空间清理指南
    • IDEA 三大 AI 编程插件实测:Copilot、TRAE 与灵码深度对比
    • MedGemma-1.5-4B 实战:医学影像多模态理解与 Web 集成
    • OpenClaw:从程序员玩具到开源 AI 代理的演变
    • OpenClaw 对接 Stable Diffusion 实现免费 AI 绘画
    • 论文 AIGC 检测原理与降重工具实测指南

    相关免费在线工具

    • 加密/解密文本

      使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

    • RSA密钥对生成器

      生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online

    • Mermaid 预览与可视化编辑

      基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online

    • 随机西班牙地址生成器

      随机生成西班牙地址(支持马德里、加泰罗尼亚、安达卢西亚、瓦伦西亚筛选),支持数量快捷选择、显示全部与下载。 在线工具,随机西班牙地址生成器在线工具,online

    • Gemini 图片去水印

      基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

    • curl 转代码

      解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online