器學(xué)習(xí)入門量化交易:從環(huán)境搭建到首個(gè)策略Demo全流程解析)
簡介一份面向量化交易入門者的Python機(jī)器學(xué)習(xí)與量化交易學(xué)習(xí)筆記聚焦多因子選股與數(shù)據(jù)預(yù)處理核心環(huán)節(jié)。內(nèi)容覆蓋p16~p20五個(gè)章節(jié)包括市值因子選股策略的案例介紹與代碼演示、多因子策略整體流程、因子數(shù)據(jù)組成與面板數(shù)據(jù)概念并重點(diǎn)講解中位數(shù)去極值、三倍中位數(shù)去極值和三倍標(biāo)準(zhǔn)差法去極值的具體實(shí)現(xiàn)以及如何利用RiceQuant平臺(tái)獲取財(cái)務(wù)數(shù)據(jù)、篩選股票池、調(diào)整持倉。筆記為單文件PDF共一個(gè)文件壓縮包大小五百六十二KB適合直接閱讀和隨時(shí)回看。已有一千三百余人學(xué)習(xí)被不少量化入門者作為參考。通過閱讀這份筆記讀者可快速掌握市值因子選股的完整步驟理解因子異常值對(duì)模型穩(wěn)定性的影響學(xué)會(huì)使用去極值技術(shù)減小極端數(shù)據(jù)干擾為后續(xù)構(gòu)建更復(fù)雜的多因子策略打下扎實(shí)基礎(chǔ)。1. 這一part到底講了啥從“跑通代碼”到“看懂流程”先說個(gè)實(shí)話量化交易這塊大多數(shù)人一開始都是被“自動(dòng)賺錢”四個(gè)字吸引進(jìn)來的結(jié)果一上手就懵了——pandas都沒裝明白機(jī)器學(xué)習(xí)四個(gè)字更是聽著像天書。我當(dāng)初也是這樣所以這份筆記我特意按p16到p20的順序重新整理了一遍核心就一件事把機(jī)器學(xué)習(xí)在量化里的角色講清楚然后讓你親手跑通一個(gè)最簡單的流程。這4節(jié)課的內(nèi)容定位很明確不是教你寫多復(fù)雜的策略而是幫你把“數(shù)據(jù) → 特征 → 模型 → 信號(hào) → 回測”這條鏈路打通。p16到p20剛好覆蓋了環(huán)境搭建收尾、機(jī)器學(xué)習(xí)基礎(chǔ)概念、以及第一個(gè)簡單的量化策略demo。如果你正卡在“代碼能跑但不知道在干嘛”的階段這幾節(jié)課就是給你補(bǔ)上那個(gè)“干嘛”的。適合誰來參考兩類人。一是剛學(xué)完python基礎(chǔ)、想往量化方向走但不知道從哪下手的二是已經(jīng)裝了一堆庫、但始終沒搞明白機(jī)器學(xué)習(xí)在交易里到底怎么用的人。如果你是沖著“一周暴富”來的那可以直接關(guān)掉這里只有枯燥的數(shù)據(jù)和代碼。2. 環(huán)境搭建收尾別在第一步就勸退自己2.1 python裝哪個(gè)版本、用不用anacondap16花了些時(shí)間講環(huán)境很多人覺得啰嗦但以我?guī)н^幾十個(gè)新人的經(jīng)驗(yàn)講環(huán)境問題能卡住一半以上的人。python版本這塊無腦選3.8到3.10之間的就行別追最新版。原因很實(shí)際量化生態(tài)里大量庫的預(yù)編譯包更新速度跟不上python新版本發(fā)布速度你裝個(gè)3.12很可能遇到numba、ta-lib這種庫直接沒有對(duì)應(yīng)wheel包只能源碼編譯然后報(bào)一堆錯(cuò)。至于anaconda我的建議是如果你只是學(xué)機(jī)器學(xué)習(xí)那直接裝miniconda就行體積小夠用。如果你連python都沒裝過那anaconda一步到位更省心自帶conda環(huán)境管理python版本隨便切換不污染系統(tǒng)環(huán)境。我當(dāng)年就是嫌anaconda太大死活不用結(jié)果裝個(gè)庫把系統(tǒng)python搞崩了一次后來老實(shí)了。提示環(huán)境管理是量化開發(fā)的剛需千萬別圖省事把所有庫都往系統(tǒng)python里裝。一個(gè)項(xiàng)目一個(gè)虛擬環(huán)境出事直接刪掉重建五分鐘恢復(fù)。2.2 vscode還是jupyter這兩節(jié)課明顯是用jupyter notebook演示的我建議你也用。機(jī)器學(xué)習(xí)的探索階段特征怎么選、參數(shù)怎么調(diào)本身就是不斷試錯(cuò)的過程jupyter的單元格執(zhí)行模式天然適合這種工作流。數(shù)據(jù)長什么樣、中間結(jié)果對(duì)不對(duì)你一眼就能看到。vscode當(dāng)然也有jupyter插件但我個(gè)人體驗(yàn)是插件版偶爾會(huì)有內(nèi)核連不上的問題尤其是conda環(huán)境切換之后。所以你要是純學(xué)習(xí)直接裝個(gè)anaconda打開jupyter就能用界面丑點(diǎn)沒關(guān)系能干活就行。等后面寫正式策略了再換vscode寫.py文件也不遲。3. 機(jī)器學(xué)習(xí)核心概念用“預(yù)測房價(jià)”理解一切3.1 特征、標(biāo)簽、訓(xùn)練集、測試集p17到p18開始講機(jī)器學(xué)習(xí)基礎(chǔ)這部分如果你之前看過相關(guān)視頻會(huì)覺得重復(fù)但它的意義在于把概念和量化場景綁在一起講——這是很多純機(jī)器學(xué)習(xí)課程做不到的。拿預(yù)測房價(jià)來打比方你要預(yù)測一套房子能賣多少錢這是標(biāo)簽也就是y你手里有面積、地段、房齡、朝向這些信息這是特征也就是X。機(jī)器學(xué)習(xí)做的就是找到一套規(guī)則能從這些特征算出房價(jià)。規(guī)則怎么找給它看大量“特征真實(shí)房價(jià)”的樣本這叫訓(xùn)練集看完之后拿它沒見過的數(shù)據(jù)考它這叫測試集。放到量化里特征就是各種技術(shù)指標(biāo)、量價(jià)數(shù)據(jù)、甚至輿情信息標(biāo)簽就是你未來N天是漲還是跌或者漲跌幅。模型的任務(wù)變成根據(jù)這些特征算出未來上漲的概率或者預(yù)測的漲跌幅。本質(zhì)和預(yù)測房價(jià)沒區(qū)別只是數(shù)據(jù)源和業(yè)務(wù)背景不同。3.2 過擬合你以為學(xué)會(huì)了其實(shí)只是背題了p19重點(diǎn)講了過擬合我建議你把這個(gè)概念刻在腦子里因?yàn)樗橇炕呗曰販y最經(jīng)典的坑。過擬合說白了就是模型在訓(xùn)練集上表現(xiàn)極好因?yàn)榘阉氨场毕聛砹说坏經(jīng)]見過的數(shù)據(jù)上就原形畢露。我見過太多新手策略在回測里收益曲線完美得像畫出來的一樣一上實(shí)盤就虧成狗九成都是過擬合。怎么判斷最簡單的辦法是看訓(xùn)練集和測試集的差距訓(xùn)練集準(zhǔn)確率95%測試集只有60%那基本就是過擬合了。后面做特征工程和參數(shù)優(yōu)化時(shí)這個(gè)問題會(huì)反復(fù)遇到現(xiàn)在先有這個(gè)概念后面少交學(xué)費(fèi)。4. 你的第一個(gè)“量化策略”demo從數(shù)據(jù)到信號(hào)4.1 數(shù)據(jù)從哪里來p20開始動(dòng)手寫第一個(gè)簡單的策略demo用到的數(shù)據(jù)是tushare或者其他免費(fèi)數(shù)據(jù)源。這里有個(gè)大坑我先提醒一下現(xiàn)在很多數(shù)據(jù)源的接口改了規(guī)則老視頻里的代碼直接跑會(huì)報(bào)錯(cuò)別慌這是正?,F(xiàn)象。我寫這篇筆記的時(shí)候tushare pro需要積分才能獲取完整日線數(shù)據(jù)但基礎(chǔ)的每日行情數(shù)據(jù)用免費(fèi)額度基本夠用。如果你不想注冊(cè)、不想搞token也可以直接用yfinance拉美股數(shù)據(jù)接口穩(wěn)定、不用注冊(cè)?;蛘哂胊kshare覆蓋國內(nèi)數(shù)據(jù)免費(fèi)且接口比較干凈。選數(shù)據(jù)源的原則就一條先跑通流程別在數(shù)據(jù)下載上耗太久。import pandas as pd import numpy as np from sklearn.linear_model import LinearRegression # 模擬數(shù)據(jù)過去20天的收盤價(jià) np.random.seed(42) price pd.Series(np.cumsum(np.random.randn(100) * 2 50)) # 構(gòu)造特征過去N天的收益率 df pd.DataFrame({price: price}) df[ret_1] df[price].pct_change() df[ret_2] df[price].pct_change(2) df[ret_3] df[price].pct_change(3) df[ret_5] df[price].pct_change(5) # 標(biāo)簽未來1天的收益率 df[target] df[price].shift(-1) / df[price] - 1 df df.dropna() # 特征和標(biāo)簽劃分 X df[[ret_1, ret_2, ret_3, ret_5]].values y df[target].values # 劃分訓(xùn)練集和測試集 split int(len(X) * 0.8) X_train, X_test X[:split], X[split:] y_train, y_test y[:split], y[split:] # 訓(xùn)練線性回歸模型 model LinearRegression() model.fit(X_train, y_train) # 預(yù)測測試集 y_pred model.predict(X_test) # 簡單判斷方向預(yù)測漲就買預(yù)測跌就賣 signal np.where(y_pred 0, 1, -1)這段代碼看著簡單但包含了完整流程造數(shù)據(jù)、做特征、設(shè)標(biāo)簽、分訓(xùn)練集測試集、訓(xùn)練模型、生成交易信號(hào)。我建議你一定要親手敲一遍而不是復(fù)制粘貼。敲的過程中你會(huì)注意到很多細(xì)節(jié)比如pct_change會(huì)產(chǎn)生NaN需要dropna比如shift(-1)才是“未來一天”方向搞反了整個(gè)模型就廢了。4.2 這個(gè)demo的局限它離“策略”還差得遠(yuǎn)p20這個(gè)demo說白了是個(gè)教學(xué)演示不是能實(shí)盤的東西。它沒有算交易成本沒有考慮資金管理也沒有做任何回測驗(yàn)證。線性回歸預(yù)測漲跌幅本身就是一個(gè)極弱的模型更別說只用過去幾天收益率當(dāng)特征這本質(zhì)上就是在預(yù)測一個(gè)隨機(jī)游走序列——理論上就賺不到錢。但它的意義在于把一個(gè)抽象的“量化機(jī)器學(xué)習(xí)流程”變成了具體可運(yùn)行的代碼。你可以改特征、換模型、調(diào)參數(shù)然后在同樣的數(shù)據(jù)上看效果變化這是理解整個(gè)系統(tǒng)的最高效路徑。我自己當(dāng)年就是把每個(gè)小demo都改一遍、折騰一遍才真正把流程刻進(jìn)腦子里的。4.3 特征工程初體驗(yàn)不是特征越多越好p16到p20雖然沒有展開講特征工程但demo里其實(shí)隱含了這個(gè)問題。上面代碼里我用了ret_1、ret_2、ret_3、ret_5四個(gè)特征它們之間高度相關(guān)——都基于同一個(gè)價(jià)格序列算出來的。特征之間的相關(guān)性高會(huì)對(duì)某些模型比如線性回歸的系數(shù)解釋造成干擾但這不代表模型完全不能用。新手做特征工程最大的誤區(qū)是堆特征覺得特征越多信息越多模型越準(zhǔn)。實(shí)際往往是反的冗余特征帶來噪聲增加過擬合風(fēng)險(xiǎn)拉慢訓(xùn)練速度。我的習(xí)慣是先用手里的數(shù)據(jù)做幾個(gè)有業(yè)務(wù)邏輯的特征跑一版看效果再逐步加特征對(duì)比驗(yàn)證每個(gè)特征是否真的在“增量”。這個(gè)方法論比特征本身重要得多。5. 常見問題與排查技巧實(shí)錄5.1 pandas的pct_change和shift方向搞混這是我自己第一批踩的坑也是我?guī)率謺r(shí)見的最多的錯(cuò)誤。pct_change是算當(dāng)前值相對(duì)前一個(gè)值的變化率方向是“過去 → 當(dāng)前”而shift(-1)是把整個(gè)序列往前移動(dòng)一格相當(dāng)于把未來的值放到現(xiàn)在的位置。做標(biāo)簽時(shí)要用shift(-1)把未來收益挪到當(dāng)前行做特征時(shí)用pct_change是取值過去的變化。我見過有人把標(biāo)簽方向弄反了模型訓(xùn)練出來預(yù)測結(jié)果和實(shí)際走勢恰好相反——預(yù)測漲的它跌、預(yù)測跌的它漲。但神奇的是如果忽略正負(fù)號(hào)只看絕對(duì)值模型“準(zhǔn)確率”還挺高。這種錯(cuò)誤最迷惑人因?yàn)槟銜?huì)覺得自己已經(jīng)做出來了只是效果不夠好于是開始調(diào)參、換特征折騰半天才發(fā)現(xiàn)方向反了。注意寫完特征和標(biāo)簽后先打印出最后幾行看一遍確認(rèn)“當(dāng)前行的特征是已知的標(biāo)簽是未來發(fā)生的”這是最便宜的驗(yàn)證方式。5.2 sklearn版本更新導(dǎo)致的代碼不兼容老視頻里的很多代碼在最新版sklearn下會(huì)報(bào)Warning甚至Error最典型的就是一些舊API被移除了。比如老代碼里可能有from sklearn.cross_validation import train_test_split這個(gè)模塊早就被移到sklearn.model_selection底下了。解決方法很簡單報(bào)錯(cuò)了就搜一下新API是什么別死磕舊代碼。順便說一句國內(nèi)訪問部分pip鏡像源不穩(wěn)定建議把源切到清華或者阿里云pip install -i https://pypi.tuna.tsinghua.edu.cn/simple scikit-learn pandas numpy或者一次性配置好pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple5.3 jupyter kernel連接不上這個(gè)問題在新手期太常見了。明明conda環(huán)境里裝了庫jupyter里import卻報(bào)錯(cuò)或者kernel直接死掉。原因通常是jupyter不是在當(dāng)前環(huán)境里啟動(dòng)的。解決辦法conda activate your_env conda install ipykernel python -m ipykernel install --user --name your_env --display-name your_env然后在jupyter界面里切換kernel到你剛注冊(cè)的環(huán)境。這個(gè)操作本質(zhì)上就是在告訴jupyter“每個(gè)kernel對(duì)應(yīng)哪個(gè)python環(huán)境別搞混了”。5.4 回測結(jié)果好得離譜先別高興看p20的demo如果你把策略的收益率曲線打印出來可能會(huì)發(fā)現(xiàn)“哇這策略太強(qiáng)了”。停一下先冷靜。這個(gè)demo沒有任何交易成本、沒有任何滑點(diǎn)假設(shè)它的“收益”是模型在測試集上預(yù)測方向和實(shí)際走勢一致的累計(jì)結(jié)果本質(zhì)上是在驗(yàn)證模型有沒有學(xué)到東西不是在證明這個(gè)策略能賺錢。真實(shí)的回測至少要包含手續(xù)費(fèi)和滑點(diǎn)、漲跌停無法成交的情況、停牌股的處理、信號(hào)產(chǎn)生到實(shí)際成交的時(shí)間差。這些p16到p20都沒涉及后面才會(huì)講到。所以你現(xiàn)在看任何回測曲線都默認(rèn)打上“理想化”三個(gè)字別上頭。6. 這4節(jié)課學(xué)完你該有什么狀態(tài)按我的理解p16到p20學(xué)完之后你不需要背下來任何算法原理也不需要記住所有函數(shù)參數(shù)。你只需要確認(rèn)自己能做到三件事第一能獨(dú)立搭建起jupyter環(huán)境知道在哪個(gè)環(huán)境里安裝了哪些庫。第二能看懂一行簡單的機(jī)器學(xué)習(xí)代碼在做什么——特征、標(biāo)簽、訓(xùn)練、預(yù)測這四個(gè)環(huán)節(jié)分別對(duì)應(yīng)哪段代碼。第三能跑通上面那個(gè)demo并且能動(dòng)手改一個(gè)特征或多個(gè)參數(shù)觀察結(jié)果怎么變。做到這三點(diǎn)這4節(jié)課就算真正吸收了。如果還要再進(jìn)一步我建議你試著用真實(shí)股票數(shù)據(jù)替換掉demo里的模擬數(shù)據(jù)把代碼里sklearn的LinearRegression換成其他模型比如隨機(jī)森林RandomForest或者邏輯回歸LogisticRegression你會(huì)發(fā)現(xiàn)同一個(gè)流程換個(gè)模型只需要改一兩行代碼但對(duì)整體流程的理解會(huì)深很多。最后再分享一個(gè)小經(jīng)驗(yàn)學(xué)量化機(jī)器學(xué)習(xí)最怕的不是數(shù)學(xué)差、代碼弱而是“看懂了但不動(dòng)手”。視頻里代碼一跑結(jié)果一出來你覺得“我懂了”關(guān)閉視頻三天后讓你自己寫大腦一片空白。所以我的習(xí)慣是每看完一小節(jié)先關(guān)掉視頻憑記憶手寫一遍代碼寫不出來的地方先空著最后再對(duì)照視頻補(bǔ)。這樣折騰幾輪代碼就是你自己的了。p21開始估計(jì)就要進(jìn)入真實(shí)的特征工程和策略優(yōu)化了這部分底子打好了后面會(huì)輕松很多。本文還有配套的精品資源點(diǎn)擊獲取