【专题研究】基于SVM支持向量机模型的选股策略

svm
专题报告
机器学习
策略分享
标签: #<Tag:0x00007fc5786f53c0> #<Tag:0x00007fc5786f5280> #<Tag:0x00007fc5786f5140> #<Tag:0x00007fc5786f5000>

(iQuant) #1

研究过集成学习中的 随机森林XGBoost后,本文将介绍一种更传统的机器学习方法:SVM支持向量机。SVM由于其较高的准确度,并且能够解决非线性分类问题,曾一度成为非常流行的机器学习算法。本文分别介绍线性支持向量机和核支持向量机,探究SVM如何解决线性和非线性分类、回归问题,最后以一个实例展示SVM模型在选股方面的应用。


$$目录$$
1、SVM原理介绍
1.1 线性支持向量机
1.2 核支持向量机
2、SVM关键问题
2.1 核函数的选取
2.2 C和$\gamma$的调整
2.3 模型评价
3、实例:SVM模型选股


1、SVM原理介绍

支持向量机(Support Vector Machine,SVM)可分为线性支持向量机和核支持向量机,前者针对线性分类问题,后者属于非线性分类器。支持向量回归也能够处理回归问题。

1.1 线性支持向量机

最大间隔分类

最大间隔分类是寻找最佳分类边界的核心原则。简单来讲,就是在所有可能的分类界面中,寻找使分类边缘最宽的界面。


$$图1:最大间隔分类示意图$$
如图1,红色和蓝色两条直线,称为最大边缘超平面(Maximum Margin Hyperplane),类似于“楚河汉界”。这条“楚河汉界”越宽,分类的效果应越好,所以根据最大间隔分类原则,左图的分类效果优于右图。

用数学语言表示,二维平面中的任意一条直线均可以表示为$𝑤_1𝑥_1 + 𝑤_2𝑥_2 + 𝑏 = 0$的形式,简记为$𝒙^𝑇𝒘 + 𝑏 = 0$,图2中的分类超平面(黑色直线)表示为$𝒙^𝑇𝒘 + 𝑏 = 0$,其上方的最大边缘超平面(红色直线)则相应表示为$𝒙^𝑇𝒘 + 𝑏 − 1 = 0$,即$𝒙^𝑇𝒘 + 𝑏 = 1$。类似地,下方的最大边缘超平面(黑色直线)表示为$𝒙^𝑇𝒘 + 𝑏 = −1$。两个最大边缘超平面之间的间隔等于$2/‖𝒘‖$,其中$‖𝒘‖$为向量$w$的2范数,即各元素平方和的平方根。


$$图2:SVM分类超平面与最大边缘超平面$$
线性支持向量机的目标是寻找一组直线的参数$𝒘$和$b$,使得分类间隔取得最大值。目标函数:
$$\max_{w,b}\frac{2}{||w||}$$
更常用的目标函数是上式的等价形式:
$$\min_{w,b}\frac{||w||^2}{2}$$
约束条件为:
$$𝑦_𝑖 (𝒙_𝑖^𝑇𝒘 + 𝑏) ≥ 1$$
即所有样本均归入正确的类别。其中$(𝒙_𝑖 , 𝑦_𝑖 )$表示第i 个样本的特征和标签。

松弛变量

上面讨论的只是理想情况,绝大多数时候,数据中会包含噪音,难以用一条直线将两类样本完美地区分开来。此时就需要引入松弛变量的概念。对每个样本点赋予一个松弛变量的值:如果该点落在最大边缘超平面正确的一侧,则松弛变量$𝜉 = 0$;否则,松弛变量的值等于该点到最大边缘超平面的距离。


$$图3:松弛变量示意图$$
如图3,被正确分类的样本其松弛变量的值$𝜉 = 0$;少数样本点落在分类边界(黑线)对方一侧,这些错误分类的样本其松弛变量的值$𝜉 > 1$,即红/蓝色样本点到红/蓝线的距离;还有部分样本点尽管
落在分类边界本方一侧,但距离最大边缘超平面不够远,其松弛变量的值取一个较小的正数$0 < 𝜉 ≤ 1$。

此时线性支持向量机的目标函数改写为:
$$\min_{w,b,𝜉}(\frac{||w||^2}{2}+C\sum_{i=1}^{n}𝜉_i)$$
约束条件为:
$$𝑦_𝑖 (𝒙_𝑖^𝑇𝒘 + 𝑏) ≥ 1-𝜉_i, \quad 𝜉_i≥0$$
引入松弛变量后,目标函数在原有的基础之上新加入$C\sum_{i=1}^{n}𝜉_i$一项,即所有样本松弛变量之和乘以系数C。这里的系数C 称为惩罚系数,表示模型对错误分类的容忍度。当C取较大的数时,即使很小的松弛变量也会造成很大的损失,因此分类器对错误分类的容忍度较低,将尽可能保证分类正确,从而导致较高的训练集正确率(如图4 左图)。反之,当C 取较小的数时,分类器对错误分类的容忍度较高,允许错误分类的存在,分类器倾向于以最大间隔分类的原则进行分类(如图表4 右图)。


$$图4:惩罚系数示意图$$

支持向量回归

在分类问题的损失函数之上稍加改动,就能得到用于回归问题的支持向量回归(Support Vector Regression),其损失函数为:
$$\min_{w,b,𝜉,𝜉^*}(\frac{||w||^2}{2}+C\sum_{i=1}^{n}(𝜉_i+𝜉_{i}^{*})$$
约束条件为:
$$-\xi-𝜉_{i}^{*}\leq𝑦_𝑖 -(𝒙_𝑖^𝑇𝒘 + 𝑏) \leq \xi+𝜉_{i}^{*}, \quad 𝜉_i,𝜉_{i}^{*}≥0 \quad \text {$\xi$表示预测误差的容忍量} $$

1.2 核支持向量机

非线性分类

线性支持向量机能够处理线性分类问题,然而对于非线性分类问题,我们需要寻找新的解决途径——增加维度。


$$图5:非线性分类:异或问题$$
如图5,左图是不可能在二维平面内被一条直线分类的,因此考虑增维,将二维点投射到三维空间,从而在三维空间内可以找到一个超平面成功分开蓝色/红色。

核支持向量机同理:非线性分类转化为线性分类。首先通过非线性映射𝜙把原始数据𝑥变换到高维特征空间,随后使用线性支持向量机对高维空间下的数据进行分类,从而解决非线性分类问题:
$$ 𝒙 ⟼ 𝜙(𝒙) = (𝜙_1(𝒙), … , 𝜙_𝑘 (𝒙), … ) $$

核函数

核函数是为了减少映射到高维空间后的计算量而设计的一个内积函数:$𝐾(𝒙_𝑖 , 𝒙_𝑗 ) =〈𝒙_𝑖 , 𝒙_𝑗 〉^2$,从而让目标函数不含低维到高维映射方式𝜙的显式表达,仅与核函数的选取有关:
$$\min_{\alpha}(\sum_{i=1}^{n}\alpha_i-\frac{1}{2}\sum_{i,j=1}^{n}y_iy_j\alpha_i\alpha_jK(x_i,x_j))$$
任意一种映射方式都对应一个确定的核函数,理论上任何满足一定数学性质的核函数都可以成为核支持向量机的核函数。在实际应用中,通常使用线性核、多项式核、Sigmoid 核和高斯核等。不同核函数的分类性能和分类边界不尽相同,所以如何选择核函数是使用SVM的关键问题之一,本文将在下方详细阐述。


$$图6:常用核函数$$
如图6所示,多项式核、Sigmoid 核和高斯核的核函数都包含$\gamma$值一项。$\gamma$决定了原始数据映射到高维数据后,在高维特征空间中的分布。$\gamma$越大,样本在高维空间中的分布越稀疏,样本之间间隔越远,更容易被分类边界区分开来。$\gamma$的选取影响着模型准确度,同样是SVM使用中的关键问题,下文会具体阐述。

2、SVM关键问题

2.1 核函数的选取

在选核函数之前,我们首先要确定数据集是否线性可分。低维数据可以直接画图辨认,高维数据可以检查凸包(convex hull)是否相交,不相交,则线性可分。

确定线性不可分之后,需要采用核支持向量机模型,这就涉及了核函数选取问题:

核函数 用处
线性核 线性可分时,特征数量多时,样本数量多再补充一些特征时,linear kernel可以是RBF kernel的特殊情况
多项式 image processing,参数比RBF多,取值范围是(0,inf)
RBF 通用,线性不可分时,特征维数少 样本数量正常时,在没有先验知识时用,取值在[0,1]
Sigmoid 生成神经网络,在某些参数下和RBF很像,可能在某些参数下是无效的
高斯核 通用,在没有先验知识时用
Laplace RBF 通用,在没有先验知识时用
Hyperbolic tangent 一般用于神经网络
Bessel function of the first kind Kernel 可消除函数中的交叉项
ANOVA radial basis 一般用于回归问题
一维Linear splines text categorization,回归问题,处理大型稀疏向量

不同核函数的分类性能和分类边界不尽相同。实际使用中,一般采用线性核、高斯核、RBF和多项式核。图7展示了对同一组数据使用不同核函数的分类表现。线性核的分类边界为直线,多项式核、Sigmoid 核和高斯核的分类边界在高维空间中为超平面,在原始空间中为曲线。线性核、低阶多项式核和Sigmoid 核计算速度快,不容易过拟合,但是在复杂分类问题下表现不佳。高阶多项式核和高斯核的优点是能够求解复杂的边界,对训练样本的分类能力强大,缺点是计算速度缓慢,并且可能导致过拟合。实际使用中需要根据数据自身的特点,选择最合适的核函数。
%E6%8D%95%E8%8E%B7
$$图7:不同核函数的分类表现$$

2.2 C和$\gamma$的调整

惩罚系数C和$\gamma$是影响支持向量分类器性能的关键参数。实际应用中,当数据量较小的候,可以采用“网格搜索”对C和$\gamma$进行遍历,选择全局最优参数。但是“网格搜索”计算量很大,一般难以进行,所以我们主要还是根据C和$\gamma$的影响进行判断。

C和$\gamma$越大,惩罚越多,分类器对于错误的容忍程度低;同时经过映射后的样本在高维空间的分布越稀疏,更容易被区分。这都会导致训练集的正确率更高,但是也可能带来“过拟合”问题,使得偏差bias减小但variance方差增大。具体参数选择需要多尝试。

2.3 模型评价

可参见 随机森林专题研究

3、实例:SVM模型选股

%E6%B5%81%E7%A8%8B
$$图8:SVM智能选股策略$$
如图8所示,一个基础的SVM选股策略构建包含下列步骤:

  • 获取数据 :A股所有股票。
  • 特征和标签提取 :计算18个因子作为样本特征;计算未来5日的个股收益,收益率前95%的标注为1,其余标注为0。
  • 特征预处理 :进行缺失值处理;去掉特征异常的股票,比如某个特征值高于99.5%或低于0.5%的;标准化处理,去除特征量纲/数量级差异的影响。
  • 模型训练与预测 :使用SVM模型进行训练和预测;尝试多种核函数。
  • 策略回测 :利用2015到2016年数据进行训练,预测2016到2017年的股票表现。每周等权重买入预测值为1的50只股票(深市优先),至少持有五日,同时淘汰预测值为0的股票。
  • 模型评价 :查看模型回测结果;对比不同核函数的策略结果。

不同核函数的回测效果如下:
【线性核】


$$图9:线性核SVM选股$$

【多项式(3项)】


$$图10:多项式核SVM选股$$

【RBF】


$$图11:RBF核SVM选股$$

【Sigmoid】


$$图12:Sigmoid核SVM选股$$

由上图可见,线性核和RBF的回测效果明显优于多项式和Sigmoid核函数;并且RBF表现更稳定,最大回撤最小,为8.7%。综合策略收益和风险的平衡来看,RBF在几个核函数中表现最优。

整体来讲,此策略还有很大的改进空间,如改变因子选取、股票标注方式、策略逻辑、SVM参数等,大家可以进一步探索。

克隆策略

    {"Description":"实验创建于2017/8/26","Summary":"","Graph":{"EdgesInternal":[{"DestinationInputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-15:instruments","SourceOutputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-8:data"},{"DestinationInputPortId":"-787:instruments","SourceOutputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-8:data"},{"DestinationInputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-53:data1","SourceOutputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-15:data"},{"DestinationInputPortId":"-787:features","SourceOutputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-24:data"},{"DestinationInputPortId":"-794:features","SourceOutputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-24:data"},{"DestinationInputPortId":"-803:features","SourceOutputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-24:data"},{"DestinationInputPortId":"-810:features","SourceOutputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-24:data"},{"DestinationInputPortId":"-8155:input_2","SourceOutputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-24:data"},{"DestinationInputPortId":"-8144:features","SourceOutputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-24:data"},{"DestinationInputPortId":"-131:features","SourceOutputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-24:data"},{"DestinationInputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-84:input_data","SourceOutputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-53:data"},{"DestinationInputPortId":"-803:instruments","SourceOutputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-62:data"},{"DestinationInputPortId":"-982:instruments","SourceOutputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-62:data"},{"DestinationInputPortId":"-8155:input_1","SourceOutputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-84:data"},{"DestinationInputPortId":"-8155:input_3","SourceOutputPortId":"-86:data"},{"DestinationInputPortId":"-794:input_data","SourceOutputPortId":"-787:data"},{"DestinationInputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-53:data2","SourceOutputPortId":"-794:data"},{"DestinationInputPortId":"-810:input_data","SourceOutputPortId":"-803:data"},{"DestinationInputPortId":"-86:input_data","SourceOutputPortId":"-810:data"},{"DestinationInputPortId":"-8144:train_ds","SourceOutputPortId":"-8155:data_1"},{"DestinationInputPortId":"-8144:test_ds","SourceOutputPortId":"-8155:data_2"},{"DestinationInputPortId":"-131:training_ds","SourceOutputPortId":"-8144:train_data"},{"DestinationInputPortId":"-131:predict_ds","SourceOutputPortId":"-8144:test_data"},{"DestinationInputPortId":"-982:options_data","SourceOutputPortId":"-131:predictions"}],"ModuleNodes":[{"Id":"287d2cb0-f53c-4101-bdf8-104b137c8601-8","ModuleId":"BigQuantSpace.instruments.instruments-v2","ModuleParameters":[{"Name":"start_date","Value":"2015-01-01","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"end_date","Value":"2016-05-31","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"market","Value":"CN_STOCK_A","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"instrument_list","Value":"","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"max_count","Value":"0","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"rolling_conf","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-8"}],"OutputPortsInternal":[{"Name":"data","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-8","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":1,"IsPartOfPartialRun":null,"Comment":"","CommentCollapsed":true},{"Id":"287d2cb0-f53c-4101-bdf8-104b137c8601-15","ModuleId":"BigQuantSpace.advanced_auto_labeler.advanced_auto_labeler-v2","ModuleParameters":[{"Name":"label_expr","Value":"shift(close, -5) / shift(open, -1)-1\nrank(label) #收益率排名\n#where(label>=0.95,1,where(label<=0.1, 0, NaN))\n# 收益率前1/4的标注为1,后1/4的标注为0,中间的为NA\nwhere(label>=0.95,1,0)","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"start_date","Value":"","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"end_date","Value":"","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"benchmark","Value":"000300.SHA","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"drop_na_label","Value":"False","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"cast_label_int","Value":"False","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"user_functions","Value":"","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"instruments","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-15"}],"OutputPortsInternal":[{"Name":"data","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-15","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":2,"IsPartOfPartialRun":null,"Comment":"","CommentCollapsed":true},{"Id":"287d2cb0-f53c-4101-bdf8-104b137c8601-24","ModuleId":"BigQuantSpace.input_features.input_features-v1","ModuleParameters":[{"Name":"features","Value":"(close_0-mean(close_0,12))/mean(close_0,12)*100\nrank(std(amount_0,15))\nrank_avg_amount_0/rank_avg_amount_8\nts_argmin(low_0,20)\nrank_return_30\n(low_1-close_0)/close_0\nta_bbands_lowerband_14_0\nmean(mf_net_pct_s_0,4)\namount_0/avg_amount_3\nreturn_0/return_5\nreturn_1/return_5\nrank_avg_amount_7/rank_avg_amount_10\nta_sma_10_0/close_0\nsqrt(high_0*low_0)-amount_0/volume_0*adjust_factor_0\navg_turn_15/(turn_0+1e-5)\nreturn_10\nmf_net_pct_s_0\n(close_0-open_0)/close_1\n ","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"features_ds","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-24"}],"OutputPortsInternal":[{"Name":"data","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-24","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":3,"IsPartOfPartialRun":null,"Comment":"","CommentCollapsed":true},{"Id":"287d2cb0-f53c-4101-bdf8-104b137c8601-53","ModuleId":"BigQuantSpace.join.join-v3","ModuleParameters":[{"Name":"on","Value":"date,instrument","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"how","Value":"inner","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"sort","Value":"False","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"data1","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-53"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"data2","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-53"}],"OutputPortsInternal":[{"Name":"data","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-53","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":7,"IsPartOfPartialRun":null,"Comment":"","CommentCollapsed":true},{"Id":"287d2cb0-f53c-4101-bdf8-104b137c8601-62","ModuleId":"BigQuantSpace.instruments.instruments-v2","ModuleParameters":[{"Name":"start_date","Value":"2016-06-01","ValueType":"Literal","LinkedGlobalParameter":"交易日期"},{"Name":"end_date","Value":"2017-01-01","ValueType":"Literal","LinkedGlobalParameter":"交易日期"},{"Name":"market","Value":"CN_STOCK_A","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"instrument_list","Value":"","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"max_count","Value":"0","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"rolling_conf","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-62"}],"OutputPortsInternal":[{"Name":"data","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-62","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":9,"IsPartOfPartialRun":null,"Comment":"预测数据,用于回测和模拟","CommentCollapsed":false},{"Id":"287d2cb0-f53c-4101-bdf8-104b137c8601-84","ModuleId":"BigQuantSpace.dropnan.dropnan-v1","ModuleParameters":[],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"input_data","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-84"}],"OutputPortsInternal":[{"Name":"data","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-84","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":13,"IsPartOfPartialRun":null,"Comment":"","CommentCollapsed":true},{"Id":"-86","ModuleId":"BigQuantSpace.dropnan.dropnan-v1","ModuleParameters":[],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"input_data","NodeId":"-86"}],"OutputPortsInternal":[{"Name":"data","NodeId":"-86","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":14,"IsPartOfPartialRun":null,"Comment":"","CommentCollapsed":true},{"Id":"-787","ModuleId":"BigQuantSpace.general_feature_extractor.general_feature_extractor-v7","ModuleParameters":[{"Name":"start_date","Value":"","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"end_date","Value":"","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"before_start_days","Value":0,"ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"instruments","NodeId":"-787"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"features","NodeId":"-787"}],"OutputPortsInternal":[{"Name":"data","NodeId":"-787","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":15,"IsPartOfPartialRun":null,"Comment":"","CommentCollapsed":true},{"Id":"-794","ModuleId":"BigQuantSpace.derived_feature_extractor.derived_feature_extractor-v3","ModuleParameters":[{"Name":"date_col","Value":"date","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"instrument_col","Value":"instrument","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"drop_na","Value":"False","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"remove_extra_columns","Value":"False","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"user_functions","Value":"","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"input_data","NodeId":"-794"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"features","NodeId":"-794"}],"OutputPortsInternal":[{"Name":"data","NodeId":"-794","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":16,"IsPartOfPartialRun":null,"Comment":"","CommentCollapsed":true},{"Id":"-803","ModuleId":"BigQuantSpace.general_feature_extractor.general_feature_extractor-v7","ModuleParameters":[{"Name":"start_date","Value":"","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"end_date","Value":"","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"before_start_days","Value":0,"ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"instruments","NodeId":"-803"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"features","NodeId":"-803"}],"OutputPortsInternal":[{"Name":"data","NodeId":"-803","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":17,"IsPartOfPartialRun":null,"Comment":"","CommentCollapsed":true},{"Id":"-810","ModuleId":"BigQuantSpace.derived_feature_extractor.derived_feature_extractor-v3","ModuleParameters":[{"Name":"date_col","Value":"date","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"instrument_col","Value":"instrument","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"drop_na","Value":"False","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"remove_extra_columns","Value":"False","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"user_functions","Value":"","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"input_data","NodeId":"-810"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"features","NodeId":"-810"}],"OutputPortsInternal":[{"Name":"data","NodeId":"-810","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":18,"IsPartOfPartialRun":null,"Comment":"","CommentCollapsed":true},{"Id":"-982","ModuleId":"BigQuantSpace.trade.trade-v4","ModuleParameters":[{"Name":"start_date","Value":"","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"end_date","Value":"","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"handle_data","Value":"# 回测引擎:每日数据处理函数,每天执行一次\ndef bigquant_run(context, data):\n \n context.extension['index'] += 1\n # 不在换仓日就return,相当于后面的代码只会一周运行一次,买入的股票会持有一周\n if context.extension['index'] % context.rebalance_days != 0:\n return \n \n # 当前的日期\n date = data.current_dt.strftime('%Y-%m-%d')\n \n cur_data = context.indicator_data[context.indicator_data['date'] == date]\n # 根据日期获取调仓需要买入的股票的列表\n #stock_to_buy = list(cur_data.instrument[:context.stock_num])\n cur_data = cur_data[cur_data['pred_label'] == 1.0]\n \n stock_to_buy = list(cur_data.sort_values('instrument',ascending=False).instrument)[:context.stock_num]\n if date == '2017-02-06':\n print(date, len(stock_to_buy), stock_to_buy)\n # 通过positions对象,使用列表生成式的方法获取目前持仓的股票列表\n stock_hold_now = [equity.symbol for equity in context.portfolio.positions]\n # 继续持有的股票:调仓时,如果买入的股票已经存在于目前的持仓里,那么应继续持有\n no_need_to_sell = [i for i in stock_hold_now if i in stock_to_buy]\n # 需要卖出的股票\n stock_to_sell = [i for i in stock_hold_now if i not in no_need_to_sell]\n \n # 卖出\n for stock in stock_to_sell:\n # 如果该股票停牌,则没法成交。因此需要用can_trade方法检查下该股票的状态\n # 如果返回真值,则可以正常下单,否则会出错\n # 因为stock是字符串格式,我们用symbol方法将其转化成平台可以接受的形式:Equity格式\n\n if data.can_trade(context.symbol(stock)):\n # order_target_percent是平台的一个下单接口,表明下单使得该股票的权重为0,\n # 即卖出全部股票,可参考回测文档\n context.order_target_percent(context.symbol(stock), 0)\n \n # 如果当天没有买入的股票,就返回\n if len(stock_to_buy) == 0:\n return\n\n # 等权重买入 \n weight = 1 / len(stock_to_buy)\n \n # 买入\n for stock in stock_to_buy:\n if data.can_trade(context.symbol(stock)):\n # 下单使得某只股票的持仓权重达到weight,因为\n # weight大于0,因此是等权重买入\n context.order_target_percent(context.symbol(stock), weight)\n ","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"prepare","Value":"# 回测引擎:准备数据,只执行一次\ndef bigquant_run(context):\n pass\n","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"initialize","Value":"# 回测引擎:初始化函数,只执行一次\ndef bigquant_run(context):\n # 加载预测数据\n context.indicator_data = context.options['data'].read_df()\n\n # 系统已经设置了默认的交易手续费和滑点,要修改手续费可使用如下函数\n context.set_commission(PerOrder(buy_cost=0.0003, sell_cost=0.0013, min_cost=5))\n context.rebalance_days = 5\n context.stock_num = 50\n if 'index' not in context.extension:\n context.extension['index'] = 0\n \n","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"before_trading_start","Value":"# 回测引擎:每个单位时间开始前调用一次,即每日开盘前调用一次。\ndef bigquant_run(context, data):\n pass\n","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"volume_limit","Value":"0","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"order_price_field_buy","Value":"open","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"order_price_field_sell","Value":"open","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"capital_base","Value":"10000000","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"auto_cancel_non_tradable_orders","Value":"True","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"data_frequency","Value":"daily","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"price_type","Value":"后复权","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"product_type","Value":"股票","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"plot_charts","Value":"True","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"backtest_only","Value":"False","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"benchmark","Value":"","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"instruments","NodeId":"-982"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"options_data","NodeId":"-982"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"history_ds","NodeId":"-982"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"benchmark_ds","NodeId":"-982"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"trading_calendar","NodeId":"-982"}],"OutputPortsInternal":[{"Name":"raw_perf","NodeId":"-982","OutputType":null}],"UsePreviousResults":false,"moduleIdForCode":4,"IsPartOfPartialRun":null,"Comment":"","CommentCollapsed":true},{"Id":"-8155","ModuleId":"BigQuantSpace.cached.cached-v3","ModuleParameters":[{"Name":"run","Value":"# Python 代码入口函数,input_1/2/3 对应三个输入端,data_1/2/3 对应三个输出端\ndef bigquant_run(input_1, input_2, input_3):\n train_df = input_1.read()\n features = input_2.read()\n feature_min = train_df[features].quantile(0.005)\n feature_max = train_df[features].quantile(0.995)\n train_df[features] = train_df[features].clip(feature_min,feature_max,axis=1) #去极值\n data_1 = DataSource.write_df(train_df)\n test_df = input_3.read()\n test_df[features] = test_df[features].clip(feature_min,feature_max,axis=1)\n data_2 = DataSource.write_df(test_df)\n return Outputs(data_1=data_1, data_2=data_2, data_3=None)\n","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"post_run","Value":"# 后处理函数,可选。输入是主函数的输出,可以在这里对数据做处理,或者返回更友好的outputs数据格式。此函数输出不会被缓存。\ndef bigquant_run(outputs):\n return outputs\n","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"input_ports","Value":"","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"params","Value":"{}","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"output_ports","Value":"","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"input_1","NodeId":"-8155"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"input_2","NodeId":"-8155"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"input_3","NodeId":"-8155"}],"OutputPortsInternal":[{"Name":"data_1","NodeId":"-8155","OutputType":null},{"Name":"data_2","NodeId":"-8155","OutputType":null},{"Name":"data_3","NodeId":"-8155","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":6,"IsPartOfPartialRun":null,"Comment":"去掉特征异常的股票,比如某个特征值高于99.5%或低于0.5%的","CommentCollapsed":false},{"Id":"-8144","ModuleId":"BigQuantSpace.RobustScaler.RobustScaler-v13","ModuleParameters":[{"Name":"scale_type","Value":"standard","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"quantile_range_min","Value":"0.01","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"quantile_range_max","Value":"0.99","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"global_scale","Value":"True","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"train_ds","NodeId":"-8144"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"features","NodeId":"-8144"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"test_ds","NodeId":"-8144"}],"OutputPortsInternal":[{"Name":"train_data","NodeId":"-8144","OutputType":null},{"Name":"test_data","NodeId":"-8144","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":8,"IsPartOfPartialRun":null,"Comment":"","CommentCollapsed":true},{"Id":"-131","ModuleId":"BigQuantSpace.svc.svc-v1","ModuleParameters":[{"Name":"C","Value":"1","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"kernel","Value":"rbf","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"degree","Value":3,"ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"gamma","Value":"-1","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"coef0","Value":0,"ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"tol","Value":"0.1","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"max_iter","Value":"100","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"key_cols","Value":"date,instrument","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"other_train_parameters","Value":"{}","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"training_ds","NodeId":"-131"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"features","NodeId":"-131"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"model","NodeId":"-131"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"predict_ds","NodeId":"-131"}],"OutputPortsInternal":[{"Name":"output_model","NodeId":"-131","OutputType":null},{"Name":"predictions","NodeId":"-131","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":10,"IsPartOfPartialRun":null,"Comment":"","CommentCollapsed":true}],"SerializedClientData":"<?xml version='1.0' encoding='utf-16'?><DataV1 xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'><Meta /><NodePositions><NodePosition Node='287d2cb0-f53c-4101-bdf8-104b137c8601-8' Position='63,4,200,200'/><NodePosition Node='287d2cb0-f53c-4101-bdf8-104b137c8601-15' Position='-66,124,200,200'/><NodePosition Node='287d2cb0-f53c-4101-bdf8-104b137c8601-24' Position='656,-21,200,200'/><NodePosition Node='287d2cb0-f53c-4101-bdf8-104b137c8601-53' Position='151,308,200,200'/><NodePosition Node='287d2cb0-f53c-4101-bdf8-104b137c8601-62' Position='1077,121,200,200'/><NodePosition Node='287d2cb0-f53c-4101-bdf8-104b137c8601-84' Position='149,395,200,200'/><NodePosition Node='-86' Position='1078,418,200,200'/><NodePosition Node='-787' Position='301,127,200,200'/><NodePosition Node='-794' Position='304,212,200,200'/><NodePosition Node='-803' Position='1078,236,200,200'/><NodePosition Node='-810' Position='1081,327,200,200'/><NodePosition Node='-982' Position='716,821,200,200'/><NodePosition Node='-8155' Position='556,417,200,200'/><NodePosition Node='-8144' Position='555,594,200,200'/><NodePosition Node='-131' Position='567,712,200,200'/></NodePositions><NodeGroups /></DataV1>"},"IsDraft":true,"ParentExperimentId":null,"WebService":{"IsWebServiceExperiment":false,"Inputs":[],"Outputs":[],"Parameters":[{"Name":"交易日期","Value":"","ParameterDefinition":{"Name":"交易日期","FriendlyName":"交易日期","DefaultValue":"","ParameterType":"String","HasDefaultValue":true,"IsOptional":true,"ParameterRules":[],"HasRules":false,"MarkupType":0,"CredentialDescriptor":null}}],"WebServiceGroupId":null,"SerializedClientData":"<?xml version='1.0' encoding='utf-16'?><DataV1 xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'><Meta /><NodePositions></NodePositions><NodeGroups /></DataV1>"},"DisableNodesUpdate":false,"Category":"user","Tags":[],"IsPartialRun":true}
    In [43]:
    # 本代码由可视化策略环境自动生成 2019年5月6日 15:23
    # 本代码单元只能在可视化模式下编辑。您也可以拷贝代码,粘贴到新建的代码单元或者策略,然后修改。
    
    
    # Python 代码入口函数,input_1/2/3 对应三个输入端,data_1/2/3 对应三个输出端
    def m6_run_bigquant_run(input_1, input_2, input_3):
        train_df = input_1.read()
        features = input_2.read()
        feature_min = train_df[features].quantile(0.005)
        feature_max = train_df[features].quantile(0.995)
        train_df[features] = train_df[features].clip(feature_min,feature_max,axis=1) #去极值
        data_1 = DataSource.write_df(train_df)
        test_df = input_3.read()
        test_df[features] = test_df[features].clip(feature_min,feature_max,axis=1)
        data_2 = DataSource.write_df(test_df)
        return Outputs(data_1=data_1, data_2=data_2, data_3=None)
    
    # 后处理函数,可选。输入是主函数的输出,可以在这里对数据做处理,或者返回更友好的outputs数据格式。此函数输出不会被缓存。
    def m6_post_run_bigquant_run(outputs):
        return outputs
    
    # 回测引擎:每日数据处理函数,每天执行一次
    def m4_handle_data_bigquant_run(context, data):
        
        context.extension['index'] += 1
        # 不在换仓日就return,相当于后面的代码只会一周运行一次,买入的股票会持有一周
        if  context.extension['index'] % context.rebalance_days != 0:
            return 
        
        # 当前的日期
        date = data.current_dt.strftime('%Y-%m-%d')
        
        cur_data = context.indicator_data[context.indicator_data['date'] == date]
        # 根据日期获取调仓需要买入的股票的列表
        #stock_to_buy = list(cur_data.instrument[:context.stock_num])
        cur_data = cur_data[cur_data['pred_label'] == 1.0]
        
        stock_to_buy =  list(cur_data.sort_values('instrument',ascending=False).instrument)[:context.stock_num]
        if date == '2017-02-06':
            print(date, len(stock_to_buy), stock_to_buy)
        # 通过positions对象,使用列表生成式的方法获取目前持仓的股票列表
        stock_hold_now = [equity.symbol for equity in context.portfolio.positions]
        # 继续持有的股票:调仓时,如果买入的股票已经存在于目前的持仓里,那么应继续持有
        no_need_to_sell = [i for i in stock_hold_now if i in stock_to_buy]
        # 需要卖出的股票
        stock_to_sell = [i for i in stock_hold_now if i not in no_need_to_sell]
      
        # 卖出
        for stock in stock_to_sell:
            # 如果该股票停牌,则没法成交。因此需要用can_trade方法检查下该股票的状态
            # 如果返回真值,则可以正常下单,否则会出错
            # 因为stock是字符串格式,我们用symbol方法将其转化成平台可以接受的形式:Equity格式
    
            if data.can_trade(context.symbol(stock)):
                # order_target_percent是平台的一个下单接口,表明下单使得该股票的权重为0,
                #   即卖出全部股票,可参考回测文档
                context.order_target_percent(context.symbol(stock), 0)
        
        # 如果当天没有买入的股票,就返回
        if len(stock_to_buy) == 0:
            return
    
        # 等权重买入 
        weight =  1 / len(stock_to_buy)
        
        # 买入
        for stock in stock_to_buy:
            if data.can_trade(context.symbol(stock)):
                # 下单使得某只股票的持仓权重达到weight,因为
                # weight大于0,因此是等权重买入
                context.order_target_percent(context.symbol(stock), weight)
     
    # 回测引擎:准备数据,只执行一次
    def m4_prepare_bigquant_run(context):
        pass
    
    # 回测引擎:初始化函数,只执行一次
    def m4_initialize_bigquant_run(context):
        # 加载预测数据
        context.indicator_data = context.options['data'].read_df()
    
        # 系统已经设置了默认的交易手续费和滑点,要修改手续费可使用如下函数
        context.set_commission(PerOrder(buy_cost=0.0003, sell_cost=0.0013, min_cost=5))
        context.rebalance_days = 5
        context.stock_num = 50
        if 'index' not in context.extension:
            context.extension['index'] = 0
         
    
    # 回测引擎:每个单位时间开始前调用一次,即每日开盘前调用一次。
    def m4_before_trading_start_bigquant_run(context, data):
        pass
    
    
    m1 = M.instruments.v2(
        start_date='2015-01-01',
        end_date='2016-05-31',
        market='CN_STOCK_A',
        instrument_list='',
        max_count=0
    )
    
    m2 = M.advanced_auto_labeler.v2(
        instruments=m1.data,
        label_expr="""shift(close, -5) / shift(open, -1)-1
    rank(label) #收益率排名
    #where(label>=0.95,1,where(label<=0.1, 0, NaN))
    # 收益率前1/4的标注为1,后1/4的标注为0,中间的为NA
    where(label>=0.95,1,0)""",
        start_date='',
        end_date='',
        benchmark='000300.SHA',
        drop_na_label=False,
        cast_label_int=False
    )
    
    m3 = M.input_features.v1(
        features="""(close_0-mean(close_0,12))/mean(close_0,12)*100
    rank(std(amount_0,15))
    rank_avg_amount_0/rank_avg_amount_8
    ts_argmin(low_0,20)
    rank_return_30
    (low_1-close_0)/close_0
    ta_bbands_lowerband_14_0
    mean(mf_net_pct_s_0,4)
    amount_0/avg_amount_3
    return_0/return_5
    return_1/return_5
    rank_avg_amount_7/rank_avg_amount_10
    ta_sma_10_0/close_0
    sqrt(high_0*low_0)-amount_0/volume_0*adjust_factor_0
    avg_turn_15/(turn_0+1e-5)
    return_10
    mf_net_pct_s_0
    (close_0-open_0)/close_1
     """
    )
    
    m15 = M.general_feature_extractor.v7(
        instruments=m1.data,
        features=m3.data,
        start_date='',
        end_date='',
        before_start_days=0
    )
    
    m16 = M.derived_feature_extractor.v3(
        input_data=m15.data,
        features=m3.data,
        date_col='date',
        instrument_col='instrument',
        drop_na=False,
        remove_extra_columns=False
    )
    
    m7 = M.join.v3(
        data1=m2.data,
        data2=m16.data,
        on='date,instrument',
        how='inner',
        sort=False
    )
    
    m13 = M.dropnan.v1(
        input_data=m7.data
    )
    
    m9 = M.instruments.v2(
        start_date=T.live_run_param('trading_date', '2016-06-01'),
        end_date=T.live_run_param('trading_date', '2017-01-01'),
        market='CN_STOCK_A',
        instrument_list='',
        max_count=0
    )
    
    m17 = M.general_feature_extractor.v7(
        instruments=m9.data,
        features=m3.data,
        start_date='',
        end_date='',
        before_start_days=0
    )
    
    m18 = M.derived_feature_extractor.v3(
        input_data=m17.data,
        features=m3.data,
        date_col='date',
        instrument_col='instrument',
        drop_na=False,
        remove_extra_columns=False
    )
    
    m14 = M.dropnan.v1(
        input_data=m18.data
    )
    
    m6 = M.cached.v3(
        input_1=m13.data,
        input_2=m3.data,
        input_3=m14.data,
        run=m6_run_bigquant_run,
        post_run=m6_post_run_bigquant_run,
        input_ports='',
        params='{}',
        output_ports=''
    )
    
    m8 = M.RobustScaler.v13(
        train_ds=m6.data_1,
        features=m3.data,
        test_ds=m6.data_2,
        scale_type='standard',
        quantile_range_min=0.01,
        quantile_range_max=0.99,
        global_scale=True
    )
    
    m10 = M.svc.v1(
        training_ds=m8.train_data,
        features=m3.data,
        predict_ds=m8.test_data,
        C=1,
        kernel='rbf',
        degree=3,
        gamma=-1,
        coef0=0,
        tol=0.1,
        max_iter=100,
        key_cols='date,instrument',
        other_train_parameters={}
    )
    
    m4 = M.trade.v4(
        instruments=m9.data,
        options_data=m10.predictions,
        start_date='',
        end_date='',
        handle_data=m4_handle_data_bigquant_run,
        prepare=m4_prepare_bigquant_run,
        initialize=m4_initialize_bigquant_run,
        before_trading_start=m4_before_trading_start_bigquant_run,
        volume_limit=0,
        order_price_field_buy='open',
        order_price_field_sell='open',
        capital_base=10000000,
        auto_cancel_non_tradable_orders=True,
        data_frequency='daily',
        price_type='后复权',
        product_type='股票',
        plot_charts=True,
        backtest_only=False,
        benchmark=''
    )
    
    • 收益率12.7%
    • 年化收益率23.27%
    • 基准收益率4.43%
    • 阿尔法0.15
    • 贝塔0.84
    • 夏普比率1.16
    • 胜率0.6
    • 盈亏比1.02
    • 收益波动率16.76%
    • 信息比率0.07
    • 最大回撤8.68%
    bigcharts-data-start/{"__type":"tabs","__id":"bigchart-0e16faadef8140668160749727c91433"}/bigcharts-data-end

    参考文献