下载MetaTrader 5

创建手动交易策略的模糊逻辑

25 三月 2016, 07:46
Alexander Fedosov
0
2 157

简介

科技的迅猛发展,使得在现代外汇交易市场上使用自动化交易系统的趋势越来越显著。然而,许多交易者仍旧进行手动交易。两种交易方式的优缺点众所周知:自动交易对市场的变化缺乏弹性,相反,手动交易因为人性的特点容易太具有弹性。事实上,在这个对比中,这是同一种实质的两种极端情况。

先前的文章中我给出了例子,我试图通过应用模糊逻辑来弥补手工交易的缺点。例如,将应用于交易机器人或者指标的过度严格的策略进行模糊化处理。在本文中将讨论改进人工交易策略的方法。现在科技的应用,即使是最终决定在交易者手中的人工交易领域,也是利大于弊。

 

根据一个特定的条件,选择手动交易策略

许多现代交易者选择主观开仓及平仓,而非依赖自动交易系统。他们要求开发属于自己的交易策略,将所有市场行为的可能结果考虑在内。之后,你必须严格遵守它并且抵制任何由恐惧和贪婪引起的冲动。

因此,首先我们要有一个交易策略。让我向你描述一下我们打算构建策略的三个步骤。

  • 阶段 1. 找到并确定我们要使用策略的交易对象。
  • 阶段 2. 设置交易者在市场上开仓的特定条件。
  • 阶段 3. 设置需要平仓的特定条件,不管是盈利还是亏损的。

阶段 1.

在第一阶段,作为一个例子,我选用三个指标来构建交易策略:

  1. 平均定向运动指数,ADX。这是一个用于确定当前趋势强度的趋势指标。
  2. 相对强度指数,RVI 振荡器。
  3. Bill Williams的加速度振荡器(AC)指标

选择普通视图和MQL4交易终端的设置:

图 1. 策略设置的一般视图

阶段 2.

在第二阶段,我们将找到使用选定交易标的的方法,交易条件以及开仓参数。

让我们从头开始。

  • 我们的第一个指标是ADX。如图1所示,指标的周期为10。另外,主趋势线(绿色)的水平被设置为30。任何等于或超过它的值,将被认为是一个入市的信号。值得注意的是,这个指标的买入信号出现在当+DI(绿色虚线)高于-DI(红色虚线)时。同样,卖出信号相反,即当-DI高于+DI时。
  • 第二个指标是AC。这里我们将使用在官方文件中描述的信号。具体而言,如果指标的值小于0并且在当前及前两个柱形上逐渐增长,那么这是一个买入信号。因此,如果指标的值超过0并且在当前及前两个柱形上逐渐下降时,我们得到一个卖出信号。
  • 第三个指标是RVI。让我们将其运行周期设置为10. 买入信号的条件是当信号线(浅红色)穿越主线(绿色)时。在交叉的时候,当前被分析的柱形上线的值必须要小于0。类似的,我们将设置卖出条件:信号线穿越主线,但是值在0之上
  • 下一个交易条件是小时时间框架(H1)。
  • 开仓条件是指所有三个选定指标发出相似的信号。
  • 最后,我们将要决定交易量的大小。作为一个例子,设置如下:0.01手,止赢50点,止损30点。

为了更加清晰,这些设置将被标准化。

做多(买入信号)

  1. 绿色的ADX指标主线具有大于或对于30的值,而+DI值大于-DI。
  2. AC的值在当前柱形上增长,并且比前两个柱形上逐渐增大的值都要大。视觉上,有三列绿色直方图,每列都比前一列短,并且所有这三个直方图都位于负值区域。
  3. RVI信号(浅红色)线穿越主线(绿色),两者都在增长,但仍旧在零点以下。
  4. 我们买0.01手,设置止赢50点止损30点。
做空(卖出信号)
  1. 绿色的ADX指标主线具有大于或对于30的值,而+DI的值小于-DI。
  2. AC值在当前柱形上下跌,并且前两个柱形上AC值也持续下跌。视觉上,有三列红色直方图,每一列都比前一列低,三个的值都大于零。
  3. RVI信号线(浅红色)穿越主线(绿色),都为下降趋势但都在正值区域。
  4. 我们卖出0.01手,设置止赢50点止损30点。

阶段 3.

我们所有要做的工作是确定如何退出。作为退出条件,我们将设置如前所述的价格目标:即获得50点利润或者执行30点的止损。

因此,我们的交易策略现在确定了。我们已经设置好了开仓和平仓的条件,选定了指标以及它们的参数,确定了交易量以及目标。最后我们决定了退出市场的条件。

在下一阶段,我们打算在实际市场环境下检验创建的交易策略。我们需要理解的第一件事情是,没有长期来看理想的和绝对适合所有市场环境的策略。采用自动和手动的交易者经常审视他们的交易系统,在不同的市场条件下系统的表现有所不同。同时,使用初始条件的交易系统也经常能够有很好的表现。

例如,对于我们的系统,交易者可能注意到止赢的设置可以设的更大一些。这并不是因为他简单的希望获得更多利润,而是因为他不断地分析此系统,并且统计数据表明,在平仓之后,价格一直朝着预期的方向移动。因此,交易者可能会问:如何应用交易系统长生的统计数据和观察值来改进结果?

 

用模糊逻辑修正严格形式化的缺点

让我们以模糊逻辑的理论来看看系统中使用的指标。在我先前的文章中我试图传达它的主要优点 — 对于分析应用严格交易条件的策略部分,它能增加其弹性。模糊逻辑模糊化严格边界,给出一个更为宽泛的评价图景以及系统在其执行边界区域的响应。这里有一个更为合适的方法来应用我们的ADX指标。首先,在弱的、平稳的的和强的趋势之间进行严格区分,但是随后这些分类被迷糊化,不严格根据指标的值来确定趋势的强度。

但是回到我们的交易系统中并问问我们自己:这对我们有什么用?

想象一下,我们的交易者观察市场并发现他的第一个指标发出了信号:比如,ADX到达了32。他标记下来并等待其他两个指标的确认。不久AC指标发出了信号,此时ADX显示已经上升到了40。随后RVI信号线穿越了主线,这意味着所有三个条件被满足。ADX已经达到了45点。但是ADX的绝对值在我们的系统中并不重要。关键是它超过了30。因此,交易者遵循他的规则,并且开仓了,0.01手,止赢50点止损30点。

现在,我们来模拟另一种场景。一开始,情形的发展和第一个案例一样。ADX=32,AC产生了信号,ADX同时到达40点。但是最后一个开仓信号RVI出现时,ADX飙升到了55而非45。比较这两种情形,第二种信号更强,但是我们的交易者仍旧以相同的手数进行交易,并且止赢止损也一样。

此处我们遇到了策略的第一个缺点。仅仅评估信号的出现,而没有关注其质量。即使我们能够评估并定义其种类,但是定义的精度仍旧将在过渡区域中丢失。

因此我们如何才能明确ADX、RVI指标的某一特定情景,并且将其参数和我们的开仓量相结合呢?要实现这个目标,我们得执行以下步骤:

  • 建立明确的趋势强度(ADX)和相对活力指数(RVI)的分类评价体系。这将是一个输入信号,我们将在此基础上作出额外的决定。
  • 建立清晰的头寸目标分类(止赢或者止损,此处我们也可以设置交易量)。这是一个输出信号,在给定趋势强度的前提下修正市场头寸。
  • 用模糊集理论的成员函数来描述输入和输出信号的类别。
  • 创建新的界面来显示基于新条件下改变初始策略头寸的建议。
  • 创建富有弹性的配置项,来调整可在必要时对系统进行修正的成员函数。

我们将从描述第一个输入变量 — 趋势强度的值开始。

1. 我们将设置4中趋势强度的类型:弱的, 温和的, 中等的剧烈的。它看上去像这样:

图 2. 趋势强度可视化分类

2. 为了设置输出信号的类型,需要确定ADX的类别是如何影响我们的头寸的。通常,趋势越强持续的时间越久。因此,我们将做相应处理:取决于当所有三个信号出现时ADX的位置,我们打算增加止赢10-50点。

下面的类别将被使用到获利目标值上,在我们策略的初始止赢50点基础上添加。

  • low_take 分类:弱趋势,止赢增加10 - 20点。
  • mod_take 分类:温和趋势,止赢增加 20 - 30点。
  • med_take 分类:中等的趋势,止赢增加30 - 40点。
  • high_take 分类:强的趋势,止赢增加40 - 50点。

3. 在接下来的步骤中我们将描述由先前模糊集理论的成员函数设置的条件。四种趋势类型的描述如下:


图 3. 模糊理论对四种趋势的描述

如图3所示,每一个类别都由成员函数设置,诸如:弱趋势和强趋势由两个梯形函数设置,温和的和中等的趋势类型由两个三角形函数设置。

现在,我们同样定义RVI。

1. 让我们设置RVI的类型。有四种类型:弱的中等的强的以及剧烈的。它看上去像这样:

图 4. 相对活力指数的可视化分类

2. 现在,我们将介绍成员函数定义的分类。梯形函数将用于描述若的剧烈的两种类型,三角形函数将用于描述中等的强的两种类型。


图. 5. RVI指数类型的描述

同样,我们将盈利目标的值分为四类:第一和第四类(10-20和40-50点)使用梯形函数,剩下的两类(20-30和30-40点) — 使用三角形函数。这是我们描述的输入信号看上去的样子。


图. 6. 对于利润目标值类别的描述

 

采用面板界面来显示头寸修改的建议

当创建信息面板时,我们选择四个观察参数:

  • ADX值。仅当特定的条件满足时,例如 — 30或者更高。
  • RVI值。仅当它大于0.1(卖出信号),或者小于 -0.1(买入信号)。
  • 建议的点数必须添加到初始目标50点上。
  • 以交易标的价格形式表示的获利值(考虑初始价格和推荐的增加值)。

完整实现的交易策略总体看上去如下(图6)。

图. 7. 完整实现,整体展现,以及交易策略的设置

现在让我们研究下使用MQL4工具FuzzyNet库实现的这个面板。

我们实现并分析这个由MQL4工具生成的信息面板的关键逻辑块。

//+------------------------------------------------------------------+
//| FuzzyNet面板
//+------------------------------------------------------------------+
#property copyright "Alexander Fedosov"
#property version "1.0"
#property strict
#property link "https://www.mql5.com/ru/users/alex2356/"
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_color1 Green
//+------------------------------------------------------------------+
//| 连接库
//+------------------------------------------------------------------+
#include <Math\FuzzyNet\MamdaniFuzzySystem.mqh>

我们定义初始属性并将库和模糊逻辑连接起来。我们将设置选项来配置信息面板在图表上的位置。我们将为当前所分析柱形的箭头指标,定义一个指标缓存和颜色(绿色)。

//--- 输入参数
input string  p1="==== Parameters ====";
input int fontSize=15;
input int adx_period=10;
input int rvi_period=10;
input int num_bar=0;
input int Screen_corner=4;
input color label_clr=Red;
input color textColor=Black;

我们来仔细分析下输入参数的第一块。它包含下面的元素:

  • fontSize — 文本信息的字体大小(建议范围为8-15)。
  • adx_period — ADX指标的运行周期。
  • num_bar — 系统要计算的柱形的数量。
  • Screen_corner — 显示面板的角落位置。
  • label_clr — 标题文本颜色。
  • textColor — 文本内容颜色。

输入参数的第二块模糊逻辑参数包含了描述所有输入(ADX趋势强度,RVI指数)和输出参数(获利目标点数的推荐值)的成员函数的大多数扩展性设置。

input string  p2="==== Fuzzy Logic Parameters ====";
//--- ADX
input double in_term1a = 20;
input double in_term1b = 30;
input double in_term1c = 40;
input double in_term1d = 45;
input double in_term2a = 40;
input double in_term2b = 50;
input double in_term2c = 60;
input double in_term3a = 50;
input double in_term3b = 60;
input double in_term3c = 70;
input double in_term4a = 60;
input double in_term4b = 70;
input double in_term4c = 100;
input double in_term4d = 120;
//--- RVI
input double in_term1a1 = -0.25;
input double in_term1b1 = 0.1;
input double in_term1c1 = 0.15;
input double in_term1d1 = 0.25;
input double in_term2a1 = 0.15;
input double in_term2b1 = 0.25;
input double in_term2c1 = 0.35;
input double in_term3a1 = 0.25;
input double in_term3b1 = 0.35;
input double in_term3c1 = 0.45;
input double in_term4a1 = 0.4;
input double in_term4b1 = 0.45;
input double in_term4c1 = 1;
input double in_term4d1 = 1.2;
//--- 输出
input double out_term1a = 5;
input double out_term1b = 10;
input double out_term1c = 15;
input double out_term1d = 22.5;
input double out_term2a = 17.5;
input double out_term2b = 25;
input double out_term2c = 32.5;
input double out_term3a = 27.5;
input double out_term3b = 35;
input double out_term3c = 42.5;
input double out_term4a = 37.5;
input double out_term4b = 45;
input double out_term4c = 50;
input double out_term4d = 60;
input double min_tp = 10;
input double max_tp = 50;


下一个块中,我们声明变量,标题名称,信息面板的模板(尺寸、位置、字体和其他),并且设置显示当前柱形标识(我们的例子中为箭头)的参数。

int scaleX=55,scaleY=25,offsetX=35;
//---声明指标名称的数组
string signalName[]={"ADX_val:","RVI_val:","TP_plus:","TP_prc:"};
double adx,adx_di_minus,adx_di_plus,rvi,rvi_sig,mdm;
double Buffer[];
//+------------------------------------------------------------------+
//| 自定义指标初始化函数                               
//+------------------------------------------------------------------+
int OnInit()
  {
   if(fontSize>15 || fontSize<8)
     {
      Print("ERROR: Incorrect fontSize. Must be 8-15.");
      Alert("ERROR: Incorrect fontSize. Must be 8-15.");
      return(0);
     }
   if(Screen_corner>4 || Screen_corner<1)
     {
      Print("ERROR: Incorrect Screen_corner. Must be 1-4.");
      Alert("ERROR: Incorrect Screen_corner. Must be 1-4.");
      return(0);
     }
//---
   SetIndexStyle(0,DRAW_ARROW,EMPTY,1);
   SetIndexArrow(0,234);
   SetIndexBuffer(0,Buffer);
   ArrayInitialize(Buffer,0.0);
//---
   for(int y=0;y<4;y++)
     {
      ObjectCreate("lb_ind_nm"+string(y),OBJ_LABEL,0,0,0,0,0);
      //--- 改变角落的位置 
      ObjectSet("lb_ind_nm"+string(y),OBJPROP_SELECTABLE,false);
      ObjectSet("lb_ind_nm"+string(y),OBJPROP_CORNER,Screen_corner);
      ObjectSet("lb_ind_nm"+string(y),OBJPROP_XDISTANCE,offsetX-30);
      ObjectSet("lb_ind_nm"+string(y),OBJPROP_YDISTANCE,y*scaleY+20);
      ObjectSetText("lb_ind_nm"+string(y),signalName[y],fontSize,"Tahoma",label_clr);
     }
//---
   for(int y=0;y<4;y++)
     {
      ObjectCreate("lb_ind0"+string(y),OBJ_LABEL,0,0,0,0,0);
      //---改变角落位置
      ObjectSet("lb_ind0"+string(y),OBJPROP_SELECTABLE,false);
      ObjectSet("lb_ind0"+string(y),OBJPROP_CORNER,Screen_corner);
      ObjectSet("lb_ind0"+string(y),OBJPROP_XDISTANCE,scaleX+offsetX);
      ObjectSet("lb_ind0"+string(y),OBJPROP_YDISTANCE,y*scaleY+20);
      ObjectSetText("lb_ind0"+string(y),"",fontSize,"Tahoma",textColor);
     }
   return(INIT_SUCCEEDED);
  }


现在,让我们看看ADX和RVI指标的信号处理主要模块

条件被设置为指标值满足出现买和卖的信号。当满足时,这些值通过mamdani(double t, double v)函数进行处理并显示在面板上。所有这些有如下形式:当前指标值显示我们接收到一个买入或者卖出信号;建议的止赢(以点数及数值计)。

//+------------------------------------------------------------------+
//| 自定义指标迭代函数                                                  
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
   Buffer[num_bar]=High[num_bar]+20*_Point;
   adx=NormalizeDouble(iADX(_Symbol,PERIOD_CURRENT,adx_period,PRICE_CLOSE,MODE_MAIN,num_bar),_Digits);
   adx_di_plus=NormalizeDouble(iADX(_Symbol,PERIOD_CURRENT,adx_period,PRICE_CLOSE,MODE_PLUSDI,num_bar),_Digits);
   adx_di_minus=NormalizeDouble(iADX(_Symbol,PERIOD_CURRENT,adx_period,PRICE_CLOSE,MODE_MINUSDI,num_bar),_Digits);
//---
   rvi=NormalizeDouble(iRVI(_Symbol,PERIOD_CURRENT,rvi_period,MODE_MAIN,num_bar),_Digits);
   rvi_sig=NormalizeDouble(iRVI(_Symbol,PERIOD_CURRENT,rvi_period,MODE_SIGNAL,num_bar),_Digits);
//---   
   if(adx>30 && adx_di_plus>adx_di_minus && rvi>rvi_sig && rvi<-0.1)
     {
      mdm=MathCeil(mamdani(adx,MathAbs(rvi)));
      ObjectSetText("lb_ind00","buy_signal: "+DoubleToString(adx,_Digits),fontSize,"Tahoma",textColor);
      ObjectSetText("lb_ind01","buy_signal: "+DoubleToString(rvi,_Digits),fontSize,"Tahoma",textColor);
      ObjectSetText("lb_ind02",DoubleToString(mdm,0),fontSize,"Tahoma",textColor);
      ObjectSetText("lb_ind03",DoubleToString(tp_prc(mdm),_Digits),fontSize,"Tahoma",textColor);
     }
   else if(adx>30 && adx_di_plus<adx_di_minus && rvi<rvi_sig && rvi>0.1)
     {
      mdm=MathCeil(mamdani(adx,rvi));
      ObjectSetText("lb_ind00","sell_signal: "+DoubleToString(adx,_Digits),fontSize,"Tahoma",textColor);
      ObjectSetText("lb_ind01","sell_signal: "+DoubleToString(rvi,_Digits),fontSize,"Tahoma",textColor);
      ObjectSetText("lb_ind02",DoubleToString(mdm,0),fontSize,"Tahoma",textColor);
      ObjectSetText("lb_ind03",DoubleToString(tp_prc(mdm),_Digits),fontSize,"Tahoma",textColor);
     }
   else
     {
      ObjectSetText("lb_ind00","no_signal",fontSize,"Tahoma",textColor);
      ObjectSetText("lb_ind01","no_signal",fontSize,"Tahoma",textColor);
      ObjectSetText("lb_ind02"," - ",fontSize,"Tahoma",textColor);
      ObjectSetText("lb_ind03"," - ",fontSize,"Tahoma",textColor);
     }
   return(rates_total);
  }


这个函数创建模糊逻辑系统。它包含两个来自指标的输入信号 — 趋势强度(每一个都由成员函数描述的四种模式组成),以及一个输出信号。连结输入和输出信号的四条规则也包含在此系统中。

//+------------------------------------------------------------------+
//| 基于模糊逻辑创建和计算系统的函数
//+------------------------------------------------------------------+
double mamdani(double t,double v)
  {
   double res=0;
//--- Mamdani Fuzzy 系统  
   MamdaniFuzzySystem *fsSignal=new MamdaniFuzzySystem();
//--- 为系统创建输入参数
   FuzzyVariable *fsTrend=new FuzzyVariable("trend",30.0,100.0);
   FuzzyVariable *fsVigor=new FuzzyVariable("vigor",0.1,1.0);
//--- ADX
   fsTrend.Terms().Add(new FuzzyTerm("low", new TrapezoidMembershipFunction(in_term1a, in_term1b, in_term1c, in_term1d)));
   fsTrend.Terms().Add(new FuzzyTerm("moderate", new TriangularMembershipFunction(in_term2a, in_term2b, in_term2c)));
   fsTrend.Terms().Add(new FuzzyTerm("medium", new TriangularMembershipFunction(in_term3a, in_term3b, in_term3c)));
   fsTrend.Terms().Add(new FuzzyTerm("high",new TrapezoidMembershipFunction(in_term4a, in_term4b, in_term4c, in_term4d)));
   fsSignal.Input().Add(fsTrend);
//--- RVI
   fsVigor.Terms().Add(new FuzzyTerm("low", new TrapezoidMembershipFunction(in_term1a1, in_term1b1, in_term1c1, in_term1d1)));
   fsVigor.Terms().Add(new FuzzyTerm("medium", new TriangularMembershipFunction(in_term2a1, in_term2b1, in_term2c1)));
   fsVigor.Terms().Add(new FuzzyTerm("high", new TriangularMembershipFunction(in_term3a1, in_term3b1, in_term3c1)));
   fsVigor.Terms().Add(new FuzzyTerm("higher",new TrapezoidMembershipFunction(in_term4a1, in_term4b1, in_term4c1, in_term4d1)));
   fsSignal.Input().Add(fsVigor);
//--- 创建输出
   FuzzyVariable *fvSignal=new FuzzyVariable("signal",min_tp,max_tp);
   fvSignal.Terms().Add(new FuzzyTerm("low_take", new TrapezoidMembershipFunction(out_term1a, out_term1b, out_term1c, out_term1d)));
   fvSignal.Terms().Add(new FuzzyTerm("mod_take", new TriangularMembershipFunction(out_term2a, out_term2b, out_term2c)));
   fvSignal.Terms().Add(new FuzzyTerm("med_take", new TriangularMembershipFunction(out_term3a, out_term3b, out_term3c)));
   fvSignal.Terms().Add(new FuzzyTerm("high_take", new TrapezoidMembershipFunction(out_term4a, out_term4b, out_term4c, out_term4d)));
   fsSignal.Output().Add(fvSignal);
//--- 创建四个Mamdani模糊逻辑规则
   MamdaniFuzzyRule *rule1 = fsSignal.ParseRule("if (trend is low) and (vigor is low) then signal is low_take");
   MamdaniFuzzyRule *rule2 = fsSignal.ParseRule("if (trend is moderate) and (vigor is medium) then signal is mod_take");
   MamdaniFuzzyRule *rule3 = fsSignal.ParseRule("if (trend is medium) and (vigor is high) then signal is med_take");
   MamdaniFuzzyRule *rule4 = fsSignal.ParseRule("if (trend is high) and (vigor is higher) then signal is high_take");
//--- 向系统中添加四个Mamdani模糊逻辑规则
   fsSignal.Rules().Add(rule1);
   fsSignal.Rules().Add(rule2);
   fsSignal.Rules().Add(rule3);
   fsSignal.Rules().Add(rule4);
//--- 设置输入值
   CList *in=new CList;
   Dictionary_Obj_Double *p_od_adx=new Dictionary_Obj_Double;
   Dictionary_Obj_Double *p_od_rvi=new Dictionary_Obj_Double;
   p_od_adx.SetAll(fsTrend,t);
   p_od_rvi.SetAll(fsVigor,v);
   in.Add(p_od_adx);
   in.Add(p_od_rvi);
//--- 获取结果
   CList *result;
   Dictionary_Obj_Double *p_od_out;
   result=fsSignal.Calculate(in);
   p_od_out=result.GetNodeAtIndex(0);
   res=NormalizeDouble(p_od_out.Value(),_Digits);
//---
   delete in;
   delete result;
   delete fsSignal;
   return res;
  }


让我们看看最后一个模块— “附加函数”。第一个 — tp_prc(double take)将以点数计的止赢值转换为当前货币价格的数值值。第二个函数定义当前货币对的报价小数位数。

//+------------------------------------------------------------------+
//| 确定获利目标的函数
//+------------------------------------------------------------------+
double tp_prc(double take)
  {
   int tip;
   double opr,tp;
   take+=50;
   adx_di_plus=NormalizeDouble(iADX(_Symbol,PERIOD_CURRENT,adx_period,PRICE_CLOSE,MODE_PLUSDI,num_bar),_Digits);
   adx_di_minus=NormalizeDouble(iADX(_Symbol,PERIOD_CURRENT,adx_period,PRICE_CLOSE,MODE_MINUSDI,num_bar),_Digits);
//---
   if(adx_di_plus>adx_di_minus)
      tip=0;
   else if(adx_di_plus<adx_di_minus)
      tip=1;
//---
   switch(tip)
     {
      case 0:
         opr=Ask;
         break;
      case 1:
         opr=Bid;
         break;
     }
   if(MathMod(tip,2.0)==0.0)
     {
      tp=opr+take*Dig()*_Point;
     }
   else
     {
      tp=opr-take*Dig()*_Point;
     }
   return(tp);
  }
//+------------------------------------------------------------------+
//|  返回小数位数的函数
//+------------------------------------------------------------------+
int Dig()
  {
   return((_Digits==5 || _Digits==3 || _Digits==1)?10:1);
  }
//+------------------------------------------------------------------+

我还想提醒你们在测试时请注意对参数设置的修正,以及在模糊逻辑参数模块中对参数正确性的预先效验。我建议使用图3、5、6中的初始图形展现形式,因为不正确的参数会导致报错以及正系统的错误运行。请当心!

 

总结

我们将总结我们所学到的知识。

  • 使用模糊逻辑创建手动交易策略的第一部分工作是要建立此策略严格的量化规则。这在步骤1到步骤3中讨论过了。
  • 然后要找到这些规则的缺点,这些缺点可能存在于任何已建立模块或者参数的严格分类上。在给出的例子中,我们发现策略中不允许我们以足够的弹性来确定开仓交易量。
  • 此外,所有分类使用模糊集理论描述,并且因此而变得更具有灵活性。现在,在边界值附近,可能不像之前一样仅仅归属于某一个特定的类别,还可能同时归属到不同的范围中去。
  • 此策略以指标,面板或者告警的形式实现。在本文中,选用MQL4语言中的一个面板。
我们讨论了通过应用模糊逻辑来改进手动交易策略的可能性。使用样例来揭示如果改进现有交易策略的更多细节,使用模糊逻辑来实现并弥补已知缺陷。

本文译自 MetaQuotes Software Corp. 撰写的俄文原文
原文地址: https://www.mql5.com/ru/articles/2195

附加的文件 |
fuzzy_panel.mq4 (11.84 KB)
跟踪止损和退出市场的模式 跟踪止损和退出市场的模式

订单修改/关闭算法的开发人员面临无止境的痛苦 - 如何比较通过不同方法获得的结果?检查机制众所周知 - 它就是策略测试程序。但如何使 EA 同等地处理建立/关闭订单?本文将介绍一个能够重复建立大量订单的工具,让我们能够维持一个在数学上保持正确的平台,以比较针对跟踪止损和退出市场的不同算法的结果。

通过 DDE 在 MetaTrader 4 与 Matlab 之间进行交互 通过 DDE 在 MetaTrader 4 与 Matlab 之间进行交互

分步说明如何使用 DDE 将数据从 Matlab 传输到 MetaTrader 4。

通过"单元测试"的帮助来提高代码质量 通过"单元测试"的帮助来提高代码质量

就算是简单程序也会经常出现看似难以置信的错误。 “我怎么会编出这种东西?”是我们发现这种错误时的第一反应。 “我应该如何避免它?”则是较少会映入脑海的第二个问题。 编写完美无缺的代码是不可能的,特别是在大型项目里,但可通过技术手段及时检测出这些错误。 本文介绍如何借助通用的“单元测试”方法来提高 MQL4 代码质量。

在一个 Expert Advisor 内的多个 Expert Advisor 的竞争 在一个 Expert Advisor 内的多个 Expert Advisor 的竞争

使用虚拟交易,你可以创建一个自适应的 Expert Advisor,在真实市场上打开和关闭交易。 将多个策略组合到一个 Expert Advisor 内! 你的多系统 Expert Advisor 会根据虚拟交易的获利能力,自动选择进行真实市场交易的最佳策略。 这种方法可以降低亏损并增加你在市场上操作的获利能力。 进行实验并跟其他人分享你的结果吧! 我想,很多人会对你的策略组合感兴趣。