
最近在 CSDN 和短视频平台上经常能看到类似“100% AI 交易而且免费”“从分析到下单全交给 AI0 成本上手”的标题像【孙越AI量化交易】这类课程页面也获得了很高的关注。很多人第一反应是真的能自动赚钱吗有没有隐含的坑正好我自己在项目里也搭过几条 AI 量化研究链路所以这篇文章不打算评价某个课程而是把 AI 量化交易这条链路拆开从数据获取、策略回测、AI 信号增强、模拟下单到定时运行完整地走一遍。文章里的代码我会尽量保持可以直接运行重点不是给你一个“稳赚策略”而是让你掌握这套系统的搭建思路。弄清楚哪些环节 AI 能帮上忙哪些环节必须人工兜底。1. AI 量化交易到底是什么1.1 一个现象背后的真实需求先说一个判断凡是强调“100% 胜率”“全自动躺赚”“永久免费”的量化交易宣传都要带着怀疑去看。金融市场本身充满不确定性AI 模型不可能百分百预测对方向。那些标题之所以流行本质上还是击中了普通人对“省心赚钱”的期待。抛开营销话术AI 量化交易确实有真实的落地价值。传统量化交易是“人写公式程序执行”而 AI 量化交易多了一个环节让机器学习模型或大语言模型参与数据分析、信号生成和策略优化。比如模型从历史行情中挖掘出价格变化规律大模型读取财报、新闻、研报输出情绪判断AI Agent 把“分析—决策—下单”串成自动化流水线。换句话说AI 量化交易的核心价值不是“预测涨跌”而是把原来需要人工盯盘、人工复盘、人工写规则的工作自动化同时减少主观情绪对交易的干扰。1.2 AI 在量化交易链路中的位置一条完整的量化交易链路通常包含五个环节数据获取行情数据、财务数据、新闻舆情数据特征工程把原始数据加工成模型能用的指标信号生成通过规则或模型判断买入、卖出、持仓回测验证在历史数据上模拟交易评估策略表现执行与风控连接券商或模拟盘接口完成下单并控制风险。AI 可以在前四个环节介入。比如用机器学习模型替代传统技术指标的信号生成也可以用大模型做新闻情绪分析还能让 Agent 自动执行复盘。但执行环节要特别谨慎尤其是实盘委托必须考虑滑点、延迟、接口稳定性和资金安全。1.3 “免费”和“全自动”的理性理解免费不等于零成本。“免费”通常体现在两个层面一是开源工具免费比如 Python、pandas、backtrader、akshare、scikit-learn 都是免费的二是部分大模型 API 提供免费额度或者你可以通过 Ollama 在本地部署开源模型这部分也不需要付费。但免费的代价是你要自己处理数据源稳定性、回测质量和代码维护问题。真正值得投入的是把基础设施和策略逻辑掌握在自己手里。2. 环境准备与项目结构2.1 运行环境我本地环境如下你可以根据实际情况调整版本重点理解配置思路操作系统Windows 11macOS、Ubuntu 也可以Python 版本3.9 及以上包管理建议使用 conda 或 venv 创建虚拟环境数据接口akshareA 股、yfinance美股部分网络环境不稳定回测框架backtrader机器学习scikit-learn、pandas、numpy定时调度APScheduler大模型接口OpenAI SDK 或 Ollama 本地模型。需要说明的是Python 生态更新很快akshare 的接口有时会因为数据源网站改版而失效。如果遇到接口报错优先去官方文档查看最新用法。2.2 创建项目目录建议在本地建一个干净的目录方便后续扩展ai_quant_tutorial/ ├── data/ # 行情数据缓存 ├── strategies/ # 策略代码 ├── ai_models/ # AI 相关模型和调用 ├── broker/ # 模拟下单和风控 ├── main.py # 定时任务入口 ├── requirements.txt # 依赖文件 └── README.md创建虚拟环境并安装依赖python -m venv .venv # Windows .venv\Scripts\activate # macOS / Linux source .venv/bin/activate pip install pandas numpy akshare backtrader scikit-learn apscheduler openai如果你的网络环境访问外网有限制可以先不安装 yfinance 和 openaiA 股数据用 akshare 就能跑通大部分示例。3. 整体架构与技术选型3.1 模块化设计我建议把 AI 量化交易系统拆成五层每层之间通过数据接口解耦这样出问题的时候能快速定位[数据层] akshare / yfinance / 本地CSV ↓ [信号层] 技术指标 / 机器学习模型 / 大模型情绪分析 ↓ [决策层] 仓位计算 / 买卖信号合并 / 风险过滤 ↓ [执行层] 模拟撮合 / 券商API需授权 ↓ [风控层] 最大回撤熔断 / 单笔仓位限制 / 人工接管后面实战部分会按照这个分层来写代码。为什么这么分层因为 AI 模型经常会调整但数据接口和下单逻辑相对稳定。把模型单独放一层换模型的时候不需要改动数据层和执行层。3.2 技术选型对照模块方案说明行情数据akshareA 股免费数据源接口丰富数据处理pandas清洗、对齐、特征工程策略回测backtrader事件驱动框架适合策略验证机器学习scikit-learn特征处理和分类模型适合入门大模型OpenAI SDK / Ollama新闻情绪分析、策略解释调度APScheduler定时拉取数据并生成信号模拟交易自研 PaperBroker避免直接连实盘接口带来的风险这里要特别提醒模拟盘和实盘有很大区别。实盘还要考虑手续费、滑点、涨跌停无法成交、网络延迟等问题。初学者至少跑三个月的模拟盘再考虑真实资金。4. 实战从零搭建一套“AI 分析—回测—模拟下单”流程4.1 获取行情数据我们先用 akshare 获取贵州茅台的日线数据。文件路径data_loader.pyimport akshare as ak import pandas as pd def fetch_a_stock_daily(symbol: str, start_date: str, end_date: str) - pd.DataFrame: 获取A股日线数据 symbol: 股票代码如 600519 start_date: 开始日期格式 20230101 end_date: 结束日期格式 20241231 df ak.stock_zh_a_hist( symbolsymbol, perioddaily, start_datestart_date, end_dateend_date, adjustqfq # 前复权 ) # akshare 返回的列名是中文这里统一转成英文 df.rename( columns{ 日期: date, 开盘: open, 收盘: close, 最高: high, 最低: low, 成交量: volume, 成交额: amount, }, inplaceTrue, ) df[date] pd.to_datetime(df[date]) df df[[date, open, close, high, low, volume, amount]] df df.sort_values(date).reset_index(dropTrue) return df if __name__ __main__: data fetch_a_stock_daily(600519, 20230101, 20241231) print(data.head()) print(data.tail())需要注意几点akshare 的列名是中文记得做映射复权方式选择前复权避免历史价格因为分红除权出现断层有的版本列名可能是“日期”“股票代码”建议先打印原始数据再处理。4.2 编写一个基础策略为了让 AI 信号有对比基准我们先实现一个经典的双均线策略。它的逻辑很简单短期均线上穿长期均线时买入下穿时卖出。文件路径strategies/ma_strategy.pyimport pandas as pd def generate_ma_signal(df: pd.DataFrame, short: int 5, long: int 20) - pd.DataFrame: 双均线策略生成交易信号 规则short上穿long - 买入short下穿long - 卖出 result df.copy() result[ma_short] result[close].rolling(windowshort).mean() result[ma_long] result[close].rolling(windowlong).mean() result[ma_diff] result[ma_short] - result[ma_long] result[signal] 0 # diff从负变正产生买入信号从正变负产生卖出信号 result.loc[(result[ma_diff] 0) (result[ma_diff].shift(1) 0), signal] 1 result.loc[(result[ma_diff] 0) (result[ma_diff].shift(1) 0), signal] -1 return result双均线策略虽然简单但用来解释回测流程足够了。后面的 AI 模型可以看作是对“signal”这个字段做增强。4.3 用 backtrader 回测有了行情数据和信号下一步用 backtrader 做回测。这里直接在 backtrader 里内置双均线逻辑避免再次读取 CSV 的麻烦。文件路径backtest_ma.pyimport backtrader as bt import akshare as ak import pandas as pd class MaCrossStrategy(bt.Strategy): params ( (short, 5), (long, 20), ) def __init__(self): self.sma_short bt.indicators.SimpleMovingAverage( self.data.close, periodself.params.short ) self.sma_long bt.indicators.SimpleMovingAverage( self.data.close, periodself.params.long ) self.crossover bt.indicators.CrossOver(self.sma_short, self.sma_long) def next(self): if not self.position: if self.crossover 0: self.buy(size100) elif self.crossover 0: self.close() def load_data_from_akshare(symbol: str, start: str, end: str): df ak.stock_zh_a_hist( symbolsymbol, perioddaily, start_datestart, end_dateend, adjustqfq, ) df.rename( columns{ 日期: date, 开盘: open, 收盘: close, 最高: high, 最低: low, 成交量: volume, }, inplaceTrue, ) df[date] pd.to_datetime(df[date]) df df[[date, open, close, high, low, volume]] df df.sort_values(date) data bt.feeds.PandasData(datanamedf, datetimedate) return data if __name__ __main__: cerebro bt.Cerebro() data load_data_from_akshare(600519, 20230101, 20241231) cerebro.adddata(data) cerebro.addstrategy(MaCrossStrategy) cerebro.broker.setcash(100_000.0) cerebro.broker.setcommission(commission0.0002) # 万2手续费 cerebro.addsizer(bt.sizers.FixedSize, stake100) print(初始资金: %.2f % cerebro.broker.getvalue()) cerebro.run() print(期末资金: %.2f % cerebro.broker.getvalue()) cerebro.plot()运行后你会看到类似这样的输出初始资金: 100000.00 期末资金: 103260.50如果期末资金低于初始资金也是很正常的说明策略在历史数据上表现一般。回测的目的不是让你立刻拿去实盘而是建立起“先验证再上线”的习惯。4.4 让 AI 生成辅助信号双均线策略的规则是固定的行情变化之后容易失效。这里用随机森林模型做一个简单的方向预测把模型输出作为信号增强。文件路径ai_models/trend_predictor.pyimport pandas as pd from sklearn.ensemble import RandomForestClassifier from sklearn.model_selection import TimeSeriesSplit from sklearn.metrics import accuracy_score def build_features(df: pd.DataFrame) - pd.DataFrame: 构建用于训练的特征注意不能用未来数据 result df.copy() # 历史收益率 result[ret_1] result[close].pct_change(1) result[ret_5] result[close].pct_change(5) result[ret_10] result[close].pct_change(10) # 均线偏离度 result[ma_5] result[close].rolling(5).mean() result[ma_20] result[close].rolling(20).mean() result[bias_5] result[close] / result[ma_5] - 1 result[bias_20] result[close] / result[ma_20] - 1 # 波动率 result[volatility] result[ret_1].rolling(10).std() # 标签明天收盘价比今天高则为1否则为0 result[label] (result[close].shift(-1) result[close]).astype(int) # 删除空值 result result.dropna().reset_index(dropTrue) return result def train_and_predict(df: pd.DataFrame): 演示模型训练与预测流程 实盘中应使用滚动训练防止用到未来数据 feature_columns [ret_1, ret_5, ret_10, bias_5, bias_20, volatility] model RandomForestClassifier( n_estimators200, max_depth5, random_state42, n_jobs-1, ) # 前80%训练后20%验证 split_idx int(len(df) * 0.8) train_df df.iloc[:split_idx] test_df df.iloc[split_idx:] model.fit(train_df[feature_columns], train_df[label]) pred model.predict(test_df[feature_columns]) acc accuracy_score(test_df[label], pred) print(f验证集准确率: {acc:.2%}) # 最新一天信号 last_features df[feature_columns].iloc[[-1]] prob model.predict_proba(last_features)[0][1] print(f最新看涨概率: {prob:.2%}) return model, prob这段代码最需要注意的是数据泄露问题。标签label使用的是“明天的收盘价”所以特征里不能包含明天的信息。上面代码用shift(-1)构造标签训练时删掉最后一行样本内不会直接用未来数据但在实盘部署时还要做滚动更新。4.5 模拟下单模块真实券商接口需要认证和资金门槛本文先实现一个模拟下单模块用于验证信号能不能被正确执行。文件路径broker/paper_broker.pyfrom datetime import datetime class PaperBroker: 模拟经纪商处理买入、卖出、持仓和委托记录 def __init__(self, init_cash: float 100_000.0): self.cash init_cash self.position 0.0 self.trades [] def buy(self, price: float, size: int): cost price * size if cost self.cash: print(资金不足买入失败) return False self.cash - cost self.position size self.trades.append( { time: datetime.now().isoformat(), action: BUY, price: price, size: size, amount: cost, } ) print(f买入 {size} 股价格 {price:.2f}剩余资金 {self.cash:.2f}) return True def sell(self, price: float, size: int): if size self.position: print(持仓不足卖出失败) return False income price * size self.cash income self.position - size self.trades.append( { time: datetime.now().isoformat(), action: SELL, price: price, size: size, amount: income, } ) print(f卖出 {size} 股价格 {price:.2f}剩余仓位 {self.position:.2f}) return True def portfolio_value(self, current_price: float) - float: return self.cash self.position * current_price这里的模拟撮合默认按收盘价成交。真实交易中会有滑点回测时可以在价格基础上加一个滑点比例比如exec_price price * 1.001。4.6 用 APScheduler 定时运行行情数据每天更新策略也应该在固定时间自动运行。下面用 APScheduler 实现一个每天收盘后运行的流程先拉数据再生成信号最后执行模拟下单。文件路径main.pyimport akshare as ak import pandas as pd from apscheduler.schedulers.blocking import BlockingScheduler from broker.paper_broker import PaperBroker from ai_models.trend_predictor import build_features, train_and_predict broker PaperBroker(init_cash100_000) def daily_task(): print(开始执行每日 AI 量化任务) # 1. 获取近两年的数据 df ak.stock_zh_a_hist( symbol600519, perioddaily, start_date20230101, end_date20241231, adjustqfq, ) df.rename( columns{日期: date, 开盘: open, 收盘: close, 最高: high, 最低: low, 成交量: volume}, inplaceTrue, ) df df[[date, open, close, high, low, volume]] df df.sort_values(date) # 2. 训练模型获取最新看涨概率 feature_df build_features(df) model, prob train_and_predict(feature_df) # 3. 根据概率执行模拟下单 current_price df[close].iloc[-1] if prob 0.55: broker.buy(pricecurrent_price, size100) elif prob 0.45: broker.sell(pricecurrent_price, sizeint(broker.position)) total_value broker.portfolio_value(current_price) print(f当前总资产: {total_value:.2f}) if __name__ __main__: scheduler BlockingScheduler() # 每个交易日收盘后执行示例为下午 15:30 scheduler.add_job(daily_task, cron, day_of_weekmon-fri, hour15, minute30) scheduler.start()使用定时任务前先手动运行一次确认数据源和模型没有报错再部署到服务器上。生产环境中还要加入异常通知比如任务失败时往企业微信或钉钉机器人发一条消息。5. 让大模型参与决策一个最小可用的 AI Agent5.1 从“信号系统”到 Agent 的差距前面的流程本质上是一个规则驱动的自动化系统。今天我手动改了买入阈值明天想让它自动分析新闻又得改代码。如果希望系统更接近“从分析到下单全交给 AI”可以引入大模型 Agent。大模型在量化里的价值不是算 K 线而是处理非结构化数据。比如拼接财经新闻片段让大模型判断市场情绪把当日交易记录交给大模型自动生成复盘报告让 Agent 根据用户指令调用数据查询和下单工具。要注意的是大模型存在幻觉可能一本正经地编造数据。所以工具调用结果必须来自真实数据源大模型只能做解读和决策建议不能直接生成数据当结果。5.2 简单的工具调用 Agent下面写一个不依赖 LangChain 的最小示例核心思路是用户提问 - 判断意图 - 调用对应函数 - 使用大模型组织回答。文件路径ai_models/agent_demo.pyimport os from openai import OpenAI client OpenAI(api_keyos.getenv(OPENAI_API_KEY)) def query_stock_price(symbol: str) - str: 模拟行情查询工具真实环境应接入 akshare 或数据库 price_map { 600519: 1700.00, 000001: 10.50, } return price_map.get(symbol, 未找到该股票) def execute_buy(symbol: str, size: int) - str: 模拟下单工具真实环境需要券商接口和授权 return f模拟买入 {symbol} {size} 股订单已提交 def run_agent(user_input: str) - str: 简单意图识别 工具调用 tools { 查价格: query_stock_price, 买入: execute_buy, } # 简单关键词路由 if 价格 in user_input or 多少 in user_input: symbol user_input.split( )[-1] tool_result tools[查价格](symbol) elif 买入 in user_input: parts user_input.split( ) symbol parts[1] size int(parts[2]) tool_result tools[买入](symbol, size) else: tool_result 暂不支持该指令 # 大模型组织最终回复 completion client.chat.completions.create( modelgpt-4o-mini, # 请按你的实际账号可用模型调整 messages[ { role: system, content: 你是量化交易助理请根据工具调用结果用中文回复不要编造数据。, }, { role: user, content: f用户指令{user_input}\n工具结果{tool_result}, }, ], ) return completion.choices[0].message.content if __name__ __main__: # 需要先在命令行设置 OPENAI_API_KEY 环境变量 print(run_agent(查价格 600519)) print(run_agent(买入 600519 100))如果你不想付费调用大模型 API也可以用 Ollama 部署本地开源模型然后把client替换成 Ollama 的接口地址。替换方式也很简单client OpenAI( base_urlhttp://localhost:11434/v1, api_keyollama, )模型名称改成你本地拉取的名字比如qwen2.5:7b。本地模型的好处是数据不出内网隐私性好但推理速度和效果通常不如云端大模型。5.3 Agent 的边界上面这个 Agent 只是演示意图路由和工具调用真正的生产级 Agent 还需要加入多轮对话记忆、权限校验、风控复核。比如买入指令必须经过二次确认单笔金额超过阈值时自动拒绝。我在第 7 部分会专门讲风控这里先记住一点Agent 越快越需要风控把关。6. 常见问题与排查思路AI 量化交易涉及数据、模型、执行三个层面最容易出问题的地方往往是数据接口和回测设计。问题现象常见原因解决思路akshare 接口返回空值数据源网站改版或接口限流查看 akshare 官方文档检查网络适当重试回测结果特别好用了未来函数或前视偏差检查特征和标签是否在时间点之后才生成信号历史回测盈利、实盘亏损过拟合或模拟盘成本设置过低加入手续费、滑点延长回测周期做样本外测试模型准确率不高特征太弱或行情本身难以预测增加特征维度使用集成模型降低交易频率定时任务没有运行服务器时区或调度表达式错误检查 cron 表达式使用本地时间测试大模型生成虚假数据幻觉问题强制 Agent 通过工具获取数据禁止模型直接给出行情数值模拟下单失败资金不足或持仓不足检查账户资金和持仓打印日志定位新手上路最容易犯的错误是只关注“模型准确率”。实际上准确率只代表分类正确比例不代表策略能赚钱。就算准确率到了 60%如果亏损的交易平均亏得多、赚钱的交易赚得少最终仍然是负收益。这也是为什么一定要走完“回测 — 模拟盘 — 小资金实盘”的完整流程。7. 风险控制与工程建议7.1 实盘之前必须想清楚的几件事AI 量化交易真正的门槛不是写代码而是风险控制。代码写错可以改模型不准可以换但实盘账户资金亏没了就很难挽回。先说我在实战里见过的问题有人把 API Key 写死在代码里结果代码传到 GitHub 导致密钥泄露有人直接用历史数据训练模型然后立刻用同段数据“验证”准确率虚高有人回测时忽略跌停买不进、涨停卖不出的情况实盘才知道成交是有限制的有人让 Agent 自动下单结果单笔仓位过大一次亏损就超过了整个月的收益。这些都是可以提前避免的。7.2 最小可用的风控规则我给自己的模拟盘系统设置了几条硬性规则单笔交易金额不超过总资产的 10%单只股票仓位不超过总资产的 30%当日亏损达到总资产 5%停止当日交易策略回撤超过 20%强制停用策略进入人工复核所有自动下单都在模拟盘验证至少 30 个交易日。文件路径broker/risk_manager.pyclass RiskManager: 简单风控模块 def __init__( self, max_single_rate: float 0.1, max_position_rate: float 0.3, max_loss_rate: float 0.05, ): self.max_single_rate max_single_rate self.max_position_rate max_position_rate self.max_loss_rate max_loss_rate def check_order(self, total_asset: float, current_position: float, order_value: float) - bool: # 单笔比例检查 if order_value total_asset * self.max_single_rate: return False # 加仓后总仓位检查 new_position_rate (current_position order_value) / total_asset if new_position_rate self.max_position_rate: return False return True def check_loss_stop(self, total_asset: float, init_asset: float) - bool: loss_rate (init_asset - total_asset) / init_asset if loss_rate self.max_loss_rate: print(触发日亏损熔断停止交易) return False return True这套风控很朴素但已经能挡住不少风险。真正生产环境中还会加入订单超时重试、接口幂等、审计日志、操作人员双人复核等机制。7.3 工程化建议敏感信息用环境变量管理不要硬编码数据落地到本地数据库或 Parquet 文件方便复盘日志要记录关键时间点、模型参数、下单结果模型建议保存版本号方便回溯出现异常时优先停止自动下单而不是继续运行每一步操作都遵循最小权限原则尤其是涉及真实资金的时候。8. 总结与下一步学习路线这篇文章从概念到代码完整搭建了一套“数据获取 — 规则策略 — AI 信号 — 模拟下单 — 定时调度”的 AI 量化交易雏形。整体链路可以概括为用 akshare 拉数据用 backtrader 验证基础策略用机器学习模型生成方向概率用模拟券商执行订单最后用 APScheduler 自动化运行。真正要进阶可以沿着下面几条路线继续深入因子研究学习 IC、IR、因子分层测试理解什么样的因子才能真正预测收益组合优化多股票、多策略如何分配资金用风险平价或最大夏普比率目标优化低延迟执行如果做高频策略需要学习 C、FPGA 或专业量化平台Agent 增强把公告、研报、宏观经济数据接入 Agent让系统具备更强的信息解读能力。从学习路径来看新人不要急着上实盘。先把本文代码跑通替换成自己熟悉的股票增加交易成本做样本外测试。等模拟盘连续三个月没有出现重大回撤再考虑用极小资金试水。AI 量化交易最有价值的地方是它能逼着你把交易规则、资金管理和风险边界都想清楚这套工程化能力在任何领域都用得上。希望这篇文章能帮你迈出第一步。