MT4用フリーツール:ChatGPT(GPTs)で作成:水平ライン越えで、エントリー、ポジションクローズを行う

ChatGPTでEA作成
スポンサーリンク

水平ライン越えで、エントリー、ポジションクローズを行うツール(EA)の作成

ChatGPT(GPTs)にお願いして、ちょっと便利なツール(EA)を作ってもらいました。
チャート上に、買い、売り用の水平ラインを設定し、水平ラインの上抜け、下抜けで、買いエントリ・売りポジションのクローズ、売りエントリー・買いポジションのクローズを行います。

パラメータで、エントリーのみ、クローズのみ、損切ライン(逆指値)の設定などもできるようにしています。

使用GPTs:EA Creator

依頼内容と実行結果

今回は、何度か修正たり、仕様を変えてもらったりしたので、ちょっと苦労しましたが、基本そのまま使えるものを作ってもらえました。

依頼内容(1回目)

以下の仕様でEAの作成をお願いします。

#パラメータ
・注文ロット数
・買い判定用水平ラインの名称:買いエントリー 兼 売りポジションクローズ用
・売り判定用水平ラインの名称:売りエントリー 兼 買いポジションクローズ用
・エントリー、クローズ条件の判定間隔(秒単位で、初期値は1秒)
その他、必要なものあれば追加

#仕様
・取引通貨ペアはEAをセットしたチャートの通貨ペア
・エントリー、クローズ条件の判定は、OnTick()でパラメータで指定された判定間隔単位で行う
・エントリー条件は以下。
 ポジションを持っていない
 買い判定用水平ラインを上抜けて足が確定したら、買いエントリー
 売り判定用水平ラインを下抜けて足が確定したら、売りエントリー
・ポジションのクローズ条件
 買いポジションを持っているときに、売り判定用水平ラインを下抜けて足が確定したらクローズする
 売りポジションを持っているときに、買い判定用水平ラインを上抜けて足が確定したらクローズする

ChatGPT出力結果

以下の仕様に基づいて、EAのMQL4コードを提供します。このEAは、指定された水平ラインを基に売買エントリーおよびポジションクローズを行い、エントリーおよびクローズ条件の判定をパラメータで指定された間隔で行います。

//+------------------------------------------------------------------+
//|                                         EA_LineBreakTrader       |
//|                        Copyright 2023, MetaQuotes Software Corp. |
//|                                       http://www.metaquotes.net/ |
//+------------------------------------------------------------------+
#property strict

input double LotSize = 0.1; // 注文ロット数
input string BuyLineName = "BuyLine"; // 買い判定用水平ラインの名称
input string SellLineName = "SellLine"; // 売り判定用水平ラインの名称
input int CheckIntervalSeconds = 1; // エントリー、クローズ条件の判定間隔(秒単位)

datetime lastCheckTime = 0;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   datetime currentTime = TimeCurrent();

   if (currentTime - lastCheckTime >= CheckIntervalSeconds)
     {
      lastCheckTime = currentTime;

      // 水平ラインの価格を取得
      double buyLineLevel = ObjectGetDouble(0, BuyLineName, OBJPROP_PRICE);
      double sellLineLevel = ObjectGetDouble(0, SellLineName, OBJPROP_PRICE);

      // エントリーとクローズの条件をチェック
      CheckEntryConditions(buyLineLevel, sellLineLevel);
      CheckCloseConditions(buyLineLevel, sellLineLevel);
     }
  }
//+------------------------------------------------------------------+
//| エントリー条件のチェック                                         |
//+------------------------------------------------------------------+
void CheckEntryConditions(double buyLineLevel, double sellLineLevel)
  {
   if (OrdersTotal() == 0)
     {
      double open = iOpen(NULL, 0, 1);
      double close = iClose(NULL, 0, 1);

      // 買いエントリー条件
      if (close > buyLineLevel && open < buyLineLevel)
        {
         OrderSend(Symbol(), OP_BUY, LotSize, Ask, 3, 0, 0, "", 0, 0, clrGreen);
        }

      // 売りエントリー条件
      if (close < sellLineLevel && open > sellLineLevel)
        {
         OrderSend(Symbol(), OP_SELL, LotSize, Bid, 3, 0, 0, "", 0, 0, clrRed);
        }
     }
  }
//+------------------------------------------------------------------+
//| クローズ条件のチェック                                           |
//+------------------------------------------------------------------+
void CheckCloseConditions(double buyLineLevel, double sellLineLevel)
  {
   for (int i = OrdersTotal() - 1; i >= 0; i--)
     {
      if (OrderSelect(i, SELECT_BY_POS))
        {
         double open = iOpen(NULL, 0, 1);
         double close = iClose(NULL, 0, 1);

         // 買いポジションクローズ条件
         if (OrderType() == OP_BUY && close < sellLineLevel && open > sellLineLevel)
           {
            OrderClose(OrderTicket(), OrderLots(), Bid, 3, clrBlue);
           }

         // 売りポジションクローズ条件
         if (OrderType() == OP_SELL && close > buyLineLevel && open < buyLineLevel)
           {
            OrderClose(OrderTicket(), OrderLots(), Ask, 3, clrOrange);
           }
        }
     }
  }
//+------------------------------------------------------------------+

説明

  1. パラメータ
  • LotSize: 注文ロット数
  • BuyLineName: 買い判定用水平ラインの名称
  • SellLineName: 売り判定用水平ラインの名称
  • CheckIntervalSeconds: エントリーおよびクローズ条件の判定間隔(秒単位)
  1. 初期化 (OnInit)
  • 特に初期化は必要ありません。
  1. ティックイベント (OnTick)
  • ポジションチェックを設定された間隔で行うための条件を追加しました。
  • 水平ラインの価格を取得し、エントリーおよびクローズ条件の判定を行います。
  1. エントリー条件のチェック (CheckEntryConditions)
  • 水平ラインの価格を基に、買いおよび売りエントリーの条件をチェックします。
  • 条件が満たされた場合、新しい注文を送信します。
  1. クローズ条件のチェック (CheckCloseConditions)
  • 保有中のポジションに対して、買いおよび売りポジションのクローズ条件をチェックします。
  • 条件が満たされた場合、該当するポジションをクローズします。

このEAは、指定された水平ラインを基に売買エントリーおよびポジションクローズを行います。EAをチャートに適用し、指定された水平ラインを引くことで動作を確認できます。

依頼内容(2回目)

上記EAに追加の対応をお願いします

・EAに”EA_”で始まる名前を付ける
・OrderSend()のリターン値判定を行い、エラーの場合はエラー内容のPrint文出力を行う
・以下の仕様追加を行う

#パラメータ
・エントリーのみ、ポジションクローズのみ、両方を指定できるパラメータの追加
・再エントリー抑止有無

#仕様
・パラメータで、
 エントリーのみが指定されている場合は、クローズ判定は行わない
 ポジションクローズのみが指定されている場合は、エントリー判定は行わない
・買い、売り判定用水平ラインの価格に変更がなく、かつ、再エントリー抑止有りの場合は、
 同じ価格での再エントリーは行わない

ChatGPT出力結果

以下の仕様に基づいて、EAのMQL4コードを修正し、追加対応を行います。

変更点

  1. EAに”EA_”で始まる名前を付ける。
  2. OrderSend()のリターン値判定を行い、エラーの場合はエラー内容をPrint文で出力する。
  3. エントリーのみ、ポジションクローズのみ、両方を指定できるパラメータの追加。
  4. 再エントリー抑止有無のパラメータ追加。
  5. 新しい仕様に基づくエントリーおよびクローズ判定の実装。
//+------------------------------------------------------------------+
//|                                         EA_LineBreakTrader       |
//|                        Copyright 2023, MetaQuotes Software Corp. |
//|                                       http://www.metaquotes.net/ |
//+------------------------------------------------------------------+
#property strict

input double LotSize = 0.1; // 注文ロット数
input string BuyLineName = "BuyLine"; // 買い判定用水平ラインの名称
input string SellLineName = "SellLine"; // 売り判定用水平ラインの名称
input int CheckIntervalSeconds = 1; // エントリー、クローズ条件の判定間隔(秒単位)
input int Mode = 0; // 0: 両方、1: エントリーのみ、2: ポジションクローズのみ
input bool PreventReEntry = true; // 再エントリー抑止有無

datetime lastCheckTime = 0;
double lastBuyLineLevel = 0;
double lastSellLineLevel = 0;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   lastBuyLineLevel = ObjectGetDouble(0, BuyLineName, OBJPROP_PRICE);
   lastSellLineLevel = ObjectGetDouble(0, SellLineName, OBJPROP_PRICE);
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   datetime currentTime = TimeCurrent();

   if (currentTime - lastCheckTime >= CheckIntervalSeconds)
     {
      lastCheckTime = currentTime;

      // 水平ラインの価格を取得
      double buyLineLevel = ObjectGetDouble(0, BuyLineName, OBJPROP_PRICE);
      double sellLineLevel = ObjectGetDouble(0, SellLineName, OBJPROP_PRICE);

      // エントリー条件の判定
      if (Mode == 0 || Mode == 1)
        CheckEntryConditions(buyLineLevel, sellLineLevel);

      // クローズ条件の判定
      if (Mode == 0 || Mode == 2)
        CheckCloseConditions(buyLineLevel, sellLineLevel);

      // 再エントリー抑止のためのラインレベル更新
      lastBuyLineLevel = buyLineLevel;
      lastSellLineLevel = sellLineLevel;
     }
  }
//+------------------------------------------------------------------+
//| エントリー条件のチェック                                         |
//+------------------------------------------------------------------+
void CheckEntryConditions(double buyLineLevel, double sellLineLevel)
  {
   if (OrdersTotal() == 0)
     {
      double open = iOpen(NULL, 0, 1);
      double close = iClose(NULL, 0, 1);

      // 買いエントリー条件
      if (close > buyLineLevel && open < buyLineLevel && (!PreventReEntry || buyLineLevel != lastBuyLineLevel))
        {
         int ticket = OrderSend(Symbol(), OP_BUY, LotSize, Ask, Slippage, 0, 0, "", 0, 0, clrGreen);
         if (ticket < 0)
           {
            Print("Buy OrderSend failed with error #", GetLastError());
           }
        }

      // 売りエントリー条件
      if (close < sellLineLevel && open > sellLineLevel && (!PreventReEntry || sellLineLevel != lastSellLineLevel))
        {
         int ticket = OrderSend(Symbol(), OP_SELL, LotSize, Bid, Slippage, 0, 0, "", 0, 0, clrRed);
         if (ticket < 0)
           {
            Print("Sell OrderSend failed with error #", GetLastError());
           }
        }
     }
  }
//+------------------------------------------------------------------+
//| クローズ条件のチェック                                           |
//+------------------------------------------------------------------+
void CheckCloseConditions(double buyLineLevel, double sellLineLevel)
  {
   for (int i = OrdersTotal() - 1; i >= 0; i--)
     {
      if (OrderSelect(i, SELECT_BY_POS))
        {
         double open = iOpen(NULL, 0, 1);
         double close = iClose(NULL, 0, 1);

         // 買いポジションクローズ条件
         if (OrderType() == OP_BUY && close < sellLineLevel && open > sellLineLevel)
           {
            if (!OrderClose(OrderTicket(), OrderLots(), Bid, Slippage, clrBlue))
              {
               Print("Buy OrderClose failed with error #", GetLastError());
              }
           }

         // 売りポジションクローズ条件
         if (OrderType() == OP_SELL && close > buyLineLevel && open < buyLineLevel)
           {
            if (!OrderClose(OrderTicket(), OrderLots(), Ask, Slippage, clrOrange))
              {
               Print("Sell OrderClose failed with error #", GetLastError());
              }
           }
        }
     }
  }
//+------------------------------------------------------------------+

説明

  1. パラメータ
  • LotSize: 注文ロット数
  • BuyLineName: 買い判定用水平ラインの名称
  • SellLineName: 売り判定用水平ラインの名称
  • CheckIntervalSeconds: エントリーおよびクローズ条件の判定間隔(秒単位)
  • Mode: 0 = 両方、1 = エントリーのみ、2 = ポジションクローズのみ
  • PreventReEntry: 再エントリー抑止有無
  1. 初期化 (OnInit)
  • 水平ラインの初期価格を取得します。
  1. ティックイベント (OnTick)
  • ポジションチェックを設定された間隔で行います。
  • 水平ラインの価格を取得し、エントリーおよびクローズ条件の判定を行います。
  • 再エントリー抑止のためのラインレベルを更新します。
  1. エントリー条件のチェック (CheckEntryConditions)
  • 水平ラインの価格を基に、買いおよび売りエントリーの条件をチェックします。
  • 条件が満たされた場合、新しい注文を送信し、エラーの場合はエラーメッセージを出力します。
  1. クローズ条件のチェック (CheckCloseConditions)
  • 保有中のポジションに対して、買いおよび売りポジションのクローズ条件をチェックします。
  • 条件が満たされた場合、該当するポジションをクローズし、エラーの場合はエラーメッセージを出力します。

このEAは、指定された水平ラインを基に売買エントリーおよびポジションクローズを行います。EAをチャートに適用し、指定された水平ラインを引くことで動作を確認できます。

依頼内容(7回目)

以下、修正お願いできますか
・BuyStopLineが無い場合、buyStopLineLevel=0となってしまうかと思います。その場合、Askより必ず小さいので、Stopが0となってしまうので、buyStopLineLevel!=0の条件を追加してもらえますか
・エントリー条件から「ポジションを持っていない」を無くしてください

ChatGPT出力結果

以下の仕様に基づいて、EAのMQL4コードを修正し、提供します。

変更点

  1. パラメータに買いストップ用水平ラインの名称と売りストップ用水平ラインの名称を追加。
  2. 買い注文時に買いストップ用水平ラインの価格が注文価格より下にある場合、そのラインの価格を逆指値に設定。
  3. 売り注文時に売りストップ用水平ラインの価格が注文価格より上にある場合、そのラインの価格を逆指値に設定。
  4. 損切幅の設定よりも水平ラインの価格を優先する。
//+------------------------------------------------------------------+
//|                                         EA_LineBreakTrader       |
//|                                             Copyright 2024, SeSe |
//|                                     https://fx-trading-gym.info/ |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, SeSe"
#property link      "https://fx-trading-gym.info/"
#property version   "1.00"
#property strict

input double LotSize = 0.1; // 注文ロット数
input string BuyLineName = "BuyLine"; // 買い判定用水平ラインの名称
input string SellLineName = "SellLine"; // 売り判定用水平ラインの名称
input string BuyStopLineName = "BuyStopLine"; // 買いストップ用水平ラインの名称
input string SellStopLineName = "SellStopLine"; // 売りストップ用水平ラインの名称
input int CheckIntervalSeconds = 1; // エントリー、クローズ条件の判定間隔(秒単位)
input int Mode = 0; // 0: 両方、1: エントリーのみ、2: ポジションクローズのみ
input bool PreventReEntry = true; // 再エントリー抑止有無
input int Slippage = 3; // スリッページ
input double StopLossPips = 0; // 損切幅(Pips指定)

datetime lastCheckTime = 0;
double lastBuyLineLevel = 0;
double lastSellLineLevel = 0;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   datetime currentTime = TimeCurrent();
   
   if (currentTime - lastCheckTime >= CheckIntervalSeconds)
     {
      lastCheckTime = currentTime;

      // 水平ラインの価格を取得
      double buyLineLevel = ObjectGetDouble(0, BuyLineName, OBJPROP_PRICE);
      double sellLineLevel = ObjectGetDouble(0, SellLineName, OBJPROP_PRICE);
      double buyStopLineLevel = ObjectGetDouble(0, BuyStopLineName, OBJPROP_PRICE);
      double sellStopLineLevel = ObjectGetDouble(0, SellStopLineName, OBJPROP_PRICE);

      // エントリー条件の判定
      if (Mode == 0 || Mode == 1)
        CheckEntryConditions(buyLineLevel, sellLineLevel, buyStopLineLevel, sellStopLineLevel);

      // クローズ条件の判定
      if (Mode == 0 || Mode == 2)
        CheckCloseConditions(buyLineLevel, sellLineLevel);
     }
  }
//+------------------------------------------------------------------+
//| エントリー条件のチェック                                         |
//+------------------------------------------------------------------+
void CheckEntryConditions(double buyLineLevel, double sellLineLevel, double buyStopLineLevel, double sellStopLineLevel)
  {
   if (OrdersTotal() == 0)
     {
      double open = iOpen(NULL, 0, 1);
      double close = iClose(NULL, 0, 1);

      // 買いエントリー条件
      if (close > buyLineLevel && open < buyLineLevel && (!PreventReEntry || buyLineLevel != lastBuyLineLevel))
        {
         double sl = 0;
         if (buyStopLineLevel < Ask)
           {
            sl = buyStopLineLevel;
           }
         else if (StopLossPips > 0)
           {
            sl = NormalizeDouble(Ask - StopLossPips * Point, Digits);
           }

         int ticket = OrderSend(Symbol(), OP_BUY, LotSize, Ask, Slippage, sl, 0, "", 0, 0, clrGreen);
         if (ticket < 0)
           {
            Print("Buy OrderSend failed with error #", GetLastError());
           }
         else
           {
            lastBuyLineLevel = buyLineLevel; // 注文完了時に更新
           }
        }

      // 売りエントリー条件
      if (close < sellLineLevel && open > sellLineLevel && (!PreventReEntry || sellLineLevel != lastSellLineLevel))
        {
         double sl = 0;
         if (sellStopLineLevel > Bid)
           {
            sl = sellStopLineLevel;
           }
         else if (StopLossPips > 0)
           {
            sl = NormalizeDouble(Bid + StopLossPips * Point, Digits);
           }

         int ticket = OrderSend(Symbol(), OP_SELL, LotSize, Bid, Slippage, sl, 0, "", 0, 0, clrRed);
         if (ticket < 0)
           {
            Print("Sell OrderSend failed with error #", GetLastError());
           }
         else
           {
            lastSellLineLevel = sellLineLevel; // 注文完了時に更新
           }
        }
     }
  }
//+------------------------------------------------------------------+
//| クローズ条件のチェック                                           |
//+------------------------------------------------------------------+
void CheckCloseConditions(double buyLineLevel, double sellLineLevel)
  {
   for (int i = OrdersTotal() - 1; i >= 0; i--)
     {
      if (OrderSelect(i, SELECT_BY_POS))
        {
         double open = iOpen(NULL, 0, 1);
         double close = iClose(NULL, 0, 1);

         // 買いポジションクローズ条件
         if (OrderType() == OP_BUY && close < sellLineLevel && open > sellLineLevel)
           {
            if (!OrderClose(OrderTicket(), OrderLots(), Bid, Slippage, clrBlue))
              {
               Print("Buy OrderClose failed with error #", GetLastError());
              }
           }

         // 売りポジションクローズ条件
         if (OrderType() == OP_SELL && close > buyLineLevel && open < buyLineLevel)
           {
            if (!OrderClose(OrderTicket(), OrderLots(), Ask, Slippage, clrOrange))
              {
               Print("Sell OrderClose failed with error #", GetLastError());
              }
           }
        }
     }
  }
//+------------------------------------------------------------------+

説明

  1. パラメータ
  • LotSize: 注文ロット数
  • BuyLineName: 買い判定用水平ラインの名称
  • SellLineName: 売り判定用水平ラインの名称
  • BuyStopLineName: 買いストップ用水平ラインの名称
  • SellStopLineName: 売りストップ用水平ラインの名称
  • CheckIntervalSeconds: エントリーおよびクローズ条件の判定間隔(秒単位)
  • Mode: 0 = 両方、1 = エントリーのみ、2 = ポジションクローズのみ
  • PreventReEntry: 再エントリー抑止有無
  • Slippage: スリッページ
  • StopLossPips: 損切幅(Pips指定)
  1. 初期化 (OnInit)
  • 特に初期化は必要ありません。
  1. ティックイベント (OnTick)
  • ポジションチェックを設定された間隔で行います。
  • 水平ラインの価格を取得し、エントリーおよびクローズ条件の判定を行います。
  1. エントリー条件のチェック (CheckEntryConditions)
  • 水平ラインの価格を基に、買いおよび売りエントリーの条件をチェックします。
  • 買い注文時、買いストップ用水平ラインが注文価格より下に設定してある場合は、そのラインの価格を逆指値に設定します。
  • 売り注文時、売りストップ用水平ラインが注文価格より上に設定してある場合は、そのラインの価格を逆指値に設定します。
  • 損切幅(Pips指定)が0でない場合、注文時に逆指値を設定しますが、水平ラインの価格が優先されます。
  • 条件が満たされた場合、新しい注文を送信し、エラーの場合はエラーメッセージを出力します。
  • 注文が成功した場合、再エントリー抑止のためのラインレベルを更新します。
  1. クローズ条件のチェック (CheckCloseConditions)
  • 保有中のポジションに対して、買いおよび売りポジションのクローズ条件をチェックします。
  • 条件が満たされた場合、該当するポジションをクローズし、エラーの場合は

依頼内容(3~6回目)

以下の修正をお願いします
・初期化 (OnInit)の 水平ラインの初期価格を取得 を削除
 EA設定前に水平ラインが引いてあると、初回エントリーもしなくなってしまうため
・再エントリー抑止のためのラインレベルを更新は、注文完了時、買い、売りそれぞれのみを行う
 買いトレードを行った後、売りトレードは行えるようにする(その逆も)

Slippageが抜けているので追加お願いします

以下の仕様追加をお願いします。

#パラメータ
・損切幅(Pips指定。初期値は0。注文時、注文値から逆指値を設定する位置)

#仕様
・注文時に、注文値を基準に損切幅で指定されたマイナスで損切するよう逆指値を設定する
 0の場合は未設定。

仕様追加をお願いします。

#パラメータ
・買いストップ用水平ラインの名称
・売りストップ用水平ラインの名称

#仕様
・買い注文時、買いストップ用水平ラインが注文価格より下に設定してある場合は、
 そのラインの価格を逆指値に設定する。
・売り注文時、売りストップ用水平ラインが注文価格より上に設定してある場合は、
 そのラインの価格を逆指値に設定する。
・損切幅の設定より優先する。

ChatGPT出力結果

以下に、指定された修正を加えたEAのMQL4コードを提供します。

修正点

  1. BuyStopLineLevel0 の場合を考慮し、buyStopLineLevel != 0 の条件を追加。
  2. エントリー条件から「ポジションを持っていない」条件を削除。
//+------------------------------------------------------------------+
//|                                         EA_LineBreakTrader       |
//|                                             Copyright 2024, SeSe |
//|                                     https://fx-trading-gym.info/ |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, SeSe"
#property link      "https://fx-trading-gym.info/"
#property version   "1.00"
#property strict

input double LotSize = 0.1; // 注文ロット数
input string BuyLineName = "BuyLine"; // 買い判定用水平ラインの名称
input string SellLineName = "SellLine"; // 売り判定用水平ラインの名称
input string BuyStopLineName = "BuyStopLine"; // 買いストップ用水平ラインの名称
input string SellStopLineName = "SellStopLine"; // 売りストップ用水平ラインの名称
input int CheckIntervalSeconds = 1; // エントリー、クローズ条件の判定間隔(秒単位)
input int Mode = 0; // 0: 両方、1: エントリーのみ、2: ポジションクローズのみ
input bool PreventReEntry = true; // 再エントリー抑止有無
input int Slippage = 3; // スリッページ
input double StopLossPips = 0; // 損切幅(Pips指定)

datetime lastCheckTime = 0;
double lastBuyLineLevel = 0;
double lastSellLineLevel = 0;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   datetime currentTime = TimeCurrent();

   if (currentTime - lastCheckTime >= CheckIntervalSeconds)
     {
      lastCheckTime = currentTime;

      // 水平ラインの価格を取得
      double buyLineLevel = ObjectGetDouble(0, BuyLineName, OBJPROP_PRICE);
      double sellLineLevel = ObjectGetDouble(0, SellLineName, OBJPROP_PRICE);
      double buyStopLineLevel = ObjectGetDouble(0, BuyStopLineName, OBJPROP_PRICE);
      double sellStopLineLevel = ObjectGetDouble(0, SellStopLineName, OBJPROP_PRICE);

      // エントリー条件の判定
      if (Mode == 0 || Mode == 1)
        CheckEntryConditions(buyLineLevel, sellLineLevel, buyStopLineLevel, sellStopLineLevel);

      // クローズ条件の判定
      if (Mode == 0 || Mode == 2)
        CheckCloseConditions(buyLineLevel, sellLineLevel);
     }
  }
//+------------------------------------------------------------------+
//| エントリー条件のチェック                                         |
//+------------------------------------------------------------------+
void CheckEntryConditions(double buyLineLevel, double sellLineLevel, double buyStopLineLevel, double sellStopLineLevel)
  {
   double open = iOpen(NULL, 0, 1);
   double close = iClose(NULL, 0, 1);

   // 買いエントリー条件
   if (close > buyLineLevel && open < buyLineLevel && (!PreventReEntry || buyLineLevel != lastBuyLineLevel))
     {
      double sl = 0;
      if (buyStopLineLevel != 0 && buyStopLineLevel < Ask)
        {
         sl = buyStopLineLevel;
        }
      else if (StopLossPips > 0)
        {
         sl = NormalizeDouble(Ask - StopLossPips * Point, Digits);
        }

      int ticket = OrderSend(Symbol(), OP_BUY, LotSize, Ask, Slippage, sl, 0, "", 0, 0, clrGreen);
      if (ticket < 0)
        {
         Print("Buy OrderSend failed with error #", GetLastError());
        }
      else
        {
         lastBuyLineLevel = buyLineLevel; // 注文完了時に更新
        }
     }

   // 売りエントリー条件
   if (close < sellLineLevel && open > sellLineLevel && (!PreventReEntry || sellLineLevel != lastSellLineLevel))
     {
      double sl = 0;
      if (sellStopLineLevel != 0 && sellStopLineLevel > Bid)
        {
         sl = sellStopLineLevel;
        }
      else if (StopLossPips > 0)
        {
         sl = NormalizeDouble(Bid + StopLossPips * Point, Digits);
        }

      int ticket = OrderSend(Symbol(), OP_SELL, LotSize, Bid, Slippage, sl, 0, "", 0, 0, clrRed);
      if (ticket < 0)
        {
         Print("Sell OrderSend failed with error #", GetLastError());
        }
      else
        {
         lastSellLineLevel = sellLineLevel; // 注文完了時に更新
        }
     }
  }
//+------------------------------------------------------------------+
//| クローズ条件のチェック                                           |
//+------------------------------------------------------------------+
void CheckCloseConditions(double buyLineLevel, double sellLineLevel)
  {
   for (int i = OrdersTotal() - 1; i >= 0; i--)
     {
      if (OrderSelect(i, SELECT_BY_POS))
        {
         double open = iOpen(NULL, 0, 1);
         double close = iClose(NULL, 0, 1);

         // 買いポジションクローズ条件
         if (OrderType() == OP_BUY && close < sellLineLevel && open > sellLineLevel)
           {
            if (!OrderClose(OrderTicket(), OrderLots(), Bid, Slippage, clrBlue))
              {
               Print("Buy OrderClose failed with error #", GetLastError());
              }
           }

         // 売りポジションクローズ条件
         if (OrderType() == OP_SELL && close > buyLineLevel && open < buyLineLevel)
           {
            if (!OrderClose(OrderTicket(), OrderLots(), Ask, Slippage, clrOrange))
              {
               Print("Sell OrderClose failed with error #", GetLastError());
              }
           }
        }
     }
  }
//+------------------------------------------------------------------+

説明

  1. ヘッダ部分
  • Copyright 2024, SeSe
  • https://fx-trading-gym.info/
  • version "1.00"
  • strict
  1. パラメータ
  • LotSize: 注文ロット数
  • BuyLineName: 買い判定用水平ラインの名称
  • SellLineName: 売り判定用水平ラインの名称
  • BuyStopLineName: 買いストップ用水平ラインの名称
  • SellStopLineName: 売りストップ用水平ラインの名称
  • CheckIntervalSeconds: エントリーおよびクローズ条件の判定間隔(秒単位)
  • Mode: 0 = 両方、1 = エントリーのみ、2 = ポジションクローズのみ
  • PreventReEntry: 再エントリー抑止有無
  • Slippage: スリッページ
  • StopLossPips: 損切幅(Pips指定)
  1. 初期化 (OnInit)
  • 特に初期化は必要ありません。
  1. ティックイベント (OnTick)
  • ポジションチェックを設定された間隔で行います。
  • 水平ラインの価格を取得し、エントリーおよびクローズ条件の判定を行います。
  1. エントリー条件のチェック (CheckEntryConditions)
  • 水平ラインの価格を基に、買いおよび売りエントリーの条件をチェックします。
  • 買い注文時、買いストップ用水平ラインが注文価格より下に設定してある場合は、そのラインの価格を逆指値に設定します。
  • 売り注文時、売りストップ用水平ラインが注文価格より上に設定してある場合は、そのラインの価格を逆指値に設定します。
  • 損切幅(Pips指定)が0でない場合、注文時に逆指値を設定しますが、水平ラインの価格が優先されます。
  • 条件が満たされた場合、新しい注文を送信し、エラーの場合はエラーメッセージを出力します。
  • 注文が成功した場合、再エントリー抑止のためのラインレベルを更新します。
  1. クローズ条件のチェック (CheckCloseConditions)
  • 保有中のポジションに対して、買いおよび売りポジションのクローズ条件をチェックします。
  • 条件が満たされた場合、

ツール(EA)

作成したEAを上げておきます。
基本的な動作確認はしておりますが、不具合を原因とする場合を含め、利用者の損失を補填することは致しかねますのでご了承ください。
ご自身の責任の範囲で(ご自身でも動作確認するなど)ご利用ください。

水平ライン越えで、エントリー、ポジションクローズを行うツール(EA) (37 ダウンロード )

ご協力のお願い

もし、こちらのインジケータ、ツールを気に入ってもらえて、気が向いたら(何か利用する機会あれば)、ドネーション代わりに以下のいずれか何でもよいので、ご対応いただけたら幸いです。活動の励みになります。

何らかの商品購入時、以下のリンク経由でアクセスし購入する

amazonでFX関連書籍購入など

国内FX口座の開設

詳しくはこちらの記事をご参照ください。

  • その他FX口座の開設

MT4対応口座等もピックアップしています。こちらの記事からお願いします。

海外FX口座の開設

  • その他、口座(キャッシュバックあり)の開設

海外FXキャッシュバック口座開設ならTariTali(タリタリ)

詳しくはこちらの記事をご参照下さい。

トレードシステム(EA)の購入
  • 私が作成したEAのご購入

こちらの記事「FXトレーダー必見!MT4向け利益追求型自動売買EAの紹介」で、私が作成したEAの紹介をしています。利用いただけたら嬉しいです。
特に、おすすめは(調子が良いのは)こちら「ポンドュール(HL band M15 for GJ)」「BBHL band H1 for AJ」辺りです。

  • 他のEAのご購入

以下より人気EA、売れ筋EAを購入する。

関連記事

スポンサーリンク
海外FXキャッシュバック口座開設ならTariTali(タリタリ)

コメント

タイトルとURLをコピーしました