赫兹股票量化交易软件:交易策略的色彩优化

经过优化后,赫兹股票量化交易只需要从各种各样的参数集中选择一个。在选择这样的一个集合时,没有明确的答案可以使用什么标准:盈利能力、回撤、恢复系数或这些或其他参数的某种组合。但是如何评价参数组合呢?

在本文中,赫兹股票量化交易将进行一个实验:我们将使用颜色优化结果。颜色由三个参数决定:红色、绿色和蓝色(RGB)的级别。还有其他的颜色编码方法,它们也使用三个参数。因此,可以将三个测试参数转换为一种颜色,以直观方式表示这些值。在本文的最后,我们将了解这种表示是否有用。

 

初始数据

在文章使用 HTML 报告分析交易结果中, 赫兹股票量化交易为分析报告文件创建了一个函数库, HTMLReport.mqh. 库中包含 OptimizerXMLReportToStruct()函数,该函数是为具有优化结果的操作而设计的。赫兹股票量化交易将使用此函数向函数传递两个参数:

  • string aFileName 是包含优化报告的文件名,该文件必须在终端数据目录的 MQL5/Files文件夹中可用。

  • SOptimization & aOptimization 是通过引用传递的,函数执行后,从报告中提取的数据将位于该结构中。

SOptimisation 结构: struct SOptimization{ string ParameterName[]; SPass Pass[]; }; 该结构包括两个数组:string ParameterName[] 和 SPAS Pass[],要优化的参数名称位于 ParameterName[] 中,赫兹股票量化交易主要感兴趣的是第二个数组 SPass[]: 这个数组中的一个元素就包含着一个优化通过的有关数据。 SPass 结构: struct SPass{ string Pass; string Result; string Profit; string ExpectedPayoff; string ProfitFactor; string RecoveryFactor; string SharpeRatio; string Custom; string EquityDD_perc; string Trades; string Parameters[]; }; 结构的栏位:

  • Pass — 优化过程的编号;

  • Result — 优化后的最终余额;

  • Profit — 结果利润值;

  • ExpectedPayoff — 期望收入值;

  • ProfitFactor — 利润因子值;

  • RecoveryFactor — 采收系数;

  • SharpeRatio — 夏普比率;

  • Custom — 一个自定义参数;

  • EquityDD_perc — 回撤百分比;

  • Trades — 交易数量;

  • Parameters[] — 优化的参数数值数组.

以下是分析交易结果最常用的参数:

  • Profitability(盈利能力),每笔交易的平均利润

  • Drawdown(回撤), 相对最大值的净值下降值

  • Recovery factor(采收系数),绝对利润与最大回撤之比

首先,赫兹股票量化交易将使用这些参数。但是,报告包含其他值,因此我们需要提供使用这些值的可能性。 为了启用任意参数选择,赫兹股票量化交易将创建一个额外的结构来替换SPass。优化参数将位于该结构中的双精度数组中。我们不会完全重写结构,而是使用继承可能性。让我们继续实现部分: 1. 创建 ColorOptimization.mqh 文件,创建彩色报告的所有函数都将位于此文件中。 2. 在 ColorOptimization.mqh 文件的开头关联 HtmlReport.mqh 文件: #include <HTMLReport.mqh> 3. 创建一个新的结构,它继承 SPass 结构的所有栏位,并且在其中加上 factor[] 和 dParameters[] 数组: struct SPass2:SPass{ double factor[9]; double dParameters[]; }; 两个数组都是双精度类型的,在 factor[] 数组中将有九个结果值,也就是除了 Pass (测试编号) 的所有将要优化的参数。优化参数的值位于sParameters[]数组中。虽然结构中已经有了所有的数据,但是它们是以字符串格式呈现的,所以每次使用数据时,我们都需要将它们转换为数字。数组允许以方便的格式保存数据。 4. 为优化数据创建最终结构: struct SOptimization2{ string ParameterName[]; SPass2 Pass[]; }; 5. 创建一个将数据从sOptimeization结构转换为sOptimeization2的函数: void ConvertOptimizationStruct(SOptimization & src,SOptimization2 & dst){ ArrayCopy(dst.ParameterName,src.ParameterName); int cnt=ArraySize(src.Pass); ArrayResize(dst.Pass,cnt); for(int i=0;i<cnt;i++){ ArrayCopy(dst.Pass[i].Parameters,src.Pass[i].Parameters); dst.Pass[i].Pass=src.Pass[i].Pass; dst.Pass[i].Result=src.Pass[i].Result; dst.Pass[i].Profit=src.Pass[i].Profit; dst.Pass[i].ExpectedPayoff=src.Pass[i].ExpectedPayoff; dst.Pass[i].ProfitFactor=src.Pass[i].ProfitFactor; dst.Pass[i].RecoveryFactor=src.Pass[i].RecoveryFactor; dst.Pass[i].SharpeRatio=src.Pass[i].SharpeRatio; dst.Pass[i].Custom=src.Pass[i].Custom; dst.Pass[i].EquityDD_perc=src.Pass[i].EquityDD_perc; dst.Pass[i].Trades=src.Pass[i].Trades; dst.Pass[i].factor[0]=StringToDouble(src.Pass[i].Result); dst.Pass[i].factor[1]=StringToDouble(src.Pass[i].Profit); dst.Pass[i].factor[2]=StringToDouble(src.Pass[i].ExpectedPayoff); dst.Pass[i].factor[3]=StringToDouble(src.Pass[i].ProfitFactor); dst.Pass[i].factor[4]=StringToDouble(src.Pass[i].RecoveryFactor); dst.Pass[i].factor[5]=StringToDouble(src.Pass[i].SharpeRatio); dst.Pass[i].factor[6]=StringToDouble(src.Pass[i].Custom); dst.Pass[i].factor[7]=StringToDouble(src.Pass[i].EquityDD_perc); dst.Pass[i].factor[8]=StringToDouble(src.Pass[i].Trades); int pc=ArraySize(src.Pass[i].Parameters); ArrayResize(dst.Pass[i].dParameters,pc); for(int j=0;j<pc;j++){ if(src.Pass[i].Parameters[j]=="true"){ dst.Pass[i].dParameters[j]=1; } else if(src.Pass[i].Parameters[j]=="false"){ dst.Pass[i].dParameters[j]=0; } else{ dst.Pass[i].dParameters[j]=StringToDouble(src.Pass[i].Parameters[j]); } } } } 带有数据的数据结构作为第一个参数传递给函数,新结构作为第二个参数通过引用返回。在函数中执行所有优化过程的循环;同时复制结构的某些字段,并对某些字段执行类型转换。一般的过程并不复杂,可以从函数代码中理解。 将使用枚举访问factor[]数组元素: enum EOptimizatrionFactor{ Result=0, Profit=1, ExpectedPayoff=2, ProfitFactor=3, RecoveryFactor=4, SharpeRatio=5, Custom=6, EquityDD_perc=7, Trades=8 }; 枚举选项值以零开始,并增加1,因此可能不需要指定值。但是,这些值还是指定了,因为提供与factor[]数组的匹配是很重要的。这将有助于避免进一步修改和添加程序时可能出现的错误。 6. 创建一个函数,用于将报告文件加载到sOptimeization2结构中,该结构与 HtmlReport.mqh 中的 OptimizerXMLReportToStruct()类似: bool OptimizerXMLReportToStruct2(string aFileName,SOptimization2 & aOptimization){ SOptimization tmp; if(!OptimizerXMLReportToStruct(aFileName,tmp)){ return(false); } ConvertOptimizationStruct(tmp,aOptimization); return(true); } 报告文件名作为第一个参数传递给函数,填充的 sOptimeration2 结构作为第二个参数返回。 现在一切就绪,可以解决本文的主要任务了。 创建彩色报告 用于创建彩色报告的函数将位于ColorOptimization.mqh中。调用这些函数将从脚本执行。 1. 让我们创建一个脚本 ColorOptimization.mq5. 2. 把 ColorOptimization.mqh 与 ColorOptimization.mq5 关联. #include <ColorOptimization.mqh> 3. 在脚本中另外增加外部参数。首先,我们将添加一个指示属性窗口存在的属性,然后我们将添加变量。 属性: #property script_show_inputs 外部变量: input string ReportName = "*.xml"; input string OutputName = "ColorOptimization1-1.htm"; input EOptimizatrionFactor Factor1 = Profit; input EOptimizatrionFactor Factor2 = EquityDD_perc; input EOptimizatrionFactor Factor3 = RecoveryFactor; input bool Factor1Invert = false; input bool Factor2Invert = true; input bool Factor3Invert = false; input bool Sort = true; 变量的描述:

  • ReportName — 源优化报告文件的名称;

  • OutputName — 由脚本所创建的报告文件的名称;

  • Factor1 — 第一个因子,根据该因子确定报告颜色;

  • Factor2 — 第二个因子,根据该因子确定报告颜色;

  • Factor3 — 第三个因子,根据该因子确定报告颜色;

  • Factor1Invert — 反转第一个因子;

  • Factor2Invert — 反转第二个因子;

  • Factor3Invert — 反转第三个因子;

  • Sort — 根据颜色指示对最终报告进行排序;

4. 在脚本的 OnStart()函数中,赫兹股票量化交易声明一个sOptimisation2 类型的变量,并接收源报告数据: SOptimization2 opt; if(!OptimizerXMLReportToStruct2(ReportName,opt)){ Alert("错误的 OptimizerXMLReportToStruct2"); return; } 5. 由于RGB只是许多不同颜色模型中的一种,因此让我们提供进一步修改库的可能性,特别是添加其他颜色模型。这就是为什么我们将从0到1的抽象值计算开始,而不是计算RGB组件的值。然后我们将这些值转换为从0到255的RGB组件。每个优化过程都使用单独的颜色指示,因此我们需要为SPass2添加三个颜色组件字段。我们不添加三个字段,而是添加一个三元素数组: double ColorComponent[3]; 6. ColorOptimization.mqh 中的 SolveColorComponents() 函数将计算颜色组成部分,应该向函数中传入以下参数:

  • SOptimization2 & aOpt — 源优化报告中的数据

  • int i1, int i2, int i3 — 源优化报告中数值的索引 (SPass 结构中的 factor[9] 数组)

  • bool r1=false, bool r2=false, bool r3=false — 用于反转数值

函数执行后,SPass 结构数组中的 ColorComponents[3] 数组将填充值。 对于颜色分量的计算,赫兹股票量化交易需要找到每个参数的最小值和最大值,然后计算0到1之间的值。以下显示 SolveColorComponents() 函数的完整代码: void SolveColorComponents( SOptimization2 & aOpt, int i1,int i2,int i3, bool r1=false,bool r2=false,bool r3=false){ double mx[3]={0,0,0}; double mn[3]={DBL_MAX,DBL_MAX,DBL_MAX}; int size=ArraySize(aOpt.Pass); for(int i=0;i<size;i++){ mx[0]=MathMax(mx[0],aOpt.Pass[i].factor[i1]); mx[1]=MathMax(mx[1],aOpt.Pass[i].factor[i2]); mx[2]=MathMax(mx[2],aOpt.Pass[i].factor[i3]); mn[0]=MathMin(mn[0],aOpt.Pass[i].factor[i1]); mn[1]=MathMin(mn[1],aOpt.Pass[i].factor[i2]); mn[2]=MathMin(mn[2],aOpt.Pass[i].factor[i3]); } double c1,c2,c3,d; for(int i=0;i<size;i++){ c1=0; c2=0; c3=0; d=mx[0]-mn[0]; if(d!=0){ c1=(aOpt.Pass[i].factor[i1]-mn[0])/d; } d=mx[1]-mn[1]; if(d!=0){ c2=(aOpt.Pass[i].factor[i2]-mn[1])/d; } d=mx[2]-mn[2]; if(d!=0){ c3=(aOpt.Pass[i].factor[i3]-mn[2])/d; } if(r1)c1=1.0-c1; if(r2)c2=1.0-c2; if(r3)c3=1.0-c3; aOpt.Pass[i].ColorComponent[0]=c1; aOpt.Pass[i].ColorComponent[1]=c2; aOpt.Pass[i].ColorComponent[2]=c3; } }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值