原创文章第603篇,专注“AI量化投资、世界运行的规律、个人成长与财富自由"。
我们重新更新了可转债的全量数据,包含全量已经退市的转债。
——这是与股票市场不一样的地方,股票退市相对少,而转债本身就有退出周期。
因此,如果没有包含进来,那么策略就是有偏差的。
双低指标,单调性非常好:



单因子回测一下:

年化27.9%,最大回撤-13.6%。
策略核心代码如下:
import bt
from bt_algos_extend import SelectTopK
order_by = 'close'#'double_low'#'double_low'
signal = CSVDataloader.get_col_df(df,col=order_by)
#signal.dropna(inplace=True)
all = []
for K in [30,]:
s = bt.Strategy('可转债单因子策略'.format(K), [
bt.algos.RunWeekly(),
SelectTopK(signal,K,sort_descending=False),
bt.algos.WeighEqually(),
bt.algos.Rebalance()])
all.append(s)
stras = [bt.Backtest(s, data) for s in all]

把转债的价格单独拆分出来:

分层单调性一般:

IC值很好,但回测结果一般。

回测结果,年化12.6%,最大回撤-11.7%。

转股溢价率因子——单调性良好:


IC值一般:

年化28.6%,回撤-33.6%。

三个因子的分析结果看下来,有一个简单的结果:
分层单调性,对于轮动因子非常。
IC值大,但分层效果不好,大概率因子里包含了非线性因素。
IC值大的因子,可以经由机器学习模型来组合。
今天我们开始用机器学习的方式来初筛因子集。
咱们还是使用lightGBM集成学习的方式,决策树是可以筛选特征的重要性的。
import pandas as pd
from lightgbm import LGBMRegressor
from sklearn.metrics import mean_squared_error, r2_score
def calc_metrics(model, X, y):
y_pred = model.predict(X)
mse = mean_squared_error(y, y_pred)
r2 = r2_score(y, y_pred)
print('r2:', r2, 'mse:', mse)
def split_data(df, date):
df_train = df[df.index <= date]
df_val = df[df.index > date]
return df_train, df_val
def train(df_train, df_val, feature_cols, label_col='label'):
model = LGBMRegressor(boosting='gbdt', # gbdt \ dart
n_estimators=600, # 迭代次数
learning_rate=0.1, # 步长
max_depth=10, # 树的最大深度
seed=42, # 指定随机种子,为了复现结果
num_leaves=250,
# min_split_gain=0.01,
lambda_l1=2,
lambda_l2=2000
)
X_train = df_train[feature_cols]
y_train = df_train[label_col]
X_test = df_val[feature_cols]
y_test = df_val[label_col]
model.fit(X_train, y_train)
calc_metrics(model, X_train, y_train)
calc_metrics(model, X_test, y_test)
"""模型保存"""
from config import DATA_DIR
# model.booster_.save_model(DATA_DIR.joinpath('models').joinpath('lgb_regressor.txt'))
feat_importances = pd.Series(model.feature_importances_, index=X_train.columns).sort_values(ascending=False)
print(feat_importances.head(20))
return model
if __name__ == '__main__':
import pandas as pd
from config import DATA_DIR_BASIC
from datafeed.dataloader import CSVDataloader
# bonds = pd.read_csv(DATA_DIR_BASIC.joinpath('cb_list2.csv'))
# bonds = bonds[bonds['delist_date'] is None]
# bonds = bonds['ts_code']
df = CSVDataloader.get_df(symbols=None, set_index=True, start_date='20190101', path='bonds_all')
print(df)
df = CSVDataloader.calc_expr(df, ['close+cb_over_rate', 'roc(close,20)', 'ta_cci(high,low,close,20)',
'shift(close,-10)/close-1'],
['double_low', 'roc_20', 'cci_20', 'label'])
df.dropna(inplace=True)
df_train, df_val = split_data(df, '2023-12-31')
train(df_train, df_val, feature_cols=['cb_over_rate','close','bond_value','cb_value','ps_ttm','bond_over_rate','double_low', 'pb','pe_ttm'], label_col='label')
机器学习的权重排序:

bond_value IC值不明显,分层不单调,但lightGBM的权重重要性很高。这一点是比较矛盾的。
代码在这里:

AI量化实验室——2024量化投资的星辰大海

吾日三省吾身
欲速则不达。——这句老话非常有道理。
有时候,我们总希望把一些不喜欢的事情,尽快终结掉。
在评估不够充分时就快速推进事情。
结果有可能,事情也许办了,但引入其他更加不可控的事情。
有时候,淡定一点,把事情处理得稳妥一点,后续的事情会更少。
好事多磨,淡定一点。
历史文章:
全量可转债:平价底价溢价率与正股PB的单因子分析(附python代码)
代码发布:quantlabv5.3,可转债所有数据及双低、动量因子策略,单因子分析框架
量化私募公司的多因子构建方案(附python代码)
年化22.8%的单因子分析:基于Alphalens做可转债全市场数据的单因子分析(附python代码+全量数据)
AI量化实验室——2024量化投资的星辰大海



















