当前位置:首页>python>量化系列(八十八): Python 获取某财富股票历史数据|附可直接运行完整源码

量化系列(八十八): Python 获取某财富股票历史数据|附可直接运行完整源码

  • 2026-10-11 06:27:06
量化系列(八十八): Python 获取某财富股票历史数据|附可直接运行完整源码

一. 认真学完这一章节,你可以做什么?

上一章节,我们获取了股票的实时数据并进行展示, 我看有群友问,怎么获取某财富的股票的历史数据。

今天小亥整理了一下, 分享给大家。 并形成了 streamlit 页面,免费开放给大家。

样式大概如下:

可以查看 K线图

可以查看收盘 价走势

可以查看日K数据并进行下载

也可以查看原始数据。

本文含系统自动匹配的广告,广告收入用于支持持续创作,感谢理解

二.    数据源和响应信息

股票的实时数据,从 某财富平台获取,暂不采用 金亥跃江的股票平台数据。

请求样式为:

https://www.eastmoney.com/

请求地址:

https://push2his.eastmoney.com/api/qt/stock/kline/get?cb=jQuery351030739714292037856_1783413734029&secid=1.000001&ut=fa5fd1943c7b386f172d6893dbfba10b&fields1=f1%2Cf2%2Cf3%2Cf4%2Cf5%2Cf6&fields2=f51%2Cf52%2Cf53%2Cf54%2Cf55%2Cf56%2Cf57%2Cf58%2Cf59%2Cf60%2Cf61&klt=101&fqt=1&end=20500101&lmt=120&_=1783413734042

请求方式:   Get

请求参数:

cb: jQuery351030739714292037856_1783413734029secid: 1.000001ut: fa5fd1943c7b386f172d6893dbfba10bfields1: f1%2Cf2%2Cf3%2Cf4%2Cf5%2Cf6fields2: f51%2Cf52%2Cf53%2Cf54%2Cf55%2Cf56%2Cf57%2Cf58%2Cf59%2Cf60%2Cf61klt: 101fqt: 1end: 20500101lmt: 120_: 1

请求头  Cookie :

xxxxx

关于相应的解析,可以看历史文章

Java量化系列(三):实现东方财富历史日K线数据同步

三.   Python 实现获取股票的实时数据

为了方便大家理解和使用, 小亥将采用 streamlit  进行编写相关的脚本, 这样有页面,也方便点击 。

大家可以通过 AI 自行实现,  小亥这儿提供一个简单的版本。

脚本名称为   stock_history_df.py

安装依赖:

pip install streamlit requests pandas plotly -i https://pypi.tuna.tsinghua.edu.cn/simple

完整的代码是:

# -*- coding: utf-8 -*-"""Stock History - 东方财富日K线数据展示工具通过输入 secid 获取股票日K线数据,支持表格展示和K线图可视化。"""import timeimport jsonimport reimport requestsimport pandas as pdimport streamlit as stimport plotly.graph_objects as gofrom plotly.subplots import make_subplots# ==================== 配置 ====================EASTMONEY_API = "https://push2his.eastmoney.com/api/qt/stock/kline/get"COOKIE = "st_nvi=JXtoOSyJp10OOMO7codqk7cf9; nid18=0d409d1bdf0f765bed359fb5afb19b0e; nid18_create_time=1776172143567; gviem=Ra4LtS_JOVVDYxS7GBjK1e061; gviem_create_time=1776172143567; mtp=1; ct=LvJ51CmrljYbsp7qFlSOHn7VFCigLZ-oUKziSdwhm6QoiW2PfEY8NuMNbIAhQltzdIL7cXRBNiMr4qp1BoNETrOvupIlJSg6-CX9utxINQQ29VzIW752DBIjV2HnhLPM4vZqa8gKqQIUyV-nurLw-Mt1uEp_5c2QBnB3r8bICYo; ut=FobyicMgeV5FJnFT189SwKsr5jWOQIjKhBFsML-oN6OsBB6yqsyPbl2exqGvqIznyDIwf2IUGOjBI62xNrfy4dMMINyh9bY6q097910z-zTtlawTdRkdujUTwgPoC4gsmCb8_bdltdAizQOiKYVyQb607PJ9ZUDekqP9gFhZ5XrCB82ujMtz8dksMJDIlaacTw2TiUGSTPEBLDJCV0r3NFdaW9u3xZXbLwoZpZZ4Mn4Yvp7p9sGGpk6VLmXuEB28jmDszyO-GIb3ZHapeQShBiz3_WSmXHmGMyd9_yTZHzw3TVAZUsxTpA3AxHfxYzyAdU9TOiJfq4SUwdkaXVbn7oOKONuWOFDJ; pi=3113356087927502%3Bu3113356087927502%3B%E9%87%91%E4%BA%A5%E8%B7%83%E6%B1%9F%E8%81%8A%E9%87%8F%E5%8C%96%3BZ8jzwulgDvjTB%2FdfMXwe7MWCuDFdJYeEZ9YXPw9DaPvNf0yss8FbUnlXbM7VA%2BXQMLHx%2Fd8Jr4Ur6RwdlfiezLt0muyOGZXSCSQyLCn0IYkUMhRoBXDNUUWpEe2YNyTEQMRw68ZUoFByBu86AcX6rz2eoYpSzkDX51UV%2BN%2FwS%2FqYpykpkb9clgPcxcCTeGuDZ56yRw3M%3B3gLCycLHHXJ9%2BdAtJ%2BhdrjF4T3DZE%2BoSuug3tmpvI0DgArXOqSfIAeEEuafgzB6LdnHYk6qYHmBaTH%2FGPAevaAu%2Fr%2F5qvAuRrP8SaMXEeFdxDbmScJ%2Bq%2Bp7KZLm414bBKr5RwgdVmt53CM0n3XPsvgPtBvGZrQ%3D%3D; uidal=3113356087927502%e9%87%91%e4%ba%a5%e8%b7%83%e6%b1%9f%e8%81%8a%e9%87%8f%e5%8c%96; sid=155993128; vtpst=|; qgqp_b_id=afa30b2a29cfa4527a0c5d7a241f3923; emshistory=%5B%22%E4%BA%BA%E5%91%98%E7%BB%84%E5%90%88%22%2C%22%E5%88%9B%E4%B8%9A%E6%9D%BF%E6%8C%87%22%5D; websitepoptg_api_time=1783509762928; st_si=78864800140191; fullscreengg=1; fullscreengg2=1; st_asi=delete; st_pvi=76568201336250; st_sp=2021-11-07%2009%3A48%3A02; st_inirUrl=http%3A%2F%2Fquote.eastmoney.com%2Fsh603233.html; st_sn=27; st_psi=20260709193704892-111000300841-8316770403";HEADERS = {    "User-Agent": (        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "        "AppleWebKit/537.36 (KHTML, like Gecko) "        "Chrome/120.0.0.0 Safari/537.36"    ),    "Referer": "https://quote.eastmoney.com/",    "Cookie": COOKIE,}# fields2 字段映射: f51~f61FIELDS2_MAP = {    "f51": "日期",    "f52": "开盘",    "f53": "收盘",    "f54": "最高",    "f55": "最低",    "f56": "成交量",    "f57": "成交额",    "f58": "振幅(%)",    "f59": "涨跌幅(%)",    "f60": "涨跌额",    "f61": "换手率(%)",}# 常用 secid 示例SECID_EXAMPLES = {    "上证指数": "1.000001",    "深证成指": "0.399001",    "创业板指": "0.399006",    "贵州茅台": "1.600519",    "中国平安": "1.601318",    "比亚迪": "0.002594",    "宁德时代": "0.300750",    "腾讯控股(HK)": "116.00700",}# ==================== 数据获取 ====================def fetch_kline_data(    secid: str,    klt: int = 101,    lmt: int = 120,    end: str = "20500101",    fqt: int = 1,) -> dict:    """    从东方财富接口获取K线数据。    Args:        secid: 股票代码,格式为 "市场.代码"(如 1.000001 表示上证指数)        klt: K线类型,101=日K, 102=周K, 103=月K, 5=5分钟, 15=15分钟, 30=30分钟, 60=60分钟        lmt: 返回数据条数        end: 结束日期,格式 YYYYMMDD        fqt: 复权类型,0=不复权, 1=前复权, 2=后复权    Returns:        dict: 接口返回的JSON数据    """    params = {        "secid": secid,        "ut": "fa5fd1943c7b386f172d6893dbfba10b",        "fields1": "f1,f2,f3,f4,f5,f6",        "fields2": "f51,f52,f53,f54,f55,f56,f57,f58,f59,f60,f61",        "klt": str(klt),        "fqt": str(fqt),        "end": end,        "lmt": str(lmt),        "_": str(int(time.time() * 1000)),    }    try:        resp = requests.get(EASTMONEY_API, params=params, headers=HEADERS, timeout=15)        resp.raise_for_status()        data = resp.json()        return data    except requests.exceptions.JSONDecodeError:        # 某些情况下返回 JSONP,用正则提取        text = resp.text        match = re.search(r"\((\{.*\})\)", text)        if match:            return json.loads(match.group(1))        raise ValueError("无法解析接口返回数据")    except Exception as e:        raise RuntimeError(f"请求接口失败: {e}")def parse_kline_to_df(data: dict) -> pd.DataFrame:    """    将接口返回的K线数据解析为 DataFrame。    Args:        data: fetch_kline_data 返回的 dict    Returns:        pd.DataFrame: 包含日期、开盘、收盘、最高、最低等列的 DataFrame    """    klines = data.get("data", {}).get("klines", [])    if not klines:        return pd.DataFrame()    rows = []    for line in klines:        parts = line.split(",")        if len(parts) >= 11:            rows.append({                "日期": parts[0],                "开盘": float(parts[1]),                "收盘": float(parts[2]),                "最高": float(parts[3]),                "最低": float(parts[4]),                "成交量": int(float(parts[5])),                "成交额": float(parts[6]),                "振幅(%)": float(parts[7]),                "涨跌幅(%)": float(parts[8]),                "涨跌额": float(parts[9]),                "换手率(%)": float(parts[10]),            })    df = pd.DataFrame(rows)    df["日期"] = pd.to_datetime(df["日期"])    df = df.sort_values("日期").reset_index(drop=True)    return df# ==================== 可视化 ====================def render_candlestick_chart(df: pd.DataFrame, stock_name: str = ""):    """    使用 Plotly 渲染K线图 + 成交量副图。    Args:        df: K线数据 DataFrame        stock_name: 股票名称(用于标题)    """    # 中国股市惯例:涨红跌绿    colors_up = "#E63946"   # 红色 - 涨    colors_down = "#2A9D8F" # 绿色 - 跌    # 根据涨跌设置K线颜色    df_plot = df.copy()    df_plot["颜色"] = df_plot["收盘"] >= df_plot["开盘"]    # 涨用红色,跌用绿色    df_plot["颜色"] = df_plot["颜色"].map({True: colors_up, False: colors_down})    fig = make_subplots(        rows=2,        cols=1,        shared_xaxes=True,        vertical_spacing=0.08,        row_heights=[0.75, 0.25],        subplot_titles=("K线图", "成交量"),    )    # --- K线图 ---    fig.add_trace(        go.Candlestick(            x=df_plot["日期"],            open=df_plot["开盘"],            high=df_plot["最高"],            low=df_plot["最低"],            close=df_plot["收盘"],            name="K线",            increasing_line_color=colors_up,            decreasing_line_color=colors_down,            increasing_fillcolor=colors_up,            decreasing_fillcolor=colors_down,        ),        row=1,        col=1,    )    # --- 成交量柱状图 ---    vol_colors = df_plot["收盘"] >= df_plot["开盘"]    vol_colors = vol_colors.map({True: colors_up, False: colors_down})    fig.add_trace(        go.Bar(            x=df_plot["日期"],            y=df_plot["成交量"],            name="成交量",            marker_color=vol_colors,            showlegend=False,        ),        row=2,        col=1,    )    # 布局配置    title = f"{stock_name} 日K线图" if stock_name else "日K线图"    fig.update_layout(        title=dict(text=title, x=0.5, font=dict(size=18)),        xaxis_rangeslider_visible=False,        template="plotly_white",        height=600,        margin=dict(l=50, r=50, t=60, b=40),        legend=dict(orientation="h", yanchor="bottom", y=1.02),    )    fig.update_yaxes(title_text="价格", row=1, col=1)    fig.update_yaxes(title_text="成交量", row=2, col=1)    st.plotly_chart(fig, use_container_width=True)def render_line_chart(df: pd.DataFrame):    """渲染收盘价折线图。"""    fig = go.Figure()    fig.add_trace(        go.Scatter(            x=df["日期"],            y=df["收盘"],            mode="lines+markers",            name="收盘价",            line=dict(color="#1d6fdb", width=2),            marker=dict(size=4),        )    )    fig.update_layout(        title=dict(text="收盘价走势", x=0.5, font=dict(size=18)),        xaxis_title="日期",        yaxis_title="价格",        template="plotly_white",        height=400,        margin=dict(l=50, r=50, t=60, b=40),    )    st.plotly_chart(fig, use_container_width=True)# ==================== Streamlit 页面 ====================def main():    st.set_page_config(        page_title="金亥跃江_股票日K数据查询",        page_icon="📈",        layout="wide",    )    st.title("📈 金亥跃江_股票日K数据查询")    st.markdown("---")    # --- 侧边栏:参数设置 ---    with st.sidebar:        st.header("🔧 参数设置")        # secid 输入        secid_input = st.text_input(            "请输入 secid",            value="1.000001",            help="格式:市场.代码(1=沪市, 0=深市, 116=港股),如 1.000001 表示上证指数",        )        # 快捷选择        st.markdown("**快捷选择:**")        selected = st.selectbox(            "常用股票/指数",            options=[""] + list(SECID_EXAMPLES.keys()),            index=0,            label_visibility="collapsed",        )        if selected:            secid_input = SECID_EXAMPLES[selected]        # K线类型        klt_options = {            101: "日K",            102: "周K",            103: "月K",            5: "5分钟K",            15: "15分钟K",            30: "30分钟K",            60: "60分钟K",        }        klt = st.selectbox("K线类型", options=list(klt_options.keys()),                           format_func=lambda x: klt_options[x], index=0)        # 数据条数        lmt = st.slider("数据条数", min_value=30, max_value=500, value=120, step=10)        # 复权类型        fqt_options = {0: "不复权", 1: "前复权", 2: "后复权"}        fqt = st.selectbox("复权类型", options=list(fqt_options.keys()),                           format_func=lambda x: fqt_options[x], index=1)        st.markdown("---")        fetch_btn = st.button("🔍 查询数据", type="primary", use_container_width=True)    # --- 主区域 ---    if fetch_btn or secid_input:        if not secid_input.strip():            st.warning("请输入 secid")            return        with st.spinner("正在获取数据..."):            try:                raw_data = fetch_kline_data(secid_input.strip(), klt=klt, lmt=lmt, fqt=fqt)                df = parse_kline_to_df(raw_data)            except Exception as e:                st.error(f"获取数据失败:{e}")                return        if df.empty:            st.warning("未获取到数据,请检查 secid 是否正确。")            return        # 获取股票名称        stock_name = raw_data.get("data", {}).get("name", "")        code = raw_data.get("data", {}).get("code", "")        market = raw_data.get("data", {}).get("market", "")        # --- 数据概览 ---        col1, col2, col3, col4 = st.columns(4)        latest = df.iloc[-1]        first = df.iloc[0]        total_change = ((latest["收盘"] - first["收盘"]) / first["收盘"] * 100) if first["收盘"] != 0 else 0        col1.metric("股票名称", stock_name or "未知")        col2.metric("数据条数", f"{len(df)} 条")        col3.metric("最新收盘价", f"{latest['收盘']:.2f}",                     delta=f"{latest['涨跌幅(%)']:.2f}%")        col4.metric("区间涨跌幅", f"{total_change:.2f}%",                     delta=f"{total_change:+.2f}%")        st.markdown("---")        # --- Tab 切换 ---        tab_chart, tab_line, tab_table, tab_raw = st.tabs(            ["📊 K线图", "📈 收盘价走势", "📋 数据表格", "🔍 原始数据"]        )        with tab_chart:            render_candlestick_chart(df, stock_name)        with tab_line:            render_line_chart(df)        with tab_table:            # 反转显示(最新在前)            df_display = df.iloc[::-1].copy()            df_display["日期"] = df_display["日期"].dt.strftime("%Y-%m-%d")            st.dataframe(                df_display,                use_container_width=True,                height=500,                column_config={                    "成交量": st.column_config.NumberColumn(format="%d"),                    "成交额": st.column_config.NumberColumn(format="%.2f"),                },            )            # 下载按钮            csv = df_display.to_csv(index=False).encode("utf-8-sig")            st.download_button(                label="📥 下载 CSV",                data=csv,                file_name=f"{stock_name or secid_input}_{klt_options[klt]}.csv",                mime="text/csv",            )        with tab_raw:            st.json(raw_data)    else:        st.info("请在左侧输入 secid 并点击「查询数据」按钮。")        # 使用说明        with st.expander("📖 使用说明"):            st.markdown("""            ### secid 格式说明            secid 由 **市场代码** 和 **股票代码** 组成,用 `.` 分隔:            | 市场 | 市场代码 | 示例 | 说明 |            |------|---------|------|------|            | 沪市 | 1 | 1.600519 | 贵州茅台 |            | 深市 | 0 | 0.000001 | 平安银行 |            | 创业板 | 0 | 0.300750 | 宁德时代 |            | 港股 | 116 | 116.00700 | 腾讯控股 |            | 指数-沪 | 1 | 1.000001 | 上证指数 |            | 指数-深 | 0 | 0.399001 | 深证成指 |            ### 功能说明            - **K线图**:展示日K蜡烛图 + 成交量副图(涨红跌绿,符合中国股市惯例)            - **收盘价走势**:折线图展示收盘价变化趋势            - **数据表格**:可排序、筛选的表格,支持 CSV 下载            - **原始数据**:查看接口返回的 JSON 原始数据            """)if __name__ == "__main__":    main()

Google 浏览器会自动打开

免责声明:本文仅供技术交流,不构成任何投资建议。股市有风险,投资需谨慎。

如果你觉得这篇文章说到了心坎里,请点个“在看” 和推荐 ,点个关注,并转发给身边的朋友,让更多人支持小亥!

#Python量化   #股票量化  #股票实时数据  #金亥跃江聊量化 #金亥跃江

最新文章

随机文章