用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
七、扩展思路
这个框架稍加改动就能用于:
- 南向资金监控 → 改一下API参数即可
- 行业资金流向 → 改为行业板块数据源
- 个股主力资金 → 换个API接口
- 实时行情监控 → 改为分钟级别轮询
总结
本文完整实现了一个A股北向资金自动监控系统,核心代码不足200行。要点:
- 东方财富API无需认证,适合个人开发者
- 预警阈值可配置,灵活适应不同策略
- 支持多渠道推送(飞书/邮件均可)
- 配合cron可完全无人值守运行
完整源码已开源,欢迎Star和PR。