拓冰建站拓冰建站
首页 / 资讯中心 / 正文

Python机器学习量化交易实战:从数据清洗到特征工程与建模

简介资源是《4天学会Python机器学习与量化交易》系列笔记的第二部分对应视频教程p16至p20面向正在入门量化投资与Python机器学习的学习者。笔记聚焦多因子策略中的市值因子选股结合RiceQuant在线量化平台以沪深300成分股为例介绍如何通过get_fundamentals等API获取市值、财务等基本面数据并利用query函数按市值排序筛选股票、构建并动态调整个股组合。内容还系统梳理了多因子策略的完整流程——从数据获取、因子计算、因子筛选到组合构建与交易执行同时说明因子数据中截面数据与面板数据的区别。去极值处理是重点模块分别讲解了中位数去极值、3倍中位数去极值和3sigma法的原理及代码实现并配有p19、p20的具体案例帮助读者消除极端值对因子模型的干扰。资源以单个PDF文件呈现大小仅562KB方便本地阅读与检索目前已有1363人学习浏览适合希望快速上手量化选股与常见因子预处理方法的初学者作为笔记型参考。 这是“4天学会python机器学习与量化交易”系列笔记的第二篇接着上次的进度今天覆盖p16到p20这5节课程。上一篇笔记写完了p1~p15那会儿还处在python基础语法、numpy和pandas的入门阶段代码写得再多也还是“学会了工具但不知道拿来干嘛”的状态。到p16~p20这块课程节奏明显变了开始真正进入量化交易的数据获取、数据处理、特征工程和机器学习建模环节算是第一次把python、机器学习和量化交易串在了一条线上。如果你正在跟着这套课学或者只是想看看“机器学习做量化到底怎么落地”这篇笔记应该能帮你省不少事。我不光会把每节课的知识点重新梳理一遍还会把跑代码时遇到的坑、视频里没解释清楚的细节、以及我自己的一些扩展思考一并写出来方便你复现和避雷。1. p16~p20课程地图学习量化的第一段完整闭环1.1 五节课分别讲了什么前15节还在铺python基础语法和数据分析工具的底子到了p16~p20课程开始动真格了。我把这几节的内容做了一张对照表方便你一目了然地看到整个节奏安排视频主题核心知识点p16机器学习与量化交易概述机器学习在量化中的应用场景、策略类型、整体处理流程p17行情数据获取akshare/tushare等数据接口的基本用法、数据结构p18数据清洗与预处理列名统一、缺失值处理、数据类型转换、时间索引设置p19特征工程与标签构造常用技术指标计算、训练样本构造、预测目标定义p20第一个机器学习模型线性回归入门、sklearn建模、训练集测试集划分与评估这五节课整体看下来其实就是在走一条“从数据到模型”的产业链先用接口把行情数据拿到手然后清洗成能用的标准格式接着从价格序列中构造出特征和预测目标最后丢给sklearn跑一个最简单的模型。整套流程走完你就算是对“机器学习做量化”这件事有了一个全景认知——尽管此时还看不清它的全貌但至少知道了零件长什么样、大概怎么装配。1.2 为什么课程在这个位置切入机器学习我翻了一下p1~p15的内容基本是变量、循环、函数、numpy和pandas的基础操作。如果课程从这会儿就直接上随机森林、神经网络新手大概率当场劝退因为数据不会整理、维度对不上、概念听不懂报错都看不懂在报什么。而p16~p20作为过渡段把“数据处理”当成了先头部队——这其实是很符合实战节奏的安排。实际做量化的朋友应该深有体会真正花时间的从来不是模型调参而是数据获取、清洗、拼接、对齐这些脏活累活。数据质量不过关后面模型再强也是“垃圾进、垃圾出”。课程把数据处理放在建模前面而且是分了两节课篇幅来讲这个比例我是认可的。另外线性回归作为第一个模型也选得很稳它足够简单几行代码就能跑完能让刚接触机器学习的人先建立起“特征-模型-预测-评估”的完整心智模型而不是一上来就被复杂算法的数学推导劝退。2. 数据获取别一上来就调接口2.1 akshare和tushare到底选哪个视频里老师用的是tushare但我实操下来发现tushare的新版接口需要先到官网注册申请token部分接口还有积分门槛——不同积分等级能调用的数据范围不一样。对刚入门的朋友来说这是一个不小的隐形门槛。相比之下akshare不用注册、不用token直接pip install akshare装好就能用接口返回的就是pandas的DataFrame刚好可以顺势复习上一篇笔记里学的pandas操作。我把两者做了个简单对比对比项aksharetushare是否需要token不需要需要注册申请上手难度较低中等数据来源聚合公开网页数据自建数据仓库适合场景个人学习、快速验证想对数据稳定性要求更高的场景当然这只是我基于个人学习体验做的对比不是要分个高下。数据源没有绝对的优劣只有合不合适。如果你想快速验证一个想法、跑通一套流程akshare足够如果后续要做更正式的量化项目再去研究tushare的积分体系也不迟。2.2 一个能跑的取数demo以获取贵州茅台的历史日线数据为例用akshare只需要几行代码import akshare as ak # 获取贵州茅台历史日线数据不复权 df ak.stock_zh_a_hist( symbol600519, perioddaily, start_date20200101, end_date20241231, adjust ) print(df.head()) print(df.tail())第一次跑通这个接口时我还是有点兴奋的——毕竟这是第一次真正“亲手”把真实行情数据拉到本地。但兴奋劲很快就过去了因为紧接着就会发现一个让人头疼的问题返回的DataFrame列名是中文的而且包含了不少我们暂时用不上的字段比如振幅、涨跌幅、换手率等。2.3 清洗从“能跑”到“能用”如果只是打印出来看看那确实不需要额外处理。但要喂给机器学习模型就得先把数据整理成统一格式。这一步没什么高深技术主要就是四件事列名改英文、日期转成datetime类型、把日期设为索引、按时间排序。我当时的清洗代码如下import pandas as pd # 统一列名只保留后续用得上的字段 df.columns [date, open, close, high, low, volume, amount, amplitude, pct_change, change, turnover] # 日期转datetime并设为索引按时间正序排列 df[date] pd.to_datetime(df[date]) df df.set_index(date).sort_index() # 只保留建模需要的列 df df[[open, close, high, low, volume]] # 检查缺失值 print(df.isnull().sum())这里有两个细节值得多说一句。第一sort_index()一定要做因为有些数据源返回的顺序可能不是严格按时间排的而后续计算移动平均线依赖数据的先后顺序一旦顺序乱了指标就全是错的。第二改列名时不要只图省事直接照抄建议提前想好你后面建模到底需要哪些字段把多余的列尽早砍掉数据干净了后续的排查成本会低很多。3. 特征工程机器学习里的“吃鸡装备”3.1 为什么需要特征工程如果只把原始价格喂给模型相当于让一个没带装备的新人直接跳伞到决赛圈——他肉眼看到的只有红红绿绿的K线很难从中归纳出规律。特征工程就是给这个新人配上倍镜、防弹衣和医疗包让模型从同样的数据里看到更有区分度的信息。具体到量化场景移动平均线、RSI、布林带这些经典技术指标本质上就是对原始价格序列做了一次加工和压缩把“最近一段时间的趋势强弱”这类信息显式地暴露给模型。这一步做得好不好直接决定模型能力的上限。很多初学者喜欢把时间花在调模型超参数上但实战经验是特征工程对效果的提升往往比调参来得更明显。3.2 用pandas计算常见技术指标这里我用pandas把几个出场率最高的指标都算了一遍# 移动平均线 df[ma5] df[close].rolling(window5).mean() df[ma10] df[close].rolling(window10).mean() df[ma20] df[close].rolling(window20).mean() # RSI指标 delta df[close].diff() gain delta.clip(lower0) loss -delta.clip(upper0) avg_gain gain.rolling(window14).mean() avg_loss loss.rolling(window14).mean() rs avg_gain / avg_loss df[rsi] 100 - (100 / (1 rs)) # 布林带 df[std20] df[close].rolling(window20).std() df[boll_upper] df[ma20] 2 * df[std20] df[boll_lower] df[ma20] - 2 * df[std20] # 把刚开始计算产生的NaN丢弃 df df.dropna()先解释一下rolling(window5).mean()到底做了什么它相当于开了一个长度为5的滑窗从数据第一行开始往后滑动每滑到一行就取包括自己在内的前5行求平均这个值和这一行绑定在一起。所以ma5这一列的第10行表示第6到第10天的收盘价均值。窗口越短指标对价格反应越灵敏但也越容易产生噪音窗口越长趋势越平滑但滞后越严重。这个“灵敏与滞后”的权衡几乎贯穿所有技术指标的设计逻辑。RSI的公式看起来有点唬人其实就是计算一段时间内“涨的力量”在总波动中的占比取值在0到100之间。通常认为RSI高于70进入超买区、低于30进入超卖区但学习阶段先不用纠结阈值怎么选而是要把“它是在衡量什么”想明白——衡量的是最近涨跌力量的对比。3.3 标签构造你到底要预测什么特征有了接下来最重要的问题是模型的y是什么机器学习本质上是找x到y的映射关系在量化场景里最常见的一个做法是把“明天的收盘价比今天高不高”定义为一个分类问题明天涨记作1跌记作0。# 用明天的收盘价是否高于今天作为预测目标 df[target] (df[close].shift(-1) df[close]).astype(int) df df.dropna()这一行代码可以说是整个p16~p20里最容易被忽视、但最值得停下来想明白的地方。shift(-1)的作用是把整列数据向上平移一行——让第t行的target值等于第t1天的收盘价与第t天收盘价的比较结果。为什么要这么干因为我们今天能拿到的所有特征ma5、rsi、布林带等都是基于截至今天的历史数据计算出来的我们想要预测的是明天会发生什么所以标签必须来自未来一天的信息。如果不做shift直接用当天的close去构造target模型就是在拿今天的特征预测今天已经发生的事——这就不叫预测了叫“事后诸葛亮”。这也是量化里经常提到的“未来函数”问题后面踩坑部分我会专门展开说。4. 第一个模型线性回归其实暴露了很多问题4.1 为什么选线性回归而不是别的p20一口气把线性回归的建模、训练、评估流程走完了。这里选线性回归而不是逻辑回归或者决策树我觉得有三个原因简单、可解释、跑得快。线性回归的预测结果本质上是对所有特征做了一次加权求和公式就是y w1x1 w2x2 ... b配合sklearn大概五行代码就能训练完。对于刚接触机器学习的同学重要的不是模型多高级而是先把“fit-predict-evaluate”这条流水线走通。当然线性回归本身是回归模型输出的是连续值而我们构造的target是0和1的分类标签。课程这里直接用“预测值大于0.5就判定为涨”的方式把回归结果硬掰成分类结果。严格来说更标准的做法是用逻辑回归LogisticRegression它对分类问题的建模方式更合理。但作为启蒙演示线性回归够用了它能把“训练一套模型”的流程感建立起来逻辑回归的数学细节留到后面再深入反而是更平滑的学习曲线。4.2 时间序列数据不能随机切分很多第一次跑机器学习的人会习惯性地直接调用train_test_split()把数据随机切成训练集和测试集。但在量化场景里这个做法有严重问题时间序列数据有先后依赖关系随机切分等于让模型“看了未来再做过去题”测试集里混入了未来信息评估结果会虚高得非常离谱。正确做法是按时间顺序用前80%的数据训练、后20%的数据测试from sklearn.linear_model import LinearRegression from sklearn.metrics import classification_report # 特征列 feature_cols [ma5, ma10, ma20, rsi, boll_upper, boll_lower] X df[feature_cols].values y df[target].values # 按时间切分前80%训练后20%测试 split_idx int(len(X) * 0.8) X_train, X_test X[:split_idx], X[split_idx:] y_train, y_test y[:split_idx], y[split_idx:] # 训练线性回归模型 model LinearRegression() model.fit(X_train, y_train) # 预测并将连续值转换为0/1 y_pred (model.predict(X_test) 0.5).astype(int) # 输出评估报告 print(classification_report(y_test, y_pred))这里还有个容易踩的雷特征x和标签y必须严格对齐。如果特征计算完dropna之后又单独对y做了一次dropna行数就对不上了后面的fit会直接报错。我当时就犯过这个错来回对了好几遍索引才发现是行数不一致。建议习惯性看一眼X.shape和y.shape是不是一致。4.3 评估结果怎么看以及为什么赚钱没那么容易classification_report会输出precision、recall、f1-score这些指标。第一次看到这份报告的时候我的准确率大概在53%左右比瞎猜的50%强了一点点但远谈不上“找到了财富密码”。这里多说一句很多新手容易盯住准确率不放但涨跌分类有一个天然的不平衡问题如果市场整体上涨天数略多模型什么都不做、全部预测“涨”也能拿到一个还不错的准确率。所以真正要看的其实是precision、recall和f1-score的组合尤其对“涨”这个类别单独看。更扎心的是即便模型准确率做到了52%在真实交易里还要扣掉手续费、滑点这些交易成本52%的胜率扣完成本很可能根本不赚钱。机器学习在量化里的作用不是“点石成金”而是帮你从大量数据里找出统计意义上的规律再把规律包装成策略去执行。离“稳定盈利”中间还隔着一个完整的交易系统——仓控、止损、资金管理、回撤控制这些一个都不能少。p16~p20只是把机器学习模型的轮子转了起来离“上路”还远。5. 踩坑记录这些坑比课程本身更有学习价值5.1 未来函数看似90%准确率的假象我在自己动手复现时曾经写出了这样一段错误的标签构造代码# 错误示范 df[target] (df[close] df[close].shift(1)).astype(int)看起来好像没什么问题就是把“今天比昨天涨没涨”作为标签。问题出在特征里ma5、ma10、ma20这些指标都包含了当天的收盘价信息而target又是由当天收盘价和昨天收盘价的比较得到的。模型训练时特征和标签共享了同一个“今天的收盘价”相当于考试时答案就压在卷子底下——测试集准确率冲到了90%以上我还以为自己发现了什么不得了的规律后来对照课程才发现标签构造逻辑搞反了方向。应该用close.shift(-1)制造“明天”的信息而不是用close.shift(1)去提取“昨天”的信息。这类未来函数问题是量化新手最容易踩的坑错误代码跑出来的评估结果越漂亮越要警惕数据里是不是藏着未来。5.2 除权除息会把股价“打出一个坑”取数时还有一个很容易被忽视的细节默认参数获取的往往是“不复权”数据。一旦股票在某一天除权除息价格会突然向下跳空一大截但跳空之前的历史价格没有做调整。这时候计算均线、RSI等指标就会在除权日附近出现假信号——模型会以为股价暴跌了但其实只是分红除权导致的价格修正。解决办法很简单把取数接口的adjust参数改成qfq前复权让历史价格在除权时做统一调整。前复权的逻辑是保持当前价格不变把历史价格按比例调整这样算出来的技术指标才是连续的。5.3 sklearn版本差异带来的API变更课程视频里用的是当时某个版本的sklearn代码在我现在的新版本环境里偶尔会碰到一些参数失效或者模块迁移的情况。比如某些老版本里的函数在新版本中换了位置或者改了默认值直接复制老代码会莫名其妙报错。我的处理办法是在项目一开始就创建一个虚拟环境把依赖版本固定下来pip install scikit-learn1.0.2这样做的好处是以后不管课程代码怎么变、系统环境怎么升级项目本身能稳定复现。如果你懒得管版本也没问题——但每跑一步遇到报错先看一眼报错信息里的sklearn相关字样通常就能定位是版本问题还是代码问题。5.4 重新理解“4天学会”这件事把p16~p20跑通之后我对“4天学会”这个标题的理解更清醒了。4天时间能完成的事是搭好环境、了解接口、跑通一套标准的建模流程让你看到一个从数据到模型的完整骨架。但距离真正“学会”还差着大量的实操换一只股票能不能跑通换一组特征效果会怎样模型参数调一调又会怎样这些问题靠4天是不可能得到答案的。课程的真正价值是把一条最常用的技术路径喂到你嘴边——数据获取-清洗-特征-建模-评估后面需要你自己反复咀嚼、消化成自己的能力。写到这里p16~p20的内容算是基本消化完了。一个很主观的感受这套课程真正的价值不在那几行代码而在把“机器学习做量化”这条路上最常见的几个坑提前暴露给你。我踩过的未来函数、复权、版本兼容你大概率也会踩一遍早点知道至少能少掉几根头发。接下来我会继续往下学下一篇笔记打算整理p21~p25的回测部分到那会儿就能看到策略完整跑起来是什么效果了。有兴趣的可以继续关注也建议你把上一篇笔记里的环境搭建和基础语法补一补再看本文的代码会顺畅很多。本文还有配套的精品资源点击获取
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门