[续] 把整条量化研究流程又重做了一遍 - V2EX
matters

[续] 把整条量化研究流程又重做了一遍

  •  
  •   matters Apr 30 578 views

    前阵子发了个小频率动量策略,当时回测看着还行,但实盘一跑就开始露问题。

    最近刚好在看《打开量化投资的黑箱》第九章,且根据 v 友建议,顺手把自己那一套研究流程从头捋了一遍,相当于是给之前那个策略“补课”。

    1. 策略起点

    之前做动量,基于一个很直觉的想法:

    涨得多的继续涨

    当时没太多犹豫,直接写代码+回测。

    现在回头看,更像是一个“没被明确表达的假设”。

    现在会刻意把这一步写清楚一点:

    • 是基于经济逻辑?
    • 还是纯数据挖出来的?

    简单给自己加了一条约束:

    if 没有清晰逻辑: 回测再好也不直接用 

    2. 数据

    之前策略有个问题其实一直没认真处理数据。

    现在回头看,这一块基本决定了上限。

    ( 1 )幸存者偏差

    用当前成分股回测历史,这个坑就不展开了。

    ( 2 )时间对齐

    之前直接拼不同频率数据,本质就是未来函数。

    现在我给自己加了个很简单的检查:

    每一份数据都问一句:当时能不能拿到

    顺手也把数据源换成了直接拉 API ,至少链路是“接近实盘”的:

    import requests import pandas as pd API_KEY = "YOUR_ALLTICK_API_KEY" def get_price_data(symbol="AAPL"): url = "https://api.alltick.co/marketdata/stock/history" params = { "symbol": symbol, "start_date": "2020-01-01", "end_date": "2023-01-01", "interval": "1d", "apikey": API_KEY } res = requests.get(url, params=params) data = res.json()["data"] df = pd.DataFrame(data) df["date"] = pd.to_datetime(df["date"]) return df df = get_price_data() # 基础清洗 df = df.sort_values("date") df["close"] = df["close"].fillna(method="ffill") df = df[df["volume"] > 0] 

    这块其实没什么技术含量,但好处是:

    回测用的数据结构,跟以后实盘用的是同一套来源

    3. 回测:开始老老实实加“现实约束”

    之前那版动量策略的问题是:

    默认理想成交

    现在基本都会强制加:

    • 成本
    • 简单滑点
    • 信号延迟

    举个最简单的均线例子:

    df['ma20'] = df['close'].rolling(20).mean() df['signal'] = (df['close'] > df['ma20']).astype(int) df['returns'] = df['close'].pct_change() df['strategy'] = df['signal'].shift(1) * df['returns'] cost = 0.0005 df['strategy_net'] = df['strategy'] - cost * df['signal'].diff().abs() 

    一旦把成本加进去,很多策略当场变脸。

    现在对回测的理解更偏向:

    这是一个“历史条件下的生存测试”

    4. 参数优化:开始刻意“反着来”

    之前是找最优参数,现在是故意破坏它:

    for p in [17, 20, 23]: 跑一下 

    不稳的策略,一动就崩。

    再加一个基本操作:

    train = df[df['date'] < '2021-01-01'] test = df[df['date'] >= '2021-01-01'] 

    test 基本只看一次。

    慢慢变成一个很简单的判断:

    • 能扛参数扰动的 → 再看
    • 需要精调的 → 基本放弃

    这一轮下来,有个挺明显的变化:

    不太会被“完美回测”骗了

    以前是:

    • 曲线好看 = 可以上

    现在更像是:

    if 解释不了 + 不抗扰动: 默认不可用 

    有点反直觉的是:

    能用的策略变少了, 但心里反而更踏实一点。

    connor123
        1
    connor123      Apr 30
    看不懂,不够还是想吐槽下 3 月的美伊战争,以及昨晚的鲍威尔讲话,我的量化系统纯纯变成了全自动亏钱系统,tmd
    About     Help     Advertise     Blog     API     FAQ     Solana     1173 Online   Highest 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 36ms UTC 23:16 PVG 07:16 LAX 16:16 JFK 19:16
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86