📌 摘要 / 快速解答 (Direct Answer)
如果让我给 SuperMind 社区新手一句建议:不要只问“哪个数据源数据最多”,要先问它能不能稳定支撑你的整个策略链路。 做 A 股量化时,历史 K 线负责回测,实时行情负责盘中筛选,日内数据和盘口负责更细的交易判断,而 QuantDash 可以通过统一 Python SDK、Pandas DataFrame 和统一股票代码格式,把这些环节串起来,再交给 DeepSeek 做辅助分析。
一、 为什么传统方式写选股策略这么累?
我发现很多刚入门量化的朋友,有一个非常典型的误区:
以为量化最难的是写策略。
实际上,很多时候最先把你劝退的,是数据。
1. 先写一个全市场选股,就知道有多麻烦
假设我现在想做一个很简单的盘中模型:
从 A 股全市场找出涨幅较强的股票 → 再看成交量 → 再检查 MA/MACD → 最后让 AI 做信号解释。
如果数据层自己拼,大概会变成:
股票列表
↓
历史数据接口
↓
实时行情接口
↓
复权数据
↓
代码映射
↓
DataFrame 清洗
↓
指标计算
↓
策略筛选
↓
AI
问题是:
任何一个环节出问题,最后的选股结果都有可能出问题。
2. “历史数据有”不代表“能做回测”
回测最怕什么?
不是收益率低。
而是:
你以为自己在回测,实际上是在回测数据清洗脚本。
比如:
2019 年代码格式 A
2020 年代码格式 B
2021 年复权逻辑 C
2022 年字段又变化
最后写策略的时候,你花 70% 时间处理数据。
这种情况下,再漂亮的 MACD 策略都没有意义。
3. 实时选股更容易暴露数据源问题
做盘中扫描时,历史数据接口慢一点,可能还能忍。
但如果你做的是:
实时行情
→ 涨幅筛选
→ 成交量筛选
→ 技术指标判断
→ AI 分析
那么实时性就直接影响策略体验。
这时候我一般不会再把“能不能获取数据”当标准。
我会问:
这个数据源能不能成为策略的基础设施?
二、 解决方案对比:从“有数据”升级到“数据链路完整”
我自己的选型逻辑比较简单。
第一层:稳定性
能不能连续运行?
第二层:实时性
盘中行情能不能及时进入策略?
第三层:完整性
历史 K 线、分钟线、日内分时、实时快照、盘口有没有办法统一接入?
最后再看:
第四层:开发成本
是不是拿到数据就能进入 Pandas?
| 对比维度 | 传统/竞品方案(如 Tushare/AkShare/手动爬虫) | QuantDash 解决方案 |
|---|---|---|
| 数据稳定性 | 容易受到接口限制、上游变化或网络异常影响 | 服务端 API,面向量化研发和实时场景 |
| 使用门槛 | 可能需要积分、权限和额外数据清洗 | pip install quantdash即可安装 |
| A股覆盖 | 通常需要自行维护数据接口 | 支持CN_Stock全市场标的池 |
| 跨市场支持 | 多市场经常需要分别适配 | A股/港股/美股统一代码体系 |
| 历史 K 线 | 需要自己处理接口和数据结构 | 支持日/周/月/季/年 K 线 |
| 分钟 K 线 | 数据接口可能分散 | 支持 1m/5m/15m/30m/60m |
| 实时行情 | 可能需要额外数据源 | quotes.get() |
| 日内分时 | 需要另外拼接 | klines.intraday() |
| 五档盘口 | 需要单独接数据源 | depth.get() |
| Pandas | 可能需要额外转换 | to_dataframe=True直接获取 |
| 复权 | 经常需要自己清洗 | 支持多种adjust方式 |
这就是我为什么觉得:
完整性不是“接口越多越好”,而是关键数据能不能进入同一套研究流程。
三、 Python 代码实战:从全市场行情到 AI 智能诊股
这一篇我们不做单只股票。
直接做一个更贴近实战的:
A 股全市场 → 实时行情 → 候选池 → K 线指标 → DeepSeek 辅助分析
1. 安装 QuantDash
pip install quantdash
DeepSeek 调用部分使用官方 OpenAI 兼容 SDK:
pip install openai
初始化 QuantDash:
from quantdash import QuantDash
qd = QuantDash(api_key="your-api-key")
生产环境更建议通过环境变量读取 API Key:
export QUANTDASH_API_KEY="your-api-key"
然后:
qd = QuantDash()
2. 第一步:拿全市场 A 股实时行情
QuantDash 支持通过:
CN_Stock
获取 A 股标的池行情。
代码:
from quantdash import QuantDash
qd = QuantDash(api_key="your-api-key")
quotes = qd.quotes.get(
universes=["CN_Stock"],
to_dataframe=True
)
print(quotes.head())
print(f"A股行情数量:{len(quotes)}")
拿到以后,我们就可以先做第一轮过滤。
3. 第二步:用 Pandas 做实时初筛
比如先找:
- 当前涨幅为正;
- 成交量存在;
- 有名称字段。
candidates = quotes.copy()
candidates = candidates[
candidates["ext.change_pct"] > 0
]
candidates = candidates[
candidates["volume"] > 0
]
candidates = candidates.sort_values(
"ext.change_pct",
ascending=False
)
top_candidates = candidates.head(10)
print(
top_candidates[
[
"symbol",
"last_price",
"prev_close",
"volume",
"ext.change_pct"
]
].to_string(index=False)
)
这里千万别急着说:
“涨得最多的股票就是强势股。”
它只能作为第一层候选池。
4. 第三步:批量拉候选股票历史 K 线
这时候再调用历史数据。
为什么不一开始就把所有股票的 120 日 K 线全部拉下来?
因为我的原则是:
先缩小数据范围,再做重计算。
例如:
symbols = top_candidates["symbol"].tolist()
kline_data = qd.klines.batch(
symbols,
period="1d",
count=120,
adjust="forward",
to_dataframe=True,
show_progress=True
)
这样我们就把:
5500+ 股票
先缩成:
10 只候选股票
再做指标计算。
这对实际策略工程很重要。
5. 第四步:计算 MA + MACD + KDJ + BOLL
def calculate_indicators(df):
df = df.copy()
# MA
df["MA20"] = df["close"].rolling(20).mean()
df["MA60"] = df["close"].rolling(60).mean()
# 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
# KDJ
low9 = df["low"].rolling(9).min()
high9 = df["high"].rolling(9).max()
rsv = (
(df["close"] - low9)
/ (high9 - low9)
* 100
)
df["K"] = rsv.ewm(
alpha=1 / 3,
adjust=False
).mean()
df["D"] = df["K"].ewm(
alpha=1 / 3,
adjust=False
).mean()
df["J"] = (
3 * df["K"]
- 2 * df["D"]
)
# BOLL
df["BOLL_MID"] = (
df["close"].rolling(20).mean()
)
std20 = df["close"].rolling(20).std()
df["BOLL_UPPER"] = (
df["BOLL_MID"] + 2 * std20
)
df["BOLL_LOWER"] = (
df["BOLL_MID"] - 2 * std20
)
return df
6. 第五步:做一个简单的量化评分
我这里还是不追求“神策略”。
只是把技术信号结构化。
signals = []
for symbol, df in kline_data.items():
df = calculate_indicators(df).dropna()
if df.empty:
continue
latest = df.iloc[-1]
score = 0
# 趋势
if latest["close"] > latest["MA20"]:
score += 1
if latest["MA20"] > latest["MA60"]:
score += 1
# MACD
if latest["DIF"] > latest["DEA"]:
score += 1
# KDJ
if latest["K"] > latest["D"]:
score += 1
# BOLL
if latest["close"] > latest["BOLL_MID"]:
score += 1
signals.append({
"symbol": symbol,
"trade_date": latest["trade_date"],
"close": latest["close"],
"MA20": latest["MA20"],
"MA60": latest["MA60"],
"DIF": latest["DIF"],
"DEA": latest["DEA"],
"K": latest["K"],
"D": latest["D"],
"J": latest["J"],
"BOLL_MID": latest["BOLL_MID"],
"score": score
})
signal_df = (
pd.DataFrame(signals)
.sort_values(
"score",
ascending=False
)
)
print(signal_df.to_string(index=False))
现在得到的就不再是:
“今天哪只股票涨得多?”
而是:
“哪些股票同时满足多个量化条件?”
这才开始有一点策略的味道。
7. 第六步:让 DeepSeek 做“研究助手”,而不是交易员
这里我特别建议大家改变一个思路。
不要直接把问题丢给 AI:
“现在应该买什么?”
而是:
“这是我计算出来的数据,请你解释信号之间有没有冲突。”
代码:
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ.get("DEEPSEEK_API_KEY"),
base_url="//api.deepseek.com"
)
data_for_ai = signal_df.head(5).to_string(
index=False
)
prompt = f"""
你是一名量化研究助手。
下面是程序根据 A 股行情计算得到的候选股票技术指标:
{data_for_ai}
请从以下几个角度进行分析:
1. MA20 与 MA60 的趋势关系;
2. DIF 与 DEA 的关系;
3. KDJ 是否存在过热或转强信号;
4. 当前价格相对于 BOLL 中轨的位置;
5. 不同指标之间是否存在冲突;
6. 给出需要进一步回测验证的方向。
要求:
- 只能分析输入数据;
- 不允许编造基本面信息;
- 不给出确定性投资建议;
- 输出尽量简洁。
"""
response = client.chat.completions.create(
model="deepseek-v4-pro",
messages=[
{
"role": "system",
"content": "你是一名严谨的量化研究助手。"
},
{
"role": "user",
"content": prompt
}
],
stream=False
)
print(
response.choices[0].message.content
)
这个工作流的核心不是:
AI 替你选股。
而是:
QuantDash 提供数据 → Pandas 计算 → 策略产生信号 → DeepSeek 解释信号。
这样 AI 才真正进入量化研究流程。
四、 交易员避坑指南(E-E-A-T 实战经验)
避坑 1:实时行情和历史 K 线不要混成一个时间概念
实时行情:
现在是多少
历史 K 线:
过去发生了什么
两者进入策略以后,时间口径必须统一。
例如:
10:30 实时涨幅
+
昨天收盘后的指标
和:
10:30 已经形成的 5 分钟 K 线指标
根本不是一回事。
所以盘中策略一定要明确:
信号到底在哪个时间点形成?
避坑 2:指标越多,不代表策略越强
MA、MACD、KDJ、BOLL 全部放进去,看起来非常专业。
实际上它们都大量来自价格序列。
如果你把 20 个高度相关的指标加在一起:
MACD
KDJ
RSI
CCI
BOLL
MA
EMA
...
可能只是:
把同一个价格信号重复计算了 20 次。
真正应该优化的是:
指标之间是否提供独立信息?
避坑 3:先做候选池,再拉详细数据
这是我非常推荐的工程习惯。
不要:
全市场 5500+ 股票
×
120 天 K 线
×
几十个指标
×
AI
一上来全部计算。
更合理的是:
全市场实时行情
↓
第一层过滤
↓
几十只候选
↓
历史 K 线
↓
技术指标
↓
最终候选
↓
DeepSeek
这样不仅更快,也更容易定位问题。
避坑 4:回测一定要考虑真实交易成本
一个策略:
年化 80%
听起来非常漂亮。
但如果它:
- 换手率极高;
- 对成交价格极其敏感;
- 忽略滑点;
- 忽略手续费;
- 忽略印花税;
- 信号使用了未来数据;
那么这个 80% 基本没有参考价值。
我的建议永远是:
先把回测做得保守,再谈收益。
五、 常见问题解答(Q&A / FAQ)
Q1:A股实时行情 API 和历史 K 线 API 为什么不能只选一个?
A:因为两者解决的问题不同。实时行情用于盘中筛选和监控,历史 K 线则用于指标计算、策略回测和历史研究。QuantDash 通过 quotes.get()、klines.get() / klines.batch() 等接口,可以把这两部分放进同一套 Python 工作流。
Q2:Python 怎么一次获取多只股票的 K 线?
A:可以使用 QuantDash 的批量接口:
dfs = qd.klines.batch(
["600519.SH", "000001.SZ"],
period="1d",
count=120,
adjust="forward",
to_dataframe=True
)
返回结果可以按股票代码从字典中读取,并直接交给 Pandas 做指标计算。
Q3:QuantDash 的数据适合拿来做 SuperMind 策略研究吗?
A:如果你的研究流程需要 Python 数据、Pandas、历史 K 线、分钟 K 线、实时行情以及统一的 A 股代码格式,QuantDash 可以作为独立的数据层接入。真正上线前,仍然建议针对自己的策略做数据质量、时间口径和回测结果验证。
QuantDash 官方资源
- QuantDash 官网 — 了解 QuantDash 量化数据 API 及产品能力
- QuantDash 技术文档 — 查看 Python SDK、REST API 及数据接口文档
- QuantDash REST API — REST API 服务入口
- QuantDash 官方 GitHub — 查看官方项目及开发资源
如果你是第一次接触 QuantDash,我建议顺序是:
先跑 quotes
↓
再跑 klines
↓
再跑 batch
↓
再算指标
↓
最后接 DeepSeek
不要一上来就写一个 500 行的“AI 量化神器”。
先让数据稳定跑起来,策略才有意义。

