AI股票投资顾问

APPLICATION Oct 29, 2024

在为金融科技项目进行股票数据可视化时,我曾想过:如果数据可以用简单的英语解释自己会怎么样?这就是这个支线任务的开始。使用 LLM 支持的(Llama 3)洞察,此脚本每分钟获取股票数据,分析趋势并提供直截了当的解释。不再需要眯着眼睛看图表 - 这就像有一位私人股票专家实时分析正在发生的事情。

1、开发环境设置

在我们开始编写代码之前,需要安装一些使此项目成为可能的关键库。我们将使用 Streamlit 作为 UI,使用 yfinance 获取股票数据,并使用 Ollama 生成自然语言洞察:

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

2、获取股票数据进行分析

接下来,我们获取苹果 (AAPL) 和道琼斯指数 (DJI) 的历史股票数据。我们将使用 yfinance 以 1 分钟为间隔获取前一天股票数据:

# Fetching historical data for Apple (AAPL) and Dow Jones (DJI)
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")

在此阶段,我们拥有股票数据,我们将使用它进行进一步分析。为了演示目的,我使用了上一交易日的数据。你可以轻松调整它以直接从 API 中提取实时股票数据来处理实时市场更新。

3、处理实时股票更新

现在,让我们通过每分钟处理一个股票数据点来模拟实时更新。我们将计算滚动平均值和动量等指标以了解市场趋势:

# Global variables to store rolling data
rolling_window = pd.DataFrame()
dow_rolling_window = pd.DataFrame()
daily_high = float('-inf')
daily_low = float('inf')
buying_momentum = 0
selling_momentum = 0

# Function to process a new stock update every minute
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:
        # Simulate receiving a new data point for AAPL and Dow Jones
        update = data.iloc[0].to_frame().T
        dow_update = dow_data.iloc[0].to_frame().T
        data = data.iloc[1:]  # Remove the processed row
        dow_data = dow_data.iloc[1:]

        # Append the new data points to the rolling windows
        rolling_window = pd.concat([rolling_window, update], ignore_index=False)
        dow_rolling_window = pd.concat([dow_rolling_window, dow_update], ignore_index=False)

        # Update daily high and low
        daily_high = max(daily_high, update['Close'].values[0])
        daily_low = min(daily_low, update['Close'].values[0])

        # Calculate momentum
        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 分钟的分析。每日最高/最低值和价格动量会根据连续数据点之间的变化进行更新。

4、分析股票趋势

为了理解实时数据,我们计算移动平均线、价格变化、成交量变化以及指数移动平均线 (EMA)、布林线和 RSI(相对强弱指数)等技术指标。这些指标的工作原理如下:

def calculate_insights(window, dow_window):
    if len(window) >= 5:
        # 5-minute rolling average
        rolling_avg = window['Close'].rolling(window=5).mean().iloc[-1]
        
        # Exponential Moving Average (EMA)
        ema = window['Close'].ewm(span=5, adjust=False).mean().iloc[-1]
        
        # Bollinger Bands (using a 5-period window)
        std = window['Close'].rolling(window=5).std().iloc[-1]
        bollinger_upper = rolling_avg + (2 * std)
        bollinger_lower = rolling_avg - (2 * std)

        # RSI calculation
        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))

        # Calculate Relative Strength Index (RSI) if there are enough periods (14 is typical)
        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))

        # Calculate Dow Jones index rolling average
        dow_rolling_avg = dow_window['Close'].rolling(window=5).mean().iloc[-1]
        
        market_open_duration = get_market_open_duration(window)
        if int(market_open_duration) % 5 == 0:  # Trigger LLM every 5 minutes
            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
            )

5、使用 Ollama 获取自然语言洞察

为了使这个项目更具互动性,我们可以集成 Llama 3 模型,每 5 分钟生成一次自然语言洞察:

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, timestamp
):
    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)

这个函数使用前 5 分钟的技术指标和趋势以通俗易懂的语言总结股票表现。

6、用Streamlit搭建UI

现在让我们使用 Streamlit 设置一个基本 UI,以实时显示股票更新和见解。

message = st.chat_message("assistant")
message.write(timestamp)
message.write(response_text)
streamlit run app.py

这就是你可以构建自己的实时股票顾问的方法!

8、改进和未来增强

该项目是一个原型,专注于上一交易日的趋势。可以通过整合历史数据、新闻整合或时间序列神经网络等高级模型来增强它。以下是一些改进的想法:

  • 历史数据整合:目前,该应用程序仅处理前一个交易日的数据。你可以通过整合数周或数月的历史数据滚动窗口来增强它。
  • 新闻整合:股票趋势通常受新闻事件的影响。添加实时新闻提要可以提供更好的背景信息。
  • 高级时间序列预测:你可以通过整合时间序列神经网络来进一步提高洞察力,从而获得更准确的趋势预测。
  • 自定义警报:根据重大股票变动或 RSI 等指标实施可自定义的警报可以使该应用程序对日内交易者更实用。

完整的源代码和 Jupyter Notebook 可在 GitHub 存储库中找到。


原文链接:Real-Time AI Stock Advisor with Ollama (Llama 3) & Streamlit

汇智网翻译整理,转载请标明出处

Tags