見出し画像

ChatGPTにドル円の自動トレードのプログラムを作らせてみた その3:利益確定ロジックの追加

今回の記事では、トレンドフォロー戦略の自動トレードプログラムに利益確定ロジックを追加し、黒字化を目指します。

1. 今回の目的

今回の記事では、MQL4を使用して自動トレードを行う際に、利益確定ロジックの追加とRSIを使用したエントリー条件の追加について解説します。

2. 利益確定ロジックの追加

利益確定は、トレードで得た利益を確実に確保するために重要なポイントです。基本的な考え方としては、トレードでの目標利益に達した場合に、利益確定することが推奨されます。本項では、利益確定ロジックの実装方法について解説します。

a. 利益確定の基本的な考え方

利益確定は、トレードで得た利益を確実に確保するために重要なポイントです。利益確定の基本的な考え方は、トレードでの目標利益に達した場合に、利益確定することが推奨されます。

トレンドフォロー戦略を採用する場合、トレンドが継続する限りポジションを保有することが目的となります。そのため、トレンドが反転した場合には、ポジションを手放すことが求められます。このとき、利益確定を行うことで、トレードで得た利益を確実に確保することができます。

利益確定のタイミングについては、トレードの目標利益やリスクリワード比によって異なります。トレードの目標利益が10ピップスの場合は、利益が10ピップスに達した時点で利益確定することが一般的です。また、リスクリワード比が2:1の場合は、リスクと同じくらいの利益が出た場合に利益確定することが推奨されます。

なお、利益確定を行う際には、トレイリングストップと併用することで、トレンドが継続する限り利益確定を行いつつ、損失を最小限に抑えることができます。トレンドフォロー戦略においては、利益確定とトレイリングストップの両方をうまく活用することが重要です。

b. 利益確定ロジックの実装方法

Q:トレイリングストップで利益確定するMQL4のコードを教えてください。

A:以下は、トレイリングストップで利益確定するMQL4コードの例です。トレイリングストップを使用するには、このコードをトレードロジックに統合する必要があります。

double trailingStop = 50; // トレイリングストップの幅
double profitLock = 20; // 利益確定の幅

void OnTick()
{
    double stopLoss = 0;
    double takeProfit = 0;
    double currentPrice = MarketInfo(Symbol(), MODE_BID);
    double openPrice = OrderOpenPrice();

    if (OrderType() == OP_BUY)
    {
        stopLoss = openPrice + trailingStop * Point;
        takeProfit = openPrice + profitLock * Point;
        if (currentPrice - stopLoss > trailingStop * Point)
        {
            stopLoss = currentPrice - trailingStop * Point;
            OrderModify(OrderTicket(), OrderOpenPrice(), stopLoss, takeProfit, 0);
        }
    }
    else if (OrderType() == OP_SELL)
    {
        stopLoss = openPrice - trailingStop * Point;
        takeProfit = openPrice - profitLock * Point;
        if (stopLoss - currentPrice > trailingStop * Point)
        {
            stopLoss = currentPrice + trailingStop * Point;
            OrderModify(OrderTicket(), OrderOpenPrice(), stopLoss, takeProfit, 0);
        }
    }
}

このコードは、OnTick()関数を使用して、現在の価格を取得し、現在の注文にトレイリングストップを適用し、必要に応じてトレイリングストップを更新します。トレイリングストップは、注文が開かれたときの価格から指定された幅を越えた場合に更新されます。

このコードを使用する前に、取引ロジックを追加して、注文が開かれる条件を定義する必要があります。また、ストップロスや利益確定の幅などのパラメータを調整することができます。

c. トレイリングストップのコードを追加

利益確定コードは関数化して、エラー処理を追加しました。

// 利益確定
void takeProfit() {
   if(OrdersTotal() < 1) {
      return;
   }
   double stopLoss = 0;
   double takeProfit = 0;
   double currentPrice = MarketInfo(Symbol(), MODE_BID);
   double openPrice = OrderOpenPrice();

   if(!OrderSelect(ticket, SELECT_BY_TICKET, MODE_TRADES)) {
      Print("Error placing select order: ", GetLastError());
   }

   if(OrderType() == OP_BUY) {
      stopLoss = openPrice + trailingStop * Point;
      takeProfit = openPrice + profitLock * Point;
      if(currentPrice - stopLoss > trailingStop * Point) {
         stopLoss = currentPrice - trailingStop * Point;
         if(!OrderModify(OrderTicket(), OrderOpenPrice(), stopLoss, takeProfit, 0)) {
            Print("Error placing modify order: ", GetLastError());
         }
         // 前回のエントリー時刻を更新
         last_entry_time = Time[0];
      }
   } else if(OrderType() == OP_SELL) {
      stopLoss = openPrice - trailingStop * Point;
      takeProfit = openPrice - profitLock * Point;
      if(stopLoss - currentPrice > trailingStop * Point) {
         stopLoss = currentPrice + trailingStop * Point;
         if(!OrderModify(OrderTicket(), OrderOpenPrice(), stopLoss, takeProfit, 0)) {
            Print("Error placing modify order: ", GetLastError());
         }
         // 前回のエントリー時刻を更新
         last_entry_time = Time[0];
      }
   }
}

利益確定コードを追加したバックログテストの結果がこちら。

stoploss 100, takeprofit 300でテスト
中盤までは順調だが最後の下落でマイナス収支

3. RSIを使ったエントリー条件の追加

RSIは相対的な強弱を測定するオシレーターであり、トレンド転換のシグナルとして使用されます。RSIが70を超えた場合にエントリーしない条件の追加方法をChatGPTに聞いてみます。

Q:RSIが70を超えたらエントリーをしないためのMQL4のコードを教えてください。

A:以下は、RSIが70を超えた場合にトレードをエントリーしないMQL4コードの例です。

double rsi = iRSI(Symbol(), PERIOD_CURRENT, 14, PRICE_CLOSE, 0); // 14期間のRSIを計算する
if (rsi < 70) {
    // RSIが70未満の場合、エントリーする
    // ここにエントリーのコードを書く
}
else {
    // RSIが70以上の場合、エントリーしない
}

このコードでは、iRSI関数を使用して現在のチャートシンボルのRSIを計算しています。14はRSIの期間を指定しており、PRICE_CLOSEは終値を使ってRSIを計算することを指定しています。0はRSIの計算に使用されるバーを指定しており、0を指定すると現在のバーが使用されます。

if文を使用して、計算されたRSIが70未満の場合にエントリーするコードを書き、70以上の場合にはエントリーしないコードを書いています。エントリーに関する具体的なコードは、トレード戦略に応じて異なります。

エントリー条件を判断するshould_enter()に先ほどの条件を追加します。

// エントリー条件
bool should_enter() {
   // 現在のローソク足の時間を取得
   datetime current_time = Time[0];

   // 前回のエントリー時刻と同じであればエントリーしない
   if(current_time == last_entry_time) {
      return false;
   }

   // 14期間のRSIを計算する
   double rsi = iRSI(Symbol(), PERIOD_CURRENT, 14, PRICE_CLOSE, 0);
   if (rsi > 70) {
      return false;
   }

・・・

4. バックログテストでついに利益を生み出す!?

バックログテストの結果やいかに?

StopLossが早いですがトレンドフォローになっているように見えます
上昇相場では着実に利益を上げられるようになっています
そしてついに黒字化!

5. 実際に完成したプログラム

注意事項

  1. このコードは、自動トレードを行うためのものであり、リスクを伴います。必ず自己責任でご利用ください。

  2. このコードはあくまでサンプルとして提供されるものであり、実際のトレードに使用する前に、必ずバックテストやデモトレードなどで十分に検証を行ってください。

  3. このコードはあくまでトレード戦略の一例であり、市場環境や個人のトレードスタイルによって異なる結果が出る可能性があります。

  4. このコードを使用する際には、プログラムの内容を十分に理解した上で、必要に応じて自身で修正や改良を行ってください。

利益確定ロジックとRSIを使用したエントリー条件を組み合わせた全体コードです。

// ドル円のトレンドフォロー戦略

// パラメーター
input int FastMAPeriod = 5;     // 短期移動平均線の期間
input int SlowMAPeriod = 25;     // 長期移動平均線の期間
input double Lots = 0.1;         // 取引量
input int MagicNumber = 123456;  // 注文識別番号

int sl = 100;  // ストップロス
int tp = 300; // テイクプロフィット

// 変数
int ticket;          // 注文番号
int maFast;          // 短期移動平均線
int maSlow;          // 長期移動平均線

double trailingStop = 50; // トレイリングストップの幅
double profitLock = 20; // 利益確定の幅

// グローバル変数
datetime last_entry_time;

// 初期化関数
void OnInit() {
// 移動平均線を初期化
   maFast = iMA(NULL, 0, FastMAPeriod, 0, MODE_SMA, PRICE_CLOSE,0);
   maSlow = iMA(NULL, 0, SlowMAPeriod, 0, MODE_SMA, PRICE_CLOSE,0);
}

// エントリー条件
bool should_enter() {
// 現在のローソク足の時間を取得
   datetime current_time = Time[0];

// 前回のエントリー時刻と同じであればエントリーしない
   if(current_time == last_entry_time) {
      return false;
   }

// 14期間のRSIを計算する
   double rsi = iRSI(Symbol(), PERIOD_CURRENT, 14, PRICE_CLOSE, 0);
   if (rsi > 70) {
      return false;
   }

// エントリー条件を判定
   maFast = iMA(NULL, 0, FastMAPeriod, 0, MODE_SMA, PRICE_CLOSE, 0);
   maSlow = iMA(NULL, 0, SlowMAPeriod, 0, MODE_SMA, PRICE_CLOSE, 0);

   return (maFast >= maSlow);
}

// 利益確定
void takeProfit() {
   if(OrdersTotal() < 1) {
      return;
   }
   double stopLoss = 0;
   double takeProfit = 0;
   double currentPrice = MarketInfo(Symbol(), MODE_BID);
   double openPrice = OrderOpenPrice();

   if(!OrderSelect(ticket, SELECT_BY_TICKET, MODE_TRADES)) {
      Print("Error placing select order: ", GetLastError());
      return;
   }

   if(OrderType() == OP_BUY) {
      stopLoss = openPrice + trailingStop * Point;
      takeProfit = openPrice + profitLock * Point;
      if(currentPrice - stopLoss > trailingStop * Point) {
         stopLoss = currentPrice - trailingStop * Point;
         if(!OrderModify(OrderTicket(), OrderOpenPrice(), stopLoss, takeProfit, 0)) {
            Print("Error placing modify order: ", GetLastError());
         }
         // 前回のエントリー時刻を更新
         last_entry_time = Time[0];
      }
   } else if(OrderType() == OP_SELL) {
      stopLoss = openPrice - trailingStop * Point;
      takeProfit = openPrice - profitLock * Point;
      if(stopLoss - currentPrice > trailingStop * Point) {
         stopLoss = currentPrice + trailingStop * Point;
         if(!OrderModify(OrderTicket(), OrderOpenPrice(), stopLoss, takeProfit, 0)) {
            Print("Error placing modify order: ", GetLastError());
         }
         // 前回のエントリー時刻を更新
         last_entry_time = Time[0];
      }
   }
}

// エントリー処理
void enter() {
// 注文が既に存在する場合は処理しない
   if(OrdersTotal() > 0) {
      return;
   }
// エントリーする
// 短期移動平均線が長期移動平均線より上にある場合は買い注文を作成
   if(maFast >= maSlow) {
      ticket = OrderSend(Symbol(), OP_BUY, Lots, Ask, 3, Bid-sl*Point, Bid+tp*Point, "Trend Follow Buy", MagicNumber, 0, Blue);
      if(ticket > 0) {
         Print("Buy order placed: ", ticket);
      } else {
         Print("Error placing buy order: ", GetLastError());
      }
   }
// 短期移動平均線が長期移動平均線より下にある場合は売り注文を作成
   else if(maFast < maSlow) {
      ticket = OrderSend(Symbol(), OP_SELL, Lots, Bid, 3, Ask+20*Point, Ask-20*Point, "Trend Follow Sell", MagicNumber, 0, Red);
      if(ticket > 0) {
         Print("Sell order placed: ", ticket);
      } else {
         Print("Error placing sell order: ", GetLastError());
      }
   }

// 前回のエントリー時刻を更新
   last_entry_time = Time[0];
}

// エントリーポイント
void OnTick() {

// エントリー条件を判定
   if(should_enter()) {
      // エントリーする
      enter();
      takeProfit();
   } 
}
//+------------------------------------------------------------------+

5. まとめ

利益確定ロジックとRSIを使用したエントリー条件の追加によって、ついに利益を出せるようになりました。ただし、あくまで強い上昇相場でしか利益にならず、横ばいや下落の場面ではマイナスになってしまいます。

もしこの記事に反響があれば、売りのエントリーや別のトレード戦略の実装にもチャレンジしたいと思います。


この記事が参加している募集

この記事が気に入ったらサポートをしてみませんか?