TL; DR: 人们对台风关注程度会影响股市. 我收集了2017年以来所有台风数据加上百度搜索指数, 发现台风信息能解释许多股票收益率相对于指数的残差, 随后按照横截面筛取topk的股票回测, 发现平均每个台风日能带来0.2%的收益.

相关代码在Github开放: https://github.com/myuanz/typhoon-alpha

求职中, 详见文末

收益曲线 回撤有点高, 但因子和策略非常无脑, 就是纯线性模型, 台风指标到了就买, 没了就卖, 止损 5%. 所以应该还有不少优化空间.

数据源及预处理

台风数据

维基百科上有每年的热态风暴记录台风表格截图 我手工抓取了2017至今的所有台风数据, 写代码清洗了格式, 得到了: 台风表格-清洗 随后为方便处理, 将出现在同一天的台风叠加, 由于只考虑A股, 因此定了一个中国分数, 台风影响的中国地区越多越大. 台风的其他参数处理规则是:

  1. 气压取 max 并除以标准气压 1012 hPa
  2. 损失、死亡、中国影响度取 sum
  3. 风速则使用处理, 然后除以台风入门风速 112 km/h. 平方和再开根是因后来发现风速的贡献度非常大, 取 max 和 sum 都太粗糙, 这样光滑一点 得到结果如下: 跟你的印象相合吗?
  1. 后来意识到台风初期是没有损伤数据的, 后续处理中这两个字段没有加入
  2. 中国分数上的 非常小, 拍脑袋定的规则确实不行

搜索指数

使用百度指数, 我关注了这些关键词:

  • 台风
  • 台风路径
  • 台风实时路径
  • 暴雨
  • 暴雨预警

台风相关的倾向于全国的关注度, 暴雨相关的倾向于受灾地关注度. 百度指数中, 台风相关的数据只能从2017年开始, 因此我的后续分析也只能从2017年开始. 另外, 台风实时路径台风路径似乎有分词错误, 台风实时路径只在这几年比较高, 因此我将台风路径台风实时路径加起来了. 所有的搜索指数最终都取了 log1p. 原始数据如下: 抓取代码也在 Github 仓库.

股票指数

上证指数000001.SH、创业板指399006.SZ、深成指数399001.SZ. 后续流程中使用这三个做自变量预测股票获取残差, 再用台风数据预测残差, 交易预测效果比较好的股票.

股票日线、行业、基本面

都来自 tushare. 日线使用 ts.pro_bar 获取, 后复权. 基本面使用 pro.daily_basic . 行业使用pro.stock_basic, 包含退市股票.

数据共享

台风和百度指数我都放到了 https://github.com/myuanz/typhoon-alpha/releases 可自行下载

因子计算

使用最小二乘法, 将上证、深成、创业指数的 pct_change 和股票的 rsi14 作为输入, 下一日的股票收益作为拟合目标. 以 836961.BJ 为例, 可以得到

                             OLS Regression Results                            
==============================================================================
Dep. Variable:          fgdm_next_day   R-squared:                       0.004
Model:                            OLS   Adj. R-squared:                 -0.005
Method:                 Least Squares   F-statistic:                    0.4771
Date:                Tue, 07 Oct 2025   Prob (F-statistic):              0.753
Time:                        20:22:23   Log-Likelihood:                -1919.7
No. Observations:                 471   AIC:                             3849.
Df Residuals:                     466   BIC:                             3870.
Df Model:                           4                                         
Covariance Type:                  HC1                                         
==============================================================================
                 coef    std err          z      P>|z|      [0.025      0.975]
------------------------------------------------------------------------------
const          3.3966      2.100      1.618      0.106      -0.718       7.512
上证            -0.2324      1.105     -0.210      0.833      -2.398       1.933
深成             0.1947      1.970      0.099      0.921      -3.666       4.055
创业             0.2238      1.270      0.176      0.860      -2.266       2.714
fgdm_rsi14    -0.0488      0.043     -1.125      0.261      -0.134       0.036
==============================================================================
Omnibus:                      811.641   Durbin-Watson:                   2.149
Prob(Omnibus):                  0.000   Jarque-Bera (JB):           516995.616
Skew:                          10.217   Prob(JB):                         0.00
Kurtosis:                     164.016   Cond. No.                         214.
==============================================================================

可以看到每一个指标置信度都不太好, 随后加入台风参数, 得到:

                             OLS Regression Results                            
==============================================================================
Dep. Variable:          fgdm_next_day   R-squared:                       0.036
Model:                            OLS   Adj. R-squared:                  0.015
Method:                 Least Squares   F-statistic:                    0.8409
Date:                Tue, 07 Oct 2025   Prob (F-statistic):              0.589
Time:                        20:22:23   Log-Likelihood:                -1912.0
No. Observations:                 471   AIC:                             3846.
Df Residuals:                     460   BIC:                             3892.
Df Model:                          10                                         
Covariance Type:                  HC1                                         
===============================================================================
                  coef    std err          z      P>|z|      [0.025      0.975]
-------------------------------------------------------------------------------
const           3.2447     12.267      0.265      0.791     -20.798      27.287
上证             -0.0846      1.119     -0.076      0.940      -2.278       2.109
深成              0.1847      1.999      0.092      0.926      -3.734       4.103
创业              0.1302      1.257      0.104      0.917      -2.333       2.594
fgdm_rsi14     -0.0302      0.060     -0.503      0.615      -0.148       0.087
speed           1.3987      1.057      1.323      0.186      -0.673       3.470
china_score    -0.0839      0.711     -0.118      0.906      -1.477       1.309
index-台风        5.1638      4.903      1.053      0.292      -4.447      14.774
index-台风路径     -4.0565      3.541     -1.145      0.252     -10.997       2.884
index-暴雨       -1.1185      2.427     -0.461      0.645      -5.876       3.639
index-暴雨预警     -0.9359      0.563     -1.663      0.096      -2.039       0.167
==============================================================================
Omnibus:                      776.316   Durbin-Watson:                   2.205
Prob(Omnibus):                  0.000   Jarque-Bera (JB):           442255.482
Skew:                           9.331   Prob(JB):                         0.00
Kurtosis:                     151.953   Cond. No.                         781.
==============================================================================

从0.004来到了0.036, 你可能会觉得很低, 我也这么觉得. 抱着试一试的态度我当时试了各种模型和正则方法, 要么欠拟合, 要么过拟合, 我也考虑过新闻因子可能不是线性影响结果的, 但是多项式搜索的结果也是欠拟合. 最后我只能抱着过拟合的树模型(lightgbm)看它怎么过拟合的.

plot_tree注意到, 除了更大的树带来的过拟合, 风速是一个非常重要的条件. 于是我从风速 0.5 开始划阈值, 一直拉到2.0(即两倍入门级台风风速), 得到了非常棒的结果: 图片中横轴是速度阈值, 上半部分图蓝色线是使用指数预测股票的, 橙线是带上台风参数后, 模型可以解释多少的蓝线对应的指数残差, 即对于指数模型无法预测的部分来说, 有多大比例能被台风参数模型预测. 下半部分图是不同阈值对应的剩余交易天数, 红线是80天, 是我原来想总共有八年, 每年得留出10天来交易吧.

综合来说, 可以看出来, 随着阈值拉高, 台风参数能预测更多的残差. 这非常自然, 风速越大理论上会带来越多影响, 因此台风对股票的解释力()就逐渐扩大, 这是阈值拉到 1.0 时的 ols summary:

                             OLS Regression Results                            
==============================================================================
Dep. Variable:          fgdm_next_day   R-squared:                       0.016
Model:                            OLS   Adj. R-squared:                 -0.016
Method:                 Least Squares   F-statistic:                     1.573
Date:                Tue, 07 Oct 2025   Prob (F-statistic):              0.186
Time:                        20:25:16   Log-Likelihood:                -581.76
No. Observations:                 126   AIC:                             1174.
Df Residuals:                     121   BIC:                             1188.
Df Model:                           4                                         
Covariance Type:                  HC1                                         
==============================================================================
                 coef    std err          z      P>|z|      [0.025      0.975]
------------------------------------------------------------------------------
const          5.0887      4.415      1.153      0.249      -3.564      13.741
上证             0.8933      2.152      0.415      0.678      -3.325       5.111
深成            -3.3190      4.383     -0.757      0.449     -11.910       5.272
创业             3.2626      3.348      0.975      0.330      -3.299       9.824
fgdm_rsi14    -0.0434      0.093     -0.466      0.641      -0.226       0.139
==============================================================================
Omnibus:                      210.491   Durbin-Watson:                   2.082
Prob(Omnibus):                  0.000   Jarque-Bera (JB):            21168.370
Skew:                           6.962   Prob(JB):                         0.00
Kurtosis:                      64.953   Cond. No.                         201.
==============================================================================


                             OLS Regression Results                            
==============================================================================
Dep. Variable:          fgdm_next_day   R-squared:                       0.111
Model:                            OLS   Adj. R-squared:                  0.033
Method:                 Least Squares   F-statistic:                     2.111
Date:                Tue, 07 Oct 2025   Prob (F-statistic):             0.0289
Time:                        20:25:16   Log-Likelihood:                -575.44
No. Observations:                 126   AIC:                             1173.
Df Residuals:                     115   BIC:                             1204.
Df Model:                          10                                         
Covariance Type:                  HC1                                         
===============================================================================
                  coef    std err          z      P>|z|      [0.025      0.975]
-------------------------------------------------------------------------------
const          46.4945     51.355      0.905      0.365     -54.159     147.148
上证             -0.2964      2.912     -0.102      0.919      -6.004       5.411
深成             -0.4271      3.771     -0.113      0.910      -7.818       6.963
创业              2.0236      3.322      0.609      0.542      -4.488       8.535
fgdm_rsi14     -0.1257      0.140     -0.900      0.368      -0.399       0.148
speed          -5.5496      5.335     -1.040      0.298     -16.007       4.908
china_score     2.2868      2.352      0.972      0.331      -2.322       6.896
index-台风       10.6497      8.859      1.202      0.229      -6.714      28.013
index-台风路径     -9.1416      7.743     -1.181      0.238     -24.318       6.035
index-暴雨        1.0860      4.314      0.252      0.801      -7.369       9.541
index-暴雨预警     -9.5024      5.004     -1.899      0.058     -19.311       0.306
==============================================================================
Omnibus:                      192.744   Durbin-Watson:                   2.036
Prob(Omnibus):                  0.000   Jarque-Bera (JB):            15544.714
Skew:                           5.977   Prob(JB):                         0.00
Kurtosis:                      56.085   Cond. No.                         858.
==============================================================================

可以看得出来, 暴雨预警、台风的百度搜索指数有不低的z分数, 而且 来到了 0.11, 按照上图, 如果阈值拉到1.8, 则有60%的残差可以由台风参数解释.

这个规律在大约三分之一的股票里都有呈现, 不过每个股票的最佳速度阈值都不同, 显示出不同股票对台风的敏感度不同.

因子利用

那么, 现在该如何利用这个模型? 这里有一个潘多拉之盒, 动态风速阈值, 我花了很久在这上面, 发现最终很难找到一个良好的方案在不泄露未来和过拟合的前提下给每一个股票定一个良好的速度阈值. 所以我就给所有股票都定了一个阈值 1.0, 这个超参数很自然, 只有当风速到达台风标准后, 才纳入回归.

为了避免过拟合和未来泄露, 我从2018年开始, 每次滚动七天, 用过去三年的数据训练模型来预测这七天, 记录预测结果后再滚动七天, 相关代码如下:

# self.args.train_years           = 3
# self.args.min_days_for_training = 10
 
curr_dt = datetime.date(2018, 1, 1)
step_days = 7
while curr_dt < self.args.end_date_dt:
	curr_dt += datetime.timedelta(days=step_days)
 
	train_df = df_filt.filter(
		(curr_dt - pc('date').dt.date()) > 0,
		(curr_dt - pc('date').dt.date()).dt.total_days() <= self.args.train_years * 365,
	) # [curr_dt - train_years, curr_dt)
	if len(train_df) <= self.args.min_days_for_training:
		if self.args.print_summary:
			print(f"{curr_dt}: train_df={len(train_df)}. data is too short")
		continue
	test_df = df_filt.filter(
		pc('date').dt.date() >= curr_dt,
		pc('date').dt.date() < (curr_dt + datetime.timedelta(days=step_days)),
	) # [curr_dt, curr_dt + step_days)
	
	mkt_model = self.regression_market(train_df)
	resid_model = self.regression_resid(train_df, mkt_model)
	
	fgdm_pred = mkt_model.predict(test_df)
	resid_pred = resid_model.predict(test_df)
	fgdm_pred_total = fgdm_pred + resid_pred

单股回测

最终使用fgdm_pred_total指示交易, 基于backtesting.py写了一个非常简单粗糙的回测策略:

import datetime
 
from backtesting import Strategy
 
 
class TyphoonEventStrategy(Strategy):
    min_p: float = 0.5
    open_size: float = 0.5
    hold_days: int = 0
 
    def init(self):
        self.last_open_dt = self.data.index[0]
 
    def next(self):
        不应开仓 = datetime.datetime(2024, 9, 20) <= self.data.index[-1] <= datetime.datetime(2024, 9, 30)
        有钱开仓 = self._broker._cash > self.data.Close[-1] * self.open_size * 1.1
 
        pred = self.data.fgdm_pred_total[-1]
        date_diff = self.data.index[-1] - self.last_open_dt
 
        if pred > self.min_p:
            if not 不应开仓 and 有钱开仓:
                self.buy(size=self.open_size)
                self.last_open_dt = self.data.index[-1]
        elif pred < -self.min_p:
            self.position.close()
 
        if (pred == 0 and self.position and date_diff >= datetime.timedelta(days=float(self.hold_days))) or 不应开仓:
            self.position.close()

其中包含三个超参数:

  1. min_p: 预测值fgdm_pred_total到多大再开仓
  2. open_size: 每次开仓占仓位多少
  3. hold_days: 如果信号消失, 持有多少天后平仓 当我在这个 bar 下发单后, 框架会自动帮我在下一个 bar 上交易, 且self.data[-1]永远指向当前最新的那个bar.

这里面有一个不应开仓参数, 是因为二四年九月底发布刺激政策时, 刚好处于台风期间, 整个市场只要买了就赚, 因此专门把这段时间屏蔽. 传统上应该做行业因子中性化之类的事情, 但是我这边暴露时间比较低, 这步略过了.

单股交易结果分析

在使用所有股票(包含退市)回测后, 我发现复合年化的均值为负, 即如果不选股就开仓的话, 平均要亏损 -0.22% 再看看价格与收益 上图是价格的对数与复合年化的关系, 发现低价的更容易亏, 不过这里是后复权价格, 可能参考意义不大 股票上市时间与收益的影响呢? 看起来只有最近几年的股票平均收益明显是正的, 不过他们的方差也是最大的, 仔细检查了数据发现只是股票刚上市撞上了台风而已. 观察交易所:

交易所CAGR_meanCAGR_stdDuration_meancount
strf64f64f64u32
”BJ”1.0864914.3695912473.87451255
”SZ”-0.2356063.5676092552.1642912946
”SH”-0.3445143.4015352439.6162092332

发现上交的平均收益为负, 北京的为正, 应该是北京这几年上新比较多吧.

如果按照行业分类后按年化收益中位数排序, 可以得到:

┌──────────┬───────────┬─────────────┬─────────────┬──────────────┬──────────────┬─────────────┐
│ industry ┆ ret_ann   ┆ ret_ann_med ┆ ret_ann_std ┆ buy_hold_ret ┆ avg_drawdown ┆ stock_count │
│ ---      ┆ ---       ┆ ---         ┆ ---         ┆ ---          ┆ ---          ┆ ---         │
│ str      ┆ f64       ┆ f64         ┆ f64         ┆ f64          ┆ f64          ┆ u32         │
╞══════════╪═══════════╪═════════════╪═════════════╪══════════════╪══════════════╪═════════════╡
│ 轻工机械 ┆ 1.549255  ┆ 2.937132    ┆ 4.187368    ┆ 1.201316     ┆ -13.630155   ┆ 6           │
│ 化工机械 ┆ 9.150158  ┆ 2.054764    ┆ 26.709532   ┆ 26.454328    ┆ -8.100391    ┆ 13          │
│ 焦炭加工 ┆ 1.933969  ┆ 1.801179    ┆ 4.131917    ┆ -2.634665    ┆ -8.40675     ┆ 7           │
│ 汽车配件 ┆ 1.809086  ┆ 1.617585    ┆ 5.997559    ┆ 25.033953    ┆ -10.541559   ┆ 238         │
│ 通信设备 ┆ 2.474716  ┆ 1.576698    ┆ 6.324367    ┆ 33.451447    ┆ -10.711882   ┆ 136         │
│ 软件服务 ┆ 1.729974  ┆ 1.495614    ┆ 6.349617    ┆ 363.342988   ┆ -12.240704   ┆ 279         │
│ 橡胶     ┆ 1.293623  ┆ 1.369097    ┆ 4.789127    ┆ 114.141129   ┆ -8.814587    ┆ 14          │
│ 电信运营 ┆ 2.249887  ┆ 1.274305    ┆ 3.810379    ┆ 19.34957     ┆ -9.9307      ┆ 5           │
│ 啤酒     ┆ 0.124311  ┆ 1.112077    ┆ 4.335614    ┆ 8.911032     ┆ -8.789158    ┆ 8           │
│ 机械基件 ┆ 2.331616  ┆ 1.105714    ┆ 7.445607    ┆ 24.423211    ┆ -11.216518   ┆ 127         │
│ 公共交通 ┆ -0.089017 ┆ 1.101224    ┆ 3.105943    ┆ 0.653493     ┆ -9.540989    ┆ 7           │
│ 汽车服务 ┆ -0.127472 ┆ 1.057301    ┆ 4.152362    ┆ 12.930371    ┆ -14.374905   ┆ 10          │
│ 保险     ┆ 1.053371  ┆ 1.053941    ┆ 1.698065    ┆ 6.926107     ┆ -7.656536    ┆ 6           │
│ 汽车整车 ┆ -0.049337 ┆ 1.050551    ┆ 3.351654    ┆ 14.650057    ┆ -10.709975   ┆ 22          │
│ 元器件   ┆ 1.226606  ┆ 1.018778    ┆ 6.567954    ┆ 20.29835     ┆ -11.570074   ┆ 289         │
│ 商贸代理 ┆ 0.734907  ┆ 0.728749    ┆ 3.543827    ┆ -4.429959    ┆ -9.352753    ┆ 17          │
│ 工程机械 ┆ 0.468995  ┆ 0.682159    ┆ 5.178679    ┆ 76.408448    ┆ -8.157346    ┆ 37          │
│ 船舶     ┆ 1.056973  ┆ 0.547253    ┆ 3.836263    ┆ 2.702855     ┆ -11.846453   ┆ 11          │
│ 房产服务 ┆ -0.750391 ┆ 0.448027    ┆ 3.758148    ┆ -1.371818    ┆ -9.566793    ┆ 13          │
│ IT设备   ┆ 0.901689  ┆ 0.425187    ┆ 5.176984    ┆ 44.150034    ┆ -11.762694   ┆ 76          │
│ 石油开采 ┆ 0.472685  ┆ 0.39476     ┆ 4.006785    ┆ -1.842756    ┆ -7.500587    ┆ 20          │
│ 电气设备 ┆ 1.045216  ┆ 0.368377    ┆ 6.576012    ┆ 15.481504    ┆ -12.252266   ┆ 323         │
│ 专用机械 ┆ 1.833708  ┆ 0.317081    ┆ 11.94131    ┆ 16.418306    ┆ -11.53748    ┆ 268         │
│ 其他建材 ┆ -0.35043  ┆ 0.270036    ┆ 4.662832    ┆ 7.915539     ┆ -9.127107    ┆ 29          │
│ 运输设备 ┆ -0.163711 ┆ 0.246072    ┆ 4.456181    ┆ 4.204806     ┆ -10.752852   ┆ 48          │
│ 供气供热 ┆ 0.288715  ┆ 0.239447    ┆ 4.941166    ┆ 4.486731     ┆ -11.04589    ┆ 45          │
│ 铜       ┆ 1.583067  ┆ 0.213642    ┆ 4.169651    ┆ 21.740298    ┆ -6.684227    ┆ 17          │
│ 摩托车   ┆ 1.073083  ┆ 0.19369     ┆ 5.169783    ┆ 56.459962    ┆ -7.823474    ┆ 12          │
│ 航空     ┆ 0.587113  ┆ 0.143649    ┆ 6.142986    ┆ 8.766834     ┆ -12.153075   ┆ 52          │
│ 电器仪表 ┆ 0.601672  ┆ 0.036217    ┆ 5.700462    ┆ 28.852787    ┆ -12.356664   ┆ 102         │
│ 小金属   ┆ 0.051263  ┆ -0.038738   ┆ 6.269422    ┆ 20.777062    ┆ -13.172893   ┆ 60          │
│ 互联网   ┆ 0.068568  ┆ -0.054997   ┆ 4.883338    ┆ 4.353537     ┆ -11.909991   ┆ 80          │
│ 综合类   ┆ -0.768495 ┆ -0.142058   ┆ 3.668356    ┆ 1.87523      ┆ -11.720975   ┆ 19          │
│ 证券     ┆ -0.278318 ┆ -0.177191   ┆ 2.720938    ┆ 6.813794     ┆ -10.172545   ┆ 50          │
│ 文教休闲 ┆ -0.222644 ┆ -0.219125   ┆ 4.730904    ┆ 1.669441     ┆ -11.431009   ┆ 51          │
│ 半导体   ┆ 0.565998  ┆ -0.227407   ┆ 7.987494    ┆ 30.205938    ┆ -12.795072   ┆ 177         │
│ 全国地产 ┆ -0.252925 ┆ -0.24509    ┆ 2.920807    ┆ -5.010122    ┆ -11.858096   ┆ 26          │
│ 机床制造 ┆ -0.287689 ┆ -0.300029   ┆ 7.242996    ┆ 11.936358    ┆ -11.797132   ┆ 24          │
│ 家用电器 ┆ 0.045749  ┆ -0.346171   ┆ 4.735704    ┆ 7.386846     ┆ -11.469338   ┆ 90          │
│ 广告包装 ┆ 0.555467  ┆ -0.413487   ┆ 5.344267    ┆ 3.480715     ┆ -10.13571    ┆ 52          │
│ 陶瓷     ┆ -0.38988  ┆ -0.453105   ┆ 3.545302    ┆ -0.129121    ┆ -13.034244   ┆ 5           │
│ 钢加工   ┆ -0.508977 ┆ -0.478314   ┆ 3.169032    ┆ -2.58998     ┆ -9.840955    ┆ 23          │
│ 园区开发 ┆ 0.921851  ┆ -0.482042   ┆ 5.440351    ┆ 0.653458     ┆ -13.840561   ┆ 14          │
│ 仓储物流 ┆ -0.169723 ┆ -0.52       ┆ 3.896492    ┆ 4.708799     ┆ -13.049121   ┆ 45          │
│ 矿物制品 ┆ 0.294302  ┆ -0.520573   ┆ 6.615002    ┆ 47.444893    ┆ -13.819559   ┆ 33          │
│ 影视音像 ┆ -0.742394 ┆ -0.539302   ┆ 4.931829    ┆ -1.016355    ┆ -14.699317   ┆ 35          │
│ 纺织机械 ┆ -0.025219 ┆ -0.590908   ┆ 2.346861    ┆ 3.896016     ┆ -8.348456    ┆ 11          │
│ 玻璃     ┆ 1.010627  ┆ -0.618091   ┆ 6.184843    ┆ 23.301871    ┆ -8.795826    ┆ 18          │
│ 农用机械 ┆ -1.016995 ┆ -0.660196   ┆ 3.997347    ┆ 17.762992    ┆ -10.454939   ┆ 13          │
│ 纺织     ┆ -0.575404 ┆ -0.668765   ┆ 4.395947    ┆ 5.793774     ┆ -11.377489   ┆ 41          │
│ 火力发电 ┆ -0.474188 ┆ -0.755873   ┆ 2.883263    ┆ 0.869846     ┆ -8.737548    ┆ 31          │
│ 铝       ┆ -0.230437 ┆ -0.786673   ┆ 3.941017    ┆ 7.036094     ┆ -12.814202   ┆ 30          │
│ 塑料     ┆ -1.050083 ┆ -0.824591   ┆ 5.319208    ┆ 17.030967    ┆ -11.484213   ┆ 76          │
│ 铁路     ┆ -2.344798 ┆ -0.85257    ┆ 2.663121    ┆ 1.192934     ┆ -9.709301    ┆ 7           │
│ 其他商业 ┆ -1.30023  ┆ -0.918368   ┆ 3.835974    ┆ -2.062449    ┆ -10.97391    ┆ 12          │
│ 黄金     ┆ -1.080211 ┆ -0.955137   ┆ 2.315512    ┆ 21.626255    ┆ -9.200864    ┆ 10          │
│ 银行     ┆ -1.186664 ┆ -0.984318   ┆ 2.095428    ┆ 3.716138     ┆ -7.003359    ┆ 42          │
│ 多元金融 ┆ -0.74804  ┆ -0.987682   ┆ 3.661959    ┆ 3.763479     ┆ -12.051015   ┆ 24          │
│ 日用化工 ┆ -0.75699  ┆ -1.007666   ┆ 5.262321    ┆ 9.614547     ┆ -10.627751   ┆ 20          │
│ 铅锌     ┆ -0.761879 ┆ -1.052861   ┆ 3.053801    ┆ 13.065387    ┆ -8.177156    ┆ 14          │
│ 百货     ┆ -0.742929 ┆ -1.066785   ┆ 3.123698    ┆ -1.753444    ┆ -11.032075   ┆ 35          │
│ 路桥     ┆ -0.965708 ┆ -1.072141   ┆ 1.567191    ┆ 4.404342     ┆ -7.746819    ┆ 19          │
│ 乳制品   ┆ 0.430832  ┆ -1.153865   ┆ 5.918741    ┆ 0.136323     ┆ -11.189128   ┆ 21          │
│ 酒店餐饮 ┆ -1.667069 ┆ -1.172433   ┆ 2.696116    ┆ -0.579431    ┆ -13.68041    ┆ 9           │
│ 水务     ┆ -0.918461 ┆ -1.200159   ┆ 3.348214    ┆ 0.151258     ┆ -8.950766    ┆ 15          │
│ 化工原料 ┆ -0.826079 ┆ -1.354519   ┆ 5.995861    ┆ 12.411455    ┆ -12.557025   ┆ 247         │
│ 家居用品 ┆ -1.241408 ┆ -1.355019   ┆ 4.158453    ┆ 2.769433     ┆ -13.169057   ┆ 68          │
│ 白酒     ┆ -0.496249 ┆ -1.368377   ┆ 3.181042    ┆ 22.353597    ┆ -10.514418   ┆ 20          │
│ 出版业   ┆ -1.434482 ┆ -1.395759   ┆ 3.457198    ┆ 2.522831     ┆ -11.027082   ┆ 29          │
│ 石油加工 ┆ -0.868675 ┆ -1.452399   ┆ 3.357841    ┆ 1.364268     ┆ -14.480115   ┆ 13          │
│ 化纤     ┆ -0.881604 ┆ -1.495136   ┆ 4.349862    ┆ 8.621835     ┆ -11.002997   ┆ 31          │
│ 造纸     ┆ -1.560164 ┆ -1.555848   ┆ 4.224356    ┆ 11.510346    ┆ -10.876938   ┆ 32          │
│ 特种钢   ┆ -0.335729 ┆ -1.576895   ┆ 4.52051     ┆ 8.060349     ┆ -9.960258    ┆ 10          │
│ 建筑工程 ┆ -1.586414 ┆ -1.584698   ┆ 4.823235    ┆ 301.632773   ┆ -14.587288   ┆ 127         │
│ 煤炭开采 ┆ -1.707886 ┆ -1.614816   ┆ 2.508778    ┆ 15.649016    ┆ -9.77096     ┆ 25          │
│ 红黄酒   ┆ -0.678776 ┆ -1.622304   ┆ 4.091157    ┆ 1.125955     ┆ -8.536575    ┆ 9           │
│ 农业综合 ┆ -1.17004  ┆ -1.688245   ┆ 3.869617    ┆ 2.072222     ┆ -12.184779   ┆ 43          │
│ 种植业   ┆ 0.239463  ┆ -1.700627   ┆ 9.507213    ┆ 9.216492     ┆ -11.502641   ┆ 19          │
│ 食品     ┆ -1.446303 ┆ -1.712095   ┆ 4.546134    ┆ 14.881476    ┆ -13.994299   ┆ 93          │
│ 超市连锁 ┆ -0.594941 ┆ -1.721567   ┆ 3.16012     ┆ 0.229999     ┆ -12.049697   ┆ 8           │
│ 服饰     ┆ -1.344479 ┆ -1.816455   ┆ 4.632769    ┆ -2.476029    ┆ -11.446798   ┆ 65          │
│ 旅游景点 ┆ -1.865201 ┆ -1.846301   ┆ 3.056933    ┆ 1.150204     ┆ -11.940804   ┆ 17          │
│ 普钢     ┆ -1.932843 ┆ -1.869122   ┆ 2.724257    ┆ 1.608892     ┆ -9.45546     ┆ 26          │
│ 渔业     ┆ -1.823286 ┆ -1.885567   ┆ 3.476613    ┆ -7.510187    ┆ -14.485557   ┆ 7           │
│ 新型电力 ┆ -2.281896 ┆ -1.887134   ┆ 3.473416    ┆ 2.088612     ┆ -15.580231   ┆ 27          │
│ 医疗保健 ┆ -1.787743 ┆ -1.895641   ┆ 4.52547     ┆ 9.897957     ┆ -14.433439   ┆ 172         │
│ 医药商业 ┆ -2.346408 ┆ -1.895799   ┆ 4.210227    ┆ -2.974905    ┆ -12.900034   ┆ 36          │
│ 化学制药 ┆ -1.740405 ┆ -1.917923   ┆ 4.836623    ┆ 9.887548     ┆ -14.397021   ┆ 149         │
│ 区域地产 ┆ -1.712209 ┆ -2.074257   ┆ 3.84342     ┆ -1.786451    ┆ -15.347513   ┆ 47          │
│ 机场     ┆ -1.673498 ┆ -2.142079   ┆ 2.044346    ┆ -1.941648    ┆ -7.387256    ┆ 5           │
│ 染料涂料 ┆ -1.22326  ┆ -2.22142    ┆ 5.003563    ┆ 5.493095     ┆ -15.252377   ┆ 32          │
│ 装修装饰 ┆ -1.779848 ┆ -2.261744   ┆ 3.527382    ┆ -5.553475    ┆ -13.778507   ┆ 26          │
│ 水运     ┆ -2.665058 ┆ -2.287617   ┆ 6.036604    ┆ 7.784118     ┆ -14.615297   ┆ 19          │
│ 港口     ┆ -2.955384 ┆ -2.33884    ┆ 3.04589     ┆ -2.247103    ┆ -15.952123   ┆ 16          │
│ 水泥     ┆ -2.538043 ┆ -2.393775   ┆ 2.834931    ┆ -0.700517    ┆ -11.81964    ┆ 23          │
│ 空运     ┆ -1.541535 ┆ -2.396888   ┆ 2.689596    ┆ 0.81461      ┆ -10.576342   ┆ 8           │
│ 环境保护 ┆ -2.458103 ┆ -2.525347   ┆ 5.320228    ┆ 0.099631     ┆ -14.399199   ┆ 121         │
│ 农药化肥 ┆ -2.673085 ┆ -2.587072   ┆ 3.10889     ┆ 8.308678     ┆ -15.598873   ┆ 55          │
│ 中成药   ┆ -2.357371 ┆ -2.816012   ┆ 2.864507    ┆ 2.163557     ┆ -12.936106   ┆ 69          │
│ 水力发电 ┆ -2.403132 ┆ -2.882375   ┆ 2.676306    ┆ 6.776807     ┆ -11.953063   ┆ 21          │
│ 软饮料   ┆ -1.295691 ┆ -2.985803   ┆ 4.109405    ┆ 15.079079    ┆ -15.019588   ┆ 9           │
│ 饲料     ┆ -2.947981 ┆ -3.448997   ┆ 3.484103    ┆ 11.093685    ┆ -13.383632   ┆ 23          │
│ 生物制药 ┆ -3.172756 ┆ -3.514274   ┆ 5.226316    ┆ 14.215166    ┆ -15.168853   ┆ 77          │
│ 旅游服务 ┆ -6.230722 ┆ -4.167786   ┆ 4.846551    ┆ 10.246635    ┆ -18.510784   ┆ 7           │
│ null     ┆ -4.480726 ┆ -4.366166   ┆ 7.105163    ┆ -12.700481   ┆ -16.286001   ┆ 211         │
│ 批发业   ┆ -5.24806  ┆ -4.893173   ┆ 3.471591    ┆ -2.56649     ┆ -18.784524   ┆ 5           │
└──────────┴───────────┴─────────────┴─────────────┴──────────────┴──────────────┴─────────────┘

港口、空运、旅游、渔业负相关感觉比较自然, 但前面的一些正相关我就搞不懂了. 我最初想做这个只是想看看风电领域是否会因为台风带来的新闻学效应而上涨, 基于同花顺的台风板块股票列表, 我发现并没有明显的上涨. 画出来看看吧: 看起来这个策略跟行业的关系不大, 直接交易大部分是亏的, 还是要加上横截面才行. 再来看一下公司注册地: 更糟糕了hhh, 青海中位数是正是因为公司太少了. 最后我用之类的参数预测最终收益, 发现关系也并不大, 看起来必须得引入横截面了.

横截面优化

由于跑完五千多股票的七年回测要十分钟, 因此初步分析只是综合了所有交易记录, 然后对交易记录粉刷.

首先统计一下所有原始交易记录吧:

countret_pct_meanret_pct_stdret_pct_p5ret_pct_p25ret_pct_p50ret_pct_p75ret_pct_p95win_rateskewness
u32f64f64f64f64f64f64f64f64f64
864843-0.1441436.587112-9.547211-2.981884-0.2583062.2914219.39356546.5697242.613708

五千多支股票带来了总共有八十六万条交易记录, 中位数收益-0.25%, 偏度=2.6, 左偏. 简单地筛除带 ST 的股票和价格大于50或小于5的股票, 结果就好看很多了:

countret_pct_meanret_pct_stdret_pct_p5ret_pct_p25ret_pct_p50ret_pct_p75ret_pct_p95win_rateskewness
u32f64f64f64f64f64f64f64f64f64
521565-0.0026416.357112-8.818902-2.74924-0.122.2666279.09432647.6124742.935807

收益中位数从-0.25%-0.12%, 让我信心稍增. 随后剔除了涨停跌停和一字板交易记录. 如此以来数据就只剩下三十多万条了

countret_pct_meanret_pct_stdret_pct_p5ret_pct_p25ret_pct_p50ret_pct_p75ret_pct_p95win_rateskewness
u32f64f64f64f64f64f64f64f64f64
341598-0.0714486.187685-8.984846-2.799357-0.122.2642548.90009247.3190712.085626

中位收益没变, 但偏度小了一些.

基于 tushare, 可以比较轻松地获取每天的如下信息:

ts_code 	str 	TS股票代码
trade_date 	str 	交易日期
close 	float 	当日收盘价
turnover_rate 	float 	换手率(%)
turnover_rate_f 	float 	换手率(自由流通股)
volume_ratio 	float 	量比
pe 	float 	市盈率(总市值/净利润, 亏损的PE为空)
pe_ttm 	float 	市盈率(TTM,亏损的PE为空)
pb 	float 	市净率(总市值/净资产)
ps 	float 	市销率
ps_ttm 	float 	市销率(TTM)
dv_ratio 	float 	股息率 (%)
dv_ttm 	float 	股息率(TTM)(%)
total_share 	float 	总股本 (万股)
float_share 	float 	流通股本 (万股)
free_share 	float 	自由流通股本 (万)
total_mv 	float 	总市值 (万元)
circ_mv 	float 	流通市值(万元)

除此之外, 我又添加了adv20ret_5std5_pct_chg, 并预先

之后我对着每个指标计算了取 topk 后的分布, 发现有些指标取了 topk 后会非常差, 比如:

按 turnover_rate 降序取 topk
shape: (10, 11)
┌───────┬───────┬─────────┬─────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┐
│ top_k ┆ count ┆ ret_pct ┆ ret_pct ┆ ret_pc ┆ ret_pc ┆ ret_pc ┆ ret_pc ┆ ret_pc ┆ win_ra ┆ skewne │
│ ---   ┆ ---   ┆ _mean   ┆ _std    ┆ t_p5   ┆ t_p25  ┆ t_p50  ┆ t_p75  ┆ t_p95  ┆ te     ┆ ss     │
│ i64   ┆ i64   ┆ ---     ┆ ---     ┆ ---    ┆ ---    ┆ ---    ┆ ---    ┆ ---    ┆ ---    ┆ ---    │
│       ┆       ┆ f64     ┆ f64     ┆ f64    ┆ f64    ┆ f64    ┆ f64    ┆ f64    ┆ f64    ┆ f64    │
╞═══════╪═══════╪═════════╪═════════╪════════╪════════╪════════╪════════╪════════╪════════╪════════╡
│ 1     ┆ 408   ┆ -2.72   ┆ 13.04   ┆ -20.38 ┆ -10.03 ┆ -4.57  ┆ 2.76   ┆ 19.21  ┆ 32.35  ┆ 1.25   │
│ 2     ┆ 408   ┆ -2.69   ┆ 10.37   ┆ -17.49 ┆ -9.26  ┆ -3.53  ┆ 2.06   ┆ 16.33  ┆ 35.05  ┆ 0.89   │
│ 3     ┆ 408   ┆ -2.82   ┆ 8.92    ┆ -16.75 ┆ -8.53  ┆ -2.99  ┆ 1.79   ┆ 11.34  ┆ 35.54  ┆ 0.77   │
│ 4     ┆ 408   ┆ -2.50   ┆ 8.07    ┆ -14.88 ┆ -7.52  ┆ -2.51  ┆ 2.20   ┆ 10.39  ┆ 35.54  ┆ 0.66   │
│ 5     ┆ 408   ┆ -2.56   ┆ 7.55    ┆ -14.31 ┆ -7.75  ┆ -2.64  ┆ 1.74   ┆ 10.28  ┆ 35.05  ┆ 0.48   │
│ 6     ┆ 408   ┆ -2.40   ┆ 7.26    ┆ -13.89 ┆ -7.51  ┆ -2.23  ┆ 1.68   ┆ 9.62   ┆ 34.31  ┆ 0.34   │
│ 7     ┆ 408   ┆ -2.42   ┆ 6.96    ┆ -13.91 ┆ -7.12  ┆ -2.00  ┆ 1.66   ┆ 8.84   ┆ 35.29  ┆ 0.26   │
│ 8     ┆ 408   ┆ -2.37   ┆ 6.68    ┆ -13.29 ┆ -6.73  ┆ -2.04  ┆ 1.84   ┆ 7.81   ┆ 36.27  ┆ 0.13   │
│ 9     ┆ 408   ┆ -2.41   ┆ 6.37    ┆ -12.83 ┆ -6.86  ┆ -2.03  ┆ 1.55   ┆ 7.49   ┆ 36.03  ┆ 0.14   │
│ 10    ┆ 408   ┆ -2.40   ┆ 6.21    ┆ -12.20 ┆ -6.72  ┆ -1.88  ┆ 1.52   ┆ 6.93   ┆ 34.07  ┆ 0.10   │
└───────┴───────┴─────────┴─────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┘

那么这个指标可以做反向门控, 再看看排序与收益的关系散点图: 可以发现高换手率、高adv20、高市销率的地方总是方差更大, 我暂时没有找到方法单独把盈利为正的那部分抓出来, 因此大多数我只取了后面那部分

最终我得到了这样的门控方案:

base_p = 0.5
 
r = trades_df.lazy().join(
	mkt_df.lazy(),
	on=['ts_code', 'EntryTime'],
).filter(
	pc('close') > 5,
).with_columns(
	rk_turnover_rate = pc('turnover_rate').rank(descending=True).over('EntryTime') / pl.len().over('EntryTime'),
	rk_adv20 = pc('adv20').rank(descending=True).over('EntryTime') / pl.len().over('EntryTime'),
	rk_ret_5 = pc('ret_5').rank(descending=True).over('EntryTime') / pl.len().over('EntryTime'),
	rk_ps = pc('ps').rank(descending=True).over('EntryTime') / pl.len().over('EntryTime'),
	rk_total_mv = pc('total_mv').rank(descending=True).over('EntryTime') / pl.len().over('EntryTime'),
	rk_amount = pc('amount').rank(descending=True).over('EntryTime') / pl.len().over('EntryTime'),
	rk_std5_pct_chg = pc('std5_pct_chg').rank(descending=True).over('EntryTime') / pl.len().over('EntryTime'),
).filter(
	pc('rk_turnover_rate') > base_p,
	pc('rk_turnover_rate') < 0.99,
 
	pc('rk_adv20') > base_p,
	pc('rk_adv20') < 0.99,
 
	pc('std5_pct_chg') > 1,
 
	pc('rk_total_mv') > base_p,
	pc('rk_total_mv') < 0.99,
 
	pc('rk_ps') > base_p,
	pc('name').str.contains('ST').not_(),
).group_by('EntryTime').agg(
	pl.len().alias('num_trades'),
	# pl.all(),
	pl.all().top_k_by(-pc('total_mv') * pc('ps'), top_k),
).select(
	'EntryTime',
	'name',
	'ts_code',
	'ps',
	pc('ReturnPct').alias('ReturnPctList'),
	'num_trades',
	pc('ret_5'),
	pc('total_mv'),
	pc('ReturnPct').list.mean(),
).sort('EntryTime').collect()

即 换手率、adv20、总市值取后50%但放弃末尾1%, 市销率取后 50%, 五日return标准差要大于 1, 然后按总市值取 topk. 可以看得出来阈值非常拍脑门, 可能会有过拟合风险但应该不大, 因为base_p从0.3~0.7都不怎么影响结果. 而且分段绘制这些收益散点图结果也差不多.

这是剩下来的交易记录的统计结果:

┌───────┬───────┬─────────┬─────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┐
│ top_k ┆ count ┆ ret_pct ┆ ret_pct ┆ ret_pc ┆ ret_pc ┆ ret_pc ┆ ret_pc ┆ ret_pc ┆ win_ra ┆ skewne │
│ ---   ┆ ---   ┆ _mean   ┆ _std    ┆ t_p5   ┆ t_p25  ┆ t_p50  ┆ t_p75  ┆ t_p95  ┆ te     ┆ ss     │
│ i64   ┆ i64   ┆ ---     ┆ ---     ┆ ---    ┆ ---    ┆ ---    ┆ ---    ┆ ---    ┆ ---    ┆ ---    │
│       ┆       ┆ f64     ┆ f64     ┆ f64    ┆ f64    ┆ f64    ┆ f64    ┆ f64    ┆ f64    ┆ f64    │
╞═══════╪═══════╪═════════╪═════════╪════════╪════════╪════════╪════════╪════════╪════════╪════════╡
│ 1     ┆ 408   ┆ 0.72    ┆ 6.22    ┆ -6.55  ┆ -1.77  ┆ 0.19   ┆ 2.66   ┆ 10.96  ┆ 51.96  ┆ 1.76   │
│ 2     ┆ 408   ┆ 0.67    ┆ 4.89    ┆ -5.25  ┆ -1.70  ┆ 0.18   ┆ 2.39   ┆ 7.72   ┆ 52.70  ┆ 2.96   │
│ 3     ┆ 408   ┆ 0.66    ┆ 3.97    ┆ -4.61  ┆ -1.44  ┆ 0.25   ┆ 2.21   ┆ 7.59   ┆ 52.94  ┆ 1.64   │
│ 4     ┆ 408   ┆ 0.62    ┆ 3.47    ┆ -4.62  ┆ -1.41  ┆ 0.33   ┆ 2.28   ┆ 6.56   ┆ 55.88  ┆ 0.87   │
│ 5     ┆ 408   ┆ 0.54    ┆ 3.21    ┆ -4.44  ┆ -1.31  ┆ 0.42   ┆ 2.21   ┆ 5.77   ┆ 56.62  ┆ 0.74   │
│ 6     ┆ 408   ┆ 0.54    ┆ 3.10    ┆ -4.18  ┆ -1.31  ┆ 0.45   ┆ 2.19   ┆ 5.71   ┆ 57.84  ┆ 0.69   │
│ 7     ┆ 408   ┆ 0.43    ┆ 2.95    ┆ -4.12  ┆ -1.40  ┆ 0.45   ┆ 1.96   ┆ 5.42   ┆ 55.88  ┆ 0.58   │
│ 8     ┆ 408   ┆ 0.44    ┆ 2.94    ┆ -4.01  ┆ -1.40  ┆ 0.43   ┆ 1.96   ┆ 5.01   ┆ 57.60  ┆ 0.84   │
│ 9     ┆ 408   ┆ 0.44    ┆ 2.91    ┆ -3.67  ┆ -1.39  ┆ 0.40   ┆ 1.91   ┆ 4.78   ┆ 56.86  ┆ 0.77   │
│ 10    ┆ 408   ┆ 0.42    ┆ 2.88    ┆ -3.73  ┆ -1.35  ┆ 0.41   ┆ 1.99   ┆ 4.83   ┆ 54.90  ┆ 0.71   │
└───────┴───────┴─────────┴─────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┘

如果不取 topk 的话, 是这样:

┌───────┬───────┬─────────┬─────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┐
│ top_k ┆ count ┆ ret_pct ┆ ret_pct ┆ ret_pc ┆ ret_pc ┆ ret_pc ┆ ret_pc ┆ ret_pc ┆ win_ra ┆ skewne │
│ ---   ┆ ---   ┆ _mean   ┆ _std    ┆ t_p5   ┆ t_p25  ┆ t_p50  ┆ t_p75  ┆ t_p95  ┆ te     ┆ ss     │
│ i64   ┆ i64   ┆ ---     ┆ ---     ┆ ---    ┆ ---    ┆ ---    ┆ ---    ┆ ---    ┆ ---    ┆ ---    │
│       ┆       ┆ f64     ┆ f64     ┆ f64    ┆ f64    ┆ f64    ┆ f64    ┆ f64    ┆ f64    ┆ f64    │
╞═══════╪═══════╪═════════╪═════════╪════════╪════════╪════════╪════════╪════════╪════════╪════════╡
│ 1     ┆ 408   ┆ 0.26    ┆ 2.50    ┆ -3.69  ┆ -1.22  ┆ 0.25   ┆ 1.70   ┆ 4.56   ┆ 54.41  ┆ 0.27   │
│ 2     ┆ 408   ┆ 0.26    ┆ 2.50    ┆ -3.69  ┆ -1.22  ┆ 0.25   ┆ 1.70   ┆ 4.56   ┆ 54.41  ┆ 0.27   │
│ 3     ┆ 408   ┆ 0.26    ┆ 2.50    ┆ -3.69  ┆ -1.22  ┆ 0.25   ┆ 1.70   ┆ 4.56   ┆ 54.41  ┆ 0.27   │
│ 4     ┆ 408   ┆ 0.26    ┆ 2.50    ┆ -3.69  ┆ -1.22  ┆ 0.25   ┆ 1.70   ┆ 4.56   ┆ 54.41  ┆ 0.27   │
│ 5     ┆ 408   ┆ 0.26    ┆ 2.50    ┆ -3.69  ┆ -1.22  ┆ 0.25   ┆ 1.70   ┆ 4.56   ┆ 54.41  ┆ 0.27   │
│ 6     ┆ 408   ┆ 0.26    ┆ 2.50    ┆ -3.69  ┆ -1.22  ┆ 0.25   ┆ 1.70   ┆ 4.56   ┆ 54.41  ┆ 0.27   │
│ 7     ┆ 408   ┆ 0.26    ┆ 2.50    ┆ -3.69  ┆ -1.22  ┆ 0.25   ┆ 1.70   ┆ 4.56   ┆ 54.41  ┆ 0.27   │
│ 8     ┆ 408   ┆ 0.26    ┆ 2.50    ┆ -3.69  ┆ -1.22  ┆ 0.25   ┆ 1.70   ┆ 4.56   ┆ 54.41  ┆ 0.27   │
│ 9     ┆ 408   ┆ 0.26    ┆ 2.50    ┆ -3.69  ┆ -1.22  ┆ 0.25   ┆ 1.70   ┆ 4.56   ┆ 54.41  ┆ 0.27   │
│ 10    ┆ 408   ┆ 0.26    ┆ 2.50    ┆ -3.69  ┆ -1.22  ┆ 0.25   ┆ 1.70   ┆ 4.56   ┆ 54.41  ┆ 0.27   │
└───────┴───────┴─────────┴─────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┘

就算不取 topk, 起码期望收益是正了.

看一下按月收益的小提琴图, 可以发现台风和收益主要发生在七到十一月, 九月的盈利似乎更差一些

不过这不是真正的情况, 删去某些交易记录不等于只开剩下的仓位, 之前的方案没有真正的多标的交易回测.

横截面多股回测

backtesting.py不支持多标的回测, backtrader 太慢只能自己写一个了, 取topk=3、手续费万六, 不考虑滑点, 止损 5%, 开仓目标 100%, n股均分仓位, 信号消失后持仓5天后平仓, 最终得到文章第一张图的结果: 收益统计:

┌───────┬──────────┬─────────┬─────────┬─────────┬─────────┬─────────┬─────────┬─────────┬─────────┐
│ count ┆ ret_pct_ ┆ ret_pct ┆ ret_pct ┆ ret_pct ┆ ret_pct ┆ ret_pct ┆ ret_pct ┆ win_rat ┆ skewnes │
│ ---   ┆ mean     ┆ _std    ┆ _p5     ┆ _p25    ┆ _p50    ┆ _p75    ┆ _p95    ┆ e       ┆ s       │
│ u32   ┆ ---      ┆ ---     ┆ ---     ┆ ---     ┆ ---     ┆ ---     ┆ ---     ┆ ---     ┆ ---     │
│       ┆ f64      ┆ f64     ┆ f64     ┆ f64     ┆ f64     ┆ f64     ┆ f64     ┆ f64     ┆ f64     │
╞═══════╪══════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╡
│ 1098  ┆ 0.5248   ┆ 6.1504  ┆ -6.8922 ┆ -2.7239 ┆ -0.1200 ┆ 2.7980  ┆ 10.1303 ┆ 48.7250 ┆ 3.4956  │
└───────┴──────────┴─────────┴─────────┴─────────┴─────────┴─────────┴─────────┴─────────┴─────────┘

比之前的删除法略差, 如果按照 std5_pct_chg 取 softmax 做开仓比例呢? (之前是均分的), 结果如下:

┌───────┬──────────┬─────────┬─────────┬─────────┬─────────┬─────────┬─────────┬─────────┬─────────┐
│ count ┆ ret_pct_ ┆ ret_pct ┆ ret_pct ┆ ret_pct ┆ ret_pct ┆ ret_pct ┆ ret_pct ┆ win_rat ┆ skewnes │
│ ---   ┆ mean     ┆ _std    ┆ _p5     ┆ _p25    ┆ _p50    ┆ _p75    ┆ _p95    ┆ e       ┆ s       │
│ u32   ┆ ---      ┆ ---     ┆ ---     ┆ ---     ┆ ---     ┆ ---     ┆ ---     ┆ ---     ┆ ---     │
│       ┆ f64      ┆ f64     ┆ f64     ┆ f64     ┆ f64     ┆ f64     ┆ f64     ┆ f64     ┆ f64     │
╞═══════╪══════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╡
│ 1082  ┆ 0.5349   ┆ 6.1787  ┆ -6.8603 ┆ -2.7469 ┆ -0.1200 ┆ 2.8070  ┆ 10.1428 ┆ 48.7985 ┆ 3.4998  │
└───────┴──────────┴─────────┴─────────┴─────────┴─────────┴─────────┴─────────┴─────────┴─────────┘

稍稍变好, 也许用预测的波动率或者 取 softmax 后会更好呢? 后面我会再试试.

下一步

  1. 可以看到策略在2023年以来遇到了大回撤, 我估计是百度指数的问题, 我可能不该把「台风实时路径」这个搜索指数加进去, 因为这个搜索结果只在23~25才有, 但是没有理由之前的人不会搜索这六个字
  2. 也许搜索指数的区域、台风途径区域、公司实体区域三者能有联动
  3. 也许再加上谷歌指数会更好, 但是我之前很担心线性模型不好处理太多自变量
  4. 也许用神经网络而不是线性模型会更好, 毕竟新闻指数跟台风参数不是线性的
  5. 也许使用其他方法分配开仓权重会更好, 比如通过某种方法计算股票对台风敏感度, 按敏感度开仓
  6. 也许真能给每一个股票找到最佳风速阈值
  7. 也许有方法处理高换手率的那些股票, 而不是只有远离才能盈利

求职

为自己找一份 Quant Dev 工作, 不远程的话最好在上海. 我计算机经验足(可见我 博客), 熟悉高性能计算和性能优化(上文手写的七年五千股多标的回测只需要1s), 有集群开发经验. 精通Python, 熟悉 C/C++, 有 Web 全栈能力, 熟悉爬虫, 做过四年计算机视觉和生物信息学. 对量化交易感兴趣, 也有基本的量化能力(本文).

联系方式: