受惠於快速發展的資通科技,使得「自動交易系統」在現代貨幣市場有著相當強勢的發展。即便如此,仍然使用手動交易者也是大有人在。

關於自動和手動這兩種交易方式,則一直存在著正反兩極的觀點。闢如:
自動交易面對不斷變化的市場,靈活性不足;另一方面,
手動交易則由於人為(人性)因素頻繁的干擾而過於隨興。
事實上,類似於此的比較,剛好呈現了相同本質的兩種極端觀點。

本文嘗試引用模糊邏輯(Fuzzy Logic),以彌補自動交易系統的不足。如:
利用明確規格化的策略,套用在交易機器人或指標上(indicator)。主要在考慮在於:如何能改善人工交易策略。因為,即使交易員的手上握有手動交易最終決定的權力,而引入現代化科技來幫助決策永遠是利大於弊的。

制定交易策略的條件

手動交易的交易員靠自己的判斷進出場,選擇買進或賣出部位。他們需要考慮交易的所有可能結果後,發展自己的交易策略並嚴格遵循,同時要持續抗拒因為波動所帶來的恐懼和貪婪。

建構交易策略的三個步驟:

  • 步驟1:選擇交易策略要參考的【指標】(indicator)。
  • 步驟2:設定【多】方訊號和買進部位的條件。
  • 步驟3:設定【空】方訊號和賣出部位的條件。

步驟1:選擇用來構建交易策略的指標,分別是:ADX, RVI, AC

  • Average Directional Movement Index, ADX. (趨勢指標)。在MT4/Indicators/Trend/Average Directional Movement Index
  • Relative Vigor Index, RVI (動能指標 RVI = (CLOSE-OPEN)/(HIGH-LOW) )。MT4/Indicators/Oscillator/Relative Vigor Index
  • Accelerator Oscillator(AC) indicator by Bill Williams. (震盪指標) 。MT4/Indicators/Acclerator(或Bill Williams)/Acclerator Oscillator

  • Fig. 1. General view of strategy settings

    步驟2:設定操作的參數及條件,即:多/空訊號的條件和部位。

    • ADX指標(指標週期為10),(圖1)
      前提:ADX大於等於30。
      買入:當+DI(上漲趨勢)大於-DI(下跌趨勢),
      賣出:當-DI(下跌趨勢)大於+DI(上漲趨勢)。
    • AC指標(定義),根據前兩個K棒所產生的AC值做判斷:
      買入:AC值【小於0且漸增】,
      賣出:AC值【大於0且漸減】。
    • RVI指標(指標週期為10)。
      買入:(紅色)訊號線穿越主要(綠色)線,為買進的​​訊號,且紅線的值小於0。
      賣出:兩線交叉且,且紅線值大於0為賣出訊號。
    • 這些操作的設定套用在一小時的時間框(H1)上。
    • 操作的部位大小設定為:0,01 lot,停利50點,停損30點。

    交易訊號

    買入訊號

    1. ADX大於等於30,且+DI大於-DI。
    2. AC值小於0且漸增(負區間出現三根越來越短的綠棒)。
    3. RVI指標自下而上穿越主線,且兩者皆小於0且漸增。
    4. 買進0.01 lot,停利50點,停損30點。

    賣出訊號

    1. ADX大於等於30,且-DI大於+DI。
    2. AC值大於0且漸減(正區間出現三根越來越短的紅色棒)。
    3. RVI指標自上而下穿越主線,且兩者皆大於0且漸減。
    4. 賣出0.01 lot,停利50點,停損30點。

    步驟3:決定如何退場

    定義好交易策略後。設定開啟、關閉部位的條件,並選則套用的指標同時決定相關參數的值,及部位的大小和獲利目標。最後是定出退場的條件。我們設定退場的條件為:實現50點停利或30點停損。然後,以實際的情況來檢驗交易策略的性能。

    首先,強調一個正確的觀念;長遠而言,不存在所謂絕對理想的策略。不論是自動交易或手動交易,都有各自適用的情境。此外,運用交易實務累積的經驗,來更改原先設計的交易條件,以獲得更佳的績效,也是常有的現象。譬如:交易員發現每次停利後,價格仍繼續走高一段時間。實務中的數據統計及分析,可能會啟發交易員設定更高的 Take Profit 值,以持續擴大獲利。也因此產生了一個問題,就是:要如何善用市場上現有的訊息(數據),來改善交易策略,以提高獲利呢?

    本文所採用的方法,就是借助Fuzzy Logic來改善存在於一元明確邏輯決策下的弱點。 一元邏輯存在的一個弱點是,當以多個指標進行決策時,僅能考慮個指標是否滿足,而未能將指標的【強度】納入決策。運用Fuzzy Logic則可以將訊息的【強度】納入決策

    【先備知識】Read the article "An Introduction to Fuzzy Logic" to grasp the general concepts of the fuzzy logic theory. Also, learn the basics of FuzzyNet library for MQL4, since it is used for the implementation of the examples. 

    【先備知識】Mamdani fuzzy model 

    運用模糊邏輯彌補明確形式邏輯的弱點

    模糊理論的主要優勢是可以來「靈活地」運用策略系統中所採用的指標。模糊邏輯將明確界限模糊化,藉由給予不同程度的「歸屬」和系統的反應,擴大系統操作反應的區間範圍。所謂「靈活」,其實是將單一指標的決斷邊界模糊化,而產生一定程度的trade-off互償效應。

    舉例說明運用模糊邏輯更彈性來操作ADX指標的做法。

    原先(套用模糊邏輯之前),微弱、中度和強烈趨勢間存在著明確的區分界線。Fuzzy Logic將這些類別的區分模糊化,使它們不再明確嚴格,也不再以指標值形成明確嚴格的決策。

    然而,回到我們的交易系統並試問:運用Fuzzy Logic後,會提高操作績效嗎?

    試想,【模擬狀況A】:在盤中看到第一個指標訊號ADX值出現32時,交易員還必須等其它兩個指標的訊號才能確認操作方向。若不久AC訊號也出現了,而此時ADX已經來到40了。又過一陣子,若RVI訊號線也穿越過主線;此時進場買進的三個條件皆已經滿足,而此刻ADX值已經來到了45
    據此,交易員按照策略規則,以0,01手量獲利50點,30停損進入市場。但是我們的系統中ADX值只要有超過30即可,並未進一步去評量ADX值的大小。

    現在,讓我們來模擬另一種可能的場景。
    【模擬狀況B】,一開始,形勢的發展和A情況相同。 ADX值先來到了 32,接著AC訊號也出現,此時ADX值也達到了40。但當RVI訊號也出現時,;此時進場買進的三個條件皆已經滿足,而此刻ADX值已經爆發到55,不只是A狀況中的45。

    比較A、B兩種狀況,狀況B明顯比狀況A來得強勢。但我們的交易策略卻仍然是買進同樣的部位,也設定相同停利和停損的值。在此,我們看到明確邏輯策略所存在的缺陷。明確(一元)邏輯會只等待訊號的出現,而未對訊號的品質(強弱)進行評估。即使,我們設法對訊號品質進行評估,最終也會因為明確判定類別的邏輯,而使策略仍然掉落傳統(明確邏輯)的決策範疇。這是明確(一元)邏輯本身的缺陷。

    為了運用Fuzzy Logic,透過ADX和RVI指標來判斷進出場呢?我們需要進一步做下列的處理:

    • 建立ADX和RVI明確程度(強中弱)的類別區分,做為新的輸入訊號。
    • 建立部位目標(就是策略的利或停損點及部位的大小)的明確類別。做為輸出訊號,並根據其市場強度進行修正。
    • 建立描述輸入、輸出訊號的類別的歸屬函數。
    • 建立介面,顯示根據新條件對原先初始策略的部位所做。
    • 建立彈性的設定,以修正隸屬函數,以便在必要時能修正這個推薦系統。

    模糊邏輯處理步驟】:

    1.將ADX區分為4種不同類別:low, medium, moderate, high


    Fig. 2. Visual trend strength divided in categories

    理論上,越強趨勢會持續越長時間。本範例的做法是:在當三個策略訊號都滿足時,根據當時ADX值的大小,對停利點進行10- 50點的(增減)修正。因此,必須先定義不同ADX的趨勢類別如何影響部位的修正,以決定輸出的類別。如下:

    將ADX的強度分成四個趨勢類別,對部位做不同程度的修正:

    • low_take:微弱趨勢,擴大10 - 20點的利潤目標。
    • mod_take:溫和趨勢,擴大20 - 30點的利潤目標。
    • med_take:中度趨勢,擴大30 - 40點的利潤目標。
    • high_take:高度趨勢,擴大40 - 50點的利潤目標。

    這四個趨勢類別的(模糊Fuzzy集理論)歸屬函數定義如下圖。包含lowhigh兩個梯形函數,以及moderatemedium兩個三角形函數。


    Fig. 3. Description of four trend categories of fuzzy logic

    2.將RVI指數的強弱類別分成四種: lowmediumhigh and higher有low、higher的兩個梯形函數,以及medium、high兩個三角形函數。如下:


    Fig. 4. Visual division of Relative Vigor Index by category

    Fig. 5. Description of RVI index categories

    3.利潤目標值也分成四類:第一類、第四類(10-20,40-50點)使用梯形歸屬函數(trapezium),中間兩個(20-30,30-40點)使用三角形(triangular)歸屬函數。輸入訊號描述的如圖6。


    Fig. 6. Description of categories for values of profit goals

    實作顯示部位修正的面板

    信息面板的實作,輸出四個觀測參數:

    • ADX值:當指定條件滿足(ADX大於等於30)時,才顯示。
    • RVI值:顯示RVI大於0.1(賣出訊號),或小於-0,1(買入訊號)。
    • 顯示修正的點數。在原始50點目標利潤外,新增額外的TP_plus。
    • 原定價位結合停利值顯示成新的交易價位。

    完成後的交易策略的外觀(圖面右上角的顯示建議),如下(圖6)所示。


    Fig. 7. Full implementation, general appearance, and setting of the trading strategy

    現在,來看如何用MQL4 tools 和 FuzzyNet library 進行實作。 

    採用 MQL4 tools來實作本策略的顯示面板。

    //+------------------------------------------------------------------+
    //| FuzzyNet Panel                                                   |
    //+------------------------------------------------------------------+
    #property indicator_chart_window
    #property indicator_buffers 1
    #property indicator_color1 Green
    //+------------------------------------------------------------------+
    //| Connecting libraries                                             |
    //+------------------------------------------------------------------+
    #include <Math\FuzzyNet\MamdaniFuzzySystem.mqh>

    定義起始屬性和引用模糊邏輯的程式庫:

    #include <Math\FuzzyNet\MamdaniFuzzySystem.mqh>。在圖表的窗口面板設定面板選項。定義一個自訂指標的indicator_buffer,用綠色箭頭指出目前分析的K棒。

    【註】實作,需先從 CodeBase【下載 FuzzyLogic Lib for MQL4】,安裝模糊邏輯套件在你的平台。做法:下載壓縮檔解壓縮後將Math資料夾拷貝到 \MQL4\Include\ 路徑下

    //--- Input parameters
    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 — font size of textual information (recommended range 8-15).
    • adx_period — operation period of ADX indicator.
    • num_bar — number of bar for which the system is calculated.
    • Screen_corner — angle for displaying the panel.
    • label_clr — color of header text.
    • textColor — color of value text. 【建議】textColor=Lime 亮綠色,以免和背景顏色相同,致使訊號不可見

    Fuzzy Logic Parameters 的輸入的區塊設定參數為:描述ADX 和 RVI 強度的歸屬函數的主要參數;輸入參數則為:修正的利潤目標

    【譯者註】這裡定義的 membership ,是模糊邏輯可以著墨之處。,可以累積交易所的經驗和統計,對歸屬函數進行優化(調整梯形或三角形函數的轉折點)。

    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;

    下一個區塊宣告變數,標題的名稱,信息面板的實際的模板(大小,位置,字體等),並定義顯示的參數和指標(箭頭)指出當前分析的K棒。

    int scaleX=55,scaleY=25,offsetX=35;
    //--- declare array with indicator names
    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 || 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);
          //--- change anchor corner    
          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);
          //--- change anchor corner
          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);
      }

     【譯註】Mamdani和Sugeno模糊推論法,本例使用Mamdani方法。Mamdani法可以用更直接、更接近人類的方式來描述專家的意見。但是,Mamdani模糊推理的計算量大。

    *模糊邏輯歸屬函數和系統運算(Membership Functions and calculating based on fuzzy logic)*

    兩個輸入訊號:ADX 和 RVI 指標,各定義4個歸屬函數描述不同的類別。
    一個輸出訊號。 
    四個規則,連結輸入和輸出信號。

    Mamdani function description:

    1. Let's create the new system of the Mamdani-type fuzzy logic system *fsRisk.

    2. Add the *fsTrend variable to it with a specified trend name and the minimum and maximum values ​​of 30 and 100.

    3. Next, we should add the fuzzy terms described above (Fig. 3, 4) with the membership functions selected for each category.

    4. Pass the steps 2-3 for the output value: create *fvSignal variable named signal and the minimum and maximum tp.

    5. Now, let's create a set of three fuzzy rules representing our system:

     

    • If a (trend is low) and (vigor is low) then signal is low_take.
    • If a (trend is moderate) and (vigor is medium) then signal is mod_take.
    • If (trend is medium) and (vigor is high) then signal is med_take.
    • If (trend is high) and (vigor is higher) then signal is high_take.

    6. Let's add our rules into the system

    7. Create the lists for input and output variables and add t, v input to be the mamdani function argument. Thus, the entire fuzzy logic system with specified input and output fuzzy variables is set for the entiremamdani function, while ADX and RVI indicator values are used as inputs.

    8. The resulting function value is res variable.

    //+------------------------------------------------------------------+
    //|  Membership Functions and calculating based on fuzzy logic       |
    //+------------------------------------------------------------------+
    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 Membership functions
       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 Membership functions
       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("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);
    //--- Create four Mamdani fuzzy rule
       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");
    //--- 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;
      }

    最後一個區塊,"Additional functions".
    首先是 tp_prc(double take) ,將停利點轉換成currency instrument price的點數值 。另一個則傳回訊號的小數位數數目。

    //+------------------------------------------------------------------+
    //| Function to determine the profit goals                           |
    //+------------------------------------------------------------------+
    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);
      }
    //+------------------------------------------------------------------+
    //| Function to return the amount of decimal places      |
    //+------------------------------------------------------------------+
    int Dig()
      {
       return((_Digits==5 || _Digits==3 || _Digits==1)?10:1);
      }
    //+------------------------------------------------------------------+

    我想特別提醒你注意並一再驗證設定值和 Fuzzy Logic Parameters 中參數的正確性。建議從原始圖3,5,6中著手。由於不當的設定值將導整個系統的錯誤操作。務必小心。

    Conclusion

    總結一下本文所學到的:

    • 創建具有模糊邏輯之人工交易策略的第一部分,在於:開發此策略所應用的明確規則。階段1 - 3在做這樣的檢查。
    • 然後,必須對所有要進行估計及參數作出明確分類。
    • 接著,建立描述所有明確類別的歸屬函數。
    • 本策略選用MQL4語言以MT4指標、面板、警示的形式實作出建議面板(panel)。

    我們藉由運用模糊理論以改善人工交易策略。使用示例說明如何運用模糊邏輯修正已成型的交易策略,擺脫已知的缺陷。

    MQ5網站提供檔案下載 | 
    fuzzy_panel.mq4 (23.67 KB)

     

    【注意】外匯交易平台詐騙充斥勿輕信;本文純就技術和交易觀念進行探討

     

    【註】本範例實作,需先從 CodeBase下載 FuzzyLogic Lib for MQL4,安裝在你的平台。做法:下載壓縮檔解壓縮後將Math資料夾拷貝到\MQL4\Include\路徑下

    fuzzy_panel.mq4檔案也下載放到\MQL4\Indicators路徑下。用Tools中MetaQuotes Language Editor開啟fuzzy_panel.mq4,執行(Editor功能表中的)Compile

    【註】:本文想幫助欲了解Fuzzy於Meta Trader 交易策略應用,礙於原文有閱讀困難,或對Fuzzy缺乏基礎的讀者。原文版權屬於 MQL5 Ltd,本譯文僅供閱讀方便。

    【註】Indicators的路徑
    C:\Users\某甲\AppData\Roaming\MetaQuotes\Terminal\BBxxxExxxxExxCxExxxxABxDxAxx\MQL4\Indicators

    【原文參考】https://www.mql5.com/en/articles/2195?utm_campaign=Facebook&utm_medium=display&utm_source=MQL5+EN+Article

    https://www.mql5.com/en/articles/2032

     

    【譯註】原文轉譯時(2016/2017吧?), FuzzyLogic Lib 尚能成功compile並執行。惟後來的版本(2019年後)似乎無法正常compile,官方論壇也有使用這出現此問題(詳),
    錯誤發生在:FuzzyRule.mqh和 RuleParser.mqh這二個include的模組:
    'Term' - no one of the overloads can be applied to the function call FuzzyRule.mqh 229 24

    cannot convert type 'Lexem *' to reference of type 'CObject *' RuleParser.mqh 485 37
    (2021,May仍無解) The library doesn't compile.
    ---------------
     MQL5中,已將fuzzy lib納入正式的模組了
    Fuzzy Library files are located in \MQL5\Include\Math\Fuzzy.
    https://www.metatrader5.com/en/releasenotes/terminal/1384
    參考
    fuzzy理論與程式(matlab)實例
    創作者介紹
    創作者 The Dance of Disorder (Fluctuations of Entropy) 的頭像
    Jason

    The Dance of Disorder (Fluctuations of Entropy)

    Jason 發表在 痞客邦 留言(0) 人氣( 2 )