1.SVM用于交易模型的具体算法及模型构建
可见公众号“量化投资与机器学习”发布的文章“量化投资之机器学习应用——基于 SVM
模型的商品期货择时交易策略(提出质疑和讨论)”,文章中对每一步算法都给出了详细的解释,并在后半部分提出了相关问题思考,适合初学者理解和学习。
2.关于SVMcgForClass/SVMcgForRegress中的核函数g和惩罚函数c的理解
在将数据进行归一化处理后,需要进行SVM算法的寻优,寻找最优核函数g和惩罚函数c。在这里会涉及到寻优方法选择的问题,在下面第三点中有详细讨论。c越高,说明越不能容忍出现误差,容易过拟合。c越小,容易欠拟合。c过大或过小,泛化能力都会变差。
“C理解为调节优化方向中两个指标(间隔大小,分类准确度)偏好的权重。soft-margin
SVM针对hard-margin
SVM容易出现的过度拟合问题,适当放宽了margin的大小,容忍一些分类错误(violation),把这些样本当做噪声处理,本质上是间隔大小和噪声容忍度的一种trade-off,至于具体怎么trade-off,对哪个指标要求更高,那就体现在C这个参数上了。
1.当C趋于无穷大时,这个问题也就是不允许出现分类误差的样本存在,那这就是一个hard-margin
SVM问题(过拟合)
2.当C趋于0时,我们不再关注分类是否正确,只要求间隔越大越好,那么我们将无法得到有意义的解且算法不会收敛。(欠拟合)”
g是选择RBF函数作为kernel后,该函数自带的一个参数。隐含地决定了数据映射到新的特征空间后的分布,g越大,支持向量越少,g值越小,支持向量越多。支持向量的个数影响训练与预测的速度。
很多RBF的幅宽会影响每个支持向量对应的高斯的作用范围,从而影响泛化性能。若g太大则高斯分布将又高又瘦,则只会作用于向量样本附近,导致对于未知样本分类效果很差,存在训练准确率可以很高而测试准确率不高的可能(如果无穷小,则理论上,高斯核的SVM可以拟合任何非线性数据,但容易过拟合),就是通常说的过训练;而如果设的过小,则会造成平滑效应太大,无法在训练集上得到特别高的准确率,也会影响测试集的准确率。
3. SVM三种寻优方法的选择
参数寻优常用的方法有:grid
search、GA和PSO。一般情况下,三种方法中网格划分(grid search)的寻优结果准确率最高。李洋先生的
LIBSVM-farutoUltimateVersion3.0 版本中已经给出了全部三种寻优方式的函数,可直接调用。
##关于寻优结果我存在一些疑问:在自己进行模型复现时,绘出的寻优结果图像与参考文献中给出的寻优结果图像呈像差距较大,希望能够对于图像的显示结果能有更深入的探讨。
4.关于SVM算法的MATLAB实现:
原作者给出的部分命令由于函数包的缺失无法执行,因此在参数寻优和算法上还是调用的李洋先生的LIBSVM-farutoUltimateVersion工具箱及台湾大学林智仁先生的libsvm工具箱。
%% %%%%%%%%输入数据%%%%%%%%
data = load('temp.txt')
high = data(:,3); % 最高价
low = data(:,4); % 最低价
close = data(:,1); % 收盘价
open = data(:,2); % 开盘价
average = data(:,5); % 平均价
volume = data(:,6); % 成交量
positions = data(:,7); % 持仓量
date = data(:,8); % 日期
%% %%%%%%%%%%%%处理数据,画出交易量及价格走势图%%%%%%%%%%%%%%%%
length=1634;
figure(1)
ax(1) = subplot(2,1,1);
candle(high,low,close,open,'b')
dateaxis('x', 3, date(1,1))
hold on
plot(average,'r*')
title([num2str(length),'个交易日K线图'])
grid on
ax(2) = subplot(2,1,2);
bar(volume,'FaceColor',[1 0 0],'EdgeColor',[1 1
1],'BarWidth',1);
hold on
plot(positions,'LineWidth',2,'Color',[0 0 1]);
legend('成交量','持仓量')
title('成交量和持仓量走势图')
grid on
dateaxis('x', 2,
date(1,1)) %%% dateaxis('坐标轴',日期格式,'起始日期')
linkaxes(ax,'x')
hold off
%% %%%%%%%%%%%%%% 对数据进行归一化处理 %%%%%%%%%%%%%%%%
[Nrow,Ncol]=size(data);
length=Nrow;
Feature_data = data';
[Feature_data,Feature_data_ps] = mapminmax(Feature_data);
Feature_data = Feature_data';
%% %%%%%%%%%%%%%% SVM算法的寻优 %%%%%%%%%%%%%%%%
%核函数g、惩罚函数c
%[bestCVaccuracy,bestc,bestg]=SVMcgForClass(train_label,train,cmin,cmax,gmin,gmax,v,cstep,gstep,accstep)
%[mse,bestc,bestg] =
SVMcgForRegress(train_label,train,cmin,cmax,gmin,gmax,v,cstep,gstep,msestep)
%v:进行Cross Validation过程中的参数,即对训练集进行v-fold Cross
Validation,默认为3,即默认进行3折CV过程。
%cstep,gstep:进行参数寻优是c和g的步进大小,即c的取值为2^cmin,2^(cmin+cstep),…,2^cmax,,g的取值为2^gmin,2^(gmin+gstep),…,2^gmax,默认取值为cstep=1,gstep=1。
cstep:最后参数选择结果图中准确率离散化显示的步进间隔大小([0,100]之间的一个数),默认为4.5。
%msestep:最后显示准确率图时的步进大小. 默认为 20
llabel = sign(close - open);
Label = llabel;
Train = Feature_data(:,1:2);
[bestmse,bestc,bestg] =
SVMcgForClass(Label,Train,-10,10,-10,10,3,1,1,0.1);%出SVC参数选择结果图
[bestmse1,bestc1,bestg1] =
SVMcgForRegress(Label,Train,-10,10,-10,10,3,1,1,0.1);%出SVR参数选择结果图
%% %%%%%对数据进行训练%%%%%chy
%(1)model= svmtrain(train_label, train_matrix,
['libsvm_options']);
%其中:train_label表示训练集的标签;train_matrix表示训练集的属性矩阵;libsvm_options是需要设置的一系列参数。各参数可参见《libsvm
参数说明.txt》。如果用回归的话,其中的-s参数值应为3。
%model:训练得到的模型,是一个结构体(如果参数中用到-v,得到的就不是结构体,对于分类问题,得到的是交叉检验下的平均分类准确率;对于回归问题,得到的是均方误差)。
%(2)[predicted_label, accuracy/mse,
decision_values]=svmpredict(test_label, test_matrix, model,
['libsvm_options']);
%其中:test_label表示测试集的标签(这个值可以不知道,因为作预测的时候,本来就是想知道这个值的,这个时候,随便制定一个值就可以了,只是这个时候得到的mse就没有意义了)。
% test
_matrix表示测试集的属性矩阵;model是上面训练得到的模型;libsvm_options是需要设置的一系列参数;predicted_label表示预测得到的标签。
window=1500; %训练参数取三分之一附近
traingroup=llabel(1:window,:);
test=llabel(1+window:end,:);
cmd = ['-c ', num2str(bestc), ' -g ', num2str(bestg) , ' -s 3 -p
0.01']; %%% 利用回归预测分析最佳的参数进行SVM网络训练
model = svmtrain(traingroup,Feature_data(1:window,:),cmd);
[predict,mse] =
svmpredict(test,Feature_data(window+1:end,:),model);
%% %%%%%%%%%%%%%% 对预测数据进行归一化处理并转化为0-1变量 %%%%%%%%%%%%%%%%
%归一化
predict = predict';
[predict,predict_ps] = mapminmax(predict);
predict = predict';
%%% 将预测数据转化为0-1变量
predict_cx=predict;
predict_cx(predict_cx>0) = 1;
predict_cx(predict_cx<0) = -1 ;
predict_cx=[traingroup;predict_cx];
%% 结果分析,作图%%%%%%
figure;
hold on;
plot(llabel,'-o');
plot(predict_cx,'r-^');
legend('原始数据','回归预测数据');
hold off;
title('原始数据和回归预测数据对比','FontSize',12);
xlabel('交易日天数50','FontSize',12);
ylabel('开盘数','FontSize',12);
grid on;
figure;
error = predict_cx - llabel;
plot(error,'rd');
title('误差图(predicted data - original data)','FontSize',12);
xlabel('交易日天数50','FontSize',12);
ylabel('误差量','FontSize',12);
grid on;
figure;
error = (predict_cx - llabel)./llabel;
plot(error,'rd');
title('相对误差图(predicted data - original data)/original
data','FontSize',12);
xlabel('交易日天数50','FontSize',12);
ylabel('相对误差量','FontSize',12);
grid on;
snapnow;
%% %%%%%%%%%%%%%交易信号与实际信号对比%%%%%%%%%%%%%
dateaxis('x', 3, date(1+window,1))
r = [0;
predict.*(data(window+1:end,1)-data(window+1:end,2))];%每笔收益
cumr = cumsum(r);
benchmark = data(window+1:end,1);
x = 1:length-window;
ret = cumr+100*ones(length-window+1,1);%累计受获利点数
stop = 25;%设stop为止损点,达到时进行止损策略
for i = 1:length-window+1
if r(i)
r(i) = -stop;
end
end
%% %%%%%%%%%%%%%%%%绘出交易信号图%%%%%%%%%%%%%%%%%%
r1 = r;
r2 = r;
for i = 1:length-window+1
if r1(i) < 0
r1(i) = 0;
end
end
for i = 1:length-window+1
if r2(i) > 0
r2(i) = 0;
end
end
figure(5)
bar(r1,'FaceColor','b','EdgeColor','b')
hold on
bar(r2,'FaceColor','r','EdgeColor','r')
dateaxis('x', 1, date(1+window,1)) %参数3只显示月份
xlabel('交易日期')
ylabel('浮盈浮亏')
title('交易信号图')
grid on
hold off
%% %%%%%%%%%%%%%%%螺纹钢指数收益率分布于交易策略收益率分布%%%%%%%%%%%%%%%%%
figure(6)
subplot(2,1,1)
hist(price2ret(data(:,1:5))) %将数据转化为直方图
legend('开盘价收益率','收盘价收益率','最高价收益率','最低价收益率','结算价收益率')
title('收益率分布图')
grid on
subplot(2,1,2)
cumrdistr = price2ret(ret);
hist(price2ret(ret))
legend('策略交易收益率')
grid on
%% %模型的最大回测
[Maxdrawdown,dd] = maxdrawdown(ret,'return');
%% %螺纹钢指数跟踪及累计收益率曲线图
createfigure(x, cumr,
benchmark,dd)
dateaxis('x', 3, date(1+window,1))
hold off
%% %%%%%%%%%%%%%%%%%%%%%%各项指标的测试结果%%%%%%%%%%%%%%%%%%%%%%%
%模型准确率
k = ones(length-window,1);
z = sum(k(predict_cx(window+1:end,:)==test));
Accuratcy = z/(length-window);
%预期最大回测
rm = price2ret(ret);
Return = tick2ret(ret);
[mean,std] = normfit(Return);
EED = emaxdrawdown(mean,std,5);
%年化夏普比率
SharpeRadio = sqrt(250)*sharpe(rm,0);
%信息比率
Inforatio = inforatio(rm,price2ret(benchmark));
5.问题探讨
函数语句中对于收益率的衡量不够具体化,希望能够使用更贴近于实际决策时使用的指导指标。
由于学习SVM的时间较短,对于SVMpredict给出的预测值理解不够深入。
如何在原有模型的基础上提高准确率并相应地提高收益率?