[MT4]チャートを分析して、一番多いパターンが来たらトレードするEA

パターン分析トレードとは

今回はMT4のファイル関数を使って、パターン分析トレードシステムを作成しました。

何を言っているかというと、「このパターンが来たら次にこのパターンになる確率が最も高い」みたいなものを分析して、トレードします。

良く人間がやるパターン別のトレード法みたいなものをちょっと簡単に機械にやらせてみようって回です。

実はプログラミングでは「パターンが来たらトレードする」というのは得ですが、「どのパターンが多いか調べる」ということになると意外とやっている人が少ないって点もあります。

分析方法

まずチャートの状態をカテゴライズします。

ロウソク足で分類しても良いのですが、一度試してみた結果、出現パターンが均一化してしまう※ので、今回は移動平均線を使いました。

※これってロウソク足パターン分析&トレードが意味ないってことを表していると思うんですけどね… ロウソク足が陽線→陰線→陽線になったら次は〇線みたいな分析は50%50%になってしまうので、丁半賭博をやっていたということでしょうか…

それは置いといて..短期、中期、長期の3種類の移動平均線を用意し、それぞれの位置関係から、相場の状態を分類します。

分かりやすく全パターン羅列すると、
(短期、中期、長期)に並んでいる状態(1)
(短期、長期、中期)に並んでいる状態(2)
(中期、短期、長期)に並んでいる状態(3)
(中期、長期、短期)に並んでいる状態(4)
(長期、短期、中期)に並んでいる状態(5)
(長期、中期、短期)に並んでいる状態(6)
の6状態が存在することになります。

つまり、移動平均線が3本あれば必ずこの6つのどれかの状態にカテゴライズされるという訳です。

”状態”と”パターン”の定義

次に、
それぞれの状態に番号をつけ、

どのようにその状態が推移していったかをファイル関数を使って記録していきます。

例:状態1 → 状態2 → 状態1 → 状態3 →・・・

これをずーーと記録していくと、3つの移動平均線の状態推移を表した数字群が出来上がります。

次に、その長い数列の中から、もっとも出現確率が高いパターンを分析します。

このパターンは連続する数によって大きく変わるので、今回は3桁までとしました。

つまり、連続した3つの数字において、もっとも出現確率が高いパターンを割り出します。状態1→状態2ときたら次に状態?が最も気やすいというのが確率的にわかるって訳です。

ここが比較的大変なポイントですが、連続した3つの数字のパターンをすべて書き出し、それぞれに番号を振ります。先ほどのまでの数字は”状態”に対するナンバリングでしたが、これは”パターン”に対するナンバリングです。

具体的には、

状態1→状態2→状態1 のパターンをパターン1とする。

状態1→状態2→状態3 のパターンをパターン2とする。

のような感じです。

記録と検索

そして、その文字列を数列に対して検索し、何回検索できるかをカウントします。これならMQLの関数でも可能ですね。

それがすべて終了すると、もっとも出現頻度が高いパターンの番号が分かります。

そして、出現頻度が高いパターンが現れた際に、利益が取れる方向にエントリーするようにプログラムを組みます。

バックテストすると、レポートに下記のような表示がでます。
bandicam-2016-12-28-16-49-21-075

スタートする前のロウソク足1000本では、状態の変化回数は92回で、
652のパターンが最も出現頻度が高いということを示しています。

このコードの問題点としては、過去のロウソク足は1000本までしか参照できないというMT4の仕様がネックになっています。(この記事はかなり古いので今やればもっといけるかも)

推移だけを元にしているので、テストモデルはコントロールポイントでOKです。

下手に全ティックなどにすると、かなり重くなるかもしれません。

forex-mt4-mt5-ea

2019/1/1~2019/12/31 EURUSD H1バックテスト結果

ソースコード

EAのダウンロード

ソースコードのダウンロード

extern double Lot = 0.1;

extern int MAperiod1 = 5;
extern int MAperiod2 = 20;
extern int MAperiod3 = 100;
//extern int MAperiod4 = 40;
//extern int MAperiod5 = 80;

extern int ExamineBars = 1000;

extern int Magic = 314221;

static string StateFlow[1000];

static int Bar[2],EntryBar;
static string System;

static int BestStateFlowNum;
static string BestStateFlow;

static int EntryStateNum;
static string EntryStateFlow;
static int EntrySearchLen;
static int EntryDirection;



      
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{
//---

   
   
   //Create StateFlow
   int A = 0;
   for(int i=1; i<=6 ;i++)
   {
      for( int p=1; p<=6; p++)
      {
         for( int q=1; q<=6; q++)
         {
            if( i == p  || p ==q || q==i) continue;
            A++;
            StateFlow[A] = IntegerToString(i)+IntegerToString(p)+IntegerToString(q);
            //Print("["+A+"]"+" is... "+StateFlow[A]);
         }
      }
   }
   // this 6 comes from the total number of the StateFlows.
   
   
   //the result of this are like
   /*
   StateFlow[1] = "12";
   StateFlow[2] = "13";
   StateFlow[3] = "14";
   StateFlow[4] = "15";
   StateFlow[5] = "16";
   StateFlow[6] = "21";
   StateFlow[7] = "23";
   StateFlow[8] = "24";
   StateFlow[9] = "25";
   StateFlow[10] = "26";
   StateFlow[11] = "31";
   StateFlow[12] = "32";
   StateFlow[13] = "34";
   ....
   */
      
   
   
   
//---
   return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//---

}
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
{
//---
   
   Bar[1] = Bar[0];
   Bar[0] = Bars;
   
   
   if( Bar[0] != Bar[1] )
   {
      
      string FileText;
      int ExistedBar;
      int StateFlowChange;
      for( int m=ExamineBars ; m>0; m--)
      {   
         //Print("SearchStateNum "+m+" "+SearchStateNum(m));
         if( SearchStateNum(m) != SearchStateNum(m+1) )
         {
            FileText += IntegerToString(SearchStateNum(m),1);
            StateFlowChange++;
         }
         if( iClose(Symbol(),Period(),m) != 0 ) ExistedBar++;
      }
      //Print("FileText "+FileText);
      Print("ExamineBars are "+ExamineBars+"  Existed Bar are "+ExistedBar);
      Print("StateFlow changes "+StateFlowChange+" times");
      
      
      string FileName=Symbol()+Period()+"StateFlow"+".txt"; 
      int FileHandle=FileOpen(FileName,FILE_WRITE|FILE_TXT|FILE_COMMON); 
      //Print("Handle "+FileHandle);
      FileWriteString(FileHandle,FileText); 
      FileClose(FileHandle); 
      
      
   
      
      
      
      string AnalyzedDataStr;
      int StateFlowTimes[1000];
      for(int j=1;j<=120;j++ )
      {
         //Get StateFlow data
         FileName=Symbol()+Period()+"StateFlow"+".txt";
         FileHandle = FileOpen(FileName,FILE_READ|FILE_TXT|FILE_COMMON);
         string SearchData = FileReadString(FileHandle,0);
         FileClose(FileHandle);
   
         
         string ExtractedData;
         int StateFlowPlace;
         
         //Search most appearable StateFlow
         StateFlowPlace = StringFind(SearchData,(StateFlow[j]));
         ExtractedData = StringSubstr(SearchData,StateFlowPlace+1);
         while(true)
         {
            StateFlowPlace = StringFind(ExtractedData,(StateFlow[j]));
            if( StateFlowPlace == -1 ) break;
            else
            {
               ExtractedData = StringSubstr(ExtractedData,StateFlowPlace+1);
               StateFlowTimes[j]++;
            }
         }
         
         AnalyzedDataStr += (StateFlow[j]+":"+StateFlowTimes[j]+";");      
         //Print(StateFlow[j]+":"+StateFlowTimes[j]+",");
               
         if( BestStateFlowNum < StateFlowTimes[j] )
         {
            BestStateFlowNum = StateFlowTimes[j];
            BestStateFlow = StateFlow[j];
         } 
      }
      
      //Write Analyzed data on Analyze.txt
      FileName = Symbol()+Period()+"Analyze"+".txt";   
      FileHandle = FileOpen(FileName,FILE_WRITE|FILE_TXT|FILE_COMMON);
      FileWriteString(FileHandle,AnalyzedDataStr);
      FileClose(FileHandle);  
      
      //write best StateFlow on BestStateFlow.txt
      FileName = Symbol()+Period()+"BestStateFlow"+".txt"; 
      FileHandle = FileOpen(FileName,FILE_WRITE|FILE_TXT|FILE_COMMON); 
      FileWriteString(FileHandle,BestStateFlow);
      FileClose(FileHandle);
      
      //StateFlow means the flow of state
      EntryStateFlow = StringSubstr(BestStateFlow,0,StringLen(BestStateFlow)-1);
      //State means the state
      EntryStateNum = StringToInteger(StringSubstr(EntryStateFlow,StringLen(EntryStateFlow)-1,1));
      string BeforeState = StringSubstr(BestStateFlow,StringLen(BestStateFlow)-2,1);
      string AfterState = StringSubstr(BestStateFlow,StringLen(BestStateFlow)-1,1);
      EntryDirection = GetEntryDirection(BeforeState,AfterState);
      EntrySearchLen = StringLen(BestStateFlow)-1;
      
      Print("BestStateFlow "+BestStateFlow);
      Print("EntryDirection "+EntryDirection);
      Print("EntryStateFlow "+EntryStateFlow);
   
   }
   
   
   //CLOSE
   if( OrdersTotal() > 0 )
   {
      if( EntryBar != Bars )
      {
         bool RSelect = OrderSelect(0,SELECT_BY_POS);
         if( OrderType() == OP_BUY )
         {
            //if State changed
            if( GlobalVariableGet("EntriedState") != SearchStateNum(0)  )
            {
               bool RClose = OrderClose(OrderTicket(),OrderLots(),Bid,3,clrRed);
            }
         }
         else if( OrderType() == OP_SELL )
         {
            if( GlobalVariableGet("EntriedState") != SearchStateNum(0)  )
            {
               RClose = OrderClose(OrderTicket(),OrderLots(),Ask,3,clrBlue);
            }
         } 
         
      }
   }
   
   
   if( Bar[0] != Bar[1]  )
   {
      
      //Create Current StateFlow
      string CurrentStateFlow = "";
      for(int k=EntrySearchLen; k>=1;k--)
      {
         CurrentStateFlow += StringToInteger(SearchStateNum(k));
      }
     
      //ENTRY
      if( OrdersTotal() == 0 )
      {
         if( CurrentStateFlow == EntryStateFlow )
         {
            int Ticket;
            //BUY
            if( EntryDirection == 1 ){
               Ticket = OrderSend(Symbol(),OP_BUY,Lot,Ask,3,0,0,WindowExpertName(),Magic,0,clrRed);
               EntryBar = Bars;
               GlobalVariableSet("EntriedState",EntryStateNum);
               GlobalVariableSet("EntriedBestStateFlow",BestStateFlow);
               //Print("CurrentStateFlow "+CurrentStateFlow+" EntryStateFlow "+EntryStateFlow); 
            }
            //SELL
            if( EntryDirection == -1 ){
               Ticket = OrderSend(Symbol(),OP_SELL,Lot,Bid,3,0,0,WindowExpertName(),Magic,0,clrBlue);
               EntryBar = Bars;
               GlobalVariableSet("EntriedState",EntryStateNum);
               GlobalVariableSet("EntriedBestStateFlow",BestStateFlow);
               //Print("CurrentStateFlow "+CurrentStateFlow+" EntryStateFlow "+EntryStateFlow); 
            }
            
         }
      }
   }
}
//+------------------------------------------------------------------+
//| ChartEvent function                                              |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
{
//---
   
}
//+------------------------------------------------------------------+
string DigitFix3(string FixedStr)
{
   string DummyReturn;
   if( StringToInteger(FixedStr) < 10 ) DummyReturn = "00"+FixedStr;
   else if( StringToInteger(FixedStr) < 100 ) DummyReturn = "0"+FixedStr;
   //else if( StringToInteger(FixedStr) == -1 ) DummyReturn = "365";
   else DummyReturn = FixedStr;
   
   return(DummyReturn);
}


int SearchStateNum(int Shift)
{
   double MA[10];
   MA[1] = iMA(Symbol(),Period(),MAperiod1,0,MODE_SMA,PRICE_CLOSE,Shift);
   MA[2] = iMA(Symbol(),Period(),MAperiod2,0,MODE_SMA,PRICE_CLOSE,Shift);
   MA[3] = iMA(Symbol(),Period(),MAperiod3,0,MODE_SMA,PRICE_CLOSE,Shift);
   //MA[4] = iMA(Symbol(),Period(),MAperiod4,0,MODE_SMA,PRICE_CLOSE,Shift);
   //MA[5] = iMA(Symbol(),Period(),MAperiod5,0,MODE_SMA,PRICE_CLOSE,Shift);
   
   /*
   int StateNum;
   //State1 123
   if( MA[1] >= MA[2] && MA[2] >= MA[3] ) StateNum = 1;
   //State2 132
   else if( MA[1] >= MA[3] && MA[3] >= MA[2] ) StateNum = 2;
   //State3 213
   else if( MA[2] >= MA[1] && MA[1] >= MA[3] ) StateNum = 3;
   //State4 231
   else if( MA[2] >= MA[3] && MA[3] >= MA[1] ) StateNum = 4;
   //State5 312
   else if( MA[3] >= MA[1] && MA[1] >= MA[2] ) StateNum = 5;
   //State6 321
   else if( MA[3] >= MA[2] && MA[2] >= MA[1] ) StateNum = 6;
   
   else if( MA[1] == MA[2] && MA[2] == MA[3] ) StateNum = 6;
   else if( MA[3] >= MA[2] && MA[2] >= MA[1] ) StateNum = 6;
   else if( MA[3] >= MA[2] && MA[2] >= MA[1] ) StateNum = 6;
   */
   
   int StateNum;
   int f=0;
   for( int a =1;a<=3;a++)
   {
      for( int b=1;b<=3;b++)
      {
         for( int c=1;c<=3;c++)
         {
            if( a == b || b == c || c == a ) continue;
            f++;
            if( MA[a] >= MA[b] && MA[b] >= MA[c] )
            {
               StateNum = f;
               break;
            }
         }
         if( StateNum != 0 ) break;
      }
      if( StateNum != 0 ) break;
   }
   
   return(StateNum);
   
   /*
   111x
   112x
   113x
   121x
   122x
   123
   131x
   132
   133x
   211x
   212x
   213
   221x
   222x
   223x
   231
   232x
   233x
   311x
   312
   313x
   321
   322x
   323x
   331x
   332x
   333x
   */
   
   
}

string StateNumToStr(int InpStateNum)
{
   /*
   string State;
   switch(StateNum){
      case 1: State = "123";break;
      case 2: State = "132";break;
      case 3: State = "213";break;
      case 4: State = "231";break;
      case 5: State = "312";break;
      case 6: State = "321";break;
      default:State = "000";break;
   }
   return(State);
   */
   
   int StateNum;
   string StateStr[20];
   int f;
   for( int a =1;a<=3;a++)
   {
      for( int b=1;b<=3;b++)
      {
         for( int c=1;c<=3;c++)
         {
            if( a == b || b == c || c == a) continue;
            f++;
            StateNum = f;
            StateStr[f] = IntegerToString(a,1)+IntegerToString(b,1)+IntegerToString(c,1);
            if( InpStateNum == StateNum ) return(StateStr[StateNum]);
         }
      }
   }
   
   return("E");//Error
   
}



int GetEntryDirection(int StateNumBefore, int StateNumAfter)
{
   string StateBeforeStr = StateNumToStr(StateNumBefore);
   string StateAfterStr = StateNumToStr(StateNumAfter);
   
   if( StringFind(StateAfterStr,"1",0) < StringFind(StateBeforeStr,"1",0) ) return(1);
   if( StringFind(StateAfterStr,"1",0) > StringFind(StateBeforeStr,"1",0) ) return(-1);
   else return(0);
}

Message

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA


関連記事

no image

プログラマ向け自動売買開発アイディア

「MQL4/MQL5は扱えるようになったけど、プログラミングのアイディアがない」というプログラマは比

記事を読む

(MQL4)WEBサイトの情報を取得するやり方[EA]WebRequest

MT4のチャート上にWEBサイトの情報を参照する方法について紹介します。   背景

記事を読む

2chのスレをテキストマイニングするやり方

よく「大衆の逆をいけば勝てる」みたいなことが相場の世界では言われますよね。今回は2chの市況版の住民

記事を読む

保護中: [MT4EA]完全無敗 勝率100%のバックテストを生成するEA[ソースコードあり]

今回はバックテストで完璧な成績を出すEAを作成しました。 意味は...ありません。ただの道楽です。

記事を読む

[MT4/MT5]EAに口座縛り/期間限定縛りをかける種類と方法

良いEAができた場合、身内で配布したい場合があります。しかし、身内に渡してしばらく経ってから自分のE

記事を読む

 

上に戻る