2014年8月26日火曜日

前日高値または安値をブレークしたら、任意の時間だけエントリー注文を出す、ブレークアウトEA

6月10日にブログに載せた前日高値または安値の上下に任意のpips数離した価格に買いまたは売りストップ注文を出すEA (http://expertloungeblog.blogspot.jp/2014/06/ea.html)、に任意の時間だけエントリー注文を出す条件を付けくわえたEAです。前回のEAは日替わり時間を起点に前日の高値と安値を計算して、その日1日中エントリー注文を出す仕様でしたが、今回はエントリー注文を出す時間を指定できる条件を加えました。例えば、パラメータのEntryMinutesを180にすると、9時から180分後の12時までエントリー注文を発注します。12時以降はエントリー注文を取消します。

あくまでMQL4学習のためのサンプルコードです。今回はこのEAがどの通貨ペアやインターバルに最適なのかなど銘柄の推奨になるような、バックテストや最適化の検証結果には触れません。

サンプルをベースにご自身の好きなように変更してみてください。

■エントリールール

新規買
M時からL分までの間、前日高値のNpips上に買いのストップ注文を発注
新規売
M時からL分までの間、前日安値のNpips下に売りのストップ注文を発注

■エグジットルール

決済売
新規買価格よりMpips下に損切りのストップ注文を、Npips上に利益確定の指値注文を発注。また日替わり時間にポジションが残っていれば全決済。
決済買
新規買価格よりMpips上に損切りのストップ注文を、Npips下に利益確定の指値注文を発注。また日替わり時間にポジションが残っていれば全決済。

■コード説明

input double Lots = 0.1;
input int Break = 50;
input int Stop = 300;
input int Profit = 300;
input int StartHour = 7;
input int StartTime = 0;
 

input int EntryStartHour = 9;
input int EntryStartTime = 0;
input int EntryMinutes = 60;


Lots - ロット数設定
Break – 前日の高値/安値計算後、その上下に加算/減算するピップ数で50は5pips
Stop - エントリー約定価格からの損切りpips数で300は30pips
Profit - エントリー約定価格からの利益確定pips数で300は30pips
StartHour – 前日の高値/安値の計算開始時間で7は7時
StartTime – 前日の高値/安値の計算開始時間で0は7時0分
EntryStartHour – エントリー注文の発注開始時間で9 は9時
EntryStartTime – エントリー注文の発注開始時間で0は9時0分
EntryMinutes - エントリー注文の発注開始時間からの分数で60は9時から60分後の10時、120は9時から120分後の11時

sl = MarketInfo(Symbol(), MODE_STOPLEVEL)*p;
ブローカーのストップ注文や指値注文の最低幅(ストップレベル)を確認

positionInfo(longPos, shortPos, pendOrders, openPrice);

買いポジション数、売りポジション数、未約定注文、約定価格を計算


if (timeToSeconds(TimeCurrent()) == (entrystartHourSec + entrystartTimeSec))
現在時間がエントリー開始時間であれば

startedTime = TimeCurrent();

変数に現在時間を格納する

if (timeToSeconds(TimeCurrent()) == (startHourSec + startTimeSec)){
現在時間が日替わり時間であれば(7時の場合には7時から7時1分までの間に)

count++;

ティック数をカウントする

if (longPos > 0 || shortPos > 0)
closePositions();

買いポジションまたは売りポジションがある場合全てのポジションを決済する

if (count == 1){

最初のティックのときに

lastHH = hh;
lastLL = ll;

前日高値と安値を変数に格納する

hh = 0.1;
ll = 9999.0;

本日の高値と安値の計算のために変数を初期値に戻す

if (longPos == 0 && shortPos == 0 && pendOrders == 0 && entryDone == false && entryOK(startedTime)){

買いポジション、売りポジション、未約定注文がない、本日まだエントリーがない、そして指定したエントリー時間内の場合

            if (lastHH > 1){
               lastHH = MathMax(lastHH+breakPoint, Ask + sl);
               longTicket = OrderSend(Symbol(), OP_BUYSTOP, Lots, lastHH , 0, 0, 0, "BBreak", MagicNumber,0,Green);
            }

前日高値とストップレベルを比較して高い方を買いのストップ注文価格にして、買いのストップ注文を発注する

            if (lastLL < 9998.0){
               lastLL = MathMin(lastLL-breakPoint, Bid - sl);
               shortTicket = OrderSend(Symbol(), OP_SELLSTOP, Lots, lastLL , 0, 0, 0, "SBreak", MagicNumber,0,Red);
            }    

前日安値とストップレベルを比較して安い方を売りのストップ注文価格にして、売りのストップ注文を発注する

if (entryOK(startedTime) == false)
指定したエントリー時間外の場合

cancelPendingOrders();
エントリー注文を取消す

if (longPos > 0){

買いのストップ注文が約定して買いポジションを持っている場合

cancelPendingOrders();

売りのストップ注文を取消す

stopPrice = openPrice - stopPoint;
profitPrice = openPrice + profitPoint;

エントリー価格からの損切りと利益確定注文価格の計算

ticketMod = OrderModify(longTicket, openPrice, stopPrice, profitPrice, 0, Blue);

買いポジションに対して、損切りと利益確定注文を発注

if (shortPos > 0){

売りのストップ注文が約定して売りポジションを持っている場合

cancelPendingOrders();

売りのストップ注文を取消す

stopPrice = openPrice + stopPoint;
profitPrice = openPrice - profitPoint;

エントリー価格からの損切りと利益確定注文価格の計算

ticketMod = OrderModify(shortTicket, openPrice, stopPrice, profitPrice, 0, Magenta);

売りポジションに対して、損切りと利益確定注文を発注

hh = MathMax(hh,High[0]);
ll = MathMin(ll,Low[0]);

本日の高値と安値を計算する
以下からはユーザー定義関数で、主に上のメインの計算で使用する
bool entryOK(datetime startedTime1){
   datetime tm = TimeCurrent();
   if (tm - startedTime1 >= 0){
      if (tm - startedTime1 >= EntryMinutes*60){
         return(false);
      }else
         return(true);
   }else{
      if ((tm + (86400 - startedTime1)) >= EntryMinutes*60){
         return(false);
      }else
         return(true);   
   }
}
現在時間がエントリー時間内であることを確認する関数


int timeToSeconds(datetime time){
   int tts = TimeHour(time)*60*60 + TimeMinute(time)*60;
   return(tts);
}

時間を分数に変える計算で次のbreakCalcTimeで使う


void positionInfo(int &longPos, int &shortPos, int &pendOrders, double &openPrice){
   int i;
   for( i=0; i<OrdersTotal(); i++)
   {
     if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) break;
     if(OrderSymbol() != Symbol() && OrderMagicNumber() != MagicNumber) continue;
     if(OrderType() == OP_BUY){
        longPos++;
        openPrice = OrderOpenPrice();
     }else
     if(OrderType() == OP_SELL){
        shortPos++;
        openPrice = OrderOpenPrice();
     }else
        pendOrders++;
   }
}

買いポジション数、売りポジション数、未約定注文、約定価格を計算してOnTick()内で使う


void cancelPendingOrders(){
   int i;
   bool ticketDel;
   for( i=OrdersTotal()-1;i>=0;i--){
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) break;
      if(OrderSymbol() != Symbol() && OrderMagicNumber() != MagicNumber) continue;
      ticketDel = false;
      if (OrderType() != OP_BUY && OrderType() != OP_SELL)
         ticketDel = OrderDelete( OrderTicket() );

   }
}

未約定注文を取消す関数でOnTick()内で使う


void closePositions(){
   int i;
   bool ticketClose;
   for( i=OrdersTotal()-1;i>=0;i--)
   {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) break;
      if(OrderSymbol() != Symbol() && OrderMagicNumber() != MagicNumber) continue;
      ticketClose = false;
      if (OrderType() == OP_BUY)
         ticketClose = OrderClose( OrderTicket(), OrderLots(), MarketInfo(OrderSymbol(), MODE_BID), 0, Cyan);
      else
      if (OrderType() == OP_SELL)
         ticketClose = OrderClose( OrderTicket(), OrderLots(), MarketInfo(OrderSymbol(), MODE_ASK), 0, White);
   }
}

オープンポジションを決済する関数でOnTick()内で使う

■コード全体

input double Lots = 0.1;
input int Break = 50;
input int Stop = 300;
input int Profit = 300;
input int StartHour = 7;
input int StartTime = 0;
input int EntryStartHour = 9;
input int EntryStartTime = 0;
input int EntryMinutes = 60;
input int MagicNumber = 8888;

int startHourSec = StartHour*60*60, startTimeSec = StartTime*60, entrystartHourSec = EntryStartHour*60*60, entrystartTimeSec = EntryStartTime*60,longTicket, shortTicket, ticketMod;
double hh = 0.1, ll = 9999.0, lastHH = 0.1, lastLL = 9999.0, p = Point, breakPoint = Break*p, stopPoint = Stop*p, profitPoint = Profit*p, sl = 0;
static int count = 0;
bool entryDone = false;
datetime startedTime;

void OnTick()
  {
   int longPos, shortPos, pendOrders;
   double openPrice, stopPrice, profitPrice;
  
   sl = MarketInfo(Symbol(), MODE_STOPLEVEL)*p;
   positionInfo(longPos, shortPos, pendOrders, openPrice);
        
   if (timeToSeconds(TimeCurrent()) == (entrystartHourSec + entrystartTimeSec))
      startedTime = TimeCurrent();

   if (timeToSeconds(TimeCurrent()) == (startHourSec + startTimeSec)){
      count++;
      if (longPos > 0 || shortPos > 0)
         closePositions();
      if (count == 1){
         entryDone = False;
         lastHH = hh;
         lastLL = ll;
         hh = 0.1;
         ll = 9999.0;

      }
   }else{
      count = 0;
         if (longPos == 0 && shortPos == 0 && pendOrders == 0 && entryDone == false && entryOK(startedTime)){
            ticketMod = false;
            if (lastHH > 1){
               lastHH = MathMax(lastHH+breakPoint, Ask + sl);
               shortTicket = OrderSend(Symbol(), OP_SELLLIMIT, Lots, lastHH , 0, 0, 0, "BBreak", MagicNumber,0,Green);
            }
            if (lastLL < 9998.0){
               lastLL = MathMin(lastLL-breakPoint, Bid - sl);
               longTicket = OrderSend(Symbol(), OP_BUYLIMIT, Lots, lastLL , 0, 0, 0, "SBreak", MagicNumber,0,Red);
            }     
         }
         if (entryOK(startedTime) == false)
            cancelPendingOrders();
           
         if (longPos > 0){
            cancelPendingOrders();
            stopPrice = openPrice - stopPoint;
            profitPrice = openPrice + profitPoint;
            if (!ticketMod)
               ticketMod = OrderModify(longTicket, openPrice, stopPrice, profitPrice, 0, Blue);
            entryDone = true;
         }else
         if (shortPos > 0){
            cancelPendingOrders();
            stopPrice = openPrice + stopPoint;
            profitPrice = openPrice - profitPoint;
            if (!ticketMod)  
               ticketMod = OrderModify(shortTicket, openPrice, stopPrice, profitPrice, 0, Magenta);
            entryDone = true;
         }
   }
      hh = MathMax(hh,High[0]);
      ll = MathMin(ll,Low[0]); 

}
//+------------------------------------------------------------------+

bool entryOK(datetime startedTime1){
   datetime tm = TimeCurrent();
   if (tm - startedTime1 >= 0){
      if (tm - startedTime1 >= EntryMinutes*60){
         return(false);
      }else
         return(true);
   }else{
      if ((tm + (86400 - startedTime1)) >= EntryMinutes*60){
         return(false);
      }else
         return(true);   
   }
}

int timeToSeconds(datetime time){
   int tts = TimeHour(time)*60*60 + TimeMinute(time)*60;
   return(tts);
}

void positionInfo(int &longPos, int &shortPos, int &pendOrders, double &openPrice){
   int i;
   for( i=0; i<OrdersTotal(); i++)
   {
     if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) break;
     if(OrderSymbol() != Symbol() && OrderMagicNumber() != MagicNumber) continue;
     if(OrderType() == OP_BUY){
        longPos++;
        openPrice = OrderOpenPrice();
     }else
     if(OrderType() == OP_SELL){
        shortPos++;
        openPrice = OrderOpenPrice();
     }else
        pendOrders++;
   }
}

void cancelPendingOrders(){
   int i;
   bool ticketDel;
   for( i=OrdersTotal()-1;i>=0;i--){
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) break;
      if(OrderSymbol() != Symbol() && OrderMagicNumber() != MagicNumber) continue;
      ticketDel = false;
      if (OrderType() != OP_BUY && OrderType() != OP_SELL)
         ticketDel = OrderDelete( OrderTicket() );

   }
}

void closePositions(){
   int i;
   bool ticketClose;
   for( i=OrdersTotal()-1;i>=0;i--)
   {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) break;
      if(OrderSymbol() != Symbol() && OrderMagicNumber() != MagicNumber) continue;
      ticketClose = false;
      if (OrderType() == OP_BUY)
         ticketClose = OrderClose( OrderTicket(), OrderLots(), MarketInfo(OrderSymbol(), MODE_BID), 0, Cyan);
      else
      if (OrderType() == OP_SELL)
         ticketClose = OrderClose( OrderTicket(), OrderLots(), MarketInfo(OrderSymbol(), MODE_ASK), 0, White);
   }
}

0 件のコメント:

コメントを投稿