VQ

ここでは、インジケーターVQをEA内で算出する方法を解説します。

インジケーターVQについて知らない方は、過去記事【VQとVQ_EA】をご覧ください。
過去記事【VQとVQ_EA】へ

iCustom()関数を利用する方法

通常のやり方でiCustom()関数を利用する方法は次のようにします。

extern   bool     Crash = false;
extern   int      TimeFrame = 0;
extern   int      Length = 5;
extern   int      Method = 3;
extern   int      Smoothing = 1;
extern   int      Filter = 5;
extern   int      SignShift = 1;

VQのパラメーターとSignShiftというパラメータを設置して、OnTick()関数内で次のようにインジケーターVQのシグナルになりそうなインジケーターインデックスの値を取得します。

int  = iCustom(NULL, TimeFrame, "VQ", Crash, 0, Length, Method, Smoothing, Filter, 6, SignShift);

しかし、VQ自体にいろいろな機能が付いているため、EA内で計算したほうが動作がスムーズになります。

VQをEA内部で算出する方法

VQをEA内部で算出するには、次のようにします。

extern string  Entry_Setting  = "---------- Entry Setting";
extern double  Lots           = 0.1;
extern int     StopLoss       = 50;
extern int     TakeProfit     = 100;
extern int     Slippage       = 3;
extern int     MagicNumber    = 123456;

extern string Indicator_Setting = "---------- Indicator Setting";
extern int     TimeFrame      = 0;
extern int     Length         = 5;
extern int     Method         = 3;
extern int     Smoothing      = 1;
extern int     Filter         = 5;

extern int     EntryShift     = 1;
extern int     ExitShift      = 0;

//記憶用共通変数
int VQsign[2];    //VQのシグナル
int VQsignbar[2]; //VQのシグナルが出た場所(足の番号)
int bar;          //エントリした時の足の数(足の番号)

//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
  {
//----
   ArrayInitialize(VQsign, 0);
   ArrayInitialize(VQsignbar, 0);
   bar = 0;
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
  {
//----
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
  {
//----
   //VQ sign計算****************************************************
   FuncVQ(0);
   FuncVQ(1);
   
   //オーダーに関する部分*******************************************
   
   //現在のポジションの情報を取得
   int pos = -1;
   for(int i=OrdersTotal()-1; i>=0; i--)
   {
      OrderSelect(i,SELECT_BY_POS);
      if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber) pos = i;
   }
   
   /*
   この時点でポジションなしの場合 pos は -1
   ポジションありの場合 pos は、そのポジションのインデックスの値
   となります。
   */
   
   //ポジション有りの場合
   if(pos >= 0)
   {
      //そのポジションを選択し情報を取得できるようにする
      OrderSelect(pos, SELECT_BY_POS);
      
      if((OrderType() == OP_BUY && VQsign[ExitShift] == -1) || (OrderType() == OP_SELL && VQsign[ExitShift] == 1))
         OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), Slippage, clrYellow);
   }
   
   int ticket = 0;   //注文番号を代入する変数
   double sl, tp;   //ストップとリミットを代入する変数
   
   //まだエントリしていない足で ポジションなしの場合
   if(bar != iBars(NULL, TimeFrame) && pos < 0)
   {
      //エントリ条件を計算
      int sign;
      if(VQsignbar[EntryShift]==iBars(NULL,TimeFrame)-EntryShift)
      {
         if(VQsign[EntryShift]==1) sign=1;
         if(VQsign[EntryShift]==-1) sign=-1;
      }
      
      //sign が 1 の場合
      if(sign==1)
      {
         sl=Ask-StopLoss*Point;
         if(StopLoss<=0) sl=0;
         tp=Ask+TakeProfit*Point;
         if(TakeProfit<=0) tp=0;
         ticket=OrderSend(Symbol(),OP_BUY,Lots,Ask,Slippage,sl,tp,NULL,MagicNumber,0,Blue);
      }
      //sign が -1 の場合
      if(sign==-1)
      {
         sl=Bid+StopLoss*Point;
         if(StopLoss<=0) sl=0;
         tp=Bid-TakeProfit*Point;
         if(TakeProfit<=0) tp=0;
         ticket=OrderSend(Symbol(),OP_SELL,Lots,Bid,Slippage,sl,tp,NULL,MagicNumber,0,Red);
      }
      //エントリした時の足の数を代入
      if(ticket>0) bar=iBars(NULL,TimeFrame);
   }
   
//----
   return(0);
  }
//+------------------------------------------------------------------+

//VQ keisan
void FuncVQ(int VQshift)
{
   double MH1,ML1,MO1,MC1,MCS1,VQ1,SumVQ1,SumVQ2;
   HideTestIndicators(true);

   if(MathAbs(VQsign[VQshift])!=1)
   {
      for(int j=0;j<iBars(NULL,TimeFrame);j++)
      {
         MH1 = iMA(NULL,TimeFrame,Length,0,Method,PRICE_HIGH,VQshift+j);
         ML1 = iMA(NULL,TimeFrame,Length,0,Method,PRICE_LOW,VQshift+j);
         MO1 = iMA(NULL,TimeFrame,Length,0,Method,PRICE_OPEN,VQshift+j);
         MC1 = iMA(NULL,TimeFrame,Length,0,Method,PRICE_CLOSE,VQshift+j);
         MCS1 = iMA(NULL,TimeFrame,Length,0,Method,PRICE_CLOSE,VQshift + Smoothing+j);
         
         if(MathMax(MH1 - ML1,MathMax(MH1 - MCS1,MCS1 - ML1))==0 ||(MH1 - ML1)==0) return(0);
   
         VQ1 = MathAbs(((MC1 - MCS1) / MathMax(MH1 - ML1,MathMax(MH1 - MCS1,MCS1 - ML1))
                         + (MC1 - MO1) / (MH1 - ML1)) * 0.5)
                        * ((MC1 - MCS1 + (MC1 - MO1)) * 0.5);
         SumVQ2 = iClose(NULL,TimeFrame,2+j);
         SumVQ1 = SumVQ2 + VQ1;
         if (Filter > 0) if (MathAbs(SumVQ1 - SumVQ2) < Filter * Point) SumVQ1 = SumVQ2;

         if(SumVQ1 > SumVQ2)
         {
            if(VQsign[VQshift]==-1) break;
            
            VQsign[VQshift]=1;
            VQsignbar[VQshift]=iBars(NULL,TimeFrame)-VQshift-j;
         }
         if(SumVQ1 < SumVQ2)
         {
            if(VQsign[VQshift]==1) break;
            
            VQsign[VQshift]=-1;
            VQsignbar[VQshift]=iBars(NULL,TimeFrame)-VQshift-j;
         }
      }
   }
   
   MH1 = iMA(NULL,TimeFrame,Length,0,Method,PRICE_HIGH,VQshift);
   ML1 = iMA(NULL,TimeFrame,Length,0,Method,PRICE_LOW,VQshift);
   MO1 = iMA(NULL,TimeFrame,Length,0,Method,PRICE_OPEN,VQshift);
   MC1 = iMA(NULL,TimeFrame,Length,0,Method,PRICE_CLOSE,VQshift);
   MCS1 = iMA(NULL,TimeFrame,Length,0,Method,PRICE_CLOSE,VQshift + Smoothing);
   
   if(MathMax(MH1 - ML1,MathMax(MH1 - MCS1,MCS1 - ML1))==0 ||(MH1 - ML1)==0) return(0);
   
   VQ1 = MathAbs(((MC1 - MCS1) / MathMax(MH1 - ML1,MathMax(MH1 - MCS1,MCS1 - ML1)) + (MC1 - MO1) / (MH1 - ML1)) * 0.5) * ((MC1 - MCS1 + (MC1 - MO1)) * 0.5);
   SumVQ2 = iClose(NULL,TimeFrame,2);
   SumVQ1 = SumVQ2 + VQ1;
   if (Filter > 0) if (MathAbs(SumVQ1 - SumVQ2) < Filter * Point) SumVQ1 = SumVQ2;

   if(SumVQ1 > SumVQ2 && VQsign[VQshift]==-1)
   {
      VQsign[VQshift]=1;
      VQsignbar[VQshift]=iBars(NULL,TimeFrame)-VQshift;
   }
   if(SumVQ1 < SumVQ2 && VQsign[VQshift]==1)
   {
      VQsign[VQshift]=-1;
      VQsignbar[VQshift]=iBars(NULL,TimeFrame)-VQshift;
   }
   if(VQshift==0 && SumVQ1 == SumVQ2)
   {
      VQsign[0]=VQsign[1];
      VQsignbar[0]=VQsignbar[1];
   }
   HideTestIndicators(false);
}

今回は詳しい説明は省略しますが、コメント頂ければ詳細解説します。

ソースファイルをアップしますので、いろいろと改良してみてくださいね!
VQsimple.mq4ダウンロード

では、今回はこのへんでm(..)m