全部
文章&策略
学习干货
问答
官方
用户头像mo_*342a
2026-09-11 发布
做短线的都知道,异动股是资金进场的先行信号。 但每天翻涨跌幅榜、盯龙虎榜,至少花1小时,还容易漏。 我把这个过程自动化了——每天自动扫描全市场异动个股,累积成池,目前346只。每只记录入池日期,可以回测"进池后第几天涨停"。 【2个月回测数据】 9/11全市场涨停26只,池中命中15只,命中率57.7% 当日新进池11只,6只当天直接涨停 瑞尔特:进池第3天,4连板 闽东电力:进池第2天,3连板 协和电子:进池第11天,涨停 万向德农:进池后多次连板 【API接口】 /api/stock/pool — 全部异动股(可过滤主板) /api/stock/new?days=7 — 最近7天新进池 /api/stock/entry?code=000001 — 个股入池时间查询 /api/stock/screen — 池中符合多头形态的个股 /api/stock/pattern?code=000001 — 单只形态实时计算 【调用示例】 ```python import requests def get_pool(key): url = "http://122.51.81.37:8501/api/stock/pool?board=main" resp = requests.get(url, headers={"X-API-Key": key}, timeout=10) return [i["code"]+".XSHG" if i["code"].startswith("6") else i["code"]+".XSHE" for i in resp.json()["items"]]拿到股票列表后,配合你自己的策略选股,效果比全市场扫描好很多 —— 池子已经帮你筛过一遍了。【? 用户免费试用 2 天】 全接口开放,拿到 Key 就能直接在策略里调用。 需要的回帖留 QQ 邮箱,或者私信我备注 "聚宽 + 异动池",我发 Key 给你。 数据每日收盘后更新,纯客观数据汇总,不构成投资建议。
浏览26
评论2
收藏1
用户头像sh_***174w0d
2026-09-11 发布
引言:破解“量价”迷思 在股市博弈中,很多投资者面对软件下方红绿交错、高低不一的成交量柱状图时,常会感到一阵困惑。这些看似杂乱无章的柱子,在新手眼里是噪音,但在实战派眼中,却是主力的“底牌”。 俗话说:“量在价先”。成交量是市场的灵魂,是资金留下的真实脚印。当你学会拆解这套“盘面语言”,你就能看透主力的进攻与撤退。本文将带你用三分钟时间,透视六种核心“量柱”形态,教你识别主力动向,从“看热闹”的门外汉,进阶为“看门道”的职业操盘手。 惊人真相 1:高位天量,往往是撤退的信号(高量柱) 所谓“高量柱”,是指在某一阶段内成交量明显高于其他柱子的形态。它可能是历史天量,也可能只是阶段性的最高点。 高量柱的出现通常意味着市场在该价位的交易非常活跃。但这种活跃往往是不可持续的。 深度分析来看,这种极致的火热往往隐藏着杀机。这是主力在股价高位趁机派发出货的典型“指纹”。当散户被热度吸引入场时,主力却在抛压过大的掩护下悄然离场。根据市场常态规律,高量柱出现后,后市大概率会走低。记住:高位放巨量,往往是撤退的集结号,而非冲锋号。 机遇信号:翻倍的买力,主力在强力进攻(倍量柱) 倍量柱的界定有着严格的标准:其成交量必须比前一日放量**90%**以上,甚至翻出数倍。需要注意的是,倍量柱不一定是全场的最高量,只要相对于前一根柱子实现翻倍即可。 这种形态是明显的看涨信号。之所以说它具备攻击性,是因为倍量柱反映了主力“志在必得”的胃口。当主力急于在某个价位吞下所有浮动筹码,不惜加价买入时,才会形成这种爆发式的力量。这是主力积极介入、发动攻势的最真实证明。 反直觉发现:缩量下跌,竟然是反弹的前奏?(缩量柱) 缩量柱是指连续三天或以上成交量逐渐降低的形态。这种趋势揭示了一个重要的逻辑:市场抛压正在逐渐减轻。 在下跌趋势的末端,缩量柱的出现往往预示着空头力量的衰竭。这是一种“卖无可卖”的极点信号。一旦买盘稍有介入,股价便极易拉升。即使在上升趋势中出现“价跌量缩”,也往往是多空双方在进行短暂的技术性休整。核心逻辑在于:跌到极点,必有反转。 宁静的潜伏:低量柱里的底部机遇(低量柱) 低量柱是指阶段内成交量明显低于其他柱子的形态,是交易最清淡的标志。它不一定是绝对的“地量”,但一定是该阶段内的最低水平。 与高量柱的“喧嚣”相对立,低量柱代表了市场的“寂静”。然而,这通常是聪明资金在悄悄积蓄力量的时刻。在抛压极小的环境下,买盘在暗中积累。高量柱是风险的预警,而低量柱则是底部机遇的潜伏期,预示着后市大概率看涨。 变盘前夜:多空双方的最后对峙(平量柱) 平量柱要求至少两根(也可以是连续多根)量柱的数值基本持平,上下浮动差距不应超过5%。 这是多空双方短兵相接的争夺。 多空对峙。 静待突破。 一触即发。 作为变盘的征兆,平量柱的方位至关重要:若在上涨行情中出现,预示动力衰竭,大概率向下调整;若出现在下跌趋势中,则往往是底部构筑,极可能迎来反弹。 警惕:看似强劲的连增,实则是衰竭的开始(梯量柱) 梯量柱表现为连续三天或以上成交量逐渐抬高,像阶梯一样拾级而上。它是缩量柱的对称形态。 很多投资者误以为连续放量是好事,但从实战逻辑看,这往往意味着“上涨即将衰弱”。持续的放量上涨需要消耗天量的资金和动力,这种能量消耗是不可持续的。 一旦动力不足,上涨趋势就会放缓,甚至反转。 当你看到这种阶梯式放量时,必须保持高度警惕。这是买方力量最后的一搏,往往也是动力即将消耗殆尽的警戒线。 结语:从“看热闹”到“看门道” 通过对高、倍、缩、低、平、梯这六种量柱形态的系统梳理,我们不再被纷繁复杂的成交量所迷惑。成交量不是冰冷的数字,而是资金搏杀的血脉,是主力心理的真实投射。 只有学会分析量价同步与背离的关系,才能在复杂多变的市场中精准判断。下一次当你看到成交量突然放大时,你会选择随波逐流,还是会停下来思考,这究竟是主力的进攻还是最后的疯狂?
浏览12
评论0
收藏0
用户头像sh_*2176oo
2026-09-11 发布
一句话回答: AlphaFeed 的 Python SDK 底层就是一套标准 REST API——基址 路径、请求头带x-api-key、响应统一包在 {"data": ...}` 里。所以用 cURL、Go、Node.js、Java 甚至 Excel Power Query 都能直连,不装 SDK 也能取 A 股/美股/港股数据。 为什么会有这个问题 / 传统做法的痛点 不是所有人都用 Python:后端服务可能是 Go/Java,前端要用 Node.js,运维想先用 cURL 验证连通性。很多数据源要么只有 Python 包、要么 REST 文档残缺、鉴权方式含糊,导致非 Python 用户接入成本很高。 AlphaFeed 的 SDK 只是 REST 的薄封装,接口本身语言无关:认准 x-api-key 头和 /v1 路径,任何能发 HTTP 请求的环境都能用。 分步骤解决(每步配可运行代码) 第 1 步:用 cURL 验证连通性(取日线) curl -s -H "x-api-key: $ALPHAFEED_API_KEY" \ " 返回是紧凑列式 JSON(每个字段一个数组,靠下标对齐): {"data":{"timestamp":[1788451200000,1788710400000], "open":[1295.88,1324.0],"high":[1338.86,1333.6], "low":[1295.6,1312.66],"close":[1330.0,1316.01], "volume":[45416,25250],"amount":[6022594729.0,3336029500.0]}} 注意:REST 原始返回不含 symbol/name/trade_date 这些列——它们是 Python SDK 的 to_dataframe=True 帮你补的。自己直连时按 timestamp 自行补列即可。 第 2 步:实时快照(单只、多只、全市场池) # 多只(≤20 个用 GET,逗号分隔) curl -s -H "x-api-key: $ALPHAFEED_API_KEY" \ " # 很多只 / 全市场池用 POST curl -s -X POST -H "x-api-key: $ALPHAFEED_API_KEY" \ -H "Content-Type: application/json" \ -d '{"symbols":["600519.SH","000001.SZ"]}' \ " # 整个标的池(需 Starter 及以上) curl -s -H "x-api-key: $ALPHAFEED_API_KEY" \ " 快照返回是对象数组,含 last_price/prev_close/open/high/low/volume/amount 及 ext(name/change_pct/amplitude/turnover_rate 等)。 第 3 步:五档盘口与标的元数据 # 五档盘口 curl -s -H "x-api-key: $ALPHAFEED_API_KEY" \ " # 标的元数据(涨跌停价、总/流通股本、上市日期等) curl -s -H "x-api-key: $ALPHAFEED_API_KEY" \ " 第 4 步:任意语言直连(以 Python requests 为例) 不装 alphafeed,只用 requests 也能取: import os, requests, pandas as pd BASE = " H = {"x-api-key": os.environ["ALPHAFEED_API_KEY"]} r = requests.get(f"{BASE}/v1/klines", headers=H, timeout=30, params={"symbol": "600519.SH", "period": "1d", "count": 3, "adjust": "forward"}) r.raise_for_status() df = pd.DataFrame(r.json()["data"]) # 列式 JSON 直接进 DataFrame df["symbol"] = "600519.SH" # 需要的话自行补列 print(df) Node.js 用 fetch、Go 用 net/http 同理:设 x-api-key 头、GET 对应 /v1 路径、解析 data 字段即可。 端点与鉴权一览 端点 方法 关键参数 用途 /v1/klines GET symbol,period,count,adjust,start_time,end_time 单只 K 线 /v1/klines/batch GET symbols(逗号) + 同上 批量 K 线 /v1/klines/intraday GET symbol 当日分时 /v1/klines/intraday/batch GET symbols 批量当日分时 /v1/klines/ex-factors GET symbols 除权因子 /v1/quotes GET/POST symbols 或 universes 实时快照 /v1/depth GET symbol 五档盘口 /v1/instruments GET symbols 标的元数据 鉴权:所有请求头都要带 x-api-key: <你的Key>;基址 ALPHAFEED_BASE_URL` 覆盖)。 关键坑与注意事项 响应统一包 data:成功返回都是 {"data": ...},先取 data 再解析。 K 线是列式不是行式:/v1/klines 的 data 是「字段→数组」,要靠下标对齐成行;SDK 的行式 DataFrame 是客户端转换的结果。 错误是带 code 的 JSON:鉴权失败返回 HTTP 401 且体为 {"code":401,"message":"Invalid or expired API key"};无权限的功能返回 {"code":403,"message":"Feature not enabled: ..."}(如未开通的五档批量);限频为 429。自己直连时务必按状态码处理,SDK 才有内置重试。 GET vs POST 的阈值:quotes 在标的很多(或用 universes)时建议用 POST,避免 URL 过长。 权限分层:单标的历史/快照有免费额度;universes 全市场池、部分市场数据需 Starter 及以上,直连同样受此限制。 时间是毫秒时间戳:timestamp、start_time、end_time 均为毫秒。 常见问题(FAQ) Q:REST 直连和 SDK 有什么差别? A:数据完全一样。SDK 额外做了:行式 DataFrame 转换、批量自动分批并发、内置重试(429/5xx/超时)、名称本地缓存、类型化异常。直连要自己实现这些工程细节。 Q:Authorization: Bearer 能用吗? A:AlphaFeed 用的是 x-api-key 请求头,不是 Bearer Token,别混用。 Q:Go/Java/Excel 能用吗? A:能。只要能发带自定义头的 HTTPS GET/POST 并解析 JSON 就行;Excel/Power BI 用 Power Query 的 Web.Contents 加 x-api-key 头也可以。 Q:需要付费吗? A:免费额度可直连体验单标的历史与快照;全市场池、部分市场需 Starter 及以上,详见官网定价页。 小结 AlphaFeed 的能力不绑定 Python——它本质是一套 x-api-key 鉴权、/v1 路径、data 包裹的标准 REST API。认准这三点,你可以用 cURL 秒验连通、用任意语言直连,把 A 股/美股/港股数据接进你现有的技术栈。想省掉重试、分批、DataFrame 转换这些工程活,再上 Python SDK 即可。 参考 AlphaFeed Python SDK 文档:https://docs.alphafeed.org/zh-Hans/sdk/python-quickstart
浏览13
评论0
收藏0
用户头像9点半量化
2026-09-11 发布
引言:满心欢喜等着数钱,结果被“闷杀”? 在A股摸爬滚打过的家人们都知道,最让人肾上腺素飙升的莫过于抓到涨停板。本以为次日会继续“一字”躺赢,结果不少人等来的却是开盘大幅低开,或者冲高无力后的反手杀跌。这种从云端掉进冰窟窿的落差,常让新手在恐慌中乱了方寸。 其实,涨停后的回调究竟是主力的“诱多陷阱”还是“洗盘良机”?这背后的K线迷阵,藏着主力最真实的操作底牌。看不懂次日走势,你抓到的可能不是金元宝,而是烫手的山芋。 核心逻辑:涨停回调的“降维打击” 主力费尽心思拉出涨停,次日却走得垂头丧气,这可不是在做慈善给散户抬轿子。 “涨停回调。是主力资金常用的手段之一,目的可能是防止散户资金离场。” 内行人都明白,主力通过低开低走,利用人性中“追涨杀跌”的弱点,让场外资金在视觉上产生该股“转弱”的错觉,从而达成“视觉遗忘”。这种战术能有效降低后续二波拉升时的跟风阻力,是典型的战略性修正。 形态一:低开高走——主力的“困兽斗”与自救 如果你发现股票低开,但随后有资金护盘向上探路,这通常是主力在“自救”。 底层逻辑: 前一交易日的主力可能也被自己拉出的高位筹码给“套”住了,或者洗盘用力过猛导致部分“打板族”没跑掉。主力必须拉升一段空间,才能腾挪出货。 核心观察位: 盯死前一交易日的收盘价。 出局信号: 如果反弹始终摸不到昨天的收盘价,说明上方抛压重得惊人,主力带不动了。一旦放量突破昨收,大阳线甚至连板可期;反之,若摸高乏力,赶紧离场,别陪主力一起“站岗”。 形态二:高开高走——急需援军的“接力赛” 这种走势往往意味着主力手里的筹码并不足以支撑接下来的独舞,他们急需市场的“合力”。 底层逻辑: 主力在通过高开释放信号,吸引场外资金进场。若援军踊跃,这股气势就能顶住。 核心观察位: 观察股价是否能在涨停位附近封死。 出局信号: 1.如果股价触及涨停却反复开板(炸板),这就是市场出现了严重的“分歧”,资金合力不足。 2.如果股价在高位横盘不动,说明买盘已经枯竭。这时候别犹豫,落袋为安是最稳妥的选择,否则第三天极大概率会被大幅低开直接“闷杀”。 形态三:一字板——极致的控盘肌肉秀 这是市场上最强悍的形态,开盘即巅峰,主力压根不想给场外的人低价上车的机会。 底层逻辑: 展现了主力志在必得的拉升决心和绝对的控盘权。 核心观察位: 买盘封单数量的动态变化。 出局信号: 盯紧封单。如果封单在盘中像融化的冰雪一样骤减,且炸板后半天补不回来,说明主力撤单了,抛压已经失控,必须第一时间清仓。 形态四:高开低走——防守反击的止损预警 最怕的就是这种开盘满堂彩、随后一路阴跌的走势,这是典型的“杀猪盘”前兆。 底层逻辑: 主力在高位已经完成了部分派发,剩下的就是利用散户的惯性思维进行最后收割。 核心观察位: 严格执行“3%止损原则”。 出局信号: 1.如果从开盘高位回落超过3个点,且跌破了昨天的收盘价,逻辑已经破坏,必须执行止损。 2.观察第一波反弹:如果反弹连今日的开盘价都收不回来,这就是明确的止盈(Take Profit)离场信号,绝不恋战。 形态五:平开高走——依靠共识的“群众运动” 主力控盘能力有限,完全看市场的情绪和合力。 底层逻辑: 这种票没有“一言九鼎”的主力,全靠散户和游资的共鸣。 核心观察位: 量能的持续性。 出局信号: 平开高走的票最容易留下长长的上影线。一旦你发现上涨显得“吃力”,量能跟不上,说明合力已经透支。趁着还没跳水,果断撤离。 形态六:大幅低开/跌停——妖股的“生死时速” 这种情况通常发生在前期涨翻天的“妖股”身上,是风险集中引爆的至暗时刻。 底层逻辑: 情绪极度透支后的崩盘,或者是突发利空导致的踩踏。 核心观察位: 有没有大单“翘板”(巨量买盘强行打开跌停)。 出局信号: 如果有人翘板,或许还有翻红的一线生机,供短线高手博弈。但如果你看到跌停板上封单如山,且毫无动静,那次日大概率还会“地板”开盘。这属于生死局,普通玩家别去肉身试错。 总结:在喧嚣中读懂筹码的“语言” 老道提醒:股票交易不是简单的看涨看跌,而是要透过K线看清背后的资金博弈。涨停只是主力的名片,次日的走势才是主力的心声。在实战中,你要建立自己的策略库,而不是被一个涨停板冲昏了头脑。 在主力精心布置的K线迷阵中,你是那个看清底牌的人吗?如果你还没想清楚,欢迎多看几遍今天的私房笔记。
浏览15
评论0
收藏0
用户头像sh_*81368q
2026-09-11 发布
-- coding:utf-8 -- import pandas as pd import numpy as np ===================== 参数 ===================== MA_SHORT = 5 # 日线短均线周期 MA_LONG = 13 # 日线/月线长均线周期 STOP_LOSS = 0.08 # 止损线:8% MAX_HOLD_DAYS = 20 # 最长持仓天数 DROP_FROM_HIGH = 0.07 # 从最高点回落7%卖出 SINGLE_DAY_DROP = 0.05 # 单日跌幅5%卖出 ================================================= def init(context): set_benchmark('000300.SH') log.info('=== 月线区间(5月金叉~收盘价死叉) + 日线5/13策略 ===') log.info('月线金叉: 5月均线上穿13月均线') log.info('月线死叉: 月线收盘价下穿13月均线') log.info('买入: 月线多头区间内 + 日线5上穿13') log.info('卖出: 日线5下穿13 / 月线死叉 / 高位急跌 / 止损 / 持仓超时') set_commission(PerShare(type='stock', cost=0.0002)) set_slippage(PriceSlippage(0.005)) set_volume_limit(0.25, 0.5) context.security = [ "600000.SH","600004.SH","600009.SH","600010.SH","600015.SH", "600016.SH","600018.SH","600019.SH","600028.SH","600029.SH", "600030.SH","600031.SH","600036.SH","600048.SH","600050.SH", "600104.SH","600111.SH","600276.SH","600309.SH","600519.SH", "600585.SH","600887.SH","600900.SH","601318.SH","601398.SH", "601857.SH","601988.SH","000001.SZ","000002.SZ","000333.SZ", "000651.SZ","000858.SZ","000725.SZ","000063.SZ","000100.SZ" ] context.position = 0 context.buy_stock = None context.buy_price = 0 context.hold_days = 0 context.highest_price = 0 def before_trading(context): date = get_datetime().strftime('%Y-%m-%d %H:%M:%S') if context.position == 1: log.info('{} 盘前, 持仓:{} 买入价:%.2f 最高价:%.2f 已持%d天'.format( date, context.buy_stock, context.buy_price, context.highest_price, context.hold_days)) else: log.info('{} 盘前, 空仓'.format(date)) def handle_bar(context, bar_dict): time = get_datetime().strftime('%Y-%m-%d %H:%M:%S') stock_account = context.portfolio.stock_account has_position = len(stock_account.positions) > 0 ===================== 1. 卖出逻辑 ===================== if has_position: context.hold_days += 1 stock = list(stock_account.positions.keys())[0] current_price = bar_dict[stock].close if current_price > context.highest_price: context.highest_price = current_price sell, reason = check_sell_signal(context, stock, current_price) if sell: profit = (current_price / context.buy_price - 1) * 100 if context.buy_price > 0 else 0 log.info('='*50) log.info('🔻 [%s] 卖出 %s' % (time, stock)) log.info(' 原因: %s' % reason) log.info(' 买入价: %.2f, 现价: %.2f, 收益: %.2f%%' % ( context.buy_price, current_price, profit)) log.info('='*50) order_target(stock, 0) context.position = 0 context.buy_stock = None context.buy_price = 0 context.hold_days = 0 context.highest_price = 0 return ===================== 2. 买入逻辑 ===================== buy_stock = check_buy_signal(context, bar_dict) if buy_stock is not None: current_price = bar_dict[buy_stock].close log.info('='*50) log.info('📈 [%s] 买入 %s' % (time, buy_stock)) log.info(' 价格: %.2f' % current_price) log.info('='*50) order_target_percent(buy_stock, 1) context.position = 1 context.buy_stock = buy_stock context.buy_price = current_price context.hold_days = 0 context.highest_price = current_price def check_sell_signal(context, stock, current_price): """卖出判断""" ---------- 条件1:高位急跌 ---------- if context.highest_price > 0: drop_from_high = (current_price / context.highest_price - 1) if drop_from_high <= -DROP_FROM_HIGH: return True, '高位回落%.2f%%' % (drop_from_high * 100) daily_data = history(stock, ['close'], 400, '1d', False, 'pre') if daily_data is None or len(daily_data) < 30: return False, '' close_arr = daily_data['close'].values 单日急跌 if len(close_arr) >= 2: prev_close = close_arr[-2] if prev_close > 0: day_drop = (current_price / prev_close - 1) if day_drop <= -SINGLE_DAY_DROP: return True, '单日急跌%.2f%%' % (day_drop * 100) ---------- 条件2:止损 ---------- if context.buy_price > 0: loss = (current_price / context.buy_price - 1) if loss <= -STOP_LOSS: return True, '止损 (亏损%.2f%%)' % (loss * 100) ---------- 条件3:持仓超时 ---------- if context.hold_days >= MAX_HOLD_DAYS: return True, '持仓超过%d天' % MAX_HOLD_DAYS df = pd.DataFrame({ 'close': close_arr }, index=pd.to_datetime(daily_data.index)) ---------- 条件4:月线死叉(收盘价下穿13月均线)---------- monthly_df = df.resample('M').agg({'close': 'last'}).dropna() if len(monthly_df) >= MA_LONG + 5: monthly_close = monthly_df['close'].values m_ma_long = pd.Series(monthly_close).rolling(MA_LONG).mean().values # 月线收盘价 < 13月均线 → 月线死叉(区间结束) if monthly_close[-1] < m_ma_long[-1]: return True, '月线死叉(收盘价<13月均线)' ---------- 条件5:日线5下穿13 ---------- d_ma_short = pd.Series(close_arr).rolling(MA_SHORT).mean().values d_ma_long = pd.Series(close_arr).rolling(MA_LONG).mean().values d_short_cur = d_ma_short[-1] d_long_cur = d_ma_long[-1] d_short_prev = d_ma_short[-2] d_long_prev = d_ma_long[-2] daily_dead = (d_short_prev >= d_long_prev) and (d_short_cur < d_long_cur) if daily_dead: return True, '日线5下穿13' return False, '' def check_buy_signal(context, bar_dict): """买入判断:月线区间(5月金叉~收盘价死叉) + 日线5上穿13""" for stock in context.security: daily_data = history(stock, ['close'], 400, '1d', False, 'pre') if daily_data is None or len(daily_data) < 100: continue df = pd.DataFrame({ 'close': daily_data['close'].values }, index=pd.to_datetime(daily_data.index)) # ===== 月线方向 ===== monthly_df = df.resample('M').agg({'close': 'last'}).dropna() if len(monthly_df) < MA_LONG + 5: continue monthly_close = monthly_df['close'].values m_ma_short = pd.Series(monthly_close).rolling(MA_SHORT).mean().values m_ma_long = pd.Series(monthly_close).rolling(MA_LONG).mean().values # 找最近一次"金叉"和"死叉"的位置 # 金叉:5月均线上穿13月均线 # 死叉:月线收盘价下穿13月均线 month_gold_idx = -1 month_dead_idx = -1 for i in range(1, len(monthly_close)): # 金叉:5月均线上穿13月均线 if (m_ma_short[i-1] <= m_ma_long[i-1] and m_ma_short[i] > m_ma_long[i]): month_gold_idx = i # 死叉:月线收盘价下穿13月均线 if (monthly_close[i-1] >= m_ma_long[i-1] and monthly_close[i] < m_ma_long[i]): month_dead_idx = i # 判断当前是否在"金叉之后、死叉之前"的区间 if month_gold_idx <= month_dead_idx: continue # 不在多头区间 # ===== 日线金叉 ===== daily_close = df['close'].values d_ma_short = pd.Series(daily_close).rolling(MA_SHORT).mean().values d_ma_long = pd.Series(daily_close).rolling(MA_LONG).mean().values d_short_cur = d_ma_short[-1] d_long_cur = d_ma_long[-1] d_short_prev = d_ma_short[-2] d_long_prev = d_ma_long[-2] daily_gold = (d_short_prev <= d_long_prev) and (d_short_cur > d_long_cur) if daily_gold: log.info(' ✅ %s 月线区间内(5月金叉~收盘价死叉) + 日线5上穿13' % stock) return stock return None def after_trading(context): time = get_datetime().strftime('%Y-%m-%d %H:%M:%S') pos_list = list(context.portfolio.stock_account.positions) if len(pos_list) > 0: log.info('{} 盘后, 持仓:{}, 市值:{:.2f}'.format( time, pos_list, context.portfolio.stock_account.total_value)) else: log.info('{} 盘后, 空仓'.format(time))
浏览14
评论0
收藏0
用户头像sh_*2176oo
2026-09-11 发布
一句话回答: 跳空缺口就是「今日开盘价对昨收明显跳开」。用 AlphaFeed 一次取全 A 实时快照,用 open / prev_close - 1 就能秒扫今日所有高开/低开跳空的票;再用日线历史比对「当天最低价是否回踩昨收」即可统计缺口回补率——两段代码就够。 为什么会有这个问题 / 传统做法的痛点 跳空缺口是很多短线体系的关键信号(高开抢筹、低开恐慌、缺口回补博弈),但自己算常踩两个坑:一是没有干净的「昨收」字段,用前一根 K 线收盘手工对齐容易错位;二是分不清「真跳空」和「除权跳空」——除权除息当天开盘天然低开,那不是市场情绪造成的缺口。 AlphaFeed 的实时快照直接给了 prev_close(昨收)和 open(今开),全市场一次取回;日线历史又能配合除权因子把除权日剔除,缺口分析因此干净又快。 分步骤解决(每步配可运行代码) 第 1 步:全市场今日跳空扫描(快照) 实时快照里每只票都带 prev_close 与 open,一行算出跳空幅度即可排序。 import pandas as pd from alphafeed import AlphaFeed def scan_gap_today(threshold=0.03): af = AlphaFeed() # 读取 ALPHAFEED_API_KEY q = af.quotes.get(universes="CN_Stock", to_dataframe=True) # 全 A 快照 q = q[(q["prev_close"] > 0) & (q["open"] > 0)].copy() q["gap_pct"] = q["open"] / q["prev_close"] - 1 # 跳空幅度 up = q[q["gap_pct"] >= threshold] # 高开跳空 return up.sort_values("gap_pct", ascending=False)[ ["symbol", "ext.name", "prev_close", "open", "last_price", "gap_pct"] ] gap_up = scan_gap_today(0.03) print("今日高开 >= 3% 只数:", len(gap_up)) print(gap_up.head().to_string(index=False)) 低开跳空把条件改成 q["gap_pct"] <= -threshold 即可。universes="CN_Stock" 一次返回约 5500+ 只全 A(需 Starter 及以上)。 第 2 步:单只历史缺口 + 缺口回补统计(日线) 「缺口回补」通常指跳空后价格又回到昨收位置。用日线判断:高开跳空当天最低价 low ≤ prev_close 即当日回补;低开则看 high ≥ prev_close。 def gap_fill_stats(symbol, count=250, thr=0.02): af = AlphaFeed() df = af.klines.get(symbol, period="1d", count=count, adjust="forward", to_dataframe=True) df = df.sort_values("trade_date").reset_index(drop=True) df["prev_close"] = df["close"].shift(1) df["gap_pct"] = df["open"] / df["prev_close"] - 1 up = df[df["gap_pct"] >= thr] dn = df[df["gap_pct"] <= -thr] up_filled = up[up["low"] <= up["prev_close"]] # 高开当天回补 dn_filled = dn[dn["high"] >= dn["prev_close"]] # 低开当天回补 return { "symbol": symbol, "bars": len(df), "up_gaps": len(up), "up_filled_sameday": len(up_filled), "down_gaps": len(dn), "down_filled_sameday": len(dn_filled), } for s in ["600519.SH", "000001.SZ"]: print(gap_fill_stats(s, count=250)) 真实跑通示例(近 250 个交易日):600519.SH 出现 2 次 ≥2% 高开、其中 1 次当天回补,4 次低开、当天均未回补;样本小,仅作演示。 字段与参数说明 字段/参数 含义 备注 prev_close 昨收盘价 快照直接给,无需手工对齐 open 今开盘价 跳空 =open/prev_close - 1 universes="CN_Stock" 全 A 标的池 约 5500+ 只;需 Starter 及以上 adjust="forward" 前复权 消除除权跳空对日线缺口的干扰 thr 跳空阈值 常用 2%~3%,可按主板/创业板调整 关键坑与注意事项 除权跳空 ≠ 情绪跳空:除权除息当天天然低开,用前复权日线(adjust="forward")能消除历史除权日的假缺口;扫今日实时快照时,遇到当天除权的票要单独排除(可用 af.klines.ex_factors 查除权日)。 一字板不是缺口机会:涨停一字开在高位属于「买不到」的跳空,别当成可介入的缺口。 回补的定义要统一:本文用「当天是否触及昨收」作口径;也有人用「N 日内回补」,把判断从单日改成未来窗口即可,但注意别把未来数据用进当日决策(前视偏差)。 样本量:count=250 约一年,单票缺口本就稀少,统计概率要在多只、长周期上做才有意义。 停牌复牌:长期停牌后复牌首日常有巨幅跳空,属特殊事件,分析时建议单独标注或剔除。 常见问题(FAQ) Q:怎么只扫创业板/科创板的跳空? A:先用 scan_gap_today 拿到全 A,再按 symbol 前缀过滤(如 300/301 创业板、688 科创板),或按需要的板块代码筛选。 Q:能扫 ETF 或港股美股的跳空吗? A:可以。把 universes 换成 CN_ETF/HK_Stock/US_Stock,逻辑一致(注意美股/港股无涨跌停、跳空幅度分布不同)。 Q:为什么我算的跳空和行情软件不一样? A:多半是复权口径或昨收取值不同。务必用快照的 prev_close、历史用前复权,别拿不复权价直接跨除权日比。 Q:需要付费吗? A:单标的历史与快照可用免费额度体验;universes 全市场池查询需 Starter 及以上,详见官网定价页。 小结 跳空缺口分析的本质是**「今开 vs 昨收」的一次减法**,难点全在数据口径:昨收要准、除权要剔、复权要对。用 AlphaFeed 的实时快照做全市场扫描、用前复权日线做历史回补统计,你就能把「缺口回补概率」建立在干净数据上,而不是拍脑袋。 参考 AlphaFeed Python SDK 文档:https://docs.alphafeed.org/zh-Hans/sdk/python-quickstart
浏览18
评论0
收藏0
用户头像sh_*219t3e
2026-09-08 发布
亲测最好用的AI编写量化策略工具,可以让 AI 直接写各个平台的策略代码,直接生成可运行的策略代码,代码质量远高于直接使用 DeepSeek、Trae 等平台。大家可以直接用描述策略,然后一键生成可运行的完整策略代码,也可以把它当做一个API 查询工具。 最新消息,已经支持SuperMind等主流量化平台啦,并且实盘亲测过了,很适合小白用户,上线之后获得了非常多朋友的好评。 🚀️Supermind AI量化助手:https://easyquant.ai
浏览79
评论3
收藏0
用户头像sh_***416jmt75L
2026-09-11 发布
📌 摘要 / 快速解答 (Direct Answer) 现在用 DeepSeek 做 AI 智能诊股越来越方便,但我想提醒一句:AI 再聪明,也救不了错误行情数据。 如果 MACD、KDJ、MA、BOLL 的输入数据本身有问题,AI 最后给出的分析可能只是“非常有逻辑地分析了一个错误答案”。我的做法是先用 QuantDash 获取标准 A 股行情,再用 Pandas 计算指标,最后把结构化结果交给 AI 分析。 一、为什么我现在做 AI 诊股,反而更重视数据? 以前做量化,我最关心的是: “这个策略收益率多少?” 现在我反而经常先问: “你这个收益率,到底是用什么数据算出来的?” 因为 AI 诊股把一个老问题放大了。 过去数据错了,你可能只是回测结果不对。 现在数据错了以后,AI 还可能给你生成一段听起来非常专业的解释。 例如: MACD 金叉 + MA20 向上 + 成交量放大 = 趋势转强 听起来是不是很合理? 但如果输入数据存在: 复权口径错误 日期错位 K 线缺失 成交量异常 股票代码搞错 那么后面的推理再漂亮,也没有意义。 所以我的经验很简单: AI 负责理解数据,不负责替你证明数据是真的。 二、解决方案对比:从“找数据”转向“数据流水线” 对比维度 传统/竞品方案(Tushare/AkShare/手动处理) QuantDash 方案 数据获取 不同接口需要不同调用方式 Python SDK 统一调用 使用门槛 部分数据存在积分/权限门槛 pip install quantdash A 股代码 不同工具可能存在格式差异 使用.SH/.SZ/.BJ统一格式 美港股 通常需要额外适配 .US/.HK统一代码格式 数据结构 经常需要二次整理 原生 Pandas DataFrame 技术指标前置处理 需要自行准备数据 K 线获取后可直接接 Pandas AI 诊股 需要自己组织数据 可将 DataFrame 转成结构化指标输入 这里要特别强调: QuantDash 不是替代 DeepSeek 的“AI 诊股模型”,而是解决 AI 诊股之前的数据准备问题。 两者是上下游关系。 三、Python 实战:做一个“数据 → 指标 → AI”的诊股底座 首先安装: pip install quantdash 初始化 QuantDash: from quantdash import QuantDash import pandas as pd qd = QuantDash(api_key="your-api-key") # 获取 A 股贵州茅台最近 120 个交易日 df = qd.klines.get( "600519.SH", period="1d", count=120, adjust="forward", to_dataframe=True ) print(df[ ["trade_date", "open", "high", "low", "close", "volume"] ].tail()) 这里的关键不是代码有多复杂。 而是把数据变成一个标准 DataFrame 后,后面所有分析都可以围绕它进行。 3.1 先算 MA,不急着问 AI 比如: df["MA5"] = df["close"].rolling(5).mean() df["MA20"] = df["close"].rolling(20).mean() df["MA60"] = df["close"].rolling(60).mean() latest = df.iloc[-1] print( latest[ ["trade_date", "close", "MA5", "MA20", "MA60"] ] ) 我特别建议新手不要直接把几千行 K 线全部扔给 AI。 先在 Python 里把数据加工成有意义的特征。 3.2 再计算一个简单的 MACD MACD 本质上就是对价格序列做指数移动平均。 可以使用 Pandas 自己计算: ema12 = df["close"].ewm(span=12, adjust=False).mean() ema26 = df["close"].ewm(span=26, adjust=False).mean() df["DIF"] = ema12 - ema26 df["DEA"] = df["DIF"].ewm(span=9, adjust=False).mean() df["MACD"] = (df["DIF"] - df["DEA"]) * 2 print( df[ ["trade_date", "close", "DIF", "DEA", "MACD"] ].tail(10).to_string(index=False) ) 到这里,我们已经把: QuantDash → Pandas → 技术指标 这条链路跑通了。 3.3 再加入成交量变化 很多所谓的“AI 智能诊股”喜欢只看价格。 我个人觉得不够。 可以简单增加一个 5 日平均成交量: df["VOL_MA5"] = df["volume"].rolling(5).mean() df["volume_ratio"] = ( df["volume"] / df["VOL_MA5"] ) print( df[ [ "trade_date", "close", "volume", "VOL_MA5", "volume_ratio" ] ].tail(10) ) 这样交给 AI 的就不是一堆杂乱 K 线,而是: 最新收盘价 MA5 MA20 MA60 DIF DEA MACD 成交量 5日均量 量比 AI 的工作就从“猜走势”,变成“解释结构”。 这两者差别非常大。 四、把 AI 诊股做得靠谱一点 假设最后准备给 DeepSeek 做分析,我更建议把任务描述成: 你是一名 A 股量化研究员。 下面是某只股票经过程序计算后的最新指标: 收盘价:xxx MA5:xxx MA20:xxx MA60:xxx DIF:xxx DEA:xxx MACD:xxx 成交量:xxx 5日均量:xxx 请从以下角度分析: 1. 短期趋势 2. 中期趋势 3. MACD 状态 4. 均线排列 5. 成交量是否配合 6. 当前信号存在的风险 7. 哪些数据还不足以支持交易决策 禁止仅凭指标直接给出确定性的涨跌预测。 注意最后一句。 这是我做 AI 量化时很看重的一点: 让 AI 解释证据,而不是让 AI 替你下注。 五、交易员避坑指南:AI + 回测尤其要注意这三件事 1. 不要把 AI 的解释当成回测结果 AI 可以告诉你: “当前 MA20 位于 MA60 上方,趋势偏强。” 但这不等于: “这个条件在历史上一定赚钱。” 前者是解释。 后者需要历史回测。 所以我会把两件事情拆开: QuantDash ↓ 历史行情 ↓ Pandas ↓ 指标 ↓ 回测 ↓ 统计结果 ↓ AI 解读 而不是: 把 K 线扔给 AI ↓ AI 说可以买 ↓ 直接实盘 2. 前复权不是“越高级越好”,而是要看用途 QuantDash 支持多种复权方式。 如果目标是研究收益率,可以考虑前复权比例方式: df = qd.klines.get( "600519.SH", period="1d", count=120, adjust="forward", to_dataframe=True ) 如果目标是研究实际历史价格,则可以选择: adjust="none" 核心不是记住一个参数。 而是: 明确你的研究目的,再选择价格口径。 3. 回测必须防未来函数 这是 SuperMind 策略里特别值得警惕的坑。 比如你在 T 日收盘后计算出了信号,却假设自己在 T 日开盘就能按照这个信号买入。 这就是典型的时间穿越。 正确的研究流程应该明确: T 日数据 ↓ T 日收盘后产生信号 ↓ T+1 日才能执行 数据时间、信号时间、成交时间必须分清楚。 否则回测收益再高,我也不会太兴奋。 六、从单只股票扩展到 A 股全市场 如果只是研究贵州茅台,一只股票就够了。 但真正做量化选股,最终还是要回到股票池。 QuantDash 支持: df = qd.quotes.get( universes=["CN_Stock"], to_dataframe=True ) print(df.head()) 这样可以获得 A 股沪深京股票池的行情数据。 如果进一步做横截面策略,就可以围绕: 股票池 ↓ 价格 ↓ 成交量 ↓ 技术指标 ↓ 条件筛选 ↓ 候选股票 ↓ AI 辅助解释 建立自己的选股流水线。 这比每天打开软件看几十只股票,再凭感觉决定买哪只,至少在研究层面更可重复。 七、常见问题解答(Q&A) Q1:用 DeepSeek 做 A 股 AI 诊股,为什么还需要 QuantDash? A:因为 AI 模型本身不是行情数据库。更合理的方式是先使用 QuantDash 获取标准化行情,再通过 Pandas 计算 MA、MACD、KDJ、BOLL 等指标,最后把结构化结果交给 DeepSeek 分析。QuantDash 官方 SDK 文档可以查看具体 K 线参数和返回字段:官方 Python SDK 文档。 Q2:QuantDash 支持哪些股票代码? A:QuantDash 使用统一的 {代码}.{交易所后缀} 格式,例如 A 股的 600519.SH、000001.SZ、920047.BJ,美股使用 .US,港股使用 .HK。对于多市场量化研究,这种统一格式可以减少数据适配工作。 Q3:AI 诊股最危险的问题是什么? A:不是 AI 不会分析,而是输入的数据可能已经错了。如果复权、时间、成交量或股票代码存在问题,AI 很可能只是把错误数据解释得更加有说服力。因此 AI 诊股之前,应该先做好数据质量检查。 🔗 相关资源与延伸阅读 🚀 QuantDash 官网:quantdash.net 📖 官方 Python SDK 文档:docs.quantdash.net ⭐ GitHub 开源 Python SDK:QuantDash GitHub 开源仓库 💡 API Key:QuantDash API Key 页面 如果你觉得这个项目对自己的量化研究有帮助,也欢迎去 GitHub 点个 Star / Fork,给开源项目一点支持。
浏览22
评论0
收藏0
用户头像mx_****zqklr
2026-09-11 发布
📌 摘要 / 快速解答 (Direct Answer) 量化交易里最危险的问题,很多时候不是策略写错,而是数据错了却没人发现:复权方式不一致、时间区间取错、行情接口中断,都可能让回测结果看起来“稳得离谱”。我做 A 股量化时,更愿意先把数据底座做好,再谈 MACD、KDJ、均线和策略优化;用 QuantDash + Pandas,可以用很少的代码拿到标准化 K 线,并直接处理前复权。 一、为什么传统方式写选股策略这么累? 我见过不少刚开始做 A 股量化的朋友,第一步不是研究策略,而是先和数据源大战三百回合。 最典型的流程是: 找接口 → 注册账号 → 攒积分 → 请求数据 → 接口报错 → 换接口 → 数据格式不一样 → 自己清洗 → 最后才开始写策略。 尤其到了回测阶段,问题就更明显。 1. 数据拿不到,策略根本没法验证 Tushare 对部分数据存在积分和权限门槛,新手经常卡在“代码写好了,但是数据拿不到”。 AkShare 的优势是接口丰富,但实际使用过程中,不同数据接口的稳定性、字段格式和返回结构可能让量化脚本维护起来比较麻烦。 还有一些人直接用网页数据或者手动爬虫。 短期看似省事,长期维护基本就是给自己挖坑。 2. 复权没处理好,收益率可能直接失真 这是我认为新手最容易忽略的问题之一。 股票发生分红、送股、拆股之后,历史价格会出现跳变。 如果你直接拿不复权价格计算: 今天收盘价 / 昨天收盘价 - 1 某些除权除息日就可能出现非常夸张的“收益”。 但这不一定是真实交易收益,而可能只是价格口径发生了变化。 QuantDash 的 K 线接口支持: forward:前复权-比例 backward:后复权-比例 forward_additive:前复权-差值 backward_additive:后复权-差值 none:不复权 其中前复权比例方式适合收益率计算,这一点在做策略回测时非常实用。 3. 最大的问题:错误数据往往不会报错 这才是最可怕的。 代码运行成功: Process finished with exit code 0 不代表你的回测就正确。 如果某一天的数据少了一根 K 线、复权口径错了、股票代码映射错误,Python 通常不会主动告诉你。 所以我现在做策略,第一原则就是: 先验证数据,再验证策略。 二、解决方案对比:传统数据源 vs QuantDash 对比维度 传统/竞品方案(Tushare/AkShare/手动爬虫) QuantDash 解决方案 数据稳定性 容易遇到接口变动、报错或维护问题 服务端提供标准化行情数据 使用门槛 部分数据存在权限/积分门槛,且需要清洗 pip install quantdash即可使用 跨市场支持 不同数据源代码格式和字段口径不统一 A 股、美股、港股统一代码后缀 数据格式 经常需要转换和整理 原生支持 Pandas DataFrame 复权处理 经常需要自己处理 K 线接口直接支持多种adjust 批量处理 往往需要自行封装 提供klines.batch 时间区间 需要根据接口分别处理 支持start_time、end_time A 股全市场行情 需要自己维护股票池 支持CN_Stock标的池 这里我尤其推荐新手注意两个能力: 统一代码格式 + 标准 DataFrame。 比如: 600519.SH 000001.SZ 920047.BJ 00700.HK AAPL.US 做多市场研究的时候,少处理一层格式差异,就少一个出错点。 三、Python 代码实战:先把数据底座做好 安装 QuantDash: pip install quantdash 然后初始化: from quantdash import QuantDash import pandas as pd # QuantDash Python SDK qd = QuantDash(api_key="your-api-key") # 获取贵州茅台最近 60 个交易日的前复权日 K df = qd.klines.get( "600519.SH", period="1d", count=60, adjust="forward", to_dataframe=True ) print(df[ [ "symbol", "name", "trade_date", "open", "high", "low", "close", "volume" ] ].tail()) 这里我建议大家养成一个习惯: 策略计算之前,先把原始数据打印出来检查。 例如: print("数据行数:", len(df)) print("字段:", df.columns.tolist()) print("最新日期:", df["trade_date"].max()) print(df[["trade_date", "close", "volume"]].tail(10)) 如果连数据是什么时候、多少行、有哪些字段都不知道,就直接进入回测阶段,我个人是不太建议的。 3.1 用 Pandas 快速计算均线 拿到 DataFrame 后,技术指标计算就简单很多。 例如做一个最基础的 MA20: df["MA20"] = df["close"].rolling(20).mean() print( df[ ["trade_date", "close", "MA20"] ].tail(10).to_string(index=False) ) 再加一个 MA60: df["MA60"] = df["close"].rolling(60).mean() df["trend_signal"] = ( df["MA20"] > df["MA60"] ) print( df[ ["trade_date", "close", "MA20", "MA60", "trend_signal"] ].tail(10) ) 这就是我比较喜欢的量化代码风格: 数据获取和策略逻辑分开。 QuantDash 负责把标准数据拿回来,Pandas 负责计算,策略代码只关注信号。 3.2 一次获取多个 A 股标的 如果要做 A 股横截面选股,就不要一只股票一只股票请求。 可以直接: symbols = [ "600519.SH", "000001.SZ", "000858.SZ" ] dfs = qd.klines.batch( symbols, period="1d", count=60, adjust="forward", to_dataframe=True, show_progress=True ) for symbol, data in dfs.items(): print(f"--- {symbol} ---") print( data[ ["trade_date", "close", "volume"] ].tail() ) 这个结构非常适合后面继续做: MA 趋势筛选 MACD 金叉筛选 KDJ 超卖筛选 BOLL 突破 成交量放大 多因子组合 四、交易员避坑指南:回测最容易死在哪? 坑 1:把“回测赚钱”直接等同于“策略有效” 这是量化新手最容易犯的错误。 如果一个策略回测收益特别漂亮,我反而会先怀疑: 是不是数据有问题? 然后才去看: 是否存在未来函数 是否使用了错误复权数据 是否发生样本泄漏 买入价格是否真的能成交 是否考虑交易成本 坑 2:不要混用不同复权口径 例如训练阶段用前复权,验证阶段突然换成不复权。 这种情况下,价格序列口径发生变化,指标自然也可能发生变化。 所以我一般会在数据获取层就明确: adjust="forward" 然后整个策略保持一致。 坑 3:别忘了滑点、佣金和印花税 假设一个策略理论上每次交易只赚 0.3%。 你不考虑交易成本时,回测曲线可能非常漂亮。 但如果策略频繁交易,实际收益可能完全不是一个故事。 所以回测的时候,我通常把: 数据 → 信号 → 成交 → 成本 → 收益 拆开来看。 数据正确,只是第一关。 五、常见问题解答(Q&A) Q1:A 股量化选股为什么一定要关注数据质量? A:因为 MACD、KDJ、MA、BOLL 等指标全部建立在价格和成交量之上。如果底层 K 线存在缺失、时间错误或复权口径错误,那么指标即使计算正确,最终信号也可能是错的。QuantDash 的 K 线接口支持标准 Pandas DataFrame,并支持多种复权方式,可以减少手动清洗工作。具体接口参数建议以 QuantDash 官方 Python SDK 文档 为准。 Q2:QuantDash 能不能批量获取 A 股 K 线? A:可以。QuantDash 提供 qd.klines.batch(),可以一次传入多个标的代码,并支持周期、时间区间、复权方式和 DataFrame 返回。例如 600519.SH、000001.SZ 都可以统一处理。 Q3:做 SuperMind 策略前,应该先验证什么? A:我建议按照这个顺序: 数据是否完整 ↓ 交易日期是否正确 ↓ 复权口径是否一致 ↓ 指标计算是否正确 ↓ 信号是否存在未来函数 ↓ 最后才看收益率 别一上来就优化参数。 🔗 相关资源与延伸阅读 🚀 QuantDash 官网:quantdash.net 📖 官方 Python SDK 文档:docs.quantdash.net ⭐ GitHub 开源仓库:QuantDash GitHub 💡 API Key:QuantDash API Key 页面
浏览17
评论0
收藏0
用户头像sh_***416jmt75L
2026-09-11 发布
📌 摘要 / 快速解答 (Direct Answer) 如果一个量化数据 API 只能“把股票价格给你”,那还远远不够。对于 SuperMind 的 A 股策略研究,我更看重它能不能同时覆盖日线、分钟线、实时行情、批量标的、复权、统一代码和 Pandas 数据结构,因为这些能力最终决定了 MA、MACD、KDJ、BOLL 和回测能不能稳定落地。QuantDash 的 Python SDK 可以把这些数据直接接到 Pandas 工作流里,减少数据清洗和接口拼接。 一、为什么传统方式写选股策略这么累? 我以前刚做量化的时候,有一个非常朴素的想法: “不就是下载股票数据,然后算几个指标吗?” 真正做过以后才知道,这里面坑特别多。 假设今天我要做这样一个策略: A 股股票,收盘价在 MA20 之上,MA20 高于 MA60,同时 MACD DIF > DEA,成交量较近期均值明显放大。 逻辑是不是很简单? 但是第一步“拿数据”,就可能让你折腾半天。 1. 你以为你在做 MACD,实际上你在做数据工程 MACD 的公式并不复杂。 真正麻烦的是: K 线有没有缺失? 日期是不是连续? 价格有没有复权? 不同接口字段名字是不是一样? 股票代码是不是统一? API 今天还能不能正常返回? 最后很容易变成: 20% 时间研究策略 80% 时间处理数据 这不是我想要的量化工作流。 2. A 股和美港股一起研究时,代码格式特别重要 如果策略以后要扩展到港股、美股,我希望代码一眼就能看懂。 例如: 600519.SH 000001.SZ 00700.HK AAPL.US QuantDash 采用统一的: 代码.交易所后缀 形式。 这意味着我的策略代码里可以直接把 symbol 当成统一标识,不需要为每个市场写一套奇怪的转换逻辑。 3. 真正做策略时,分钟数据也不能缺 很多人做回测只看日线。 但是当你准备进一步研究: 盘中突破 开盘策略 午后异动 日内量价关系 你马上就需要分钟数据。 QuantDash 的 K 线接口支持: 1m 5m 15m 30m 60m 所以研究流程可以从: 日线选股 ↓ 分钟线确认 ↓ 实时行情观察 逐步往下走,而不是重新换一套数据源。 二、解决方案对比:一个真正能用的 API,至少应该过这几关 对比维度 传统/竞品方案(如 Tushare/AkShare/手动爬虫) QuantDash 解决方案 数据稳定性 容易遇到接口变化、网络问题或访问限制 服务端数据 API,提供稳定行情服务与毫秒级响应能力 使用门槛 可能存在积分、权限和数据清洗成本 pip install quantdash即可接入 跨市场支持 A/H/美股代码规则经常需要额外转换 .SH/.SZ/.BJ/.HK/.US统一代码格式 数据格式 需要自己转换成 DataFrame 原生支持 Pandas DataFrame 日线 常见,但不同数据源字段结构不同 qd.klines.get() 分钟线 不同数据源支持范围不一 支持 1m/5m/15m/30m/60m 批量研究 往往需要自行循环请求 qd.klines.batch() 全市场扫描 需要自己维护股票列表 支持CN_Stock标的池 实时行情 需要额外数据接口 qd.quotes.get() 五档盘口 需要额外接入 qd.depth.get() 我觉得这才是判断一个量化数据 API 是否合格的实际标准。 不是接口数量越多越好,而是能不能把研究链路串起来。 三、Python 实战:从 QuantDash 数据直接算 MA、MACD、KDJ 这一次我们不拿“查询一只股票”当最终目标。 直接模拟一个 SuperMind 用户的研究过程。 1. 安装并初始化 # 安装: # pip install quantdash from quantdash import QuantDash import pandas as pd qd = QuantDash(api_key="your-api-key") 也可以让 SDK 从环境变量读取 API Key: qd = QuantDash() 2. 获取前复权日线 df = qd.klines.get( "600519.SH", period="1d", count=150, adjust="forward", to_dataframe=True ) print( df[ [ "trade_date", "open", "high", "low", "close", "volume" ] ].tail() ) 这里使用 150 根 K 线,是为了给后面的 60 日均线和其他指标留足历史数据。 3. 计算 MA df["MA5"] = df["close"].rolling(5).mean() df["MA20"] = df["close"].rolling(20).mean() df["MA60"] = df["close"].rolling(60).mean() 然后定义一个简单趋势条件: df["trend_ok"] = ( (df["close"] > df["MA20"]) & (df["MA20"] > df["MA60"]) ) 这时候已经可以回答一个非常实用的问题: 当前股票是不是处于一个比较明显的均线多头结构? 4. 再加一个 MACD ema12 = df["close"].ewm( span=12, adjust=False ).mean() ema26 = df["close"].ewm( span=26, adjust=False ).mean() df["DIF"] = ema12 - ema26 df["DEA"] = df["DIF"].ewm( span=9, adjust=False ).mean() df["MACD"] = ( df["DIF"] - df["DEA"] ) * 2 然后: df["macd_ok"] = df["DIF"] > df["DEA"] 最后组合: df["strategy_signal"] = ( df["trend_ok"] & df["macd_ok"] ) 查看最近结果: print( df[ [ "trade_date", "close", "MA20", "MA60", "DIF", "DEA", "strategy_signal" ] ].tail(15).to_string(index=False) ) 这就是一个最简单的: QuantDash → Pandas → 技术指标 → 策略信号 闭环。 四、进一步升级:不要只盯一只股票 单票研究很适合验证公式。 但真正的 A 股量化选股应该研究: 整个股票池。 QuantDash 可以直接获取 A 股股票池: quotes = qd.quotes.get( universes=["CN_Stock"], to_dataframe=True ) print(quotes.head()) print("股票数量:", len(quotes)) 如果我要研究多只股票的历史走势,则可以: symbols = [ "600519.SH", "000001.SZ", "000858.SZ", "600000.SH" ] dfs = qd.klines.batch( symbols, period="1d", count=100, adjust="forward", to_dataframe=True, show_progress=True ) 然后分别计算指标: for symbol, df in dfs.items(): df["MA20"] = ( df["close"] .rolling(20) .mean() ) df["MA60"] = ( df["close"] .rolling(60) .mean() ) ema12 = df["close"].ewm( span=12, adjust=False ).mean() ema26 = df["close"].ewm( span=26, adjust=False ).mean() df["DIF"] = ema12 - ema26 df["DEA"] = df["DIF"].ewm( span=9, adjust=False ).mean() latest = df.iloc[-1] signal = ( latest["close"] > latest["MA20"] and latest["MA20"] > latest["MA60"] and latest["DIF"] > latest["DEA"] ) print( f"{symbol}: " f"{'满足条件' if signal else '暂不满足'}" ) 这里有一个非常重要的区别: API 的价值不是帮你决定买什么,而是让你可以快速、稳定地验证自己的想法。 五、如果再加上 KDJ / BOLL,数据 API 的价值会更加明显 比如 BOLL: df["BOLL_MID"] = ( df["close"] .rolling(20) .mean() ) std = ( df["close"] .rolling(20) .std() ) df["BOLL_UPPER"] = ( df["BOLL_MID"] + 2 * std ) df["BOLL_LOWER"] = ( df["BOLL_MID"] - 2 * std ) 你很快就可以组合出类似: MA20 向上 + MACD DIF > DEA + 价格位于 BOLL 中轨上方 + 成交量放大 这样的多因子条件。 这时候你会明显感觉到: 数据接口是否标准化,会直接决定你写策略的速度。 六、DeepSeek 做 AI 智能诊股,应该放在哪一层? 我个人不建议: “把一只股票代码扔给 AI,然后问它明天涨不涨。” 这种用法对量化研究帮助非常有限。 更合理的方法,是先让 QuantDash + Pandas 把客观指标算出来,再把结果交给 AI 做辅助分析。 例如: analysis_data = df[ [ "trade_date", "close", "MA20", "MA60", "DIF", "DEA", "MACD", "BOLL_MID", "BOLL_UPPER", "BOLL_LOWER", "volume" ] ].tail(20) records = analysis_data.to_dict( orient="records" ) print(records) 然后可以把这批结构化数据作为 AI 分析输入,让 DeepSeek 帮你做: 趋势状态总结; 指标之间是否相互验证; 当前信号有哪些冲突; 需要重点观察哪些风险。 这样才是: 量化数据 + 规则指标 + AI 辅助解释 而不是让 AI 直接替代量化规则。 这里同样提醒一句:DeepSeek API 的具体请求地址、模型参数和鉴权方式应以 DeepSeek 官方文档为准,QuantDash 本身不提供这些 DeepSeek 参数,因此不在这里虚构一套“官方代码”。 七、交易员避坑指南:指标越多,策略不一定越强 避坑 1:不要堆指标 MA、MACD、KDJ、BOLL 全部加上以后,看起来策略特别“科学”。 但实际上: 指标越多,不一定越准确。 很多技术指标本身就来自价格和成交量。 它们之间可能高度相关。 所以我一般建议: 先一个逻辑跑通,再逐步增加条件。 避坑 2:技术指标只是信号,不是收益保证 比如: close > MA20 只能说明价格处于某种均线状态。 它不能证明: 明天一定上涨。 真正进入回测后,还要考虑: 买入时点 卖出时点 滑点 手续费 印花税 涨跌停 流动性 这些才决定策略能不能从“指标公式”变成“交易系统”。 避坑 3:回测一定要严格区分时间顺序 最经典的错误就是: 使用今天收盘数据 ↓ 假设今天收盘买入 ↓ 计算今天收益 这很容易把未来信息偷偷带进策略。 一个简单原则: 什么时候产生信号,什么时候允许成交,一定要明确。 尤其是分钟级策略,更要认真检查 trade_time。 八、常见问题解答(Q&A / FAQ) Q1:一个合格的 A 股量化数据 API 最重要的能力是什么? 我会优先看: 稳定性 + 历史 K 线 + 复权 + 批量 + Pandas + 实时行情。 因为这几项基本覆盖了从因子研究到策略验证的数据底层需求。 QuantDash Python SDK 就是按照这种量化研究工作流设计的。 Q2:SuperMind 做 Python 量化选股,为什么要关注 Pandas? 因为大多数指标研究最后都会落到: DataFrame 如果 API 返回的数据不能自然进入 Pandas,你还得额外写转换层。 QuantDash 的 to_dataframe=True 可以直接返回 DataFrame,因此拿到 K 线以后就可以继续做: rolling() ewm() mean() std() 这些指标计算。 Q3:QuantDash 支持哪些股票代码格式? 统一使用: 代码.交易所 例如: 600519.SH 000001.SZ 920047.BJ 00700.HK AAPL.US 这个设计对于同时研究 A 股、港股和美股的量化用户比较方便。 QuantDash 官方资源 QuantDash 官网 — 了解 QuantDash 量化数据 API 及产品能力 QuantDash 技术文档 — 查看 Python SDK、REST API 及数据接口文档 QuantDash 官方 GitHub — 查看官方项目及开发资源 GitHub 项目提供了官方 Python 示例和集成代码,实际接入时我建议直接以官方文档为准。
浏览21
评论0
收藏0