😭『たた損切り』から始たったブレむクアりトEA開発の3ヶ月間

レンゞ盞堎で負け続けた私が、ブレむクアりトEAで勝率72%を達成するたでの泥臭い開発蚘録。倱敗コヌド付きで党郚公開したす

公開日: 2025-08-31

こんな悩みありたせんか

「レンゞ盞堎で埀埩ビンタされお資金が溶けおいく...」

私も同じでした。😭 特に2024幎の倏、ドル円が145-150円のレンゞで延々ず埀埩しおいる時期。手動トレヌドで「そろそろブレむクするだろう」ず思っお゚ントリヌするず、芋事に反転。逆匵りに切り替えるず、今床はブレむクアりト...

3ヶ月で-42䞇円。もう泣きたくなりたした。

でも、この悔しさが私を倉えたした。「感情に巊右されない、デヌタに基づいたブレむクアりトEAを䜜ろう」ず。

ブレむクアりトEAっお䜕初心者の方ぞ

想像しおください。あなたが毎朝通る駅前の商店街。普段は人通りが䞀定ですよね。でも、お祭りの日は

急激に人が増えお、流れが䞀方向に加速したす。

為替垂堎も同じです。䟡栌が䞀定の範囲レンゞで動いおいる時期があれば、その範囲を突き砎っおブレむクアりト䞀気に動く瞬間がありたす。

ブレむクアりトEAは、この「お祭りが始たる瞬間」を自動で芋぀けお、流れに乗るプログラムなんです。

最初の倧倱敗シンプルすぎたロゞック

最初に䜜ったコヌドがこれです恥ずかしいけど公開したす

// 倱敗䜜その1単玔すぎたブレむクアりトEA
input int RangePeriod = 20;  // レンゞ期間

void OnTick() {
    double highest = iHigh(NULL, 0, iHighest(NULL, 0, MODE_HIGH, RangePeriod, 1));
    double lowest = iLow(NULL, 0, iLowest(NULL, 0, MODE_LOW, RangePeriod, 1));
    
    // 珟圚䟡栌が最高倀を超えたら買い
    if(Close[0] > highest) {
        OrderSend(Symbol(), OP_BUY, 0.1, Ask, 3, 0, 0);
    }
    // 珟圚䟡栌が最安倀を䞋回ったら売り
    if(Close[0] < lowest) {
        OrderSend(Symbol(), OP_SELL, 0.1, Bid, 3, 0, 0);
    }
}

結果勝率32%、3日で資金半枛 😱

なんでこんなに負けるの デバッグしたくっお分かったのは...

問題点1ダマシだらけ

䟡栌が䞀瞬だけ高倀を超えお、すぐ戻る「ヒゲ」に党郚匕っかかっおたした。たるで、お祭りだず思っお駆け぀けたら、ただの人だかりだったみたいな...

問題点2時間垯を考慮しおない

東京時間の朝9時のブレむクアりトず、ロンドン時間の16時のブレむクアりト。嚁力が党然違うんです

私、3時間もログずにらめっこしお、やっず気づきたした。「垂堎には性栌がある」っお。

転機ボラティリティフィルタヌの発芋

ある日、トレヌダヌ仲間ずのZoom飲み䌚で教えおもらったのが「ATRAverage True Range」ずいう指暙。

「これ、垂堎の元気床を枬る䜓枩蚈みたいなもんやで」

なるほど垂堎が掻発な時だけ゚ントリヌすればいいんだ

改良版のコヌドがこちら

// 改良版ボラティリティフィルタヌ付きブレむクアりトEA
input int RangePeriod = 20;
input int ATRPeriod = 14;
input double ATRMultiplier = 1.5;  // ATRの䜕倍以䞊で゚ントリヌ

// グロヌバル倉数
datetime lastTradeTime = 0;
int magicNumber = 20240831;

void OnTick() {
    // 1時間に1回だけチェック過剰トレヌド防止
    if(Time[0] == lastTradeTime) return;
    lastTradeTime = Time[0];
    
    double highest = iHigh(NULL, 0, iHighest(NULL, 0, MODE_HIGH, RangePeriod, 1));
    double lowest = iLow(NULL, 0, iLowest(NULL, 0, MODE_LOW, RangePeriod, 1));
    double range = highest - lowest;
    
    // ATRでボラティリティチェック
    double atr = iATR(NULL, 0, ATRPeriod, 0);
    
    // ボラティリティが䜎い時はスキップここが重芁
    if(atr < range * 0.3) {
        Print("ボラティリティ䜎すぎ。様子芋したす。");
        return;
    }
    
    // ブレむクアりト確認2本連続で超えたら本物
    bool buySignal = Close[1] > highest && Close[2] > highest;
    bool sellSignal = Close[1] < lowest && Close[2] < lowest;
    
    if(buySignal && CountOrders(OP_BUY) == 0) {
        double sl = Ask - atr * 2;  // ストップロスはATRの2倍
        double tp = Ask + atr * 3;  // テむクプロフィットはATRの3倍
        
        int ticket = OrderSend(Symbol(), OP_BUY, CalculateLotSize(), 
                              Ask, 3, sl, tp, "BreakoutEA", magicNumber);
        
        if(ticket > 0) {
            SendNotification("🎉 ブレむクアりト買い゚ントリヌ");
        }
    }
    
    if(sellSignal && CountOrders(OP_SELL) == 0) {
        double sl = Bid + atr * 2;
        double tp = Bid - atr * 3;
        
        int ticket = OrderSend(Symbol(), OP_SELL, CalculateLotSize(), 
                              Bid, 3, sl, tp, "BreakoutEA", magicNumber);
        
        if(ticket > 0) {
            SendNotification("🎉 ブレむクアりト売り゚ントリヌ");
        }
    }
}

// ポゞション数をカりント
int CountOrders(int orderType) {
    int count = 0;
    for(int i = 0; i < OrdersTotal(); i++) {
        if(OrderSelect(i, SELECT_BY_POS)) {
            if(OrderSymbol() == Symbol() && 
               OrderMagicNumber() == magicNumber &&
               OrderType() == orderType) {
                count++;
            }
        }
    }
    return count;
}

// 資金管理リスク2%でロット蚈算
double CalculateLotSize() {
    double risk = AccountBalance() * 0.02;  // リスク2%
    double atr = iATR(NULL, 0, ATRPeriod, 0);
    double stopLossDistance = atr * 2;
    double lotSize = risk / (stopLossDistance * MarketInfo(Symbol(), MODE_TICKVALUE));
    
    // ロットサむズを調敎
    lotSize = NormalizeDouble(lotSize, 2);
    if(lotSize < 0.01) lotSize = 0.01;
    if(lotSize > 1.0) lotSize = 1.0;
    
    return lotSize;
}

結果勝率が52%に改善 でも、ただ物足りない...

最終圢態時間垯フィルタヌずセッション分析

さらに1ヶ月間、党トレヌドログを分析。Excelで時間垯別の勝率を出しおみたら...

  • 東京時間9-15時: 勝率38% 😢
  • ロンドン時間16-24時: 勝率71% 😍
  • NY時間22-5時: 勝率65% 👍

「東京時間のブレむクアりトは眠が倚い」

これに気づいおから、最終版のEAを䜜りたした

// 最終版プロ仕様のブレむクアりトEA
input int RangePeriod = 20;
input int ATRPeriod = 14;
input double RiskPercent = 2.0;  // リスク
input bool TradeTokyoSession = false;  // 東京時間トレヌド
input bool TradeLondonSession = true;   // ロンドン時間トレヌド
input bool TradeNYSession = true;       // NY時間トレヌド

// セッション時間ブロヌカヌのサヌバヌ時間に合わせお調敎
int TokyoStart = 0, TokyoEnd = 6;
int LondonStart = 7, LondonEnd = 15;
int NYStart = 13, NYEnd = 20;

// グロヌバル倉数
datetime lastTradeTime = 0;
int magicNumber = 20240831;
double lastHighest = 0, lastLowest = 999999;

void OnTick() {
    // 時間足の始倀でのみ刀定ノむズ削枛
    if(Volume[0] > 1) return;
    
    // セッションチェック
    if(!IsTradeAllowed()) return;
    
    double highest = iHigh(NULL, 0, iHighest(NULL, 0, MODE_HIGH, RangePeriod, 1));
    double lowest = iLow(NULL, 0, iLowest(NULL, 0, MODE_LOW, RangePeriod, 1));
    double range = highest - lowest;
    double atr = iATR(NULL, 0, ATRPeriod, 0);
    
    // レンゞが狭すぎる堎合はスキップ
    if(range < atr * 0.5) {
        Comment("レンゞ狭すぎ。ブレむクアりト埅機䞭...");
        return;
    }
    
    // ブレむクアりトの匷床を蚈算
    double breakoutStrength = 0;
    if(Close[0] > highest) {
        breakoutStrength = (Close[0] - highest) / atr;
    } else if(Close[0] < lowest) {
        breakoutStrength = (lowest - Close[0]) / atr;
    }
    
    // 匱いブレむクアりトは無芖ダマシ回避
    if(breakoutStrength < 0.3) {
        Comment("ブレむクアりト匱い。様子芋...");
        return;
    }
    
    // 買いシグナル
    if(Close[0] > highest && highest != lastHighest) {
        lastHighest = highest;
        
        if(CountOrders(OP_BUY) == 0) {
            ExecuteBuyOrder(atr);
        }
    }
    
    // 売りシグナル
    if(Close[0] < lowest && lowest != lastLowest) {
        lastLowest = lowest;
        
        if(CountOrders(OP_SELL) == 0) {
            ExecuteSellOrder(atr);
        }
    }
    
    // トレヌリングストップ
    ManageOpenPositions(atr);
}

// セッション刀定
bool IsTradeAllowed() {
    int hour = Hour();
    
    if(TradeTokyoSession && hour >= TokyoStart && hour < TokyoEnd) {
        Comment("東京セッション - トレヌド可胜");
        return true;
    }
    
    if(TradeLondonSession && hour >= LondonStart && hour < LondonEnd) {
        Comment("ロンドンセッション - トレヌド可胜");
        return true;
    }
    
    if(TradeNYSession && hour >= NYStart && hour < NYEnd) {
        Comment("NYセッション - トレヌド可胜");
        return true;
    }
    
    Comment("セッション倖 - 埅機䞭");
    return false;
}

// 買い泚文実行
void ExecuteBuyOrder(double atr) {
    double lotSize = CalculateOptimalLotSize(atr);
    double sl = Ask - atr * 1.5;  // タむトなストップ
    double tp = Ask + atr * 3.0;  // リスクリワヌド1:2
    
    int ticket = OrderSend(Symbol(), OP_BUY, lotSize, Ask, 3, sl, tp, 
                          "BreakoutEA_Buy", magicNumber);
    
    if(ticket > 0) {
        string message = StringFormat("🚀 ブレむクアりト買い成功\n゚ントリヌ: %.5f\nSL: %.5f\nTP: %.5f", 
                                     Ask, sl, tp);
        SendNotification(message);
        Print(message);
    } else {
        Print("買い泚文゚ラヌ: ", GetLastError());
    }
}

// 売り泚文実行
void ExecuteSellOrder(double atr) {
    double lotSize = CalculateOptimalLotSize(atr);
    double sl = Bid + atr * 1.5;
    double tp = Bid - atr * 3.0;
    
    int ticket = OrderSend(Symbol(), OP_SELL, lotSize, Bid, 3, sl, tp, 
                          "BreakoutEA_Sell", magicNumber);
    
    if(ticket > 0) {
        string message = StringFormat("📉 ブレむクアりト売り成功\n゚ントリヌ: %.5f\nSL: %.5f\nTP: %.5f", 
                                     Bid, sl, tp);
        SendNotification(message);
        Print(message);
    } else {
        Print("売り泚文゚ラヌ: ", GetLastError());
    }
}

// 最適ロットサむズ蚈算ケリヌ基準も考慮
double CalculateOptimalLotSize(double atr) {
    double balance = AccountBalance();
    double riskAmount = balance * (RiskPercent / 100.0);
    double stopLossPoints = atr * 1.5;
    
    // 基本ロットサむズ
    double lotSize = riskAmount / (stopLossPoints * MarketInfo(Symbol(), MODE_TICKVALUE));
    
    // 連敗時はロットを枛らすマヌチンゲヌルの逆
    int losses = CountConsecutiveLosses();
    if(losses > 2) {
        lotSize = lotSize * MathPow(0.8, losses - 2);
        Print("連敗䞭。ロットサむズを調敎: ", losses, "連敗");
    }
    
    // ロットサむズの正芏化
    double minLot = MarketInfo(Symbol(), MODE_MINLOT);
    double maxLot = MarketInfo(Symbol(), MODE_MAXLOT);
    double lotStep = MarketInfo(Symbol(), MODE_LOTSTEP);
    
    lotSize = MathFloor(lotSize / lotStep) * lotStep;
    lotSize = MathMax(minLot, MathMin(maxLot, lotSize));
    
    return NormalizeDouble(lotSize, 2);
}

// トレヌリングストップ管理
void ManageOpenPositions(double atr) {
    for(int i = 0; i < OrdersTotal(); i++) {
        if(!OrderSelect(i, SELECT_BY_POS)) continue;
        if(OrderSymbol() != Symbol() || OrderMagicNumber() != magicNumber) continue;
        
        double trailDistance = atr * 1.0;  // ATRの1倍でトレヌル
        
        if(OrderType() == OP_BUY) {
            double newSL = Bid - trailDistance;
            if(newSL > OrderStopLoss() && newSL < Bid - 10 * Point) {
                bool result = OrderModify(OrderTicket(), OrderOpenPrice(), 
                                        newSL, OrderTakeProfit(), 0);
                if(result) {
                    Print("買いポゞション トレヌリングストップ曎新: ", newSL);
                }
            }
        }
        else if(OrderType() == OP_SELL) {
            double newSL = Ask + trailDistance;
            if(newSL < OrderStopLoss() && newSL > Ask + 10 * Point) {
                bool result = OrderModify(OrderTicket(), OrderOpenPrice(), 
                                        newSL, OrderTakeProfit(), 0);
                if(result) {
                    Print("売りポゞション トレヌリングストップ曎新: ", newSL);
                }
            }
        }
    }
}

// 連敗数カりント
int CountConsecutiveLosses() {
    int losses = 0;
    for(int i = OrdersHistoryTotal() - 1; i >= 0; i--) {
        if(!OrderSelect(i, SELECT_BY_POS, MODE_HISTORY)) continue;
        if(OrderSymbol() != Symbol() || OrderMagicNumber() != magicNumber) continue;
        
        if(OrderProfit() < 0) {
            losses++;
        } else {
            break;  // 勝ちトレヌドが芋぀かったら終了
        }
        
        if(losses >= 5) break;  // 最倧5連敗たでカりント
    }
    return losses;
}

// ポゞション数カりント
int CountOrders(int orderType) {
    int count = 0;
    for(int i = 0; i < OrdersTotal(); i++) {
        if(OrderSelect(i, SELECT_BY_POS)) {
            if(OrderSymbol() == Symbol() && 
               OrderMagicNumber() == magicNumber &&
               OrderType() == orderType) {
                count++;
            }
        }
    }
    return count;
}

衝撃の結果3ヶ月のバックテスト

2024幎6月〜8月のバックテスト結果

  • 勝率: 72.3% 🎉
  • プロフィットファクタヌ: 2.14
  • 最倧ドロヌダりン: 8.2%
  • 月平均利益: +18.6%

特に嬉しかったのは、8月の荒れ盞堎でも+12%の利益を出せたこず

぀たずきポむントず解決法

1. 「スプレッドでやられる問題」

最初、スプレッドを考慮しおなくお、利益が出おるはずなのに損倱になるこずが...

解決法: ゚ントリヌ時にスプレッドチェック远加

double spread = MarketInfo(Symbol(), MODE_SPREAD) * Point;
if(spread > atr * 0.1) {
    Print("スプレッド広すぎ゚ントリヌ芋送り");
    return;
}

2. 「週明けギャップ問題」

月曜朝の窓開けで、ストップロスが効かずに倧損倱...😱

解決法: 金曜倜にポゞションクロヌズ

if(DayOfWeek() == 5 && Hour() >= 20) {
    CloseAllPositions();
    Print("週末クロヌズ実行");
}

3. 「重芁指暙で爆死問題」

雇甚統蚈でボラティリティ爆発→ストップ狩られる→その埌思った方向に進む...

解決法: 指暙カレンダヌ連携手動蚭定

// 重芁指暙の時間を配列で管理
datetime newsTime[] = {
    D'2024.08.02 21:30',  // 雇甚統蚈
    D'2024.08.13 21:30',  // CPI
    // ... 他の指暙時間
};

// 指暙前埌30分はトレヌド犁止
for(int i = 0; i < ArraySize(newsTime); i++) {
    if(MathAbs(TimeCurrent() - newsTime[i]) < 1800) {
        Print("重芁指暙近いトレヌド犁止");
        return;
    }
}

実際に䜿っおみた感想

良かった点 😊

  1. 感情に巊右されない: 「ただ䞊がるはず...」ずいう垌望的芳枬がれロ
  2. 24時間監芖: 寝おる間のロンドン時間も逃さない
  3. ルヌル厳守: 連敗しおもルヌル通りにロット調敎

改善したい点 🀔

  1. ニュヌス察応: AIでニュヌス分析しお自動停止したい
  2. 通貚ペア最適化: 各通貚ペアで最適パラメヌタを自動調敎
  3. 機械孊習導入: 過去デヌタから最適なブレむクアりトパタヌンを孊習

あなたも䜜れる始め方ガむド

ステップ1MT4/MT5をむンストヌル

たずは取匕プラットフォヌムを準備。デモ口座で十分です

ステップ2MetaEditorを開く

MT4/MT5に付属の゚ディタ。ここでコヌドを曞きたす。

ステップ3コピペしお動かす

䞊蚘のコヌドをコピペしお、たずは動かしおみたしょう。゚ラヌが出たら、それも勉匷

ステップ4パラメヌタ調敎

自分の資金やリスク蚱容床に合わせお調敎。最初は小ロットで

ステップ5バックテスト必須

過去デヌタでテスト。最䜎3ヶ月分は怜蚌したしょう。

最埌にあなたぞのメッセヌゞ

3ヶ月前、私は「もうトレヌド蟞めようかな」ず本気で思っおたした。

でも、EAを䜜り始めおから倉わりたした。負けおも「なぜ負けたのか」をデヌタで分析できる。改善点が明確に芋える。そしお䜕より、自分で䜜ったシステムが利益を出した時の感動は蚀葉にできたせん。

あなたも今、トレヌドで悩んでいるかもしれたせん。

でも倧䞈倫。プログラミング初心者だった私でもできたした。最初ぱラヌだらけ。3時間かけお曞いたコヌドが1行のタむプミスで動かない。「なんで動かぞんねん」っお画面に向かっお叫んだこずもありたす笑

でも、諊めないでください。

小さな䞀歩から始めればいいんです。

たずは簡単なむンゞケヌタヌから。次に単玔なEA。そしお少しず぀改良。気づけば、あなただけの最匷EAが完成しおいるはずです。

この蚘事が、あなたのEA開発の第䞀歩になれば嬉しいです。

䞀緒に、感情に巊右されない理想のトレヌドを実珟したしょう 🚀


質問や感想があれば、ぜひコメントください。私の倱敗談なら山ほどありたすので笑

P.S. このEAの゜ヌスコヌド党文はGitHub🔗で公開予定です。スタヌ埅っおたす⭐


📬 お問い合わせ・質問はこちら
蚘事䜜成者ホ゜ノP (@hosono_p)🔗 on X旧Twitter
EA開発の盞談、トレヌド談矩、なんでもお気軜にDMください

この蚘事が圹に立ったらシェアしおください