見出し画像

カギ足ロジックを使用したEAを開発してみた【無料EA配布中】

ChatGPT担当のナナミです。

前回の動画では、アベレージ・トゥルー・レンジ(ATR)を使用したEAの開発を行いました。

本日は、勝てると話題のカギ足ロジックを使用した手法の検証を行いたいと思います。


完成したEAはこのページの下の方にコードが書いてありますので、最後までお読みいただき、ダウンロードしていただければと思います。

GPTsのリンクはこちら(GPT Store)
https://chatgpt.com/g/g-VYNEupgws-masayan-ea-generator-for-mt4-ver1-01

■ブログURL
https://fx.reform-network.net/2024/08/29/新シリーズ「あなたの考えたfx手法をeaにする」/

■前回記事 アベレージ・トゥルー・レンジ(ATR)の手法を検証してみた
https://note.com/aimjey/n/n40770679d4bb

カギ足手法を簡単に説明しますと、以下のようなロジックになります。

カギ足ロジックは、カギ足チャートを使用します。
通常のチャートとは異なり、時間の経過は無視されます。

価格の変動のみをチャートに表示することで、純粋に値動きのみを把握することが出来ます。

カギ足チャートは時間を考慮しない。
つまり価格の変動のみ知ることができるチャートということですね。

エントリータイミングとしては、レンジブレイクやダブルトップ、ダブルボトムに似ていると思います。

それでは早速、ChatGPTでEAを作成してみましょう。

まず、Masayan EA Generator for MT4に、カギ足ロジックのEAを作成してとプロンプトを送信します。

ロジックが曖昧なせいか、毎回出力されるコードが異なります。

しかし、生成過程で奇妙な現象が発生しました。

順張りのロジックを作成した時に、このような一直線に負け続けるEAが出来上がりました。


そこで、売りと買いのエントリーを逆にしたところ、今度はプラスの成績を出すようになりました。


わたしのEA開発の経験上、ここまでトレード回数が多いEAは、ほぼ確実にスプレッド負けします。

このEAも、スプレッドが1.0pipsだと勝てないと思います。

また、成績を比較すると「ドル円」よりも「ユーロドル」の方が好成績でした。



このバックテスト結果は、TDSによる変動スプレッドでのバックテスト結果です。

ロジック的には、ローソク足が確定した、最初の2秒だけエントリーするように細工をしてあります。

以下が完成したEAのソースコードです。EAの名前はGrid Rashです。


#property copyright "Copyright 2024, Masayan."
#property version   "1.01"
#property strict
#property description "https://fx.reform-network.net"

extern int Magic = 20240615;  // Magic number
extern double Lots = 0.1;     // ロットサイズ
extern double StopLossRequest = 4.0;   // ストップロス幅
extern double TakeProfitRequest = 5.0; // テイクプロフィット幅
extern int MaxSpread = 50;     // 最大スプレッド
extern int MaxError = 100;     // 最大エラーカウント
extern double GridSize = 0.05;  // カギ足のサイズ(最小値0.01=1pips 推奨値0.05=5pips)
extern string CommentPositions = "Grid Rash";

//ここから改変可能
double lastBrickHigh = 0;  // 前回のカギ足高値
double lastBrickLow = 0;   // 前回のカギ足安値
//ここまで改変可能

string tmpstr;
string error_msg;
string spread_msg;
string position_msg;
bool LongSign = false;
bool ShortSign = false;
double Pips = 0.01;
int e = 0;
int Adjusted_Slippage = 0;

void OnTick()
{
    if (Bars < 10) return;

    double currentPrice = iClose(NULL, 0, 0);
    double Info_Spread = MarketInfo(Symbol(), MODE_SPREAD);
string value = Symbol();
string target = "JPY";
int pos = StringFind(value, target);
double Symbol_RATE = Close[1];
if(pos > 0){
Pips = 1.00;// ドルストレートは0.010(100pips)、クロス円は1.0(100pips)で判定
}else if(Symbol_RATE > 10 && Symbol_RATE <= 100){
Pips = 0.1;
}else if(Symbol_RATE > 100 && Symbol_RATE <= 1000){
Pips = 1.0;
}else if(Symbol_RATE > 1000 && Symbol_RATE <= 10000){
Pips = 10.0;
}else if(Symbol_RATE > 10000 && Symbol_RATE <= 100000){
Pips = 100.0;
}else if(Symbol_RATE > 100000){
Pips = 1000.0;
}
    // スプレッドのチェック
    if (MaxSpread < Info_Spread) {
        LongSign = false;
        ShortSign = false;
        spread_msg = "Max spread Orber\n";
    } else {
        spread_msg = "";
    }

    // カギ足ロジックによるシグナル生成
    GenerateRenkoSignals(currentPrice);

    if (Hour() == 4 && Minute() == 0 && Seconds() < 6) e = 0;
    if (Hour() == 11 && Minute() == 0 && Seconds() < 6) e = 0;
    if (Hour() == 18 && Minute() == 0 && Seconds() < 6) e = 0;

    if (e > MaxError) {
        LongSign = false;
        ShortSign = false;
        error_msg = "Continuous order count limit\n";
    } else {
        error_msg = "";
    }

    if (LongSign) position_msg = "LongSign = true\n";
    else if (ShortSign) position_msg = "ShortSign = true\n";
    else position_msg = "No Sign\n";

    // 売買指示
    if (LongSign) {
        if (CalculateCurrentOrders() == 0) {
            CheckForOpenLong();
            e++;
        } else {
            CloseShortPosition();
        }
    }

    if (ShortSign) {
        if (CalculateCurrentOrders() == 0) {
            CheckForOpenShort();
            e++;
        } else {
            CloseLongPosition();
        }
    }

    tmpstr = StringConcatenate(error_msg, spread_msg, position_msg);
    Comment(tmpstr);
}

// カギ足ロジックを生成する関数
void GenerateRenkoSignals(double price)
{

    // 初回は基準の高値・安値を設定
    if (lastBrickHigh == 0 && lastBrickLow == 0) {
        lastBrickHigh = price;
        lastBrickLow = price;
        return;
    }

    // カギ足の生成条件チェック
      if (price >= lastBrickHigh + (GridSize * Pips) && Seconds() < 3 ) { 
        ShortSign = true;
        LongSign = false;
        lastBrickHigh = price;
        lastBrickLow = price - (GridSize * Pips);
    } else if (price <= lastBrickLow - (GridSize * Pips) && Seconds() < 3 ) {
        LongSign = true;
        ShortSign = false;
        lastBrickLow = price;
        lastBrickHigh = price + (GridSize * Pips);
    } else {
        LongSign = false;
        ShortSign = false;
    }
}



/*ここに決済ロジックを挿入*/


// 保有中のポジションを計算
int CalculateCurrentOrders(void)
{
    int buys = 0;
    int sells = 0;
    for (int icount = 0; icount < OrdersTotal(); icount++) {
        if (!OrderSelect(icount, SELECT_BY_POS, MODE_TRADES)) break;
        if (OrderSymbol() == Symbol() && OrderMagicNumber() == Magic) {
            if (OrderType() == OP_BUY) buys++;
            if (OrderType() == OP_SELL) sells++;
        }
    }
    return (buys > 0) ? buys : -sells;
}

//+------------------------------------------------------------------+
//| ロングオーダー処理                                               |
//+------------------------------------------------------------------+
void CheckForOpenLong() {
    int    res;      // オーダー送信戻り値用
    double entrylot; // オーダー用ロット
    entrylot = NormalizeDouble(Lots,2); // 入力パラメータのロット数を、小数点第二位で正規化
//■□■□■□■□■ ロングエントリー ■□■□■□■□■
        res = OrderSend(
                        Symbol(),       // 現在の通貨ペア
                        OP_BUY,         // ロングエントリー(成行注文)
                        entrylot,        // ロット設定
                        Ask,            // 現在の買値で発注
                        Adjusted_Slippage,// スリップページ
                        Ask - (Pips * StopLossRequest),              // ストップロス設定
                        Ask + (Pips * TakeProfitRequest),              // リミット設定
                        CommentPositions,       // ロングコメント
                        Magic,        // マジックナンバー
                        0,              // 有効期限:無し
                        clrRed);          // チャート上の注文矢印の色:赤
        return; // 関数処理終了
}

//+------------------------------------------------------------------+
//| ショートオーダー処理                                             |
//+------------------------------------------------------------------+
void CheckForOpenShort() {
    int    res;      // オーダー送信戻り値用
    double entrylot; // オーダー用ロット
    entrylot = NormalizeDouble(Lots,2); // 入力パラメータのロット数を、小数点第二位で正規化
//■□■□■□■□■ ショートエントリー ■□■□■□■□■
        res = OrderSend(
                        Symbol(),        // 現在の通貨ペア
                        OP_SELL,         // ショートエントリー(成行注文)
                        entrylot,        // ロット設定
                        Bid,             // 現在の売値で発注
                        Adjusted_Slippage,// スリップページ
                        Bid + (Pips * StopLossRequest),               // ストップロス設定
                        Bid - (Pips * TakeProfitRequest),               // リミット設定
                        CommentPositions,      // ショートコメント
                        Magic,         // マジックナンバー
                        0,               // 有効期限:無し
                        clrBlue);            // チャート上の注文矢印の色:青
        return; // 関数処理終了
}

// ショートポジションをクローズ
void CloseShortPosition()
{
    for (int icount = 0; icount < OrdersTotal(); icount++) {
        if (!OrderSelect(icount, SELECT_BY_POS, MODE_TRADES)) break;
        if (OrderMagicNumber() != Magic || OrderSymbol() != Symbol()) continue;
        if (OrderType() == OP_SELL) {
            if (!OrderClose(OrderTicket(), OrderLots(), Ask, Adjusted_Slippage, clrBlue)) 
                Print("エラーコード=", GetLastError());
            break;
        }
    }
}

// ロングポジションをクローズ
void CloseLongPosition()
{
    for (int icount = 0; icount < OrdersTotal(); icount++) {
        if (!OrderSelect(icount, SELECT_BY_POS, MODE_TRADES)) break;
        if (OrderMagicNumber() != Magic || OrderSymbol() != Symbol()) continue;
        if (OrderType() == OP_BUY) {
            if (!OrderClose(OrderTicket(), OrderLots(), Bid, Adjusted_Slippage, clrRed)) 
                Print("エラーコード=", GetLastError());
            break;
        }
    }
}

このEAは、スキャルのEAとして今後もカスタマイズを加えていきたいと思います。

EA開発に自信のある方は、ロジックのところを変更するなどしてカスタマイズしてみてください。

好成績のEAが完成した際には、コメント頂けると幸いです。

他にも、こんな手法EAにしてほしいみたいなリクエストがあれば、コメントお願いします。

【免責事項】
・本GPTsについて、正当性を保証するものではありません。
・本GPTsを利用して損失を被った場合でも一切の責任を負いません。
・投資の決定は、自己判断 自己責任でお願いします。

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