1分足でストラテジーテスターを使うと価格の値動きの範囲外で決済、エントリーされてる

 
1分足でストラテジーテスターを動かしてるのですが変なところで決済やエントリーがされるのですが、原因がわかる方はいませんか?一様コードを貼っておきます

//+------------------------------------------------------------------+
//|    BollingerBands_ManualClose_Revised_M1_EA.mq4                  |
//|  改善: 決済タイミングの見直しとエラーコードのログ強化               |
//+------------------------------------------------------------------+
#property strict

// --- 外部パラメータ ---
extern int TimeFrame = PERIOD_M1;  // 使用時間足
extern int BB_Period = 20;         // ボリンジャーバンドの期間
extern double BB_Deviation = 2.0;  // ボリンジャーバンドの偏差
extern int BB_Shift = 0;           // ボリンジャーバンドのシフト
extern int BB_AppliedPrice = PRICE_CLOSE;  // 価格種別

extern double LotSize = 0.1;  // ロットサイズ
extern int Slippage = 3;      // スリッページ
extern int MagicNumber = 987654;  // マジックナンバー

extern int TakeProfitPips = 20;  // 利確(pips)
extern int StopLossPips = 20;    // 損切り(pips)

double g_BuyEntryPrice = 0.0;  // 買いエントリー価格
double g_SellEntryPrice = 0.0; // 売りエントリー価格

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int init() {
   Print("EA Initialized on TimeFrame = ", TimeFrame);
   return(0);
}

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit() {
   Print("EA Deinitialized");
   return(0);
}

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void start() {
   string sym = "USDJPYp";  // シンボルをUSDJPYpに固定

   // pipMultiplier: 桁数が5または3の場合、1pip = 10*Point、そうでなければ1pip = Point
   double pipMultiplier = (Digits == 5 || Digits == 3) ? 10.0 : 1.0;

   // --- 取得:前のローソク足 (shift=1) のデータ ---
   double candleOpen = iOpen(sym, TimeFrame, 1);
   double candleClose = iClose(sym, TimeFrame, 1);
   double candleHigh = iHigh(sym, TimeFrame, 1);
   double candleLow = iLow(sym, TimeFrame, 1);

   // --- 取得:ボリンジャーバンドの値 ---
   double bbUpper = iBands(sym, TimeFrame, BB_Period, BB_Deviation, BB_Shift, BB_AppliedPrice, MODE_UPPER, 1);
   double bbLower = iBands(sym, TimeFrame, BB_Period, BB_Deviation, BB_Shift, BB_AppliedPrice, MODE_LOWER, 1);

   // --- 現在のリアルタイム価格(Bid/Ask) ---
   double bid = MarketInfo(sym, MODE_BID);
   double ask = MarketInfo(sym, MODE_ASK);

   // --- シグナル判定 ---
   bool buySignal = false;
   bool sellSignal = false;

   // 新【買いシグナル】(条件)
   if (candleHigh > bbUpper && candleOpen < bbUpper && candleClose < bbUpper && ask >= bbUpper)
      buySignal = true;

   // 新【売りシグナル】(条件)
   if (candleLow < bbLower && candleOpen > bbLower && candleClose > bbLower && bid <= bbLower)
      sellSignal = true;

   Print("M1: buySignal=", buySignal, " sellSignal=", sellSignal);

   // --- エントリー処理 ---
   // 同一側のポジションがなければエントリー
   if (buySignal && !PositionExists(OP_BUY)) {
      int ticket = OrderSend(sym, OP_BUY, LotSize, ask, Slippage, 0, 0, "BB Buy (Reversed)", MagicNumber, 0, clrBlue);
      if (ticket < 0)
         Print("Buy OrderSend error: ", GetLastError());
      else {
         g_BuyEntryPrice = OrderOpenPrice();
         Print("Buy entry executed at price: ", ask, " (EntryPrice=", g_BuyEntryPrice, ")");
      }
   }

   if (sellSignal && !PositionExists(OP_SELL)) {
      int ticket = OrderSend(sym, OP_SELL, LotSize, bid, Slippage, 0, 0, "BB Sell (Reversed)", MagicNumber, 0, clrRed);
      if (ticket < 0)
         Print("Sell OrderSend error: ", GetLastError());
      else {
         g_SellEntryPrice = OrderOpenPrice();
         Print("Sell entry executed at price: ", bid, " (EntryPrice=", g_SellEntryPrice, ")");
      }
   }

   // --- 決済チェック ---
   for (int i = OrdersTotal() - 1; i >= 0; i--) {
      if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {
         if (OrderSymbol() == sym && OrderMagicNumber() == MagicNumber) {
            // BUYポジションの場合(決済はBidで実行)
            if (OrderType() == OP_BUY) {
               double entryPrice = OrderOpenPrice();
               double diffPips = (bid - entryPrice) / (Point * pipMultiplier);
               if (diffPips >= TakeProfitPips || diffPips <= -StopLossPips) {
                  bool closed = OrderClose(OrderTicket(), OrderLots(), bid, Slippage, clrBlue);
                  if (closed) {
                     Print("BUY closed. Entry=", entryPrice, " Exit=", bid, " DiffPips=", diffPips);
                  } else {
                     Print("BUY close error: ", GetLastError());
                  }
               }
            }
            // SELLポジションの場合(決済はAskで実行)
            if (OrderType() == OP_SELL) {
               double entryPrice = OrderOpenPrice();
               double diffPips = (entryPrice - ask) / (Point * pipMultiplier);
               if (diffPips >= TakeProfitPips || diffPips <= -StopLossPips) {
                  bool closed = OrderClose(OrderTicket(), OrderLots(), ask, Slippage, clrRed);
                  if (closed) {
                     Print("SELL closed. Entry=", entryPrice, " Exit=", ask, " DiffPips=", diffPips);
                  } else {
                     Print("SELL close error: ", GetLastError());
                  }
               }
            }
         }
      }
   }
}

//+------------------------------------------------------------------+
//| 同一シンボル・MagicNumberかつ同側のポジションが存在するかチェック   |
//+------------------------------------------------------------------+
bool PositionExists(int orderType) {
   string sym = "USDJPYp";  // シンボルをUSDJPYpに固定
   for (int i = 0; i < OrdersTotal(); i++) {
      if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {
         if (OrderSymbol() == sym && OrderMagicNumber() == MagicNumber && OrderType() == orderType)
            return true;
      }
   }
   return false;
}

 
【モデレータの秘訣】フォーラムでコードについて討議される場合、コード(Alt+S)の機能をご活用ください。
【モデレータの秘訣】フォーラムでコードについて討議される場合、コード(Alt+S)の機能をご活用ください。
  • 2025.03.18
  • Sky All
  • www.mql5.com
皆様 お世話になっております。 フォーラムでコードについて討議されたい場合、そのまま貼り付けると、ロボに勝手に削除される場合がございます。 できれる限り、コード(Alt+S)の機能をご活用いただければ幸甚です...