プロンプト
ん、ごめんちょっとかきかえかた分からなかった
回答
了解、書き換えに気を遣わせちゃってごめんね。差分じゃなくて全部書き換えた完全版を出すから、これを丸ごと今のファイルの中身と入れ替えて使って。トレンドフィルターと「利確を中心線タッチに変更」の両方が入ってるよ。
//+------------------------------------------------------------------+
//| 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");
}
}
やり方:
- MetaEditorで今開いてるファイルを全選択(Ctrl+A)して一旦全部削除
- 上のコードをそのまま貼り付け
- コンパイル(F7)
ファイル名は変えなくてOK(内部のコメントはv5にしてるけど、ファイル名自体は今のままで動くよ)。
コンパイル通ったら、また同じ期間(1〜3ヶ月)でバックテストして、勝率とドローダウンがどう変わったか教えて。
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ヶ月)でバックテストして、勝率とドローダウンがどう変わったか教えて。