プロンプト

ん、ごめんちょっとかきかえかた分からなかった

回答

了解、書き換えに気を遣わせちゃってごめんね。差分じゃなくて全部書き換えた完全版を出すから、これを丸ごと今のファイルの中身と入れ替えて使って。トレンドフィルターと「利確を中心線タッチに変更」の両方が入ってるよ。

//+------------------------------------------------------------------+
//|                              Envelope_Bounce_Gold_M5_v5.mq5      |
//|  Gold(XAUUSD) M5 エンベロープ(14, 0.2%) バンド反発EA              |
//|  SL:0.5%固定 / TP:中心線(MA)タッチ                                |
//|  ロット:基準資金(200万)の%リスクで自動計算                        |
//|  日次損失5%・累計損失10%のプロップ用ガードレール                 |
//|  4連敗で当日エントリー停止 / トレンドフィルター付き               |
//+------------------------------------------------------------------+
#property copyright "Chappie"
#property version   "5.00"

#include <Trade\Trade.mqh>

//--- エンベロープ設定
input int      InpEnvPeriod      = 14;
input double   InpEnvDeviation   = 0.2;
input ENUM_MA_METHOD InpMAMethod = MODE_SMA;
input ENUM_APPLIED_PRICE InpAppliedPrice = PRICE_CLOSE;

//--- トレンドフィルター設定
input int      InpTrendMAPeriod   = 200;
input ENUM_MA_METHOD InpTrendMAMethod = MODE_EMA;
input int      InpTrendSlopeBars  = 10;

//--- リスク管理
input double   InpSLPercent      = 0.5;
input double   InpRiskPercent    = 1.0;
input double   InpFallbackLot    = 0.01;
input double   InpBaseCapital    = 2000000;

//--- ガードレール
input double   InpDailyLossLimitPercent = 5.0;
input double   InpMaxLossLimitPercent   = 10.0;
input int      InpMaxConsecutiveLosses  = 4;

//--- 発注管理
input int      InpMagic          = 20240918;
input int      InpSlippage       = 30;
input int      InpMaxSpreadPoints= 300;

//--- 経済指標フィルター
input bool     InpUseNewsFilter        = true;
input string   InpNewsCurrency         = "USD";
input int      InpNewsMinutesBefore    = 30;
input int      InpNewsMinutesAfter     = 30;
input bool     InpNewsHighImportanceOnly = true;

int      envHandle;
int      trendMAHandle;
CTrade   trade;
datetime lastBarTime = 0;

int      consecutiveLosses   = 0;
bool     tradingStoppedToday = false;
bool     haltedPermanently   = false;
double   dailyStartEquity    = 0;
datetime dailyStartDate      = 0;

//+------------------------------------------------------------------+
int OnInit()
{
   envHandle = iEnvelopes(_Symbol, PERIOD_M5, InpEnvPeriod, 0, InpMAMethod, InpAppliedPrice, InpEnvDeviation);
   if(envHandle == INVALID_HANDLE)
   {
      Print("エンベロープのハンドル作成に失敗しました");
      return(INIT_FAILED);
   }

   trendMAHandle = iMA(_Symbol, PERIOD_M5, InpTrendMAPeriod, 0, InpTrendMAMethod, PRICE_CLOSE);
   if(trendMAHandle == INVALID_HANDLE)
   {
      Print("トレンドMAのハンドル作成に失敗しました");
      return(INIT_FAILED);
   }

   trade.SetExpertMagicNumber(InpMagic);
   trade.SetDeviationInPoints(InpSlippage);

   dailyStartEquity = AccountInfoDouble(ACCOUNT_EQUITY);
   dailyStartDate    = TimeCurrent();
   return(INIT_SUCCEEDED);
}

void OnDeinit(const int reason)
{
   IndicatorRelease(envHandle);
   IndicatorRelease(trendMAHandle);
}

//+------------------------------------------------------------------+
bool IsNewBar()
{
   datetime t[1];
   if(CopyTime(_Symbol, PERIOD_M5, 0, 1, t) < 1) return false;
   if(t[0] != lastBarTime) { lastBarTime = t[0]; return true; }
   return false;
}

//+------------------------------------------------------------------+
bool HasOpenPosition()
{
   for(int i = PositionsTotal() - 1; i >= 0; i--)
   {
      ulong ticket = PositionGetTicket(i);
      if(ticket <= 0) continue;
      if(PositionGetString(POSITION_SYMBOL) == _Symbol &&
         PositionGetInteger(POSITION_MAGIC) == InpMagic)
         return true;
   }
   return false;
}

//+------------------------------------------------------------------+
double CalcLotByRisk(double slDistancePrice)
{
   double balance = AccountInfoDouble(ACCOUNT_BALANCE);
   double riskAmount = balance * InpRiskPercent / 100.0;

   double tickValue = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);
   double tickSize  = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);
   if(tickSize <= 0 || tickValue <= 0 || slDistancePrice <= 0)
      return InpFallbackLot;

   double lossPerLot = (slDistancePrice / tickSize) * tickValue;
   if(lossPerLot <= 0) return InpFallbackLot;

   double lot = riskAmount / lossPerLot;

   double lotStep = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
   double minLot  = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
   double maxLot  = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);

   lot = MathFloor(lot / lotStep) * lotStep;
   if(lot < minLot) lot = minLot;
   if(lot > maxLot) lot = maxLot;
   return lot;
}

//+------------------------------------------------------------------+
bool IsNewsBlocked()
{
   if(!InpUseNewsFilter) return false;

   MqlCalendarValue values[];
   datetime from = TimeCurrent() - 2*24*3600;
   datetime to   = TimeCurrent() + 2*24*3600;

   int total = CalendarValueHistory(values, from, to, NULL, InpNewsCurrency);
   if(total <= 0) return false;

   for(int i = 0; i < total; i++)
   {
      MqlCalendarEvent evt;
      if(!CalendarEventById(values[i].event_id, evt)) continue;
      if(InpNewsHighImportanceOnly && evt.importance != CALENDAR_IMPORTANCE_HIGH) continue;

      datetime eventTime = values[i].time;
      datetime blockFrom = eventTime - InpNewsMinutesBefore * 60;
      datetime blockTo   = eventTime + InpNewsMinutesAfter  * 60;

      if(TimeCurrent() >= blockFrom && TimeCurrent() <= blockTo)
         return true;
   }
   return false;
}

//+------------------------------------------------------------------+
//| 1=上昇トレンド(ショート禁止) / -1=下降トレンド(ロング禁止) / 0=レンジ |
//+------------------------------------------------------------------+
int GetTrendDirection()
{
   double maBuf[];
   ArraySetAsSeries(maBuf, true);
   if(CopyBuffer(trendMAHandle, 0, 0, InpTrendSlopeBars + 1, maBuf) < InpTrendSlopeBars + 1)
      return(0);

   double currentMA  = maBuf[0];
   double pastMA     = maBuf[InpTrendSlopeBars];
   double closePrice = iClose(_Symbol, PERIOD_M5, 0);

   bool priceAboveMA   = closePrice > currentMA;
   bool priceBelowMA   = closePrice < currentMA;
   bool maRisingSlope  = currentMA > pastMA;
   bool maFallingSlope = currentMA < pastMA;

   if(priceAboveMA && maRisingSlope)  return(1);
   if(priceBelowMA && maFallingSlope) return(-1);
   return(0);
}

//+------------------------------------------------------------------+
//| 日次リセット判定                                                   |
//+------------------------------------------------------------------+
void CheckDailyReset()
{
   MqlDateTime nowStruct, startStruct;
   TimeToStruct(TimeCurrent(), nowStruct);
   TimeToStruct(dailyStartDate, startStruct);

   if(nowStruct.day != startStruct.day || nowStruct.mon != startStruct.mon || nowStruct.year != startStruct.year)
   {
      dailyStartEquity    = AccountInfoDouble(ACCOUNT_EQUITY);
      dailyStartDate       = TimeCurrent();
      consecutiveLosses    = 0;
      tradingStoppedToday  = false;
      Print("新しい日になったので日次カウンターをリセットしました");
   }
}

//+------------------------------------------------------------------+
//| 日次5%・累計10%のガードレール確認                                 |
//+------------------------------------------------------------------+
void CheckGuardrails()
{
   double equity = AccountInfoDouble(ACCOUNT_EQUITY);

   double dailyLossPercent = (dailyStartEquity - equity) / InpBaseCapital * 100.0;
   if(dailyLossPercent >= InpDailyLossLimitPercent && !tradingStoppedToday)
   {
      tradingStoppedToday = true;
      Print("日次損失リミット", InpDailyLossLimitPercent, "%に到達。本日のエントリーを停止します");
   }

   double cumulativeLossPercent = (InpBaseCapital - equity) / InpBaseCapital * 100.0;
   if(cumulativeLossPercent >= InpMaxLossLimitPercent && !haltedPermanently)
   {
      haltedPermanently = true;
      Print("累計損失リミット", InpMaxLossLimitPercent, "%に到達。EAを完全停止します");
   }
}

//+------------------------------------------------------------------+
//| 中心線(MA)タッチで利確                                            |
//+------------------------------------------------------------------+
void ManageOpenPositions()
{
   double upperNow[], lowerNow[];
   ArraySetAsSeries(upperNow, true);
   ArraySetAsSeries(lowerNow, true);
   if(CopyBuffer(envHandle, 0, 0, 1, upperNow) < 1) return;
   if(CopyBuffer(envHandle, 1, 0, 1, lowerNow) < 1) return;

   double midLine = (upperNow[0] + lowerNow[0]) / 2.0;

   for(int i = PositionsTotal() - 1; i >= 0; i--)
   {
      ulong ticket = PositionGetTicket(i);
      if(ticket <= 0) continue;
      if(PositionGetString(POSITION_SYMBOL) != _Symbol) continue;
      if(PositionGetInteger(POSITION_MAGIC) != InpMagic) continue;

      long type = PositionGetInteger(POSITION_TYPE);
      if(type == POSITION_TYPE_BUY)
      {
         double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
         if(bid >= midLine)
            trade.PositionClose(ticket);
      }
      else if(type == POSITION_TYPE_SELL)
      {
         double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
         if(ask <= midLine)
            trade.PositionClose(ticket);
      }
   }
}

//+------------------------------------------------------------------+
//| 決済結果を見て連敗カウントを更新                                   |
//+------------------------------------------------------------------+
void OnTradeTransaction(const MqlTradeTransaction& trans,
                         const MqlTradeRequest& request,
                         const MqlTradeResult& result)
{
   if(trans.type != TRADE_TRANSACTION_DEAL_ADD) return;

   if(!HistoryDealSelect(trans.deal)) return;
   if(HistoryDealGetString(trans.deal, DEAL_SYMBOL) != _Symbol) return;
   if(HistoryDealGetInteger(trans.deal, DEAL_MAGIC) != InpMagic) return;
   if(HistoryDealGetInteger(trans.deal, DEAL_ENTRY) != DEAL_ENTRY_OUT) return;

   double profit = HistoryDealGetDouble(trans.deal, DEAL_PROFIT);

   if(profit < 0)
   {
      consecutiveLosses++;
      Print("連敗数:", consecutiveLosses);
      if(consecutiveLosses >= InpMaxConsecutiveLosses)
      {
         tradingStoppedToday = true;
         Print(InpMaxConsecutiveLosses, "連敗に到達。本日のエントリーを停止します");
      }
   }
   else if(profit > 0)
   {
      consecutiveLosses = 0;
   }
}

//+------------------------------------------------------------------+
void OnTick()
{
   ManageOpenPositions();
   CheckDailyReset();
   CheckGuardrails();

   if(haltedPermanently)   return;
   if(tradingStoppedToday) return;
   if(!IsNewBar())         return;

   double spreadPoints = (double)SymbolInfoInteger(_Symbol, SYMBOL_SPREAD);
   if(spreadPoints > InpMaxSpreadPoints) return;

   if(HasOpenPosition()) return;
   if(IsNewsBlocked())   return;

   int trend = GetTrendDirection();

   double upper[], lower[];
   ArraySetAsSeries(upper, true);
   ArraySetAsSeries(lower, true);
   if(CopyBuffer(envHandle, 0, 1, 2, upper) < 2) return;
   if(CopyBuffer(envHandle, 1, 1, 2, lower) < 2) return;

   double high1  = iHigh(_Symbol, PERIOD_M5, 1);
   double low1   = iLow(_Symbol, PERIOD_M5, 1);
   double close1 = iClose(_Symbol, PERIOD_M5, 1);

   double upper1 = upper[0];
   double lower1 = lower[0];

   //--- 買いシグナル
   if(low1 <= lower1 && close1 > lower1)
   {
      if(trend == -1) return; // 下降トレンド中はロング禁止

      double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
      double slDistance = ask * InpSLPercent / 100.0;
      double sl = ask - slDistance;
      double lot = CalcLotByRisk(slDistance);

      trade.Buy(lot, _Symbol, ask, sl, 0, "Envelope Bounce Buy");
   }
   //--- 売りシグナル
   else if(high1 >= upper1 && close1 < upper1)
   {
      if(trend == 1) return; // 上昇トレンド中はショート禁止

      double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
      double slDistance = bid * InpSLPercent / 100.0;
      double sl = bid + slDistance;
      double lot = CalcLotByRisk(slDistance);

      trade.Sell(lot, _Symbol, bid, sl, 0, "Envelope Bounce Sell");
   }
}

やり方:

  1. MetaEditorで今開いてるファイルを全選択(Ctrl+A)して一旦全部削除
  2. 上のコードをそのまま貼り付け
  3. コンパイル(F7)

ファイル名は変えなくてOK(内部のコメントはv5にしてるけど、ファイル名自体は今のままで動くよ)。

コンパイル通ったら、また同じ期間(1〜3ヶ月)でバックテストして、勝率とドローダウンがどう変わったか教えて。

anthropic
Sonnet 5の回答

Sonnet 5

了解、書き換えに気を遣わせちゃってごめんね。差分じゃなくて全部書き換えた完全版を出すから、これを丸ごと今のファイルの中身と入れ替えて使って。トレンドフィルターと「利確を中心線タッチに変更」の両方が入ってるよ。 //+------------------------------------------------------------------+ //| Envelope_Bounce_Gold_M5_v5.mq5 | //| Gold(XAUUSD) M5 エンベロープ(14, 0.2%) バンド反発EA | //| SL:0.5%固定 / TP:中心線(MA)タッチ | //| ロット:基準資金(200万)の%リスクで自動計算 | //| 日次損失5%・累計損失10%のプロップ用ガードレール | //| 4連敗で当日エントリー停止 / トレンドフィルター付き | //+------------------------------------------------------------------+ #property copyright "Chappie" #property version "5.00" #include <Trade\Trade.mqh> //--- エンベロープ設定 input int InpEnvPeriod = 14; input double InpEnvDeviation = 0.2; input ENUM_MA_METHOD InpMAMethod = MODE_SMA; input ENUM_APPLIED_PRICE InpAppliedPrice = PRICE_CLOSE; //--- トレンドフィルター設定 input int InpTrendMAPeriod = 200; input ENUM_MA_METHOD InpTrendMAMethod = MODE_EMA; input int InpTrendSlopeBars = 10; //--- リスク管理 input double InpSLPercent = 0.5; input double InpRiskPercent = 1.0; input double InpFallbackLot = 0.01; input double InpBaseCapital = 2000000; //--- ガードレール input double InpDailyLossLimitPercent = 5.0; input double InpMaxLossLimitPercent = 10.0; input int InpMaxConsecutiveLosses = 4; //--- 発注管理 input int InpMagic = 20240918; input int InpSlippage = 30; input int InpMaxSpreadPoints= 300; //--- 経済指標フィルター input bool InpUseNewsFilter = true; input string InpNewsCurrency = "USD"; input int InpNewsMinutesBefore = 30; input int InpNewsMinutesAfter = 30; input bool InpNewsHighImportanceOnly = true; int envHandle; int trendMAHandle; CTrade trade; datetime lastBarTime = 0; int consecutiveLosses = 0; bool tradingStoppedToday = false; bool haltedPermanently = false; double dailyStartEquity = 0; datetime dailyStartDate = 0; //+------------------------------------------------------------------+ int OnInit() { envHandle = iEnvelopes(_Symbol, PERIOD_M5, InpEnvPeriod, 0, InpMAMethod, InpAppliedPrice, InpEnvDeviation); if(envHandle == INVALID_HANDLE) { Print("エンベロープのハンドル作成に失敗しました"); return(INIT_FAILED); } trendMAHandle = iMA(_Symbol, PERIOD_M5, InpTrendMAPeriod, 0, InpTrendMAMethod, PRICE_CLOSE); if(trendMAHandle == INVALID_HANDLE) { Print("トレンドMAのハンドル作成に失敗しました"); return(INIT_FAILED); } trade.SetExpertMagicNumber(InpMagic); trade.SetDeviationInPoints(InpSlippage); dailyStartEquity = AccountInfoDouble(ACCOUNT_EQUITY); dailyStartDate = TimeCurrent(); return(INIT_SUCCEEDED); } void OnDeinit(const int reason) { IndicatorRelease(envHandle); IndicatorRelease(trendMAHandle); } //+------------------------------------------------------------------+ bool IsNewBar() { datetime t[1]; if(CopyTime(_Symbol, PERIOD_M5, 0, 1, t) < 1) return false; if(t[0] != lastBarTime) { lastBarTime = t[0]; return true; } return false; } //+------------------------------------------------------------------+ bool HasOpenPosition() { for(int i = PositionsTotal() - 1; i >= 0; i--) { ulong ticket = PositionGetTicket(i); if(ticket <= 0) continue; if(PositionGetString(POSITION_SYMBOL) == _Symbol && PositionGetInteger(POSITION_MAGIC) == InpMagic) return true; } return false; } //+------------------------------------------------------------------+ double CalcLotByRisk(double slDistancePrice) { double balance = AccountInfoDouble(ACCOUNT_BALANCE); double riskAmount = balance InpRiskPercent / 100.0; double tickValue = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE); double tickSize = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE); if(tickSize <= 0 || tickValue <= 0 || slDistancePrice <= 0) return InpFallbackLot; double lossPerLot = (slDistancePrice / tickSize) tickValue; if(lossPerLot <= 0) return InpFallbackLot; double lot = riskAmount / lossPerLot; double lotStep = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP); double minLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN); double maxLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX); lot = MathFloor(lot / lotStep) lotStep; if(lot < minLot) lot = minLot; if(lot > maxLot) lot = maxLot; return lot; } //+------------------------------------------------------------------+ bool IsNewsBlocked() { if(!InpUseNewsFilter) return false; MqlCalendarValue values[]; datetime from = TimeCurrent() - 2243600; datetime to = TimeCurrent() + 2243600; int total = CalendarValueHistory(values, from, to, NULL, InpNewsCurrency); if(total <= 0) return false; for(int i = 0; i < total; i++) { MqlCalendarEvent evt; if(!CalendarEventById(values[i].event_id, evt)) continue; if(InpNewsHighImportanceOnly && evt.importance != CALENDAR_IMPORTANCE_HIGH) continue; datetime eventTime = values[i].time; datetime blockFrom = eventTime - InpNewsMinutesBefore 60; datetime blockTo = eventTime + InpNewsMinutesAfter 60; if(TimeCurrent() >= blockFrom && TimeCurrent() <= blockTo) return true; } return false; } //+------------------------------------------------------------------+ //| 1=上昇トレンド(ショート禁止) / -1=下降トレンド(ロング禁止) / 0=レンジ | //+------------------------------------------------------------------+ int GetTrendDirection() { double maBuf[]; ArraySetAsSeries(maBuf, true); if(CopyBuffer(trendMAHandle, 0, 0, InpTrendSlopeBars + 1, maBuf) < InpTrendSlopeBars + 1) return(0); double currentMA = maBuf[0]; double pastMA = maBuf[InpTrendSlopeBars]; double closePrice = iClose(_Symbol, PERIOD_M5, 0); bool priceAboveMA = closePrice > currentMA; bool priceBelowMA = closePrice < currentMA; bool maRisingSlope = currentMA > pastMA; bool maFallingSlope = currentMA < pastMA; if(priceAboveMA && maRisingSlope) return(1); if(priceBelowMA && maFallingSlope) return(-1); return(0); } //+------------------------------------------------------------------+ //| 日次リセット判定 | //+------------------------------------------------------------------+ void CheckDailyReset() { MqlDateTime nowStruct, startStruct; TimeToStruct(TimeCurrent(), nowStruct); TimeToStruct(dailyStartDate, startStruct); if(nowStruct.day != startStruct.day || nowStruct.mon != startStruct.mon || nowStruct.year != startStruct.year) { dailyStartEquity = AccountInfoDouble(ACCOUNT_EQUITY); dailyStartDate = TimeCurrent(); consecutiveLosses = 0; tradingStoppedToday = false; Print("新しい日になったので日次カウンターをリセットしました"); } } //+------------------------------------------------------------------+ //| 日次5%・累計10%のガードレール確認 | //+------------------------------------------------------------------+ void CheckGuardrails() { double equity = AccountInfoDouble(ACCOUNT_EQUITY); double dailyLossPercent = (dailyStartEquity - equity) / InpBaseCapital 100.0; if(dailyLossPercent >= InpDailyLossLimitPercent && !tradingStoppedToday) { tradingStoppedToday = true; Print("日次損失リミット", InpDailyLossLimitPercent, "%に到達。本日のエントリーを停止します"); } double cumulativeLossPercent = (InpBaseCapital - equity) / InpBaseCapital 100.0; if(cumulativeLossPercent >= InpMaxLossLimitPercent && !haltedPermanently) { haltedPermanently = true; Print("累計損失リミット", InpMaxLossLimitPercent, "%に到達。EAを完全停止します"); } } //+------------------------------------------------------------------+ //| 中心線(MA)タッチで利確 | //+------------------------------------------------------------------+ void ManageOpenPositions() { double upperNow[], lowerNow[]; ArraySetAsSeries(upperNow, true); ArraySetAsSeries(lowerNow, true); if(CopyBuffer(envHandle, 0, 0, 1, upperNow) < 1) return; if(CopyBuffer(envHandle, 1, 0, 1, lowerNow) < 1) return; double midLine = (upperNow[0] + lowerNow[0]) / 2.0; for(int i = PositionsTotal() - 1; i >= 0; i--) { ulong ticket = PositionGetTicket(i); if(ticket <= 0) continue; if(PositionGetString(POSITION_SYMBOL) != _Symbol) continue; if(PositionGetInteger(POSITION_MAGIC) != InpMagic) continue; long type = PositionGetInteger(POSITION_TYPE); if(type == POSITION_TYPE_BUY) { double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID); if(bid >= midLine) trade.PositionClose(ticket); } else if(type == POSITION_TYPE_SELL) { double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK); if(ask <= midLine) trade.PositionClose(ticket); } } } //+------------------------------------------------------------------+ //| 決済結果を見て連敗カウントを更新 | //+------------------------------------------------------------------+ void OnTradeTransaction(const MqlTradeTransaction& trans, const MqlTradeRequest& request, const MqlTradeResult& result) { if(trans.type != TRADE_TRANSACTION_DEAL_ADD) return; if(!HistoryDealSelect(trans.deal)) return; if(HistoryDealGetString(trans.deal, DEAL_SYMBOL) != _Symbol) return; if(HistoryDealGetInteger(trans.deal, DEAL_MAGIC) != InpMagic) return; if(HistoryDealGetInteger(trans.deal, DEAL_ENTRY) != DEAL_ENTRY_OUT) return; double profit = HistoryDealGetDouble(trans.deal, DEAL_PROFIT); if(profit < 0) { consecutiveLosses++; Print("連敗数:", consecutiveLosses); if(consecutiveLosses >= InpMaxConsecutiveLosses) { tradingStoppedToday = true; Print(InpMaxConsecutiveLosses, "連敗に到達。本日のエントリーを停止します"); } } else if(profit > 0) { consecutiveLosses = 0; } } //+------------------------------------------------------------------+ void OnTick() { ManageOpenPositions(); CheckDailyReset(); CheckGuardrails(); if(haltedPermanently) return; if(tradingStoppedToday) return; if(!IsNewBar()) return; double spreadPoints = (double)SymbolInfoInteger(_Symbol, SYMBOL_SPREAD); if(spreadPoints > InpMaxSpreadPoints) return; if(HasOpenPosition()) return; if(IsNewsBlocked()) return; int trend = GetTrendDirection(); double upper[], lower[]; ArraySetAsSeries(upper, true); ArraySetAsSeries(lower, true); if(CopyBuffer(envHandle, 0, 1, 2, upper) < 2) return; if(CopyBuffer(envHandle, 1, 1, 2, lower) < 2) return; double high1 = iHigh(_Symbol, PERIOD_M5, 1); double low1 = iLow(_Symbol, PERIOD_M5, 1); double close1 = iClose(_Symbol, PERIOD_M5, 1); double upper1 = upper[0]; double lower1 = lower[0]; //--- 買いシグナル if(low1 <= lower1 && close1 > lower1) { if(trend == -1) return; // 下降トレンド中はロング禁止 double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK); double slDistance = ask InpSLPercent / 100.0; double sl = ask - slDistance; double lot = CalcLotByRisk(slDistance); trade.Buy(lot, _Symbol, ask, sl, 0, "Envelope Bounce Buy"); } //--- 売りシグナル else if(high1 >= upper1 && close1 < upper1) { if(trend == 1) return; // 上昇トレンド中はショート禁止 double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID); double slDistance = bid * InpSLPercent / 100.0; double sl = bid + slDistance; double lot = CalcLotByRisk(slDistance); trade.Sell(lot, _Symbol, bid, sl, 0, "Envelope Bounce Sell"); } } やり方: 1. MetaEditorで今開いてるファイルを全選択(Ctrl+A)して一旦全部削除 2. 上のコードをそのまま貼り付け 3. コンパイル(F7) ファイル名は変えなくてOK(内部のコメントはv5にしてるけど、ファイル名自体は今のままで動くよ)。 コンパイル通ったら、また同じ期間(1〜3ヶ月)でバックテストして、勝率とドローダウンがどう変わったか教えて。

チャッピー

チャッピーを無料で試す

すべてのAIモデルをひとつのアプリで。

Download on the App Storeチャッピーからシェア
チャッピー

チャッピーを無料で試す

すべてのAIモデルをひとつのアプリで。

Download