你好亚历山大
我下载并安装了您的示例,但没有运行该示例。 ADX和RVI没有信号。你有什么建议吗?
谢谢
Mike
技术的飞速发展导致现代货币市场中自动交易系统的使用增加。尽管如此,许多交易者仍在继续手动交易。两种交易方式的优缺点都是众所周知的:面对不断变化的市场,自动交易缺乏灵活性,而另一方面,由于人为干扰,手动交易可能过于灵活。实际上,这些极端情况只是同一枚硬币的两个方面。
在我的 上一篇文章 我在示例中尝试通过使用模糊逻辑来弥补自动交易的弊端,例如通过软化过于严格的交易机器人或指标策略的形式化。本文探讨了改善手动交易策略的可能性。现代技术的使用也将给总是做出自己决定的手工交易者带来更多的好处而不是缺点。
如今,许多交易者更愿意自己负责开仓和平仓,而将其留给非自动化系统。您需要制定自己的交易策略,并考虑市场的所有可能性。他们必须严格遵守它,并出于恐惧和贪婪抵制一切冲动。
因此,我们首先需要的是一种交易策略。让我描述实现这一目标的三个阶段。
阶段№1。
例如,在第一阶段,我为交易策略选择了三个指标:
MQL4交易终端设置的整体图:
图1.交易策略的整体图
阶段№2。
在第二阶段,我们发现如何使用工具,其功能条件和参数进入市场。
但是,让我们从头开始。
让我们形式化条件以更好地理解。
开仓(买入信号)
阶段№3。
现在我们只需要确定何时再次平仓即可。作为退出的条件,我们使用设定的价格目标:获利50点或止损30点。
我们的交易策略现已到位。我们有开仓和平仓的条件,我们已选择指标并确定其参数,并定义了头寸规模和价格目标。最后,我们决定了平仓的情况。
接下来,让我们回顾一下实际情况下的交易策略。我们首先要接受的事实是,没有一种理想的策略可以长期适用于所有市场情况。使用自动系统的交易者和使用手动系统的交易者偶尔会发现他们的系统在不同情况下的行为有所不同。如果已经定义的交易系统的初始条件实际上可以显示出更好的结果,这也不罕见。
例如,使用我们系统的交易者可能会注意到,止盈也可能设置得更高。但这不是因为他只是想要更多,而是因为他继续分析自己的系统,并且他的统计数据表明,在平掉获利头寸之后,价格在一段时间内继续沿交易方向移动。对于零售商而言,出现的问题是:如何使用统计数据和观察结果来改进系统?
让我们从模糊逻辑理论的角度考虑系统中使用的指标。在上一篇文章中,我试图解释它们的主要优点-可以灵活地分析使用严格分类的交易策略的各个部分。模糊逻辑模糊了严格的边界,并提供了工作中具有边界值的系统评估和反应的更广阔画面。这也是使用ADX指标的一种更适应方法的示例。首先,对弱,中和强趋势进行了严格的区分,然后软化了这种分类,以使趋势强度不再严格地与纯指标值联系在一起。
但是,让我们回到我们的系统并自问,这对我们有什么帮助?
想象一下,我们的交易者正在观察市场,并看到其第一个指标发出的信号:例如,ADX达到32。它标记了这一点并等待其他两个指标进行确认。此后不久,随着ADX上升到40,来自AC的信号就会出现。此后不久,RVI的信号线也越过主线,因此满足开仓的所有三个条件。 ADX已经达到45。但是ADX的绝对值在我们的系统中并不那么重要。最主要的是,它大于30。交易者按照他的规则开仓0.01手,在50点获利,在30点止损。
现在让我们模拟一种不同的方法。在开始时,一切都与第一种情况相同。 ADX = 32,出现来自AC的信号,现在ADX达到40。但是现在,尽管来自RVI的信号没有出现,但ADX跳到55而不是45。比较上述两个选项表明,第二个信号更强与以前相比,但我们的交易者仍然以相同的手数和相同的价值开立头寸以获利和止损。
在这里,我们遇到了我们策略的第一个缺点。仅评估信号的外观,而不考虑其质量。即使我们可以评估和确定类别,也无法在边缘区域中获得准确性。
那么,我们如何改善ADX和RVI指标的特殊情况,并将它们的参数链接到未平仓头寸?为此,我们必须执行以下操作:
首先,让我们描述第一个输入变量 -趋势强度的值.
1.我们确定四种趋势强度: 小, 中等, 中 和 高。看起来是这样的:
图2.趋势强度的光学分类
2.为了定义信号输出的类别,必须确定ADX如何影响位置。通常,趋势越强,持续时间越长。我们将对此进行对应:根据当前的ADX,当所有三个信号出现时,我们将获利增加10-50点。
因此,我们将以下获利目标的价值类别添加到了策略最初的50点中。
3.接下来,我们描述模糊集理论的隶属函数的条件(请参见上文)。四个趋势类别如下:
图3.模糊逻辑的四个趋势类别的描述
如图3所示,每个类别由隶属函数确定:梯形函数确定弱趋势和强趋势,三角函数确定中等趋势和中等趋势的类别。
让我们为 RVI。
1.让我们设置相对活力指数的类别。将有四个: 弱, 中, 高 和 更高。看起来是这样的:
图4.根据类别对相对活力指数的光学分类
2.现在让我们描述隶属函数引入的类别。梯形失真校正功能用于类别 弱 和 更高 类别使用的三角函数 中 和 高 .
图5. RVI索引类别的描述
和往常一样,我们确定类别的值 利润目标:使用梯形函数的第一和第四类(10-20和40-50点),其余两个(20-30和30-40点)-使用三角函数。这就是该实现的样子。
图6.利润目标的分类功能
我们为显示选择四个参数:
图7.带有设置的交易策略的完整实现
现在让我们看一下MQL4和 FuzzyNet库。
我们使用MQL4分析和实现此信息显示的主要逻辑部分。
//+------------------------------------------------------------------+ //| FuzzyNet Panel | //+------------------------------------------------------------------+ #property copyright "亚历山大·费多索夫(Alexander Fedosov)" #property version "1.0" #property strict #property link "//www.tbxfkj.com/ru/users/alex2356/" #property indicator_chart_window #property indicator_buffers 1 #property indicator_color1 Green //+------------------------------------------------------------------+ //| Connecting libraries | //+------------------------------------------------------------------+ #include <Math\FuzzyNet\MamdaniFuzzySystem.mqh>
我们定义初始属性并加载模糊逻辑库。我们在图表窗口中设置显示条件。我们将颜色为绿色的指标缓冲区定义为所分析条的箭头符号指标。
//--- Input parameters input string p1="==== Parameters ===="; input int 字体大小=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;
现在让我们看一下 输入参数 详细地。它具有以下元素:
第二块 模糊逻辑的输入参数 包含所有输入参数(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; //--- Output 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; //--- Der Array mit den Namen des Indikators string signalName[]={"ADX_val:","RVI_val:","TP_plus:","TP_prc:"}; double adx,adx_di_minus,adx_di_plus,rvi,rvi_sig,mdm; double Buffer[]; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { if(fontSize>15 || 字体大小<8) { Print("ERROR: Incorrect 字体大小. Must be 8-15."); Alert("ERROR: Incorrect 字体大小. 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); //--- Änderung der Ecke 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); //--- Änderung der Ecke 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) 评估并显示。整体具有以下形式:当前指标值显示我们何时收到买入或卖出信号;建议止盈(以点和数值表示)。
//+------------------------------------------------------------------+ //| Custom indicator iteration function | //+------------------------------------------------------------------+ 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); }
该函数创建模糊逻辑系统。它正在等待两个指示信号- 趋势 和 活力 (均由隶属函数的4个项组成),并生成一个传出的 信号。系统的一部分是输入和输出信号的四个规则。
//+------------------------------------------------------------------+ //| Funktion erstellt 和 berechnet die 模糊逻辑 des Systems | //+------------------------------------------------------------------+ double mamdani(double t,double v) { double res=0; //--- Mamdani Fuzzy System MamdaniFuzzySystem *fsSignal=new MamdaniFuzzySystem(); //--- Create input variables for the system 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); //--- Create Output FuzzyVariable *fvSignal=new FuzzyVariable("signal",min_tp,max_tp); fvSignal.Terms().Add(new FuzzyTerm("低吸", 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("高吃", new TrapezoidMembershipFunction(out_term4a, out_term4b, out_term4c, out_term4d))); fsSignal.Output().Add(fvSignal); //--- Create four Mamdani fuzzy rule MamdaniFuzzyRule *rule1 = fsSignal.ParseRule("if (trend is low) and (vigor is low) then signal is 低吸"); 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 高吃"); //--- Add four Mamdani fuzzy rule in system fsSignal.Rules().Add(rule1); fsSignal.Rules().Add(rule2); fsSignal.Rules().Add(rule3); fsSignal.Rules().Add(rule4); //--- Set input value 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); //--- Get result 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(双拍) 将以点为单位的止盈值转换为交易品种价格格式的数值。第二个返回交易品种的位数。
//+------------------------------------------------------------------+ //| Funktion zur Bestimmung der 利润目标 | //+------------------------------------------------------------------+ 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); } //+------------------------------------------------------------------+ //| Funktion, die die Zahl der Dezimalstelle liefert | //+------------------------------------------------------------------+ int Dig() { return((_Digits==5 || _Digits==3 || _Digits==1)?10:1); } //+------------------------------------------------------------------+
我想指出的是,设置的正确性和对参数的正确性的反复检查 模糊逻辑 在测试过程中必须遵守。我建议以其原始图形表示为图3、5、6,因为不正确的值可能会导致错误并导致整个系统的错误行为。小心!
让我们总结一下我们学到的东西。
由MetaQuotes软件公司从俄语翻译而来。
来源文章: //www.tbxfkj.com/ru/articles/2195
你好亚历山大
我下载并安装了您的示例,但没有运行该示例。 ADX和RVI没有信号。你有什么建议吗?
谢谢
Mike
是fü许多策略对于识别市场是否存在至关重要'flach'是或不是。借助著名的ADX,我们展示了如何不仅可以将策略测试器用于für该指标的优化fü用于我们的特殊用途können, wir kö我们还可以决定该指标是否达到我们的目标以及我们是否可以ö可以是侧面的平均跨度 ä实时交易市场和趋势市场确定哪个重要ür die Abschä止损和价格目标为könnte.
盈利能力ä交易系统的数量不仅仅通过逻辑和公关ä确定交易符号动态的精确度,还取决于质量ät des Algorithmus'这种逻辑。错误的旅行öser sind typisch fü低质量ä这是交易机器人的逻辑。 L的方法ö解决此特定问题是本文的主题。
本文介绍了Thomas DeMark发现的TD点和TD线。显示了它们的实际用途。达尔ü此外,还演示了如何根据Thomas DeMark的概念编写三个指标和两个EA交易。