Back to skills
extension
Category: Data & AnalyticsNo API key required

养基宝基金查询

通过养基宝 API 批量查询用户个人基金持仓数据(净值、估值、涨跌、板块行情)。当用户说"查我的基金"、"查持仓"、"基金净值"、"养基宝"、"基金涨跌"、"我的基金怎么样了"时触发。此 skill 直接调用养基宝后端接口,数据比通用金融数据源快 1-2 天且包含盘中估值。

personAuthor: user_3991c844hubcommunity

养基宝基金查询(完整版)

通过养基宝 API 实现完整的基金持仓管理:微信扫码登录 → 获取个人持仓 → 净值估算 → 数据分析。

触发的两套数据源

养基宝有两套 API,按需求选择:

数据源 A: 公网行情(无需登录)⚠️ 已不可用

  • Base URL: https://app-api.yangjibao.com(2026-08-04 实测 404,接口已下线)
  • 用途: 基金净值、指数行情、板块排行、历史净值
  • 脚本: scripts/yjb_market.py 从未实现——本 skill 只维护数据源 B(个人持仓)
  • 替代: 基金净值/行情用天天基金 pingzhongdata 或东财接口(见财富指挥官框架 wc_common.py)

数据源 B: 个人持仓(需微信扫码登录)

  • Base URL: http://browser-plug-api.yangjibao.com
  • 用途: 个人持仓数据、账户汇总、收益分析
  • 认证: 微信扫码 → 获取 Token → 签名验证
  • 脚本: scripts/yjb_login.py(登录)+ scripts/yjb_fetch.py(拉取数据)

多用户支持

每个用户有独立的 token 文件(~/.yjb_token_{昵称}.json),数据完全隔离,不会串。

yjb_login.py --user 张三     # 为朋友添加账户(生成二维码让朋友扫)
yjb_login.py --list           # 列出所有已登录用户
yjb_login.py --switch 张三    # 切换到朋友的账户
yjb_login.py                  # 登录/查看活跃用户

yjb_fetch.py                  # 查活跃用户持仓
yjb_fetch.py --user 张三      # 查指定用户持仓
yjb_fetch.py --list           # 列出所有用户

使用场景:

  • 查我的基金持仓 → 自动使用活跃用户
  • 帮张三查他的持仓 → 先用 --user 张三 查,若未登录则扫友码
  • 切到张三--switch 张三,后续默认查张三

一、个人持仓数据(数据源 B)

1.1 认证机制

所有 authenticated API 需要 3 个自定义 Header:

| Header | 说明 | |--------|------| | Request-Time | Unix 时间戳 | | Request-Sign | MD5 签名 | | Authorization | 登录后的 Token |

签名算法:

sign = MD5("" + path + token + timestamp + SECRET)
SECRET = "YxmKSrQR4uoJ5lOoWIhcbd7SlUEh9OOc"

其中 path 为 URL 路径(不含 query string)。

注意: 不带签名 header 的请求会返回 404(而非 401),这是服务器设计行为。

1.2 QR 码登录流程(多用户 + 全自动)

⚠️ 关键规则:展示 QR 码后必须立即开始自动轮询,不要等用户说「已扫码」!

多用户模式:每个用户登录后自动保存为独立 token 文件(~/.yjb_token_{昵称}.json),微信昵称作为用户名。活跃用户记录在 ~/.yjb_active_user

使用 scripts/yjb_login.py 一键完成:

  1. 获取 QR 码:

    GET http://browser-plug-api.yangjibao.com/qr_code
    

    返回 {id: "loginQrIdxxx", url: "http://weixin.qq.com/q/xxx"}

  2. 展示 QR 码给用户扫描: 使用 show_widget 生成 SVG 二维码(推荐),或提供在线图片链接: https://api.qrserver.com/v1/create-qr-code/?size=300x300&data={qr_url}

    同时用文本告知用户:「请用微信扫描二维码,无需手动告知,我会自动检测」

  3. 自动轮询登录状态(每 2 秒一次,最多 3 分钟):

    GET http://browser-plug-api.yangjibao.com/qr_code_state/{qr_id}
    
    • state=1 → 未扫码,继续轮询,打印进度点 .
    • state=2 → 已扫码,提取 token,自动停止轮询,立即进入下一步
    • 超时 → 提示用户重新发起
  4. 扫码成功 → 自动保存 → 自动继续: 收到 token 后自动以微信昵称为用户名保存到 ~/.yjb_token_{昵称}.json,并设为活跃用户。无需等待用户指令,立即继续执行数据查询

1.3 核心 API 接口(需认证)

| 路径 | 说明 | 返回关键字段 | |------|------|------| | /user_account | 账户列表 | list[{id, title, count}] | | /account_collect | 账户汇总 | account_data[{hold_cost, today_income, today_income_rate}] | | /fund_hold?account_id={id} | 账户持仓 | [{fund_id, code, short_name, money, hold_earn, hold_share, hold_cost}] | | /index_data | 指数行情 | [{name, v(price), dir(change%)}] | | /income_data?collect=true&date_type=day | 收益数据 | {income, income_rate, ranking} | | /income_line_data?collect=true&date_type=day | 收益走势 | {line_list[{time, rate}]} | | /notice | 系统公告 | {notice_list} | | /search_fund?keyword=xxx | 搜索基金 | [{fund_id, short_name, code}] |

1.4 持仓数据字段说明

| 字段 | 含义 | |------|------| | fund_id | 基金内部 ID | | code | 基金交易代码(6位) | | short_name | 基金名称 | | money | 当前市值(元) | | hold_earn | 持仓盈亏(元) | | hold_share | 持有份额 | | hold_cost | 持仓成本单价 | | cost_money | 投入本金 | | hold_day | 首次买入日期 | | category | 基金类型 | | market_type | 交易市场 |

1.5 使用流程(多用户 + 全程自动)

首次使用 / 添加新用户:

  1. 说「添加张三的持仓」→ 执行 yjb_login.py --user 张三 → 弹出二维码给张三扫
  2. 扫完后 token 自动保存为 ~/.yjb_token_张三.json,不覆盖你的数据

日常查询:

  • 查我的基金yjb_fetch.py(默认活跃用户)
  • 查张三的持仓yjb_fetch.py --user 张三
  • 切到李四yjb_login.py --switch 李四

Token 过期时:

  • 自动检测到 401 后重新弹出当前用户的二维码

重要: 整个流程是连续的——展示二维码后不要停下来等用户回复「扫好了」,轮询会自动检测。

1.6 数据分析与呈现

获取持仓数据后,按以下格式汇总展示:

  1. 账户汇总:总资产、今日收益、收益率
  2. 指数行情:A股/港股/美股 12 个主要指数
  3. 持仓明细表:基金名称、代码、市值、盈亏(🔴🟢标识)、份额、成本
  4. 汇总统计:总市值、总盈亏

二、公网行情数据(数据源 A)

2.1 批量基金净值(无需登录)

POST https://app-api.yangjibao.com/market/v1/fund/batch
Content-Type: application/json
User-Agent: YJB/2.0.4
Body: {"funds": [{"fund_id": 1359, "data_source": "1"}, ...]}

基金 ID 映射见 references/fund-mapping.md

2.2 返回字段

nv_info: dwjz(净值), rzzl(日涨幅), jzrq(净值日), vgszzl(估值涨幅), true_valuation_date(真实估值日) 其他: short_name, code, category, year_increase_rate, sector_info.name/ratio, market_type, heavy_position_info

2.3 历史净值 & 指数

GET https://app-api.yangjibao.com/market/v1/fund-nav/fund-history-nav?fund_id=X&page=1&per_page=30
GET https://app-api.yangjibao.com/market/v1/quote/index-data
GET https://app-api.yangjibao.com/market/v1/market-ranking/list
GET https://app-api.yangjibao.com/market/v1/fund/relation-gz-data?id=X&type=4
GET https://wx.yangjibao.com/wxapi/day_info

三、净值日期规则

  1. A股基金: 净值日=最近交易日,当日 19:00-22:00 发布
  2. QDII 基金: 净值滞后 2-3 个交易日,以 true_valuation_date 为准
  3. 估值: vgsz/vgszzl 为当日盘中估值,A股收盘后更新
  4. 建议: 20:00 后查询可获取完整当日净值

四、内联登录代码(AI 直接执行,无需调用脚本)

当需要登录时,可直接执行以下 Python(已在轮询中内置自动检测,无需等待用户说「扫好了」):

import requests, hashlib, time, json, os, sys

SECRET = 'YxmKSrQR4uoJ5lOoWIhcbd7SlUEh9OOc'
BASE = 'http://browser-plug-api.yangjibao.com'
TOKEN_FILE = os.path.expanduser('~/.yjb_token.json')

def make_headers(path, token=''):
    sign_path = path.split('?')[0]
    t = int(time.time())
    s = hashlib.md5(('' + sign_path + (token or '') + str(t) + SECRET).encode()).hexdigest()
    return {'Request-Time': str(t), 'Request-Sign': s, 'Authorization': token}

# 1. 获取 QR 码
r = requests.get(f'{BASE}/qr_code', headers=make_headers('/qr_code'), timeout=10)
data = r.json()
qr_id = data['data']['id']
qr_url = data['data']['url']
print(f'QR_IMAGE: https://api.qrserver.com/v1/create-qr-code/?size=300x300&data={qr_url}')
# 同时用 show_widget 生成 SVG 二维码(inline HTML with qr_url)

# 2. 自动轮询(每 2 秒一次,共 90 次 / 3 分钟)—— 全程自动,不需要用户告知扫码
for i in range(90):
    time.sleep(2)
    r = requests.get(f'{BASE}/qr_code_state/{qr_id}',
                     headers=make_headers(f'/qr_code_state/{qr_id}'), timeout=10)
    sd = r.json()
    state = str(sd.get('data', {}).get('state', '0'))
    token = sd.get('data', {}).get('token', '')
    if state == '2' and token:
        nickname = sd.get('data', {}).get('nickname', '')
        with open(TOKEN_FILE, 'w') as f:
            json.dump({'token': token, 'timestamp': int(time.time()), 'nickname': nickname}, f, ensure_ascii=False)
        print(f'LOGIN_OK: {nickname}')
        break
    if i >= 89:
        print('LOGIN_TIMEOUT')
        sys.exit(1)

# 3. Token 已自动保存,立即继续查询(不要停下来等用户消息!)

⚠️ 执行要点:

  • 展示二维码后立即启动轮询循环,不要在中间停下来等用户消息
  • 轮询检测到 state=2自动保存 token 并继续后续查询
  • 整个过程用户只需扫一次码,其余全自动

五、已知问题与排错

| 问题 | 原因 | 解决 | |------|------|------| | API 返回 404 | 缺少签名 Header | 确保 Request-Time、Request-Sign、Authorization 三个 Header 齐全 | | Token 401 未授权 | Token 过期 | 重新执行登录流程 | | 签名错误 | 签名 path 含 query string | 签名时 path 去掉 ? 及之后部分 | | 扫码后不自动识别 | AI 没有启动轮询 | 展示二维码后立即轮询,不等用户回复 | | 会串朋友的数据吗 | 单 token 文件会覆盖 | 已改造为多用户模式,每人独立 ~/.yjb_token_{昵称}.json |