请 [注册] 或 [登录]  | 返回主站

量化交易吧 /  量化策略 帖子:3364693 新帖:14

交易策略中的模糊逻辑

你在说什么呢发表于:4 月 17 日 16:38回复(1)

导言

交易者经常想知道如何通过机器学习来改善交易系统或创建新的交易系统。尽管有大量出版物发表, 依然未能找到一个不借助计算机辅助计算来建立简单、直观分析模型的方法。模糊逻辑是机器学习世界的一个窗口。结合遗传算法, 它能够扩展创建自学习或易于优化的交易系统的能力。同时, 模糊逻辑是直观的, 因为它在模糊的 (虚化的) 条例中封装了清晰的数值信息, 就像一个人在思考过程中所做的那样。

此处是一个例子。在清晰的逻辑层面, 运动车辆的速度由测量设备判定: 例如, 60 千米/小时。但一个没有测量设备且漫不经心的观察者只能依靠他的经验或认知基础来粗略地估计车辆的速度。例如, 已知车辆可以快速行驶, 而 "快速" 大约定义为 100 千米/小时以上。同样已知, 一辆车也可慢速运动, 即 5-10 千米/小时。最后, 如果相应的车辆以中等速率增加, 则目视评估速度为平均 (约 60 千米/小时)。因此, 可以用四种不同的表达式来表征 60 千米/小时:

  • 平均速度;
  • 速度接近平均水平;
  • 比平均快;
  • 以及最后, 比平均慢。

这就是信息如何被封装在人的意识中, 令他只需掌握当前必要的信息, 例如: "如果车辆行驶速度 不是很快, 我是否有时间穿过马路?"。在做出任何具体的决定之前: "跑过马路或让车先行", 一次性地深入思考所有事情会迫使一个人花费大量的时间和精力。与此同时, 彻底研究当前形势, 而其也许今后永远不会重现, 只会有类似的轮廓。在机器学习中, 这种情况被称为过度拟合。

本文不会深入到模糊逻辑理论。有关此主题的信息可以在互联网和 MQL5 网站 上获得。我们现在立即开始实践, 用理论节选和奇妙的事实来解释。

为了构建模型, 使用标准 MetaTrader 5 终端软件包中提供的 模糊逻辑 函数库。

成果为现成的是基于模糊逻辑的智能交易系统, 可作为建立定制系统的一个例子。

创建交易系统的原型

我们继续创建 清晰的 交易逻辑, 这将作为进一步研究的基础。然后可以比较两个相同的系统, 其中第二个将运用模糊逻辑。

将使用 3 个不同周期的 RSI 振荡器作为基础:

hnd1 = iRSI(_Symbol,0,9,PRICE_CLOSE);
hnd2 = iRSI(_Symbol,0,14,PRICE_CLOSE);
hnd3 = iRSI(_Symbol,0,21,PRICE_CLOSE);

我们将信号的清晰条件公式化, 并在函数中定义它们:

double CalculateSignal()
{
 double res =0.5;
 CopyBuffer(hnd1,0,0,1,arr1);
 CopyBuffer(hnd2,0,0,1,arr2);
 CopyBuffer(hnd3,0,0,1,arr3);
 
 if(arr1[0]>70 && arr2[0]>70 && arr3[0]>70) res=1.0;                    // 如果所有指标都处于超买区域, 卖出
 if(arr1[0]<30 && arr2[0]<30 && arr3[0]<30) res=0.0;                    // 如果所有指标都处于超卖区域, 买入
 
 if(arr1[0]<30 && arr2[0]<30 && arr3[0]>70) res=0.5;                    // 如果 2 个超卖, 1 个超买, 则无信号
 if(arr1[0]<30 && arr2[0]>70 && arr3[0]<30) res=0.5;
 if(arr1[0]>70 && arr2[0]<30 && arr3[0]<30) res=0.5;
 
 if(arr1[0]>70 && arr2[0]>70 && arr3[0]<30) res=0.5;                    // 如果 2 个超买, 1 个超卖, 则无信号
 if(arr1[0]>70 && arr2[0]<30 && arr3[0]>70) res=0.5;
 if(arr1[0]<30 && arr2[0]>70 && arr3[0]>70) res=0.5;
 
 if(arr1[0]<30 && arr2[0]<30 && (arr3[0]>40 && arr3[0]<60)) res=0.0;    // 如果 2 个超卖, 第 3 个范围在 40 - 60, 则为买入信号
 if(arr1[0]<30 && (arr2[0]>40 && arr2[0]<60) && arr3[0]<30) res=0.0;
 if((arr1[0]>40 && arr1[0]<60) && arr2[0]<30 && arr3[0]<30) res=0.0;
 
 if(arr1[0]>70 && arr2[0]>70 && (arr3[0]>40 && arr3[0]<60)) res=1.0;    // 如果 2 个超买, 第 3 个范围在 40 - 60, 则为卖出信号
 if(arr1[0]>70 && (arr2[0]>40 && arr2[0]<60) && arr3[0]>70) res=1.0;
 if((arr1[0]>40 && arr1[0]<60) && arr2[0]>70 && arr3[0]>70) res=1.0;
 
 return(res);
}


下一步, 我们编写所有其它的服务函数, 针对 EURUSD, 时间帧 М15 和 М5, 从 2017 年初开始测试 (完整的 智能系统代码附于文章末尾):

EURUSD M15

EURUSD M5

尽管已经定义了三个指标组合的清晰条件, 这些条件是合乎逻辑且一致的, 但这种方法过于简单和僵化。平均而言, 这个系统在 8 个月的时间内既没亏损也没赚钱。为了赚取收益, 有必要遍历多种条件组合, 并可能添加更多的振荡器。但这里没留下太多的优化控件, 因为条件设置极端精确。

我们尝试运用模糊逻辑来虚化交易系统盈利的条件。

创建一个模糊逻辑模型

首先, 必须包含模糊函数库。准确地说, 使用两种可用的模糊逻辑模型之一 - Mamdani 或 Sugeno。它们之间的区别在于, Sugeno 无需创建模糊项集合形式的输出变量即可输出一个线性模型, 而 Mamdani 提供这个元素。由于这篇文章是为模糊交易者撰写的, 所以将使用 Mamdani。但这并不意味着 Sugeno 模型不适用于某些特定的任务: 依据对模糊逻辑的基本理解, 进行实验始终是可能的且必要的。

#include <Math\Fuzzy\MamdaniFuzzySystem.mqh>
CMamdaniFuzzySystem *OurFuzzy=new CMamdaniFuzzySystem();

函数库已包含在内, 声明 Mamdani 类的引用。这就是开始所需的一切。

现在我们来研究构建模糊推理的主要阶段。它在模糊建模系统中占据着中心地位。模糊推理过程是运用模糊逻辑的基本操作, 基于模糊假设获得模糊结论的具体过程或算法。

模糊推理有 7 个阶段。

  • 判断模糊推理系统的结构

输入和输出的数量, 以及成员函数在设计阶段即已定义。在我们的案例中, 会有 4 个输入, 1 个输出, 每个输入都有 3 个成员函数。

  • 形成模糊推理系统的规则基准

在开发过程中, 我们基于交易系统的专业判断, 创建模糊推理的自定义规则。

  • 输入变量的模糊化。

在模糊推理系统输入变量的数值, 与语言变量对应项的成员函数的值之间设置对应关系。

  • 聚合

判断模糊推理系统每条规则的条件真实度的过程。

  • 激活

查找构成所有模糊生产规则的核心后果的每个基本命题 (小节) 的真实度的过程。

  • 积累

为每个输出的语言变量查找成员函数的过程。

  • 去模糊化

从输出的语言变量的成员函数过渡为清晰 (数字) 值的过程。输出值将在从 0 到 1 范围内。

应该指出的是, 只有第 1 点和第 2 点需要执行, 其它所有的操作都将由系统完成, 无需干预。若对模糊逻辑操作所有阶段的细微之处感兴趣的人可在 这里 找到更多细节。

判断模糊推理系统的结构

我们继续创建模型。定义三个输入和一个输出的对象, 以及辅助字典对象, 以便于运用逻辑操作:

CFuzzyVariable *firstInput=new CFuzzyVariable("rsi1",0.0,1.0);
CFuzzyVariable *secondInput=new CFuzzyVariable("rsi2",0.0,1.0);
CFuzzyVariable *thirdInput=new CFuzzyVariable("rsi3",0.0,1.0);
CFuzzyVariable *fuzzyOut=new CFuzzyVariable("out",0.0,1.0);

CDictionary_Obj_Double *firstTerm=new CDictionary_Obj_Double;
CDictionary_Obj_Double *secondTerm=new CDictionary_Obj_Double;
CDictionary_Obj_Double *thirdTerm=new CDictionary_Obj_Double;
CDictionary_Obj_Double *Output;

三个不同周期的 RSI 将被用作输入。由于 RSI 振荡器始终在 0-100 范围内, 因此必须为其创建一个具有相同维度的变量。但为方便起见, 指标值将被常规化到 0-1 的范围。请记住, 所创建变量的维度必须等于输入向量的维度, 即它必须包含所有的值。输出也设置为从 0 到 1 的范围。

根据模糊逻辑创建的第 1 点, 还需要定义和配置成员函数。这将在 OnInit() 事件处理程序中完成:

firstInput.Terms().Add(new CFuzzyTerm("buy", new CZ_ShapedMembershipFunction(0.0,0.6)));
firstInput.Terms().Add(new CFuzzyTerm("neutral", new CNormalMembershipFunction(0.5, 0.2)));
firstInput.Terms().Add(new CFuzzyTerm("sell", new CS_ShapedMembershipFunction(0.4,1.0)));
OurFuzzy.Input().Add(firstInput);
   
secondInput.Terms().Add(new CFuzzyTerm("buy", new CZ_ShapedMembershipFunction(0.0,0.6)));
secondInput.Terms().Add(new CFuzzyTerm("neutral", new CNormalMembershipFunction(0.5, 0.2)));
secondInput.Terms().Add(new CFuzzyTerm("sell", new CS_ShapedMembershipFunction(0.4,1.0)));
OurFuzzy.Input().Add(secondInput);
   
thirdInput.Terms().Add(new CFuzzyTerm("buy", new CZ_ShapedMembershipFunction(0.0,0.6)));
thirdInput.Terms().Add(new CFuzzyTerm("neutral", new CNormalMembershipFunction(0.5, 0.2)));
thirdInput.Terms().Add(new CFuzzyTerm("sell", new CS_ShapedMembershipFunction(0.4,1.0)));
OurFuzzy.Input().Add(thirdInput);
   
fuzzyOut.Terms().Add(new CFuzzyTerm("buy", new CZ_ShapedMembershipFunction(0.0,0.6)));
fuzzyOut.Terms().Add(new CFuzzyTerm("neutral", new CNormalMembershipFunction(Gposition, Gsigma)));
fuzzyOut.Terms().Add(new CFuzzyTerm("sell", new CS_ShapedMembershipFunction(0.4,1.0)));
OurFuzzy.Output().Add(fuzzyOut);

现在我们看看成员函数是什么样, 以及它的用途是什么。

已经为每个输入 (和一个输出) 变量创建了三个条例: "买入", "中性", "卖出", 每个都有自己的成员函数。换言之, 振荡器值现在可以被划分到 3 个模糊组, 并且可以使用成员函数为每个组分配一定范围的值。用模糊逻辑的语言来说, 已经创建了 4 个条例集, 每个条例集有 3 个条例。为了描绘上述情况, 我们将编写一个简单的脚本, 用于条例及其成员函数的可视化:

//+------------------------------------------------------------------+ 
//|                                      Our MembershipFunctions.mq5 | 
//|                                   版权所有 2016, MetaQuotes 软件公司| 
//|                                             https://www.mql5.com | 
//+------------------------------------------------------------------+ 
#include <Math\Fuzzy\membershipfunction.mqh> 
#include <Graphics\Graphic.mqh> 
//--- 创建成员函数 
CZ_ShapedMembershipFunction func2(0.0, 0.6);
CNormalMembershipFunction func1(0.5, 0.2); 
CS_ShapedMembershipFunction func3(0.4, 1.0);

//--- 创建成员函数的包装 
double NormalMembershipFunction1(double x) { return(func1.GetValue(x)); } 
double ZShapedMembershipFunction(double x) { return(func2.GetValue(x)); }
double SShapedMembershipFunction(double x) { return(func3.GetValue(x)); }
 
//+------------------------------------------------------------------+ 
//| 脚本程序启动函数                                                    | 
//+------------------------------------------------------------------+ 
void OnStart() 
  { 
//--- 创建图形 
   CGraphic graphic; 
   if(!graphic.Create(0,"Our MembershipFunctions",0,30,30,780,380)) 
     { 
      graphic.Attach(0,"Our MembershipFunctions"); 
     } 
   graphic.HistoryNameWidth(70); 
   graphic.BackgroundMain("Our MembershipFunctions"); 
   graphic.BackgroundMainSize(16); 
//--- 创建曲线 
   graphic.CurveAdd(NormalMembershipFunction1,0.0,1.0,0.01,CURVE_LINES,"[0.5, 0.2]"); 
   graphic.CurveAdd(ZShapedMembershipFunction,0.0,1.0,0.01,CURVE_LINES,"[0.0, 0.6]"); 
   graphic.CurveAdd(SShapedMembershipFunction,0.0,1.0,0.01,CURVE_LINES,"[0.4, 1.0]"); 
//--- 设置 X 轴属性 
   graphic.XAxis().AutoScale(false); 
   graphic.XAxis().Min(0.0); 
   graphic.XAxis().Max(1.0); 
   graphic.XAxis().DefaultStep(0.1); 
//--- 设置 Y 轴属性 
   graphic.YAxis().AutoScale(false); 
   graphic.YAxis().Min(0.0); 
   graphic.YAxis().Max(1.1); 
   graphic.YAxis().DefaultStep(0.1); 
//--- 绘图 
   graphic.CurvePlotAll(); 
   graphic.Update(); 
  }

在图表上运行脚本:

图例 1. 成员函数。

所选的这些成员函数, 是因为它们只有 2 个可优化的输入参数 (这将在稍后的系统测试阶段完成)。它们也很好地描述了这个系统的极值和中心位置。您可以应用模糊函数库中 可用的 任何成员函数。

我们采用一个规则, 即振荡器的极值指示即将发生的方向变化, 随后将出现趋势反转。所以, 振荡器接近零轴暗示可能的增长开始。Movement of the oscillator to the 0.5 mark is accompanied by a gradual decrease in CZ_ShapedMembershipFunction or term "Buy zone". 与此同时, 在 "中性区域" 的 CNormalMembershipFunction 当中不确定性将会增长, 随着振荡器接近 1, 最终被 CS_ShapedMembershipFunction 或 "卖出区域" 的增长所替代。所有输入和输出都使用相同的原理, 即检查指标值是否属于具有模糊边界的特定区域。

每个变量成员函数的数量没有限制。你可以设置 5, 7, 15 个函数, 替代三个, 不过当然, 在常识和模糊逻辑的名义范围内。

形成模糊推理系统的规则基准

在此阶段, 当制定模糊决策时, 我们为所用系统增加了一个知识基准。

   rule1 = OurFuzzy.ParseRule("if (rsi1 is buy) and (rsi2 is buy) and (rsi3 is buy) then (out is buy)");
   rule2 = OurFuzzy.ParseRule("if (rsi1 is sell) and (rsi2 is sell) and (rsi3 is sell) then (out is sell)");
   rule3 = OurFuzzy.ParseRule("if (rsi1 is neutral) and (rsi2 is neutral) and (rsi3 is neutral) then (out is neutral)"); 
   
   rule4 = OurFuzzy.ParseRule("if (rsi1 is buy) and (rsi2 is sell) and (rsi3 is buy) then (out is neutral)");
   rule5 = OurFuzzy.ParseRule("if (rsi1 is sell) and (rsi2 is sell) and (rsi3 is buy) then (out is neutral)");
   rule6 = OurFuzzy.ParseRule("if (rsi1 is buy) and (rsi2 is buy) and (rsi3 is sell) then (out is neutral)"); 
   
   rule7 = OurFuzzy.ParseRule("if (rsi1 is buy) and (rsi2 is buy) and (rsi3 is neutral) then (out is buy)");
   rule8 = OurFuzzy.ParseRule("if (rsi1 is sell) and (rsi2 is sell) and (rsi3 is neutral) then (out is sell)");
   rule9 = OurFuzzy.ParseRule("if (rsi1 is buy) and (rsi2 is neutral) and (rsi3 is buy) then (out is buy)");
   rule10 = OurFuzzy.ParseRule("if (rsi1 is sell) and (rsi2 is neutral) and (rsi3 is sell) then (out is sell)");
   rule11 = OurFuzzy.ParseRule("if (rsi1 is neutral) and (rsi2 is buy) and (rsi3 is buy) then (out is buy)");
   rule12 = OurFuzzy.ParseRule("if (rsi1 is neutral) and (rsi2 is sell) and (rsi3 is sell) then (out is sell)");

   OurFuzzy.Rules().Add(rule1);
   OurFuzzy.Rules().Add(rule2);
   OurFuzzy.Rules().Add(rule3);
   OurFuzzy.Rules().Add(rule4);
   OurFuzzy.Rules().Add(rule5);
   OurFuzzy.Rules().Add(rule6);
   OurFuzzy.Rules().Add(rule7);
   OurFuzzy.Rules().Add(rule8);
   OurFuzzy.Rules().Add(rule9);
   OurFuzzy.Rules().Add(rule10);
   OurFuzzy.Rules().Add(rule11);
   OurFuzzy.Rules().Add(rule12);


必须至少添加一个逻辑条件到知识基准中: 如果至少有一个条例不涉及逻辑操作, 则认为它是不完整的。可以有无限数量的逻辑条件。

所提供的例子设置了 12 个逻辑条件, 当满足时影响模糊推理。因此, 所有条例都参与逻辑运算。默认情况下, 所有的逻辑运算分配的权重系数相同, 等于 1。在这个例子中不会改变它们。

如果所有 3 个指标都在买入模糊区域内, 则会输出模糊买入信号。卖出和中性信号也是如此。(规则 1-3)

如果两个指标显示买入, 一个显示卖出, 那么输出值将为中性, 即不确定。(规则 4-6)

如果两个指标显示买入或卖出, 而一个是中性的, 则买入或卖出被分配到输出值。(规则 7-12)

显然, 这不是创建规则基准的唯一变体, 您可以自由地进行实验。这个规则基准只是建立在我对系统应该如何运作的 "专业" 判断和构想上。

去模糊后获得清晰的输出值

它仍然是计算模型, 且所获结果从 0 到 1。接近于 0 的数值表示强烈的买入信号, 接近于 0.5 的数值是中性的, 接近 1 的数值意味着强烈的卖出信号。

double CalculateMamdani()

{
 CopyBuffer(hnd1,0,0,1,arr1);
 NormalizeArrays(arr1);
   
 CopyBuffer(hnd2,0,0,1,arr2);
 NormalizeArrays(arr2);
    
 CopyBuffer(hnd3,0,0,1,arr3);
 NormalizeArrays(arr3);
     
 firstTerm.SetAll(firstInput,arr1[0]);
 secondTerm.SetAll(secondInput,arr2[0]);
 thirdTerm.SetAll(thirdInput,arr2[0]);
       
 Inputs.Clear(); 
 Inputs.Add(firstTerm);
 Inputs.Add(secondTerm);
 Inputs.Add(thirdTerm);
      
 CList *FuzzResult=OurFuzzy.Calculate(Inputs);
 Output=FuzzResult.GetNodeAtIndex(0);
 double res = Output.Value();
 delete FuzzResult;

 return(res);
}

该函数获取三个不同周期 RSI 振荡器的数值, 将它们归一化到 0 到 1 的范围 (数值可以简单除以 100), 依据模糊字典对象 (最新的指标值) 更新列表, 将其送交计算, 为输出变量创建一个列表, 并从 "res" 变量中获取结果。

添加服务函数, 并优化/测试结果系统

由于机器学习或至少其基础知识也正在考虑之中, 一些参数将被转移到输入并已优化。

input string Fuzzy_Setings;        //模糊优化设置
input double Gsigma = 0.5;         //sigma 从 0.05 至 0.5 步长 0.05
input double Gposition=0.5;        //position 从 0.0 至 1.0 步长 0.1
input double MinNeutralSignal=0.4; //MinNeutralSignal 从 0.3 至 0.5 步长 0.1
input double MaxNeutralSignal=0.6; //MaxNeutralSignal 从 0.5 至 0.7 步长 0.1

高斯 (成员函数) 的参数将在模糊逻辑的输出端进行优化。它的中心沿 X 轴偏移 (参数 Gposition), 其 sigma 已变化 (钟形变宅并压缩, 参数 Gsigma)。这样可以更好地微调系统, 以防止买入和卖出的 RSI 信号不对称。

此外, 优化开单条件: 中性信号的最小值和最大值 (由于未定义信号, 在这些值之间的范围内不会开新仓)。

在下面的清单中展示了模糊逻辑输出的信号过程:

void OnTick()
  {
//---
   if(!isNewBar())
     {  
      return;
     }
     
   double TradeSignal=CalculateMamdani(); 
   
   if(CountOrders(0)!=0 || CountOrders(1)!=0)                                           // 如果有开仓
      {
       for(int b=OrdersTotal()-1; b>=0; b--)
         {
          if(OrderSelect(b,SELECT_BY_POS)==true)
           {
            if(OrderSymbol()==_Symbol && OrderMagicNumber()==OrderMagic)
             {
              if(OrderType()==OP_BUY && TradeSignal>=MinNeutralSignal)                  // 选择买单且交易信号大于中性信号的左边界
               {                                                                        // 也就是说, 有一个中性的信号或卖出的信号
                if(OrderClose(OrderTicket(),OrderLots(),OrderClosePrice(),0,Red))       // 然后平多头仓位
                 {
                  if(TradeSignal>MaxNeutralSignal)                     // 如果订单已平仓且存在卖出信号 (超出中性信号的右边界), 立即开仓
                  {
                   lots = LotsOptimized(); 
                   if(OrderSend(Symbol(),OP_SELL,lots,SymbolInfoDouble(_Symbol,SYMBOL_BID),0,0,0,NULL,OrderMagic,Red)){
                     };
                  }
                 }
               }
               if(OrderType()==OP_SELL && TradeSignal<=MaxNeutralSignal)                 // 选择一笔卖单....///.... 与多头仓位一样, 但所有条件都是镜像的
               {
                if(OrderClose(OrderTicket(),OrderLots(),OrderClosePrice(),0,Red))
                 {
                  if(TradeSignal<MinNeutralSignal)
                  {
                   lots = LotsOptimized(); 
                   if(OrderSend(Symbol(),OP_BUY,lots,SymbolInfoDouble(_Symbol,SYMBOL_ASK),0,0,0,NULL,OrderMagic,Green)){
                    };
                  }
                 }
               }
             }
            }
          }
         return;
        }
                 // 如果没有持仓, 根据信号开仓
   lots = LotsOptimized(); 
   if(TradeSignal<MinNeutralSignal && CheckMoneyForTrade(_Symbol,lots,ORDER_TYPE_BUY))
     { 
      if(OrderSend(Symbol(),OP_BUY,lots,SymbolInfoDouble(_Symbol,SYMBOL_ASK),0,0,0,NULL,OrderMagic,Green)){
       };
     }
   else if(TradeSignal>MaxNeutralSignal && CheckMoneyForTrade(_Symbol,lots,ORDER_TYPE_SELL))
     {
      if(OrderSend(Symbol(),OP_SELL,lots,SymbolInfoDouble(_Symbol,SYMBOL_BID),0,0,0,NULL,OrderMagic,Red)){
       };
     }
   return;
     
  }


计算将在新柱线上进行, 以便加速演示。您可以根据自己的意愿自由定制逻辑, 例如, 简单地删除新柱线检查以便在逐笔报价到达时均可交易。

如果有持仓, 且信号与当前持仓相矛盾或未定义, 则平仓。如果满足逆向开仓的条件, 就开仓。

该系统未使用止损, 因为这不是反向交易, 而交易的平仓/重开均基于信号。

智能交易系统使用 MT4Orders 函数库来简化订单操作, 并可将代码轻松地转换为 MQL4。

测试过程

系统使用截图中示意的设置进行优化, 时间帧为 M15, 区间为 8 个月, 基于开盘价格, 使用 快速遗传算法, 以及 余额 + 最大利润 优化准则。


选择最佳的优化结果:

将其与严格模型的测试结果进行比较:

优化之后, 输出的结果成员函数 (输入保持不变, 因为它们没有被优化):

在变化之前:

之后:


优化系统使用相同的设置, 但在 M5 时间帧:

将其与严格模型的测试结果进行比较:

优化之后, 输出的结果成员函数 (输入保持不变, 因为它们没有被优化):

在变化之前:

之后:

在这两种情况下, 高斯 (中性区域) 都偏向买入, 多头仓位的数量超过了空头仓位的数量。这意味着买入和卖出信号在这段历史上是不对称的, 如果没有这样的实验就不可能发现。由三个 RSI 组成的系统有可能在超卖区域 (区域 1) 多于超买区域 (区域 0), 而高斯优化有助于消除这种不平衡。对于新清晰的输出, 难以想象为什么这种输出配置对于改善交易系统结果有所贡献, 因为使用重心法去模糊化的过程, 连同输入映射到模糊集合, 本身已经是一个复杂的系统。

即使只有 4 个参数被优化, 该系统在 8 个月内仍然相当稳定。并且可轻易地将它们减少到两个 (Gsigma 和 Gposition), 因为剩下的 2 个对结果影响不大, 总是在 0.5 附近徘徊。对于一个实验系统来说, 这是一个令人满意的结果, 目的是通过在交易系统中引入一个模糊逻辑元素来展示如何减少优化参数的数量。相比之下, 有必要为严格的规则创建许多优化标准, 这会增加系统开发的复杂性和优化参数的数量。

还应当注意的是, 这仍然是基于模糊逻辑建立交易系统的一个非常粗略的例子, 因为它使用初级的基于 RSI 的策略而没有使用止损。不过, 这应该足以理解模糊逻辑在创建交易系统中的适用性。

结束语

模糊逻辑允许使用模糊规则来快速创建系统, 这些规则非常容易优化。同时, 选择交易系统参数的复杂过程通过遗传优化, 将开发者从寻找交易策略的重复劳动中解放出来, 将精力集中在交易系统各种规则的开发和算法化。与其它机器学习方法 (例如神经网络) 一起, 这种方法可以实现令人印象深刻的结果。它减少了过度拟合的机会和输入数据的维度 (3 个不同周期的 RSI 指标收窄到单一信号, 这比每个指标本身更加全面和更普适于描述行情形势)。

如果您仍然不清楚模糊逻辑的工作原理, 那么问问自己, 您的思维方式, 操作条例以及决策所依据的规则是什么。

这是一个强化的例子。比如, 您有 3 个愿望: 去参加一个聚会, 在家看电影或者拯救世界。"在家看电影" 这个条件最为重要, 因为您已经在家了, 没有必要再去努力了。如果有人邀请并来接您, 那么去参加一个聚会是可行的, 但是由于它还没有发生, 所以出发的几率是平均的。最后, 为了拯救世界, 您需要调动您所有的超自然能力, 穿上超人服, 与外星怪物作战。您决定今天就做这件事, 不把它拖到明天, 只是这不太可能, 所以机会很渺茫。

模糊推论是这样的: 我很可能留在家里, 也许我会去参加聚会, 但我今天绝对不会去拯救世界。去模糊之后, 我们的机会可在 0 到 10 之间评估, 其中 0 代表 "留在家里", 5 代表 "去参加聚会", 10 代表 "打怪"。显然, 清晰输出在 0 到 3 之间, 即您最有可能呆在家里。在所呈现的交易系统中使用同样的原则: 它比较三个指标的数值, 并使用逻辑条件来确定当前时刻的最佳选择 — 买入, 卖出或什么都不做。

改进这个例子的可能方法 (用于自学):

  • 增加输入和逻辑条件的数量。这增加了系统的能力, 令其更适应市场。
  • 优化不仅输出高斯, 还有输入和输出的所有成员函数。
  • 优化规则基准。
  • 优化逻辑表达式的权重。
  • 创建一个由多个模糊模型组成的委员会, 负责交易系统的不同层面。
  • 使用模糊推理作为神经网络的预测变量 ("特征") 和/或 目标变量。

如果对这篇文章有足够的兴趣, 且我收到足够的反馈意见, 我可以考虑写一篇有关模糊逻辑和神经网络相结合的新文章。

下面是智能系统的源代码和成员函数的测试脚本。为了能让智能系统编译和工作, 必需下载 MT4Orders 函数库和更新的 Fuzzy 函数库。

全部回复

0/140

达人推荐

量化课程

    移动端课程