AIを使って自作EAを作ろうシリーズ第3回です。
前回一般的なロジックを使った簡単なEAコードの作成はできました。
今回はもと複雑なEAを作成して実際に動くものができるのか検証していきます。
移動平均線+RSI
copilotへの命令文は
・移動平均線を使ってロング、ショートエントリー。
・フィルターとしてRSIを使う複合ロジックを検討。
・SLとTPはトレーリングで。
この後いくつかの会話がありましたが、最終的なCopilotの戦略仕様が以下
EAの戦略仕様(概要)
項目 | 内容 |
通貨ペア | 任意(制限なし) |
時間足 | 推奨は H1 or H4(4時間足) |
トレンド判定 | EMA50とEMA200のクロスでBUY/SELL判断 |
RSI条件 | RSI(14)が BUY時:30〜50 / SELL時:50〜70 にあるときだけ許可 |
SL/TP | 初期SL = ATR×1.5 / TPなし(トレーリングで利伸ばす) |
トレーリングストップ | 含み益に応じてSLを ATR×1.0 の距離で追従(損小利大) |
ポジション管理 | 同一シンボルで最大1ポジ(BUY or SELL)保持、方向転換時は全決済して反転エントリー可能 |
コード作成
吐き出されたEAが以下。
input double Lots = 0.1;
input int EMA_Short = 50;
input int EMA_Long = 200;
input int RSI_Period = 14;
input int ATR_Period = 14;
input double SL_ATR = 1.5;
input double Trail_ATR = 1.0;
int Magic = 10000;
int OnInit() { return(INIT_SUCCEEDED); }
void OnDeinit(const int reason) {}
void OnTick()
{
if(OrdersTotal() >= 1) ApplyTrailing(); // トレーリングSL更新
double emaFast = iMA(Symbol(), 0, EMA_Short, 0, MODE_EMA, PRICE_CLOSE, 0);
double emaSlow = iMA(Symbol(), 0, EMA_Long, 0, MODE_EMA, PRICE_CLOSE, 0);
double rsi = iRSI(Symbol(), 0, RSI_Period, PRICE_CLOSE, 0);
double atr = iATR(Symbol(), 0, ATR_Period, 0);
bool buySignal = emaFast > emaSlow && rsi > 30 && rsi < 50;
bool sellSignal = emaFast < emaSlow && rsi < 70 && rsi > 50;
// エントリー(保有ポジションがないとき)
if(CountMyPositions() == 0)
{
if(buySignal)
{
double sl = NormalizeDouble(Bid - SL_ATR * atr, Digits);
OrderSend(Symbol(), OP_BUY, Lots, Ask, 3, sl, 0, "EMA+RSI Buy", Magic, 0, clrBlue);
}
else if(sellSignal)
{
double sl = NormalizeDouble(Ask + SL_ATR * atr, Digits);
OrderSend(Symbol(), OP_SELL, Lots, Bid, 3, sl, 0, "EMA+RSI Sell", Magic, 0, clrRed);
}
}
}
// トレーリングストップロジック
void ApplyTrailing()
{
double atr = iATR(Symbol(), 0, ATR_Period, 0);
for(int i = 0; i < OrdersTotal(); i++)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES) &&
OrderSymbol() == Symbol() &&
OrderMagicNumber() == Magic)
{
double trail = Trail_ATR * atr;
if(OrderType() == OP_BUY)
{
double newSL = NormalizeDouble(Bid - trail, Digits);
if(OrderStopLoss() < newSL)
OrderModify(OrderTicket(), OrderOpenPrice(), newSL, 0, 0, clrGreen);
}
else if(OrderType() == OP_SELL)
{
double newSL = NormalizeDouble(Ask + trail, Digits);
if(OrderStopLoss() > newSL || OrderStopLoss() == 0)
OrderModify(OrderTicket(), OrderOpenPrice(), newSL, 0, 0, clrGreen);
}
}
}
}
// マジックナンバーでフィルタ
int CountMyPositions()
{
int count = 0;
for(int i = 0; i < OrdersTotal(); i++)
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES) &&
OrderSymbol() == Symbol() &&
OrderMagicNumber() == Magic)
count++;
return count;
}
バックテスト
今回も普通に動きました。

損小利大EA
次に命令文をかなりラフにしてみました。
・損小利大となるようなEA。
・4時間足、EURJPY、使いたいインジケーターは特にない
・エントリー回数を絞り勝率を重視してほしい
その後いくつかの会話を経て、最終的なCopilotの戦略仕様が以下
EAの戦略仕様(概要)
項目 | 内容 |
通貨ペア | EURJPY 専用 |
時間足 | H4(4時間足) |
エントリー条件 | ローソク足パターン+平均足によるトレンド判定+マルチタイム確認 |
SL/TP | 損切30pips、利確90pips(リスクリワード1:3) |
フィルター | 日足トレンド一致、東京時間外取引禁止、エントリー間隔制限(6本以上)など |
ポジション制御 | 同時保有1つまで、Magic Number管理 |
コード作成
//+------------------------------------------------------------------+
//| EURJPY_H4 損小利大 勝率重視EA(完全版) |
//+------------------------------------------------------------------+
#property strict
extern double Lots = 0.1;
extern int StopLoss = 30;
extern int TakeProfit = 90;
extern int Slippage = 3;
extern int MagicNumber = 987654;
datetime lastTradeTime = 0;
// 平均足チェック
bool IsHeikenAshiTrend(bool isBuy) {
double haOpen1 = iCustom(NULL, 0, "Heiken Ashi", 1, 1);
double haClose1 = iCustom(NULL, 0, "Heiken Ashi", 0, 1);
double haOpen2 = iCustom(NULL, 0, "Heiken Ashi", 1, 2);
double haClose2 = iCustom(NULL, 0, "Heiken Ashi", 0, 2);
if (isBuy)
return haClose1 > haOpen1 && haClose2 > haOpen2;
else
return haClose1 < haOpen1 && haClose2 < haOpen2;
}
// ローソク足の勢いチェック
bool IsStrongCandle(bool isBuy) {
double body = MathAbs(Close[1] - Open[1]);
double range = High[1] - Low[1];
if (range == 0) return false;
double strength = body / range;
if (isBuy)
return (Close[1] > Open[1]) && (strength > 0.7);
else
return (Open[1] > Close[1]) && (strength > 0.7);
}
// 日足トレンド確認(SMA50)
bool IsDailyTrendMatch(bool isBuy) {
double maToday = iMA(NULL, PERIOD_D1, 50, 0, MODE_SMA, PRICE_CLOSE, 0);
double maYesterday = iMA(NULL, PERIOD_D1, 50, 0, MODE_SMA, PRICE_CLOSE, 1);
if (isBuy)
return maToday > maYesterday;
else
return maToday < maYesterday;
}
// 時間帯フィルター(東京時間=日本時間9:00〜15:00)
bool IsTokyoSession() {
datetime localTime = TimeLocal();
int hour = TimeHour(localTime);
return (hour >= 9 && hour <= 15);
}
// エントリーレート制限(6本以上間隔)
bool IsEnoughTimePassed() {
return (TimeCurrent() - lastTradeTime) > (6 * PeriodSeconds());
}
void OnTick() {
if (Period() != PERIOD_H4 || Symbol() != "EURJPY") return;
if (!IsEnoughTimePassed()) return;
if (OrdersTotal() > 0) return;
if (IsTokyoSession()) return;
// 買い条件チェック
if (IsStrongCandle(true) && IsHeikenAshiTrend(true) && IsDailyTrendMatch(true)) {
double sl = Bid - StopLoss * Point;
double tp = Bid + TakeProfit * Point;
if (OrderSend(Symbol(), OP_BUY, Lots, Ask, Slippage, sl, tp, "Buy EURJPY", MagicNumber, 0, clrBlue) > 0) {
lastTradeTime = TimeCurrent();
}
}
// 売り条件チェック
if (IsStrongCandle(false) && IsHeikenAshiTrend(false) && IsDailyTrendMatch(false)) {
double sl = Ask + StopLoss * Point;
double tp = Ask - TakeProfit * Point;
if (OrderSend(Symbol(), OP_SELL, Lots, Bid, Slippage, sl, tp, "Sell EURJPY", MagicNumber, 0, clrRed) > 0) {
lastTradeTime = TimeCurrent();
}
}
}
バックテスト
残念ながら動きませんでした。
Copilotで修正を試みるもうまくいかず、その後私の知識でも修正することができず結局動かすことができませんでした。
まとめ
Copilotでは複雑なロジックでもEAを作ってくれるが、命令文がラフになりすぎるとうまくいかない。
動かすだけならCopilotは十分コードを作れる実力があったので、今後はプロフィットファクターの改善という目線でCopilotの実力を見ていきたいと思います。