據(jù)清洗到策略回測的完整知識地圖)
簡介這份Python股票量化投資課程配套課件定位為零基礎(chǔ)到進(jìn)階的量化交易學(xué)習(xí)資料面向想用Python進(jìn)行金融數(shù)據(jù)分析、策略構(gòu)建與自動化交易的學(xué)員可系統(tǒng)補(bǔ)齊編程、數(shù)據(jù)、策略、回測、風(fēng)控與機(jī)器學(xué)習(xí)全鏈路能力。資源壓縮包共142個(gè)文件、約56.91MB核心是85個(gè).py可運(yùn)行腳本與21個(gè).pyc編譯文件配合9個(gè).csv股票行情數(shù)據(jù)、12個(gè).xml配置、3個(gè).zip依賴包及若干說明文檔形成從數(shù)據(jù)到代碼的完整配套。目前已有2393人學(xué)習(xí)下載是被量化初學(xué)者反復(fù)參考的一套課件。內(nèi)容覆蓋Pandas/NumPy數(shù)據(jù)處理、Matplotlib可視化、Yahoo Finance等數(shù)據(jù)獲取、移動均線與布林帶指標(biāo)、Backtrader回測、經(jīng)紀(jì)商API自動交易、止損與資金管理以及機(jī)器學(xué)習(xí)預(yù)測實(shí)戰(zhàn)壓縮包內(nèi)還提供A股歷史行情CSV與選股數(shù)據(jù)詳細(xì)說明便于直接運(yùn)行演練從數(shù)據(jù)讀取到策略回測一氣呵成。1. 量化投資的知識地圖Python、股票與策略怎么接起來很多人學(xué) Python 股票量化投資會遇到同一個(gè)卡點(diǎn)語法書看了兩遍但不知道整條路怎么走。課程配套課件的價(jià)值不是把某個(gè)指標(biāo)公式貼出來而是把量化交易從頭到尾拆成一條可執(zhí)行的生產(chǎn)鏈路數(shù)據(jù)獲取與清洗、因子計(jì)算、策略信號、回測驗(yàn)證、績效歸因、風(fēng)險(xiǎn)控制。這條鏈路里數(shù)據(jù)是地基因子是武器回測是照妖鏡風(fēng)險(xiǎn)控制則是活下來的前提。這份課件適合兩類人一是已經(jīng)掌握 Python 基礎(chǔ)、想系統(tǒng)進(jìn)入量化交易方向的學(xué)習(xí)者二是做過簡單回測但總被“回測很漂亮、實(shí)盤很慘淡”困擾的復(fù)習(xí)者。復(fù)習(xí)時(shí)不需要逐條重讀公式只要抓住主線就能判斷自己漏在哪一環(huán)。把整門課想象成一條流水線位置越靠前錯誤越致命數(shù)據(jù)一旦帶錯后面所有因子和回測都是空中樓閣。知識地圖的順序就是復(fù)習(xí)的順序。2. 數(shù)據(jù)是第一關(guān)行情、財(cái)務(wù)與預(yù)處理怎么做進(jìn)入量化學(xué)習(xí)后的第一個(gè)“勸退點(diǎn)”通常是數(shù)據(jù)。很多人以為拿到收盤價(jià)就能開始算信號結(jié)果在處理復(fù)權(quán)、停牌、公告日期時(shí)不斷翻車。梳理下來會發(fā)現(xiàn)數(shù)據(jù)層解決的問題就三個(gè)拿什么數(shù)據(jù)、數(shù)據(jù)長什么樣、哪些數(shù)據(jù)不能直接用于回測。2.1 先想清楚行情數(shù)據(jù)要什么樣的列結(jié)構(gòu)和頻率規(guī)范的行情表不是 Excel 那樣的寬表格而是長表。每一行對應(yīng)一個(gè)股票在一個(gè)交易日的記錄核心字段包括字段含義注意事項(xiàng)symbol股票代碼統(tǒng)一格式不要混用帶前綴和不帶前綴date交易日期必須是datetime類型不要用字符串open / high / low / close開高低收復(fù)權(quán)前或復(fù)權(quán)后要統(tǒng)一volume成交量確認(rèn)單位是“股”還是“手”amount成交額做流動性過濾時(shí)很有用拿到數(shù)據(jù)后的第一步不是畫 K 線而是做排序、去重、類型修正import pandas as pd df pd.read_csv(daily.csv, parse_dates[date]) df df.sort_values([symbol, date]).reset_index(dropTrue) df df.drop_duplicates(subset[symbol, date], keeplast) df[ret] df.groupby(symbol)[close].pct_change()代碼里最關(guān)鍵的是pct_change()它計(jì)算的是相鄰兩行之間的收益率。若中間有缺失交易日它不會自動跳過缺失行而是在出現(xiàn) NaN 的位置直接給到缺失收益。更嚴(yán)謹(jǐn)?shù)淖龇ㄊ窍扔媒灰兹諝v對齊再決定填充策略。頻率上日線足夠覆蓋選股和低頻擇時(shí)分鐘線適合日內(nèi)策略但初期不建議直接上分鐘級先跑通日線再說。2.2 復(fù)權(quán)口徑前復(fù)權(quán)、后復(fù)權(quán)與回測的對應(yīng)關(guān)系復(fù)權(quán)問題是數(shù)據(jù)層最大的坑。除權(quán)除息會讓價(jià)格出現(xiàn)人為跳空如果不復(fù)權(quán)收益率的計(jì)算就會失真。前復(fù)權(quán)以最近價(jià)格為基準(zhǔn)調(diào)整歷史價(jià)格適合看圖后復(fù)權(quán)以最早日期為基準(zhǔn)適合計(jì)算真實(shí)收益率?;販y中計(jì)算信號和收益率應(yīng)該統(tǒng)一使用后復(fù)權(quán)價(jià)格否則分紅次數(shù)多的股票會被系統(tǒng)誤判為暴跌。代碼里通常這樣處理df[adj_close] df[close] * df[adj_factor] df[ret_adj] df.groupby(symbol)[adj_close].pct_change()adj_factor是行情源提供的復(fù)權(quán)因子它通常是累乘的拿來直接乘原始收盤價(jià)即可。最容易漏的一點(diǎn)是前復(fù)權(quán)價(jià)格會隨著新行情發(fā)布而整體變化今天算出的前復(fù)權(quán)歷史值和下周算出的不一樣。因此研究過程中的數(shù)據(jù)快照要固定版本不要每次回測都重新下載否則回測結(jié)果無法復(fù)現(xiàn)。2.3 預(yù)處理三坑缺失值、停牌、零成交缺失值不能無腦刪除也不能無腦前向填充。停牌期間沒有成交本來就該沒有價(jià)格記錄如果你用ffill()把上一交易日的價(jià)格延續(xù)到停牌日回測引擎就會在停牌日“假裝”成交這是典型的隱性未來函數(shù)。正確處理是保留交易狀態(tài)信息df[tradable] df[volume] 0 df[can_buy] df[tradable] (df[ret] 0.095) df[can_sell] df[tradable] (df[ret] -0.095)這里用漲跌幅近似過濾漲跌停無法買入賣出的情況漲幅接近 10% 時(shí)買單大概率無法成交跌幅接近 10% 時(shí)賣單大概率無法成交。閾值是示意創(chuàng)業(yè)板、科創(chuàng)板需要換擋。更準(zhǔn)確的方案是讓行情源直接提供漲跌停價(jià)格字段計(jì)算前先判斷當(dāng)日能否成交。2.4 財(cái)務(wù)數(shù)據(jù)不能用報(bào)告期對齊用公告日期年報(bào)、季報(bào)發(fā)布存在明顯滯后。如果只按“報(bào)告期”把財(cái)務(wù)數(shù)據(jù)和行情合并等于在 4 月末就使用了 3 月末才發(fā)布的季報(bào)數(shù)據(jù)這在回測里是未來函數(shù)。正確做法是以公告日期為信息生效日讓因子在公告發(fā)布之后才“看見”數(shù)據(jù)。fin fin.sort_values(anno_date) price price.sort_values(date) merged pd.merge_asof( price.sort_values(date), fin, left_ondate, right_onanno_date, bysymbol, directionbackward, )merge_asof會為每個(gè)交易日找到最近一次已經(jīng)公告的財(cái)務(wù)數(shù)據(jù)directionbackward表示只取早于或等于當(dāng)前日期的記錄。這個(gè)方向一旦寫反就變成了未來數(shù)據(jù)。數(shù)據(jù)層最后應(yīng)該有一份自查腳本檢查每個(gè)股票的最短歷史長度、缺失值比例、復(fù)權(quán)因子是否單調(diào)以及merge_asof之后是否有空值。數(shù)據(jù)沒有問題后面的策略才有討論意義。3. 指標(biāo)與因子從均線到多因子選股的轉(zhuǎn)化策略層是另一個(gè)學(xué)習(xí)分水嶺。很多人以為把 MACD、RSI、布林帶湊在一起就是量化策略實(shí)際上技術(shù)指標(biāo)只是信號的一種來源。更系統(tǒng)的做法是先理解指標(biāo)的計(jì)算口徑再從單因子到多因子一步步建立選股邏輯。3.1 技術(shù)指標(biāo)的計(jì)算口徑均線、MACD、布林帶指標(biāo)計(jì)算在 Pandas 里幾乎是模板化操作但有一個(gè)共性要求按股票分組后計(jì)算不能把不同股票混在一個(gè)序列里滾動。df df.sort_values([symbol, date]) df[ma5] df.groupby(symbol)[adj_close].transform( lambda x: x.rolling(5).mean() ) ema12 df.groupby(symbol)[adj_close].transform( lambda x: x.ewm(span12).mean() ) ema26 df.groupby(symbol)[adj_close].transform( lambda x: x.ewm(span26).mean() ) df[macd] ema12 - ema26 df[macd_signal] df.groupby(symbol)[macd].transform( lambda x: x.ewm(span9).mean() )transform的作用是讓計(jì)算結(jié)果保持原索引對齊不會因?yàn)榉纸M而打亂行序。滾動窗口的前 N 行一定會產(chǎn)生 NaN后續(xù)生成信號前必須dropna()否則 NaN 會被當(dāng)成空倉或買入信號。布林帶就是均線加減兩倍標(biāo)準(zhǔn)差核心不是指標(biāo)本身而是“突破”和“回歸”兩種狀態(tài)分別對應(yīng)趨勢策略和均值回歸策略。同一個(gè)指標(biāo)放在不同市場狀態(tài)下含義完全不同。3.2 因子與未來收益IC、分組回測與因子方向因子的本質(zhì)是排序工具。它不直接告訴你買什么而是告訴你哪些股票應(yīng)該排在前面。判斷一個(gè)因子有沒有效不能只看收益曲線要看因子值和未來收益之間的單調(diào)關(guān)系。信息系數(shù) IC 是因子與未來 N 期收益的相關(guān)系數(shù)通常用 Spearman 秩相關(guān)計(jì)算from scipy import stats def factor_ic(df, factor_col, fwd_ret_col): ic_by_date df.groupby(date).apply( lambda g: stats.spearmanr(g[factor_col], g[fwd_ret_col])[0] ) return ic_by_date.mean(), ic_by_date.std() ic_mean, ic_std factor_ic(df, zscore, fwd_ret_5) icir ic_mean / ic_std * np.sqrt(52)IC 均值為正且穩(wěn)定說明因子有預(yù)測力ICIR 是經(jīng)波動調(diào)整后的指標(biāo)用來判斷因子穩(wěn)定性。只看 IC 均值不夠一個(gè)因子可能均值很高但方向經(jīng)常反轉(zhuǎn)實(shí)盤根本無法信任。更直觀的驗(yàn)證是分組回測把每日股票按因子值分成 5 組每組建倉后持有 N 天觀察收益是否隨因子值單調(diào)變化。如果第 3 組收益最高、第 1 組次之、第 5 組最低因子很可能只是噪聲而不是有效排序。3.3 多因子合成標(biāo)準(zhǔn)化、中性化與合成單因子容易失效多因子合成可以分散風(fēng)險(xiǎn)但前提是合成方法正確。不同因子的量綱不同直接相加等于給量綱大的因子更高權(quán)重。正確做法是先在每個(gè)交易日截面上做標(biāo)準(zhǔn)化。df[zscore] df.groupby(date)[factor].transform( lambda x: (x - x.mean()) / x.std() )標(biāo)準(zhǔn)化之后還要做行業(yè)中性化。如果一個(gè)因子只是選出了某個(gè)行業(yè)的一堆股票那它捕捉的可能不是 alpha而是行業(yè) beta。最簡單的中性化是減去行業(yè)均值df[factor_neutral] ( df.groupby([date, industry])[zscore] .transform(lambda x: x - x.mean()) )行業(yè)分組股票數(shù)量太少時(shí)組內(nèi)均值會不穩(wěn)定這時(shí)可以考慮行業(yè)啞變量回歸取殘差。市值中性化思路類似把因子值對市值做回歸用殘差代替原始因子值。中性化不是可選項(xiàng)而是多因子研究的標(biāo)準(zhǔn)動作。跳過這一步后面所有分析結(jié)果都會帶上一層隱性的行業(yè)或市值風(fēng)格。3.4 從因子到策略打分、選股與擇時(shí)的配合單因子研究最終要落到一籃子股票。常見的落地方案是每個(gè)調(diào)倉日按因子 zscore或中性化后分值排序取前 N 只等權(quán)買入持有到下一個(gè)調(diào)倉日。這里面有兩個(gè)容易被忽略的量調(diào)倉頻率和換手成本。signal df.sort_values([date, zscore], ascending[True, False]) signal signal.groupby(date).head(20) targets signal[[date, symbol]].copy()每天調(diào)倉會讓手續(xù)費(fèi)和滑點(diǎn)吃掉大量收益更常見的是周頻或月頻調(diào)倉。技術(shù)指標(biāo)如指數(shù)均線可以作為擇時(shí)過濾條件市場整體處于下跌趨勢時(shí)降低倉位或空倉這比單獨(dú)使用某一種指標(biāo)更穩(wěn)健。到這里一個(gè)完整的策略已經(jīng)從“數(shù)據(jù)”走到了“信號”下一步是回測驗(yàn)證。4. 回測引擎與績效分析別讓圖表騙了你回測是量化學(xué)習(xí)中最容易被“自欺”的環(huán)節(jié)。初學(xué)者看到一段漂亮的凈值曲線就以為策略有效實(shí)際上回測框架的一個(gè)小錯誤可能讓結(jié)果嚴(yán)重失真。這一章從最小回測框架開始把績效指標(biāo)和常見偏差一起理清。4.1 最小可用的回測框架逐筆結(jié)算還是逐 bar 結(jié)算最簡單的回測邏輯是在每個(gè)交易日先結(jié)算持倉市值再按信號決定買賣。from dataclasses import dataclass dataclass class Position: symbol: str shares: int def run_backtest(daily, select_func, initial_cash1_000_000): cash initial_cash positions [] timeline sorted(daily[date].unique()) for date in timeline: today daily[daily[date] date] for pos in positions: px today.loc[today[symbol] pos.symbol, close].values if len(px) 0: pos.last_price px[0] targets select_func(today) # 先賣后買簡化處理但要有滑點(diǎn)與手續(xù)費(fèi) for pos in list(positions): if pos.symbol not in targets: cash pos.shares * today.loc[ today[symbol] pos.symbol, close ].iloc[0] positions.remove(pos) for symbol in targets: if symbol not in [p.symbol for p in positions]: price today.loc[today[symbol] symbol, close].iloc[0] shares int(cash * 0.1 // price) cash - shares * price positions.append(Position(symbolsymbol, sharesshares)) equity cash sum(p.shares * p.last_price for p in positions) yield date, equity這個(gè)框架里至少有兩個(gè)問題需要明確第一這里用“當(dāng)日收盤信號、當(dāng)日收盤價(jià)成交”在嚴(yán)格回測中屬于前視偏差相當(dāng)于你看到了收盤價(jià)才決定買入?yún)s又按收盤價(jià)成交第二沒有手續(xù)費(fèi)和滑點(diǎn)收益會虛高。更穩(wěn)妥的做法是信號在收盤后產(chǎn)生成交放在次日開盤價(jià)??蚣芸梢韵群喓髧?yán)但心里要清楚它偏樂觀。4.2 績效指標(biāo)的計(jì)算口徑年化、最大回撤、夏普比率凈值曲線出來后第一件事不是畫圖而是算四個(gè)核心指標(biāo)。equity pd.Series([e for _, e in results], index[d for d, _ in results]) daily_ret equity.pct_change().dropna() total_ret equity.iloc[-1] / equity.iloc[0] - 1 days len(equity) annual_ret (1 total_ret) ** (252 / days) - 1 roll_max equity.cummax() drawdown equity / roll_max - 1 max_dd drawdown.min() excess daily_ret - 0.02 / 252 # 假設(shè)無風(fēng)險(xiǎn)年化2% sharpe np.sqrt(252) * excess.mean() / excess.std()年化收益率不是簡單地把總收益除以年數(shù)而是按 252 個(gè)交易日做復(fù)利折算。最大回撤要看凈值峰值到谷底的跌幅而不是只看某一段收益波動。夏普比率對異常值非常敏感日收益標(biāo)準(zhǔn)差偏小時(shí)夏普會被算得異常高最好同時(shí)看最大回撤和收益回撤比。指標(biāo)計(jì)算口徑常見錯誤年化收益率對總收益做 252 日復(fù)利折算直接總收益/年份最大回撤凈值峰值到后續(xù)最低點(diǎn)的最大跌幅用收益率序列代替凈值夏普比率日超額收益均值/標(biāo)準(zhǔn)差 再年化忘記減無風(fēng)險(xiǎn)利率勝率盈利交易次數(shù)/總交易次數(shù)勝率高但盈虧比很低盈虧比平均盈利/平均虧損單獨(dú)使用容易誤判4.3 回測偏差自查清單回測結(jié)果異常漂亮?xí)r先別高興按下面的清單逐一排查。第一幸存者偏差。股票池只包含“今天還活著”的股票歷史上已經(jīng)退市的股票被排除在外回測自然會偏向樂觀。復(fù)盤時(shí)要加入歷史退市股或者用全量歷史成分股。第二前視偏差。未來數(shù)據(jù)進(jìn)入了信號計(jì)算比如用當(dāng)日收盤價(jià)生成當(dāng)日信號再按當(dāng)日收盤價(jià)成交。排查方式是檢查所有信號計(jì)算中使用的數(shù)據(jù)是否都在信號生成時(shí)刻之前。第三過擬合。策略參數(shù)反復(fù)調(diào)整到與歷史完美匹配換一段樣本外數(shù)據(jù)立刻失效。應(yīng)對方法是做滾動訓(xùn)練測試或用參數(shù)敏感性分析觀察鄰近參數(shù)下績效是否劇烈波動。第四成本缺失。雙邊手續(xù)費(fèi)、印花稅、滑點(diǎn)全部設(shè)為 0高頻調(diào)倉策略在回測里會顯得異常優(yōu)秀。實(shí)際回測至少應(yīng)計(jì)入雙邊萬三到千一的手續(xù)費(fèi)以及一個(gè)最小滑點(diǎn)。5. 最該警惕的易錯點(diǎn)量化交易里的“黑匣子”陷阱學(xué)完數(shù)據(jù)、因子和回測之后靠前的坑大多能避開但有一些錯誤藏在代碼細(xì)節(jié)里屬于“看著沒問題跑起來全錯”的類型。梳理整個(gè)課程內(nèi)容我總結(jié)出五個(gè)最容易漏掉、也最值得反復(fù)檢查的易錯點(diǎn)。5.1 未來函數(shù)回測悄悄用了未來的數(shù)據(jù)易漏點(diǎn)信號生成時(shí)沒有注意數(shù)據(jù)的時(shí)間邊界最常見的是“用當(dāng)日收盤價(jià)計(jì)算信號再用當(dāng)日收盤價(jià)成交”。為什么漏因?yàn)橹鹦刑幚頃r(shí)同一行里既有價(jià)格又有信號代碼不會報(bào)錯邏輯上也渾然不覺。尤其是在計(jì)算因子時(shí)如果因子值來自未來 N 天的收益那整個(gè)回測都是自欺欺人。怎么補(bǔ)寫一個(gè)統(tǒng)一的工具函數(shù)把所有信號統(tǒng)一到“信號生成日”的次日處理。每次回測前做一次數(shù)據(jù)泄漏檢查把因子值隨機(jī)打亂如果績效不變差說明原有因子可能是噪聲如果把因子滯后一天后績效顯著變差就要警惕未來函數(shù)。簡單有效。5.2 復(fù)權(quán)口徑混用前復(fù)權(quán)數(shù)據(jù)算收益率后復(fù)權(quán)數(shù)據(jù)算信號易漏點(diǎn)同一套代碼里歷史價(jià)格有的來自前復(fù)權(quán)接口有的來自后復(fù)權(quán)接口兩者混用會導(dǎo)致除權(quán)日附近的信號和收益無法對齊。為什么漏因?yàn)榍皬?fù)權(quán)價(jià)格會隨時(shí)間變化今天下載的歷史前復(fù)權(quán)價(jià)格和下周下載的可能不同。如果研究過程跨越多次數(shù)據(jù)更新復(fù)現(xiàn)結(jié)果就會悄悄改變。怎么補(bǔ)建立研究數(shù)據(jù)快照整個(gè)實(shí)驗(yàn)周期內(nèi)固定使用同一份數(shù)據(jù)計(jì)算收益統(tǒng)一用復(fù)權(quán)因子看行情圖才用前復(fù)權(quán)。如果條件允許直接在后復(fù)權(quán)價(jià)格上完成全部計(jì)算。5.3 手續(xù)費(fèi)和滑點(diǎn)設(shè)為零低換手策略也會“虛胖”易漏點(diǎn)回測里把交易成本設(shè)為 0策略年化收益看著很高實(shí)盤一執(zhí)行就縮水。為什么漏因?yàn)槌鯇W(xué)者通常先用簡單框架驗(yàn)證思路忽略了每筆交易的摩擦成本。尤其是多因子周頻調(diào)倉策略每次調(diào)倉一籃子股票換手率很容易超過 100%成本會被快速放大。怎么補(bǔ)回測框架至少內(nèi)置一個(gè)cost_model參數(shù)買入收萬二傭金賣出收萬二傭金加千一印花稅滑點(diǎn)按固定金額或固定比例計(jì)入。調(diào)倉頻率越高成本模型越要精細(xì)。在策略篩選階段可以直接看“扣除成本后的收益”不要看毛收益。5.4 股票池里的幸存者偏差退市股被悄悄丟掉了易漏點(diǎn)從某個(gè)“當(dāng)前存活股票列表”里取股票池歷史回測自然只包含現(xiàn)在還在的公司退市股票全部缺失。為什么漏因?yàn)榇蠖鄶?shù)行情源默認(rèn)只提供當(dāng)前可交易的股票歷史停牌和退市記錄需要額外接口補(bǔ)齊。很多人不知道這一點(diǎn)導(dǎo)致回測結(jié)果天然偏高。怎么補(bǔ)回測的股票池要使用歷史時(shí)點(diǎn)的成分股全集至少包含當(dāng)時(shí)存在過的所有股票代碼??梢杂猛耸泄闪斜砘靥顢?shù)據(jù)源或者在研究報(bào)告中明確標(biāo)注“僅包含當(dāng)前存續(xù)股票”并接受這個(gè)偏差。復(fù)習(xí)時(shí)這一條直接決定回測結(jié)論是否可信。5.5 時(shí)間切分錯誤隨機(jī)劃分訓(xùn)練集和測試集易漏點(diǎn)做因子測試時(shí)把歷史數(shù)據(jù)隨機(jī)切分一部分當(dāng)訓(xùn)練集、一部分當(dāng)測試集導(dǎo)致同一時(shí)間段的數(shù)據(jù)既參與訓(xùn)練又參與驗(yàn)證。為什么漏因?yàn)橥ㄓ脵C(jī)器學(xué)習(xí)的交叉驗(yàn)證習(xí)慣是隨機(jī)劃分但金融數(shù)據(jù)是強(qiáng)序列相關(guān)的時(shí)間序列隨機(jī)切分會讓模型“偷看”到未來數(shù)據(jù)的信息。怎么補(bǔ)金融場景必須按時(shí)間順序切分前 70% 做訓(xùn)練后 30% 做樣本外測試更嚴(yán)格的做法是滾動訓(xùn)練每次只用過去一段窗口訓(xùn)練然后預(yù)測下一段。課程里反復(fù)強(qiáng)調(diào)這一點(diǎn)因?yàn)樗苯記Q定了因子測試結(jié)論能不能外推到實(shí)盤。6. 復(fù)習(xí)清單從頭到尾復(fù)盤量化知識樹的 12 個(gè)問題把課件重新過一遍時(shí)最有效的不是重讀全部代碼而是按清單逐個(gè)回答“你能不能做到”。以下這 12 個(gè)問題覆蓋了數(shù)據(jù)、因子、回測三個(gè)階段的關(guān)鍵能力。模塊復(fù)習(xí)問題完成標(biāo)準(zhǔn)數(shù)據(jù)能否把原始數(shù)據(jù)整理成規(guī)范長表排序、去重、類型修正無報(bào)錯數(shù)據(jù)能否說明前復(fù)權(quán)與后復(fù)權(quán)的區(qū)別能說清回測用哪一檔、實(shí)盤看哪一檔數(shù)據(jù)能否正確處理停牌與缺失值回測中不會出現(xiàn)停牌日成交數(shù)據(jù)能否用公告日期合并財(cái)務(wù)數(shù)據(jù)merge_asof方向正確且無未來信息因子能否獨(dú)立計(jì)算均線、MACD、布林帶分組計(jì)算、不混股票因子能否計(jì)算 IC 和 ICIR能解釋因子是否穩(wěn)定有效因子能否做截面標(biāo)準(zhǔn)化和行業(yè)中性化知道為什么要先標(biāo)準(zhǔn)化再合成策略能否把因子變成一個(gè)調(diào)倉方案有明確的調(diào)倉頻率和持倉數(shù)量回測能否寫出最小回測框架信號與成交分離回測能否計(jì)算年化、回撤、夏普公式口徑正確回測能否識別未來函數(shù)能說出至少三個(gè)泄漏場景回測是否計(jì)入手續(xù)費(fèi)和滑點(diǎn)回測績效為扣除成本后的結(jié)果查漏補(bǔ)缺的方法也很直接先跑一遍數(shù)據(jù)層自查腳本再跑一個(gè)單因子 IC 分析最后跑一次完整回測。哪個(gè)環(huán)節(jié)報(bào)錯或結(jié)果異常就回到對應(yīng)模塊復(fù)習(xí)。最容易漏的不是代碼而是“數(shù)據(jù)口徑”和“時(shí)間對齊”這類看不見的邏輯。從那以后我每次拿到新數(shù)據(jù)都會強(qiáng)制走一遍這套流程先檢查列結(jié)構(gòu)和缺失值再確認(rèn)復(fù)權(quán)口徑最后用滯后一天的信號跑一次對照回測。如果對照結(jié)果和原結(jié)果差距過大說明一定有未來函數(shù)藏在代碼里。這套習(xí)慣幫我避免了很多次“回測很爽、實(shí)盤翻車”的尷尬。希望幫到你。本文還有配套的精品資源點(diǎn)擊獲取