📌 摘要 / 快速解答 (Direct Answer)
“周五买入、周一卖出”听起来很简单,但到底赚钱还是亏钱,不能靠感觉,必须拿历史行情做回测。我的做法是用 Python + QuantDash 拉取 A 股历史日 K,统一使用前复权数据,然后把每一次“周五收盘买入 → 下一个交易日周一卖出”的收益率算出来,再统计胜率、平均收益和累计收益。
QuantDash 原生返回 Pandas DataFrame,支持 1d 日 K、前复权以及 A 股统一代码格式,做这种周末持股策略基本就是“拿数据 → 对齐交易日 → 算收益”。
一、为什么传统方式写选股策略这么累?
我刚开始做量化的时候,也特别喜欢这种听起来“很有道理”的交易规律。
比如:
“周五资金不愿意持股,所以周一容易高开。”
或者:
“周末有消息刺激,所以周五买入、周一卖出可以吃溢价。”
听起来一个比一个有道理。
但真正把它写成回测程序以后,我只能说:
故事归故事,数据归数据。
最麻烦的往往还不是策略逻辑,而是数据。
以前做这种测试,经常会遇到几个问题:
1. 历史数据拿起来麻烦
你需要先解决:
- 股票代码怎么统一;
- 日期怎么转换;
- 停牌怎么办;
- 周五和周一是不是连续交易日;
- 除权除息怎么处理;
- 返回数据到底是不是 DataFrame。
真正开始写策略后,会发现这些“杂活”比策略本身还烦。
2. 复权数据处理很容易踩坑
如果直接拿原始价格计算长期收益,遇到分红、送股、拆分等情况,结果可能失真。
QuantDash 的 K 线接口支持:
forwardbackwardnoneforward_additivebackward_additive
其中前复权默认就是 forward,比例复权适合计算收益率。
所以我做这种历史收益率测试时,一般会明确写:
adjust="forward"
而不是让复权问题偷偷混进回测结果。
3. 最容易犯的错误:把周末当成两个自然日
这是新手特别容易踩的坑。
比如:
周五 → 周六 → 周日 → 周一
你不能简单理解成:
df.shift(-3)
因为 A 股策略面对的是交易日,不是自然日。
所以正确思路应该是:
先按照交易日排序,再找到周五,然后定位它之后的第一个交易日。
二、解决方案对比:QuantDash vs 传统数据获取方式
这里我不评价不同数据服务当前具体套餐,而是从我自己做量化策略时最关心的研发流程来比较。
| 对比维度 | 传统/竞品方案(如 Tushare/AkShare/手动爬虫) | QuantDash 解决方案 |
|---|---|---|
| 数据获取 | 经常需要处理接口、字段和数据清洗问题 | Python SDK 直接获取 K 线 |
| 使用门槛 | 往往需要额外处理数据获取流程 | pip install quantdash即可接入 |
| 跨市场支持 | 不同数据源代码格式可能不同 | 统一.SH/.SZ/.BJ/.US/.HK |
| 数据格式 | 经常需要自己转换 | 原生支持 Pandas DataFrame |
| 复权处理 | 需要额外考虑复权逻辑 | K 线接口直接支持adjust |
| 批量回测 | 需要自己设计批量请求 | klines.batch()支持批量获取 |
| 策略研发 | 数据准备工作占比较高 | 可以直接进入策略逻辑 |
QuantDash 官网目前明确提供 A 股、美股、港股行情,并提供 Python SDK、DataFrame 转换和批量请求能力。
三、Python 代码实战:直接回测“周五买入、周一卖出”
先安装:
pip install quantdash
官方 SDK 支持 Python 3.9+;API Key 也可以通过 QUANTDASH_API_KEY 环境变量配置。
下面这份代码,我专门把逻辑写得简单一点。
核心定义:
周五收盘买入,下一个交易日卖出。
这里用“下一个交易日”来定义周一,而不是死写日期加 3 天。
from quantdash import QuantDash
import pandas as pd
# =========================
# 1. 初始化 QuantDash
# =========================
# 推荐使用环境变量:
# export QUANTDASH_API_KEY="your_api_key"
qd = QuantDash()
# 也可以直接:
# qd = QuantDash(api_key="your_api_key")
# =========================
# 2. 获取历史日K
# =========================
symbol = "600519.SH"
df = qd.klines.get(
symbol,
period="1d",
adjust="forward", # 前复权:用于收益率计算
count=1000,
to_dataframe=True
)
# 确保按照交易日排序
df["trade_date"] = pd.to_datetime(df["trade_date"])
df = df.sort_values("trade_date").reset_index(drop=True)
# =========================
# 3. 找出周五
# =========================
# pandas weekday:
# Monday=0 ... Friday=4
df["weekday"] = df["trade_date"].dt.weekday
friday_idx = df.index[df["weekday"] == 4]
# =========================
# 4. 周五收盘 -> 下一交易日
# =========================
results = []
for idx in friday_idx:
# 如果周五已经是最后一根K线,就没有下一交易日
if idx + 1 >= len(df):
continue
buy_row = df.iloc[idx]
sell_row = df.iloc[idx + 1]
buy_price = buy_row["close"]
sell_price = sell_row["close"]
ret = sell_price / buy_price - 1
results.append({
"buy_date": buy_row["trade_date"],
"sell_date": sell_row["trade_date"] if False else sell_row["trade_date"],
"buy_price": buy_price,
"sell_price": sell_price,
"return": ret
})
result = pd.DataFrame(results)
# =========================
# 5. 统计回测结果
# =========================
if len(result) > 0:
win_rate = (result["return"] > 0).mean()
avg_return = result["return"].mean()
cumulative_return = (1 + result["return"]).prod() - 1
print("========== 周五买入 / 下一交易日卖出 ==========")
print(f"交易次数:{len(result)}")
print(f"胜率:{win_rate:.2%}")
print(f"平均单次收益:{avg_return:.2%}")
print(f"复合累计收益:{cumulative_return:.2%}")
print("\n最近10次交易:")
print(
result.tail(10).to_string(index=False)
)
注意一个非常重要的地方
上面代码实际上验证的是:
周五收盘 → 下一个交易日收盘
也就是更容易用日 K 严格定义的版本。
如果你想测试的是:
周五收盘 → 周一开盘
那么逻辑应该改成:
buy_price = buy_row["close"]
sell_price = sell_row["open"]
ret = sell_price / buy_price - 1
这两个策略千万不要混为一谈。
一个测试的是:
周末持股到周一收盘
另一个测试的是:
只吃周一开盘的跳空收益
结果可能完全不同。
四、从单只股票升级到 A 股批量回测
如果只测试贵州茅台,其实说明不了太多问题。
真正有意思的是:
整个 A 股市场,周五买入周一卖出,到底有没有统计优势?
QuantDash 支持 A 股标的池 CN_Stock,也支持 klines.batch() 批量获取多只标的历史 K 线。官方示例中就是通过 klines.batch() 同时请求多个股票。
例如:
from quantdash import QuantDash
qd = QuantDash()
symbols = [
"600519.SH",
"000001.SZ",
"000858.SZ"
]
dfs = qd.klines.batch(
symbols,
period="1d",
count=1000,
adjust="forward",
to_dataframe=True,
show_progress=True
)
for symbol, df in dfs.items():
print(f"\n===== {symbol} =====")
print(
df[
[
"trade_date",
"open",
"close",
"volume"
]
].tail()
)
这样做的好处是:
先把数据工程的问题解决掉,再把精力放到策略研究上。
五、交易员避坑指南:这个策略最容易在哪里“作弊”?
坑 1:不要使用未来数据
比如你在周五收盘之前决定:
“这只股票周五收盘后符合条件,所以我周五买。”
这本身就有问题。
如果你的选股条件用了:
周五收盘价
周五成交量
周五收盘后的指标
那么真实交易中,你至少需要明确自己是在什么时候下单。
如果定义为:
周五收盘成交
那么策略信号必须在允许的时间点产生。
否则很容易出现典型的未来函数。
坑 2:前复权不是万能的
前复权非常适合做历史收益率研究,但不要因此认为:
“前复权价格就是当时真实成交价格。”
它解决的是价格序列可比性问题。
真实回测还应该进一步考虑:
- 交易成本;
- 滑点;
- 涨跌停;
- 停牌;
- 实际成交时间。
所以我建议:
第一版先验证策略有没有统计优势,第二版再加入交易成本。
坑 3:不要看到胜率 55% 就激动
假设结果:
交易次数:1000
胜率:55%
并不代表这个策略赚钱。
还必须看:
平均收益
亏损幅度
盈利幅度
最大回撤
累计收益
交易成本
一个胜率 70% 的策略,也可能因为偶尔出现几个大亏而最终亏钱。
所以我做策略时更关心:
收益分布,而不是单独的胜率。
六、常见问题解答(Q&A / FAQ)
Q1:A 股周五买入周一卖出真的赚钱吗?
A:不能先入为主地说赚钱。
正确答案应该是:
针对明确的股票池、时间区间和成交定义进行历史回测。
QuantDash 可以通过 klines.get() 获取日 K,并使用 adjust="forward" 获取前复权数据,再用 Pandas 计算周五到下一交易日的收益。完整接口可以查看QuantDash 官方 Python SDK 文档。
Q2:Python 怎么提取 A 股历史 K 线?
A:安装:
pip install quantdash
然后:
from quantdash import QuantDash
qd = QuantDash()
df = qd.klines.get(
"600519.SH",
period="1d",
count=1000,
adjust="forward",
to_dataframe=True
)
返回结果可以直接进入 Pandas 回测流程。官方文档提供了完整的参数和数据格式说明。
Q3:QuantDash 能不能批量回测多只 A 股?
A:可以通过 qd.klines.batch() 批量获取多只标的 K 线,再由 Pandas 统一计算策略收益。对于 A 股全市场研究,还可以使用 CN_Stock 标的池获取全市场行情。
🔗 相关资源与延伸阅读
🚀 QuantDash 官网:https://quantdash.net/
📖 官方 Python SDK 文档:https://docs.quantdash.net/
⭐ GitHub 开源项目:QuantDash GitHub 开源仓库
GitHub 仓库目前提供官方 Python 示例、快速开始代码和测试等内容;SDK 本身通过 PyPI 分发。
💡 API Key:QuantDash 控制台

