A股量化实战:用道法术器势构建系统化交易框架
量化交易这几年在A股市场已经从“少数人的黑科技”变成了“多数人的必修课”。行情软件里自带的各种策略模型、社群天天讨论的因子与回测、私募量化产品的规模爆发都说明这件事不再是门槛极高的象牙塔内容。但很多人学量化都会遇到同一个困境资料越看越多指标越学越杂策略回测了一堆实盘一上就懵。问题不出在工具不够新也不在代码不够快而是脑子里缺一个能把所有碎片串起来的认知框架。我习惯用五个字来搭这个框架——道、法、术、器、势。把这个框架套在量化交易上从理念到代码、从策略到执行、从单笔交易到整个账户管理一条线全捋清楚。这篇文章就把这套框架怎么用在A股量化的具体方法完整拆开讲适合刚接触量化但不知道从哪下手的新手也适合已经有策略但总在回测和实盘之间反复“翻车”的进阶玩家。1. 为什么是“道法术器势”——先把认知框架立起来很多人在量化交易上花了大量时间却始终在原地打转。今天学一个MACD金叉策略明天研究布林带突破后天又开始看机器学习。每一个单独拿出来好像都有道理但它们之间是什么关系、各自处在什么位置、怎么组合成一个完整系统很少有人能说清楚。这就是“只见树木不见森林”。“道法术器势”这个框架恰好能把量化的所有知识点归位。它不是一个技术概念而是一套分层认知模型让你清楚自己现在学的东西到底属于哪个层面下一步应该往哪走。1.1 五层结构各自对应什么道交易的底层认知与价值观。你相信市场是什么——是随机漫步还是可预测的你赚的是谁的钱——是趋势的钱、波动的钱、还是定价错误的钱这决定了你整个量化体系的方向。法在“道”之下的策略规则与交易逻辑。比如“趋势跟踪”是一种“法”它把“市场有趋势”这个“道”层面的认知转成一套可执行的规则体系。术具体的入场信号、出场条件、仓位管理技巧。比如用双均线金叉死叉作为信号用ATR动态止盈止损这些具体操作就是“术”。器承载策略的工具与载体。数据源、回测框架、交易接口、服务器、下单软件都属于“器”。势宏观环境与市场生态的把握。市场整体处于牛市还是熊市、监管政策导向、行业轮动节奏这些是“势”。量化系统再精妙逆着“势”也很难做出正收益。1.2 为什么大多数人学量化学乱了绝大多数人学量化是从“术”和“器”入手的。这很正常因为看一眼K线图、写一段Python代码马上就能看到反馈正反馈来得快。但问题在于没有“道”和“法”兜底学再多的“术”也只是一盘散沙。我见过有人把几十个技术指标堆在同一个策略里回测曲线漂亮得不行实盘一跑就连续亏损。原因就是他的“术”没有统一在“法”之下指标之间的逻辑互相打架有的做趋势、有的做反转信号互相抵消。也见过有人用很贵的量化终端拉数据、配了最好的服务器但策略本身连“赚谁的钱”都没想清楚器越强大亏得越快。这个框架的真正价值在于它强迫你按顺序思考。先想清楚“道”再定“法”再找“术”再选“器”最后看“势”。顺序不能乱层级不能跳。就像盖房子道是地基、法是承重结构、术是装修方案、器是施工工具、势是施工季节。地基没打牢就去选窗帘颜色没有任何意义。2. “道”与“法”的落地——先解决认知与策略方向“道”和“法”听起来玄但落到A股量化里其实非常具体。这个层面想不清楚后面全白搭。2.1 先回答最核心的三个问题第一个问题你相信A股市场是有效的吗如果相信市场有效那一切技术分析都没有意义你能做的只有被动跟踪指数拿贝塔收益。如果不相信市场有效那你就需要寻找市场定价错误的时刻赚阿尔法收益。第二个问题你赚的是谁的钱这个问题的答案直接决定你的策略类型。做趋势跟踪赚的是市场参与者的惯性钱做统计套利赚的是价格偏离回归的钱做事件驱动赚的是信息反应滞后的钱。每一种钱的来源不同对应的持仓周期、风险特征完全不同。第三个问题你能承受多大的回撤这个问题大多数人是在实盘亏了20%之后才开始认真想的但那时候已经被动了。量化交易和主观交易一样回撤是必然的不存在没有回撤的策略。你的资金属性、心态承受力直接决定你能用什么杠杆、做什么频率。2.2 从“道”推导出“法”的具体路径把上面三个问题回答清楚了“法”的框架自然就出来了。我举个例子假设你的答案是A股市场存在明显的行为金融偏差道层面的判断市场不完全有效你想赚趋势惯性延续的钱法层面的方向趋势跟踪你最大能承受30%的回撤风险约束。那么你的“法”就可以定成以日线级别趋势跟踪为主不参与震荡市通过严格止损控制大回撤通过分散持仓平滑净值波动。定了这个“法”后面所有的“术”和“器”都有了选择标准。选任何指标、任何工具都要先问一句它是否符合我的“法”如果不符合再好用也不碰。2.3 一个完整的策略定义模板实践中有个很好用的模板可以把“法”落实到纸上作为策略开发的需求文档。每次开发新策略前先把这个模板填完再开始写代码策略哲学一句话说明你相信什么道的落点收益来源明确说明你赚的是什么钱持仓周期日内、数日、数月还是更长交易标的池全市场、沪深300成分股、某个行业板块信号生成逻辑核心规则描述对应到“术”的框架风控约束最大回撤容忍度、单笔最大亏损、仓位上限失效条件什么情况下这个策略会失去优势这个模板看起来简单但填完之后你会发现策略的方向已经非常清晰了后面写代码、调参数都有据可依不会再东一榔头西一棒子。3. “术”与“器”的配合——从策略想法到可执行代码“法”定好了接下来就是把规则变成信号、把信号变成代码、把代码跑起来。这是大多数人对量化的直接印象也是工作量最集中的部分。3.1 “术”的层面把规则拆成可量化的信号“术”的核心工作是把模糊的规则描述拆成计算机能执行的精确信号。举个完整例子“法”定了趋势跟踪那么“术”层面就需要定义怎么判断趋势存在趋势反转怎么识别入场后怎么设置止损止盈仓位分配怎么确定以“怎么判断趋势存在”为例可以用最简单的双均线系统短期均线上穿长期均线视为上升趋势确认下穿视为趋势结束。这是最朴素但同时也是最经典的趋势跟踪“术”之一。但在A股市场上直接用裸的双均线会有个问题单边上涨时均线信号一直有效但在横盘震荡时均线会频繁交叉产生大量假信号。所以“术”的层面还需要加过滤条件。常见做法有加一个趋势强度过滤比如DIFF大于某阈值才开仓加一个市场环境过滤比如大盘指数在年线上方才允许做多加一个时间过滤比如只在特定时段开仓这些过滤条件本质上是在提高信号的胜率代价是放弃部分盈利机会。这是“术”层面的经典取舍胜率和盈亏比、灵敏度与稳定性的平衡。3.2 “器”的层面回测框架与数据细节“器”的选择直接决定你的开发效率和结果可信度。在A股做量化“器”主要包含几个层次数据源行情数据、财务数据、资金流数据。数据频率、复权方式、字段完整性都直接影响策略信号计算。尤其要注意的是A股历史行情存在大量停牌、涨跌停、除权除息情况如果数据清洗不干净回测结果会和实盘差异巨大。回测框架现成的框架很多各有侧重。有的适合超高频回测有的适合日线级别策略研究。对绝大多数个人投资者和中小团队而言一个支持日线级别、有滑点和手续费模拟、能快速迭代策略逻辑的工具就足够了。交易接口实盘阶段需要对接券商的交易接口实现程序化下单。不同券商提供的接口能力差异很大有的只支持实盘有的有仿真环境可以先跑模拟。仿真环境非常重要强烈建议实盘前先跑一段时间的仿真交易。3.3 一个双均线策略的完整Python实现多说无益给一份可以直接跑通的代码。这是最基础的日线双均线趋势策略用Python实现包含数据获取、指标计算、回测逻辑和结果统计。import pandas as pd import numpy as np # 模拟一段行情数据实际使用时应从数据源拉取 np.random.seed(42) dates pd.date_range(2020-01-01, periods500, freqD) price 100 np.cumsum(np.random.randn(500) * 0.5) df pd.DataFrame({close: price}, indexdates) # 技术指标计算快慢均线 df[ma_fast] df[close].rolling(window10).mean() df[ma_slow] df[close].rolling(window30).mean() # 信号快线上穿慢线为买入下穿为卖出 df[signal] 0 df.loc[df[ma_fast] df[ma_slow], signal] 1 # 用diff识别金叉死叉的瞬间 df[position] df[signal].diff().fillna(0) # 交易模拟记录每一笔交易的进出场 entry_price None entry_date None trades [] for i in range(len(df)): if df[position].iloc[i] 1 and entry_price is None: entry_price df[close].iloc[i] entry_date df.index[i] elif df[position].iloc[i] -1 and entry_price is not None: exit_price df[close].iloc[i] trades.append({ entry_date: entry_date, exit_date: df.index[i], pnl_pct: (exit_price - entry_price) / entry_price * 100 }) entry_price None # 统计结果 if trades: trades_df pd.DataFrame(trades) win_rate (trades_df[pnl_pct] 0).mean() avg_win trades_df.loc[trades_df[pnl_pct] 0, pnl_pct].mean() avg_loss trades_df.loc[trades_df[pnl_pct] 0, pnl_pct].mean() total_pnl trades_df[pnl_pct].sum() print(f交易次数: {len(trades_df)}) print(f胜率: {win_rate:.2%}) print(f平均盈利: {avg_win:.2f}%) print(f平均亏损: {avg_loss:.2f}%) print(f累计收益率: {total_pnl:.2f}%)代码逻辑很简单但有几个细节值得注意第一信号用diff()来捕捉交叉瞬间而不是直接用signal的值。如果用signal1作为持仓信号会把“持有中”误判成“开仓信号”。第二这里没有处理涨停无法买入和跌停无法卖出的情况。实盘中这两个因素对趋势策略的影响非常大。涨停时你想买买不进跌停时你想卖卖不出直接导致策略表现的恶化。这个问题会在后面的常见问题里展开。第三这里也没有加交易成本。A股的成本包括佣金、印花税和滑点对中高频策略的影响尤其明显。回测时一定要把成本算进去否则你看到的利润是假的。3.4 回测与实盘之间必须跨过的鸿沟很多新手第一次跑通回测看到漂亮的收益曲线就开始兴奋地规划怎么赚钱了。这一步往往就是亏钱的开始。回测到实盘的鸿沟主要来自几个方面幸存者偏差回测用的股票池包含了现在已经上市的公司但过去十年它退市的股票不会在现在的股票池里。如果你不做处理回测会系统性高估收益。前视偏差未来函数是另一个常见陷阱。比如用当天的收盘价计算指标却在同一天收盘前就买入这在逻辑上是不可能的因为收盘价还没出来。撮合差异回测时假设信号出现就能以收盘价成交但实盘中信号出现的那一刻市场已经在动了你实际成交的价格往往比信号价格差这就是滑点。滑点和冲击成本对大盘股而言滑点可能可以忽略但中小盘股、流动性差的标的滑点可能直接吞掉策略的全部收益。要解决这些问题实操中最有效的办法是留出一段数据做“样本外测试”再激进一点可以做“前向测试”——用历史数据训练策略然后在一个全新的时间段里模拟交易全程不做任何调整看看策略能不能活着走出来。4. “势”的判断——A股市场的特殊性与应对策略如果说“道法术器”解决的是“这套系统怎么运作”的问题那么“势”解决的问题是“这套系统现在适不适合运作”。很多策略本身没毛病亏钱亏在逆势上场。4.1 A股的“势”到底特殊在哪里A股市场有几个非常鲜明的生态特征直接决定了量化策略的设计逻辑散户占比高A股的换手率长期高于成熟市场个人投资者在交易量中占比很大。这带来两个后果一是市场容易出现情绪化波动趋势一旦形成往往会走过头二是存在明显的“反转效应”短期涨多了容易回调。涨跌停制度涨跌停板限制了单日价格波动的上限这导致在极端行情下你没法按预期价格成交。趋势策略在连续涨停时买不进、连续跌停时卖不出流动性瞬间蒸发。T1交易制度当天买入的股票当天不能卖出。这意味着日内策略的入场和出场逻辑完全不同于T0市场你至少需要跨日持仓才能完成一次交易闭环。政策与事件敏感性重大政策、行业监管变化、突发新闻都会在短时间内极大冲击市场结构。这在回测里很难精确模拟但对实盘的影响是巨大的。4.2 怎么判断“势”并调整量化系统的节奏判断“势”不能靠感觉还是要有可量化的指标。宏观层面可以观察货币环境、市场整体估值分位、成交量能变化微观层面可以观察涨停家数、连板高度、成交额集中度等情绪指标。但比指标更重要的是一个心态准备量化系统不是任何时候都应该满仓运行的。市场最差的时候最好的操作是降低策略交易频率、缩小单笔仓位甚至空仓等待。这不是对策略的否定而是对“势”的尊重。具体到仓位上可以采用“动态暴露”的思路当“势”的指标转弱时自动降低整体仓位系数比如原本用一倍杠杆现在降到0.5倍当指标转强时再恢复满配。这样做也许会让收益曲线不那么“激进”但能显著改善回撤控制和持有体验系统能活得久远比跑得快重要。4.3 风险控制是“势”的一部分风险控制绝对不是选一个止损参数那么简单。完整的风险控制应该横跨多个时间尺度和多个资产维度单笔层面每笔交易最大亏损不能超过本金的某个比例策略层面同一个策略的总暴露不能无限制放大组合层面不同策略之间的相关性不能太高否则集中回撤会出现账户层面总回撤达到一定程度必须强制降杠杆把这些规则写进代码由系统自动执行比任何时候都靠“手动止损”靠谱得多。5. 常见问题与排查技巧实录最后一个部分把我在实操中遇到过的、也看别人踩过的高频问题整理成清单。这些问题在文档里通常找不到完整答案但实盘中随时可能碰到。5.1 回测完美但实盘亏损一定是什么环节出错了这是出现频率最高的一个问题。如果你是第一次遇到先别急着怀疑策略逻辑先按顺序排查数据是否对得上实盘的行情数据是实时的回测用的历史数据是复权后的两者的价格基准可能完全不同。尤其注意除权除息日前复权数据在除权当天会跳变。成本是否算够了用万2.5佣金、千1印花税、滑点按0.1%估算这是底线值不是乐观值。然后重新跑一遍回测看看收益还剩多少。信号延迟是否模拟了程序计算出信号到实际下单之间有时延如果用分钟级别的微盘交易这个时延会显著影响成交价格。实时行情里的停牌和涨跌停回测时要明确记录哪些日子标的无法交易实盘中这些情况会造成无法成交要统计这种“滑点”的亏损幅度。如果以上都查过了还是亏那就要冷静问一个问题这个策略在逻辑上是不是只是过拟合了历史数据几个参数的组合恰好碰到了一波大行情换一个时间段就失效了。5.2 过拟合怎么识别和规避过拟合是量化策略开发里最隐蔽的坑。识别方法有几个信号同一套参数在2005-2015年有效在2016-2025年失效参数微调一点结果剧烈变化。比如周期从10改成11胜率从55%变成42%策略里有超过5个以上自由参数且每个参数都在优化时被调到“完美值”规避方法核心思路是“简单即有效”。策略逻辑越简单参数越少过拟合的风险就越低。一个只有1-2个参数、逻辑清晰的策略即使实盘表现稳定度低一点也比一个20个参数、回测完美的一堆代码可靠得多。5.3 代码层面有什么常见的“隐形刺客”写策略代码时很多细节会毁掉整个策略结果这里列几个印象最深的数组越界和未来函数计算指标时用到了未来数据而不自知。检查方法是把预测结果和真实结果对比如果预测准确率高到不合理先查代码里是不是用了未来数据循环剪不断理还乱写循环计算指标效率极低学会用rolling和shift这些向量化操作不仅速度快而且不容易出错浮点精度坑价格比较时用了判断会因为浮点误差漏掉交易信号应该用abs(a-b) 1e-8这种写法5.4 实盘跑着跑着突然不交易了怎么办程序化交易最怕的是系统“静默罢工”——没有报错、没有日志、但也没有交易。排查要点先查数据源是否还活着。数据断流是最常见的原因断流后策略没有新信号自然不交易再看行情时间是否正确。节假日前后、行情数据时间戳错乱会导致信号判断失效查服务器时间与交易所时间是否校准。时间误差超过几十毫秒对限价单的影响都很明显确认是否有异常单置位。交易接口有“熔断”设置当连续亏损达到阈值后会自动停止下单这个是保护的机制但需要定期检查5.5 实盘和模拟差异巨大先检查撮合逻辑程序化交易最怕的是模拟盘赚钱、实盘亏钱。差别往往出在撮合逻辑不透明上。你写模拟盘时假设“信号出现就按收盘价成交”但实盘这个价格根本排不到。应对方法有两个方向想在模拟盘上贴近实盘就要把限价单的排队模型做进去想在实盘上贴近模拟就要主动调低成交阈价目标主动多让滑点。这个经验很重要模拟盘的目标不是让你赚钱而是让你知道在现实中你会赚多少钱。我个人经历中最大的体会是把“道法术器势”想清楚比写一万行代码更有价值。框架给了一个人方向和优先级。有人花了几个月调整指标参数却从没想过自己的“法”本身就是错的有人到处找最新的量化框架却连最基础的交易日志都没做好。先有框架细节才能归位。先有“道”和“法”后面所有细节才不会跑偏。这个顺序值得反复体会。