【零依赖量化数据实战 #11】ETF 历史 K 线与均线:4 个 URL 做技术面回看

📅 2026/8/26 1:30:11
【零依赖量化数据实战 #11】ETF 历史 K 线与均线:4 个 URL 做技术面回看
【场内基金 ETF #11】ETF 历史 K 线与均线4 个 URL 做技术面回看系列《零依赖量化数据实战》零依赖 · 纯 GET · 不 import 任何 SDK适用想做 ETF 技术面分析、K 线落地、均线偏离监控不想装库或对接多个数据源的开发者你将得到什么4 个「ETF 历史 K 线/均线」端点的路径、返回字段和语义历史K线 / 最新K线 / 历史MA / 最新MA照公开文档核对过的不是猜的一段kline_with_ma(code)把历史 K 线 历史 MA 拉齐算出最后一日涨跌幅与收盘价相对均线的偏离字段名容错写法候选键命中对字段名不敏感、对形态list / dict不敏感完整可复制运行代码把你的token换成真实证书即可直接跑一、四个端点一张语义表「技术面回看」拆成 4 个端点路径前缀统一/jh/hq/且分时级别是路径参数不是查询参数GET https://api.zhituapi.com/jh/hq/lskx/{code}/{level} 历史 K 线日/周/月… GET https://api.zhituapi.com/jh/hq/zxkx/{code}/{level} 最新 K 线 GET https://api.zhituapi.com/jh/hq/lsma/{code}/{level} 历史 MA移动均线已算好 GET https://api.zhituapi.com/jh/hq/zxma/{code}/{level} 最新 MA鉴权统一?token你的token。{code}是基金代码{level}是分时级别d日w周m月具体以文档示例为准。lskx/zxkx返回 K 线序列每根含开高低收lsma/zxma返回对应的均线序列。两种形态代码都要吃得下。一个实际用法先lskx拿历史 K 线 → 用lsma拿现成均线 → 算「收盘价 − 均线」的偏离偏离为正说明价格在均线上方偏强为负则偏弱。这就是技术面回看。代码形态提醒接 #10 坑 #4这些{code}用基金代码如510300{level}是路径参数必须拼进 URL/jh/hq/lskx/510300/d不能写成?leveld。二、字段名不固定用候选键命中K 线/均线的返回字段名可能因数据源更新而变化。与其硬编码字段名改了就全崩不如用候选键列表命中抽取def_hit_key(d,candidates):从字典中按候选键名列表命中第一个存在的键。forkincandidates:ifkind:returnkreturnNonedef_to_float(v):把可能是字符串/数字/None 的值安全转 float转不了返回 None。try:ifvisNone:returnNonereturnfloat(v)except(TypeError,ValueError):returnNonedefsummarize_kline(name,data):从 K 线/均线中抽取关键字段做汇总对字段名不敏感、对形态不敏感。ifdataisNone:returnf{name}: 无数据ifisinstance(data,list):ifnotdata:returnf{name}: 0 条firstdata[0]ifisinstance(data[0],dict)else{}date_key_hit_key(first,[date,rq,day,time,rqstr])close_key_hit_key(first,[close,c,last,dwjz,nav,price,closeprice])parts[f{name}:{len(data)}条]ifdate_key:parts.append(f首日{first.get(date_key)})ifclose_key:parts.append(f收盘键{first.get(close_key)})return | .join(parts)ifisinstance(data,dict):returnf{name}: 聚合对象键{list(data.keys())[:6]}returnf{name}:{type(data).__name__}这样就算数据源把close改成dwjz代码不用动。命不中也不报错——只是那行汇总少一个字段。三、技术面回看K 线 均线算偏离核心不是「把四个接口都调通」而是把 K 线与均线归一后算出能用的指标。我们关心两件事最后一日涨跌幅末日收盘 − 前日收盘/ 前日收盘收盘价相对均线的偏离末日收盘 − 均线值/ 均线值importsys,timeimportrequests TOKEN你的token# ← 换成你的真实 tokenBASEhttps://api.zhituapi.comKLINE_ENDPOINTS{lskx:(/jh/hq/lskx/{code}/{level},历史 K 线),zxkx:(/jh/hq/zxkx/{code}/{level},最新 K 线),lsma:(/jh/hq/lsma/{code}/{level},历史 MA),zxma:(/jh/hq/zxma/{code}/{level},最新 MA),}deffetch(name,code,leveld,tokenTOKEN,timeout15):拉一个 K 线/均线端点返回 (data, err)。path_tmpl,_KLINE_ENDPOINTS[name]urlf{BASE}{path_tmpl.format(codecode,levellevel)}try:rrequests.get(url,params{token:token},timeouttimeout)exceptrequests.RequestExceptionase:returnNone,f网络异常{e}ifr.status_code!200:returnNone,f{r.status_code}{r.text.strip()[:140]}try:payloadr.json()exceptValueError:returnNone,f非 JSON 返回{r.text[:140]}ifisinstance(payload,dict):detailpayload.get(detail)orpayload.get(error)returnNone,f业务错误{detailorlist(payload)[:6]}returnpayload,Nonedeflast_return_and_dev(kline,ma):从 K 线算最后一日涨跌幅从 K 线MA 算收盘价相对均线的偏离。rows[rforrin(klineor[])ifisinstance(r,dict)]ck[close,c,last,dwjz,nav,price,closeprice]ifnotrows:returnNone,Nonelastrows[-1]prevrows[-2]iflen(rows)2elseNoneclose_k_hit_key(last,ck)close_to_float(last.get(close_k))ifclose_kelseNonedaily_retNoneifprevandclose_k:pclose_to_float(prev.get(close_k))ifpclose:daily_retround((close-pclose)/pclose*100,2)devNonema_rows[rforrin(maor[])ifisinstance(r,dict)]ifma_rowsandcloseisnotNone:ma_lastma_rows[-1]ma_val_k_hit_key(ma_last,[ma,ma5,ma10,ma20,value,avg,mean])ma_val_to_float(ma_last.get(ma_val_k))ifma_val_kelseNoneifma_val:devround((close-ma_val)/ma_val*100,2)returndaily_ret,devdefkline_with_ma(code,leveld,tokenTOKEN,sleep0.2):拉历史 K 线 历史 MA合成「收盘价 vs 均线」的技术面快照。iftoken你的token:print([演示] TOKEN 为占位符下面请求会返回错误码契约请换成真实 token 后再跑。)kline,kerrfetch(lskx,code,level,token)ma,maerrfetch(lsma,code,level,token)ifkerr:print(f lskx: 暂不可用{kerr})else:print(summarize_kline(lskx,kline))ifmaerr:print(f lsma: 暂不可用{maerr})else:print(summarize_kline(lsma,ma))time.sleep(sleep)returnkline,masleep0.2是限频保护——2 个端点 0.2 秒间隔 ≈ 0.4 秒。要回看多只基金把kline_with_ma套一层循环外面再撑一个更大的间隔即可。四、代码自验结果离线自测 6 项全 PASS真实输出不联网selftest PASS: _hit_key 命中 / 列表汇总 / 聚合对象 / 空数据兜底 / 涨跌幅与偏离 / 字段名不敏感 共 6 项其中「涨跌幅与偏离」用的是合成数据8/19 收 3.80、8/20 收 3.90、8/21 收 4.00均线 3.90断言最后一日涨跌幅 (4.00−3.90)/3.90 ≈ 2.56%、偏离 (4.00−3.90)/3.90 ≈ 2.56%——这些是逻辑自验用的假数不是真实行情。联网跑占位 token真实输出[演示] TOKEN 为占位符下面请求会返回错误码契约请换成真实 token 后再跑。 lskx: 暂不可用404 102:Licence证书(你的token)不存在 lsma: 暂不可用404 102:Licence证书(你的token)不存在两个端点契约一致单端点失败不影响整体流程、程序友好退出。本文未编造任何 K 线/均线数值——换成覆盖该接口的正式证书后重跑即可打印真实技术面快照。五、坑与注意事项坑 #1102 不代表路径写对了。鉴权发生在路由匹配之前。路径故意写错配无效 token同样返回102。路径合法性只能靠客户端按白名单自查——本文 4 个路径是照公开文档核对的。实测 HTTP 状态码是404而不是403重点是看到102:Licence证书...就知道是证书问题。坑 #2{level}是路径参数不是查询参数。必须拼成/jh/hq/lskx/510300/d写?leveld会因缺路径参数而拿不到数据。这是本篇最容易踩的坑。坑 #3K 线序列顺序要确认。不同数据源返回的 K 线可能是「时间正序」也可能是「倒序」。算「最后一日涨跌幅」前先确认末位是最近一天必要时sorted一下否则会把最老一天当最新。坑 #4lskx历史和zxkx最新别混。lskx是整段历史zxkx往往只给最近一根要算涨跌幅用lskx足够zxkx适合做「盘中最新一根」的轻量刷新。小结与下篇预告这篇你拿到了 4 个 ETF 历史 K 线/均线端点历史K线 / 最新K线 / 历史MA / 最新MA、字段名容错抽取写法、以及一个把 K 线均线合成「技术面快照」的模板算出最后一日涨跌幅与均线偏离顺带避开了 102 误判、level 路径参数、序列顺序、lskx/zxkx 混淆四个坑。下一篇#12讲ETF 同类排名、规模与分红——用/js/pm/kfpm/kfsjj_gpxjj_zsx业绩排名/js/gm/kfgm/kfsjj_gpxjj_zsx规模/js/jf/kffh/kfsjj_gpxjj_zsx分红做一只基金的「选基三维度」对比把技术面升级成基本面筛选。免责声明本文仅演示公开数据接口的用法所有代码示例均以占位 token 自验未含任何真实 K 线/均线数据文中合成数据仅为逻辑自验用途不构成投资建议亦不承诺收益。投资决策请基于你自己的判断与风险承受力。