AI Stock 助手应用程序
本文将介绍一个使用 Streamlit 构建的 AI 股票助手应用程序。该应用程序能够实时更新股票数据,并提供市场分析和见解。以下是代码的详细说明和注释。
代码结构
1. 导入必要的库
import streamlit as st
import pandas as pd
import schedule
import time
import ollama
from datetime import datetime, timedelta
- streamlit: 用于构建Web应用程序的库。
- pandas: 用于数据处理和分析的库。
- schedule: 用于定时任务调度的库。
- time: 提供时间相关的功能。
- ollama: 用于生成自然语言响应的模型。
- datetime: 用于处理日期和时间的模块。
2. 设置Streamlit用户界面
# Streamlit UI
st.title("AI Stock 助手")
logtxtbox = st.empty()
- 使用
st.title()
设置应用程序的标题。 logtxtbox
是一个空的占位符,用于后续显示当前时间。
3. 读取和处理股票数据
# 读取 stock.cxv 文件
file_path = './stock.csv' # 请替换为您的文件路径
data = pd.read_csv(file_path)# 将数据转换为适合处理的格式
data['Date'] = pd.to_datetime(data['Date']) # 确保日期列为 datetime 类型
data.set_index('Date', inplace=True) # 将日期设置为索引
- 从 CSV 文件中读取股票数据,并将日期列转换为
datetime
类型。 - 将日期设置为数据框的索引,以便后续分析。
4. 读取道琼斯数据
# 读取 Dow 数据文件
dow_file_path = './stock.csv' # 请替换为您的 Dow 数据文件路径
dow_data = pd.read_csv(dow_file_path)# 将 Dow 数据转换为适合处理的格式
dow_data['Date'] = pd.to_datetime(dow_data['Date']) # 确保日期列为 datetime 类型
dow_data.set_index('Date', inplace=True) # 将日期设置为索引
- 同样读取道琼斯指数的数据,并进行相同的格式转换。
5. 初始化变量
# 使用读取的数据替换 yf.Ticker
rolling_window = data[['Close']].copy() # 复制收盘价数据# 计算每日的高低价
daily_high = rolling_window['Close'].max()
daily_low = rolling_window['Close'].min()# Global variables to store rolling data for analysis
rolling_window = pd.DataFrame()
dow_rolling_window = pd.DataFrame()# Variables to track daily context
daily_high = float('-inf')
daily_low = float('inf')
buying_momentum = 0
selling_momentum = 0
- 初始化用于存储滚动数据的变量,并计算每日的最高价和最低价。
6. 定义处理股票更新的函数
# Function to process a new stock update every minute
def process_stock_update():global rolling_window, data, dow_rolling_window, dow_dataglobal daily_high, daily_low, buying_momentum, selling_momentumif not data.empty and not dow_data.empty:# Simulate receiving a new data point for AAPL and Dow Jonesupdate = data.iloc[0].to_frame().T# 获取当前时间并格式化current_time = datetime.now().strftime("%H:%M:%S")logtxtbox.caption(current_time) # 更新显示的时间dow_update = dow_data.iloc[0].to_frame().Tdata = data.iloc[1:] # Safely remove the first row without causing index issuesdow_data = dow_data.iloc[1:]# Append the new data points to the rolling windowsrolling_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 lowdaily_high = max(daily_high, update['Close'].values[0])daily_low = min(daily_low, update['Close'].values[0])# Calculate momentum based on price changesif len(rolling_window) >= 2:price_change = update['Close'].values[0] - rolling_window['Close'].iloc[-2]if price_change > 0:buying_momentum += price_changeelse:selling_momentum += abs(price_change)# Limit the rolling window to 5 minutes for moving averageif 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 (moving averages, Bollinger Bands, RSI, etc.)calculate_insights(rolling_window, dow_rolling_window)
process_stock_update
函数每分钟处理一次股票更新,更新当前时间并计算新的高低价和动能。
7. 计算市场开放时间
def get_market_open_duration(window):# Extract current time from the last element of the windowcurrent_time = window.index[-1].time() # Returns a datetime.time object# Get the previous trading day's dateprevious_trading_day = datetime.today() - timedelta(days=1)# Combine the previous trading day with the current timecurrent_datetime = datetime.combine(previous_trading_day, current_time)# Define the market opening time as 09:30:00 on the previous trading daymarket_start_time = datetime.combine(previous_trading_day, datetime.strptime("09:30:00", "%H:%M:%S").time())# Calculate the duration the market has been open in minutesmarket_open_duration = (current_datetime - market_start_time).total_seconds() / 60 # in minutesreturn market_open_duration
- 该函数计算市场自开盘以来的持续时间。
8. 计算市场见解
# Function to calculate insights like moving averages and trends
def calculate_insights(window, dow_window):if len(window) >= 5:# Calculate 5-minute rolling average of the 'Close' pricesrolling_avg = window['Close'].rolling(window=5).mean().iloc[-1]# Calculate price change and volume changeprice_change = window['Close'].iloc[-1] - window['Close'].iloc[-2] if len(window) >= 2 else 0volume_change = window['Volume'].iloc[-1] - window['Volume'].iloc[-2] if len(window) >= 2 else 0# Calculate DOW price change and volume changedow_price_change = dow_window['Close'].iloc[-1] - dow_window['Close'].iloc[-2] if len(dow_window) >= 2 else 0dow_volume_change = dow_window['Volume'].iloc[-1] - dow_window['Volume'].iloc[-2] if len(dow_window) >= 2 else 0# Calculate Exponential Moving Average (EMA) and Bollinger Bands (with a 5-period window)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)# 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 averagedow_rolling_avg = dow_window['Close'].rolling(window=5).mean().iloc[-1]market_open_duration = get_market_open_duration(window)# Print the calculated insightsprint(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")if int(market_open_duration) % 5 == 0: # Trigger LLM every 5 minutesget_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, window.index[-1].time().strftime("%H:%M:%S"))
- 该函数计算各种市场指标,如移动平均线、布林带和相对强弱指数(RSI),并打印结果。
9. 生成自然语言见解
# Function to generate natural language insights using Ollama
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"""您是一位专业的股票经纪人。苹果公司的股票5分钟滚动平均为 {rolling_avg:.2f}。指数移动平均(EMA)为 {ema:.2f},相对强弱指数(RSI)为 {rsi:.2f}。布林带的上轨为 {bollinger_upper:.2f},下轨为 {bollinger_lower:.2f}。价格变化为 {price_change:.2f},成交量变化为 {volume_change}。道琼斯指数的价格变化为 {dow_price_change:.2f},成交量变化为 {dow_volume_change}。同时,道琼斯指数的5分钟滚动平均为 {dow_rolling_avg:.2f}。市场已经开放了 {market_open_duration:.2f} 分钟。今天的最高价为 {daily_high:.2f},最低价为 {daily_low:.2f}。买入动能为 {buying_momentum:.2f},卖出动能为 {selling_momentum:.2f}。根据这些数据,提供对当前股票趋势和整体市场情绪的见解。见解不应超过500个字,并且不应有引言,用中文。"""response = ollama.chat(model="llama3",messages=[{"role": "user", "content": prompt}])response_text = response['message']['content'].strip()message = st.chat_message("assistant")current_time = datetime.now().strftime("%H:%M")message.write(current_time) # 使用当前时间message.write(response_text)print("Natural Language Insight:", response_text)
- 该函数生成自然语言的市场见解,并在 Streamlit 界面中显示。
10. 定时任务调度
# Schedule job to simulate receiving updates every minute
schedule.every(10).seconds.do(process_stock_update) message = st.chat_message("assistant")
message.write("正在启动 AAPL 股票更新的实时模拟。第一次更新将在 5 分钟后处理...")
# Run the scheduled jobs
print("Starting real-time simulation for AAPL stock updates...")
while True:schedule.run_pending()time.sleep(1)
- 使用
schedule
库每10秒调用一次process_stock_update
函数,以模拟实时数据更新。 - 在 Streamlit 界面中显示初始消息。
总结
这个 AI 股票助手应用程序通过实时更新股票数据并提供市场见解,帮助用户更好地理解市场动态。通过使用 Streamlit,Pandas 和其他库,您可以轻松构建一个功能强大的股票分析工具。
相关代码:https://gitee.com/ooooinfo/streamlitollama.gitgitee