用Python实现A股北向资金自动监控系统——从数据获取到预警推送完整实战

2 阅读1分钟

用Python实现A股北向资金自动监控系统

保姆级教程 | 2026-05-21 | 约3000字

引言

北向资金(北上资金)是A股市场最重要的资金流向指标之一。外资通过沪深港通每日进出,其净流入/流出规模往往能提前预示市场方向。

本文从零搭建一套完整的北向资金监控系统,包含:

  • 数据获取(东方财富API)
  • 指标计算(5日均值、趋势判断)
  • 阈值预警(单日超100亿推送)
  • 自动推送(飞书机器人/邮件)
  • 定时任务(cron/config)

一、数据获取层

1.1 东方财富API接口

东方财富的沪深港通数据接口无需认证,直接HTTP GET即可获取:

import requests
import pandas as pd
from datetime import datetime, timedelta

def fetch_northbound_flow(days=30):
    """获取北向资金近N日流向数据"""
    url = "https://push2his.eastmoney.com/api/qt/stock/fflow/kline/get"
    params = {
        "secid": "1.000001",
        "fields1": "f1,f2,f3,f7",
        "fields2": "f51,f52,f53,f54,f55,f56",
        "klt": "101",  # 日K
        "lmt": str(days),
        "_": str(int(datetime.now().timestamp() * 1000))
    }
    
    resp = requests.get(url, params=params, timeout=10)
    data = resp.json()
    
    if data.get("data") and data["data"].get("klines"):
        records = []
        for line in data["data"]["klines"]:
            items = line.split(",")
            records.append({
                "date": items[0],
                "sh_net": float(items[1]),   # 沪股通净流入
                "sz_net": float(items[2]),   # 深股通净流入
                "total_net": float(items[3]), # 合计净流入
                "sh_amount": float(items[4]), # 沪股通成交额
                "sz_amount": float(items[5])  # 深股通成交额
            })
        return pd.DataFrame(records)
    return pd.DataFrame()

1.2 数据清洗

def clean_data(df):
    """数据清洗与特征工程"""
    df["date"] = pd.to_datetime(df["date"])
    df["total_amount"] = df["sh_amount"] + df["sz_amount"]
    
    # 5日均值
    df["ma5_net"] = df["total_net"].rolling(5).mean()
    
    # 连续流入/流出天数
    df["direction"] = df["total_net"].apply(lambda x: 1 if x > 0 else -1)
    df["consecutive_days"] = (
        df["direction"].groupby(
            (df["direction"] != df["direction"].shift()).cumsum()
        ).cumcount() + 1
    ) * df["direction"]
    
    return df

二、预警逻辑层

2.1 阈值定义

class AlertConfig:
    """预警配置"""
    # 红色预警
    SINGLE_DAY_INFLOW_HIGH = 100  # 单日净流入超100亿
    SINGLE_DAY_OUTFLOW_HIGH = -100  # 单日净流出超100亿
    CONSECUTIVE_INFLOW = 5  # 连续流入5天
    CONSECUTIVE_OUTFLOW = 3  # 连续流出3天
    
    # 黄色预警
    CUMULATIVE_5DAY_HIGH = 300  # 5日累计超300亿
    CUMULATIVE_5DAY_LOW = -300  # 5日累计流出超300亿

2.2 预警判断

def check_alerts(df):
    """扫描最新数据,判断是否触发预警"""
    latest = df.iloc[-1]
    alerts = []
    
    # 单日预警
    if latest["total_net"] > AlertConfig.SINGLE_DAY_INFLOW_HIGH:
        alerts.append({
            "level": "🔴",
            "title": "单日大额净流入",
            "detail": f"今日北向资金净流入{latest['total_net']:.0f}亿"
        })
    elif latest["total_net"] < AlertConfig.SINGLE_DAY_OUTFLOW_HIGH:
        alerts.append({
            "level": "🔴",
            "title": "单日大额净流出",
            "detail": f"今日北向资金净流出{abs(latest['total_net']):.0f}亿"
        })
    
    # 连续方向预警
    cons = latest["consecutive_days"]
    if cons >= AlertConfig.CONSECUTIVE_INFLOW:
        alerts.append({
            "level": "🟡",
            "title": "连续净流入",
            "detail": f"已连续{cons}日净流入"
        })
    elif cons <= -AlertConfig.CONSECUTIVE_OUTFLOW:
        alerts.append({
            "level": "🟡",
            "title": "连续净流出",
            "detail": f"已连续{abs(cons)}日净流出"
        })
    
    return alerts

三、推送层

3.1 飞书机器人推送

import json

def push_to_feishu(webhook_url: str, alerts: list, summary: dict):
    """通过飞书Webhook推送预警消息"""
    if not alerts:
        return
    
    content_lines = ["## 📊 北向资金监控报告\n"]
    for alert in alerts:
        content_lines.append(f"{alert['level']} **{alert['title']}**")
        content_lines.append(f"> {alert['detail']}\n")
    
    content_lines.append("---")
    content_lines.append(f"📅 日期:{summary['date']}")
    content_lines.append(f"💰 今日净流入:{summary['total_net']:.0f}亿")
    content_lines.append(f"📈 5日均值:{summary['ma5_net']:.0f}亿")
    
    payload = {
        "msg_type": "interactive",
        "card": {
            "header": {"title": {"tag": "plain_text", "content": "北向资金预警"}},
            "elements": [{"tag": "markdown", "content": "\n".join(content_lines)}]
        }
    }
    
    requests.post(webhook_url, json=payload, timeout=5)

3.2 邮件推送(备选方案)

import smtplib
from email.mime.text import MIMEText

def push_to_email(alerts: list, smtp_config: dict):
    """通过SMTP邮件推送"""
    if not alerts:
        return
    
    body = "北向资金监控报告\n" + "=" * 30 + "\n"
    for alert in alerts:
        body += f"{alert['level']} {alert['title']}: {alert['detail']}\n"
    
    msg = MIMEText(body, "plain", "utf-8")
    msg["Subject"] = f"北向资金预警 - {datetime.now().strftime('%Y-%m-%d')}"
    msg["From"] = smtp_config["from"]
    msg["To"] = smtp_config["to"]
    
    with smtplib.SMTP_SSL(smtp_config["host"], smtp_config["port"]) as server:
        server.login(smtp_config["user"], smtp_config["password"])
        server.send_message(msg)

四、主流程与定时任务

4.1 主函数

def main():
    """主流程:获取数据→检查预警→推送"""
    print(f"[{datetime.now().strftime('%H:%M:%S')}] 开始监控...")
    
    # 1. 获取数据
    df = fetch_northbound_flow(days=30)
    if df.empty:
        print("数据获取失败")
        return
    
    # 2. 数据清洗
    df = clean_data(df)
    
    # 3. 预警检查
    alerts = check_alerts(df)
    
    # 4. 推送
    if alerts:
        latest = df.iloc[-1]
        summary = {
            "date": latest["date"].strftime("%Y-%m-%d"),
            "total_net": latest["total_net"],
            "ma5_net": latest["ma5_net"]
        }
        # push_to_feishu(WEBHOOK_URL, alerts, summary)
        # push_to_email(alerts, SMTP_CONFIG)
        print(f"发现 {len(alerts)} 条预警")
    else:
        print("无预警,一切正常")

4.2 Cron定时任务

# 每天收盘后运行(15:30)
30 15 * * 1-5 cd /path/to/project && python3 main.py >> logs/$(date +\%Y\%m\%d).log 2>&1

# 午休时段(11:30)快速检查
30 11 * * 1-5 cd /path/to/project && python3 main.py --check-only >> logs/$(date +\%Y\%m\%d).log 2>&1

五、完整项目结构

northbound-monitor/
├── main.py              # 主入口
├── config.py            # 配置(API Key、Webhook等)
├── fetcher.py           # 数据获取
├── analyzer.py          # 分析与预警
├── notifier.py          # 推送模块
├── requirements.txt     # 依赖
├── logs/                # 日志目录
└── README.md            # 项目说明

六、部署建议

云服务器部署

# 1. 安装依赖
pip install requests pandas schedule

# 2. 配置环境变量
export FEISHU_WEBHOOK="https://open.feishu.cn/..."
export SMTP_HOST="smtp.qq.com"

# 3. 后台运行
nohup python3 main.py --daemon > /dev/null 2>&1 &

本地开发测试

git clone https://github.com/yourname/northbound-monitor
cd northbound-monitor
pip install -r requirements.txt
python3 main.py --dry-run

七、扩展思路

这个框架稍加改动就能用于:

  1. 南向资金监控 → 改一下API参数即可
  2. 行业资金流向 → 改为行业板块数据源
  3. 个股主力资金 → 换个API接口
  4. 实时行情监控 → 改为分钟级别轮询

总结

本文完整实现了一个A股北向资金自动监控系统,核心代码不足200行。要点:

  • 东方财富API无需认证,适合个人开发者
  • 预警阈值可配置,灵活适应不同策略
  • 支持多渠道推送(飞书/邮件均可)
  • 配合cron可完全无人值守运行

完整源码已开源,欢迎Star和PR。