全部
文章&策略
学习干货
问答
官方
用户头像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 断线容错方面遇到过哪些问题?在回测数据集清洗方面有哪些实践思路,欢迎在评论区分享工程经验与调优方案。
浏览10
评论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 深度行情,将更多精力投入策略模型与回测分析工作。
浏览12
评论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
浏览12
评论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 线的量化策略,缓存不是可选项,而是基础组件。提前设计好缓存逻辑,后续增加品种和数据量时,系统会更稳定、更容易扩展。
浏览11
评论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/
浏览22
评论0
收藏0
用户头像upsets
2026-08-18 发布
-- coding: utf-8 -- """ A股价值因子选股策略回测系统 策略逻辑: 全A股股票池,按市盈率(PE)由低到高取前40% 按市净率(PB)由低到高取前40% 按股息率由高到低取前40% 最终持仓不超过30只,等权分配 止损条件: 个股较买入成本跌幅超15% → 清空该股票,等待下次调仓 交易规则: T+1限制、100股整手、佣金万3(最低5元)、印花税千1(卖出单边)
浏览47
评论1
收藏0

实盘交易个人不能使用吗?

用户头像火花要掉了
2026-08-18 发布
麻烦问问官方大大,个人不能使用量化智能交易嘛?还是就只能利用企微、飞书、钉钉等软件通知手动执行啊?不能自动吗,或者自动的条件是什么,我申请了2回,也没见给我回个电话啊。。。。。。好无奈,给不给用,回个电话呢呗。。
浏览37
评论1
收藏0
用户头像sh_***174w0d
2026-08-18 发布
引言:寻找混乱市场中的节奏感 对于多数投资者而言,盘中分时图的波动宛如随机漫步的电波,充满了无序的噪音与致命的诱惑。新手往往在急拉时盲目跟进,又在跳水时因恐惧割肉,这种被情绪支配的“本能反应”正是亏损的根源。 然而,在职业交易员眼中,分时走势并非杂乱无章,而是存在一套关于“时间”的底层律动。成功交易的关键,在于识别并执行一套被市场反复验证的操作密码。本文将为你深度拆解一套流传于资深圈内的分时操作秘籍,带你从混乱的波动中洞察职业资金的真实意图。平时盯盘我也习惯搭配一些专业的金融数据平台做辅助参考,像 9db交割单 平台的分时行情和资讯更新得比较及时,对把握盘中节奏有点帮助,感兴趣的可以自己去看看。 核心秘籍一:早盘定胜负——大跌是机遇,大涨是诱饵 早盘阶段(9:30-10:30)是市场情绪最激烈的碰撞期,也是机构博弈、散户踩踏的高发时段。 早上大跌可加仓,上午大跌不卖票。 早上大涨要减仓,逢低加仓加零。 深度解析: **●**早盘急跌: 通常是受到隔夜负面情绪或主力“诱空”洗盘的影响。此时的放量下跌往往会导致卖压提前释放,出现流动性枯竭后的技术性修复。对于持仓者而言,上午的阴跌绝非割肉良机,反而是通过“加零”(指在底仓基础上进行日内T+0补仓)摊薄成本的机会。 **●**早盘急涨: 往往伴随着散户的追涨情绪,主力常借此高点进行筹码换手或减压。资深分析师会建议此时“先出后进”,利用早盘的高点降低整体风险敞口。 核心秘籍二:午后冲高的冷静期——只减不加 午后盘面(1:00-3:00)进入博弈的中后期,此时的走势往往带有极强的迷惑性。 下午冲高不追涨,午后大涨只减仓。 逢高减仓加一。 职业策略: **●**坚决不追涨: 午后市场的拉升往往缺乏持续性的成交量支撑,更多是短线获利盘试探性的抛压释放。 **●**减仓逻辑: “逢高减仓加一”是指在午后脉冲式上涨时,应当果断实施“T+0”减仓操作,将早盘补进的份额或多余的持仓单位(“加一”)获利了结。午后的强势往往难以转化成次日的溢价,此时锁定既有利润是维持账户主动权的艺术。 核心秘籍三:关键节点的时间法则——10点与2点 在交易时间轴上,10:00 AM 和 2:00 PM 是两个决定性的“真相节点”。它们是判断个股强弱的分水岭。 上午10:00(强度生死线): **●**股若强势十点封: 真正具备顶级强度的个股,其主力意图在开盘半小时内便已清晰。如果一只票具备冲击涨停的基因,通常会在10点前通过高强度的换手直接“点封”(封死涨停)。若10点后仍无法封板,其全天的强度将大打折扣。 下午2:00(动能试金石): **●**股若不强两点冲: 对于那些上午表现平淡、缺乏主动攻击性的个股,2点钟是最后的补涨机会。此时的拉伸往往是主力为了修正收盘价、维持K线图形或吸引跟风盘,其持续性通常存疑,不建议作为买入参考。 核心秘籍四:逆向思维——午后大跌的次日预判 这或许是整套逻辑中最具“逆直觉”的一条法则,它揭示了筹码博弈的极致状态。 午后大跌次日强。 深度分析: 从心理博弈角度看,午后至尾盘的剧烈跳水,能最大程度地引发场内恐慌盘的踩踏式抛售。当恐慌在收盘前达到顶峰,意味着潜在的卖压已在日内彻底出尽。这种“暴力洗盘”清除了浮筹,降低了次日的抛压阻力,往往会引发次日的低开高走、甚至大幅反包。一个资深的分析师会从中看到“洗盘”而非“崩盘”,这种利用时间差进行的筹码收割,是主力在为次日的反攻预留空间。 结语:从“看天吃饭”到“对表操盘” 股市交易从来不是关于精准预测,而是关于在特定的时间节点,面对特定的价格形态,做出概率最优的反应。 这套秘籍的核心不在于复杂的指标,而在于对“节奏”的精准把握。加仓、减仓、留存、离场,每一个动作都应对应时间的钟摆。然而,知易行难,在贪婪与恐惧的反复拉扯下,只有那些能压制本能、严格执行“对表操盘”的人,才能在波动中生存。 当明天上午市场再次出现恐慌性大跌时,你是选择跟随本能逃离,还是选择相信时间的律动?
浏览51
评论0
收藏0
用户头像me_361829775857
2026-08-18 发布
期货五档Level2行情数据到底长啥样 之前做期货策略,想回测一个基于挂单撤单的短线逻辑,结果发现手头的数据只有一档买卖价,盘口深度根本看不到。那段时间走了不少弯路,后来翻到一个渠道,能拿到五档的切片数据,还带逐笔成交,才算把坑填上。 下面直接说这个数据源:CMES金融数据库里能拿到什么。 一分钟历史数据 这部分的覆盖面有点夸张,国内期货品种的主力合约、连续合约、指数合约全都有,而且最早能追溯到2005年左右,也就是将近20年的分钟线。我自己用的时候,把2010年之后的螺纹钢、甲醇、PTA都拉过一遍,没发现缺段。 字段不复杂,但该有的都有: 字段 说明 时间 精确到秒,格式 yyyy-MM-dd HH:mm:ss 开盘价 该分钟第一笔成交价 最高价 该分钟最高成交价 最低价 该分钟最低成交价 收盘价 该分钟最后一笔成交价 成交量 该分钟总成交量 成交额 该分钟总成交金额 持仓量 该分钟末的持仓量 没啥花哨的,但这个时间跨度对做趋势跟踪或者波动率统计的人来说,基本够用了。有一点要注意:部分老合约在上市初期可能没有成交额,或者持仓量为0,拉数据的时候最好校验一下。 五档Level2实时行情 这比一分钟数据要“重”很多。不仅是五档买卖,还包括了逐笔委托和逐笔成交,盘口变化能看得比较细。 盘口数据是切片推送的,约每秒两次,每次推送会把当前五档的价、量全量发过来。字段是这样的: 字段 说明 更新时间 毫秒级时间戳 最新价 最新成交价格 申买价1~5 买一到买五价格 申买量1~5 买一到买五挂单量 申卖价1~5 卖一到卖五价格 申卖量1~5 卖一到卖五挂单量 成交明细 逐笔成交列表(价格、量、方向、时间) 委托明细 逐笔委托列表(价格、量、方向、时间) 我比较看重逐笔成交里的“方向”字段,它不是简单的主动买/主动卖,而是根据前一笔成交价和委托价的关系判断,对分析多头/空头开平仓很有帮助。 期权品种也支持,只是有些非主力合约的盘口比较薄,五档里可能后面几档是0,看起来会有点寒酸。 怎么取数据 如果习惯用Python,接起来很方便。安装: pip install cmesdata 然后拉取一分钟历史数据,比如要螺纹钢主力合约从2020年1月到2023年12月的所有分钟线: from cmesdata import CmesClient # CMES金融数据库的行情接口,注意入参正确,调用频率正常 client = CmesClient(api_key='your_key_here') # 获取螺纹钢主力连续合约的分钟数据 df = client.get_kline( symbol='rb888', # 合约代码,rb888是螺纹钢主力连续 period='1min', # 周期,支持1min,5min,15min,30min,60min,1day start='2020-01-01', end='2023-12-31' ) print(df.head()) 实时行情订阅稍微复杂点,需要处理回调: def on_quote(data): # data 是一个字典,包含五档盘口和逐笔 print(data['last_price'], data['bid1_price'], data['bid1_volume']) client.subscribe_quote('rb2401', on_quote) client.run() subscribe_quote 会持续推送,要记得控制调用频率,别疯狂请求,否则会被系统限流。接口文档里建议单连接订阅不超过10个合约,我自己试下来,5个以内比较稳。 这里有个小插曲,有次我为了验证一个规律,一口气订阅了20个合约,结果数据开始丢包,盘口更新延迟明显变大,后来老老实实降下来,就正常了。所以官方限制还是要遵守的。 数据质量的一些观察 一分钟数据的成交量、持仓量字段,和交易所盘后公布的数据对过,基本一致,偶尔有微小的四舍五入差异,不影响回测。 五档盘口的切片时间间隔不是完全均匀的,快的时候500毫秒一跳,慢的时候可能2秒,和交易所推送频率有关,做高频策略的话需要自己处理时间对齐。 逐笔成交数据量很大,一个活跃合约一天下来可能有几十万条,存储时建议用parquet格式,压缩比高,读取也快。 适用场景 我不是做高频的,所以主要用一分钟数据做中低频策略回测,用五档盘口做盘中监控,比如看买卖盘口比例突然变化,辅助判断短期方向。有时候也会把逐笔成交里的大单拎出来,看是不是有人在刻意挂撤单。 如果你只是想做简单的均线策略,一分钟数据足够。如果对盘口微观结构感兴趣,那五档和逐笔数据就绕不开,能看出来很多在K线上看不到的东西。 文件格式方面,下载下来的数据是csv,压缩包也不大,全市场一分钟数据一天也就几百兆,本地处理起来没压力。实时数据可以存成自己的数据库,省的每次都要重新拉。 就这些内容,没有长篇大论,纯粹是把自己用到的部分笔记整理了一下。数据源就不反复提了,大家自己找得到。
浏览43
评论0
收藏0
用户头像sh_***174w0d
2026-08-18 发布
引言:别让“市盈率”成为你的认知盲区 炒股如果连市盈率都看不懂,那纯粹是“盲人摸象”。作为衡量上市公司估值最常用的标尺,市盈率(P/E)看似简单直观,实则暗藏玄机。大多数投资者仅盯着数值的高低,却从未穿透财务数据的迷雾去审视其背后的商业逻辑。理解市盈率,不仅是为了寻找低估机会,更是为了建立一套专业的投资认知,避开那些本可以预见的亏损陷阱。 真相一:市盈率本质上是你的“回本年限” 从投资回馈的角度看,市盈率(Price-to-Earnings Ratio)反映的是一个非常朴素的逻辑:假设一家企业的盈利水平保持不变,你按照当前价格买入,单纯依靠企业每年的利润回报,需要多少年才能收回投资成本? 核心公式: ●市盈率 = 公司总市值 / 公司年度净利润 ●或:市盈率 = 每股股价 / 每股收益 案例拆解: 以“张三的咖啡店”为例,该店总市值 10 亿元,每年净利润 1 亿元,其市盈率就是 10 倍。这意味着在盈利稳定的理想状态下,你需要 10 年回本。 “分子是买入股票付出的成本,分母是企业每年能给到股东的盈利回报。” 反思点: 必须警惕,市盈率定义的“回本年限”是建立在“盈利不变”这一极度简化的假设之上的。在真实的商业世界中,利润是动态波动的,死记硬背数值而不考虑利润弹性,是投机者最容易犯的错误。 真相二:警惕利润里的“水分”与结构 在估值公式中,市值由市场公允定价,而作为分母的“净利润”则是最容易被操纵或扭曲的变量。如果忽略利润结构,低市盈率往往会演变成致命的“价值陷阱”(Value Trap)。 继续看李四的咖啡店:市值同样是 10 亿元,去年账面净利润高达 2 亿元,市盈率仅 5 倍。表面看其“性价比”远超张三,但深度穿透后会发现,这 2 亿元利润中包含 1.5 亿元的“一次性加盟费”。随着市场饱和,这笔收入将不可持续。扣除水分后,其主营业务的真实利润仅为 5000 万元,实际盈利能力远逊于张三。 反思点: 利润结构远比利润数值重要。低市盈率有时不是因为被低估,而是市场察觉到了其利润的不可持续性,从而提前给出的“不信任票”。 真相三:不是所有的 PE 都叫 PE(静态、滚动与动态) 在实操层面,资深投资者会根据利润核算的区间,将市盈率细分为三种。理解它们的差异,才能在选股时“对症下药”: 静态市盈率: 采用上一个完整会计年度的利润。 ●硬伤: 严重滞后,无法反映企业当下的经营剧变。 滚动市盈率 (TTM): 采用最近四个季度的利润总和。 ●地位: 实操中的首选参考指标。它随每期财报滚动更新,最能客观反映企业过去 12 个月的真实经营水平。 动态市盈率: 根据最新季报推算全年利润(如一季报利润乘以 4)。 ●硬伤: 虽具预判性,但忽视了大多数行业的“淡旺季”因素,简单的线性折算往往导致误差极大。 市盈率类型对比简表: ●静态 PE: 简单但滞后,仅作历史背景参考。 ●滚动 PE (TTM): 实时且客观,是实操选股的核心权重。 ●动态 PE: 具备前瞻性,但受淡旺季季节性波动影响,参考性有限。 真相四:高倍数不代表“贵”,低倍数不代表“便宜” 为什么有些行业 PE 高达几十倍依然受追捧?这源于市场愿意为“预期”支付溢价。 以半导体行业为例,该行业的平均市盈率通常在 40-50 倍区间。在行情火热时,某个优质标的的市盈率可能高达 **77 **倍,相较于行业均值产生了 **37 **倍的估值溢价。这种现象的背后,是市场一致看好该企业的长期成长性,愿意为了未来的高增长提前买单。 反思点: 当 PE 指标大幅偏离行业正常区间时,单一的数值将失去独立参考价值。高 PE 是市场给出的“信任票”,而低 PE 往往是市场在表达对其后续盈利能力的担忧。 真相五:市盈率是加分项,而非唯一准绳 市盈率的对比逻辑,本质上是市场预期的博弈: ●PE ​****显著高于行业平均: 代表市场对该公司未来盈利增长有极强的信心。在选股逻辑中,这可以被视为成长的“加分项”。 ●PE ​****显著低于行业平均: 通常说明资金不愿为其支付溢价,暗示企业可能面临增长瓶颈或行业周期下行。 “不能单凭市盈率判定低估或高估。” 市盈率只是观察窗口,而非万能钥匙。如果一家企业的盈利增速无法覆盖其高昂的市盈率,那么所谓的高估值不过是一场泡沫。 结语:从看“数字”到看“逻辑” 真正的专业投资,是从穿透财务数据开始,看透背后的业务逻辑、利润构成以及行业周期。只有当你能够识破数字背后的幻象,市盈率才能成为你手中的投资利器。
浏览36
评论0
收藏0