原创文章第76篇,专注“个人成长与财富自由、世界运作的逻辑, AI量化投资”。
backtrader代表传统量化,而qlib代表AI量化,二者的范式不同。
backtrader擅长规则驱动,更像是传统技术分析的“自动化”版本,当然可以多进程搜索参数空间。但这些策略是无法“自我进化”的,它的进化还是取决于人,使用者自身经验的积累,对策略的改进。传统量化更像经验的规则表达,比如MACD为何是12,26,9,你要仔细问,这就伤感情,本身就是一种“模糊的”经验。
backtrader还提供了一种能力,那就是高度还原真实交易场景以及可以对接实盘的能力。这样,你可以使用历史数据,充分地试验你的想法,而不用真的掏真金白银去试错,又浪费时间,精力又浪费钱,这是量化回测的意义所在。
AI已经进化到今天这一波高峰,理应可以在数据如此丰富的金融业有所作为。
01 数据准备
均值回归模型要求时间序列的平稳,而金融序列大部分都是“不平稳”的。机器学习没有特别就要示,我们可以直接从数据开始。
qlib一开来就是300支股票一起,初学者直接run它的script就蒙了,有效果就有,也不知道如何优化。而且性能 相当考验你的电脑,除了lightGBM之外,其余的models跑起来都很费劲。
我们先从一支我们熟悉指数开始,沪深300或者SPX。
我们使用“收盘价”,“成交量”,以及5天前的数据,“预测””下一天“是”涨“还是”跌“
def make_dataset(df, time_lags=5): df_lag = pd.DataFrame(index=df.index) df_lag["close"] = df["close"] df_lag["volume"] = df["volume"] df_lag["close_Lag%s" % str(time_lags)] = df["close"].shift(time_lags) #df_lag["close_Lag%s_Change" % str(time_lags)] = df_lag["close_Lag%s" % str(time_lags)].pct_change() * 100.0 df_lag["volume_Lag%s" % str(time_lags)] = df["volume"].shift(time_lags) #df_lag["volume_Lag%s_Change" % str(time_lags)] = df_lag["volume_Lag%s" % str(time_lags)].pct_change() * 100.0 #df_lag["close_Direction"] = np.sign(df_lag["close_Lag%s_Change" % str(time_lags)]) df_lag['close_Dir'] = np.sign(df['close'].shift(-1).pct_change()) #df_lag["volume_Direction"] = np.sign(df_lag["volume_Lag%s_Change" % str(time_lags)]) return df_lag.dropna(how='any')
按比例划分数据集:
def get_date_by_percent(start_date, end_date, percent): days = (end_date - start_date).days target_days = np.trunc(days * percent) target_date = start_date + dt.timedelta(days=target_days) # print days, target_days,target_date return target_date def split_dataset(df, input_column_array, output_column, spllit_ratio): split_date = get_date_by_percent(df.index[0], df.index[df.shape[0] - 1], spllit_ratio) input_data = df[input_column_array] output_data = df[output_column] # Create training and test sets X_train = input_data[input_data.index < split_date] X_test = input_data[input_data.index >= split_date] Y_train = output_data[output_data.index < split_date] Y_test = output_data[output_data.index >= split_date] return X_train, X_test, Y_train, Y_test
02 机器学习模型
我们分别实现了”随机森林“,’logistic回归‘,”SVM“三种分类模型:
from sklearn.ensemble import RandomForestClassifier from sklearn.linear_model import LogisticRegression from sklearn.metrics import confusion_matrix from sklearn.svm import LinearSVC, SVC def do_logistic_regression(x_train, y_train): classifier = LogisticRegression() classifier.fit(x_train, y_train) return classifier def do_random_forest(x_train, y_train): classifier = RandomForestClassifier() classifier.fit(x_train, y_train) return classifier def do_svm(x_train, y_train): classifier = SVC() classifier.fit(x_train, y_train) return classifier
03 模型评价
对测试集的数据,计算准确率和得分:
def test_predictor(classifier, x_test, y_test): pred = classifier.predict(x_test) hit_count = 0 total_count = len(y_test) for index in range(total_count): if (pred[index]) == (y_test[index]): hit_count = hit_count + 1 hit_ratio = hit_count / total_count score = classifier.score(x_test, y_test) # print "hit_count=%s, total=%s, hit_ratio = %s" % (hit_count,total_count,hit_ratio) return hit_ratio, score
04 结果
from engine.ml.models import do_svm, do_random_forest, do_logistic_regression, test_predictor lr_classifier = do_logistic_regression(X_train, Y_train) lr_hit_ratio, lr_score = test_predictor(lr_classifier, X_test, Y_test) rf_classifier = do_random_forest(X_train, Y_train) rf_hit_ratio, rf_score = test_predictor(rf_classifier, X_test, Y_test) svm_classifier = do_svm(X_train, Y_train) svm_hit_ratio, svm_score = test_predictor(rf_classifier, X_test, Y_test) print("%s : Hit Ratio - Logistic Regreesion=%0.2f, RandomForest=%0.2f, SVM=%0.2f" % ( 'name', lr_hit_ratio, rf_hit_ratio, svm_hit_ratio))
结果如预期不理想,
name : Hit Ratio - Logistic Regreesion=0.51, RandomForest=0.49, SVM=0.49
50%左右,跟瞎猜差不多,意料之中,哪有这么容易,那门槛也太低了。
机器学习只是一种高级”统计“手段,投资并没有圣杯。
但这项工作很有意义,机器学习的基本框架上述代码基本都呈现出来了。
就是数据集准备,数据划分,然后模型训练,模型检验。
交付使用时,直接接到backtrader里即可。
总结:本篇使用了sklearn内置的三种模型,对小数据集进行了简单的”分类“预测,皆在显示如何把机器学习算法应用于金融时间序列上。