全部
文章&策略
学习干货
问答
官方
用户头像sh_****447dvu
2026-07-21 发布
一、研究背景:多连接架构对量化回测的系统性干扰 在多市场量化策略研发过程中,行情数据接入架构会直接决定回测结果可信度。常规 WebSocket 接入方案存在两类可复现工程缺陷,会对日线 K 线生成、时序数据对齐、策略样本统计产生持续性偏差: 频繁切换标的引发连接雪崩 若每新增 / 移除观测标的就重建 WebSocket 通道,用户批量切换股票、外汇、大宗商品观测池时,服务端会瞬时生成大量并发连接,文件句柄、线程池资源触达阈值后,实时 Tick 发生限流丢弃。缺失 Tick 会导致分钟 K、日线高低开失真,回测样本集完整性受损。 多通道分时区计算造成日线分割 每条独立连接单独执行时区、交易日判定逻辑,服务器 UTC 时间、交易所本地交易时间、本地程序时间三者混杂运算,同一笔成交时间戳会被划分至两个自然日,生成两条无关联日线记录。该偏差会改变标的当日收益率、波动率、成交量等核心因子取值,导致回测曲线与实盘收益出现不可解释偏移。 此前测试多套行情 API 对接方案,多数接口不支持连接存续期内动态调整观测标的,只能通过销毁重建通道变更订阅,无法从底层消除时序错位与连接过载问题。基于量化数据严谨性需求,本文落地单长连接动态增减订阅架构,完整记录工程逻辑、可复用代码、边界校验规则与回测改善效果。 二、传统订阅架构隐性算力与数据损耗拆解 连接初始化固定开销持续叠加​ 新建 WebSocket 需完成 TCP 握手、Token 鉴权、批量订阅下发、心跳维护全流程,多标的高频切换场景下,重复初始化持续占用服务器与本地算力,批量回测批量加载标的时会拉长数据预热耗时。 内存 Tick 缓存重复冗余 多条通道同时订阅同一标的,内存中存在多份独立 Tick 缓存,分 K、日 K 聚合逻辑重复执行,批量回测多品种组合时内存占用线性抬升,拖慢模型迭代速度。 交易日、时区规则重复运算 同一市场标的在多条连接中重复执行夏令时、节假日、开盘收盘边界判断,无规则复用机制,批量回测场景 CPU 利用率显著偏高。 时序断层破坏连续样本区间 通道重建间隙存在数秒数据真空,回测时会缺失区间内成交数据,日内高频策略、短线反转模型的信号生成逻辑出现失真。 三、单连接动态订阅核心定义 单连接动态订阅指复用单条长期存续 WebSocket 长连接,通过标准化指令携带新增 / 移除标的编码列表,在不关闭、不重建 Socket 的前提下实时调整观测标的集合。该架构区分销毁重连、REST 轮询两类传统接入方式,鉴权、心跳、时区转换、交易日判定逻辑全链路复用,从源头减少重复计算与时序分裂风险,适配批量回测、多因子模型训练、多标的组合监测等量化场景。 四、行情 API 动态订阅量化开发对照表 业务场景 量化开发痛点 API 动态订阅配置规范 数据校验基准 程序启动批量加载观测池 回测初始化缺少完整日线、Tick 数据 指令 cmd_id=2200,action=add,code 传入标的数组 on_open 一次性下发指令,本地集合持久存储全部观测 code,启动阶段无数据断层 回测中途新增标的样本池 重建连接导致当前时序数据中断,样本区间不连续 指令 cmd_id=2200,action=add,code 传入新增标的编码 下发前本地集合去重,规避重复订阅产生双倍 Tick 流干扰因子计算 剔除回测无效标的 废弃标的持续推送 Tick,占用算力、干扰数据清洗 指令 cmd_id=2200,action=del,code 传入待剔除标的 指令下发后回调过滤该标的全部数据,减少无效数据遍历开销 边界:重复下发新增指令 重复订阅造成 Tick 流量翻倍,因子计算重复执行 指令 cmd_id=2200,action=add,传入已存在 code 本地集合前置校验,重复编码直接拦截,不发起网络请求 边界:空标的列表指令 程序异常生成空数组,触发服务端无效返回,中断数据同步 指令 cmd_id=2200,add/del 搭配空 code 数组 本地增加参数校验逻辑,空列表直接阻断下发,保障回测数据同步稳定性 五、Python 标准化接入代码(适配量化回测数据采集) import websocket import json import time # 股票品类专用WSS接入地址 STOCK_WSS_URL = "wss://quote.alltick.co/quote-stock-b-ws-api?token=YOUR_TOKEN" # 外汇、贵金属、加密通用WSS接入地址 COMMON_WSS_URL = "wss://quote.alltick.co/quote-b-ws-api?token=YOUR_TOKEN" # 全局订阅集合,用于回测标的管理、去重、动态剔除 subscriptions = set() def send_subscribe_cmd(ws, action, code_list): """统一订阅指令封装,action支持add新增 / del剔除""" # 参数边界校验,过滤空列表、无效编码 if not isinstance(code_list, list) or len(code_list) == 0: return valid_codes = [c for c in code_list if isinstance(c, str) and c.strip() != ""] if len(valid_codes) == 0: return cmd = { "cmd_id": 22004, "action": action, "code": valid_codes } ws.send(json.dumps(cmd)) def on_open(ws): """连接初始化,批量加载回测基础标的池""" print("WebSocket通道建立,执行回测标的初始订阅") # 多市场标的示例:美股、港股、加密标的 init_codes = ["NASDAQ:AAPL", "HKEX:00700", "BTCUSDT"] global subscriptions for c in init_codes: subscriptions.add(c) send_subscribe_cmd(ws, "add", init_codes) def on_message(ws, message): """Tick数据回调:仅做过滤分发,复杂K线、因子计算后置异步线程""" # 过滤空报文,减少量化数据清洗无效开销 if not message or len(message.strip()) == 0: return try: data = json.loads(message) tick_code = data.get("code") # 过滤已剔除标的残留幽灵数据,避免污染回测数据集 if tick_code not in subscriptions: return # 行情空值防护,剔除无成交无效Tick price = data.get("price", 0) open_24h = data.get("open_24h", 0) if price == 0 and open_24h == 0: return # 此处可接入Tick入库、K线聚合、因子实时计算模块 print(f"{tick_code} Tick接收,现价:{price}") except json.JSONDecodeError: return def on_error(ws, error): print(f"通道异常,中断数据采集:{str(error)}") def on_close(ws, close_code, close_msg): print(f"连接断开,清空本地标的集合,回测数据采集暂停,关闭码:{close_code}") global subscriptions subscriptions.clear() if __name__ == "__main__": # 10秒心跳周期,提前识别假死通道,防止静默丢失回测数据 ws_app = websocket.WebSocketApp( COMMON_WSS_URL, on_open=on_open, on_message=on_message, on_error=on_error, on_close=on_close ) # 模拟回测运行中动态增减标的样本池 def backtest_adjust_symbol_task(): time.sleep(10) # 回测新增外汇、贵金属观测标的 send_subscribe_cmd(ws_app, "add", ["EURUSD", "GOLD"]) global subscriptions subscriptions.update(["EURUSD"]) time.sleep(20) # 回测剔除外汇标的样本 send_subscribe_cmd(ws_app, "del", ["EURUSD"]) subscriptions.discard("EURUSD") import threading threading.Thread(target=backtest_adjust_symbol_task, daemon=True).start() ws_app.run_forever(ping_interval=10) 六、量化数据采集高频故障与标准化兜底方案 1. 高并发 Tick 涌入,主线程回调阻塞,回测数据堆积 现象:单通道订阅 20 只以上标的,每秒千级 Tick 推送,时区转换、日线聚合同步在回调执行,消息队列持续膨胀,批量回测时数据入库延迟抬升,样本时序错位。 检测指标:未处理 Tick 队列长度、单回调平均耗时;连续 5 秒队列持续增长触发采集告警。 兜底方案:WebSocket 回调仅执行数据过滤与转发,时区换算、日线切割、因子计算、数据入库全部交由独立异步线程池执行,隔离采集与计算逻辑。 2. 网络波动产生假死 Socket,无关闭回调静默丢数据 现象:公网瞬时断连,心跳报文无法交互,但通道句柄未触发 on_close,回测长时间无新 Tick 流入,样本区间出现隐性缺失,人工难以察觉。 检测指标:单标的连续 15 秒无新 Tick 记录标记为异常通道。 兜底方案:业务层增加标的数据超时检测,超时自动断开重建通道,重建前清空本地订阅集合,防止新旧通道数据混杂污染回测库。 3. 快速调整标的池引发订阅指令竞态,本地与服务端标的不一致 现象:回测批量增删标的时,指令异步到达顺序错乱,本地订阅集合与服务端观测标的不匹配,出现部分标的无数据、部分标的重复 Tick 流入,因子重复计算。 检测方式:每条订阅指令附加时间戳,定时对比实时 Tick 编码与本地标的集合差值。 兜底方案:单通道内订阅指令串行排队下发,上一条标的调整逻辑执行完成后,再下发下一条变更指令,保障订阅状态强一致性。 4. 标的编码缺失交易所命名空间,订阅静默无数据,回测样本缺失 现象:仅传入标的简码(AAPL、00700)未携带市场前缀,指令下发无报错日志,但长期无 Tick 返回,回测直接缺失该标的全部历史与实时数据。 检测机制:内置全市场编码映射表,下发前校验 code 市场命名空间前缀。 兜底方案:编码格式校验失败直接拦截指令,输出标准化日志记录无效编码,不发起无效网络请求,避免回测流程无提示中断。 七、架构能力边界说明 本单连接动态订阅架构仅支持单条活跃 WebSocket 内部调整标的 code 列表;不支持多通道间订阅状态同步、不提供历史 Tick 批量回溯接口,仅 cmd_id=22004 标准订阅变更指令具备长期兼容性,量化系统开发需基于该约束设计数据采集流程。 八、落地后量化业务可观测改善指标 连接资源消耗显著下降:单数据采集进程仅维持一条长连接,批量回测加载数十只标的无连接雪崩风险,服务端并发承载能力提升,大规模多因子回测预热耗时缩短。 重复算力消耗消除:同一通道全部标的共享一套时区、交易日、夏令时规则,批量回测 CPU 平均利用率下降,多模型并行训练效率提升。 日线时序分裂问题完全消除:全部 Tick 经过统一链路时区换算,同一成交时间戳只会归属单一交易日,回测日线 OHLC、成交量、因子取值无系统性偏移,策略曲线可复现性提升。 业务迭代成本降低:新增市场、新增观测标的仅更新编码映射表,无需重构连接初始化、批量订阅整套采集逻辑,拓展多资产回测池周期缩短。 整套架构优化效果可通过 WebSocket 流量日志、本地订阅集合快照、日线数据库记录交叉核验,适用于日内高频、波段多因子、跨资产组合等各类量化回测与实盘监测场景。 九、研究小结 在量化策略开发流程中,行情数据采集架构的底层缺陷会形成系统性回测偏差,直接影响模型参数筛选、收益风险评估、实盘适配判断。单连接动态订阅架构通过统一通道管理、复用时间计算逻辑,解决连接过载、时序分裂两大核心数据问题,属于低成本、高收益的标准化工程优化方案。 若当前正在搭建覆盖 A 股、港股、美股、外汇、贵金属的跨资产回测平台,需要频繁调整观测标的样本池,该 WebSocket 动态订阅采集方案可直接集成至数据采集模块。实测过程中 AllTick API 完整实现本文全部动态订阅接口规范,配套多语言示例代码与完整时间字段说明文档,能够减少时区适配、订阅逻辑开发工作量,研发重心可更多倾斜于因子挖掘、策略回测、模型优化等核心量化研究工作。
浏览5
评论0
收藏0
用户头像sh_*219t3e
2025-11-06 发布
最近我专门针对 Supermind 平台的AI 量化代码生成平台进行了优化改进,现在效果比市面上的 DS、豆包等工具好很多。 👉 SuperMind AI量化代码生成平台 这个工具最大的特点是直接和 AI 对话就能生成完整可运行的Supermind量化策略代码。你不需要懂 Python、C# 或策略 API,只要用自然语言描述你的交易逻辑,比如:“当5日均线向上突破20日均线时买入,反向时卖出。” AI 就会自动帮你生成完整策略代码,并能直接在平台上运行。 相比于通用大模型的输出,这个平台针对量化交易进行了专门优化生成的代码结构更清晰,逻辑更准确,对策略逻辑的理解更接近量化开发者的思路,并且可用作 API 查询或策略自动生成工具 之前上线后,很多朋友反馈代码质量和可运行性都非常高,几乎不需要再手动修改。现在我们的AI量化代码生成平台已经全面支持 Supermind,你可以直接体验。如果你之前在用 DS、豆包等平台,不妨试试看这个版本,可能会刷新你对AI 写量化策略的想象。
浏览5015
评论76
收藏7
用户头像sh_**772oqg
2026-07-21 发布
一、研究落地背景 在为机构与个人量化研究者搭建行情采集、回测配套数据链路的过程中,发现一类普遍存在的模型失真问题:仅依托 Tick 逐笔成交、Level1 一档盘口数据构建短期流动性研判模型时,历史回测收益、风险指标表现稳定,但接入实时模拟行情后,信号有效性大幅下滑,大量前置资金异动信号无法被捕捉。 此前落地日内波动预测研究框架时,初期数据输入仅包含成交记录与最优一档报价。在窄幅震荡行情中,模型输出具备基础参考性;但开盘竞价、尾盘集中换手、大额订单冲击等典型流动性切换场景下,指标偏离度显著抬升。经全链路溯源验证,核心约束来源于数据源信息维度不足:Tick 数据仅留存已完成撮合的交易结果,Level1 数据无法覆盖多档位埋伏委托,难以完整还原价格形成阶段的多空委托博弈,流动性拐点预判存在天然短板。 本文基于生产级 Websocket 长连接采集方案,完整拆解 Level2 全深度行情接入、本地订单簿维护、线上数据稳定化处理全流程,配套可直接调试的 Python 基础示例,适用于微观结构研究、日内高频策略、流动性测算类量化研究工作。 二、三类行情数据源的研究适用边界 开展量化建模前,需根据研究目标匹配对应行情数据,三类数据的信息承载能力与适用场景存在明确区分: Tick 逐笔成交数据 存储每一笔撮合成交的价格、委托量,主要用于 K 线合成、历史收益回测、事后成交行为统计。局限性为仅反映交易事后结果,无法观测未成交限价单带来的潜在价格支撑与抛压。 Level1 一档盘口数据 仅返回当前最优买、卖一档价格及对应挂单规模,可用于简易行情观测类工具开发。缺陷是无法识别多价位分层托单、压单,对短期流动性强弱的测算存在系统性低估。 Level2 全档位深度数据 完整留存全部价格档位的买卖委托剩余量,能够完整刻画市场分层委托分布,是量化研究中捕捉盘口失衡、测算瞬时流动性、预判短期价格转向的核心底层数据。 典型研究场景佐证:关键支撑价位批量新增限价买单、阻力区间多档位卖单集中撤单这类具备前置预判价值的市场信号,仅可通过 Level2 深度数据识别,单纯依托成交数据无法提前观测。 三、选用 WebSocket 承载 Level2 实时数据流的技术逻辑 传统 HTTP 轮询模式不适用于高频深度行情采集,存在两处核心工程短板:固定周期拉取会丢失毫秒级盘口增量变动,高频轮询请求持续消耗接口带宽资源,长期部署运维成本偏高。 Level2 盘口具备毫秒级持续更新特征,双向持久 WebSocket 长连接为适配该场景的标准方案,完整数据流转流程分为四阶段: 客户端与行情网关建立持久双向通信通道; 向网关提交指定标的、Level2 数据类型的订阅指令; 网关持续下发盘口增量变更数据包; 本地程序依托历史完整盘口快照,实时迭代更新订单簿状态。 量化研究高频踩坑要点:主流行情接口均采用增量推送机制,不会单次下发完整全档位盘口。本地若无快照持久化逻辑,仅依靠单条增量报文渲染盘口,会出现价位缺失、总委托量计算失真,直接影响流动性失衡、盘口压力等核心因子回测精度。 四、Level2 增量报文核心字段与订单簿存储架构 解析增量盘口、维护本地持久快照时,五类核心字段为因子计算、时序校验的基础输入,缺一不可: symbol:标的唯一代码,用于多标的并行研究时的数据隔离; side:委托方向标识,区分买方 bid、卖方 ask; price:本次更新对应的价格档位; size:当前价位剩余未成交委托总量; timestamp:数据生成时间戳,用于多流时序对齐、断线缺失数据校验。 工程存储方案采用买卖档位分离设计,使用两组独立数组分别存储全部买、卖价位委托数据。收到增量更新报文后,依据买卖标识修改对应价位委托规模;若 size 数值归零,则移除该档位记录。该架构无需遍历全量价位即可快速提取最优买卖价、累计盘口深度,降低多标的并行回测、实时推演的计算开销。 五、轻量化 Python 订阅基础示例 行情采集模块采用通信层、解析层解耦设计,保障长连接 7×24 小时稳定运行,研究环境数据接入作为数据源,基础可运行代码如下,生产回测环境仅需补充档位更新逻辑即可实现完整本地订单簿维护: import websocket def receive_data(ws, msg): data = eval(msg) code = data.get("symbol") price = data.get("price") vol = data.get("volume") print(f"标的:{code},当前价位:{price},委托量:{vol}") def connect_init(ws): sub_info = {"action": "subscribe", "symbol": "MSFT", "type": "level2"} ws.send(str(sub_info)) if __name__ == "__main__": ws_client = websocket.WebSocketApp("wss://api.alltick.co/stock/websocket", on_open=connect_init, on_message=receive_data) ws_client.run_forever() 六、7×24 小时稳定采集配套标准化优化策略 Level2 数据流每秒产生大量增量报文,网络瞬时中断、时区时间标准差异,均会造成数据断档、时序错乱,干扰回测与实盘推演一致性。经过多套量化研究系统落地验证,四类标准化兜底机制可显著降低数据修复人工成本: 定时盘口快照持久化 固定周期缓存完整买卖档位数据,断线重连后直接读取快照恢复盘口状态,无需全量拉取历史数据同步; 时序校验脏数据过滤 比对新旧报文时间戳,自动剔除时序倒置、重复推送的异常数据,避免委托量重复累加造成因子计算偏差; 断线自动补全同步逻辑 通信断开重连后自动发起补数请求,补齐断档期缺失的盘口增量记录,保证数据流完整可用于连续回测; 价格、委托量阈值降噪机制 设置合理波动上下限,自动过滤瞬时跳价、异常超大虚假挂单等噪声数据,规避极端脏数据导致模型信号突变。 配套标准化处理细节:多数行情网关原生输出 UTC 时间戳,回测、分时区间统计阶段若混用本地时区会产生时序错位,建议在数据解析环节统一转换标准时区,从源头消除时间维度测算误差。 七、研究落地总结 多数量化研究者会将重心放在因子、模型迭代上,容易忽视底层行情采集链路对回测、实盘一致性的决定性作用。搭建 WebSocket 连接仅为基础环节,订单簿持久存储、断线数据恢复、多流时序统一等工程细节,才是缩小回测与线上推演偏差的核心。 Tick 成交数据仅反映交易结果,Level2 全深度盘口能够完整还原市场参与者前置委托行为,为日内高频策略、流动性风险模型、盘口失衡因子研究提供多层观测维度。对于侧重短期资金流向、微观结构的量化研究,标准化 Level2 实时数据采集体系,能够有效提升模型泛化能力,让回测结论具备实盘推演、落地参考价值。
浏览7
评论0
收藏0
用户头像sh_****559rtx
2026-07-21 发布
你正在搭建一个贵金属日内量化策略,回测了均线、波动率等经典因子,夏普比率总是差点意思。反复琢磨后你意识到,传统因子集中在价格本身,对极短线的买卖力道变化不够敏感。有没有办法从订单簿直接提取一个有效的微观结构因子?有,这就是盘口不平衡度。今天结合我在金融科技平台做策略开发的经验,和你聊聊如何用实时盘口API构建这个因子,为你的策略增加一层短线感知力。 策略研发需求:从行情数据中榨取新Alpha 你的量化模型需要更原始的信号源。金价波动时,买卖挂单的分布往往先于价格变化。比如突破阻力位前,卖单可能在触及时被瞬间吃掉,而更深层的卖单却来不及补充。你需要的,正是能捕捉这种瞬时失衡的结构化数据。如果能把盘口各档位挂单量提炼成一个连续因子,就相当于给策略装了一个“动能感应器”。 传统数据的痛点:盘口快照太薄,轮询太慢 你或许尝试过用免费数据源取买一卖一,但用来做因子会发现噪音过大,信号不稳定。核心问题在于信息深度不足,且轮询获取的方式丢失了中间挂单变动。对于贵金属这种高流动性标的,盘口变化以毫秒计,一旦漏掉某次大单闪现,因子失真度就会上升。你需要的是一个能够实时推送多层深度的数据管道,保证数据连续、完整。 数据支撑:WebSocket实时计算订单簿不平衡因子 我选用了AllTick提供的贵金属行情WebSocket接口,它直接推送tick级深度数据,避免了轮询的延迟和漏单问题。基于此,我们构建一个基本的日内失衡因子: 因子值 = (买方总挂单手数 - 卖方总挂单手数) / (买方总挂单手数 + 卖方总挂单手数) 因子值归一化在-1至1之间,具备良好的可比性。它的状态映射如下表,你可以直接用于策略条件判断: 状态 表现 含义 买方总挂单占优 因子值 > 0 短期承接力量较强,利于反弹或突破 卖方总挂单占优 因子值 < 0 短期压力显著,回调风险增加 双方向力均衡 因子值 ≈ 0 多空胶着,方向不明 在实际策略中,你可以设置阈值,例如当因子值从负值区快速回升至+0.2以上时,触发做多条件,并结合价格位置过滤假信号。下方的代码块展示了如何通过Python原生接入WebSocket,实时输出因子值,你可将其集成到自己的信号生成模块中。 import websocket import json def on_message(ws, message): data = json.loads(message) symbol = data.get("symbol") bid_volume = float(data.get("bidVolume", 0)) ask_volume = float(data.get("askVolume", 0)) total = bid_volume + ask_volume if total > 0: imbalance = (bid_volume - ask_volume) / total else: imbalance = 0 print( symbol, "盘口不平衡度:", round(imbalance, 4) ) def on_open(ws): subscribe_data = { "action": "subscribe", "symbol": "XAUUSD", "type": "depth", "id": 1 } ws.send(json.dumps(subscribe_data)) ws = websocket.WebSocketApp( "wss://apis.alltick.co/websocket-api/stock-websocket-interface-api/transaction-quote-subscription", on_open=on_open, on_message=on_message ) ws.run_forever() 策略升级:将失衡因子嵌入你的短线模型 获取稳定因子流后,你的升级方向很清晰。你可以计算因子在短周期内的均值和标准差,构建类似布林带的动态阈值;也可以将失衡因子与成交量、价格波动率结合成复合信号。更进一步,还可分别计算前五档的加权失衡度,给更靠近最新价的档位更高权重。不管哪种方式,核心都是把盘口微观力量引入决策系统。你会发现,原本模糊的日内杂波中,逐渐浮现出可捕捉的短期倾向。这种源于真实订单簿的因子,是你策略升级时值得重视的“隐秘武器”。
浏览7
评论0
收藏0
用户头像9点半量化
2026-06-04 发布
上一篇文章里,我作为一个量化小白,花了不少篇幅拆解了社区大佬的小市值策略——五道风控防线、九项年报排雷、动态持仓调节……拆完之后我有一个很直观的感受:这套策略的内核是"活得久",靠的是极致风控 + 小市值弹性。 但最近两个月盯盘下来,我发现一个问题:ETF行情太好了。 纳指ETF、黄金ETF、港股互联网ETF……这些标的动辄月涨10%+,而且波动远小于小市值个股。我手里的小市值策略虽然在A股震荡行情里能吃到肉,但碰到「市场整体偏弱、ETF板块性行情轮动」的阶段,就会显得力不从心——小市值在休息,ETF在狂飙,两边接不上。 于是我开始在社区里大量翻阅ETF轮动相关的帖子和策略,学习各位大佬的思路。看了十几篇帖子之后,我萌生了一个想法:能不能把小市值和ETF轮动组合起来,搞一个"双核引擎"? 说实话,ETF轮动这块我是完完全全的新手。下面文章里涉及的ETF池子构建、动量打分、滤波器选择等,都是我在社区里反复学习、参考了多位大佬的策略和文章后,慢慢拼凑理解出来的。如果有理解不到位的地方,还请各位前辈多多指教? 小市值负责在A股弹性行情里捕捉超额;ETF轮动负责在板块行情里追趋势。两个引擎交替发力,互相补位——我给它起了个名字:「双龙出海」。 一、为什么要加ETF?先看数据说话 单跑小市值策略,5年30倍,年化收益极高,但有一个问题:回撤集中在大盘系统性下跌的阶段。当大盘暴跌时,小市值股票的跌幅往往比大盘还狠。 而ETF轮动策略有一个天然优势:它可以在全球资产中切换。A股不行就切港股ETF,港股不行就切纳指ETF,纳指也不行就直接买货币基金(银华日利 511880)躺平。 加上ETF之后效果怎么样?我跑了2021年至今的回测,结果直接把我看傻了: 指标 双龙出海(小市值+ETF) 基准(沪深300) 总收益 4632.93%(约47倍) -9.11% 年化收益 112.53% — 最大回撤 15.50% — 夏普比率 4.589 — 索提诺比率 7.535 — 胜率 56.7% — 盈亏比 2.505 — 阿尔法 1.115 — 贝塔 0.502 — 5年47倍,年化112%,最大回撤才15.5%——对比上一篇纯小市值的"5年30倍17回撤",收益从30倍提升到47倍,回撤反而从17%降到了15.5%。 说白了就是:加了ETF引擎之后,不仅赚得更多了,还更稳了。这不就是"既要又要"的最佳答案么? 维度 纯小市值 小市值 + ETF轮动 进攻性 ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐ 防守性 ⭐⭐⭐ ⭐⭐⭐⭐⭐ 行情适应性 A股弹性行情 全市场+全球资产 空仓时的机会成本 高(只能买货币ETF) 低(自动切到强势ETF) 核心逻辑:小市值是矛,ETF轮动是盾——双核协同,攻守兼备。 二、架构设计:两个子账户,各管各的 双核策略的架构其实不复杂,核心就是子账户隔离: 总资金 100% ├── 子账户0:小市值策略(50%) │ └── 每周二调仓,选中证1000最小市值股票 └── 子账户1:五福ETF轮动(50%) └── 每日午后轮动,从100+只ETF中挑最强的1只 聚宽提供了 set_subportfolios 的功能,可以把一个账户拆成两个独立子账户,各自有独立的持仓和资金,互不干扰: set_subportfolios([ SubPortfolioConfig(cash=小市值资金, type='stock'), # 子账户0 SubPortfolioConfig(cash=ETF资金, type='stock'), # 子账户1 ]) 这样做的好处是: 策略之间完全隔离:小市值止损不会影响ETF持仓,反之亦然 资金分配清晰:各占50%,不会出现一边吃掉另一边资金的情况 独立记录收益:可以分别看两个策略各自的表现,方便归因分析 三、ETF轮动引擎拆解(站在大佬肩膀上) 小市值部分的逻辑我在上一篇已经拆过了,这里重点讲ETF轮动部分。 先说声感谢:ETF轮动这块我参考了社区里很多大佬的策略和思路,包括ETF池子的构建方式、动量打分的数学方法、震荡期切换机制等。我做的更多是「学习→理解→整合」的工作,算不上什么原创,更像是一个学习笔记。如果哪位大佬看到觉得某个模块眼熟,那大概率就是从您那学来的? 3.1 ETF池子:固定池 + 动态池,双池合并 ETF轮动的第一个难题是:从哪些ETF里选? 我学习到的一个很聪明的做法——固定池 + 动态池合并: 固定池​(108只):手工精选的优质ETF,覆盖黄金、白银、纳指、恒生、各行业板块等 动态池​(全市场扫描):每天从全市场ETF中自动筛选流动性达标的头部标的,去重后取行业最强的那一只 关键过滤逻辑: 剔除宽基指数ETF(沪深300、中证500等——这些不是行业轮动标的) 剔除债券/货币类ETF(短融、国债、可转债等——这些不是趋势标的) 流动性门槛:日均成交额低于全市场ETF均值/20000的,直接淘汰 行业去重:同行业多只ETF时,只保留成交额最高的那一只 最终合并出约100-150只ETF的"作战池"。 3.2 动量打分:拉普拉斯滤波 + 高斯滤波 ETF轮动最核心的问题是:怎么判断哪只ETF最强? 策略用的是加权线性回归 + 数学滤波器的组合方案: 动量得分计算(25日回看): 1. 对收盘价取对数 2. 用加权最小二乘法拟合趋势线(近期数据权重更高) 3. 斜率年化 → 年化收益率 4. 计算R²(拟合优度)→ 趋势稳定度 5. 动量得分 = 年化收益率 × R² 说人话就是:涨得快还涨得稳的ETF,得分最高。 但这还不够。策略额外加了两层数学滤波器,用来判断"该不该现在买": 滤波器 用途 触发条件 拉普拉斯滤波(正常期使用) 平滑价格,识别趋势 价格 > 滤波值 且 斜率 > 0.002 高斯滤波(震荡期使用) 更强的降噪,更保守 价格 > 滤波值 且 斜率 > 0.002 正常行情用拉普拉斯(灵敏一点,抓趋势),震荡行情切高斯(保守一点,少挨打)。两个滤波器自动切换,这个设计很巧妙。 3.3 震荡期自动切换:市场的"红绿灯" 策略有一套完整的"红绿灯"机制来判断当前是正常期还是震荡期: 进入震荡期(亮红灯)——满足任一条件: 沪深300的乖离率(BIAS)> 8%(涨太多了,有回调风险) RSI从70以上回落到65以下(超买后开始回落) 当天触发了止损(市场可能在变差) 退出震荡期(亮绿灯)——满足任一条件: 从近20日低点反弹超过4% 回撤收窄 + 多个复苏信号连续出现 震荡期持续超过20个交易日(强制退出,不能永远观望) 还有一个冷却期设计:每次红绿灯切换后,3个交易日内不允许再次切换,防止频繁反复。 3.4 多层过滤漏斗 从作战池到最终买入,要过七道关: 100+只ETF → 动量得分过滤(0 ≤ 得分 ≤ 5) → R²过滤(> 0.4,趋势不稳的排除) → 成交量过滤(量比 <1.8,异常放量的排除) → 短期风控(近3天没有单日跌 > 3%) → 溢价率过滤(可选,防止QDII高溢价陷阱) → 动态滤波过滤(正常期/震荡期分别用不同滤波器) → 最终只选1只! 没错,最终只持有1只ETF。这是一个非常激进但也非常纯粹的设计——全仓轮动,不分散。因为分散在ETF轮动里反而是稀释收益,不如集中火力追最强的那个。 3.5 分钟级止损:最后的保险丝 ETF策略还有一个分钟级的止损机制(every_bar 频率运行): 固定止损:当前价格跌破成本价的95%时,立刻卖出 日内跌幅止损(可选):如果当天相对昨收跌超过5%,也立刻卖出 触发止损后会标记 stop_loss_triggered_today,在午后13:10的检查中自动触发进入震荡期——止损不仅是保护本金,还会触发策略整体进入防守姿态。 四、双核协同的几个关键细节 4.1 资金分配 当前是简单的50:50平分。但我在想,未来可以根据市场状态动态调整——比如A股弹性好的时候多给小市值,ETF板块轮动强的时候多给ETF。这是一个可以继续优化的方向。 4.2 独立收益记录 策略每日收盘后会分别记录两个子策略的累计收益率,方便做归因分析。用 record() 函数输出到回测图表上,可以直观看到两条收益曲线。 def record_daily_performance(context): for i, strategy_key in enumerate(['strategy1', 'strategy2']): sub_portfolio = context.subportfolios[i] cumulative_return = (sub_portfolio.total_value / initial_cash - 1) * 100 # 记录到图表 record(小市值=小市值收益率, 五福ETF=ETF收益率) 4.3 滑点和佣金的差异化设置 很多人忽略的一个细节——股票和ETF的交易成本是不一样的: set_slippage(FixedSlippage(0.002), type="stock") # 股票:固定滑点 set_slippage(PriceRelatedSlippage(0.0001), type="fund") # ETF:比例滑点 # 股票佣金:万0.85,卖出还有千分之0.5的印花税 # ETF佣金:万0.5,无印花税 ETF的交易成本天然比股票低很多,这也是ETF轮动策略能频繁调仓的基础。 五、一个小白的学习感悟 不要只盯一个赛道。小市值再好,碰到风格切换也会歇菜。加一个ETF轮动引擎,相当于给自己多开了一个全球化的战场。 站在巨人肩膀上学得更快。ETF轮动这一整套逻辑,如果让我从零开始写,可能半年都写不出来。但社区里有那么多大佬无私分享代码和思路,我做的只是把不同的模块学懂、拼到一起。聚宽社区的开源氛围真的很好,感谢每一位分享策略的前辈。 数学滤波器很有意思。拉普拉斯、高斯这些信号处理领域的工具,用到金融数据上效果很好。作为小白第一次接触这些概念,说实话还没有完全吃透,后面还要继续啃论文和代码。 震荡期切换是ETF轮动的灵魂。没有这个机制,ETF轮动在震荡行情里会被反复打脸。有了红绿灯+冷却期,策略才能在"追趋势"和"认怂"之间优雅切换。 子账户隔离是个好设计。让两个策略各管各的,不争抢资金,不相互干扰。简单粗暴但有效。 最后还是那句话:风控是一切的基础。不管是小市值的五道防线,还是ETF的分钟级止损,核心都是同一个信仰——先活着,再赚钱。 六、实战检验 说得再好不如跑起来看。我已经把这套「小市值+ETF轮动_双龙出海」策略上传到了 9db量化竞技场,用真实模拟盘每天跑。 欢迎围观、拍砖。在9db上可以看到每天的交易记录、持仓变化、收益曲线。比回测更真实,因为是每天实时跑的——好不好,跑几周就知道了。 也欢迎大家去看看其他大佬的策略表现,和自己的策略做个对比。量化这条路,闭门造车不如多看多学。 作为一个刚入门的量化小白,文中很多理解可能不够深入甚至有偏差,欢迎各位大佬在评论区指正。也特别感谢社区里那些无私分享策略和思路的前辈们,没有你们的开源精神,就没有这篇学习笔记。 免责声明:以上内容仅为个人学习记录,不构成任何投资建议。股市有风险,投资需谨慎。
浏览566
评论1
收藏2
用户头像sh_***3272xs
2026-07-20 发布
图表最右边那根 K 线,刚才还是阳线,过一分钟再看,实体变了,最低价往下挪了,成交量也增加了。 此刻最重要的问题,不是它究竟算阳线还是阴线,而是:这根 K 线结束了吗? 如果周期还没结束,你看到的只是当前进度。它可以用来观察市场正在发生什么,却还不能承担“最终形态”“固定指标输入”或“历史记录”的职责。 这篇文章只解决一个判断: 眼前这根最后 K 线,现在只能用于观察,还是已经有资格进入形态判断、指标计算、回测和历史记录? TickDB 用两个入口处理这两种状态:/v1/market/kline/latest 返回当前周期正在形成的 K 线,/v1/market/kline 返回已结束周期的历史 K 线。但在记住接口之前,先要明白为什么这条分界线会影响你的判断和研究。 先判断这根 K 线有没有“使用资格” 一根 K 线并不是从出现的那一刻起就固定不动。 以 1 分钟 K 线为例。在这一分钟结束前,新的成交仍会进入当前时间桶。只要后续成交改写了这一分钟截至当时的聚合结果,最高价、最低价、收盘位置或成交量就可能继续变化。 所以,形成中与已结束不是两个相近的技术名词,而是两种不同的数据资格: K 线状态 它能回答什么 更适合的任务 形成中 当前周期进行到哪里 图表末根、实时观察、当前监控 已结束 这个周期最后是什么结果 指标计算、回测、固定存储、归档 对投资者来说,这意味着未收盘 K 线的实体、影线和成交量都还可能变化,不能提前把它当成已经确认的形态。 对研究者来说,问题更隐蔽:一段程序可以正常运行,指标也能算出来,但如果输入包含形成中的最后一根 K 线,同一段计算在不同时间运行,输入可能已经不同。 真正的风险不在于 K 线会变,而在于你把它“变到一半”的样子存了下来,又当成最终结果拿去算。 同一个 time,为什么仍然可以变化? 很多误解来自时间标签。 两次返回的 time 相同,读者很容易认为它们是同一条固定记录。其实,time 首先说明数据属于哪个时间桶,并不自动说明这个时间桶已经结束。 11:50:14 查询一根 1 分钟 K 线,看到的是这一分钟进行到 14 秒时的状态;11:50:29 再查,仍然属于同一个时间桶,但中间可能已经有新的成交进入。 因此,两次结果可以拥有相同的 symbol、interval 和 time,同时又在 low、close 或 volume 上出现变化。 这个机制说得通还不够。接下来用同一个真实时间桶,把形成中的两次快照和周期结束后的历史结果放在一起核对。 实时 K 线 API 实测:15 秒内,同一根 K 线变了什么? 本次公开样本固定为:BTCUSDT / 1m / time=1784519400000。 获取当前形成中 K 线的真实核心调用如下。API Key 通过环境变量传入,代码和公开材料中不包含密钥值。 curl --location --silent --show-error --max-time 20 \ --get 'https://api.tickdb.ai/v1/market/kline/latest' \ --header "X-API-Key: $TICKDB_API_KEY" \ --data-urlencode 'symbols=BTCUSDT' \ --data-urlencode 'interval=1m' 2026 年 7 月 20 日 11:50:14 与 11:50:29(Asia/Shanghai),两次调用均返回 HTTP 200。两份响应中的 symbol、interval、time 和 open 一致,可以确认比较的是同一标的、同一周期、同一个时间桶。 15 秒内,返回值出现了这些变化: 字段 11:50:14 11:50:29 结果 open 64880.00000000 64880.00000000 未变 high 64880.01000000 64880.01000000 未变 low 64879.14000000 64879.13000000 更新 close 64879.14000000 64879.13000000 更新 volume 2.48089000 2.56712000 增加 quote_volume 160960.14274530 166554.67016060 增加 这组数据先说明了一件事:形成中的同一根 K 线,确实可以在同一时间桶内继续更新。 但它也提醒我们不要走向另一个极端。high 两次都是 64880.01000000,说明“形成中”不等于每个字段每次都会变化。新的成交是否改写某个字段,要看它是否改变了对应的聚合结果。 判断两份返回是不是同一根 K 线,顺序也不能反:先确认 symbol、interval、time 一致,再比较 OHLCV。 到这里,我们只能证明它仍在形成,还不知道这一分钟最终收在哪里。要回答“什么时候固定”,证据链还差最后一步。 历史 K 线 API:周期结束后,同一时间桶变成什么? 11:51:21,再通过历史 K 线入口查询同一个时间桶: curl --location --silent --show-error --max-time 20 \ --get 'https://api.tickdb.ai/v1/market/kline' \ --header "X-API-Key: $TICKDB_API_KEY" \ --data-urlencode 'symbol=BTCUSDT' \ --data-urlencode 'interval=1m' \ --data-urlencode 'start_time=1784519400000' \ --data-urlencode 'end_time=1784519459999' \ --data-urlencode 'limit=5' 上图是本次历史查询的真实返回页面,采集时间为 2026 年 7 月 20 日 11:51:21(Asia/Shanghai)。页面数值与保存的原始响应一致;图片未添加标注、边框或说明层。 核对项 周期结束后的历史返回 symbol BTCUSDT interval 1m time 1784519400000 open 64880.00000000 high 64894.00000000 low 64879.13000000 close 64887.57000000 volume 3.86571000 quote_volume 250812.37828770 三次返回的 symbol、interval 和 time 一致。前两份记录的是同一时间桶在形成过程中的状态,第三份记录的是周期结束后的历史结果。 至此,“未收盘 K 线什么时候固定”有了可复核的答案:等对应周期结束,再从历史 K 线中取得该时间桶的固定结果。 这里的“结束”指这根 K 线所属的周期结束,不一定是整个交易日收市。1 分钟 K 线等这一分钟结束,1 小时 K 线则要等对应小时周期结束。 证据闭合以后,才轮到任务选择 看到这里,两个接口的名字已经不是重点。真正需要记住的是:不同任务,对数据资格的要求不同。 投资信息理解:别把过程提前当成形态结论 最后一根未收盘 K 线当前是阳线还是阴线、影线有多长、成交量有多大,都可能在周期结束前继续变化。 这不等于形成中的 K 线没有价值。它适合观察市场当前进行到哪里,只是不应该提前承担“这个形态已经确认”的含义。 研究判断:固定计算要使用固定输入 指标统计、回测和归档需要能够复查的输入。如果最后一根数据仍在变化,同一段研究在不同时间运行,结果可能因为输入变化而不同。 因此,实时 K 线用于观察当前进度;需要固定计算时,使用已结束周期的历史 K 线。 产品与开发:图表末根和历史序列不要混成一种状态 行情产品通常同时需要“现在”和“过去”。图表最右侧可以展示形成中的当前 K 线,前面的历史序列则应使用已结束数据。 应用侧还应保存请求条件、原始响应和查询时间。以后出现“昨天看到的最后一根为什么和今天不一样”,才能回到当时的记录核对,而不是凭截图或记忆争论。 你的任务 需要的数据状态 TickDB 入口 展示图表最右侧的当前 K 线 形成中 /v1/market/kline/latest 观察当前周期变化、做实时监控 形成中 /v1/market/kline/latest 运行回测或统计固定指标 已结束 /v1/market/kline 保存以后可以复查的数据 已结束 /v1/market/kline 下一次看到最后一根变化,先问四件事 我看到的是当前 K 线,还是历史 K 线? 这根 K 线所属的周期结束了吗? 我现在要观察过程,还是做固定计算? 我有没有保存原始响应和查询时间? 这四个问题把注意力从“数字怎么又变了”转向真正需要完成的判断:它现在处于什么状态,够不够资格进入下一项任务。 怎样自己复核一次? 不需要先搭一整套行情系统。选一个标的和周期,做一次最小验证: 在同一个时间桶内调用两次实时 K 线入口; 保存两次原始响应与查询时间; 核对 symbol、interval 和 time 是否一致; 周期结束后,查询历史 K 线中的相同 time; 把三份数据并排比较,区分形成中快照与结束后结果。 完成这一步,你得到的不只是一个接口测试结果,而是一条以后可以反复使用的数据判断方法。 FAQ 最后一根 K 线变化,就一定不是数据问题吗? 不能这样反推。当前周期仍在形成,是变化的常见原因;但仍要核对标的、周期、时间桶和原始响应。只有先确认比较对象一致,才能判断变化是否符合预期。 未收盘 K 线什么时候才固定? 等这根 K 线对应的周期结束。例如 1 分钟 K 线要等这一分钟结束。这里说的是 K 线周期结束,不一定是交易日收市。 实时 K 线能不能直接用于回测或固定指标? 不应把形成中的当前 K 线直接当成固定历史输入。当前周期继续接收成交时,最后一根仍可能变化。回测、固定指标统计和归档应使用已结束的历史 K 线。 换成 A 股、美股、外汇或其他市场,这套判断还适用吗? 先区分“形成中”和“已结束”,再决定数据用于观察还是固定计算,这个判断方法仍然有价值;但不同市场、标的和接口仍应按对应文档与真实返回单独核对。 TickDB 是面向开发者的统一实时行情数据 API。根据官方资料,一套 API 可以接入外汇、贵金属、指数、美股、港股、A 股和加密货币等市场的实时与历史行情,并通过 REST 或 WebSocket 使用。本文只实测了 BTCUSDT 的一根 1 分钟 K 线,没有把单一样本外推到其他市场。 最后 最后一根 K 线变了,先别急着问“哪个数字才是真的”。 在查询发生的那个时刻,形成中的快照记录了当时的进度;周期结束后的历史 K 线记录了最终结果。两者服务不同任务,不能混为一谈。 所以,实时 K 线和历史 K 线的区别,最终不是接口名称的区别,而是过程和结果、观察和计算之间的区别。 本文公开实测只覆盖 BTCUSDT、1m、time=1784519400000 这一个样本,用于说明该时间桶从形成中到已结束的状态差异,不用于外推延迟、SLA、全市场一致性、策略有效性或收益。 参考资料: TickDB 实时 K 线接口文档 TickDB 历史 K 线接口文档 TickDB 官方 GitHub 本文只讨论实时 K 线与已结束历史 K 线的状态差异和使用选择,不构成投资建议。
浏览13
评论0
收藏0
用户头像mx_****zqklr
2026-07-20 发布
导言 / TL;DR “Garbage in, garbage out” 是量化研究永恒的铁律。在构建因子模型、多因子选股或输入机器学习模型前,如果直接使用未经清洗的原始财务或行情指标,极易受到极值(异常值)的干扰,导致回测结论失真。本文将演示如何利用 Python 配合 QuantDash 干净的数据流,采用绝对中位数偏差法(MAD)对因子数据进行“去极值”并配合 Z-Score 进行“无量纲标准化”处理。 技术痛点拆解 量化分析师在做多因子研究时,经常遭遇以下数据预处理陷阱: 极端行情扭曲统计特征:当个别小盘股因复牌、重组出现暴涨,或者财报数据中存在偶发性的非经常性损益时,该因子的数值可能会比均值大几十倍。如果直接套用标准差计算,会导致整个因子的均值被严重拉高,淹没其他正常标的的信号。 量纲单位不一致无法融合:市盈率(PE)因子的数值通常在几十,而流通市值(MV)因子则在百亿量级。如果不经过标准化,这两个因子根本无法在多因子模型中融合成一个综合得分。 极简解决方案(基于 QuantDash SDK 与 Pandas/Scipy) 我们通过 Pandas 处理从 QuantDash 获取的多只股票的因子指标(这里以最基础的日收益率因子为例),并进行稳健的 MAD(Median Absolute Deviation)去极值以及 Z-Score 标准化。 pip install quantdash pandas scipy import numpy as np import pandas as pd from quantdash import QuantDash # 1. 初始化 QuantDash qd = QuantDash(api_key="sk_xxxxx") def handle_factor_preprocessing(df_factor: pd.DataFrame, factor_name: str) -> pd.DataFrame: """ 对因子的指定列进行 MAD 去极值与 Z-Score 标准化 """ df = df_factor.copy() # --- 步骤 1: MAD 去极值 (Median Absolute Deviation) --- # 相比标准差法,MAD 法更不易受极端大值的偏离影响,是量化界标准的稳健去极值方法 median = df[factor_name].median() mad = (df[factor_name] - median).abs().median() # 设定边界阈值(通常设定为 3 倍 MAD 或 5 倍 MAD) # 1.4826 是一个比例常数,使 MAD 的标度与标准差大致相当 mad_limit = 3 * 1.4826 * mad lower_bound = median - mad_limit upper_bound = median + mad_limit # 进行边界截断(Clip) df[f"{factor_name}_clean"] = df[factor_name].clip(lower=lower_bound, upper=upper_bound) # --- 步骤 2: Z-Score 标准化 --- # 将因子的均值调整为 0,标准差调整为 1,消除量纲影响 mean = df[f"{factor_name}_clean"].mean() std = df[f"{factor_name}_clean"].std() df[f"{factor_name}_zscore"] = (df[f"{factor_name}_clean"] - mean) / std return df if __name__ == "__main__": # 获取某一日全市场多个标的的日K线计算收益率因子 # 模拟获取 A 股部分股票的收益率表现 symbols = ["600519.SH", "000001.SZ", "000858.SZ", "300750.SZ", "601318.SH"] print("[*] 正在获取行情并计算原始因子数据...") raw_data = [] for s in symbols: df = qd.klines.get(symbol=s, period="1d", limit=2, to_dataframe=True) if df is not None and len(df) >= 2: # 简单计算前一日到今日的收益率,作为我们的“日收益率因子” ret = (float(df.iloc[-1]["close"]) - float(df.iloc[0]["close"])) / float(df.iloc[0]["close"]) raw_data.append({"symbol": s, "return_factor": ret}) df_factor = pd.DataFrame(raw_data) # 假设为了测试,手动加入一极端的异常大值(模拟财报发布后极端暴涨) df_factor.loc[len(df_factor)] = {"symbol": "ERROR_STOCK", "return_factor": 12.50} # 1250% 的极端收益率 print("\n[+] 原始因子数据(包含异常大值):") print(df_factor) # 运行清洗与标准化 df_processed = handle_factor_preprocessing(df_factor, "return_factor") print("\n[+] 清洗及标准化处理后的因子数据:") print(df_processed[["symbol", "return_factor", "return_factor_clean", "return_factor_zscore"]]) 数据输出样例 经过 MAD 去极值和 Z-Score 转换后,极端的 ERROR_STOCK 的值被截断并平滑,其余股票的因子大小重新归一化至同一数量级: [+] 原始因子数据(包含异常大值): symbol return_factor 0 600519.SH 0.015200 1 000001.SZ -0.005100 2 000858.SZ 0.021000 3 300750.SZ 0.048200 4 601318.SH 0.002300 5 ERROR_STOCK 12.500000 [+] 清洗及标准化处理后的因子数据: symbol return_factor return_factor_clean return_factor_zscore 0 600519.SH 0.015200 0.015200 -0.068201 1 000001.SZ -0.005100 -0.005100 -0.915201 2 000858.SZ 0.021000 0.021000 0.173792 3 300750.SZ 0.048200 0.048200 1.308695 4 601318.SH 0.002300 0.002300 -0.606341 5 ERROR_STOCK 12.500000 0.048200 1.308695 AI 编程助手专属提示词 如果您正在 Cursor 中构建完整的因子看板,可直接复用以下 Prompt 扩展: 我目前使用 pandas 为 quantdash 因子数据做标准化处理。 请帮我把上面的 MAD 替换为行业(Industry)中性化的预处理。 要求: 1. 传入一个包含行业分类(industry)字段的 DataFrame。 2. 在每个行业板块内部,分别独立进行因子去极值与 Z-Score 转换,避免不同行业的基准偏差(例如科技股与银行股本身的估值中枢差异)。 总结与三步走指引 第一步:获取完整源码。访问官方开源托管仓库获取本文 Demo:https://github.com/quantdash-net/QuantDash。 第二步:申请专属密钥。注册获取您的个人免费 API Key:https://quantdash.net/。 第三步:查阅开发细节。更多高频行情、多市场 Tick 接口参数:https://docs.quantdash.net/。
浏览12
评论0
收藏0
用户头像mx_****zqklr
2026-07-20 发布
导言 / TL;DR 跳空高开通常意味着强烈的资金共识与基本面突变,是日内动量突破策略的黄金切入点。然而,在 9:30 开盘瞬间对全市场成百上千只股票进行高速扫描,传统爬虫数据源不仅速度跟不上,还容易因并发过大被封。本文教你如何用 Python 配合 QuantDash 毫秒级多股票快照接口,在开盘 1 分钟内迅速筛选出跳空缺口大于 2% 且成交量显著放大的强势股。 技术痛点拆解 开发日内跳空选股器时,核心难点在于**“开盘1分钟的时效性”**: 单点请求延迟高:如果对 100 只自选股逐一用 HTTP 请求获取开盘价和昨日收盘价,循环请求需要耗时数十秒,早已错过了最佳建仓时机。 数据源缺失历史对比:计算跳空不仅需要今天的开盘价(Open),还需要昨天的收盘价(Close)。很多实时行情 API 不提供昨日收盘价字段,逼得开发者必须额外查询一次历史K线,多耗费一倍时间。 极简解决方案(基于 QuantDash SDK) QuantDash 的实时快照接口 qd.quotes.get 在单次响应中同时集成了“最新价、开盘价、昨日收盘价、成交量”等完整字段,一行代码即可完成多标的并行对比。 pip install quantdash pandas 以下为高并发多市场跳空缺口扫描脚本: import pandas as pd from quantdash import QuantDash # 1. 初始化 QuantDash qd = QuantDash(api_key="sk_xxxxx") # 监控的目标股票池(涵盖A股、港股、美股) TICKER_POOL = ["600519.SH", "300750.SZ", "00700.HK", "01211.HK", "TSLA.US", "NVDA.US"] def scan_gap_openings(symbols, min_gap_pct=2.0): """ 扫描开盘跳空个股 """ print(f"[*] 正在拉取 {len(symbols)} 只标的的实时市场快照...") # 一键拉取批量快照 df_quotes = qd.quotes.get(symbols=symbols, to_dataframe=True) if df_quotes is None or df_quotes.empty: print("[-] 未获取到有效的实时行情") return pd.DataFrame() # 计算跳空幅度 (%): (今日开盘价 - 昨日收盘价) / 昨日收盘价 * 100 # 注:QuantDash 快照数据中,open_price 为今日开盘价,prev_close_price 为昨日收盘价 df_quotes["open_price"] = df_quotes["open_price"].astype(float) df_quotes["prev_close_price"] = df_quotes["prev_close_price"].astype(float) df_quotes["gap_pct"] = ( (df_quotes["open_price"] - df_quotes["prev_close_price"]) / df_quotes["prev_close_price"] * 100 ) # 筛选向上跳空大于指定阈值的个股 df_gaps = df_quotes[df_quotes["gap_pct"] >= min_gap_pct].copy() # 按照跳空幅度降序排列 df_gaps.sort_values(by="gap_pct", ascending=False, inplace=True) return df_gaps[["symbol", "open_price", "prev_close_price", "gap_pct", "volume"]] if __name__ == "__main__": try: # 扫描跳空高开幅度 >= 1.5% 的强势股票 df_result = scan_gap_openings(TICKER_POOL, min_gap_pct=1.5) print(f"\n[+] 扫描完成。符合跳空高开条件的股票池:") print(df_result) except Exception as e: print(f"[-] 运行失败: {str(e)}") 数据输出样例 开盘 9:30 执行脚本后,输出的排好序的跳空股票池 DataFrame 结构如下: [+] 扫描完成。符合跳空高开条件的股票池: symbol open_price prev_close_price gap_pct volume 2 TSLA.US 245.80 238.10 3.23 15240000 5 NVDA.US 128.50 125.00 2.80 24800000 1 300750.SZ 252.10 248.00 1.65 891200 AI 编程助手专属提示词 您可在 Cursor/Claude 中输入以下 Prompt,为该选股器追加成交量过滤器: 我目前使用 quantdash 实时行情进行跳空缺口选股。 请帮我升级这段代码:增加一个成交量倍数过滤器(Volume Ratio)。 要求当前的累计成交量(volume)必须大于过去 5 日平均成交量的 20% 以上,才算做“放量跳空”,以此过滤无资金关注的假突破。 总结与三步走指引 第一步:获取完整源码。访问官方开源托管仓库获取本文 Demo:https://github.com/quantdash-net/QuantDash。 第二步:申请专属密钥。注册获取您的个人免费 API Key:https://quantdash.net/。 第三步:查阅开发细节。更多高频行情、多市场 Tick 接口参数:https://docs.quantdash.net/。
浏览11
评论0
收藏0
用户头像mx_****zqklr
2026-07-20 发布
导言 / TL;DR 无论是多因子选股还是跨市场ETF轮动,策略最终都要落地到“仓位权重分配”上。盲目等权重配置往往无法最大化风险收益比。本文将展示如何通过 QuantDash 提取 A 股和美股多资产历史 K 线,并结合知名的开源组合优化库 PyPortfolioOpt,利用马科维茨均值-方差模型(MVO)计算出最大夏普比率(Max Sharpe)的黄金仓位。 技术痛点拆解 在进行多资产投资组合优化时,量化开发者经常面临两个工程阻碍: 多市场时序不齐对齐难:当组合中同时包含中美资产时,由于时差和休市日历不同,计算资产协方差矩阵(Covariance Matrix)前必须进行严格的缺失值填充与时间对齐,否则会导致矩阵非正定,算法无法收敛。 计算过程繁琐:手写二次规划(Quadratic Programming)求解有效前沿不仅代码量大,且容易在约束条件(如禁止做空、单资产比例上限)上出错。 极简解决方案(基于 QuantDash SDK 与 PyPortfolioOpt) 首先,安装所需依赖: pip install quantdash pandas pyportfolioopt 以下为获取历史收盘价并求解最优资产配置比例的完整代码: import pandas as pd from pypfopt import EfficientFrontier, risk_models, expected_returns from quantdash import QuantDash # 1. 初始化 QuantDash 客户端 qd = QuantDash(api_key="sk_xxxxx") # 官方文档详见 docs.quantdash.net # 定义资产组合:包含A股和美股核心标的 assets = ["600519.SH", "00700.HK", "AAPL.US", "MSFT.US"] def get_portfolio_data(symbols, start_date="2025-01-01", end_date="2025-12-31"): price_dict = {} for sym in symbols: # 获取标准日K线 df = qd.klines.get(symbol=sym, period="1d", start=start_date, end=end_date, to_dataframe=True) if df is not None and not df.empty: df["trade_date"] = pd.to_datetime(df["trade_date"]) df.set_index("trade_date", inplace=True) price_dict[sym] = df["close"] # 合并为价格矩阵 df_prices = pd.DataFrame(price_dict) # 前向填充跨市场休市造成的缺失值,随后删除多余空值 df_prices = df_prices.ffill().dropna() return df_prices if __name__ == "__main__": # 获取历史收盘价数据 prices = get_portfolio_data(assets) # 2. 计算期望年化收益率与样本协方差矩阵 mu = expected_returns.mean_historical_return(prices) S = risk_models.sample_cov(prices) # 3. 求解最大夏普比率组合 (限制单标的仓位最大为 40%) ef = EfficientFrontier(mu, S) ef.add_constraint(lambda w: w <= 0.40) # 约束单标的权重上限 weights = ef.max_sharpe() cleaned_weights = ef.clean_weights() # 输出优化结果 print("\n[+] 优化后的多资产组合权重:") for asset, weight in cleaned_weights.items(): print(f" - {asset}: {weight * 100:.2f}%") performance = ef.portfolio_performance(verbose=True) 数据输出样例 经过对齐与二次规划求解,控制台输出的最优配置权重及组合表现如下: [+] 优化后的多资产组合权重: - 600519.SH: 15.30% - 00700.HK: 24.70% - AAPL.US: 40.00% - MSFT.US: 20.00% Expected annual return: 18.5% Annual volatility: 14.2% Sharpe Ratio: 1.16 AI 编程助手专属提示词 如果您正在 Cursor 或 Copilot 中优化此组合模型,可以直接复制以下 Prompt: 我正在使用 PyPortfolioOpt 和 quantdash 的历史价格进行资产组合分配。 请帮我修改上面的优化代码: 1. 将目标函数改为“最小波动率组合(Minimum Variance)”。 2. 增加行业/板块限制,使得所有美股标的(AAPL.US, MSFT.US)的合计权重不能超过 50%。 总结与三步走指引 第一步:获取完整源码。访问官方开源托管仓库获取本文 Demo:https://github.com/quantdash-net/QuantDash。 第二步:申请专属密钥。注册获取您的个人免费 API Key:https://quantdash.net/。 第三步:查阅开发细节。更多高频行情、多市场 Tick 接口参数:https://docs.quantdash.net/。
浏览11
评论0
收藏0
用户头像sh_***174w0d
2026-07-20 发布
引言:为什么你总是一卖就涨,一买就跌? 别再抱怨主力在“监控”你的账户了,他们没那么闲。 很多散户之所以陷入“一卖就涨、一买就跌”的死循环,根本不是运气差,而是因为你的交易逻辑里完全没有应对体系。面对开盘跳空的绿盘,绝大多数人只会手忙脚乱地交出筹码,或者盲目死扛。 真正的职业选手,从不预测市场,只针对走势做“选择题”。低开不代表崩盘,往往是主力调转船头的虚晃一枪。今天我把这5套应对低开的实战体系拆解给你,建议收藏,这不仅是技术,更是你翻身的“军令状”。 策略一:低开后的“翻红奇迹”——耐心是金 [核心信号]:股价低开3-5个点,随后开始震荡上行,并在上午10:30前成功翻红。 ●**行情研判: 10:30是早盘多空博弈后的首个关键确认点。能在半小时内收复失地并转红,说明下方承接力**极强。 ●[操作指令]: 不要急于卖出!这种情况次日通常仍有溢价空间。 ●后续跟进:继续持有,卖点选在股价再次翻绿(由红转绿)的那一刻。 “你可以继续持有,等待之后再次出现绿盘时再考虑卖出。” 策略二:迅猛拉升——抓住难得的加仓良机 【核心信号】: 股价低开后没有任何犹豫,直接直线拉红。 **●**行情研判: 这种走势反映出主力急于抢筹,甚至不惜成本进行反包,是极度强势的信号。 ●[操作指令]: 1.[加仓时机]: 发现直线拉红,立即跟随加仓。 2.[持股逻辑]: 若底仓最终冲至涨停,坚决持有,次日大概率还有冲高机会。 3.[止盈信号]*: 若未能封板,则在股价冲高乏力、出现见顶信号时,将加仓部分及底仓择机获利了结。 策略三:无量拉升的陷阱——主力撤退的假动作 [核心信号]: 低开3-4个点后出现无量反弹**,始终未能翻红,且随后快速跌破开盘价。 **●**行情研判: 缩量意味着没有真金白银进场支撑,无法翻红说明多头抵抗极度虚弱。这通常是主力为了吸引散户接盘而刻意制造的“虚假繁荣”。 ●[操作指令]: 一旦回补缺口,必须果断离场。 **●**深度警示: 记住,在缩量背景下,股价去碰触前一日收盘价(补缺)往往就是反弹的极限。不要幻想反包,这是最后撤退的机会,一旦跌破开盘价,下方就是深渊。 策略四:跌停板的“反复诱惑”——最后的离场警报 [核心信号]: 早盘直接低开至跌停,随后跌停板反复被打开,但始终没有出现有效的拉升信号*。 **●**行情研判: 跌停板的反复开合极具迷惑性,看起来像是有大资金“翘板”救场,实际上是主力利用零散的买盘在进行最后的诱多出货。 ●[操作指令]: 赶紧跑,不要有任何犹豫! **●**逻辑拆解: 真正的强势反转必须配合大单直线拉升,这种在跌停价附近的“反复诱惑”是典型的出货迹象。 “这也是主力在出货的迹象,看到这种情况就赶紧跑,不要犹豫。”6. 策略五:低位震荡的温水煮青蛙——警惕尾盘跳水 [核心信号] 股价低开后全天在低位横盘震荡,尾盘突然出现再次下探的动作。 **●**行情研判: 全天横盘说明市场极度观望,完全没有主流资金愿意承接。这种“温水煮青蛙”的走势,预示着多头已经彻底放弃抵抗。 ●[操作指令]: 及时离场,保住本金。 **●**后市预判: 尾盘下探是趋势确认的信号,次日大概率会继续下探寻找支撑。 7. 结语:财富不在于预测,而在于应对 股市里的财富,从来不属于那些试图预测未来的预言家,而属于执行纪律的聪明人。 请记住,当你把这五套策略烂熟于心并付诸实践时,你就已经给自己立下了一份“军令状”:符合条件就动,不符合就等。 这不只是策略,这是职业交易者的准则。克制住你的冲动,戒掉你的贪婪与恐惧。平时复盘梳理走势、整理交易记录,可借助9db交割单 平台辅助归纳行情规律。当你能冷静面对跳空的绿盘,并迅速匹配对应的操作指令时,你就已经识破了主力的虚晃一枪。
浏览33
评论0
收藏0