全部
文章&策略
学习干货
问答
官方
用户头像sh_***174w0d
2026-10-15 发布
为什么绝大多数人在股市里都在“凭实力亏钱”? 为什么大家都在炒股,但真正能够实现长期稳定盈利的,永远只是极少数人? 绝大多数散户在市场里痛苦挣扎、频频割肉,绝非不够努力,而是陷入了凭直觉交易的迷局。“凭实力亏钱”的扎心真相背后,是人性难以克服的贪婪与恐惧。 其实,股市里的盈利逻辑极其纯粹,从来不需要十八般武艺样样精通。能够在这个残酷竞技场中真正实现长期盈利的,总结起来只有6种特定类型的“狠角色”。而绝大多数陷入巨额亏损的投资者,往往是因为盲目跟风,落入了最可怕的第7种人的陷阱。 看清这7种人的行为模式与心理博弈,你就能一眼看透股市的盈利本质,找准属于你自己的生存之道。 股市长期盈利的6种“狠角色” 1.猎手型:极度忍耐,一年只做一两波的“空仓狠人” 第一种人拥有常人难以企及的定力。他们可以常年保持空仓,忍受市场的日常波动与诱惑,一年之中往往只出手一两次(只做一两波行情)。一旦达成盈利目标,赚了就走,绝不恋战。 对于普通散户而言,“常年空仓”是极具折磨性的,这背后最大的心理魔鬼叫 FOMO**(害怕错过)**——看着别人赚钱,手痒难耐、报复性建仓是绝大多数人亏损的起点。但在顶级猎手眼里,现金就是最致命的武器。他们避开了90%无意义的无序波动,用极度的忍耐去换取确定性最高的致命一击。 极度忍耐,赚了就走,绝不恋战。 2.陪伴型:拿时间换收益的“长线玩家” 第二种人是坚定的长线持有者。他们持股时间长达三五年,在持股期间完全不理会短期的涨跌波动,心如止水。 这类交易者深刻理解复利与周期的力量。他们通过主动屏蔽市场的短期噪音,克服了对账面浮亏的恐惧与对小利即满的贪婪。他们选择以时间为杠杆,去换取确定性的长期企业价值成长,以此轻松战胜市场短期的无序与不确定性。 3.匠人型:把成本做成负数的“做T高手” 第三种人极其专注。他们绝不贪多,只指定一两支股票进行深耕,通过持续不断的高抛低吸,一步一步地将持仓成本一点点做低。 日积月累之下,他们甚至能够把持仓成本做到负数。当持仓成本被降为负数时,交易者便获得了绝对的心理免疫——市场的任何剧烈甩洗和暴跌都再也无法引发任何恐惧,股票彻底沦为了无风险的“现金流印钞机”。这种策略成功的关键,在于对单一标的股性有着极致了解与专注。 4.刀锋型:只做主线龙头的“纪律选手” 第四种人是敏锐的板块龙头玩家。他们只做市场的主线龙头股票,绝不把精力与资金浪费在毫无辨识度的跟风杂毛股上。 他们的核心优势在于纪律严明、出手极快。凭借对市场情绪与资金主线的敏锐洞察,一旦信号确认即迅速出击,趋势破位则果断割肉,绝不拖泥带花。 5.机器型:无情执行信号的“系统交易者” 第五种人将自己训练成了无情的交易机器。他们只严格按照自己的交易信号操作,买点不到,即使股票涨停也绝不关注;而一旦卖点触发,像机器一样无情扣动扳机。 “买点不到,涨停都不看”——这需要极其强大的心理定力。普通交易者往往因贪婪而盲目追高涨停股,而系统交易者明白,未经信号确认的涨停蕴含着无法控制的尾部风险。他们彻底摒弃了人性的贪婪与恐惧,做到了真正的“人机合一”。 6.智者型:提前离场的“知足聪明人” 第六种人懂得适可而止。他们只吃行情最安全的中段(“鱼身”),绝不上当去贪图尾声的最后一点利润(“鱼尾”)。一旦察觉行情进入尾声,便提前离场保住胜利果实。 需要特别强调的是:尤其是第六种,大多数人根本做不到。人性的贪婪会疯狂暗示散户“还能再涨一点”,最终往往在狂欢的顶峰(鱼尾)沦为接盘侠。懂得知足止盈、甘愿放弃最后一个铜板的人,才掌握了防范市场剧烈回撤的终极武器。 警惕!最可怕的第7种人:市场的“送钱童子” 看清前6种盈利者后,更需要时刻警惕的是最可怕的第7种人。 这种人的典型特征是:什么都懂一点,但什么都不精通。他们看似满腹理论,实则陷入了致命的战术矛盾——在实际操作中,他们长线拿不住,短线舍不得;战术天天换,今天学龙头追高,明天学抄底接飞刀,后天又开始跟着做****T。 这种“既要龙头动能,又要抄底安全”的逻辑分裂,给他们带来了致命的虚假安全感。因为没有明确的交易主线与严密的交易体系,他们做出的每一次决策都是对人性的妥协。前面6种人赚的都是符合自己逻辑的钱,而这第7种人,因其系统性混乱,彻底成为了市场上给前6种人提供流动性的“筹码提供者”与“送钱童子”。 前面六种人赚的是自己的钱,第七种人专门给前面六种人送钱。股市里不是比谁赚得快,而是比谁活得久。 在股市中,你究竟是哪一种人? 在股市这个残酷的竞技场中,盈利的关键从来不是博采众长、频繁更换招式,而是找到适合自己的定位,建立清晰的交易逻辑,并贯彻铁一般的纪律。无论是选择做极度忍耐的冷酷猎手,还是坚守时间的陪伴玩家,唯有摒弃杂念、坚持一套行之有效的方法,才能在市场中长久生存。
浏览6
评论0
收藏0
用户头像9点半量化
2026-10-15 发布
交易的艺术在于“等待” 在金融市场中,绝大多数交易者都深陷于同一个噩梦:见涨就追,见跌就割,操作越频繁,账户缩水越严重。这种因缺乏耐心而导致的冲动交易,是吞噬本金的根源。 真正的交易高手,绝不是时刻在市场里频繁进出的“勤劳蜂”,而是手握猎枪、极具定力的“潜伏者”。市场的本质不是预测未来,而是一场关于规则与克制的博弈——未出现确定性信号前,绝不上弹;信号触发之时,果断出击。 “这五种模式至少看七遍” 这句警醒,道出了交易系统中最为核心的五种盈利模式与入场节点。深刻领悟并融入血脉,是你摆脱散户思维、构建成熟交易系统的第一步。 模式一:做趋势,等的是回调 在主升或主降趋势中,顺势而为是获利的基础,但这绝不意味着看到价格飙升就能盲目追高。 散户往往在趋势拉升的最高点因贪婪而急忙抢筹,结果买在短期顶部,稍有风吹草动便在恐慌中割肉出局。相比之下,高手的做趋势,等的是回调。 当价格在主干趋势中出现合理的回踩与整理时,市场正在完成筹码换手与风险释放。等待回调企稳后再行入场,不仅能重新验证下方关键支撑位的有效性,更大幅压低了止损成本,从而获得极高的风险收益比。 等待二次启动的确认,才是顺势交易中兼具安全性与爆发力的最佳时机。 💡 导师实战口诀:无回调不顺势,宁可错过高位,绝不盲目追高。 模式二:做突破,等的是回踩 突破形态往往孕育着强劲的单边行情,但市场中同样充斥着大量主力资金精心制造的假突破陷阱。 如果在价格刚刚穿透阻力位的瞬间凭热血追入,极易被假突破挂在阶段性的“天花板”上。因此,成熟交易者的做突破,等的是回踩。 回踩的深层逻辑,在于验证原有的阻力位是否已经成功转化为强有力的支撑位。只有当价格回踩该位置且抛压被彻底消化、支撑重新确认时,突破的有效性才算真正立足。 耐心等待回踩企稳后再介入,虽然放弃了极小一段初始涨幅,换来的却是胜率与确定性的质变。 💡 导师实战口诀:突破多诱多,回踩定乾坤;支撑不确认,决不出重手。 模式三:做反弹,等的是放量 面对连绵下挫的行情,盲目抄反弹无异于徒手接“下坠的飞刀”。 无量反弹不是给散户抄底的福利,而是主力资金诱多的陷阱。缺乏资金关注的缩水反弹,仅仅是下跌动能的暂时衰竭,随时可能重新向下砸出新低。 做反弹的核心铁律,等的是放量。 成交量是市场最真实的语言。放量意味着有规模化的主力资金开始逆势承接,市场筹码完成了高效的筹码换手。只有看到明确的放量信号,超跌反弹才具备资金面上的可持续性与参与价值。 💡 导师实战口诀:无量反弹皆是空,放量确认方建仓。 模式四:做震荡,等的是高点 无明确方向的震荡箱体,是消耗交易者本金与心态的“绞肉机”。 散户最容易在箱体中间的中轴位置凭感觉下注,结果价格上下摇摆,被两头刮蹭、频繁止损。高手的做震荡,等的是高点——即坚决恪守边界原则。 需要特别说明的是,“等高点”绝非让交易者在箱体顶部去追买,而是指耐心等待价格运行至区间上轨或核心阻力区域时,执行逢高减仓或布局高抛****/****做空的策略。 坚决不在无秩序的中轴区域下注,静待价格触碰上限边界再行决策,才能彻底杜绝无谓的本金磨损。 💡 导师实战口诀:震荡不赌中轴线,高抛低吸守边界。 模式五:做抄底,等的是大面积情绪崩盘 抄底是所有交易行为中风险最高的一种,仅凭指标超卖或主观“跌透了”的感觉去抄底,极其危险。 做抄底有着极为严苛的前提条件,等的是大面积情绪崩盘。请注意,这里的核心修饰词是大面积。 局部的下挫或个股的下跌,往往只是阴跌洗盘的开始,盲目介入只会买在半山腰。唯有当恐慌蔓延至整个市场,出现大面积情绪崩盘(如板块批量跌停、绝望抛盘涌出、流动性短暂缺失),市场经历彻底的筹码出清与情绪宣泄后,真正的阶段性底部才会坚固浮现。 未见大面积情绪崩盘,绝不轻易出手接刀。 💡 导师实战口诀:局部回调莫接刀,大面积崩盘方显底。 从冲动到克制,你的交易系统建好了吗? 交易是一场反人性的自我克制。 无论是做趋势、做突破、做反弹、做震荡还是做抄底,这五种模式的共同本质,都是要求交易者放弃主观预测,将重点放在制定规则与耐心“等待”触发条件上。条件不满足,哪怕盘面再诱人,也绝不出手。 在这五种模式中,你最容易在哪一种的“等待”上失去耐心?又在哪一种模式里踩过“假信号”的坑?欢迎在评论区留下你的实战体会。
浏览11
评论0
收藏0
用户头像sh_***3272xs
2026-10-15 发布
用 TradingView 开源的 Lightweight Charts 画腾讯10月14日的日K,图上显示的是10月13日。图表库没错,数据也没错,错在喂数据的那一步。我用真实行情把同一组数据喂了两遍,挑出跨市场K线最容易画错的10个地方,文末附一段能直接复制的喂数代码。 10月9日,香港证监会透露,香港正在研究延长证券交易时段,港交所第四季度会就现货市场延时发讨论文件。再过两周多,11月1日,美股换冬令时,北京时间开盘从21:30推迟到22:30。 交易时间要变了。做行情App的人该先问自己一句:K线的时间轴是写死的还是算出来的? 我先拿腾讯试了一下。用 TradingView 开源的 Lightweight Charts 画日K,接口返回的数据原样喂进去: 10月14日的K线,图上写着13日,整条时间轴都早了一天。 做单一市场,这类错一两处;做A股、港股、美股一起的跨市场App,它们会一起冒出来。 图表库只负责画,画得对不对取决于你怎么喂数据。 读完你能带走:10个最常见的画错点和修法,一段约50行的喂数代码,一张上线前体检表。 一、图表库只管画,不懂行情 Lightweight Charts 免费、轻量,几十行代码就能画出专业样式的K线,很多行情App和交易工具都在用。 但它不知道你的时间戳属于哪个市场,不知道国内习惯红涨绿跌,不知道这只股票上个月除过权,也不知道A股成交量的“1”是一手。这些都得在数据进图表之前处理好,我把这一步叫“喂数层”。 下面每一条都是同一组真实数据喂两遍的对比:一遍原样喂,一遍先过喂数层。 二、首页对比图 ① 腾讯10月14日的K线,标成了13日 行情接口的日K时间戳,通常标在交易所当地零点。腾讯10月14日这根是北京时间14日0点,换成 UTC 是13日16点。图表库只按 UTC 显示时间,所以标成13日。用户电脑设成北京时间也没用。 用户截图发群里一句“你们日期都错了”,比什么 bug 报告都伤口碑。 修法:日K别喂时间戳,换成当地日期字符串 '2026-10-14' 再喂。 ② 三个市场放进一张图,同一天对不上 腾讯标在北京零点,苹果标在纽约零点,比特币标在 UTC 零点。放在同一条时间轴上,“10月14日”变成了三个点,腾讯那根还掉进了13日。 分钟K也一样。我取的15分钟K里,寒武纪第一根标09:45,腾讯第一根标09:30:A股标的是结束时刻,港股标的是开始时刻。两边各有一根“09:45”,管的是相邻的两段。 做联动分析、相关性、配对交易,最怕的就是这种错位。 修法:每个市场先换成各自的当地交易日,再对齐。另外得有人拍板:美股10月14日那一场在北京是14日晚上到15日凌晨,你的首页算它哪一天? 三、个股K线 ③ 涨是绿的,跌是红的 图表库默认绿涨红跌,这是欧美习惯。国内用户第一眼就会看反。 修法:按用户地区设涨跌色,K线和成交量柱一起改。 ④ 寒武纪除权那天,像是暴跌了36.7% 5月8日是寒武纪除权日。前一天收盘1,868元,当天收盘1,182.53元,不复权的图上断开一个大缺口。 前复权后,前一天收盘折算成1,252.68元,当天其实只跌了5.6%。不复权的话,均线、指标在这里都会失真,按涨跌幅设的提醒也会误报。 修法:看图用前复权。做回测记下复权方式,因为每次新的除权都会让前复权的历史价格整体变一次。 ⑤ 汇率6.69916,图上只剩6.70 图表库默认保留2位小数,股票够用,汇率不够。汇率一天的波动常在千分位,两位小数什么都看不出来。 修法:按品种设小数位,外汇5位,股票2位,低价港股3位。 四、盘中分时 ⑥ A股分时图从凌晨01:45开始 还是 UTC 显示的问题,到了分时图上更扎眼:09:45显示成01:45,15:00显示成07:00。 修法:用图表库的时间格式化选项,按交易所时区名显示:A股 Asia/Shanghai,美股 America/New_York。别写“加8小时”。 ⑦ 11月以后,美股时间错一小时 很多代码里写死了“美东加12小时就是北京时间”。夏令时是对的,11月1日以后要加13小时。 写死的话,开盘、收盘、“交易中”的判断全部早一小时。港股如果真延长交易时段,所有写死“16:00收盘”的地方也得改。 修法:时区换算用时区名,夏令时交给系统处理。交易时段从接口读,别写死在代码里,交易所改时间你也不用发版。 ⑧ 最后一根K线,看着像缩量六成 北京时间23:33打开苹果日K,最新一根成交量1,482万股,前一天3,898万股。其实是这根还没收盘,当天才交易了两个小时。 “放量缩量”、均线信号、价格提醒,都会被这根半成品带偏。拿它算策略信号,回测里看不出问题,实盘才出事。 修法:最后一根单独标“未完成”,颜色画浅一点;更新它用 series.update();指标和提醒只用已收盘的K线。 五、成交量和上线当天 ⑨ 寒武纪的量柱,只有腾讯的1/270 10月14日,寒武纪成交量73,781,单位是手;腾讯19,933,548,单位是股。直接画在一起,寒武纪的柱子几乎看不见。乘100换成股,是738万股,约为腾讯的37%。 修法:A股成交量乘100换成股。跨市场比活跃度,用成交额更稳。 ⑩ 日期跑到58709年,或者整张图白屏 这是上线当天最常见的两种“图没了”: 毫秒没转秒:接口时间戳一般是毫秒,图表库要秒。毫秒直接喂进去不报错,横轴写着“58709年”,所有K线挤在一角。 没按时间排序:图表库要求数据严格升序、不能重复。顺序一乱,整张图白屏,生产环境只报一句 Value is null,很难查。 顺带一个合规提醒:图表左下角那个小 logo 是开源许可要求的署名。嫌碍眼关掉的话,记得在页面别处补上 TradingView 的署名和链接。 修法:毫秒转秒、升序排序、去掉重复时间,三件事都放进喂数层。 六、上线前体检表 # 用户看到的 修法 ① 日K日期早一天 日K换成当地日期字符串 ② 三个市场同一天对不上 先换成各自交易日再对齐 ③ 涨跌颜色反了 按用户地区设颜色 ④ 除权日像暴跌 看图用前复权 ⑤ 汇率只剩两位小数 按品种设小数位 ⑥ 分时从01:45开始 按交易所时区名显示 ⑦ 冬令时后错一小时 时区名换算,时段从接口读 ⑧ 最后一根像缩量 标记未完成,不进指标 ⑨ A股量柱矮100倍 乘100换成股,或用成交额 ⑩ 58709年、白屏 毫秒转秒、升序去重、保留署名 七、怎么做:一个喂数层 10条修法都落在同一个地方:数据进图表之前。别在每个页面各修各的,写一个喂数层,所有K线都从这里过。 喂数层代码 这段代码用本文的真实数据在 Lightweight Charts 5.2.1 里跑通过: // feed.js:K线数据进图表之前,统一过这一层 const TZ = { CN: 'Asia/Shanghai', HK: 'Asia/Hong_Kong', US: 'America/New_York', CRYPTO: 'UTC', FX: 'UTC' }; const LOT = { CN: 100, HK: 1, US: 1, CRYPTO: 1, FX: 1 }; // A股成交量按手,乘100换成股 const DIGI = { CN: 2, HK: 2, US: 2, CRYPTO: 2, FX: 5 }; // 价格小数位,低价港股、个别品种单独覆盖 const dayOf = (ms, tz) => // 交易所当地日期 'YYYY-MM-DD' new Intl.DateTimeFormat('en-CA', { timeZone: tz, year: 'numeric', month: '2-digit', day: '2-digit' }) .format(new Date(ms)); function normalize(klines, { market, interval, lastIsForming = false }) { const tz = TZ[market]; const daily = /^(1d|1w|1M)$/.test(interval); const rows = klines .map(k => ({ ms: Number(k.time), o: +k.open, h: +k.high, l: +k.low, c: +k.close, v: +k.volume * LOT[market], amt: k.quote_volume == null ? null : +k.quote_volume })) .filter(r => Number.isFinite(r.ms) && Number.isFinite(r.c)) .sort((a, b) => a.ms - b.ms); // 不假设接口返回顺序 const out = []; for (const r of rows) { const time = daily ? dayOf(r.ms, tz) : Math.floor(r.ms / 1000); // 日K用日期,分钟K用秒 const bar = { time, open: r.o, high: r.h, low: r.l, close: r.c, volume: r.v, amount: r.amt }; if (out.length && out[out.length - 1].time === time) out[out.length - 1] = bar; // 重复时间保留后到的 else out.push(bar); } if (lastIsForming && out.length) out[out.length - 1].forming = true; // 未收盘,指标和提醒不用它 return out; } function chartOptions(market) { const tz = TZ[market]; const hm = new Intl.DateTimeFormat('zh-CN', { timeZone: tz, hour: '2-digit', minute: '2-digit', hourCycle: 'h23' }); const ymd = new Intl.DateTimeFormat('zh-CN', { timeZone: tz, year: 'numeric', month: '2-digit', day: '2-digit' }); const fmt = t => typeof t === 'number' ? `${ymd.format(new Date(t * 1000))} ${hm.format(new Date(t * 1000))}` : t; return { layout: { attributionLogo: true }, // 保留署名,或在页面别处放 NOTICE 和链接 localization: { timeFormatter: fmt }, timeScale: { timeVisible: true, tickMarkFormatter: t => typeof t === 'number' ? hm.format(new Date(t * 1000)) : null }, }; } function seriesStyle(market, region = 'CN') { const [up, down] = region === 'CN' ? ['#e5484d', '#16a34a'] : ['#16a34a', '#e5484d']; const d = DIGI[market]; return { upColor: up, downColor: down, wickUpColor: up, wickDownColor: down, borderVisible: false, priceFormat: { type: 'price', precision: d, minMove: 10 ** -d } }; } function safeUpdate(series, bar) { // 推送乱序时,旧K线不回写 const last = series.data().at(-1); if (last && bar.time < last.time) return; // 日期字符串和秒数都能直接比大小 series.update(bar); } 用法: // resp:后端转发的K线接口返回,API Key 留在后端 const bars = normalize(resp.data.klines, { market: 'CN', interval: '1d', lastIsForming: true }); const chart = LightweightCharts.createChart(el, chartOptions('CN')); const candles = chart.addSeries(LightweightCharts.CandlestickSeries, seriesStyle('CN')); candles.setData(bars); 跨市场,最好只接一套接口 喂数层要按市场分支,这躲不掉,A股按手、港股按股是市场规则。但按数据源分支是可以躲掉的。如果A股、港股、美股、加密、外汇各接一家,每一家的时间戳格式、字段名、复权参数都要单独写一套转换,哪家一升级就可能出错。 TickDB 为开发者和 AI 应用提供统一的全球行情数据接口,让团队通过一套接入获取多市场实时与历史数据,更快构建行情、分析和监控产品。 本文的实验数据都来自 TickDB 的K线接口,和喂数层直接相关的有三点: A股、港股、美股、外汇、加密资产的K线是同一组字段,喂数层只需要按市场分支; 股票K线用 adjust 一个参数切换不复权、前复权、后复权; 交易时段有单独的接口,按市场返回当地时段,开收盘时间不用写死。 最后 打开你们的K线页面,把光标停在最新一根上,看看日期是不是今天;再找一只最近除过权的股票,看看除权那天。两分钟就能知道,第①④条你们中了没有。 港股延时还在讨论,美股冬令时还有两周多。交易时间会变,复权因子会变,这些变化都放在喂数层里处理,别散落在每一张图里。 参考资料 21世纪经济报道,[香港证监会:将就延长交易时段发讨论文件],2026-10-10 每日经济新闻,[港交所将就延长交易时段发表讨论文件],2026-10-12 TradingHours.com,[Nasdaq Trading Hours] TradingView,[Lightweight Charts™ version 5]
浏览11
评论0
收藏0
用户头像sh_*219t3e
2026-09-23 发布
亲测最好用的AI编写量化策略工具,可以让 AI 直接生成同花顺Supermind上可运行的策略代码,代码质量远高于直接使用 DeepSeek、GPT等平台。 😃Supermind AI工具入口:https://easyquant.ai/ 大家可以直接向AI描述策略,然后一键生成可运行的完整策略代码,也可以把它当做一个API 查询工具。
浏览406
评论11
收藏0
用户头像Fxdund
2026-10-14 发布
跨市场量化策略写了一半,发现美股数据用一个接口、A股用另一个、港股还得再申请一个;免费接口昨天还能跑,今天字段就变了;所谓"实时行情",实际延迟十几秒。个人做全球股票策略,最容易低估的不是策略难度,而是多市场数据源的工程成本决定了策略能跑多远。 这篇文章不堆接口名单,直接回答三个问题:历史回测用什么,盘中行情用什么,跨市场统一数据又该怎么搭。 先说结论:不要迷信"一个数据源包打天下" 个人开发者做全球股票,比较稳妥的方案不是找到一个万能API,而是按需求分层: 数据层 主要用途 适合的选择 历史研究层 日线、财务、指数成分、因子研究 本地数据库+免费历史接口 盘中行情层 实时快照、K线、跨市场比价 统一格式的实时行情API 交易验证层 持仓、委托、成交 券商交易接口 历史数据追求完整和可复现,实时数据追求延迟与稳定,交易数据必须以券商回报为准。 如果你只做日频选股,没必要为毫秒行情买单;如果策略依赖跨市场比价、盘口或实时资金流,免费网页数据再省钱也可能把策略做废。 常见全球股票数据源横向对比 数据源 覆盖市场 实时能力 接口稳定性 使用成本 更适合谁 Yahoo Finance 全球主要市场 较弱(延迟明显) 依赖网页,偶尔限流 低 学习、原型验证、低频分析 Alpha Vantage 美股为主 一般 较规范,但调用频率受限 免费额度有限 美股日频研究、入门项目 Tushare Pro A股为主 一般 较规范 按积分权限 A股因子研究、财务分析 AKShare A股+部分海外 一般 依赖上游网页 低 多市场探索、数据抓取 iTick 美股/A股/港股/日股/印股 较强 API化接入 需申请Token 跨市场策略、实时监控、多市场并行 这里没有绝对排名。数据源是否好用,取决于你的策略频率、市场范围、预算和容错能力。 只做日频选股和做跨市场实时比价讨论"哪个数据源最好",就像自行车和赛车讨论哪种轮胎最好,场景根本不同。 免费数据源:适合研究,不宜裸奔进生产 Yahoo Finance和AKShare这类免费源最大的优势是覆盖面广、上手快。股票、基金、指数都能在一个Python包里调用,很适合验证想法。 它们的不确定性也很明显:部分接口封装自公开网页,上游页面结构、参数或反爬策略发生变化,接口可能随之失效。Yahoo Finance的免费接口经常限流,高频调用会被封IP;AKShare的部分字段依赖网页解析,页面一改就挂。 适合它们的任务包括: 快速验证一个因子有没有研究价值 抓取低频公开数据做一次性分析 学习不同市场的代码格式和交易规则 不建议把单一免费接口直接放进无人值守的实盘链路。真要使用,至少要增加本地缓存、字段校验、异常告警和备用源。 免费的数据不一定便宜。你花三天修复字段变化,成本很可能已经超过一年的接口费用。 统一实时行情API:跨市场策略的工程解法 做跨市场策略的时候,最头疼的不是单市场数据拿不到,而是每个市场用一个接口,代码维护成本爆炸。美股用一个SDK,A股用另一个,港股还要再申请一个Token,时间戳格式不一样,字段命名不一样,出了问题都不知道查哪头。 统一实时行情API的思路是:用一套接口格式、一个认证Token,覆盖多个市场。看几个实际能力: import requests API_BASE = "https://api.itick.org" TOKEN = "your_token_here" headers = {"accept": "application/json", "token": TOKEN} # 同一份代码,换个region就能拿不同市场的数据 def get_quote(region, code): resp = requests.get( f"{API_BASE}/stock/quote", headers=headers, params={"region": region, "code": code} ) return resp.json()["data"] # 美股苹果 us = get_quote("US", "AAPL") # A股贵州茅台 cn = get_quote("CN", "600519") # 港股腾讯 hk = get_quote("HK", "00700") # 日股丰田 jp = get_quote("JP", "7203") # 印股Reliance in_ = get_quote("IN", "RELIANCE") print(f"美股AAPL: {us['ld']} ({us['chp']}%)") print(f"A股600519: {cn['ld']} ({cn['chp']}%)") print(f"港股00700: {hk['ld']} ({hk['chp']}%)") 同一份get_quote函数,换个region参数就能拿五个市场的数据。这种统一格式对跨市场策略开发来说,工程价值很大——不用维护五套代码,出了问题查一个接口就行。 WebSocket实时推送也是统一格式: import json import websocket WS_URL = "wss://api.itick.org/stock" TOKEN = "your_token_here" authenticated = False def on_message(ws, message): global authenticated payload = json.loads(message) # 等鉴权成功 if payload.get("resAc") == "auth" and payload.get("code") == 1 and not authenticated: authenticated = True # 同时订阅美股和港股 ws.send(json.dumps({ "ac": "subscribe", "params": "AAPL$US,00700$HK", "types": "quote" })) return data = payload.get("data") or {} if data.get("type") == "quote": print(f"{data['s']}: {data['ld']} ({data['chp']}%)") ws = websocket.WebSocketApp(WS_URL, header=[f"token: {TOKEN}"], on_message=on_message) ws.run_forever() 一个WebSocket连接同时订阅美股和港股,不用维护两个连接。这种统一设计在做跨市场实时监控的时候特别省心。 注意几个容易踩的坑: 各市场代码格式不一样:美股是AAPL,A股是600519,港股是00700,日股是7203 印度股票订阅格式特殊,是三个参数:RELIANCE$NSE$IN 时间戳都是毫秒,直接当秒数处理会出错 交易时间不一样,美股晚上才开盘,做跨市场监控要注意时间窗口 不同策略到底应该怎么选 只做单市场日频选股和回测 推荐组合是免费历史接口加本地数据库(DuckDB、Parquet或PostgreSQL)。行情收盘后增量更新一次即可,不需要持续轮询实时接口。 预算非常有限时,用免费源建主库,再用实时API补充盘中数据。 做多市场对比和跨市场监控 这时候统一实时行情API的价值就出来了。历史数据可以用免费源,但盘中实时监控需要一个稳定、格式统一的接口。不然你美股用一个SDK、A股用另一个,代码维护成本会吃掉你做策略的时间。 做AH股溢价、中美比价这类跨市场价差策略 这类策略需要同时拿两个市场的实时价格,时间戳一致性很重要。用两个不同接口的数据,时间戳对不上,算出来的价差不准。统一接口的好处是两边的数据来自同一个服务,时间戳一致性好很多。 准备长期实盘 生产环境不要只有一个行情源。主数据源负责实时决策,备用数据源负责监控和故障切换,券商成交回报负责校准真实持仓。三个来源都不一致时,应暂停开仓,而不是猜哪个数字正确。 选型建议总结 预算接近零、还在学习阶段:用免费接口,先把研究流程和本地数据仓库跑通。 主要研究单市场日频因子和财务数据:用单市场的专业历史接口做研究主库,免费接口补充缺失字段。 做跨市场对比、AH溢价、多市场实时监控:重点测试统一格式的实时行情API,用历史主库补齐长期样本。 个人量化的数据源终极选型,不是选最贵的,也不是选接口最多的,而是选一个与你的策略频率匹配、能够被验证、发生故障时还能退出的系统。 数据决定回测是否可信,风控决定实盘能活多久。策略代码,反而常常是最容易的那一部分。 接口的具体参数和返回字段说明,可以参考官方文档对照着写,比自己猜参数靠谱多了。 GitHub:https://github.com/itick-org/
浏览33
评论0
收藏0
用户头像KAO普
2026-10-14 发布
一、策略思路 只做两只 ETF:进攻端用红利低波 ETF,防守端用十年期国债 ETF,二选一满仓持有,不做杠杆、不做空、不做日内。用日线级别的趋势信号判断该持有哪一边,T 日收盘出信号、T+1 开盘调仓,单边佣金万 0.5。 二、回测结果 指标 策略 基准(红利低波ETF) 累计收益 +366% +139% 年化收益 22.0% 12.4% 最大回撤 -14.2% -16.5% 卡玛比率 1.55 0.75 Beta 约 0.2 1.0 回测区间 2019-01 ~ 2026-10,初始资金 10 万,按不复权真实价格成交。 三、交易特征 7 年半只调仓 25 次,平均持有 103 天,年化换手不到 2 次——交易成本几乎可以忽略,也不用担心冲击成本。 13 次买入、12 次完整平仓,12 笔全部盈利,单笔收益 +8% ~ +19%。 持仓分布约 2/3 时间在红利低波 ETF、1/3 时间在国债 ETF,所以和宽基指数的相关性很低,适合当组合里的低波卫星仓位。
浏览29
评论0
收藏0
用户头像Jacktick
2026-10-14 发布
谷歌开放AI自建应用:让AI写跨市场行情App要过12关 让 AI 写一个跨市场行情面板只要两分半,模拟数据下一切正常;接上真实接口,第一屏全是“数据获取失败”。我用同一个 AI 写了5份行情代码:不给资料的3份,在适用的检查项里错了27处;先让它查一遍真实接口的2份,只错1处。这是一份让 AI 写行情 App 的全景指南,12道关,附提示词模板和自检脚本。 10月13日,谷歌宣布:美国18岁以上的用户,可以用 Google AI Studio 让 AI 做一个只给自己用的 App,直接通过 Google Play 运行;之后还能分享给信任的朋友,想公开上架,要先过安全审核。谷歌负责人的说法是,Play 商店要从“总有一个 App 适合这件事”变成“总有一个 App 是给我的”。 国内也一样热。证券时报9月28日报道,券商正在成批上线智能体;一家大模型公司给数十家头部金融机构的方案,把“权威数据源”放在了第一位。柯林斯词典早在2025年就把“vibe coding”(凭感觉写代码)选为年度词汇。 人人都能让 AI 写 App 了。可如果你让 AI 写的是一个行情 App,“只给自己用”也不安全,它算错的是你的钱。 我做了一个实验。同一个主流 AI 编程助手,三段老板、产品经理、个人投资者都会说的普通需求,一共写了5份行情代码: 不给任何资料的3份,对照真实接口逐项检查,适用的30项里错了27项; 写之前先让它通过 MCP 查一遍真实接口的2份,适用的20项里只错了1项。 不给资料的那3份,AI 在交付说明里都老老实实写着一句话:路径、参数、字段,“都是我猜的”。 AI 写得出能跑的行情 App,写不出知道自己在显示什么的行情 App。它缺的不是编程能力,是两样东西:你接的接口长什么样,行情数字背后的规则是什么。 这篇写给想用 AI 做行情产品的老板、产品经理和开发者,也写给想让 AI 帮自己写盯盘脚本的投资者。读完你能带走: 一次5份代码的对照实验,和三张没修饰过的截图 让 AI 写行情 App 要过的12道关:每一关 AI 会怎么写错、代价多大、提示词里该怎么写 一段复制即用的提示词模板 一段“接口事实卡”脚本:写代码前先把真实接口的事实取出来,贴给 AI 6件 AI 替你决定不了、必须人来拍板的事 一、一次实验:同一个AI,5份行情代码 不给资料,AI 靠“常见写法”猜接口;先查一遍真实接口,它几乎不犯低级错。 实验怎么做 我准备了三段需求,都是现实里最常见的说法: 编号 需求原话(节选) 谁会这么说 A “帮我写一个跨市场行情面板,3小时内要能上线给老板看……React 单文件,后端用 Flask 做个转发,能跑就行” 产品经理、外包团队 B “只要一个 HTML 文件,不要后端,双击打开就能看,今天下午要给老板演示” 赶时间的任何人 C “我是个人投资者,帮我用 Python 写一个盯盘脚本……算一下持仓市值和今日盈亏,统一换算成人民币” 个人投资者 六个品种和系列前两篇一致:A股寒武纪、港股腾讯、美股苹果、黄金、比特币、标普500。 每段需求先在“不给资料”的条件下写一遍(A0、B0、C0)。A 和 C 再在“先查接口”的条件下各写一遍(A1、C1):动笔前,让 AI 用 MCP 工具对每个品种实际调一次接口,同时给它一份官方接口要点。B 的场景是“双击就能看的单文件”,没有做第二轮。 结果:先查接口,错误从27处降到1处 我把每份代码对照2026年10月14日上午实测的真实接口返回,按12个检查项逐项判定: 几个数字: 不给资料:三份代码分别用了81、104、154秒写完,最长的778行。适用的检查项 A0 错10/12,B0 错10/10,C0 错7/8。 先查接口:两份代码用了237秒和319秒,只多花2到3分钟。A1 错1/12(价格转成了浮点数),C1 全对。 先查接口的两份代码,交付时各列了一串“需要你确认”的问题,比如“今日”按北京时间0点还是 UTC 0点算、美股夜盘算不算进盈亏。这些问题本来就该人来回答,第四部分细说。 三张截图:演示、接真接口、改对路径 我把 A0 的代码原样跑起来,分三步截图。真实数据是10月14日09:56通过接口取得的单次返回,按官方路径回放给它: 给老板演示时:一切正常。可价格是 AI 编的,寒武纪1,277元、比特币10.9万;右上角还弹出一条“黄金大跌2.79%”的提醒,同样是编的。 接上真实接口:每一行都是“数据获取失败”,AI 猜的快照路径根本不存在。这时页面左上角挂着一个“实时”标签。 只把路径和参数改对:价格出来了,问题也露出来了。成交量、成交额整列是“—”,买一卖一几乎全空;涨幅榜第一名是比特币,用的是滚动24小时的涨幅;苹果显示341.27美元,那是几个小时前的美股收盘价,页面上没有时间。 AI的行情常识停在哪一天 三份“不给资料”的代码都带了一套演示数据。AI 自己说这些数是随手编的,但它编出来的数,暴露了它的“常识”停在哪一天: 演示价格编错了,标个“模拟数据”就算了。真正危险的是 C0 写死的汇率:美元兑人民币7.10、港元兑人民币0.91,取不到实时汇率时就用它兜底。而当天真实的是6.6927和0.8527。 它猜的港元汇率代码在接口里不存在,所以港元会直接退回0.91,仅腾讯500股一项,持仓市值就多算约1.2万元。如果两个汇率都退回写死值,整个持仓(真实约115.99万元)会被高估约5.98万元,高5.2%。脚本不会报错,只会安静地显示一个更好看的数字。 二、全景地图:让AI写行情App要过的12关 12道关分三层:接得上、显示对、上得了线。AI 不给资料时,几乎每一关都会栽。 第一层决定代码能不能跑,第二层决定显示的数对不对,第三层决定敢不敢上线。第二层的8关,正好对应系列第一篇讲的“价格身份证”五格:品种、时段、算法、时间、状态。 下面每一关都按同一个顺序写:AI 不给资料时怎么写 → 真实接口是什么样 → 代价 → 提示词里怎么写。 第一层 接得上:接口路径、字段名、数字精度 ① 接口路径和参数 AI 怎么写:三份代码猜了三种路径,/quote、/quotes,还有直接请求根地址;A0 把参数写成单数 symbol,三份都没传资产类型。 真实接口:快照是 /ticker,参数是 symbols(逗号分隔,可批量)加 type。 代价:第一屏全部报错。更隐蔽的是不传资产类型:系列第一篇实测过,“000001”同时是平安银行和上证指数,接口会报歧义错误;换一家会替你猜的接口,你的自选里就会出现一个3,808元的“平安银行”。 提示词:“先调用真实接口,以返回为准,不要按常见写法猜路径和参数;每个品种写明资产类型。” ② 字段名 AI 怎么写:成交量按 volume、vol 取,成交额按 amount、turnover、quote_volume 取,涨跌幅按 change_pct 一类取。B0 和 C0 一口气列了七八个候选名,挨个试。 真实接口:volume_24h、quote_volume_24h、price_change_percent_24h。最新价 last_price 猜中了,这三个一个都没猜中。 代价:路径改对以后,这三列依然是“—”;涨跌幅取不到,AI 就自己拿前收重算,算法问题被藏得更深(见第⑤关)。 提示词:“字段名以真实返回为准;取不到的字段报错,不要用候选名挨个试。” ③ 数字精度 AI 怎么写:三份代码都把价格转成浮点数再算。 真实接口:价格、成交额都以字符串返回,比如 "4155.87000"、"83400.01000000",保留了数据源给的精度。 代价:显示一个价格时看不出来,一旦算持仓市值、累计成交额,浮点误差会一路带进报表和对账。先查接口的 A1 也栽在这一关,C1 用了十进制计算。 提示词:“价格和金额保留字符串,计算用十进制,不要直接转浮点数。” 第二层 显示对:单位、窗口、时段、时间、零值、盘口、K线、币种 ④ 成交量单位 AI 怎么写:成交量不带单位,统一按“万、亿”格式化。 真实接口:寒武纪的成交额÷成交量÷价格约等于100,成交量按手(100股)计;腾讯约等于1,按股计。先查接口的 A1 自己算出了这个比值,把A股成交量乘了100。 代价:A股成交额、换手率、大单筛选全部差100倍(系列第一篇返工点②)。 提示词:“每个市场的成交量写明单位;用成交额÷成交量÷价格自检。” ⑤ 涨跌幅窗口 AI 怎么写:用(现价−前收)÷前收自己算,涨幅榜直接混排,超过±2%就提醒。 真实接口:股票按当个交易日;比特币是滚动24小时;黄金没有官方收盘价,前收落在哪根K线要看数据源怎么切日。 代价:截图里涨幅榜第一名是比特币,它比的是“过去24小时”,其他品种比的是“今天”,名次没有可比性。系列第二篇实测过,同一刻同一个金价,涨跌可以是−0.69%,也可以是+0.24%,提醒一家响一家不响。 提示词:“每个涨跌幅标明窗口;跨市场排序或提醒前,先按同一个窗口重算。” ⑥ 美股时段 AI 怎么写:只读主快照的价格,忽略接口里的盘前、盘后、夜盘对象。 真实接口:北京时间上午,苹果主快照341.27美元,时间戳是凌晨4:00(美股收盘);同一份返回里还有夜盘价341美元,时间是一分钟前。 代价:用户把几个小时前的收盘价当成现价;首页和详情页对不上(系列第二篇场景④)。 提示词:“美股主快照与盘前、盘后、夜盘分开显示,各标时段。” ⑦ 数据时间 AI 怎么写:A0 的列表不显示行情时间;更危险的是一行兜底代码,返回里没有时间戳时,就用“现在”补上。 真实接口:每个快照都带毫秒时间戳,不同品种的时间可以差好几个小时。 代价:一条旧数据会被显示成刚刚更新。盯盘最怕的不是数据慢,是不知道它慢。 提示词:“界面显示每个数字的数据时间;没有时间戳就标‘时间未知’,不要用当前时间代替。” ⑧ 零和没有 AI 怎么写:B0 只过滤空值,标普500的买一卖一会显示成“0.0000”。A0 碰巧没出错:它的写法把“0”当成了空值,这是运气,不是设计。 真实接口:标普500的买价、卖价返回 "0.00000",成交量返回 "0.00"。指数没有买卖盘,这里的0意思是“没有”。 代价:中间价按(0+0)÷2算成0,指数估值归零;用价差做风控,价差变成0(系列第一篇返工点⑤)。 提示词:“对该品种不适用的字段,即使返回0也显示‘—’。” ⑨ 盘口档数 AI 怎么写:A0 请求盘口时写死 limit=5,前端最多画5档;它的演示数据里,标普500也有5档买卖盘。 真实接口:同一时刻,寒武纪5档、腾讯10档、苹果夜盘只有1档,指数没有盘口。 代价:港股深度丢一半;演示给老板看的,是一份根本不存在的指数盘口。用户照着假深度下单,是最贵的一种错(系列第一篇返工点⑦)。 提示词:“盘口按接口实际返回的档数画,不截断、不补档;不支持的市场写‘不支持’。” ⑩ K线时间戳 AI 怎么写:K线时间戳统一处理,最后一根不做标记。 真实接口:09:56查寒武纪5分钟K线,最后一根标着10:00,它还在走;A股K线标的是每根的结束时刻,港股标的是开始时刻(由返回结果推断)。先查接口的 A1 发现了这一点,把A股统一减了5分钟。 代价:A股和港股叠在一张图上错开一根;回测会提前用到5分钟后才有的数据。 提示词:“写明K线时间戳是开始还是结束,最后一根标‘未结束’。” ⑪ 币种与汇率 AI 怎么写:A0、B0 把人民币、港元、美元的成交额都格式化成“万、亿”,不标币种;C0 汇率取不到时用写死的7.10和0.91。 真实接口:当天美元兑人民币6.6927,港元兑人民币0.8527。先查接口的 C1 从接口取汇率,还发现港元汇率要换一个代码才取得到。 代价:前面算过,同一组持仓最多高估约5.98万元。 提示词:“不同币种不直接相加;汇率从接口取,取不到就报错,不用写死的数。” 第三层 上得了线:密钥、模拟数据、刷新频率 ⑫ 密钥与模拟数据 AI 怎么写:B0 按需求把 API Key 明文写进了 HTML(它自己提醒了:“把这个文件发给别人,就等于把 key 也给了别人”);接口连续失败3次,页面会自动切到模拟数据,只挂一条黄色横幅。A0 把 Key 放在服务端,模拟数据也挂了醒目标签,这一关做得对。 真实情况:GitGuardian 2026年的报告统计,2025年公开 GitHub 上新泄露的密钥约2,865万个,同比增长34%;带 AI 编程助手署名的提交,泄露比例约是平均水平的2倍。 代价:Key 被盗刷、额度被用光;更难发现的是“自动切到模拟数据”,演示时数字一直在跳,没人会想到它是假的。 提示词:“API Key 只放服务端或环境变量;没有真实数据时页面醒目标出‘模拟数据’,不自动切换。” 上线前还有两件事 AI 一般不会主动问:刷新频率和失败处理。B0 按需求每秒刷新一次;A0、B0 都提醒了要注意调用频率限制,但都说不清额度是多少。一个页面每秒打一次接口,多开几个标签页就可能触发限流,限流以后整页空白。请求频率、限额、失败后显示什么,要在上线前问清楚。 12关一张表 关 AI 不给资料时的典型写法 正确做法 对应前文 ① 接口路径和参数 猜/quote,不传资产类型 先查真实接口,写明类型 系列第一篇① ② 字段名 七八个候选名挨个试 以真实返回为准,取不到就报错 ③ 数字精度 转浮点数 字符串保留,十进制计算 ④ 成交量单位 不带单位 按市场写单位,比值自检 系列第一篇② ⑤ 涨跌幅窗口 自己重算,直接混排 标窗口,同窗口重算再排 系列第二篇 ⑥ 美股时段 只读主快照 各时段分开显示 系列第一篇③ ⑦ 数据时间 不显示,缺了用“现在”补 每个数字带时间 ⑧ “0”和“没有” 0照常显示 不适用显示“—” 系列第一篇⑤ ⑨ 盘口档数 写死5档,演示造档 按实际返回画 系列第一篇⑦ ⑩ K线时间戳 统一处理 标开始或结束,末根标未结束 系列第一篇⑥ ⑪ 币种与汇率 混币种、写死汇率 分币种,汇率从接口取 ⑫ 密钥与模拟数据 Key 写进前端,失败自动切模拟 Key 放服务端,模拟数据醒目标注 这张表就是上线前的体检清单:12项逐项打勾,打不上勾的那一项,就是上线后的第一个工单。 三、为什么AI会这样:它缺的是事实,不是能力 AI 没见过你的接口,只能按“常见写法”补全;行情规则不在任何通用知识里,它不知道要问。 它在猜,而且猜得很自信。这不是行情接口独有的毛病。美国三所大学的研究人员测试了16个代码生成模型,模型推荐的软件包里约19.7%根本不存在;商用模型约5.2%,开源模型约21.7%。AI 编出一个不存在的接口路径,和编出一个不存在的软件包,是同一种行为。 它的常识停在学习的那一天。价格、汇率、交易规则都在变。今年7月6日起A股多了一段15:05到15:30的盘后固定价格交易,11月1日美国结束夏令时,11月16日起港股开始统一每手股数。这些 AI 都可能不知道,前面那张“行情常识”表就是证据。 行情规则不在通用知识里。成交量按手还是按股、涨跌幅按哪个窗口、K线时间戳标开始还是结束,每个市场、每家数据源都不一样。AI 不知道这里有坑,也就不会问。 差一点就对最贵。Stack Overflow 2025年开发者调查:80%的开发者在工作中用 AI 工具,但信任 AI 准确性的只有29%;45%的人把“差一点就对的 AI 代码”列为头号烦恼,66%的人说花在修这类代码上的时间变多了。行情 App 恰恰是“差一点”的重灾区:页面能跑,数字看着合理,错在单位和窗口里。 安全问题不会自己消失。Veracode 2025年测试了100多个大模型、80个编程任务,45%的情况下 AI 写出的代码引入了安全漏洞,Java 的失败率超过70%。 这五条加起来,结论很简单:AI 缺的是事实,补上就好。补事实的办法也很简单:让它先查真实接口,再动笔。 四、正确姿势:先查、再写、人拍板 先让 AI 看到真实接口,再把行情规则写进提示词,最后用12项清单验收。定义类的问题,留给人。 1. 先查:让AI看到真实接口 两种做法,选一种: 你的 AI 工具支持 MCP:像实验里的 A1、C1 一样,在需求前加一句“先调用真实接口,看到返回再写代码”。AI 会自己调几次接口,把字段、单位、时段看一遍。 不支持 MCP:先跑一遍下面这段“接口事实卡”脚本,把输出贴进对话框。它只做一件事:把真实返回里和“价格身份证”有关的事实整理成 AI 能读的说明。 # 测试环境:Python 3.11 # 用途:写代码之前,先把真实接口的“事实”取一遍,生成一段可以直接贴给 AI 的说明 import os import sys import time from decimal import Decimal import requests API_KEY = os.getenv("TICKDB_API_KEY") # 只放在环境变量或服务端 BASE_URL = "https://api.tickdb.ai/v1/market" WATCHLIST = { # 资产类型逐个写明,不靠代码后缀猜 "688256.SH": "stock", "700.HK": "stock", "AAPL.US": "stock", "XAUUSD": "forex", "BTCUSDT": "crypto", "SPX": "indices", } WINDOW = {"stock": "当个交易日(美股为常规盘)", "forex": "按数据源切日,需确认切日时刻", "indices": "上一交易日收盘", "crypto": "滚动24小时"} def get_tickers(type_, symbols): resp = requests.get(f"{BASE_URL}/ticker", params={"symbols": ",".join(symbols), "type": type_}, headers={"X-API-Key": API_KEY}, timeout=10) body = resp.json() if resp.status_code != 200 or body.get("code") != 0: raise RuntimeError(f"{type_}: HTTP {resp.status_code}, code={body.get('code')}, {body.get('message')}") return body["data"] def is_zero(v): try: return Decimal(str(v)) == 0 except Exception: return False def facts(q, type_, now_ms): lines = [f"- {q['symbol']}(type={type_})"] lines.append(f" 返回字段:{', '.join(sorted(k for k in q if not isinstance(q[k], dict)))}") lines.append(f" 数值是字符串(如 last_price=\"{q.get('last_price')}\"),计算请用十进制,不要直接转浮点") lines.append(f" 涨跌幅字段 price_change_percent_24h=\"{q.get('price_change_percent_24h')}\"(已是百分数),窗口:{WINDOW[type_]}") age_h = (now_ms - q["timestamp"]) / 3_600_000 lines.append(f" 数据时间距现在 {age_h:.1f} 小时;界面必须显示数据时间,不要用当前时间代替") vol, amt, last = q.get("volume_24h"), q.get("quote_volume_24h"), q.get("last_price") if vol and amt and not is_zero(vol): ratio = Decimal(amt) / Decimal(vol) / Decimal(last) unit = "手(100股)" if ratio > 50 else "股或币" lines.append(f" 成交额÷成交量÷价格 ≈ {ratio:.1f} → 成交量单位推断为:{unit}(接入前以文档确认)") elif amt is None: lines.append(" 没有成交额字段:显示“—”,不要补0,也不要自己算") for k in ("bid_price", "ask_price", "volume_24h"): if k in q and is_zero(q[k]): lines.append(f" {k} 返回 \"{q[k]}\":对这个品种表示“没有”,显示“—”,不要显示0") if type_ == "stock" and "bid_price" not in q: lines.append(" 快照里没有买一卖一:需要另调盘口接口,或在界面上写明“无”") for k in ("pre_market_quote", "post_market_quote", "overnight_quote"): if k in q: sub = q[k] lines.append(f" {k}:last_done={sub.get('last_done')},前收={sub.get('prev_close')}," f"距现在 {(now_ms - sub['timestamp']) / 3_600_000:.1f} 小时;与主快照分开显示,各标时段") return lines def main(): if not API_KEY: sys.exit("请先设置环境变量 TICKDB_API_KEY") now_ms = int(time.time() * 1000) by_type = {} for sym, t in WATCHLIST.items(): by_type.setdefault(t, []).append(sym) print("【接口事实卡】以下内容来自真实接口返回,写代码时以此为准:") for t, syms in by_type.items(): got = {q["symbol"]: q for q in get_tickers(t, syms)} for sym in syms: if sym not in got: print(f"- {sym}:接口没有返回这个代码,先确认代码写法和资产类型") continue print("\n".join(facts(got[sym], t, now_ms))) if __name__ == "__main__": main() 用10月14日09:56的实测数据跑出来的结果(节选三个品种): 【接口事实卡】以下内容来自真实接口返回,写代码时以此为准: - 688256.SH(type=stock) 返回字段:category, high_24h, last_price, low_24h, name, open, prev_close, price_change_24h, price_change_percent_24h, quote_volume_24h, symbol, timestamp, type, volume_24h 数值是字符串(如 last_price="976.8"),计算请用十进制,不要直接转浮点 涨跌幅字段 price_change_percent_24h="0.03"(已是百分数),窗口:当个交易日(美股为常规盘) 数据时间距现在 0.0 小时;界面必须显示数据时间,不要用当前时间代替 成交额÷成交量÷价格 ≈ 99.5 → 成交量单位推断为:手(100股)(接入前以文档确认) 快照里没有买一卖一:需要另调盘口接口,或在界面上写明“无” - AAPL.US(type=stock) 返回字段:high_24h, last_price, low_24h, name, open, prev_close, price_change_24h, price_change_percent_24h, quote_volume_24h, symbol, timestamp, type, volume_24h 数值是字符串(如 last_price="341.27"),计算请用十进制,不要直接转浮点 涨跌幅字段 price_change_percent_24h="0.09"(已是百分数),窗口:当个交易日(美股为常规盘) 数据时间距现在 5.9 小时;界面必须显示数据时间,不要用当前时间代替 成交额÷成交量÷价格 ≈ 1.0 → 成交量单位推断为:股或币(接入前以文档确认) 快照里没有买一卖一:需要另调盘口接口,或在界面上写明“无” pre_market_quote:last_done=345.27,前收=340.97,距现在 12.4 小时;与主快照分开显示,各标时段 post_market_quote:last_done=340.311,前收=341.27,距现在 1.9 小时;与主快照分开显示,各标时段 overnight_quote:last_done=341,前收=341.27,距现在 0.0 小时;与主快照分开显示,各标时段 - SPX(type=indices) 返回字段:ask_price, bid_price, high_24h, last_price, low_24h, name, open, prev_close, price_change_24h, price_change_percent_24h, symbol, timestamp, type, volume_24h 数值是字符串(如 last_price="7805.45000"),计算请用十进制,不要直接转浮点 涨跌幅字段 price_change_percent_24h="-0.02"(已是百分数),窗口:上一交易日收盘 数据时间距现在 0.0 小时;界面必须显示数据时间,不要用当前时间代替 没有成交额字段:显示“—”,不要补0,也不要自己算 bid_price 返回 "0.00000":对这个品种表示“没有”,显示“—”,不要显示0 ask_price 返回 "0.00000":对这个品种表示“没有”,显示“—”,不要显示0 volume_24h 返回 "0.00":对这个品种表示“没有”,显示“—”,不要显示0 这几行就是 AI 最缺的东西:成交量单位、数据时间、哪些0其实是“没有”、美股的时段对象。把它贴在需求前面,第一层的三关和第二层的大半关卡,AI 就有了依据。 2. 写规则:复制即用的提示词模板 查到的是事实,规则还得你告诉它。下面这段模板,每一条都对应实验里 AI 实际犯过的一个错,放在需求前面一起发: 你要写一个跨市场行情应用。动手前先做两件事: 1. 先调用真实接口(MCP 工具,或我贴给你的“接口事实卡”),以真实返回为准,不要按常见写法猜路径、参数和字段名。 2. 不确定的定义先列出来问我,不要自己编。 写代码时遵守: - 每个数字同时带上单位、涨跌窗口(当日 / 滚动24小时 / 切日时刻)和数据时间。 - 价格和金额保留字符串或用十进制计算,不要直接转成浮点数。 - 接口没返回、或返回0但对该品种不适用的字段,显示“—”,不补0,不编造。 - 美股主快照与盘前、盘后、夜盘分开显示,各标时段。 - 盘口按接口实际返回的档数画,不截断、不补档;不支持的市场写“不支持”。 - K线写明时间戳是开始还是结束,最后一根标“未结束”。 - 不同币种不直接相加;汇率从接口取,取不到就报错,不用写死的数。 - 跨市场排序或提醒前,先把涨跌幅按同一个窗口重算。 - API Key 只放服务端或环境变量;没有真实数据时页面必须醒目标出“模拟数据”,不自动切换。 3. 验收:12项体检,6件事人来拍板 代码写完,按第二部分那张表逐项打勾。还有6件事,AI 查了接口也替你决定不了。先查接口的两份代码,交付时都主动列出了这些问题: 今日怎么算:北京时间0点、UTC 0点、纽约17:00,还是滚动24小时? 美股盘后和夜盘算不算:涨跌、市值和提醒用常规盘,还是用最新的延长时段价格? 稳定币怎么换算:USDT 是否按1美元算? 提醒规则:跨过阈值提醒一次,还是每次刷新都提醒?用哪个窗口的涨跌幅? 汇率怎么取:多币种汇总用哪个汇率、哪个时点? A股除权日:前收用不用除权参考价(系列第二篇场景③)? 这6件事没有标准答案,但必须有人定、写进文档、显示在界面上。 4. 跨市场为什么更需要统一接口 只做A股,AI 要猜一套字段;做跨市场,如果每个市场各接一家数据源,AI 要猜的是好几套:路径不同、字段名不同、时间戳格式不同、前收的定义不同。实验里不给资料的 AI,光是成交额一个字段就列了七八个候选名,这还只是假设只有一家数据源。 数据源越多,AI 越容易猜错,你要写的“接口事实卡”也越长。规则还在变,每变一次,每一家都得重新核对。所以用 AI 做跨市场行情 App,省事的做法是一套接口覆盖所有市场:AI 只需要学一套字段,事实卡只需要一份,提示词里的规则只需要写一次。 5. 本文实验怎么用的数据接口 TickDB 通过 Skill、MCP、CLI 和 API 为 AI 工具提供结构化市场数据,让模型先取得带标的、字段和时间的事实,再进行分析与表达。 本文“先查接口”那一轮,AI 就是通过 MCP 直接调用它的接口,在写代码前看到了6个品种的真实返回: 能做到 要你自己定 支持 MCP 的 AI 工具可以直接调用接口,写代码前先看到真实字段和数值 上面6件需要拍板的事,接口给不了答案 A股、港股、美股、外汇贵金属、指数、加密资产的快照用同一组字段返回现价、前收和时间戳,AI 只需要学一套 成交量单位、K线时间戳含义,本文由返回结果推断,接入前以文档确认 美股快照里盘前、盘后、夜盘分成独立对象,各带价格和时间;代码有歧义时返回错误,不替你猜 不同套餐的能力不同,盘口、逐笔等以账户权限为准 左边是这次实验能证明的,右边是任何数据源都替代不了的判断。(作者实测,2026年10月13日至14日。) 常见问题 AI写的行情App能直接上线吗? 不建议。本文实验里,不给资料的3份 AI 代码在模拟数据下都能跑,但对照真实接口,适用的30个检查项错了27个,错在接口路径、字段名、成交量单位、涨跌窗口、美股时段等地方。上线前至少做两件事:让 AI 先查真实接口再写,写完按12项清单逐项检查。 让AI写行情代码的提示词怎么写? 最重要的一句是“先调用真实接口,以返回为准,不要按常见写法猜”。然后把行情规则写成约束:每个数字带单位、涨跌窗口和数据时间;不适用的字段显示“—”不补0;美股各时段分开显示;盘口按实际档数画;汇率从接口取;Key 只放服务端。完整模板见第四部分。 AI为什么会编造接口路径和字段名? 因为它没见过你用的接口,只能按训练时见过的“常见写法”补全。学术研究发现,代码模型推荐的软件包里约两成根本不存在,编造接口是同一类问题。解决办法是写代码前先让它看到真实返回:用支持 MCP 的工具直接调接口,或者把接口的真实返回贴给它。 用AI写行情App时API Key放在哪里? 放在服务端或环境变量里,不要写进前端页面。本文实验中,需求要求“只要一个 HTML 文件、不要后端”时,AI 把 Key 明文写进了页面,只附了一句提醒。GitGuardian 的统计显示,带 AI 编程助手署名的代码提交,泄露密钥的比例约是平均水平的2倍。 跨市场行情App用几家数据源合适? 能用一家覆盖就用一家。每多一家数据源,AI 就要多猜一套路径、字段和时间格式,你要核对的规则也多一套;规则变化时,每一家都要重新检查。用一套接口覆盖多个市场,AI 的事实卡和提示词都只需要写一份。 最后一个问题 你们现在用 AI 写的那个行情页面,能说出每个数字的单位、窗口和时间吗? 今天就能做的一件事:把你的需求原封不动发给 AI 之前,先加一句“先调用真实接口,看到返回再写代码”。实验里,这一句只多花了2到3分钟,省掉的是第一屏的全部报错。 AI 写得出能跑的行情 App。让它知道自己在显示什么,是你的事。 参考资料 TechCrunch,[Google Play now lets anyone build private, vibe-coded apps that run on Android],2026-10-13 证券时报(中证网转载),[智能体浪潮席卷证券业 券商AI转型从单点增效迈向体系重构],2026-09-28 CNN(经 KRDO 转载),[“Vibe coding” named Collins Dictionary’s word of the year],2025-11-06 GitGuardian,[The State of Secrets Sprawl Report 2026] Stack Overflow,[2025 Developer Survey results],2025-07-29 Veracode,[2025 GenAI Code Security Report 新闻稿],2025-07-30 Spracklen 等,[We Have a Package for You! A Comprehensive Analysis of Package Hallucinations by Code Generating LLMs];CSO Online 相关报道
浏览53
评论0
收藏0
用户头像Fxdund
2026-10-13 发布
做跨境量化或者港股通策略的开发者,接港股数据是绕不开的。港股跟A股有个很特别的联动关系——同一家公司在A股和港股两地上市,价格经常不一样,这就是所谓的AH股溢价。这个价差不仅是金融从业者关心的套利机会,也是技术开发者做跨市场数据监控的典型场景。 这篇从AH股溢价监控这个实际场景出发,讲一下怎么用Python接港股实时行情数据,以及怎么同时拉A股和港股的价格做价差计算。 为什么要接港股数据 一开始我做A股量化的时候,数据都是国内的接口,用得挺顺手。后来想做AH股套利策略,才发现需要同时拿A股和港股两边的实时价格。这时候问题就来了——用两个不同的接口拿两边的数据,时间戳对不上,延迟也不一样,算出来的价差不准。 后来找了一圈,试了几个不同的金融数据接口,最后留下来一直在用的是那种同时覆盖A股和港股的统一数据源——不用维护两套代码,两边的数据时间戳一致性也靠谱很多。现在做跨市场监控,一个key打通多个市场的接口选择其实挺关键的。 港股市场的基本情况 先理一下港股的基本情况,这样看返回数据的时候才知道每个字段是什么意思。 交易时间:上午9:30-12:00,下午13:00-16:00。比A股多半小时,中午也有1小时休市。 代码格式:港股代码是5位数字,比如00700是腾讯、09988是阿里、03690是美团。跟A股的6位数字不一样,传参数的时候要注意位数。 交易货币:港币(HKD)。算AH股溢价的时候要注意汇率换算。 region代码:港股市场region传 HK,A股传 CN。 REST拉取港股报价 先从REST开始,确认数据格式。 import requests API_BASE = "https://api.itick.org" TOKEN = "your_token_here" headers = {"accept": "application/json", "token": TOKEN} # 拉港股实时报价 def get_hk_stock_quote(code): resp = requests.get( f"{API_BASE}/stock/quote", headers=headers, params={ "region": "HK", "code": code } ) return resp.json()["data"] # 拉几只港股大盘股 stocks = ["00700", "09988", "03690"] for code in stocks: q = get_hk_stock_quote(code) sign = "+" if q["chp"] >= 0 else "" print(f"{code}: {q['ld']} ({sign}{q['chp']}%)") 返回字段跟其他市场基本一致:ld最新价、chp涨跌幅、o/h/l开高低、v成交量。做行情看板这些字段够用了。 注意:港股代码是5位数字,传参数的时候要传字符串形式("00700"),不要传数字。一开始我传了"700",结果返回空数据——港股代码必须带前导零,5位数字。 WebSocket订阅港股 做实时监控的时候,轮询REST接口效率太低,这时候就得用WebSocket实时推送了。 import json import threading import time import websocket WS_URL = "wss://api.itick.org/stock" TOKEN = "your_token_here" authenticated = False def on_message(ws, message): global authenticated payload = json.loads(message) # 先等鉴权成功 if payload.get("resAc") == "auth" and payload.get("code") == 1 and not authenticated: authenticated = True # 港股订阅格式:代码$市场 ws.send(json.dumps({ "ac": "subscribe", "params": "00700$HK,09988$HK", "types": "quote" })) return if payload.get("resAc") == "pong": return data = payload.get("data") or {} if data.get("type") == "quote": sign = "+" if data["chp"] >= 0 else "" print(f"{data['s']}: {data['ld']} ({sign}{data['chp']}%)") 港股订阅是两个参数(00700$HK),跟美股、A股一样,不是印度那种三个参数。 AH股溢价监控实战 这是港股数据最有技术含量的应用场景——同一家公司在A股和港股两地上市,价格经常不一样。 比如招商银行,A股代码是600036,港股代码是03968。两边的价格理论上应该差不多,但实际上经常有5%-30%的溢价差。这个价差就是量化交易者关心的套利机会。 # AH股溢价监控 # 招商银行:A股 600036,港股 03968 # 中国平安:A股 601318,港股 02318 def get_ah_premium(a_code, h_code, hkd_cny_rate=0.92): """ 计算AH股溢价率 a_code: A股代码 h_code: 港股代码 hkd_cny_rate: 港币兑人民币汇率 """ # 拉A股价格 a_resp = requests.get( f"{API_BASE}/stock/quote", headers=headers, params={"region": "CN", "code": a_code} ).json()["data"] # 拉港股价格 h_resp = requests.get( f"{API_BASE}/stock/quote", headers=headers, params={"region": "HK", "code": h_code} ).json()["data"] # 港股价格换算成人民币 h_price_cny = h_resp["ld"] * hkd_cny_rate # 计算溢价率 premium = (a_resp["ld"] - h_price_cny) / h_price_cny * 100 return { "a_code": a_code, "a_price": a_resp["ld"], "h_code": h_code, "h_price_hkd": h_resp["ld"], "h_price_cny": round(h_price_cny, 2), "premium_pct": round(premium, 2) } # 监控几只AH股 ah_pairs = [ ("600036", "03968"), # 招商银行 ("601318", "02318"), # 中国平安 ("600900", "00900"), # 长江电力 ] for a_code, h_code in ah_pairs: result = get_ah_premium(a_code, h_code) print(f"{result['a_code']} / {result['h_code']}: " f"A股{result['a_price']}元, 港股{result['h_price_hkd']}港币 " f"(≈{result['h_price_cny']}元), " f"溢价{result['premium_pct']}%") 这个脚本跑起来之后,就能看到每只AH股的溢价率了。溢价率过高或者过低的时候,就是套利的机会。 注意:汇率是动态变化的,做实时监控的时候要定期更新汇率,不能写死。 K线数据获取 K线接口跟其他市场一样,只是region传 HK。 def get_hk_kline(code, k_type=8, limit=100): """ k_type: 1=1分钟 2=5分钟 5=1小时 8=日K 9=周K 10=月K """ resp = requests.get( f"{API_BASE}/stock/kline", headers=headers, params={ "region": "HK", "code": code, "kType": k_type, "limit": limit } ) return resp.json()["data"] # 拉腾讯近100根日K daily = get_hk_kline("00700", k_type=8, limit=100) closes = [bar["c"] for bar in daily] # 算20日均线 ma20 = sum(closes[-20:]) / 20 print(f"00700最新收盘: {closes[-1]}, 20日均线: {ma20:.2f}") K线返回标准OHLCV:t时间戳、o/h/l/c开高低收、v成交量。做技术分析直接用这些字段。 港股特有的注意事项 代码是5位数字,带前导零。 港股代码是5位数字(00700、09988),跟A股的6位数字(600519)不一样。一开始我传了"700",结果返回空数据——港股代码必须是5位,前面补零。 交易时间比A股长半小时。 港股上午9:30-12:00,下午13:00-16:00。比A股多半小时,做跨市场监控的时候要注意两边的交易时间窗口。 交易货币是港币。 港股价格单位是港币(HKD),做AH股溢价计算的时候要换算成人民币。汇率是动态的,不能写死。 港股通标的有限。 不是所有港股都能通过港股通买,做策略的时候要注意标的范围。 时间戳是毫秒。 所有返回的时间戳都是毫秒,直接当秒数处理会得到一个很远的未来时间,记得除以1000。 完整脚本:港股+AH股溢价监控 把前面几块拼起来,最终的完整脚本: import json, time, threading, requests, websocket API_BASE = "https://api.itick.org" WS_URL = "wss://api.itick.org/stock" TOKEN = "your_token_here" headers = {"accept": "application/json", "token": TOKEN} # 港股监控列表 watchlist = ["00700", "09988", "03690"] # 启动时拉快照 print("=== 港股快照 ===") for code in watchlist: r = requests.get(f"{API_BASE}/stock/quote", headers=headers, params={"region": "HK", "code": code}).json()["data"] sign = "+" if r["chp"] >= 0 else "" print(f" {code}: {r['ld']} ({sign}{r['chp']}%)") # AH股溢价快照 print("\n=== AH股溢价 ===") ah_pairs = [("600036", "03968"), ("601318", "02318")] for a_code, h_code in ah_pairs: a = requests.get(f"{API_BASE}/stock/quote", headers=headers, params={"region": "CN", "code": a_code}).json()["data"] h = requests.get(f"{API_BASE}/stock/quote", headers=headers, params={"region": "HK", "code": h_code}).json()["data"] h_cny = h["ld"] * 0.92 premium = (a["ld"] - h_cny) / h_cny * 100 print(f" {a_code}/{h_code}: A股{a['ld']}元, 港股{h['ld']}港币 " f"(≈{h_cny:.2f}元), 溢价{premium:.1f}%") # WebSocket实时推送港股 authenticated = False def on_message(ws, message): global authenticated payload = json.loads(message) if payload.get("resAc") == "auth" and payload.get("code") == 1 and not authenticated: authenticated = True params = ",".join(f"{c}$HK" for c in watchlist) ws.send(json.dumps({ "ac": "subscribe", "params": params, "types": "quote" })) threading.Thread(target=heartbeat, args=(ws,), daemon=True).start() return if payload.get("resAc") == "pong": return data = payload.get("data") or {} if data.get("type") == "quote": sign = "+" if data["chp"] >= 0 else "" print(f"[实时] {data['s']}: {data['ld']} ({sign}{data['chp']}%)") def heartbeat(ws): while True: time.sleep(30) ws.send(json.dumps({"ac": "ping", "params": str(int(time.time() * 1000))})) ws = websocket.WebSocketApp(WS_URL, header=[f"token: {TOKEN}"], on_message=on_message) ws.run_forever() 这个脚本跑起来之后,开盘前先看到一组港股的快照和AH股溢价率,盘中实时更新港股价格。 小结 接港股数据的技术框架跟A股、美股差不多——REST做快照和历史数据,WebSocket做实时推送。主要区别在代码格式(5位数字带前导零)、交易货币(港币)和交易时间(比A股长半小时)。最有技术含量的应用场景是AH股溢价监控——同时拉A股和港股两边的价格,算跨市场价差。 做港股量化策略或者AH股套利的话,这套流程可以直接套。具体的参数细节和返回字段说明,我一般都是边写代码边翻官方文档对照,比自己猜参数靠谱多了。 GitHub:https://github.com/itick-org/
浏览70
评论0
收藏0
用户头像sh_***3272xs
2026-10-13 发布
做跨市场行情App,最容易被用户截图投诉的,是价格旁边那个红绿百分比。同一刻、同一个金价,涨跌可以是−0.69%,也可以是+0.24%。本文拆解涨幅榜、价格提醒、持仓页、首页详情页4个最容易出错的场景,附一张跨市场分母清单。 做跨市场行情App,最容易被用户截图投诉的,往往是价格旁边那个红绿百分比。 2026年10月13日周二,北京时间10:56,黄金4,175.15美元。同一个价格,我按5种常见算法各算了一遍涨跌幅: 跟谁比 基准价(美元) 涨跌 24小时前(约) 4,204.35 −0.69% 我实测的接口给的“前收” 4,190.27 −0.36% 纽约17:00 4,171.38 +0.09% UTC 0点(日K收盘) 4,170.54 +0.11% 北京时间0点 4,164.95 +0.24% 单次快照。基准价都取自同一数据源的K线,涨跌幅按同一个公式重算,可以自己验算。 换成钱:持有100盎司黄金,按“24小时前”算,账面一天亏约2,920美元;按“北京时间0点”算,赚约1,020美元,相差3,940美元。两个App给出相反的颜色,都没算错。 黄金只是一个品种。把A股、港股、美股、外汇、加密放进同一个App,这种事会成倍出现:寒武纪除权那天,日K线上“暴跌36.7%”,实际只跌5.6%;同一只苹果,首页显示+1.29%,详情页显示+0.47%;比特币的“今日涨跌”,其实是过去24小时。 跨市场行情应用里,涨跌幅不是一个现成的字段,而是一道除法:分子是现价,各家一样;分母是“跟谁比”,每个市场都不一样。分母不统一就上屏,涨幅榜、价格提醒、持仓页、首页推送,四个地方都会出错。 这篇写给做行情产品的人——产品、运营和技术同事,也写给每天看行情App的投资者。读完你能带走: 4个最容易出错的产品场景:用户看到什么、错在哪、代价多大、怎么修 一张跨市场“分母清单”:每个市场的涨跌幅该跟谁比,界面上该写什么 上线前问数据供应商的5个问题 一段代码(给技术同事):按统一基准重算涨跌,自动识别A股除权除息日 先记住一句话:看涨跌,先问“跟谁比”。 一、一分钟看懂:涨跌幅为什么会对不上 涨跌幅 =(现价 − 基准价)÷ 基准价。现价各家一样,分歧全在基准价。 系列上一篇《行情看板Demo三天、上线三个月:拆解7个返工点》提出过一个检查框架:界面上的每个数字,都要能说清自己的品种、时段、算法、时间、状态。涨跌幅是“算法”这一格里最常见、也最容易出错的数字。 拆开看,基准价由3个问题决定: 跟哪个价比?昨天的收盘价、某个整点的价格,还是除权后的参考价。 跟几点的价比?“今天”从北京时间0点算、UTC 0点算、纽约17:00算,还是干脆用“过去24小时”。 中间发生过什么?除权除息、跨时段(盘后、夜盘)、休市。 连“收盘价”本身都是规则算出来的。上交所从2018年8月20日起,股票收盘价由14:57–15:00的收盘集合竞价产生,这三分钟可以报单、不能撤单;纳斯达克16:00的收盘撮合产生官方收盘价;黄金干脆没有官方收盘价。每个市场规则不同,默认分母也不同: 市场 涨跌幅通常跟谁比 最容易出错的地方 A股 上一交易日收盘价 除权除息日要改用参考价 港股 上一交易日收市价(由收市竞价时段决定) 跨市场排序时和美股、加密的窗口不同 美股 上一常规交易日收盘价 盘前、盘后、夜盘另有基准 黄金、外汇 没有官方收盘:纽约17:00、UTC 0点、北京0点都有人用 周日开盘会切出一根“迷你日K” 加密资产 没有收盘:滚动24小时,或用户自选0点 窗口每时每刻都在挪 指数 上一交易日收盘价 休市时段,各家显示不同 一个App里只放一个市场,问题不大;放进六个市场,这六套规则就会在同一块屏幕上撞车。下面是撞车最多的4个地方。 二、4个出错场景:钱和信任在哪里流失 每个场景都是同一个毛病:不同分母的涨跌幅,被当成同一种数放在了一起。 场景① 涨幅榜和自选列表:跨市场一排序,名次就失真 用户看到的:自选列表按涨跌幅排序,苹果+1.29%排第一,比特币−1.07%排最后。 错在哪:这5个涨跌幅,量的是5段不同的时间。 苹果、标普500:北京时间上午美股休市,显示的是上周五收盘到周一收盘的涨跌; 寒武纪:昨天收盘到现在; 黄金:看你选几点切日,图里按UTC 0点; 比特币:过去24小时,而且这个窗口一直在滑动。我实测它的“前收”,10月12日11:08是83,049.15,同日14:01是83,074.01,10月13日10:56是83,866.01,同一天里查两次,分母就变了。币安官方API文档把24小时行情定义为滚动窗口;Gate 则让用户在“过去24小时”“UTC+8 0点”“UTC 0点”三种起止时间里自己选。 指数还有一种情况:我实测标普500在10月12日北京白天显示0.00%(前收和最新价都是7,811.54),10月13日早上显示−0.06%(周一的涨跌)。同样是美股休市的北京白天,一天显示0,一天显示上一交易日的涨跌。 代价:榜单名次没有可比性。用户按“今日最强”去追,追的可能是两天前的涨幅;运营做跨市场涨幅榜活动,排第一的未必真涨得最多;指数休市显示0.00%,用户以为平盘。 怎么修:跨市场排序前,用K线按同一个窗口(比如“北京时间今天0点至今”)把所有品种重算一遍再排;休市的品种标“休市”,不和交易中的品种混排。 先问供应商:涨跌幅的基准时刻是几点、哪个时区?休市时显示什么? 场景② 价格提醒:同一个阈值,一个响一个不响 用户看到的:用户设了“黄金跌0.5%提醒我”。同一时刻,A平台推送了提醒,B平台没有。 错在哪:按“24小时前”算是−0.69%,提醒响;按“北京时间0点”算是+0.24%,提醒不响。两个平台都没算错,只是分母不同。 根子在于黄金没有官方收盘价。伦敦 LBMA 黄金价格每天定两次(伦敦时间10:30、15:00),上海金每天两次(北京时间10:15、14:15),COMEX 期货结算价按收盘前一段时间的成交量加权平均价算。现货平台不受这些约束,各自选时刻切“日”。CME 在2026年9月29日的文章里写,纽约时间17:00之后的一小时,是全球外汇日的“行政分界”——按这个时刻切日很常见,但不是唯一的选择。 切日时刻还会切出意外。按UTC 0点切日K线的数据源,周日晚上开盘那几个小时会单独成一根“日K”:我实测黄金10月11日(周日)这根K线成交量只有8,813,前后几个交易日都在15万以上。我实测的接口给出的“前收”4,190.27,正好就是这根周日K线的收盘,算出来是−0.36%,既不是纽约17:00的价格,也不是周一的收盘。 代价:误触发,用户可能据此卖出或加仓;漏触发,该提醒的没提醒。客服还解释不清“为什么别家提醒了你们没提醒”。 怎么修:提醒规则里写明基准,比如“较纽约17:00跌0.5%”,用户设置时就能看到;周日开盘那几个小时单独处理,不当成一个交易日。 两个边界:用小时K线取的“纽约17:00价格”,和别家的纽约收盘可能差零点几美元;“24小时前”只能取到最近的整点,是近似值。 先问供应商:黄金、外汇按几点切日?周日开盘那几个小时怎么算? 场景③ 持仓和资产页:除权那天“一夜亏三成” 用户看到的:持有寒武纪的用户,5月8日早上打开App,持仓市值少了三成;跌幅榜第一名是寒武纪,−36.70%。 错在哪:这天是寒武纪的除权除息日。2025年度分配方案是每股派现1.50元、每股转增0.49股,股权登记日5月7日。交易所规定,除权除息日的涨跌幅不跟昨天收盘比,而是跟除权(息)参考价比: 参考价 =(前收盘价 − 现金红利)÷(1 + 流通股份变动比例)=(1,868.00 − 1.50)÷ 1.49 = 1,252.68元 5月8日实际开盘1,217.03元、收盘1,182.53元: 按昨收1,868.00算:低开34.85%,收跌36.70% 按参考价1,252.68算:低开2.85%,收跌5.60% 我实测的复权因子也对得上:这次除权的前复权因子是0.6706,1,868.00 × 0.6706 = 1,252.68。 还有一个反证。寒武纪是科创板股票,涨跌幅限制20%。按参考价算,当天涨跌停区间是1,002.14–1,503.22元;如果错按昨收算,跌停价应是1,494.40元,而寒武纪全天都在1,158.01–1,220.00元之间成交——那就等于全天都在“跌停价以下”成交,这不可能。交易所自己用的分母,就是参考价。 代价:从持仓看,转增后股数变成1.49倍,每股还拿了1.50元现金,市值并没有少三成,但用户看到的是“亏了三成”,第一反应是截图投诉。跌幅榜挂错,运营要出面解释。做量化的拿不复权日K回测,除权日是一根假的大阴线,止损会在这天被误触发。 这不是一年碰上一次的事。10月正赶上中期分红集中除权,我实测的分红日历里,10月12日、13日两天的A股除权除息记录就超过20条。 怎么修:快照的前收和昨日收盘差得多,先标“除权除息”,涨跌按参考价算,持仓按新股数显示;回测用复权数据。 先问供应商:除权除息日的前收,是不是参考价? 场景④ 首页和详情页:同一只苹果,两个涨幅 用户看到的:首页上苹果+1.29%,点进详情页+0.47%。用户的第一反应:数据坏了。 错在哪:10月13日北京时间10:56,美股正在夜盘时段。我实测同一时刻的苹果有4个涨跌: 主快照340.97美元(周一常规盘收盘),较上周五收盘336.64,+1.29% 盘后341.36,较周一收盘,+0.11% 夜盘342.57,较周一收盘,+0.47% 夜盘较上周五收盘,+1.76%(自己算) 规则是:常规盘的涨跌,跟上一个常规交易日的收盘比;盘后、夜盘的涨跌,跟当天常规盘的收盘比。数据里写得很清楚:盘后、夜盘的前收是340.97(周一收盘),主快照的前收是336.64(上周五收盘)。四个数都对,只是分母不同。 代价:用户真正想知道的,往往是“从上周五到现在涨了多少”,答案是+1.76%,首页和详情页给他的哪个都不是。两个数并排、又不写分母,用户只会得出一个结论:这个App的数据不靠谱。到了财报季,盘后动辄跳空几个百分点,首页和详情页的差距会更大(本周五的文章专门讲)。 怎么修:同一屏上的每个涨跌幅,旁边写上时段和基准,比如“夜盘 较周一收盘 +0.47%”。 先问供应商:盘前、盘后、夜盘的涨跌,按哪个收盘算? 4个场景收在一张表里: 场景 用户看到的 错在哪 代价 怎么修 涨幅榜 苹果第一、比特币最后 5个涨跌幅量的是5段时间 名次失真,用户追错 按同一窗口重算再排 价格提醒 一家响、一家不响 黄金切日时刻不同 误触发、漏触发 规则里写明基准 持仓页 一夜“亏三成” 除权日没用参考价 恐慌、投诉、回测失真 识别除权日,按参考价算 首页/详情页 +1.29%和+0.47% 常规盘和夜盘分母不同 用户不再信任数据 每个涨跌幅标时段和基准 这4件事看起来是技术细节,其实是产品问题。卡尼曼和特沃斯基1979年提出的前景理论有一个结论:人判断得失,看的是相对某个参照点的变化,而不是绝对水平。行情App上的涨跌幅,就是替用户选好的参照点。同样4,175.15美元的金价,参照点选在24小时前,用户觉得亏了;选在北京时间0点,用户觉得赚了。谁定分母,谁就定了用户今天的情绪,所以分母应该写在界面上。 三、怎么修:跨市场统一分母,分3步 先给每个涨跌幅贴上分母标签,再按同一个窗口重算,最后单独处理除权。 1. 一张跨市场分母清单 市场 建议的分母 界面上要写的字 A股 上一交易日收盘;除权除息日用参考价 “较前收(除权调整)” 港股 上一交易日收市价 “较前收” 美股常规盘 上一常规交易日收盘 “较上一交易日收盘” 美股盘前/盘后/夜盘 当天常规盘收盘 “夜盘 较今日收盘” 黄金、外汇 选定一个切日时刻(如纽约17:00)并写出来 “较纽约17:00” 加密 滚动24小时,或指定时区0点 “24h”或“较UTC 0点” 指数(休市时段) 上一交易日涨跌并标日期,或标“休市” “10/12 收盘” 照着这张表,每个涨跌幅旁边都能写出它在跟谁比。A股参考价按交易所规则执行,其余是建议做法。 2. 三步落地 第一步,贴标签。每个涨跌幅带上基准价和基准时刻。不贴,用户拿两个App一比颜色不一样就来问;解释一次,下一个用户还会问。 第二步,统一窗口。跨市场比较(涨幅榜、资产总览、跨市场提醒)时,不比现成的百分比,用K线按同一个窗口自己重算。不重算,名次取决于谁的分母更旧。 第三步,单独处理除权。A股先判断是不是除权除息日:快照的前收和昨日收盘差得多,就按参考价或复权数据处理。 3. 为什么跨市场更难:6类资产,6套规则 只做A股,记住“前收、除权”两件事就够了。做跨市场,要同时管6套规则:A股的除权、港股的收市竞价、美股的四个时段、黄金外汇的切日时刻、加密的滚动窗口、指数的休市显示。 如果每个市场各接一家数据源,同样叫“前收”的字段,名字、时间戳格式、切日时刻都可能不一样。统一分母之前,得先写一层“翻译”;市场越多,翻译层越厚。规则还在变:美国夏令时11月1日结束,纽约17:00对应的北京时间要从早上5点变成6点,每一家数据源的处理都得重新核对一遍。 所以做跨市场行情应用,省事的做法是:一套接口拿到所有市场的快照、K线和复权数据,分母标签层只写一次。 4. 我用 TickDB 把6类资产跑了一遍 TickDB 为开发者和 AI 应用提供统一的全球行情数据接口,让团队通过一套接入获取多市场实时与历史数据,更快构建行情、分析和监控产品。 本文寒武纪、苹果、黄金、比特币、标普500的数字,都是我用同一套接口取的: 能做到 要你自己处理 6类资产(A股、港股、美股、外汇贵金属、指数、加密)的快照,用同一组字段返回现价、前收和时间戳 接口给的涨跌幅是一个现成的数,不带“分母说明”,标签要自己加 同一套K线接口覆盖各市场,可以按任意基准时刻(纽约17:00、北京0点、UTC 0点)自己重算 黄金、外汇这类没有官方收盘的品种,建议按自己选定、并写在界面上的基准重算 美股快照同时带盘后、夜盘各自的价格和前收;复权因子能还原寒武纪的除权参考价 复权数据会随新的公司行为更新,回测要记下查询时间和复权方式 左边是一套接口能直接支撑的,右边是任何数据源都替代不了的产品判断。(作者实测,2026年10月12–13日。) 5. 给技术同事:一段代码 不写代码的读者可以跳过这一节。下面这段代码做两件事:用小时K线按4种基准时刻重算黄金涨跌;自动识别A股除权除息日。 # 测试环境:Python 3.11 # 接口端点与字段名已于 2026-10-13 通过实际调用核对 import os import sys from datetime import datetime, timedelta, timezone from decimal import Decimal from zoneinfo import ZoneInfo import requests API_KEY = os.getenv("TICKDB_API_KEY") # 从环境变量读取,不要写进前端 BASE_URL = "https://api.tickdb.ai/v1/market" UTC, BJ, NY = timezone.utc, ZoneInfo("Asia/Shanghai"), ZoneInfo("America/New_York") HOUR_MS = 3_600_000 def get(path, **params): """调用接口,同时检查 HTTP 状态和业务返回码。""" try: resp = requests.get(f"{BASE_URL}/{path}", params=params, headers={"X-API-Key": API_KEY}, timeout=10) body = resp.json() except (requests.RequestException, ValueError) as e: raise RuntimeError(f"{path} 请求失败: {e}") from e if resp.status_code != 200 or body.get("code") != 0: raise RuntimeError(f"{path}: HTTP {resp.status_code}, code={body.get('code')}, {body.get('message')}") return body["data"] def pct(last, base): """涨跌幅(%)=(现价 − 基准价)÷ 基准价 × 100。""" last, base = Decimal(str(last)), Decimal(str(base)) return (last - base) / base * 100 def price_at(hourly, moment): """取某一时刻的价格:用“结束于该时刻”的那根小时K线的收盘价(K线时间戳为该小时的开始)。""" target = int(moment.timestamp() * 1000) - HOUR_MS for bar in hourly: if bar["time"] == target: return bar["close"] return None def last_moment(now, tz, hour): """now 之前最近一次 tz 时区的 hour 点(自动处理夏令时)。""" local = now.astimezone(tz) m = local.replace(hour=hour, minute=0, second=0, microsecond=0) if m > local: m -= timedelta(days=1) return m def gold_changes(symbol="XAUUSD"): """同一个现价,按4种自选基准价分别算涨跌。""" q = get("ticker", symbols=symbol, type="forex")[0] hourly = get("kline", symbol=symbol, interval="1h", type="forex", limit=48)["klines"] now = datetime.fromtimestamp(q["timestamp"] / 1000, UTC) day_ago = (now - timedelta(hours=24) + timedelta(minutes=30)).replace(minute=0, second=0, microsecond=0) # 24小时前,取最近的整点 bases = { "24小时前(近似)": price_at(hourly, day_ago), "纽约17:00收盘": price_at(hourly, last_moment(now, NY, 17)), "UTC 0点": price_at(hourly, last_moment(now, UTC, 0)), "北京时间0点": price_at(hourly, last_moment(now, BJ, 0)), } print(f"{symbol} 现价 {q['last_price']}({now.astimezone(BJ):%m-%d %H:%M} 北京时间)") for name, base in bases.items(): print(f" 较{name:<10} 基准 {base} 涨跌 {pct(q['last_price'], base):+.2f}%" if base else f" 较{name}:缺数据") def is_ex_rights_day(prev_close, last_daily_close, tol=Decimal("0.005")): """快照的前收和上一根日K收盘相差超过0.5%,大概率是除权除息日,要用参考价/复权数据核对。""" p, c = Decimal(str(prev_close)), Decimal(str(last_daily_close)) return abs(p / c - 1) > tol def check_ex_rights(symbol="688256.SH"): q = get("ticker", symbols=symbol, type="stock")[0] daily = get("kline", symbol=symbol, interval="1d", type="stock", limit=2)["klines"] yesterday_close = daily[-2]["close"] # 最后一根是今天(可能未结束),取倒数第二根 flag = is_ex_rights_day(q["prev_close"], yesterday_close) print(f"{symbol} 快照前收 {q['prev_close']} / 昨日K线收盘 {yesterday_close} → {'疑似除权除息日' if flag else '正常'}") if __name__ == "__main__": if not API_KEY: sys.exit("请先设置环境变量 TICKDB_API_KEY") gold_changes() check_ex_rights() # 历史核对:寒武纪 2026-05-08 除权除息日,参考价 1252.68,前一日收盘 1868.00 print("2026-05-08 寒武纪:", "疑似除权除息日" if is_ex_rights_day("1252.68", "1868.00") else "正常") 用10月13日10:56的实测数据跑出来的结果: XAUUSD 现价 4175.15(10-13 10:56 北京时间) 较24小时前(近似) 基准 4204.35 涨跌 -0.69% 较纽约17:00收盘 基准 4171.38 涨跌 +0.09% 较UTC 0点 基准 4170.54 涨跌 +0.11% 较北京时间0点 基准 4164.95 涨跌 +0.24% 688256.SH 快照前收 971.88 / 昨日K线收盘 971.88 → 正常 2026-05-08 寒武纪: 疑似除权除息日 三点说明: 基准价都取自小时K线。K线时间戳是该小时的开始,所以代码取的是“结束于某时刻”的那根K线的收盘价。 纽约17:00用时区库换算,夏令时自动处理,11月1日之后不用改代码。 0.5%的阈值是经验值,只负责标记;标记出来以后,要再用参考价或复权因子核对。 6. 上线前问供应商的5个问题 涨跌幅的基准价是哪个价?昨收、某个时刻的价格,还是除权后的参考价。 基准时刻是几点、哪个时区?周日开盘那几个小时怎么算?决定黄金、外汇、加密的涨跌能不能和股票放在一起。 除权除息日用不用参考价?不用,持仓页就会出现“一夜亏三成”。 盘前、盘后、夜盘的涨跌按哪个收盘算?不说清,首页和详情页就会对不上。 休市时显示上一交易日涨跌,还是0?显示0,用户会以为平盘。 常见问题 行情App的涨跌幅,为什么和别家不一样? 因为分母不同。涨跌幅=(现价−基准价)÷基准价,现价各家一样,基准价各家可以不同:A股除权日用参考价还是昨收,黄金按纽约17:00还是UTC 0点切日,加密用滚动24小时还是0点,美股夜盘跟周一收盘比还是跟上周五比。两个App的涨跌幅不一样,多半不是谁算错,而是分母不同。 跨市场涨幅榜怎么排才可比? 不要直接拿各市场现成的涨跌幅排序。先选定一个统一窗口,比如“北京时间今天0点至今”或“过去24小时”,用K线把每个品种按这个窗口重算一遍再排;休市的品种单独标出,不和交易中的品种混排。 黄金的收盘价是几点的价格? 黄金现货没有交易所规定的官方收盘价。伦敦 LBMA 黄金价格每天定两次,伦敦时间10:30和15:00;上海金每天两次,北京时间10:15和14:15;COMEX 黄金期货结算价按收盘前一段时间的成交量加权平均价确定。现货平台各自选时刻切“日”,常见的有纽约17:00、UTC 0点、北京时间0点。 为什么除权那天股价“暴跌”,涨跌幅却不大? 除权除息日的涨跌幅,基准不是昨天的收盘价,而是除权(息)参考价。寒武纪2026年5月8日前收1,868.00元,每股派现1.50元、转增0.49股,参考价1,252.68元;收盘1,182.53元,看着跌了36.7%,按参考价只跌5.6%。价格降下去的部分,换成了多出来的股份和到账的现金。 美股盘后、夜盘的涨跌是跟谁比? 跟当天常规盘的收盘比;常规盘的涨跌,跟上一个常规交易日的收盘比。2026年10月13日北京时间10:56,苹果主快照较上周五收盘涨1.29%,夜盘较周一收盘涨0.47%。首页显示主快照、详情页显示夜盘,就会出现两个不同的涨幅。 最后一个问题 你们App上的涨跌幅,分母写在哪? 今天就能做的一件事:打开自己App的涨幅榜,逐行写出每个涨跌幅跟谁比、从几点算起。写不出来的那一行,就是下一个客诉工单。 如果你只是用行情App的投资者,也可以试一次:同一时刻打开三个App,记下同一个品种的涨跌幅。不一样,多半不是谁错了,只是三个参照点。 看涨跌,先问“跟谁比”。 参考资料 LBMA,LBMA Gold Price CME Group,When FX Futures Pause: Understanding spread risk around the daily close,2026-09-29 上海证券交易所,收盘集合竞价相关说明,2018-08-06 Nasdaq,Opening and Closing Cross FAQ 香港交易所,Trading Mechanism of CAS in the Securities Market 上海黄金交易所,Shanghai Gold Benchmark Price Launching Ceremony,2016-04 CME Group,Gold 结算方法说明 寒武纪,2025年年度权益分派实施公告(公告编号2026-011) 上海证券交易所,《上海证券交易所科创板股票交易特别规定》 Spot API 文档:24hr Ticker Price Change Statistics Gate 帮助中心,如何切换涨跌幅起止时间 Kahneman, D. & Tversky, A. (1979). Prospect Theory: An Analysis of Decision under Risk. Econometrica, 47(2), 263–291
浏览30
评论0
收藏0
用户头像sh_***3272xs
2026-10-13 发布
做跨市场行情App,最容易被用户截图投诉的,是价格旁边那个红绿百分比。同一刻、同一个金价,涨跌可以是−0.69%,也可以是+0.24%。本文拆解涨幅榜、价格提醒、持仓页、首页详情页4个最容易出错的场景,附一张跨市场分母清单。 做跨市场行情App,最容易被用户截图投诉的,往往是价格旁边那个红绿百分比。 2026年10月13日周二,北京时间10:56,黄金4,175.15美元。同一个价格,我按5种常见算法各算了一遍涨跌幅: 跟谁比 基准价(美元) 涨跌 24小时前(约) 4,204.35 −0.69% 我实测的接口给的“前收” 4,190.27 −0.36% 纽约17:00 4,171.38 +0.09% UTC 0点(日K收盘) 4,170.54 +0.11% 北京时间0点 4,164.95 +0.24% 单次快照。基准价都取自同一数据源的K线,涨跌幅按同一个公式重算,可以自己验算。 换成钱:持有100盎司黄金,按“24小时前”算,账面一天亏约2,920美元;按“北京时间0点”算,赚约1,020美元,相差3,940美元。两个App给出相反的颜色,都没算错。 黄金只是一个品种。把A股、港股、美股、外汇、加密放进同一个App,这种事会成倍出现:寒武纪除权那天,日K线上“暴跌36.7%”,实际只跌5.6%;同一只苹果,首页显示+1.29%,详情页显示+0.47%;比特币的“今日涨跌”,其实是过去24小时。 跨市场行情应用里,涨跌幅不是一个现成的字段,而是一道除法:分子是现价,各家一样;分母是“跟谁比”,每个市场都不一样。分母不统一就上屏,涨幅榜、价格提醒、持仓页、首页推送,四个地方都会出错。 这篇写给做行情产品的人——产品、运营和技术同事,也写给每天看行情App的投资者。读完你能带走: 4个最容易出错的产品场景:用户看到什么、错在哪、代价多大、怎么修 一张跨市场“分母清单”:每个市场的涨跌幅该跟谁比,界面上该写什么 上线前问数据供应商的5个问题 一段代码(给技术同事):按统一基准重算涨跌,自动识别A股除权除息日 先记住一句话:看涨跌,先问“跟谁比”。 一、一分钟看懂:涨跌幅为什么会对不上 涨跌幅 =(现价 − 基准价)÷ 基准价。现价各家一样,分歧全在基准价。 系列上一篇《行情看板Demo三天、上线三个月:拆解7个返工点》提出过一个检查框架:界面上的每个数字,都要能说清自己的品种、时段、算法、时间、状态。涨跌幅是“算法”这一格里最常见、也最容易出错的数字。 拆开看,基准价由3个问题决定: 跟哪个价比?昨天的收盘价、某个整点的价格,还是除权后的参考价。 跟几点的价比?“今天”从北京时间0点算、UTC 0点算、纽约17:00算,还是干脆用“过去24小时”。 中间发生过什么?除权除息、跨时段(盘后、夜盘)、休市。 连“收盘价”本身都是规则算出来的。上交所从2018年8月20日起,股票收盘价由14:57–15:00的收盘集合竞价产生,这三分钟可以报单、不能撤单;纳斯达克16:00的收盘撮合产生官方收盘价;黄金干脆没有官方收盘价。每个市场规则不同,默认分母也不同: 市场 涨跌幅通常跟谁比 最容易出错的地方 A股 上一交易日收盘价 除权除息日要改用参考价 港股 上一交易日收市价(由收市竞价时段决定) 跨市场排序时和美股、加密的窗口不同 美股 上一常规交易日收盘价 盘前、盘后、夜盘另有基准 黄金、外汇 没有官方收盘:纽约17:00、UTC 0点、北京0点都有人用 周日开盘会切出一根“迷你日K” 加密资产 没有收盘:滚动24小时,或用户自选0点 窗口每时每刻都在挪 指数 上一交易日收盘价 休市时段,各家显示不同 一个App里只放一个市场,问题不大;放进六个市场,这六套规则就会在同一块屏幕上撞车。下面是撞车最多的4个地方。 二、4个出错场景:钱和信任在哪里流失 每个场景都是同一个毛病:不同分母的涨跌幅,被当成同一种数放在了一起。 场景① 涨幅榜和自选列表:跨市场一排序,名次就失真 用户看到的:自选列表按涨跌幅排序,苹果+1.29%排第一,比特币−1.07%排最后。 错在哪:这5个涨跌幅,量的是5段不同的时间。 苹果、标普500:北京时间上午美股休市,显示的是上周五收盘到周一收盘的涨跌; 寒武纪:昨天收盘到现在; 黄金:看你选几点切日,图里按UTC 0点; 比特币:过去24小时,而且这个窗口一直在滑动。我实测它的“前收”,10月12日11:08是83,049.15,同日14:01是83,074.01,10月13日10:56是83,866.01,同一天里查两次,分母就变了。币安官方API文档把24小时行情定义为滚动窗口;Gate 则让用户在“过去24小时”“UTC+8 0点”“UTC 0点”三种起止时间里自己选。 指数还有一种情况:我实测标普500在10月12日北京白天显示0.00%(前收和最新价都是7,811.54),10月13日早上显示−0.06%(周一的涨跌)。同样是美股休市的北京白天,一天显示0,一天显示上一交易日的涨跌。 代价:榜单名次没有可比性。用户按“今日最强”去追,追的可能是两天前的涨幅;运营做跨市场涨幅榜活动,排第一的未必真涨得最多;指数休市显示0.00%,用户以为平盘。 怎么修:跨市场排序前,用K线按同一个窗口(比如“北京时间今天0点至今”)把所有品种重算一遍再排;休市的品种标“休市”,不和交易中的品种混排。 先问供应商:涨跌幅的基准时刻是几点、哪个时区?休市时显示什么? 场景② 价格提醒:同一个阈值,一个响一个不响 用户看到的:用户设了“黄金跌0.5%提醒我”。同一时刻,A平台推送了提醒,B平台没有。 错在哪:按“24小时前”算是−0.69%,提醒响;按“北京时间0点”算是+0.24%,提醒不响。两个平台都没算错,只是分母不同。 根子在于黄金没有官方收盘价。伦敦 LBMA 黄金价格每天定两次(伦敦时间10:30、15:00),上海金每天两次(北京时间10:15、14:15),COMEX 期货结算价按收盘前一段时间的成交量加权平均价算。现货平台不受这些约束,各自选时刻切“日”。CME 在2026年9月29日的文章里写,纽约时间17:00之后的一小时,是全球外汇日的“行政分界”——按这个时刻切日很常见,但不是唯一的选择。 切日时刻还会切出意外。按UTC 0点切日K线的数据源,周日晚上开盘那几个小时会单独成一根“日K”:我实测黄金10月11日(周日)这根K线成交量只有8,813,前后几个交易日都在15万以上。我实测的接口给出的“前收”4,190.27,正好就是这根周日K线的收盘,算出来是−0.36%,既不是纽约17:00的价格,也不是周一的收盘。 代价:误触发,用户可能据此卖出或加仓;漏触发,该提醒的没提醒。客服还解释不清“为什么别家提醒了你们没提醒”。 怎么修:提醒规则里写明基准,比如“较纽约17:00跌0.5%”,用户设置时就能看到;周日开盘那几个小时单独处理,不当成一个交易日。 两个边界:用小时K线取的“纽约17:00价格”,和别家的纽约收盘可能差零点几美元;“24小时前”只能取到最近的整点,是近似值。 先问供应商:黄金、外汇按几点切日?周日开盘那几个小时怎么算? 场景③ 持仓和资产页:除权那天“一夜亏三成” 用户看到的:持有寒武纪的用户,5月8日早上打开App,持仓市值少了三成;跌幅榜第一名是寒武纪,−36.70%。 错在哪:这天是寒武纪的除权除息日。2025年度分配方案是每股派现1.50元、每股转增0.49股,股权登记日5月7日。交易所规定,除权除息日的涨跌幅不跟昨天收盘比,而是跟除权(息)参考价比: 参考价 =(前收盘价 − 现金红利)÷(1 + 流通股份变动比例)=(1,868.00 − 1.50)÷ 1.49 = 1,252.68元 5月8日实际开盘1,217.03元、收盘1,182.53元: 按昨收1,868.00算:低开34.85%,收跌36.70% 按参考价1,252.68算:低开2.85%,收跌5.60% 我实测的复权因子也对得上:这次除权的前复权因子是0.6706,1,868.00 × 0.6706 = 1,252.68。 还有一个反证。寒武纪是科创板股票,涨跌幅限制20%。按参考价算,当天涨跌停区间是1,002.14–1,503.22元;如果错按昨收算,跌停价应是1,494.40元,而寒武纪全天都在1,158.01–1,220.00元之间成交——那就等于全天都在“跌停价以下”成交,这不可能。交易所自己用的分母,就是参考价。 代价:从持仓看,转增后股数变成1.49倍,每股还拿了1.50元现金,市值并没有少三成,但用户看到的是“亏了三成”,第一反应是截图投诉。跌幅榜挂错,运营要出面解释。做量化的拿不复权日K回测,除权日是一根假的大阴线,止损会在这天被误触发。 这不是一年碰上一次的事。10月正赶上中期分红集中除权,我实测的分红日历里,10月12日、13日两天的A股除权除息记录就超过20条。 怎么修:快照的前收和昨日收盘差得多,先标“除权除息”,涨跌按参考价算,持仓按新股数显示;回测用复权数据。 先问供应商:除权除息日的前收,是不是参考价? 场景④ 首页和详情页:同一只苹果,两个涨幅 用户看到的:首页上苹果+1.29%,点进详情页+0.47%。用户的第一反应:数据坏了。 错在哪:10月13日北京时间10:56,美股正在夜盘时段。我实测同一时刻的苹果有4个涨跌: 主快照340.97美元(周一常规盘收盘),较上周五收盘336.64,+1.29% 盘后341.36,较周一收盘,+0.11% 夜盘342.57,较周一收盘,+0.47% 夜盘较上周五收盘,+1.76%(自己算) 规则是:常规盘的涨跌,跟上一个常规交易日的收盘比;盘后、夜盘的涨跌,跟当天常规盘的收盘比。数据里写得很清楚:盘后、夜盘的前收是340.97(周一收盘),主快照的前收是336.64(上周五收盘)。四个数都对,只是分母不同。 代价:用户真正想知道的,往往是“从上周五到现在涨了多少”,答案是+1.76%,首页和详情页给他的哪个都不是。两个数并排、又不写分母,用户只会得出一个结论:这个App的数据不靠谱。到了财报季,盘后动辄跳空几个百分点,首页和详情页的差距会更大(本周五的文章专门讲)。 怎么修:同一屏上的每个涨跌幅,旁边写上时段和基准,比如“夜盘 较周一收盘 +0.47%”。 先问供应商:盘前、盘后、夜盘的涨跌,按哪个收盘算? 4个场景收在一张表里: 场景 用户看到的 错在哪 代价 怎么修 涨幅榜 苹果第一、比特币最后 5个涨跌幅量的是5段时间 名次失真,用户追错 按同一窗口重算再排 价格提醒 一家响、一家不响 黄金切日时刻不同 误触发、漏触发 规则里写明基准 持仓页 一夜“亏三成” 除权日没用参考价 恐慌、投诉、回测失真 识别除权日,按参考价算 首页/详情页 +1.29%和+0.47% 常规盘和夜盘分母不同 用户不再信任数据 每个涨跌幅标时段和基准 这4件事看起来是技术细节,其实是产品问题。卡尼曼和特沃斯基1979年提出的前景理论有一个结论:人判断得失,看的是相对某个参照点的变化,而不是绝对水平。行情App上的涨跌幅,就是替用户选好的参照点。同样4,175.15美元的金价,参照点选在24小时前,用户觉得亏了;选在北京时间0点,用户觉得赚了。谁定分母,谁就定了用户今天的情绪,所以分母应该写在界面上。 三、怎么修:跨市场统一分母,分3步 先给每个涨跌幅贴上分母标签,再按同一个窗口重算,最后单独处理除权。 1. 一张跨市场分母清单 市场 建议的分母 界面上要写的字 A股 上一交易日收盘;除权除息日用参考价 “较前收(除权调整)” 港股 上一交易日收市价 “较前收” 美股常规盘 上一常规交易日收盘 “较上一交易日收盘” 美股盘前/盘后/夜盘 当天常规盘收盘 “夜盘 较今日收盘” 黄金、外汇 选定一个切日时刻(如纽约17:00)并写出来 “较纽约17:00” 加密 滚动24小时,或指定时区0点 “24h”或“较UTC 0点” 指数(休市时段) 上一交易日涨跌并标日期,或标“休市” “10/12 收盘” 照着这张表,每个涨跌幅旁边都能写出它在跟谁比。A股参考价按交易所规则执行,其余是建议做法。 2. 三步落地 第一步,贴标签。每个涨跌幅带上基准价和基准时刻。不贴,用户拿两个App一比颜色不一样就来问;解释一次,下一个用户还会问。 第二步,统一窗口。跨市场比较(涨幅榜、资产总览、跨市场提醒)时,不比现成的百分比,用K线按同一个窗口自己重算。不重算,名次取决于谁的分母更旧。 第三步,单独处理除权。A股先判断是不是除权除息日:快照的前收和昨日收盘差得多,就按参考价或复权数据处理。 3. 为什么跨市场更难:6类资产,6套规则 只做A股,记住“前收、除权”两件事就够了。做跨市场,要同时管6套规则:A股的除权、港股的收市竞价、美股的四个时段、黄金外汇的切日时刻、加密的滚动窗口、指数的休市显示。 如果每个市场各接一家数据源,同样叫“前收”的字段,名字、时间戳格式、切日时刻都可能不一样。统一分母之前,得先写一层“翻译”;市场越多,翻译层越厚。规则还在变:美国夏令时11月1日结束,纽约17:00对应的北京时间要从早上5点变成6点,每一家数据源的处理都得重新核对一遍。 所以做跨市场行情应用,省事的做法是:一套接口拿到所有市场的快照、K线和复权数据,分母标签层只写一次。 4. 我用 TickDB 把6类资产跑了一遍 TickDB 为开发者和 AI 应用提供统一的全球行情数据接口,让团队通过一套接入获取多市场实时与历史数据,更快构建行情、分析和监控产品。 本文寒武纪、苹果、黄金、比特币、标普500的数字,都是我用同一套接口取的: 能做到 要你自己处理 6类资产(A股、港股、美股、外汇贵金属、指数、加密)的快照,用同一组字段返回现价、前收和时间戳 接口给的涨跌幅是一个现成的数,不带“分母说明”,标签要自己加 同一套K线接口覆盖各市场,可以按任意基准时刻(纽约17:00、北京0点、UTC 0点)自己重算 黄金、外汇这类没有官方收盘的品种,建议按自己选定、并写在界面上的基准重算 美股快照同时带盘后、夜盘各自的价格和前收;复权因子能还原寒武纪的除权参考价 复权数据会随新的公司行为更新,回测要记下查询时间和复权方式 左边是一套接口能直接支撑的,右边是任何数据源都替代不了的产品判断。(作者实测,2026年10月12–13日。) 5. 给技术同事:一段代码 不写代码的读者可以跳过这一节。下面这段代码做两件事:用小时K线按4种基准时刻重算黄金涨跌;自动识别A股除权除息日。 # 测试环境:Python 3.11 # 接口端点与字段名已于 2026-10-13 通过实际调用核对 import os import sys from datetime import datetime, timedelta, timezone from decimal import Decimal from zoneinfo import ZoneInfo import requests API_KEY = os.getenv("TICKDB_API_KEY") # 从环境变量读取,不要写进前端 BASE_URL = "https://api.tickdb.ai/v1/market" UTC, BJ, NY = timezone.utc, ZoneInfo("Asia/Shanghai"), ZoneInfo("America/New_York") HOUR_MS = 3_600_000 def get(path, **params): """调用接口,同时检查 HTTP 状态和业务返回码。""" try: resp = requests.get(f"{BASE_URL}/{path}", params=params, headers={"X-API-Key": API_KEY}, timeout=10) body = resp.json() except (requests.RequestException, ValueError) as e: raise RuntimeError(f"{path} 请求失败: {e}") from e if resp.status_code != 200 or body.get("code") != 0: raise RuntimeError(f"{path}: HTTP {resp.status_code}, code={body.get('code')}, {body.get('message')}") return body["data"] def pct(last, base): """涨跌幅(%)=(现价 − 基准价)÷ 基准价 × 100。""" last, base = Decimal(str(last)), Decimal(str(base)) return (last - base) / base * 100 def price_at(hourly, moment): """取某一时刻的价格:用“结束于该时刻”的那根小时K线的收盘价(K线时间戳为该小时的开始)。""" target = int(moment.timestamp() * 1000) - HOUR_MS for bar in hourly: if bar["time"] == target: return bar["close"] return None def last_moment(now, tz, hour): """now 之前最近一次 tz 时区的 hour 点(自动处理夏令时)。""" local = now.astimezone(tz) m = local.replace(hour=hour, minute=0, second=0, microsecond=0) if m > local: m -= timedelta(days=1) return m def gold_changes(symbol="XAUUSD"): """同一个现价,按4种自选基准价分别算涨跌。""" q = get("ticker", symbols=symbol, type="forex")[0] hourly = get("kline", symbol=symbol, interval="1h", type="forex", limit=48)["klines"] now = datetime.fromtimestamp(q["timestamp"] / 1000, UTC) day_ago = (now - timedelta(hours=24) + timedelta(minutes=30)).replace(minute=0, second=0, microsecond=0) # 24小时前,取最近的整点 bases = { "24小时前(近似)": price_at(hourly, day_ago), "纽约17:00收盘": price_at(hourly, last_moment(now, NY, 17)), "UTC 0点": price_at(hourly, last_moment(now, UTC, 0)), "北京时间0点": price_at(hourly, last_moment(now, BJ, 0)), } print(f"{symbol} 现价 {q['last_price']}({now.astimezone(BJ):%m-%d %H:%M} 北京时间)") for name, base in bases.items(): print(f" 较{name:<10} 基准 {base} 涨跌 {pct(q['last_price'], base):+.2f}%" if base else f" 较{name}:缺数据") def is_ex_rights_day(prev_close, last_daily_close, tol=Decimal("0.005")): """快照的前收和上一根日K收盘相差超过0.5%,大概率是除权除息日,要用参考价/复权数据核对。""" p, c = Decimal(str(prev_close)), Decimal(str(last_daily_close)) return abs(p / c - 1) > tol def check_ex_rights(symbol="688256.SH"): q = get("ticker", symbols=symbol, type="stock")[0] daily = get("kline", symbol=symbol, interval="1d", type="stock", limit=2)["klines"] yesterday_close = daily[-2]["close"] # 最后一根是今天(可能未结束),取倒数第二根 flag = is_ex_rights_day(q["prev_close"], yesterday_close) print(f"{symbol} 快照前收 {q['prev_close']} / 昨日K线收盘 {yesterday_close} → {'疑似除权除息日' if flag else '正常'}") if __name__ == "__main__": if not API_KEY: sys.exit("请先设置环境变量 TICKDB_API_KEY") gold_changes() check_ex_rights() # 历史核对:寒武纪 2026-05-08 除权除息日,参考价 1252.68,前一日收盘 1868.00 print("2026-05-08 寒武纪:", "疑似除权除息日" if is_ex_rights_day("1252.68", "1868.00") else "正常") 用10月13日10:56的实测数据跑出来的结果: XAUUSD 现价 4175.15(10-13 10:56 北京时间) 较24小时前(近似) 基准 4204.35 涨跌 -0.69% 较纽约17:00收盘 基准 4171.38 涨跌 +0.09% 较UTC 0点 基准 4170.54 涨跌 +0.11% 较北京时间0点 基准 4164.95 涨跌 +0.24% 688256.SH 快照前收 971.88 / 昨日K线收盘 971.88 → 正常 2026-05-08 寒武纪: 疑似除权除息日 三点说明: 基准价都取自小时K线。K线时间戳是该小时的开始,所以代码取的是“结束于某时刻”的那根K线的收盘价。 纽约17:00用时区库换算,夏令时自动处理,11月1日之后不用改代码。 0.5%的阈值是经验值,只负责标记;标记出来以后,要再用参考价或复权因子核对。 6. 上线前问供应商的5个问题 涨跌幅的基准价是哪个价?昨收、某个时刻的价格,还是除权后的参考价。 基准时刻是几点、哪个时区?周日开盘那几个小时怎么算?决定黄金、外汇、加密的涨跌能不能和股票放在一起。 除权除息日用不用参考价?不用,持仓页就会出现“一夜亏三成”。 盘前、盘后、夜盘的涨跌按哪个收盘算?不说清,首页和详情页就会对不上。 休市时显示上一交易日涨跌,还是0?显示0,用户会以为平盘。 常见问题 行情App的涨跌幅,为什么和别家不一样? 因为分母不同。涨跌幅=(现价−基准价)÷基准价,现价各家一样,基准价各家可以不同:A股除权日用参考价还是昨收,黄金按纽约17:00还是UTC 0点切日,加密用滚动24小时还是0点,美股夜盘跟周一收盘比还是跟上周五比。两个App的涨跌幅不一样,多半不是谁算错,而是分母不同。 跨市场涨幅榜怎么排才可比? 不要直接拿各市场现成的涨跌幅排序。先选定一个统一窗口,比如“北京时间今天0点至今”或“过去24小时”,用K线把每个品种按这个窗口重算一遍再排;休市的品种单独标出,不和交易中的品种混排。 黄金的收盘价是几点的价格? 黄金现货没有交易所规定的官方收盘价。伦敦 LBMA 黄金价格每天定两次,伦敦时间10:30和15:00;上海金每天两次,北京时间10:15和14:15;COMEX 黄金期货结算价按收盘前一段时间的成交量加权平均价确定。现货平台各自选时刻切“日”,常见的有纽约17:00、UTC 0点、北京时间0点。 为什么除权那天股价“暴跌”,涨跌幅却不大? 除权除息日的涨跌幅,基准不是昨天的收盘价,而是除权(息)参考价。寒武纪2026年5月8日前收1,868.00元,每股派现1.50元、转增0.49股,参考价1,252.68元;收盘1,182.53元,看着跌了36.7%,按参考价只跌5.6%。价格降下去的部分,换成了多出来的股份和到账的现金。 美股盘后、夜盘的涨跌是跟谁比? 跟当天常规盘的收盘比;常规盘的涨跌,跟上一个常规交易日的收盘比。2026年10月13日北京时间10:56,苹果主快照较上周五收盘涨1.29%,夜盘较周一收盘涨0.47%。首页显示主快照、详情页显示夜盘,就会出现两个不同的涨幅。 最后一个问题 你们App上的涨跌幅,分母写在哪? 今天就能做的一件事:打开自己App的涨幅榜,逐行写出每个涨跌幅跟谁比、从几点算起。写不出来的那一行,就是下一个客诉工单。 如果你只是用行情App的投资者,也可以试一次:同一时刻打开三个App,记下同一个品种的涨跌幅。不一样,多半不是谁错了,只是三个参照点。 看涨跌,先问“跟谁比”。 参考资料 LBMA,LBMA Gold Price CME Group,When FX Futures Pause: Understanding spread risk around the daily close,2026-09-29 上海证券交易所,收盘集合竞价相关说明,2018-08-06 Nasdaq,Opening and Closing Cross FAQ 香港交易所,Trading Mechanism of CAS in the Securities Market 上海黄金交易所,Shanghai Gold Benchmark Price Launching Ceremony,2016-04 CME Group,Gold 结算方法说明 寒武纪,2025年年度权益分派实施公告(公告编号2026-011) 上海证券交易所,《上海证券交易所科创板股票交易特别规定》 Spot API 文档:24hr Ticker Price Change Statistics Gate 帮助中心,如何切换涨跌幅起止时间 Kahneman, D. & Tversky, A. (1979). Prospect Theory: An Analysis of Decision under Risk. Econometrica, 47(2), 263–291
浏览52
评论0
收藏0