// パラメータ設定
input double LotSize = 1.0;          // 固定ロットサイズ
input int Slippage = 3;              // スリッページ
input int IchimokuTenkan = 9;        // 一目均衡表の転換線期間
input int IchimokuKijun = 26;        // 一目均衡表の基準線期間
input int IchimokuSenkouSpanB = 52;  // 一目均衡表の先行スパンB期間
input int RangePeriod = 20;          // レンジブレイクの高値期間

// グローバル変数
bool positionOpened = false;         // ポジションが開かれているかどうか

// 初期化関数
int OnInit()
 {
  Print("15-Minute Ichimoku Range Breakout EA Initialized.");
  return(INIT_SUCCEEDED);
 }

// メイン関数
void OnTick()
 {
  // ポジションが開かれている場合はクローズ条件をチェック
  if (positionOpened)
    {
     CheckForClose();
     return;
    }

  // エントリー条件をチェック
  if (CheckForEntry())
    {
     Print("Opening position...");
    }
 }

// エントリー条件をチェックする関数
bool CheckForEntry()
 {
  // --- 三役好転の条件 ---
  if (!IsBullishIchimoku()) return false;

  // --- レンジブレイクの条件 ---
  if (!IsRangeBreakout()) return false;

  OpenBuy();
  positionOpened = true;
  return true;
}

// クローズ条件をチェックする関数
void CheckForClose()
 {
  // 現在の価格が雲に触れたらクローズ
  if (IsTouchingIchimokuCloud())
    {
     ClosePosition();
    }
}

// 買いポジションを開く関数
void OpenBuy()
 {
  int ticket = OrderSend(Symbol(), OP_BUY, LotSize, Ask, Slippage, 0, 0, "15M Ichimoku Range Breakout Buy", 0, 0, clrGreen);
  if (ticket > 0)
    {
     Print("Buy position opened successfully.");
    }
  else
    {
     Print("Failed to open buy position: ", GetLastError());
    }
 }

// ポジションをクローズする関数
void ClosePosition()
 {
  for (int i = OrdersTotal() - 1; i >= 0; i--)
    {
     if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES) && OrderType() == OP_BUY)
       {
        if (OrderClose(OrderTicket(), OrderLots(), Bid, Slippage, clrRed))
          {
           Print("Position closed successfully.");
           positionOpened = false;
          }
        else
          {
           Print("Failed to close position: ", GetLastError());
          }
       }
    }
 }

// 三役好転の条件を判定する関数
bool IsBullishIchimoku()
 {
  double senkouSpanA = iIchimoku(NULL, PERIOD_M15, IchimokuTenkan, IchimokuKijun, IchimokuSenkouSpanB, MODE_SENKOUSPANA, 0);
  double senkouSpanB = iIchimoku(NULL, PERIOD_M15, IchimokuTenkan, IchimokuKijun, IchimokuSenkouSpanB, MODE_SENKOUSPANB, 0);
  double tenkan = iIchimoku(NULL, PERIOD_M15, IchimokuTenkan, IchimokuKijun, IchimokuSenkouSpanB, MODE_TENKANSEN, 0);
  double kijun = iIchimoku(NULL, PERIOD_M15, IchimokuTenkan, IchimokuKijun, IchimokuSenkouSpanB, MODE_KIJUNSEN, 0);
  double chikou = iClose(NULL, PERIOD_M15, 26); // 遅行スパンは26期間前の終値

  double currentPrice = iClose(NULL, PERIOD_M15, 0);

  return (currentPrice > MathMax(senkouSpanA, senkouSpanB) && tenkan > kijun && chikou > currentPrice);
 }

// レンジブレイクの条件を判定する関数
bool IsRangeBreakout()
 {
  double highestHigh = iHigh(NULL, PERIOD_M15, iHighest(NULL, PERIOD_M15, MODE_HIGH, RangePeriod, 1));
  double currentPrice = iClose(NULL, PERIOD_M15, 0);

  return (currentPrice > highestHigh);
 }

// 雲に触れたかどうかを判定する関数
bool IsTouchingIchimokuCloud()
 {
  double senkouSpanA = iIchimoku(NULL, PERIOD_M15, IchimokuTenkan, IchimokuKijun, IchimokuSenkouSpanB, MODE_SENKOUSPANA, 0);
  double senkouSpanB = iIchimoku(NULL, PERIOD_M15, IchimokuTenkan, IchimokuKijun, IchimokuSenkouSpanB, MODE_SENKOUSPANB, 0);
  double currentPrice = iClose(NULL, PERIOD_M15, 0);

  return (currentPrice <= MathMax(senkouSpanA, senkouSpanB) && currentPrice >= MathMin(senkouSpanA, senkouSpanB));
 }

いいなと思ったら応援しよう!