尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

A06_聚宽_米筐notebook补外部数据:代码没对齐merge永远是空的

A06_聚宽_米筐notebook补外部数据:代码没对齐merge永远是空的 聚宽/米筐 notebook 补外部数据代码没对齐merge 永远是空的事实摘要量化平台的 notebook 装不了第三方 SDK但可以直接用requests发 HTTP 请求补外部数据。本文用/hs/list/all、/hs/pool/ztgc/{date}、/ht/lhb/mrxq三个纯 GET 接口演示重点解决一个最容易被忽略的问题同一个平台的不同接口会返回三种股票代码格式不做归一化merge结果永远是空表且不报错。文中代码格式转换器经 9 组用例离线自测全部通过。1. 平台数据再全也有拿不到的东西聚宽、米筐这类平台内置了行情和财务数据但总有覆盖不到的角落龙虎榜席位明细、每日涨停股池的连板梯队、交易提示日历、部分算好的因子值。这些平台的 notebook 有个共同限制你不能pip install一个新 SDK。所以「装个库调一下」这条路走不通只剩 HTTP 一条路——而这恰好是纯 GET 接口的主场requests是平台自带的。但真正会让人卡住半天的不是怎么发请求而是数据拿回来之后 join 不上。2. 真正的坑三种代码格式先看实测。同一天三个接口返回的dm字段长这样[ OK ] 股票列表 /hs/list/all dm 样例 000001.SZ [ OK ] 涨停股池 /hs/pool/ztgc dm 样例 sz000657 [ OK ] 龙虎榜 /ht/lhb/mrxq dm 样例 002202三个接口三种格式点分后缀、小写前缀、纯 6 位。而聚宽和米筐用的是第四种——000001.XSHE/600519.XSHG。于是下面这行看起来完全正常的代码df_mergeddf_platform.merge(df_lhb,left_oncode,right_ondm,howleft)df_platform[code]是000001.XSHEdf_lhb[dm]是002202。两边一个都对不上howleft又不会报错你得到一张右侧全是NaN的表然后开始怀疑是不是接口没数据。这是最难查的一类 bug不崩溃、不报警、结果看起来只是今天没有匹配到。3. 动手一个双向代码转换器思路是先把任意格式解析成(6位代码, 交易所)这个中间态再往任意目标格式转。importre _SH_PREFIX(60,68,58,51,11,50,56,20)defguess_exchange(code6):只有裸 6 位时按号段判断交易所。ifcode6.startswith((00,30,12,15,16,18,39)):returnSZifcode6.startswith(_SH_PREFIX):returnSHifcode6.startswith((43,83,87,92)):returnBJreturnSZdefparse_any(code):任意格式 - (6位代码, SH/SZ/BJ)cstr(code).strip().upper()if.inc:# 000001.SZ / 600519.XSHGhead,tailc.split(.,1)iftailXSHE:returnhead,SZiftailXSHG:returnhead,SHiftailin(SZ,SH,BJ):returnhead,tail mre.match(r^(SH|SZ|BJ)(\d{6})$,c)# sz000657ifm:returnm.group(2),m.group(1)ifre.match(r^\d{6}$,c):# 002202returnc,guess_exchange(c)raiseValueError(f无法识别的代码格式:{code!r})_SUFFIX{SH:XSHG,SZ:XSHE,BJ:XBEI}defto_joinquant(code):# - 600519.XSHG聚宽/米筐c6,exparse_any(code);returnf{c6}.{_SUFFIX[ex]}defto_dot(code):# - 600519.SH列表接口风格c6,exparse_any(code);returnf{c6}.{ex}defto_prefix(code):# - sh600519股池风格c6,exparse_any(code);returnf{ex.lower()}{c6}defto_bare(code):# - 600519行情/龙虎榜路径参数returnparse_any(code)[0]离线自测不需要 token 就能跑建议直接贴进 notebook 第一个 cell[PASS] 000001.SZ - 000001.XSHE [PASS] sz000657 - 000657.XSHE [PASS] sh603333 - 603333.XSHG [PASS] 002202 - 002202.XSHE [PASS] 600519 - 600519.XSHG [PASS] 688717 - 688717.XSHG [PASS] 600519.XSHG - 600519.XSHG [PASS] 000001.XSHE - 000001.XSHE [PASS] 830799 - 830799.XBEI 代码格式自测: 9/9 PASS4. 带缓存的取数notebook 场景的刚需notebook 的使用方式是反复重跑 cell。如果每次重跑都真发一次请求一天的额度很快就没了。加一层文件缓存几行就够importos,json,time,hashlib,requests BASEhttps://api.zhituapi.comTOKENos.environ.get(ZHITU_TOKEN)or你的智兔tokenCACHE_DIR,SLEEP,TIMEOUT,RETRY_cache,0.35,20,3def_cache_path(url,params):keyhashlib.md5((urljson.dumps(params,sort_keysTrue)).encode()).hexdigest()[:16]returnos.path.join(CACHE_DIR,key.json)defget_json(path,paramsNone,use_cacheTrue):paramsdict(paramsor{})url,cpBASEpath,_cache_path(BASEpath,params)ifuse_cacheandos.path.exists(cp):withopen(cp,encodingutf-8)asf:returnjson.load(f),Noneparams[token]TOKENforattemptinrange(1,RETRY1):try:rrequests.get(url,paramsparams,timeoutTIMEOUT)exceptrequests.RequestException:time.sleep(SLEEP*attempt*2)# 指数退避continue# 网关错误是 text/plain104 缺 token / 102 证书不存在ifjsonnotinr.headers.get(Content-Type,):returnNone,fHTTP{r.status_code}|{r.text.strip()}datar.json()# 未开通的模块返回 JSON 包装的错误体ifisinstance(data,dict)anddata.get(code)notin(None,200):returnNone,f业务错误{data.get(code)}:{data.get(msg)}ifuse_cache:os.makedirs(CACHE_DIR,exist_okTrue)withopen(cp,w,encodingutf-8)asf:json.dump(data,f,ensure_asciiFalse)time.sleep(SLEEP)returndata,NonereturnNone,重试耗尽注意缓存 key 里不要包含 token否则换证书就全部缓存失效。5. 运行结果对齐之后 merge 才有意义取当日涨停股池转成平台风格的order_book_idimportpandasaspd zt,errget_json(/hs/pool/ztgc/2026-08-12)dfpd.DataFrame(zt)df[order_book_id]df[dm].map(to_joinquant)extdf[[order_book_id,mc,p,zf,cje,lbc,fbt,zj]].rename(columns{mc:name,p:close,zf:pct_change,cje:turnover,lbc:board_count,fbt:first_seal_time,zj:seal_amount})真实输出2026-08-12A 股涨红order_book_id name close pct_change turnover board_count first_seal_time seal_amount 000657.XSHE 中钨高新 9.33 10.02 436073568.0 1 09:25:00 98243407 000715.XSHE 中兴商业 10.13 9.99 608770896.0 3 09:25:00 170175926 002403.XSHE 爱仕达 12.93 10.04 362526448.0 4 09:25:00 7605154 000017.XSHE 深中华A 5.41 9.96 83346703.0 2 09:30:06 86225164 603099.XSHG 长白山 29.18 9.99 1462451424.0 7 09:31:27 56022361 603877.XSHG 太平鸟 17.71 10.00 180538320.0 2 09:33:30 50028979和平台里的自选池 joinwatchlistpd.DataFrame({order_book_id:[000657.XSHE,000715.XSHE,600519.XSHG,603333.XSHG],my_group:[有色,商业,白酒,电缆],})mergedwatchlist.merge(ext,onorder_book_id,howleft)merged[今日涨停]merged[close].notna().map({True:是,False:否})order_book_id my_group name close pct_change 今日涨停 000657.XSHE 有色 中钨高新 9.33 10.02 是 000715.XSHE 商业 中兴商业 10.13 9.99 是 600519.XSHG 白酒 NaN NaN NaN 否 603333.XSHG 电缆 尚纬股份 6.67 10.07 是 自选 4 只中有 3 只在当日涨停股池里这才是我们要的结果。如果不做归一化这张表的右半边会全是NaN。缓存效果命中缓存耗时 0.0011 秒缓存目录 _cache/以上仅为公开数据的取数与合并演示不构成投资建议。6. 坑与注意事项#坑说明与对策1代码格式三选一列表接口000001.SZ、股池sz000657、龙虎榜002202。跨接口 join 前先归一化否则静默产生空表。2字段表和实测有出入股池的hy所属行业文档里有、实测不返回。一律row.get(k)不要row[k]。3错误不是 JSON104:缺少token参数/102:Licence证书(xxx)不存在以text/plain返回先判Content-Type。4模块未开通是 JSON 错误体形如{code:403,msg:...未开通...}和网关错误不是一套两种都要判。5北交所别漏43/83/87/92开头是北交所聚宽后缀是.XBEI按沪深两分法会判错。6缓存 key 别带 token否则换证书缓存全废。7平台外网策略部分平台对 notebook 出网有限制或需白名单先用一个最小请求验证连通性再写正式逻辑。8限频要留余量包量版 300 次/分。批量循环时固定sleep(0.35)失败用指数退避而不是死循环重试。7. 小结平台 notebook 装不了 SDK但requests一直都在——纯 GET 接口正好不需要装任何东西。补外部数据真正的门槛不是 HTTP是代码格式对齐。先写parse_any()再谈 merge。归一化函数是纯字符串逻辑可以离线自测建议贴进 notebook 第一个 cell 并保留断言。加一层不含 token 的文件缓存重跑 cell 不再消耗额度。下一篇预告《集合竞价数据怎么用开盘异动的量化描述》——从竞价阶段的量价特征出发看它和当天走势的关系。动手试试本文三个接口用免费证书都能跑通200 次/日、期限不限。 领取免费证书本文所有数据来自公开行情接口的真实返回仅用于技术演示不构成投资建议。
返回列表