あくまでMQL4学習のためのサンプルコードです。今回はこのEAがどの通貨ペアやインターバルに最適なのかなど銘柄の推奨になるような、バックテストや最適化の検証結果には触れません。
サンプルをベースにご自身の好きなように変更してみてください。
■エントリールール
新規買前日高値のNpips上に買いのストップ注文を発注
新規売
前日安値の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;
Lots - ロット数設定
Break – 前日の高値/安値計算後、その上下に加算/減算するピップ数で50は5pips
Stop - エントリー約定価格からの損切りpips数で300は30pips
Profit - エントリー約定価格からの利益確定pips数で300は30pips
StartHour – 前日の高値/安値の計算開始時間で7は7時
StattTime – 前日の高値/安値の計算開始時間で0は7時0分
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;
本日の高値と安値の計算のために変数を初期値に戻す
}else{
日替わり時間外であれば
if (longPos == 0 && shortPos == 0 && pendOrders == 0 && entryDone == false){
買いポジション、売りポジション、未約定注文がない、そして本日まだエントリーがない場合
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 (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]);
本日の高値と安値を計算する
以下からはユーザー定義関数で、主に上のメインの計算で使用する
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 MagicNumber = 8888;
int startHourSec = StartHour*60*60, startTimeSec = StartTime*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;
void OnTick()
{
int longPos, shortPos, pendOrders;
double openPrice, stopPrice, profitPrice;
sl = MarketInfo(Symbol(), MODE_STOPLEVEL)*p;
positionInfo(longPos, shortPos, pendOrders, openPrice);
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){
ticketMod = false;
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 (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]);
}
//+------------------------------------------------------------------+
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 件のコメント:
コメントを投稿