生生不息

生生不息

AI协助开发技术分析面板

2025-06-25
AI协助开发技术分析面板

提示词

我想用Streamlit制作一个简单的行情分析面板,对于功能的构想是,在左侧边栏可以选择金融产品的代码,然后根据代码通过接口获取其历史行情数据;支持选择不同的技术指标,并且使用TA-Lib根据所选的技术指标进行计算;在主面板可视化历史行情的K线图以及技术指标的计算结果:给出部署建议。请给出这个项目的实施步骤,无需写代码。

答案

以下是基于Streamlit构建金融行情分析面板的实施步骤及功能实现方案,整合了多个技术栈和最佳实践建议:

一、项目架构设计
模块划分  

数据获取模块:通过API接口获取历史行情数据(如Yahoo Finance、AKShare或交易所API)

技术指标计算模块:集成TA-Lib库,支持用户选择的指标(如MA、RSI、MACD等)动态计算

可视化模块:使用Plotly或Lightweight Charts渲染K线图和技术指标叠加图表  

交互界面模块:通过Streamlit构建侧边栏控件和主面板布局  
技术选型  

核心工具:Python 3.7+、Streamlit  

数据处理:Pandas、NumPy  

数据源:Yahoo Finance(yfinance)、AKShare(国内数据)、交易所API(如币安)  

可视化库:Plotly Express、streamlit-lightweight-charts(高性能金融图表)

技术指标库:TA-Lib  

二、核心功能实现步骤
环境准备与依赖安装  

安装Python和Streamlit核心库:pip install streamlit pandas yfinance akshare talib plotly streamlit-lightweight-charts

配置TA-Lib环境(需本地编译或使用预编译包)
数据获取与处理  

侧边栏输入控件:  

金融产品代码输入框(如股票代码AAPL、加密货币BTC-USD)  

时间范围选择(开始日期、结束日期)

数据接口调用:  

根据代码调用API获取OHLCV数据,返回Pandas DataFrame格式

示例数据源:yfinance.Ticker(ticker).history()或ak.stock_zh_a_daily() 
技术指标动态计算  

侧边栏多选控件:允许用户勾选技术指标(如SMA、EMA、RSI、布林带)

TA-Lib集成:  

根据用户选择的指标,动态调用TA-Lib函数(如talib.SMA()、talib.RSI())  

计算结果合并到原始DataFrame中
可视化呈现  

K线图渲染:  

使用streamlit-lightweight-charts或Plotly的Candlestick图表展示OHLC数据

支持缩放、平移、十字线等交互功能

技术指标叠加:  

在K线图下方或叠加区域绘制技术指标曲线(如MA线、MACD柱状图)

使用Plotly的多子图布局或Lightweight Charts的叠加功能
性能优化  

数据缓存:通过@st.cache_data装饰器缓存API返回的历史数据,减少重复请求

异步加载:对耗时操作(如TA-Lib计算)使用Streamlit的异步支持或进度条提示

三、部署建议
本地测试与调试  

运行命令streamlit run app.py启动本地服务,实时预览界面

检查数据接口的稳定性和错误处理(如网络超时、无效代码)
云部署方案  

Heroku:  

创建requirements.txt和Procfile,通过Git推送代码自动部署

配置环境变量(如API密钥)

Streamlit Sharing:  

直接关联GitHub仓库,一键部署(需申请权限)

Docker容器化:  

编写Dockerfile,部署到AWS ECS或Google Cloud Run,支持高并发
性能与安全优化  

限流机制:针对API调用设置频率限制(如每秒1次)

HTTPS加密:通过云平台自动配置SSL证书

日志监控:集成Sentry或云平台日志服务,追踪运行时错误

四、扩展功能建议
多时间周期切换:支持日线、周线、分钟级K线切换

自定义参数:允许用户调整技术指标参数(如MA周期、RSI天数)

实时数据更新:集成WebSocket实现实时行情推送(需交易所API支持)

报告导出:添加PDF或Excel导出功能,保存分析结果

五、注意事项
数据源合规性:确保使用的API符合交易所或数据提供商的使用条款

界面响应式设计:适配不同屏幕尺寸(PC/移动端)  

错误友好提示:对无效代码、网络异常等场景提供明确提示

通过以上步骤,可高效构建一个功能完备的金融行情分析面板,满足从数据获取到可视化分析的完整需求。

使用下拉菜单选择期货品种

提示词

使用AKShare获取全部主力连续合约的期货代码,并将这些期货代码以下拉菜单的形式呈现在Streamlit开发的技术分析面板的侧边栏,供用户选择,请给出示例代码。

答案

import streamlit as st
import akshare as ak
import pandas as pd

@st.cache_data  # 缓存数据避免重复请求
def get_futures_main_contracts():
    """获取主力连续合约代码列表"""
    try:
        futures_df = ak.futures_display_main_sina()
        return futures_df["symbol"].tolist()
    except Exception as e:
        st.error(f"数据获取失败: {str(e)}")
        return []

def main():
    st.title("期货技术分析面板")
  
    # 获取主力合约列表
    contracts = get_futures_main_contracts()
  
    if not contracts:
        st.warning("未获取到期货合约数据,请检查网络连接或数据源")
        return
  
    # 侧边栏布局
    with st.sidebar:
        st.header("参数配置")
      
        # 期货合约选择
        selected_contract = st.selectbox(
            label="选择主力合约代码",
            options=contracts,
            index=0,
            help="从新浪财经获取的主力连续合约列表"
        )
      
        # 日期范围选择
        start_date = st.date_input("开始日期", value=pd.to_datetime("2023-01-01"))
        end_date = st.date_input("结束日期", value=pd.to_datetime("2023-12-31"))
  
    try:
        # 获取历史行情数据
        data = ak.futures_main_sina(
            symbol=selected_contract,
            start_date=start_date.strftime("%Y%m%d"),
            end_date=end_date.strftime("%Y%m%d")
        )
      
        # 数据预处理
        data = data.rename(columns={
            "日期": "date",
            "开盘价": "open",
            "最高价": "high",
            "最低价": "low",
            "收盘价": "close",
            "成交量": "volume"
        })
      
        # 展示数据
        st.subheader(f"{selected_contract} 历史行情数据")
        st.dataframe(data.head(10), use_container_width=True)
      
    except Exception as e:
        st.error(f"数据加载失败: {str(e)}")

if __name__ == "__main__":
    main()

将答案保存为5.py.

使用anaconda命令行启动

(lianghua) PS 代码> streamlit run 5.py

  You can now view your Streamlit app in your browser.

  Local URL: http://localhost:8501
  Network URL: http://192.168.31.102:8501

浏览器自动打开了 localhost:8501
界面如下:

合约代码,起止日期都可以选择,很不错。

让用户选择起止日期

尽管前面ai已经直接给出这个功能,我还是简化代码,重新提示看看ai能不能优化,加上日期选择的功能。

提示词

import streamlit as st
import akshare as ak
import pandas as pd
import os
import requests

# 获取当前的环境变量
proxy_env_vars = {'HTTP_PROXY', 'HTTPS_PROXY', 'http_proxy', 'https_proxy'}
current_proxies = {k: v for k, v in os.environ.items() if k in proxy_env_vars}

# 清除环境变量中的代理设置
for var in proxy_env_vars:
    os.environ.pop(var, None)

# 获取所有主力连续合约的期货代码
futures_codes = ak.futures_display_main_sina()
futures_list = futures_codes["symbol"].tolist()

# Streamlit App
st.title("技术分析面板")
selected_contract = st.sidebar.selectbox("选择期货合约代码", futures_list)

# 从akshare获取期货行情数据
futures_data = ak.futures_main_sina(symbol=selected_contract)

# 预览数据
st.write(futures_data)

需要在这个边栏中运行用户选择获取期货行情数据的开始日期和截止日期,请给出示例代码。

答案

import streamlit as st
import akshare as ak
import pandas as pd
import os
import requests
from datetime import datetime, timedelta

# 获取当前的环境变量
proxy_env_vars = {'HTTP_PROXY', 'HTTPS_PROXY', 'http_proxy', 'https_proxy'}
current_proxies = {k: v for k, v in os.environ.items() if k in proxy_env_vars}

# 清除环境变量中的代理设置
for var in proxy_env_vars:
    os.environ.pop(var, None)


# 获取所有主力连续合约的期货代码
@st.cache_data  # 添加缓存减少重复请求
def get_futures_codes():
    try:
        futures_codes = ak.futures_display_main_sina()
        return futures_codes["symbol"].tolist()
    except Exception as e:
        st.error(f"获取合约代码失败: {str(e)}")
        return []


futures_list = get_futures_codes()

# Streamlit App
st.title("期货技术分析面板")

# 侧边栏布局
with st.sidebar:
    st.header("参数设置")

    # 1. 期货合约选择
    selected_contract = st.selectbox(
        "选择期货合约代码",
        futures_list,
        index=0 if futures_list else None,
        help="从新浪财经获取的主力连续合约列表"
    )

    # 2. 日期范围选择
    today = datetime.today()
    default_start = today - timedelta(days=180)  # 默认半年前

    col1, col2 = st.columns(2)
    with col1:
        start_date = st.date_input(
            "开始日期",
            value=default_start,
            min_value=datetime(2000, 1, 1),
            max_value=today
        )
    with col2:
        end_date = st.date_input(
            "结束日期",
            value=today,
            min_value=start_date,
            max_value=today
        )

    # 3. 添加刷新按钮
    refresh = st.button("刷新数据", use_container_width=True)


# 数据处理函数
@st.cache_data  # 缓存数据提高性能
def get_futures_data(symbol, start, end):
    try:
        # 转换日期格式 (YYYYMMDD)
        start_str = start.strftime("%Y%m%d")
        end_str = end.strftime("%Y%m%d")

        # 获取数据
        data = ak.futures_main_sina(
            symbol=symbol,
            start_date=start_str,
            end_date=end_str
        )

        # 数据清洗
        data = data.rename(columns={
            "日期": "date",
            "开盘价": "open",
            "最高价": "high",
            "最低价": "low",
            "收盘价": "close",
            "成交量": "volume"
        })
        data['date'] = pd.to_datetime(data['date'])
        return data.sort_values('date').reset_index(drop=True)
    except Exception as e:
        st.error(f"数据获取失败: {str(e)}")
        return pd.DataFrame()


# 获取并展示数据
if futures_list and selected_contract:
    data = get_futures_data(selected_contract, start_date, end_date)

    if not data.empty:
        st.subheader(f"{selected_contract} 行情数据 ({start_date} 至 {end_date})")

        # 显示关键指标
        col1, col2, col3 = st.columns(3)
        col1.metric("交易日数", len(data))
        col2.metric("最高价", f"{data['high'].max():.2f}")
        col3.metric("最低价", f"{data['low'].min():.2f}")

        # 显示数据表格
        st.dataframe(data, use_container_width=True)

        # 显示折线图
        st.subheader("价格走势")
        st.line_chart(data.set_index('date')[['open', 'high', 'low', 'close']])
    else:
        st.warning("未获取到有效数据,请检查日期范围或合约代码")
else:
    st.warning("未获取到期货合约列表,请检查网络连接")

我们只需要复制以上全部代码,替换掉5.py的内容,保存。

刷新网页就可以看到新的配置界面。

还自己增加了可视化。

添加技术分析指标

还是简化代码后提示ai看看

提示词

import streamlit as st
import akshare as ak
import pandas as pd
import os
import requests
from datetime import datetime, timedelta

# 获取当前的环境变量
proxy_env_vars = {'HTTP_PROXY', 'HTTPS_PROXY', 'http_proxy', 'https_proxy'}
current_proxies = {k: v for k, v in os.environ.items() if k in proxy_env_vars}

# 清除环境变量中的代理设置
for var in proxy_env_vars:
    os.environ.pop(var, None)

# 获取所有主力连续合约的期货代码
futures_codes = ak.futures_display_main_sina()
futures_list = futures_codes["symbol"].tolist()

# Streamlit App
st.title("技术分析面板")
selected_contract = st.sidebar.selectbox("选择期货合约代码", futures_list)

# 用户选择日期范围
start_date = st.sidebar.date_input("选择开始日期", datetime(2023, 1, 1))
end_date = st.sidebar.date_input("选择截止日期", datetime(2023, 12, 31))

# 从akshare获取期货行情数据
futures_data = ak.futures_main_sina(symbol=selected_contract,
                                   start_date=start_date,
                                   end_date=end_date)

# 显示所选的期货合约代码和日期范围
st.write(f"您选择了期货合约代码: {selected_contract}")
st.write(f"您选择的日期范围是从 {start_date} 到 {end_date}")

# 预览数据
st.write(futures_data)

现在我要在Streamlit开发的技术分析面板的侧边栏中添加MACD、布林带、RSI指标,供用户选择,调用TA-Lib中相应的函数对已经获取的数据futures_data进行计算,并且将计算结果存储在futures_data的新列中,请给出示例代码。

答案

import streamlit as st
import akshare as ak
import pandas as pd
import talib  # 导入TA-Lib库
import os
import requests
from datetime import datetime

# 获取当前的环境变量
proxy_env_vars = {'HTTP_PROXY', 'HTTPS_PROXY', 'http_proxy', 'https_proxy'}
current_proxies = {k: v for k, v in os.environ.items() if k in proxy_env_vars}

# 清除环境变量中的代理设置
for var in proxy_env_vars:
    os.environ.pop(var, None)

# 获取所有主力连续合约的期货代码
futures_codes = ak.futures_display_main_sina()
futures_list = futures_codes["symbol"].tolist()

# Streamlit App
st.title("期货技术分析面板")

# 在侧边栏添加技术指标选择
with st.sidebar:
    st.header("技术指标配置")

    # 添加技术指标复选框
    st.subheader("选择技术指标")
    calc_macd = st.checkbox("MACD", value=True)
    calc_bollinger = st.checkbox("布林带", value=True)
    calc_rsi = st.checkbox("RSI", value=True)

    # 指标参数设置
    st.subheader("指标参数")
    rsi_period = st.slider("RSI周期", 5, 30, 14)
    macd_fast = st.slider("MACD快线周期", 5, 20, 12)
    macd_slow = st.slider("MACD慢线周期", 15, 40, 26)
    bollinger_period = st.slider("布林带周期", 10, 50, 20)

# 期货合约选择
selected_contract = st.sidebar.selectbox("选择期货合约代码", futures_list)

# 用户选择日期范围
start_date = st.sidebar.date_input("选择开始日期", datetime(2023, 1, 1))
end_date = st.sidebar.date_input("选择截止日期", datetime(2023, 12, 31))

# 从akshare获取期货行情数据
futures_data = ak.futures_main_sina(symbol=selected_contract,
                                    start_date=start_date.strftime("%Y%m%d"),
                                    end_date=end_date.strftime("%Y%m%d"))

# 重命名列以便处理(中文列名可能导致问题)
futures_data = futures_data.rename(columns={
    "日期": "date",
    "开盘价": "open",
    "最高价": "high",
    "最低价": "low",
    "收盘价": "close",
    "成交量": "volume"
})

# 确保数据类型正确
futures_data['close'] = pd.to_numeric(futures_data['close'], errors='coerce')
futures_data = futures_data.dropna(subset=['close'])

# 技术指标计算
if calc_macd:
    # 计算MACD指标[3,7](@ref)
    macd, macd_signal, macd_hist = talib.MACD(
        futures_data['close'],
        fastperiod=macd_fast,
        slowperiod=macd_slow,
        signalperiod=9
    )
    futures_data['MACD'] = macd
    futures_data['MACD_signal'] = macd_signal
    futures_data['MACD_hist'] = macd_hist

if calc_bollinger:
    # 计算布林带指标[6,7](@ref)
    upper, middle, lower = talib.BBANDS(
        futures_data['close'],
        timeperiod=bollinger_period,
        nbdevup=2,
        nbdevdn=2,
        matype=0  # 0表示简单移动平均
    )
    futures_data['BB_upper'] = upper
    futures_data['BB_middle'] = middle
    futures_data['BB_lower'] = lower

if calc_rsi:
    # 计算RSI指标[3,7](@ref)
    rsi = talib.RSI(futures_data['close'], timeperiod=rsi_period)
    futures_data['RSI'] = rsi

# 显示所选的期货合约代码和日期范围
st.write(f"您选择了期货合约代码: {selected_contract}")
st.write(f"您选择的日期范围是从 {start_date} 到 {end_date}")

# 预览数据
st.subheader("期货行情数据与技术指标")
st.dataframe(futures_data)

# 显示技术指标图表
st.subheader("技术指标可视化")

if calc_macd and 'MACD' in futures_data.columns:
    st.line_chart(futures_data[['MACD', 'MACD_signal']], use_container_width=True)
    st.bar_chart(futures_data['MACD_hist'], use_container_width=True)

if calc_bollinger and 'BB_upper' in futures_data.columns:
    st.line_chart(futures_data[['close', 'BB_upper', 'BB_middle', 'BB_lower']], use_container_width=True)

if calc_rsi and 'RSI' in futures_data.columns:
    st.line_chart(futures_data['RSI'], use_container_width=True)
    st.area_chart(futures_data['RSI'], use_container_width=True)

替换5.py内容,保存,刷新网页,如下:

添加K线图与技术指标的可视化展示

提示词

简化代码再描述

import streamlit as st
import akshare as ak
import talib
import pandas as pd
from datetime import datetime
import cufflinks as cf
from plotly.offline import iplot

cf.go_offline()
import os
import requests

# 获取当前的环境变量
proxy_env_vars = {'HTTP_PROXY', 'HTTPS_PROXY', 'http_proxy', 'https_proxy'}
current_proxies = {k: v for k, v in os.environ.items() if k in proxy_env_vars}

# 清除环境变量中的代理设置
for var in proxy_env_vars:
    os.environ.pop(var, None)

# 获取所有主力连续合约的期货代码
# futures_codes = ak.futures_display_main_sina()
# futures_list = futures_codes["symbol"].tolist()
futures_list = ['V0', 'P0', 'B0', 'M0']

# Streamlit App
st.title("技术分析面板")
selected_contract = st.sidebar.selectbox("选择期货合约代码", futures_list)

# 用户选择日期范围
start_date = st.sidebar.date_input("选择开始日期", datetime(2023, 1, 1))
end_date = st.sidebar.date_input("选择截止日期", datetime(2023, 12, 31))

# 从akshare获取期货行情数据
futures_data = ak.futures_main_sina(symbol=selected_contract,
                                    start_date=start_date,
                                    end_date=end_date)

# 侧边栏选择指标
selected_indicator = st.sidebar.selectbox("选择指标", ["MACD", "布林带", "RSI"])

# 计算并显示选择的指标
if selected_indicator == "MACD":
    # 计算MACD指标
    macd, signal, _ = talib.MACD(futures_data["收盘价"])
    futures_data["MACD"] = macd
    futures_data["Signal"] = signal
    # st.line_chart(futures_data[["MACD", "Signal"]])


elif selected_indicator == "布林带":
    # 计算布林带指标
    upper, middle, lower = talib.BBANDS(futures_data["收盘价"])
    futures_data["Upper Bollinger Band"] = upper
    futures_data["Middle Bollinger Band"] = middle
    futures_data["Lower Bollinger Band"] = lower
    # st.line_chart(futures_data[["Upper Bollinger Band", "Middle Bollinger Band", "Lower Bollinger Band"]])


elif selected_indicator == "RSI":
    # 计算RSI指标
    rsi = talib.RSI(futures_data["收盘价"])
    futures_data["RSI"] = rsi
    # st.line_chart(futures_data["RSI"])

# 显示所选的期货合约代码和日期范围
st.write(f"您选择了期货合约代码: {selected_contract}")
st.write(f"您选择的日期范围是从 {start_date} 到 {end_date}")

st.write(futures_data)

现在需要在上述Streamlit应用中添加可视化的部分,使用Cufflinks绘制future_data的K线图,并把技术指标的计算结果也添加到可视化展示中,请给出示例代码。

答案

这部分,一开始报错,不过界面还挺分布合理,类似之前的布局,不过在我紧接着copy error后修改的就比较简约了,总之实现了K线图+技术指标,可以参考之前的代码再修改。

import streamlit as st
import akshare as ak
import talib
import pandas as pd
import numpy as np
from datetime import datetime
import cufflinks as cf
from plotly.subplots import make_subplots
import plotly.graph_objects as go

# 初始化Cufflinks配置
cf.go_offline()
cf.set_config_file(theme='pearl', offline=True)

# 获取期货数据(省略环境变量处理部分)
# 获取所有主力连续合约的期货代码
# futures_codes = ak.futures_display_main_sina()
# futures_list = futures_codes["symbol"].tolist()
futures_list = ['V0', 'P0', 'B0', 'M0']

selected_contract = st.sidebar.selectbox("选择期货合约代码", futures_list)
start_date = st.sidebar.date_input("开始日期", datetime(2023, 1, 1))
end_date = st.sidebar.date_input("结束日期", datetime(2023, 12, 31))

# 获取并预处理数据
futures_data = ak.futures_main_sina(
    symbol=selected_contract,
    start_date=start_date.strftime("%Y%m%d"),
    end_date=end_date.strftime("%Y%m%d")
)
futures_data = futures_data.rename(columns={
    "日期": "date", "开盘价": "open", "最高价": "high",
    "最低价": "low", "收盘价": "close", "成交量": "volume"
})
futures_data['date'] = pd.to_datetime(futures_data['date'])
futures_data.set_index('date', inplace=True)

# 计算技术指标
macd, signal, hist = talib.MACD(futures_data['close'])
futures_data['MACD'] = macd
futures_data['Signal'] = signal
futures_data['Hist'] = hist


# 使用Plotly原生方法创建复合图表
def create_macd_chart(data):
    fig = make_subplots(rows=2, cols=1,
                        shared_xaxes=True,
                        vertical_spacing=0.02,
                        row_heights=[0.7, 0.3])

    # K线图
    fig.add_trace(go.Candlestick(
        x=data.index,
        open=data['open'],
        high=data['high'],
        low=data['low'],
        close=data['close'],
        name='K线'
    ), row=1, col=1)

    # MACD指标
    colors = np.where(data['Hist'] > 0, 'green', 'red')
    fig.add_trace(go.Scatter(
        x=data.index,
        y=data['MACD'],
        name='MACD',
        line=dict(color='blue')
    ), row=2, col=1)
    fig.add_trace(go.Scatter(
        x=data.index,
        y=data['Signal'],
        name='信号线',
        line=dict(color='orange')
    ), row=2, col=1)
    fig.add_trace(go.Bar(
        x=data.index,
        y=data['Hist'],
        name='柱状图',
        marker_color=colors
    ), row=2, col=1)

    fig.update_layout(
        height=600,
        xaxis=dict(rangeslider=dict(visible=False)),
        yaxis=dict(title='价格'),
        showlegend=True
    )
    return fig


# 显示图表
st.plotly_chart(create_macd_chart(futures_data), use_container_width=True)