見出し画像

ChatGPTにドル円の自動トレードのプログラムを作らせてみた その2:エントリー条件の追加

前回作成した自動トレードプログラムにエントリー条件を追加しました。今回はその過程を追っていきます。

Q:ここまでのソースコードを最適化してください

A:以下は、最適化されたドル円のトレンドフォロー戦略のコードです。このコードでは、取引に使用されるパラメーターを変数に格納し、OnInit()関数内で初期化されます。また、OnTick()関数では、ロジックが実行されます。取引ロジックは、長期および短期の移動平均線を使用し、移動平均線がクロスしたときに新しい注文を作成します。

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

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

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

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

// エントリーポイント
void OnTick() {
    // 注文が既に存在する場合は処理しない
    if (OrdersTotal() > 0) {
        return;
    }
    
    // 短期移動平均線が長期移動平均線より上にある場合は買い注文を作成
    if (maFast > maSlow) {
        ticket = OrderSend(Symbol(), OP_BUY, Lots, Ask, 3, Bid-20*Point, Bid+20*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());
        }
    }
}

Q:14行目で次のエラーが発生します。 'iMA' - wrong parameters count

A:14行目でiMA()関数が誤ったパラメータ数で呼び出されたことが原因でエラーが発生しています。

正しいパラメータを使って関数を呼び出すように修正する必要があります。iMA()関数の正しい使い方は以下のとおりです。

double iMA(string symbol, int timeframe, int ma_period, int ma_shift, int ma_method, int applied_price, int shift)

各パラメータの説明は以下のとおりです。

symbol:データを取得する通貨ペア
timeframe:取得するデータの時間足
ma_period:移動平均線の期間
ma_shift:移動平均線をずらす数
ma_method:移動平均線の計算方法
applied_price:移動平均線の計算に使用する価格
shift:移動平均線をずらす数
具体的には、以下のように修正することができます。

// 短期移動平均線の値を取得
double ema_fast = iMA(NULL, 0, 10, 0, MODE_EMA, PRICE_CLOSE, 0);

// 長期移動平均線の値を取得
double ema_slow = iMA(NULL, 0, 50, 0, MODE_EMA, PRICE_CLOSE, 0);

このように、正しいパラメータを使ってiMA()関数を呼び出すことで、エラーを解消することができます。

この辺りはプログラミングの知識ゼロだと厳しいか?
実際に修正したコードはこちら。

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

そして本題の指示を出してみます。

このコードでは短時間に大量のオーダーがエントリーされてしまいます。1つの時間足では2回以上エントリーしないようにしてください。

A:コードを改善して、同じローソク足で複数回のエントリーが行われないようにするには、現在のローソク足のエントリー回数を追跡する必要があります。

これを実現するために、最後のエントリー時刻をグローバル変数に保存して、次のエントリーのタイミングで前回のエントリーが行われたローソク足と比較することができます。

以下は、修正済みのコード例です。前回のエントリー時刻をlast_entry_timeというグローバル変数に保存し、次のエントリーのタイミングで現在のローソク足が前回のエントリー時刻と同じであれば、エントリーを行わないようにしています。

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

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

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

    // エントリー条件を判定
    double ema_fast = iMA(NULL, 0, 10, 0, MODE_EMA, PRICE_CLOSE, 0);
    double ema_slow = iMA(NULL, 0, 50, 0, MODE_EMA, PRICE_CLOSE, 0);

    return (ema_fast > ema_slow);
}

// エントリー処理
void enter() {
    // エントリーする
    OrderSend(...);

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

// メイン関数
void OnTick() {
    // エントリー条件を判定
    if (should_enter()) {
        // エントリーする
        enter();
    }
}

このように、前回のエントリー時刻を保存しておき、次のエントリーのタイミングで現在のローソク足が前回のエントリー時刻と同じであればエントリーを行わないようにすることで、同じローソク足で複数回のエントリーを回避することができます。

これで短時間に大量オーダーをエントリーすることがなくなりました。ただ、実際に修正するには、プログラミングの知識が必要な部分もあるため、初心者には少し難しいかもしれません。
また、この回答を引き出すために何回も回答を「Regenerate」していたため、コードの生成に手間取ってしまいました。

そんな中でも、ここまでのソースコードは問題なくコンパイルでき、少し手を加えることで期待通りの動作をすることができました。

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

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

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

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

// グローバル変数
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;
    }

    // エントリー条件を判定
    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 enter() {
    // エントリーする
    // 短期移動平均線が長期移動平均線より上にある場合は買い注文を作成
    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 (OrdersTotal() > 0) {
        return;
    }
    // エントリー条件を判定
    if (should_enter()) {
        // エントリーする
        enter();
    }
}
USD/JPY 4時間足で3か月のバックログでテスト
収支はマイナス

次回は、この自動トレードプログラムに利益確定ロジックを追加してみたいと思います。

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

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