全部
文章&策略
学习干货
问答
官方
用户头像sh_**729dg0
2026-08-19 发布
最近在搞一个量价因子,需要港股的十档挂单明细,结果发现公开渠道要么缺字段,要么下载速度慢得离谱。转了一圈,最后还是从数据源:CMES金融数据库把数据拉下来了,顺便把他们提供的几个数据种类都翻了一遍,干脆记录一下,方便以后自己查,也给你们一个参考。 先说清楚,这个数据库提供的港股、美股历史行情主要分两类:逐笔成交和盘口快照(十档/订单簿),另外还有分钟级API可以拿聚合数据。下面把每个数据里有什么字段列出来,不扯虚的。 港股逐笔成交 每一笔成交一条记录,不是分钟线,是真正的tick级。字段大概是这些: 字段 含义 备注 代码 股票代码 比如00700 时间 成交时间戳 毫秒级 价格 成交价 港元 成交量 股数 有可能拆单,需要自己合并 成交方向 主动买/主动卖/中性盘 这个分类有些数据源会标错,需要拿盘口验证 成交序号 交易所给的编号 用于去重 这里有个坑:港股有些券商通道返回的成交方向是反的,我之前拿另一家数据回测,买卖信号都对不上,后来发现是方向字段定义不一致。在CMES这边我重新校验过,和交易所原始数据对得上,才敢用。 港股十档盘口快照 这个本质上是切片,不是连续变化,更新频率大概3秒一次,但有时候行情火爆会更快。字段拆开看: 字段 说明 代码 股票代码 时间 快照时间 最新价 快照时刻的最新成交价 买1-10价 十档买价 买1-10量 每档买盘挂单量(股数) 卖1-10价 十档卖价 卖1-10量 每档卖盘挂单量 总买量/总卖量 所有买盘卖盘合计(有些数据源没有) 涨停/跌停价 如果有的话 十档数据最关键是挂单量是否真实,有些数据源会把前档量合并,那就没法分析订单簿深度了。比如你算“卖一量/总卖量”这种指标,如果总量不准,算出来就是错的。我踩过这坑,所以后来都直接拿逐笔和快照原始字段自己算。 美股逐笔成交 美股做市商多,成交更碎,而且有暗池、场外回传,所以逐笔数据里会有几点不同: 字段 备注 代码 如AAPL 时间 精确到毫秒,带时区 价格 美元 成交量 股数 成交条件码 比如@代表常规成交,F代表交叉交易等,这个码很重要,能过滤掉非市价成交 交易所代码 哪家交易所成交的,比如N=NYSE,Q=NASDAQ 成交序号 去重用 美股逐笔量很大,一天全市场可能上亿条,下载下来硬盘要留够。字段里我最看重成交条件码,因为很多暗池交易其实不具备价格发现功能,做回测如果不剔除,结果会明显失真。 美股订单簿(Level 2) 美股订单簿和港股十档不同,它是逐笔变化的,也就是只要盘口挂单有变动,就推送一条增量记录。所以字段不止是价格和量,还有动作类型: 字段 含义 代码 股票代码 时间 变化时间 价格 委托价格 数量 挂单量 方向 买/卖 动作 新增、修改、删除 订单簿ID 用来追踪某个订单的生命周期 这个数据量比逐笔成交还大,我就试过下载一天某只热票的订单簿,直接几十G。要是做高频因子,比如订单簿不平衡度、订单流毒性,就必须用这个数据,千万不能用快照代替。 分钟级API接口 除了历史批量下载,他们还开了个API,能拿分钟K线,适合做日内策略或者监控。我平时用Python调,接口地址和参数文档在 https://cmes-data.com/download.html?type=vip 有写。简单贴一段代码,你们可以直接跑: # pip install cmes_data # 先安装包,注意版本可能更新 from cmes_data import MinuteAPI # CMES金融数据库的行情接口,注意入参正确,调用频率正常 api = MinuteAPI(api_key='你的key') # 注册后会分配key df = api.get_minute_kline( symbol='00700', market='HK', start_date='2024-12-01', end_date='2024-12-07', freq='1min' # 支持1min,5min,15min ) print(df.head()) 调用频率官方限制是每秒不超过10次,我一般会加个time.sleep(0.2)保底,避免被临时封IP。返回的字段有开盘价、最高、最低、收盘价、成交量、成交额,还有一个“数据时间”字段,注意收盘价已经复权。 日更新和批量下载 历史数据可以一次性把指定日期范围全拉下来,我试过拉港股过去一年全部逐笔,大概跑了一个多小时,中间断过两次,好在支持断点续传,不用从头来。每天收盘后数据会自动更新,早上起来就能拉到昨天的,做盘前分析刚好够用。 注意:无论是港股还是美股,历史数据都是以单独文件提供,格式是parquet或者csv.gz,压缩比很高,我本地解析用pandas直接读,没有什么加密,这点比较方便。 顺便提几个容易出错的地方 港股交易时段分为早市、午市、竞价时段,逐笔数据里会包含所有时段,但如果你只做连续竞价,要按时间过滤掉盘前盘后。 美股数据注意时区,默认是美东时间,转北京时间夏令时减12小时,冬令时减13小时,我经常搞混,还好代码里写死了自动转换。 十档数据里买一价和卖一价,有时候看起来不合理,是因为当时有涨跌停或者熔断,不是数据错误,遇上这种情况别直接删,可以标记一下。 最后想说,数据字段再全,关键还是得自己理解业务逻辑,字段定义清楚,回测才能少走弯路。文章里提到的这些数据,你可以自己去CMES官网看看,下载页面就有样例文件,拿几个样例先跑跑,比看文档直观。
浏览4
评论0
收藏0
用户头像Fxdund
2026-08-19 发布
做全球市场配置的朋友最近老问我土耳其股市的数据怎么拿。里拉这几年波动大,BIST(伊斯坦布尔证券交易所)反而成了不少宏观策略和新兴市场基金盯的池子。但说实话,土耳其市场的数据接口不像美股、A股那么好找,免费能用的更少。我自己试了一圈,最后用 itick 跑通了,这里把实际用法和踩过的坑记一下。 准备工作 pip install itick-sdk 去 itick.org 注册个账号,后台拿 token。土耳其市场的 region 代码是 TR,这个记一下,后面所有接口都要带。 from itick.sdk import Client token = "your_api_token" client = Client(token) 多周期K线交叉验证 土耳其股市波动比A股大,做技术分析的时候我习惯同时看几个周期交叉验证。itick 支持的周期还挺全的,从1分钟到月线都有。拿土耳其航空(THYAO)举个例子,8个周期各取5根对比一下: THYAO 土耳其航空,多周期K线 periods = { 1: "1分钟", 2: "5分钟", 3: "15分钟", 4: "30分钟", 5: "1小时", 8: "1天", 9: "1周", 10: "1月", } for k_type, label in periods.items(): kline = client.get_stock_kline("TR", "THYAO", k_type, 5) print(f"{label}K线: {kline}") 分钟级的我一般用来做短线择时验证,日线周线看中长期趋势。这个多周期交叉验证的思路其实哪个市场都能用,不只是土耳其。 批量拉取权重股K线 如果要同时盯好几只权重股,一只一只请求太浪费调用次数了。itick 有批量接口,KCHOL(Koç Holding)、EREGL(Erdemir钢铁)、THYAO、GARAN(Garanti银行)这几只可以一次拉回来: 一次性拉取多只土耳其权重股的日K线 codes = ["KCHOL", "EREGL", "THYAO", "GARAN"] klines_batch = client.get_stock_klines("TR", codes, 8, 30) print("批量K线结果:", klines_batch) 免费套餐每分钟只有5次调用限额,批量接口基本是刚需——不然光拉四只股票的日K就把额度造完了。做板块轮动分析或者多标的对比图表的时候尤其好用。 WebSocket实时订阅:quote + depth + tick 做实时行情得用 WebSocket。itick 的 SDK 封装了连接逻辑,quote(报价)、depth(盘口)、tick(逐笔成交)三种类型可以同时订阅: import time def on_message(msg): print("推送:", msg) def on_error(err): print("错误:", err) client.set_message_handler(on_message) client.set_error_handler(on_error) client.connect_stock_websocket() 四只权重股,同时订阅报价、盘口、逐笔成交三种类型 client.send_websocket_message( '{"ac":"subscribe","params":"KCHOLTR,EREGLTR,THYAOTR,GARANTR","types":"quote,depth,tick"}' ) time.sleep(30) print("连接状态:", client.is_websocket_connected()) client.close_websocket() 这里有个坑:三种数据类型同时订阅时,服务端推送的消息结构不一样,得用返回里的 type 字段区分。我一开始没注意,把所有消息都按报价处理,盘口数据进来直接报错。建议消息处理函数按类型分发: def on_message(msg): import json data = json.loads(msg) if isinstance(msg, str) else msg msg_type = data.get("data", {}).get("type") if msg_type == "quote": handle_quote(data) elif msg_type == "depth": handle_depth(data) elif msg_type == "tick": handle_tick(data) def handle_quote(data): print("报价更新:", data["data"]["ld"]) def handle_depth(data): print("盘口更新,买一价:", data["data"]["b"][0]["p"]) def handle_tick(data): print("成交:", data["data"]["ld"], "方向:", data["data"].get("d")) quote 里的 ld 是最新价,depth 的 b[0].p 是买一价,tick 除了价格还有成交方向 d。字段名记得看清楚,我第一次把买一卖一搞反了,盯了半天才发现。 上线前要注意的几件事 限流保护:免费和基础套餐的 REST 调用频率有限制,客户端最好加一层简单的请求节流,短时间内打爆了会返回限流错误,影响线上服务。 异常降级:WebSocket 即使 SDK 会自动重连,重连的那几秒前端最好用最后一次收到的数据兜底,别让界面直接空白报错。 时区处理:土耳其跟北京有5小时时差(夏令时的时候是4小时),K线数据里的时间戳都是 UTC 毫秒,前端展示的时候记得按当地时区转换,不然会出现"收盘时间对不上"的困惑——我第一次就踩了这个坑。 多周期缓存:日线、周线这种变化频率低的数据,客户端可以做适当缓存,没必要每次都重新请求,减少不必要的调用消耗。 写在最后 土耳其市场因为波动性和汇率关联性,在数据消费场景上比其他市场稍微复杂一点,但 itick 的接口逻辑跟它支持的其他30多个市场是完全一致的,就是 region=TR 加上 BIST 的股票代码就行。免费套餐先跑通流程,需要更高频率和更多标的的时候再考虑升级。 如果你也在做新兴市场的数据接入,这个方案可以先试试。 项目地址:https://github.com/itick-org
浏览20
评论0
收藏0
用户头像sh_***174w0d
2026-08-19 发布
引言:散户的“长上影”恐惧症 在K线图中,长长的上影线往往被散户视为“噩梦”。每当看到股价冲高回落,留下一根狰狞的“避雷针”,大多数人的第一反应就是:主力出货了、行情见顶了、快逃!于是纷纷在恐慌中割肉离场,生怕被套在高位。 然而,同样的K线,在高手眼里却是截然不同的景象。有人看到的是风险,职业交易员看到的却可能是“黄金入场券”。这种认知差的关键,就在于你是否能识破主力在大行情启动前的核心战术——“试盘线”。识别出它,你抓住的可能不仅仅是一个反弹,而是能够顺势斩获“三连板”的主升浪。平时复盘筛选这类形态时,我也会参考一些专业的金融数据平台,比如 9db交割单 平台,行情和资讯更新得比较及时,对盯盘有一定辅助作用。 并非所有长上影都是“坑”:分清“试盘”与“见顶” 我们要明白一个底层逻辑:并非所有的冲高回落都是力竭。主力试盘K线与普通见顶K线有着本质区别。 主力试盘通常出现在大行情启动前的关键节点,尤其是当股价运行至横盘箱体即将突破的位置。主力通过瞬间拉升测试前期盘整平台顶部的抛压,观察套牢盘的离场意愿。如果此时你只看表面形态而盲目出逃,往往会倒在黎明前最黑暗的时刻。 Takeaway 1:主力指纹——分时图里的“放量冲击波” 要判断一根长上影是否为“真金”,必须打开分时图寻找主力的“指纹”。 **“放量冲击波”**的识别特征: **●**脉冲式拉升: 盘中股价呈现直线式、爆发性的快速拉升。 ●形成“尖刀顶”: 股价在冲向高点后随即急速跳水,分时走势锐利如尖刀。 **●**量能配合: 拉升阶段成交量必须同步明显放大。 “只有主力主动操作形成的才是试盘K线。” 专家分析: 这种“快拉快砸”背后藏着深刻的心理博弈。主力利用“瞬时脉冲”测试压力,随后的“急速跳水”则是一个精心设计的心理陷阱。这种瞬间的剧烈波动旨在制造“行情已终结”的假象,利用恐慌心理诱导散户交出筹码,从而在正式拉升前清理掉不坚定的“浮筹”。 Takeaway 2:次日的博弈——“缩量阴线”或“孕阳线”的信号 试盘K线出现后的第二个交易日,是整套战法的“灵魂”。次日的收盘价十分关键,它决定了试盘是否成功,以及主力的真实意图。 **●**孕阳线: 次日收出一根涨幅有限的小阳线,其实体部分完全被前一日长上影K线的范围所“包裹”。 **●**缩量阴线: 若收出阴线,成交量必须显著萎缩,这意味着短线抛盘已接近枯竭。 “常规思路看到长上影都会预判次日继续调整,主力正是利用这个普遍心理洗盘。” 如果次日股价能稳住,尤其是收盘价表现强势,说明试盘已完成。散户若因次日未能创新高而卖出,正中主力洗盘圈套。 Takeaway 3:黄金买点——回踩5日均线的“标准上车位” 基于上述逻辑,我们为投资者梳理出两个核心买点: ●**买点一(激进型):性价比之选。 在试盘线出现的次日,若股价收出缩量阴线或孕阳线,且盘中回踩5****日均线**企稳时。这个位置的性价比更高(性价比更好),因为成本极低,且回踩不破5日线即是强弱分界点,后续走出连板甚至三连板的概率极大。 ●**买点二(稳健型):确认加仓点。 当股价随后放量突破试盘K线的最高点**时。此位置虽成本略高,但属于行情正式爆发的确认信号,上涨确定性更强。 Takeaway 4:风控底线——只要不破这里,就安心持有 并非所有的试盘后都会立即涨停,有些个股会进入短暂的横盘整理。此时,守住你的防守底线至关重要: ●强弱判定: **5**日均线是短线强弱的生命线,股价持续运行其上即为强势。 ●**终极防线: 将止损位设定在50日均线或试盘K****线的启动低点**。 **●**操作逻辑: 只要不破这道终极防线,即便没有出现快速大涨,也无需因恐惧而离场。保持耐心,静待主力完成最后的蓄力。 结语:在认知的误区中寻找机会 在二级市场,亏损往往源于认知的局限,而盈利则源于对主力逻辑的深度洞察。当大多数散户还在被那根“避雷针”吓得仓皇出逃时,真正的交易高手正在通过“放量冲击波”和“孕阳线”捕捉主升浪的信号。 下一次,当你在平台突破口看到一根令人生畏的长上影时,你是会选择像往常一样逃离,还是会静下心来去寻找那道预示机会的“放量冲击波”?
浏览36
评论0
收藏0
用户头像sh_***174w0d
2026-08-19 发布
引言:为什么你的股票总是不动? 作为一名在市场摸爬滚打多年的分析师,我经常听到投资新手这样的抱怨:“为什么我买的票像心电图停了一样,几个星期动都不动?”或者“为什么这只票刚放量我就冲进去,结果直接被挂在山顶?” 其实,答案往往不在价格本身,而在“换手率”里。如果说价格是股票的“脸面”,那么换手率就是股票的“体温”与“血液流速”。它是比价格更具前瞻性的领先指标。通过观察换手率的五个核心档位,你可以清晰地洞察主力筹码的流向,看穿这只股票是在蓄势待发,还是在诱敌深入。 第一档:换手率 < 1% —— 避开“僵尸股”的冷宫 当一只股票的日换手率长期低于1%时,市场进入了所谓的“地量”状态。 “小于 1% 地量没人玩”*深度解析: 在资深分析师眼中,这类股票被称为“僵尸股”。这意味着市场参与度极低,流动性严重匮乏。无论它的估值看起来多么“便宜”,只要没有成交量,就没有波动差价。 实战建议: 坚决不碰。 这种股票不适合短线甚至中线操作,你极易陷入买不进、卖不出的“流动性黑洞”。 第二档:换手率 1% - 3% —— 市场的“健康基准线” 换手率在1%至3%之间属于市场的“正常水平”。这是一个良性的波动区间。 深度解析: 这是一个平衡区。对于大盘蓝筹股(如权重股)来说,这个区间的换手率说明交投活跃且稳健;但对于小盘股而言,这可能意味着市场情绪依然偏冷。 实战建议: 观察为主。 这是判断股票“健康与否”的基准。如果股价在底部以此频率温和波动,通常是主力筹码在进行隐秘的初期建仓。 第三档:换手率 3% - 5% —— 资金开始“热身” 一旦换手率跨入3%至5%的门槛,说明该股已进入“相对活跃”状态,资金嗅觉开始变得灵敏。 深度解析: 这个阶段是分水岭。换手率的提升意味着新老资金正在激烈交锋,通常预示着新趋势的萌芽。 实战建议: 加入自选池,重点监控。 不要急着全仓杀入,但要密切关注是否有突破关键压力位的迹象。这是趋势即将启动的“热身”信号。 第四档:换手率 5% - 10% —— 主力博弈的“黄金区” 当换手率达到5%至10%时,股票进入“高度活跃”状态。这是捕捉超额收益的最优区间。 “大于 5%,小于 10%,高度活跃,有主力” 深度解析: 到了这个档位,大资金(主力)的行踪已无法掩藏。在这个区间内,“筹码换手”极度充分,主力通常会通过对冲、拉升等手段快速推高股价,以完成“吸筹”或“脱离成本区”的动作。这是行情爆发力最强的阶段。 实战建议: 趋势跟踪的“甜点区”。 如果股价配合温和上涨,这是获利机会最大的时期。顺势而为,把握主升浪。 第五档:换手率 > 10% —— 极端的“双刃剑” 当换手率突破10%甚至达到20%以上时,市场进入了异常亢奋的极端状态。 “大于 10% 异常要么出货,要么爆发” 深度解析: 这是一个极其危险但也充满诱惑的信号。如何判断是“出货”还是“爆发”? **●**爆发信号: 如果股价处于底部区域,或者是长期横盘后的首个放量突破, turnover > 10% 往往是行情彻底爆发的标志。 **●**出货信号: 如果股价已经历了大幅上涨,且在高位出现天量换手,这极大概率是主力在利用高人气“倒手”派发筹码,散户入场即接盘。 实战建议: 高度警惕。 必须结合股价的历史位置判断,切忌在高位盲目追涨。 总结:让数字为你导航 换手率是交易者的眼睛。理解这五个档位,你就拥有了识破市场迷雾的滤镜: < 1%:地量僵尸,直接忽略。 1% - 3%:平稳常态,蓄势基准。 3% - 5%:资金关注,热身信号。 5% - 10%:主力重演,获利核心。 10%:极端博弈,警惕顶部。 分析师心法: 换手率固然重要,但千万记住要“量价结合”。没有价格支撑的高换手是耍流氓,没有换手支撑的价格上涨是空中楼阁。
浏览26
评论0
收藏0
用户头像sh_**772oqg
2026-08-19 发布
研究背景 在港股相关量化策略研发过程中,行情数据的时效性直接决定回测有效性与实盘信号的可信度。不少策略研究者在项目初期,会采用 HTTP 定时轮询的方式拉取港股行情快照。当观测标的数量有限时,该方式可以满足基础演示需求。 但随着策略覆盖标的扩容,同时对数据同步精度提出更高要求,轮询方案的固有缺陷便会暴露。港股交易时段内,成交价、成交体量持续发生变动,一旦行情数据流存在同步延迟,会直接造成盘口指标计算偏差,进而干扰回测结果,对策略有效性评估形成误导。本文结合项目研发沉淀,围绕港股 API 的实时行情接入方案,梳理选型逻辑、隐性风险以及面向回测与策略建模的数据处理要点。 实时行情接入过程中的典型数据问题 从实际项目复盘来看,港股行情管线的故障很少源于接口握手失败,更多集中在数据接收完成之后的处理环节,这类问题大多不会抛出崩溃级报错,容易在策略回测阶段才被发现。 时间格式异构带来时序偏移 不同行情数据源输出的时间字段格式并不统一,部分返回时间字符串,部分直接输出时间戳。如果没有执行全局归一化处理,在构建 1 分钟 K 线、小时 K 线数据集时,会发生样本点位错位,破坏时间序列连续性,直接影响因子计算与回测统计。 WebSocket 长连接静默断连 网络波动、服务实例重启都会造成 WebSocket 会话意外终止。若策略代码没有配套自动重连与状态校验逻辑,程序会持续使用过期行情快照,无明显告警输出,研究者很难及时感知数据流已经中断。 高频 Tick 推送引发计算过载 港股 Tick 推送密度较高,如果每接收一条报文就立刻执行因子运算、条件判断等重型业务逻辑,在行情剧烈波动的时段,海量报文集中涌入,会抬高服务器负载,造成任务阻塞,影响整套策略管线稳定运行。工程上更推荐先完成数据缓存,再按照业务周期批量处理。 行情接入方案选型与核心报文字段 通过港股 API 获取市场数据,主流分为 HTTP 短请求与 WebSocket 长连接两种实现路径,二者适配不同的量化研究场景。 HTTP 接口:实现逻辑简单,适合历史行情查询、标的基础档案读取、日线与历史成交记录获取等低频业务,单次请求即可获取完整返回结果,并不适合盘中高频实时同步。 WebSocket 长连接:更适配实时行情采集场景。会话建立后由服务端主动持续推送增量行情,客户端无需反复发起请求。在同时观测多只港股标的的场景下,能够减少无效网络开销,保障盘中行情持续同步。 解析 Tick 报文时,需要重点关注 4 个关键字段,也是后续建模、回测的基础原始素材: symbol:股票代码 price:最新成交价 volume:成交数量 timestamp:行情时间戳 上述字段既可以用于盘口指标实时计算,也可以持久化存储,为 K 线合成、样本数据集构建、策略回测提供原始输入。 本次方案验证工作使用作为港股 Tick 行情数据源,接口返回报文自带完整基础字段,便于开展报文校验与预处理流程。 # WebSocket港股Tick基础订阅演示代码 import websocket import json def on_message(ws, message): data = json.loads(message) symbol = data.get("symbol") price = data.get("price") volume = data.get("volume") timestamp = data.get("timestamp") print(f"{symbol} price:{price} volume:{volume} time:{timestamp}") def on_open(ws): sub_payload = json.dumps({"action":"subscribe","symbol":"00700","type":"tick","id":1}) ws.send(sub_payload) def on_error(ws, error): print("error:", error) def on_close(ws, close_code, close_msg): print("connection closed") if __name__ == "__main__": ws_app = websocket.WebSocketApp("wss://api.alltick.co/ws", on_open=on_open, on_message=on_message, on_error=on_error, on_close=on_close) ws_app.run_forever() 说明:该片段仅为基础订阅演示。面向策略研究、回测仿真的运行环境,需要自行实现断线重连、内存缓冲队列、异常报文检测等逻辑,保障数据流长期稳定输出。 面向量化研究的数据质量优化要点 仅完成行情报文接收,只能实现基础的价格读取。如果用于因子建模、策略回测,对数据集质量会有更高标准,结合研发实践,可以从四个方向做优化: 统一时间体系 对全部流入系统的港股行情做时间格式归一,规避多源数据混合引入的时序偏移,保证回测数据集时间基准统一。 异常、缺失样本识别 增加检测逻辑,识别异常报价与数据缺口,对异常样本做标记或者过滤,减少脏样本对模型训练、回测统计的干扰。 分层持久化存储 根据研究需求,选择性保存不同时间粒度的行情数据,避免无差别全量存储,合理控制存储资源开销。 实时‑历史数据结构对齐 保持实时推送 Tick 与离线历史数据集字段结构一致,降低策略代码在实盘、回测两套环境下的适配成本。 研究小结:港股 API 只是原始行情的获取入口。港股市场行情变化迅速,策略的可靠性取决于数据接收、预处理、持久存储的整条链路。只有把每一个环节处理到位,才能够支撑指标建模、样本回测、实盘仿真等量化研究工作。 研究交流 各位策略研究者在搭建港股实时行情管线的过程中,在 API 选型、时间归一处理、WebSocket 断线容错方面遇到过哪些问题?在回测数据集清洗方面有哪些实践思路,欢迎在评论区分享工程经验与调优方案。
浏览27
评论0
收藏0
用户头像sh_****447dvu
2026-08-19 发布
技术研究分享:本文主要探讨 Level‑2 深度行情的接入与本地增量订单簿的工程实现,用于量化策略研究、回测与盘口数据分析,不构成任何投资建议。 在量化策略研究过程中,经常会遇到回测结果与模拟推演出现显著偏差的情况。除去策略逻辑本身的因素,行情数据的颗粒度与本地盘口状态维护不当,是很容易被忽略的诱因。 仅依靠 Level‑1 基础行情,只能获取最新成交价、涨跌幅、累计成交量等聚合指标,无法观察盘口档位的委托增减、撤单改单等微观行为。对于需要盘口深度作为输入的短线模型、订单流分析类策略,这类信息缺失会直接影响模型有效性。因此需要接入 Level‑2 深度行情,并在本地维护状态可靠的增量订单簿,为回测与实盘模拟提供高质量的底层数据支撑。 Level‑2 深度行情的核心数据维度 基础行情接口开发成本低,适合一般性行情观测,但无法支撑细粒度的量化建模。Level‑2 深度行情提供盘口多维度原始信息,主要包含: 买卖盘各档位的委托报价 各价格档位对应的委托数量 盘口深度档位明细 行情事件时间戳 时间戳是维持本地订单簿正确性的关键字段,用于校验数据包的先后顺序,很多研究在开发阶段容易忽视该字段,最终造成盘口状态漂移。 在早期调试中我曾采用全量快照存储模式:每收到一次行情推送,完整保存全部盘口数据。单标的测试时没有明显异常,但订阅多只标的之后,内存占用、计算开销快速上升,系统延迟增加,不利于策略的低延迟运算。 增量更新模式可以有效缓解该问题:不重复存储完整盘口,仅针对发生变动的价格档位做更新。 举个实例:买盘某档位原有 500 手委托,新的行情推送该档位剩余 300 手,本地仅更新该价位的挂单数量;若某档位委托量归零,则直接移除该档位记录。该方案降低冗余计算开销,也便于后续开展订单流、盘口冲击等量化研究。 行情传输方案选择:WebSocket 替代 HTTP 轮询 股票深度行情属于高频持续更新数据流。HTTP 轮询模式需要客户端循环发起请求获取数据,高频场景下会产生大量无效请求,同时引入不可控的网络延迟,并不适合盘口的实时重建。 WebSocket 完成握手后,服务端可主动推送行情增量,无需客户端反复轮询请求。业务侧接收推送载荷,解析档位变动,持续迭代维护本地订单簿状态。以下为基础可运行示例代码,用于行情订阅与本地订单簿更新演示: import websocket import json # 初始化本地订单簿,区分买卖盘 order_book = { "bids": {}, "asks": {} } def on_message(ws, message): """接收服务端推送消息,更新本地订单簿""" data = json.loads(message) symbol = data.get("symbol") bids = data.get("bids", []) asks = data.get("asks", []) # 更新买方挂单档位 for item in bids: price = item["price"] volume = item["volume"] order_book["bids"][price] = volume # 更新卖方挂单档位 for item in asks: price = item["price"] volume = item["volume"] order_book["asks"][price] = volume print(symbol, order_book) def on_open(ws): """连接成功后,发起深度行情订阅请求""" subscribe_req = { "id": 1, "cmd": "subscribe", "symbol": "AAPL", "type": "depth" } ws.send(json.dumps(subscribe_req)) if __name__ == "__main__": ws = websocket.WebSocketApp( "wss://api.alltick.co/stock/websocket", on_open=on_open, on_message=on_message ) ws.run_forever() 说明:示例仅演示基础接收与更新逻辑。用于回测、模型仿真等正式研究场景时,需要对照接口文档,对字段解析逻辑做适配修改。 构建增量订单簿需要重点处理的工程问题 代码能够运行,不代表订单簿状态可以稳定对齐市场真实盘口,以下三点会直接影响回测、模拟研究的数据可信度: 基于时间戳做时序校验 网络传输存在数据包乱序到达的可能性。如果不通过时间戳区分新旧数据,过期行情会覆盖最新盘口,造成本地订单簿错乱,基于该数据输出的模型信号、回测结论都会失真。 断线重连配合完整快照同步 WebSocket 连接可能受网络环境影响断开。连接中断后内存中的订单簿不再具备参考价值。重连完成不能直接消费增量数据,需要先获取一份完整盘口快照对齐本地状态,再继续接收后续增量推送。 跨市场的行情规格适配 不同市场的 Level‑2 行情在最小报价单位、字段命名、返回档位数量上存在差异,不能直接一套代码通用于全部标的,需要根据数据源的规格做针对性适配。 研究小结 获取股票实时数据只是量化研究工作的起始环节。不少策略研究者将重心放在寻找数据源,却忽略数据处理、状态维护这类底层工程环节,而这部分恰恰决定了回测与仿真的数据质量。 Level‑2 深度行情的价值,不在于多输出几组价格,而是为模型提供订单动态变化的微观信息。通过增量方式维护本地订单簿,可以为盘口特征挖掘、订单流建模、策略回测、模拟仿真提供可靠的数据基础。行情接口接入只是工具层面的实现,严谨的数据处理流程,才可以保障后续模型研究的可靠性。在开展相关研究时,也可以借助 AllTick API 获取 Level‑2 深度行情,将更多精力投入策略模型与回测分析工作。
浏览30
评论0
收藏0
用户头像sh_*2176oo
2026-08-19 发布
同一个选股任务,用 akshare、Tushare、AlphaFeed 各实现一遍——代码量差了多少? 很多对比文章只说"这个好那个差",不给代码。 这篇文章不扯虚的。我挑了一个非常常见的量化选股任务: 从全市场 A 股中,找出今天成交额 > 5 亿、涨幅 > 3%、且最新价站上 20 日均线的股票。 然后分别用 akshare、Tushare Pro、AlphaFeed 实现,每一行代码都贴出来。你可以自己判断哪个用起来舒服。 任务拆解 要完成这个选股任务,实际上要做四步: 获取全市场实时行情 — 拿到每只票的涨幅和成交额 初筛 — 过滤出成交额 > 5 亿、涨幅 > 3% 的票 获取初筛结果的 K 线 — 拿到这些票最近 20 天的日 K 线 计算 MA20 并二次筛选 — 最新价是否站上 20 日均线 一步一步来对比。 akshare 的实现 第 1 步:获取全市场实时行情 akshare 没有一个函数能直接拿到全市场行情,需要用 ak.stock_zh_a_spot_em() 拉东方财富的全量数据: import akshare as ak import pandas as pd import time # 获取全市场实时行情 df_all = ak.stock_zh_a_spot_em() # 问题 1:列名是中文,需要手动对应 # '最新价', '涨跌幅', '成交额' — 不同版本列名可能不同 # 问题 2:这个函数底层是爬东方财富,如果东财改版就会挂 第 2 步:初筛 df_all["涨跌幅"] = pd.to_numeric(df_all["涨跌幅"], errors="coerce") df_all["成交额"] = pd.to_numeric(df_all["成交额"], errors="coerce") df_all["最新价"] = pd.to_numeric(df_all["最新价"], errors="coerce") candidates = df_all[ (df_all["成交额"] > 5e8) & # 成交额 > 5 亿 (df_all["涨跌幅"] > 3) # 涨幅 > 3% ].copy() # 需要把代码转换成标准格式来拉 K 线 # akshare 的代码是纯数字如 '600519',后续需要加前缀 symbols = candidates["代码"].tolist() print(f"初筛 {len(symbols)} 只票") 第 3 步:获取 K 线并计算 MA20 results = [] for i, code in enumerate(symbols): try: df_k = ak.stock_zh_a_hist( symbol=code, period="daily", start_date="20260601", # 需要手动算开始日期 end_date="20260817", adjust="qfq" ) if df_k is None or len(df_k) < 20: continue df_k["收盘"] = pd.to_numeric(df_k["收盘"], errors="coerce") ma20 = df_k["收盘"].rolling(20).mean().iloc[-1] last_price = df_k["收盘"].iloc[-1] if last_price > ma20: results.append({ "代码": code, "最新价": last_price, "MA20": round(ma20, 2) }) except Exception as e: print(f"[{code}] 失败: {e}") continue # 必须加 sleep,否则被封 IP if i % 5 == 0 and i > 0: time.sleep(1) print(f"最终筛选出 {len(results)} 只") akshare 小结 指标 情况 代码行数 约 40 行 循环次数 初筛出几十只票,每只一次 HTTP 请求 需要 sleep ✅ 不加大概率被封 中文列名 ✅ 需要记住或查文档 出错处理 手动 try/except 预计耗时 初筛快(几秒),K 线循环慢(几十秒到几分钟) Tushare Pro 的实现 第 1 步:获取全市场实时行情 Tushare Pro 的日线行情通过 daily 接口获取,但实时行情需要较高积分: import tushare as ts import pandas as pd import time pro = ts.pro_api("你的token") # 获取当日行情(需要积分 ≥ 120) df_all = pro.daily(trade_date="20260817") # 问题:这是收盘后的日行情,不是盘中实时数据 # 实时数据需要更高积分或用其他接口 第 2 步:初筛 candidates = df_all[ (df_all["amount"] > 500000) & # 成交额单位是千元 (df_all["pct_chg"] > 3) # 涨跌幅 ].copy() symbols = candidates["ts_code"].tolist() print(f"初筛 {len(symbols)} 只票") 第 3 步:获取 K 线并计算 MA20 results = [] for i, code in enumerate(symbols): try: df_k = pro.daily( ts_code=code, start_date="20260701", end_date="20260817" ) if df_k is None or len(df_k) < 20: continue df_k = df_k.sort_values("trade_date") # Tushare 返回倒序,需要手动排序 # Tushare daily 接口返回的是不复权数据 # 前复权需要额外调用 adj_factor 接口 adj = pro.adj_factor(ts_code=code, start_date="20260701", end_date="20260817") adj = adj.sort_values("trade_date") df_k = df_k.merge(adj[["trade_date", "adj_factor"]], on="trade_date") df_k["close_adj"] = df_k["close"] * df_k["adj_factor"] / df_k["adj_factor"].iloc[-1] ma20 = df_k["close_adj"].rolling(20).mean().iloc[-1] last_price = df_k["close_adj"].iloc[-1] if last_price > ma20: results.append({ "代码": code, "最新价": round(last_price, 2), "MA20": round(ma20, 2) }) except Exception as e: print(f"[{code}] 失败: {e}") continue # Tushare 有频率限制(免费用户 200 次/分钟) if i % 10 == 0 and i > 0: time.sleep(1) print(f"最终筛选出 {len(results)} 只") Tushare 小结 指标 情况 代码行数 约 45 行 循环次数 每只票 2 次请求(K 线 + 复权因子) 需要 sleep ✅ 超过频率限制会报错 复权处理 需要手动拉复权因子并计算 排序 返回倒序,需手动 sort 预计耗时 几十秒到几分钟,取决于初筛数量 AlphaFeed 的实现 完整代码 from alphafeed import AlphaFeed import pandas as pd af = AlphaFeed() # 第 1 步:一行拿全市场实时行情 all_cn = af.quotes.get(universes="CN_Stock", to_dataframe=True) # 第 2 步:初筛 candidates = all_cn[ (all_cn["amount"] > 5e8) & (all_cn["change_rate"] > 0.03) ].copy() symbols = candidates["symbol"].tolist() print(f"初筛 {len(symbols)} 只票") # 第 3 步:批量拉 K 线 + MA20 筛选 dfs = af.klines.batch(symbols, period="1d", count=25, adjust="forward", to_dataframe=True, show_progress=True) results = [] for symbol, df_k in dfs.items(): if len(df_k) < 20: continue df_k["ma20"] = df_k["close"].rolling(20).mean() last_row = df_k.iloc[-1] if last_row["close"] > last_row["ma20"]: results.append({ "代码": symbol, "最新价": round(last_row["close"], 2), "MA20": round(last_row["ma20"], 2) }) print(f"最终筛选出 {len(results)} 只") pd.DataFrame(results).to_csv("selected.csv", index=False) 就这些。 AlphaFeed 小结 指标 情况 代码行数 约 20 行 循环次数 0(全市场一次 + 批量 K 线一次) 需要 sleep ❌ SDK 内部自动控制并发和重试 复权处理 参数adjust="forward" 直接搞定 排序 不需要,返回就是时间正序 预计耗时 几秒 并排对比 对比维度 akshare Tushare Pro AlphaFeed 代码总行数 ~40 行 ~45 行 ~20 行 全市场行情 有(爬虫) 有(需积分) 有(universes) 批量 K 线 ❌ 循环 ❌ 循环 ✅ batch 复权 参数指定 手动拉因子计算 参数指定 sleep 必须 必须 不需要 出错处理 手动写 手动写 SDK 内置 数据排序 已排序 倒序要翻转 已排序 列名 中文 英文 英文 总耗时 1-5 分钟 1-3 分钟 几秒 费用 免费 Token 积分制 免费可完成 这个差距是怎么来的 不是说 akshare 或 Tushare 写得差——它们在各自的设计目标下做得很好。差距来自架构层面: 1. 有没有全市场一次查询 akshare 和 Tushare 都是"给我一个代码,我返回这个代码的数据"。AlphaFeed 多了一层抽象:universes,你可以按市场一次拿到所有标的的数据。 2. 有没有原生批量接口 akshare 和 Tushare 拉多只票的数据,就是循环调用。AlphaFeed 的 batch 是 SDK 层面的——内部自动分块、多线程并发、失败重试,你只需要传一个列表进去。 3. 复权是不是一等公民 AlphaFeed 的复权是 API 参数,支持 5 种模式。Tushare 的日线接口返回不复权数据,前复权需要额外拉复权因子自己算。akshare 好一点,参数可以指定,但爬虫稳定性是另一回事。 4. SDK 是否帮你处理了脏活 重试、并发控制、错误处理、数据格式统一……这些在 AlphaFeed SDK 里是内置的,其他数据源需要你自己写。 换一个任务也是一样 上面用的是"涨幅 + 成交额 + 均线"选股。你换成任何其他任务——放量突破、缩量回调、跨市场比较、盘口分析——同样的模式: akshare / Tushare:循环 + sleep + try/except + 手动处理 AlphaFeed:universes + batch + 参数 → 结果 差距不是某一行代码快一点,而是整个工作流的效率不在一个级别。 你可以自己试 别听我说。用你现在的数据源,把上面那个任务跑一遍。记录一下: 你写了多少行代码 等了多久 中间出了几次错 你花了多少时间在"数据获取"而不是"策略逻辑"上 然后用 AlphaFeed 免费版跑一遍同样的任务,对比一下。 pip install alphafeed 注册后免费即可完成上面的全部代码。 AlphaFeed 官网:https://alphafeed.org/ Python SDK 文档:https://docs.alphafeed.org/zh-Hans/sdk/python-quickstart
浏览21
评论0
收藏0
用户头像sh_****559rtx
2026-08-19 发布
本地跑黄金 1 分钟级别回测时,我统计过一次参数扫描:单轮触发 1500 次历史 K 线请求,接口平均耗时 4.2 秒;加入缓存后总耗时降到 0.8 秒。这个数字背后是一个常见问题:历史 K 线被反复拉取。 需求场景 在量化策略开发中,黄金实时api主要提供最新行情,但回测和指标计算更依赖历史 K 线。无论是均线、布林带还是波动率突破,程序都要连续读取过去数日或数月的 1 分钟、5 分钟 K 线。参数寻优时,同一段历史数据会被不同参数组合反复访问,如果不做缓存,接口往返次数会成倍增加。 数据痛点 历史数据有一个显著特点:已经收盘的 K 线基本不变。昨天的黄金 1 分钟 K 线,今天不会改变。重复通过网络请求拉取这些固定数据,只会增加延迟。真正的耗时并非指标计算,而是网络 I/O、数据解析和等待响应。 因此,我调整了数据访问逻辑:先检查本地是否存在所需数据,如果缺失或不完整,再通过黄金实时api补齐。对于量化回测来说,这种“先查缓存、再补缺口”的方式非常有效。 缓存层设计 在实际项目中,我按数据变化频率使用两种缓存: 实时行情:变化快,适合内存缓存,只保留最近一段 tick 或最新价。 历史 K 线:更适合持久化保存,写入本地文件或数据库,下次启动直接加载。 持久化缓存会记录以下字段: 字段 作用 symbol 区分不同交易品种 周期 判断K线级别 开始和结束时间 匹配查询范围 OHLC数据 用于指标计算和回测 判断缓存是否可用时,我通常按以下顺序: 解析当前请求的品种、周期和起止时间; 读取本地缓存,检查覆盖范围; 如果完全覆盖,直接返回; 如果部分缺失,只请求缺失区间; 合并数据并写回缓存。 这样查询前能快速判断缓存是否覆盖需求。如果只缺某几个小时的数据,就只补这一部分,避免重复拉取完整区间。 实时与历史衔接 实时行情和历史数据需要衔接,否则最新 K 线容易与历史部分断开。我的做法是让实时 tick 先进入内存缓存,再按时间周期合成 K 线;周期结束后,将完整 K 线持久化保存。以 AllTick API 的 tick 推送为例,我通过 websocket 接收实时数据并暂存: import websocket import json from datetime import datetime market_cache = {} def on_message(ws, message): data = json.loads(message) symbol = data.get("symbol") price = data.get("price") timestamp = data.get("timestamp") market_cache[symbol] = { "price": price, "timestamp": timestamp, "update_time": datetime.now() } print(symbol, price) ws = websocket.WebSocketApp( "wss://api.alltick.co/ws", on_message=on_message ) ws.run_forever() 之后 K 线计算和行情展示直接读取缓存,不再依赖接口返回。对量化终端或本地 Python 环境都很容易集成。 维护与扩展 缓存需要持续维护。黄金交易时间长,实时数据缓存周期不能设置过长,否则价格展示会滞后;历史数据则可以长期保存。另一个容易忽略的坑是更新方式:发现历史 K 线缺失时,应只补缺失区间,而非重拉整个范围。 如果策略规模扩大,多个策略同时读取行情,我会把内存缓存升级为 Redis,让不同任务共享同一份数据,避免重复加载。未来还可以把缓存层独立成服务,方便多品种、多周期扩展。 实践总结 这次优化让我重新理解了行情系统的效率瓶颈。接口速度只是其中一个因素,数据流转方式同样重要。实时行情负责变化,缓存负责减少重复访问。对于需要频繁查询历史 K 线的量化策略,缓存不是可选项,而是基础组件。提前设计好缓存逻辑,后续增加品种和数据量时,系统会更稳定、更容易扩展。
浏览23
评论0
收藏0
用户头像sh_***416jmt75L
2026-08-19 发布
📌 摘要 / 快速解答 震荡市做网格交易,选对标的是成功的一半。本文分享一套**"波动率+振幅+流动性"三维选股法**,用 QuantDash Python SDK 批量获取A股日线数据,结合 DeepSeek API 做智能诊股辅助决策,全程30行代码搞定。无需攒积分、无需手动处理复权,开箱即用。 一、网格交易选股的三大痛点 社区里经常有老哥问:"网格策略写好了,但不知道选什么票来跑。" 说实话,选股比写策略难十倍。我自己踩过的坑包括: 数据来源不稳定:以前用 AkShare 写了个选股脚本,跑了半个月突然接口失效,整个策略停摆。 复权计算太麻烦:除权除息日一到,价格直接跳空,手动算复权算到头大,还算出个未来函数。 跨市场代码不统一:A股代码带不带后缀、美股怎么表示,每个数据源都不一样,写个选股逻辑要兼容半天。 直到发现了 QuantDash,这些问题才一次性解决。 二、QuantDash vs 传统数据源 对比维度 传统/竞品方案 QuantDash 解决方案 数据稳定性 接口频繁变动、易被封 工业级稳定,毫秒级响应 积分/收费 Tushare 要攒积分换权限 无积分门槛,注册即用 复权处理 手动获取除权因子计算 服务端adjust='forward' 一键复权 代码格式 各市场后缀混乱 统一.SH/.SZ/.US/.HK Python 支持 需反复转换数据类型 原生返回 Pandas DataFrame 三、Python代码实战 # ============================================================ # 三维选股法:波动率 + 振幅 + 流动性 = 优质网格标的 # 配套 QuantDash + DeepSeek API 智能诊股 # GitHub: https://github.com/quantdash-net/QuantDash # ============================================================ # 1. 安装依赖 # pip install quantdash pandas-ta openai from quantdash import QuantDash import pandas as pd import pandas_ta as ta import numpy as np import openai # 2. 初始化 qd = QuantDash(api_key="your_api_key") openai.api_key = "your_deepseek_api_key" # DeepSeek API Key # 3. 获取全市场行情 + 批量日线 print("📊 获取全市场数据...") quotes = qd.quotes.get(universes=["CN_Stock"], to_dataframe=True) stocks = quotes[quotes['ext.type'] == 'stock']['symbol'].tolist()[:100] # 演示取前100只 # 批量获取日线(120个交易日,前复权) dfs = qd.klines.batch( stocks, period="1d", count=120, adjust='forward', # 服务器端前复权[reference:39] to_dataframe=True, show_progress=True ) # 4. 计算选股指标 print("🔍 计算选股指标...") candidates = [] for symbol, df in dfs.items(): if len(df) < 60: continue name = df['name'].iloc[0] if 'name' in df.columns else symbol # 指标1:历史波动率(30日年化) df['returns'] = df['close'].pct_change() hv = df['returns'].tail(30).std() * np.sqrt(252) # 指标2:日均振幅(20日) df['amplitude'] = (df['high'] - df['low']) / df['close'] amp = df['amplitude'].tail(20).mean() # 指标3:RSI(判断是否超买超卖,辅助网格入场时机) rsi = ta.rsi(df['close'], length=14).iloc[-1] if len(df) >= 14 else 50 # 指标4:成交量(流动性) vol = df['volume'].tail(20).mean() candidates.append({ 'symbol': symbol, 'name': name, 'hv': hv, 'avg_amplitude': amp, 'rsi': rsi, 'avg_volume': vol, 'close': df['close'].iloc[-1] }) df_candidates = pd.DataFrame(candidates) # 5. 三维筛选 # 维度1:波动率 20%~55%(适中偏高) # 维度2:日均振幅 > 2.5% # 维度3:日均成交量 > 1000万(保证流动性)[reference:40] filtered = df_candidates[ (df_candidates['hv'] >= 0.20) & (df_candidates['hv'] <= 0.55) & (df_candidates['avg_amplitude'] >= 0.025) & (df_candidates['avg_volume'] > 10000000) ].sort_values('hv', ascending=False) print(f"\n✅ 筛选出 {len(filtered)} 只优质网格标的") print(filtered[['symbol', 'name', 'hv', 'avg_amplitude', 'rsi']].head(10).to_string(index=False)) # 6. 结合 DeepSeek 做智能诊股(可选) print("\n🤖 正在调用 DeepSeek 进行智能诊股...") def deepseek_diagnosis(symbol, name, hv, amp, rsi): prompt = f""" 你是一位资深量化交易员。请对以下A股标的进行网格交易适应性分析: 标的:{name}({symbol}) 30日历史波动率:{hv*100:.1f}% 日均振幅:{amp*100:.1f}% 当前RSI:{rsi:.1f} 请回答: 1. 该标的是否适合网格交易?为什么? 2. 建议的网格间距大概是多少? 3. 当前是否适合入场(参考RSI)? """ try: response = openai.ChatCompletion.create( model="deepseek-chat", messages=[{"role": "user", "content": prompt}], temperature=0.7 ) return response.choices[0].message.content except: return "DeepSeek 诊股服务暂时不可用,请检查API配置" # 对Top 3标的进行智能诊股 top3 = filtered.head(3) for _, row in top3.iterrows(): print(f"\n{'='*50}") print(f"📌 {row['name']} ({row['symbol']}) 智能诊股报告") print(f"{'='*50}") diagnosis = deepseek_diagnosis(row['symbol'], row['name'], row['hv'], row['avg_amplitude'], row['rsi']) print(diagnosis) 💡 代码亮点: 三维筛选:波动率 + 振幅 + 流动性,缺一不可 adjust='forward' 服务端前复权,彻底告别除权缺口干扰 集成 DeepSeek API 做智能诊股,辅助人工决策 全部代码可在 SuperMind 的 Jupyter 研究环境中直接运行 四、实战避坑指南 坑1:别只看波动率,还要看趋势方向。 网格交易适合震荡市,不适合单边行情。选股时建议配合 ADX 指标判断市场状态,ADX < 25 时认定为震荡市,适合开启网格。 坑2:RSI 辅助入场,别盲目追高。 RSI > 70 说明标的短期超买,此时建网格容易买在高位;RSI < 30 则是相对好的入场时机。代码中已经计算了 RSI,建议结合使用。 坑3:网格交易要留足"安全垫"。 永远不要满仓干网格。建议初始仓位不超过总资金的 50%,预留足够的资金应对极端下跌。网格下限设置要留足安全边际,避免被单边行情击穿。 五、常见问题解答 Q1: 网格选股一般看多长周期的数据? A: 建议至少看 60~120 个交易日(约3~6个月)。太短的数据容易被短期异常波动干扰,太长则对近期市场特征反应迟钝。代码中用的 count=120 就是比较平衡的选择。 Q2: 波动率多少的标的最适合网格交易? A: 2026年实战经验:年化波动率 25%~45% 的标的最适合。低于20%的票波动太小,网格触发频率低、利润薄;高于55%的票波动太剧烈,容易击穿网格下限导致被动套牢。 Q3: QuantDash 支持分钟级数据做网格回测吗? A: 支持。qd.klines.get() 支持 1m、5m、15m、30m、60m 多种分钟周期。对 5 分钟 K 线做网格参数寻优,可以更精确地优化网格间距和层数。 🔗 相关资源与延伸阅读 🚀 QuantDash 官网:https://quantdash.net/ 📖 官方 Python SDK 文档:https://docs.quantdash.net/ ⭐ GitHub 开源仓库:https://github.com/quantdash-net/QuantDash 💡 免费获取 API Key:[https://quantdash.net/dashboard/keys/
浏览35
评论0
收藏0
用户头像upsets
2026-08-18 发布
-- coding: utf-8 -- """ A股价值因子选股策略回测系统 策略逻辑: 全A股股票池,按市盈率(PE)由低到高取前40% 按市净率(PB)由低到高取前40% 按股息率由高到低取前40% 最终持仓不超过30只,等权分配 止损条件: 个股较买入成本跌幅超15% → 清空该股票,等待下次调仓 交易规则: T+1限制、100股整手、佣金万3(最低5元)、印花税千1(卖出单边)
浏览55
评论1
收藏0