:機器學習策略demo從數(shù)據(jù)到回測全流程)
簡介這是一份面向具備一定Python基礎(chǔ)、對炒股與量化投資尚不熟悉的初學者打造的入門級demo源碼圍繞機器學習在A股量化策略中的應用展開幫助讀者快速理解數(shù)據(jù)收集、特征工程、模型構(gòu)建與回測評估的完整流程。資源包共14個文件以5個py腳本、6張png圖表、2個txt說明及1個gitignore為主Python文件分別承擔回測、特征處理、模型訓練與數(shù)據(jù)讀取等模塊職責圖片則直觀展示決策樹預測股價漲幅、最大回撤、K線走勢等關(guān)鍵結(jié)果壓縮包整體約727KB結(jié)構(gòu)清晰便于按模塊學習。目前已有156人學習下載。通過這份源碼讀者可對照運行從數(shù)據(jù)處理到策略回測的全流程觀察不同機器學習算法在價格預測中的表現(xiàn)并借助回測結(jié)果理解止損、倉位控制等風險管理思路為后續(xù)獨立編寫量化策略打下實踐基礎(chǔ)。1. 從一份能跑通的 A 股量化 demo 說起它到底解決了什么很多人第一次接觸量化投資卡住的地方不是不會寫 Python而是不知道一個完整策略從數(shù)據(jù)到回測到底長什么樣。網(wǎng)上搜「機器學習 量化投資策略」出來的要么是純理論推導要么是殘缺的代碼片段跑不起來也驗證不了。這份ai_qua2323weweer.zip就是沖著這個痛點來的——它把數(shù)據(jù)獲取、特征工程、模型訓練、回測評估串成了一條能跑通的鏈路用 A 股市場做樣本適合有 Python 基礎(chǔ)但對炒股和量化一無所知的人拿來拆解。壓縮包里除了main.py、backtest.py、feature.py、model.py、data.py這幾個核心腳本還附了柱狀圖、最大回撤、K 線圖、決策樹預測股價漲幅等運行截圖以及tushare_token.png提示你需要自己配數(shù)據(jù)源憑證。說白了它不是一個能直接拿去實盤的策略而是一個讓你看清「量化策略長什么樣」的腳手架。2. 拆開壓縮包五個 Python 文件各自扛什么活2.1 模塊分工與調(diào)用關(guān)系拿到源碼先別急著pip install花五分鐘把文件職責理清楚后面調(diào)參和排錯會省很多事。這個 demo 的結(jié)構(gòu)是典型的流水線式設(shè)計main.py是總調(diào)度其余四個模塊各管一段。文件職責關(guān)鍵輸入關(guān)鍵輸出data.py拉取 A 股歷史行情、清洗缺失值tushare token、股票代碼列表規(guī)整的 DataFramefeature.py從原始行情構(gòu)造技術(shù)指標特征行情 DataFrame特征矩陣 Xmodel.py構(gòu)建并訓練機器學習模型特征矩陣、標簽 y訓練好的模型對象backtest.py用歷史數(shù)據(jù)模擬買賣、算收益模型預測信號、價格序列收益曲線、最大回撤main.py串聯(lián)全流程以上全部回測報告與圖表stock_list.txt里放的是股票池requirements.txt鎖定了依賴版本.gitignore說明作者是按工程習慣組織的。img目錄下的截圖不是裝飾是你跑完后用來對照結(jié)果是否正常的參照物——比如最大回撤.png能幫你判斷回測邏輯有沒有寫反。2.2 環(huán)境準備與依賴安裝先確認 Python 版本這類 demo 一般跑在 3.8 到 3.10 之間比較穩(wěn)。建虛擬環(huán)境是基本操作別嫌麻煩血淚經(jīng)驗是直接在系統(tǒng)環(huán)境里裝依賴后面版本沖突能讓你重裝系統(tǒng)。# 創(chuàng)建并激活虛擬環(huán)境 python -m venv venv source venv/bin/activate # Windows 用 venv\Scripts\activate # 安裝依賴requirements.txt 里通常包含這些 pip install -r requirements.txtrequirements.txt里大概率會有pandas、numpy、scikit-learn、tushare、matplotlib這幾個。如果安裝tushare時報錯常見原因是網(wǎng)絡(luò)問題或版本過舊可以指定版本重試。裝完后用pip list核對一下重點看scikit-learn的版本因為不同版本里DecisionTreeClassifier的默認參數(shù)有差異會影響你復現(xiàn)截圖里的決策樹結(jié)果。2.3 數(shù)據(jù)源配置token 是繞不過去的門檻tushare_token.png這張截圖就是在提醒你數(shù)據(jù)獲取需要憑證。tushare 的免費額度對 demo 級別的回測夠用但需要注冊后拿到 token。# data.py 中通常會有類似這樣的初始化代碼 import tushare as ts # 把這里的 token 替換成你自己的 ts.set_token(你的tushare_token) pro ts.pro_api() # 拉取單只股票日線數(shù)據(jù) df pro.daily(ts_code000001.SZ, start_date20200101, end_date20231231)邏輯說明set_token只需調(diào)用一次之后pro_api()返回的接口對象可以復用。daily接口返回的是未復權(quán)數(shù)據(jù)做量化回測時要注意復權(quán)問題否則除權(quán)除息日會出現(xiàn)價格跳空導致特征失真。參數(shù)上ts_code的格式是「代碼.交易所」000001.SZ是深交所600000.SH是上交所。如果你拉數(shù)據(jù)返回空 DataFrame先檢查 token 是否過期再確認股票代碼格式和日期范圍。3. 特征工程與模型訓練把行情變成模型能吃的數(shù)字3.1 從價格序列構(gòu)造有效特征原始行情只有開高低收和成交量直接丟給模型效果很差。feature.py的核心任務就是把這些序列轉(zhuǎn)成有預測意義的特征。常見做法是構(gòu)造動量類、波動率類、成交量類指標。# feature.py 中特征構(gòu)造的典型寫法 import pandas as pd import numpy as np def build_features(df): df df.sort_values(trade_date).reset_index(dropTrue) # 動量特征過去 5 日、10 日收益率 df[ret_5] df[close].pct_change(5) df[ret_10] df[close].pct_change(10) # 波動率特征過去 10 日收益率標準差 df[vol_10] df[close].pct_change().rolling(10).std() # 成交量特征當日成交量與 5 日均量之比 df[vol_ratio] df[vol] / df[vol].rolling(5).mean() # 標簽未來 5 日漲跌方向漲為 1 跌為 0 df[label] (df[close].shift(-5) df[close]).astype(int) df df.dropna() return df邏輯說明pct_change(5)算的是 5 日累計收益率反映中期動量。rolling(10).std()衡量波動率波動率放大往往伴隨趨勢轉(zhuǎn)折。vol_ratio捕捉放量行為放量突破在 A 股里是比較有效的信號。標簽用shift(-5)構(gòu)造未來 5 日方向注意這會造成最后 5 行標簽為 NaN必須dropna掉否則訓練時會報錯。參數(shù)上窗口期不是固定的5 日和 10 日只是 demo 默認值你可以改成 3 日或 20 日觀察模型表現(xiàn)變化。3.2 決策樹模型的訓練與調(diào)參model.py里用的是決策樹截圖決策樹預測股價漲幅.png就是它的輸出。選決策樹而不是神經(jīng)網(wǎng)絡(luò)是因為它可解釋性強能直接看到哪些特征重要對入門者友好。# model.py 中模型訓練的核心代碼 from sklearn.tree import DecisionTreeClassifier from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score def train_model(df): feature_cols [ret_5, ret_10, vol_10, vol_ratio] X df[feature_cols] y df[label] # 按時間順序切分不能隨機打亂 split int(len(X) * 0.8) X_train, X_test X[:split], X[split:] y_train, y_test y[:split], y[split:] clf DecisionTreeClassifier( max_depth4, # 控制樹深防止過擬合 min_samples_leaf50, # 葉子節(jié)點最少樣本數(shù) random_state42 ) clf.fit(X_train, y_train) pred clf.predict(X_test) print(測試集準確率:, accuracy_score(y_test, pred)) return clf邏輯說明時間序列數(shù)據(jù)絕對不能隨機切分train_test_split默認的 shuffle 會把未來信息泄露到訓練集導致回測虛高這是新手最容易翻車的地方。max_depth4是刻意壓低的決策樹不加限制可以無限生長訓練集準確率能到 99% 但測試集一塌糊涂。min_samples_leaf50保證每個葉子有足夠樣本支撐避免模型記住噪聲。如果你把max_depth調(diào)到 10 以上大概率會看到訓練準確率飆升但回測收益反而下降這就是過擬合的典型表現(xiàn)。3.3 回測邏輯別讓未來函數(shù)毀掉結(jié)果backtest.py是整個 demo 最需要盯緊的部分?;販y的核心是模擬「如果當時按信號操作收益會怎樣」但很容易寫出用到未來數(shù)據(jù)的代碼。# backtest.py 中簡化的回測循環(huán) def run_backtest(df, model): df df.copy() df[signal] model.predict(df[[ret_5, ret_10, vol_10, vol_ratio]]) # 信號滯后一期避免用當日收盤信號做當日交易 df[position] df[signal].shift(1) # 當日收益率 df[daily_ret] df[close].pct_change() # 策略收益 持倉信號 × 次日收益 df[strategy_ret] df[position] * df[daily_ret] # 累計凈值 df[cum_ret] (1 df[strategy_ret]).cumprod() # 最大回撤 df[peak] df[cum_ret].cummax() df[drawdown] (df[cum_ret] - df[peak]) / df[peak] max_dd df[drawdown].min() print(累計收益:, df[cum_ret].iloc[-1] - 1) print(最大回撤:, max_dd) return df邏輯說明shift(1)是關(guān)鍵一步它保證你今天看到的信號明天才執(zhí)行模擬真實交易中「收盤后算信號、次日開盤操作」的節(jié)奏。如果不加這個滯后等于用當天收盤價預測當天漲跌再當天買賣回測收益會好得不真實。cumprod()算累計凈值cummax()算歷史高點兩者相除得到回撤序列。最大回撤是負數(shù)越接近 0 越好。跑完后對照最大回撤.png如果你的回撤超過 -50%要么是模型有問題要么是回測邏輯寫錯了。4. 避坑與排查跑不通、結(jié)果離譜時先看這幾條4.1 現(xiàn)象tushare 返回空數(shù)據(jù)或報權(quán)限錯誤原因通常有三個token 沒設(shè)置、token 過期、或者調(diào)用的接口超出免費額度。解決方法是先打印ts.get_token()確認 token 已寫入再去 tushare 官網(wǎng)看接口權(quán)限說明。免費賬戶對daily接口有頻率限制短時間內(nèi)大量拉取會被臨時封禁建議在循環(huán)里加time.sleep(0.5)。4.2 現(xiàn)象回測收益高得離譜年化幾百個百分點這是典型的未來函數(shù)問題。檢查backtest.py里信號有沒有做shift檢查特征構(gòu)造時有沒有用到當日收盤之后才知道的數(shù)據(jù)。另一個隱蔽的坑是標簽構(gòu)造用了shift(-5)但特征里不小心混入了未來信息。解決方法是把回測信號整體滯后一期并且用樣本外數(shù)據(jù)驗證。4.3 現(xiàn)象決策樹準確率 99% 但實盤邏輯不成立原因幾乎一定是過擬合。決策樹不加max_depth和min_samples_leaf限制可以無限分裂直到每個葉子只有一個樣本訓練集完美擬合但毫無泛化能力。解決方法是在model.py里把樹深壓到 3 到 5 層葉子最小樣本數(shù)設(shè)到 30 以上然后觀察測試集準確率是否在 50% 到 60% 之間——這個區(qū)間對股票方向預測才是正常的。4.4 現(xiàn)象matplotlib 畫圖中文顯示成方塊原因是默認字體不支持中文。在main.py或畫圖腳本開頭加兩行配置即可。import matplotlib.pyplot as plt plt.rcParams[font.sans-serif] [SimHei] # Windows 用黑體 plt.rcParams[axes.unicode_minus] False # 正常顯示負號Mac 系統(tǒng)把SimHei換成Arial Unicode MS。改完如果還不行清一下 matplotlib 的字體緩存再重跑。4.5 現(xiàn)象requirements.txt 安裝時報版本沖突常見于pandas和numpy版本不匹配。解決方法是先裝numpy再裝pandas或者直接用pip install -r requirements.txt --no-deps跳過依賴解析手動補齊缺失的包。如果scikit-learn版本和 demo 作者不一致導致 API 報錯查一下你裝的版本里DecisionTreeClassifier的參數(shù)名有沒有變多數(shù)情況向下兼容。5. 進階玩法把 demo 改成你自己的策略實驗臺跑通默認流程只是起點這個 demo 真正的價值在于它給你留了改的空間。我一般會從三個方向動手換模型、換特征、換股票池。換模型最直接。model.py里把DecisionTreeClassifier換成RandomForestClassifier或GradientBoostingClassifier接口幾乎不用改但要注意隨機森林的n_estimators別設(shè)太大100 到 200 棵足夠再多訓練時間線性增長而收益提升有限。換成LogisticRegression的話記得先對特征做標準化否則量綱差異會讓系數(shù)失去意義。換特征需要回到feature.py。demo 里只用了動量和波動率你可以加均線交叉、RSI、MACD 柱狀圖斜率這些經(jīng)典指標。但每加一個特征都要問自己這個特征在交易時點是否可得如果用了未來數(shù)據(jù)回測再好看也是自欺欺人。我習慣每加三個特征就跑一次回測對比最大回撤和收益曲線避免一次性堆太多導致無法歸因。換股票池是最容易被低估的一步。stock_list.txt里如果只有幾只股票結(jié)論沒有統(tǒng)計意義。常見做法是拉滬深 300 成分股對每只股票單獨訓練模型再匯總信號或者把所有股票數(shù)據(jù)拼在一起訓練一個通用模型。前者更穩(wěn)健但計算量大后者訓練快但容易忽略個股差異。我一般先用 20 只股票做快速驗證確認流程沒問題再擴到全市場。驗證方法上除了看累計收益和最大回撤建議加一個基準對比——比如買入持有滬深 300 ETF 的收益曲線。如果你的策略跑不贏基準那模型再復雜也沒有意義。這個對比圖我每次都會畫它比任何單一指標都更能說明問題。從那以后我每次拿到新的量化 demo都強制先跑一遍默認參數(shù)、記下基準結(jié)果再動任何一行代碼。這樣后面改出問題時至少知道是改壞了還是本來就這樣。希望幫到你。本文還有配套的精品資源點擊獲取