//+------------------------------------------------------------------+ //| EA510.mq4 | //+------------------------------------------------------------------+ //Shortのみ20日以降にエントリーするように変更 //Shortのみ23日以降の月,金,最終日にエントリーするように変更 //トレンド判定を追加 #property copyright "" #property link "" #property version "1.00" #property strict #property description "EA510" // EA説明文 //+------------------------------------------------------------------+ // アカウント認証機能 bool Ninsho = false; // アカウント認証機能可否 int AccountNo = 1234567; // 認証アカウント口座番号 //+------------------------------------------------------------------+ // 列挙型宣言 enum ENUM_ONOFF{ off = 0, //OFF on = 1 //ON }; enum ENUM_HOUR{ hour0 = 0, //00時 hour1 = 1, //01時 hour2 = 2, //02時 hour3 = 3, //03時 hour4 = 4, //04時 hour5 = 5, //05時 hour6 = 6, //06時 hour7 = 7, //07時 hour8 = 8, //08時 hour9 = 9, //09時 hour10 = 10, //10時 hour11 = 11, //11時 hour12 = 12, //12時 hour13 = 13, //13時 hour14 = 14, //14時 hour15 = 15, //15時 hour16 = 16, //16時 hour17 = 17, //17時 hour18 = 18, //18時 hour19 = 19, //19時 hour20 = 20, //20時 hour21 = 21, //21時 hour22 = 22, //22時 hour23 = 23 //23時 }; enum ENUM_MINUTE{ minute0 = 0, //00分 minute1 = 1, //01分 minute2 = 2, //02分 minute3 = 3, //03分 minute4 = 4, //04分 minute5 = 5, //05分 minute6 = 6, //06分 minute7 = 7, //07分 minute8 = 8, //08分 minute9 = 9, //09分 minute10 = 10, //10分 minute11 = 11, //11分 minute12 = 12, //12分 minute13 = 13, //13分 minute14 = 14, //14分 minute15 = 15, //15分 minute16 = 16, //16分 minute17 = 17, //17分 minute18 = 18, //18分 minute19 = 19, //19分 minute20 = 20, //20分 minute21 = 21, //21分 minute22 = 22, //22分 minute23 = 23, //23分 minute24 = 24, //24分 minute25 = 25, //25分 minute26 = 26, //26分 minute27 = 27, //27分 minute28 = 28, //28分 minute29 = 29, //29分 minute30 = 30, //30分 minute31 = 31, //31分 minute32 = 32, //32分 minute33 = 33, //33分 minute34 = 34, //34分 minute35 = 35, //35分 minute36 = 36, //36分 minute37 = 37, //37分 minute38 = 38, //38分 minute39 = 39, //39分 minute40 = 40, //40分 minute41 = 41, //41分 minute42 = 42, //42分 minute43 = 43, //43分 minute44 = 44, //44分 minute45 = 45, //45分 minute46 = 46, //46分 minute47 = 47, //47分 minute48 = 48, //48分 minute49 = 49, //49分 minute50 = 50, //50分 minute51 = 51, //51分 minute52 = 52, //52分 minute53 = 53, //53分 minute54 = 54, //54分 minute55 = 55, //55分 minute56 = 56, //56分 minute57 = 57, //57分 minute58 = 58, //58分 minute59 = 59 //59分 }; enum ENUM_DST{ USStandard = 0, //US基準 UKStandard = 1 //UK基準 }; // 入力パラメータ宣言 extern string _BASIC = "──────────"; //▼基本設定 ────────── extern int MagicNumber = 5102412; //┣ マジックナンバー extern ENUM_ONOFF FukuriOnOff = off; //┣ 複利ロット設定 extern double LotsIncreaceAmt = 100000.0; //┃ ┣ ON時ロット増加証拠金単位 extern double LotsIncreaceStep = 0.01; //┃ ┣ ON時ロット増加ステップ extern double DefaultLots = 0.01; //┃ ┗ OFF時固定時ロット数 extern double MaxSpreadPips = 0.0; //┣ 最大許容スプレッド(Pips)(ゼロ設定で機能Off) extern double MaxSlippagePips = 2.0; //┗ 最大許容スリッページ(Pips) extern string _TPSL = "──────────"; //▼TP/SL設定 ────────── double TPPips = 300.0; //┣ TP幅(Pips) double SLPips = 50.0; //┗ SL幅(Pips) string _NOTICE = "──────────"; //▼通知設定 ────────── ENUM_ONOFF AlertNotice = off; //┣ アラート通知設定 ENUM_ONOFF MailNotice = off; //┣ メール通知設定 ENUM_ONOFF PushNotice = off; //┗ スマホPUSH通知設定 extern string _DST = "──────────"; //▼サマータイム・時差設定 ────────── extern ENUM_ONOFF JudgeDST = on; //┣ サマータイム判定有無 extern ENUM_DST AccountStandard = UKStandard; //┣ サマータイム適用基準(口座会社) extern int TimeDiff = 7; //┗ 時差(冬時間での日本時間とMT4サーバー時間との時間差) double Kairi_Judge_percent1_L = 2; // 【順張りエントリー可】長期MAに対する乖離〇%以内 double Kairi_Judge_percent2_L = 0; // 【逆張りエントリー可】長期MAに対して乖離〇%以上 int Trend_period1_L = 110; // 中期移動平均線 int Trend_period2_L = 460; // 長期移動平均線 double Kairi_Judge_percent1_S = 2.25; // 【順張りエントリー可】長期MAに対する乖離〇%以内 double Kairi_Judge_percent2_S = 1.75; // 【逆張りエントリー可】長期MAに対して乖離〇%以上 int Trend_period1_S = 90; // 中期移動平均線 int Trend_period2_S = 380; // 長期移動平均線 // 定数(const) const string EAName = WindowExpertName(); // EA名(コメント・アラート・メール・プッシュ通知本文) // グローバル変数 double MinLot = 0; // 最小ロット数 double MaxLot = 0; // 最大ロット数 int LotStepDigit = 0; // ロットステップ小数点桁数 int NowBuyCount = 0; // 保有ロングポジション数 int NowSellCount = 0; // 保有ショートポジション数 int MaxSpreadPoints = 0; // 最大許容スプレッドPoints int MaxSlippagePoints = 0; // 最大許容スリッページPoints int TPPoints = 0; // TP幅Points int SLPoints = 0; // SL幅Points datetime runDate = Time[0]; // 足確定判定用 string CommentText = "EA510"; // コメント本文 //+------------------------------------------------------------------+ //| OnInit(初期化)イベント | //+------------------------------------------------------------------+ int OnInit(){ // ---アカウント認証 if(IsValidAccount() == false){ ExpertRemove(); return(INIT_FAILED); } // ロットステップを取得 double LotStep = MarketInfo(Symbol(),MODE_LOTSTEP); if(LotStep == 1) LotStepDigit = 0; else if(LotStep == 0.1) LotStepDigit = 1; else LotStepDigit = 2; // 口座の最小・最大ロット数を取得 MinLot = MarketInfo(Symbol(),MODE_MINLOT); MaxLot = MarketInfo(Symbol(),MODE_MAXLOT); // エントリーロット数の設定値が最小ロット以下の場合は最小ロットに、最大ロット以上の場合は最大ロットに強制的に変更 if(DefaultLots <= MinLot){ DefaultLots = MinLot; }else if(DefaultLots >= MaxLot){ DefaultLots = MaxLot; }else{ DefaultLots = NormalizeDouble(DefaultLots,LotStepDigit); } // マジックナンバーがゼロの場合(手動エントリ―時と同値)、当システム固定のナンバーを付与 if(MagicNumber == 0){ MagicNumber = 5102412; } // Pips指定をPointsへ換算 MaxSpreadPoints = (int)(MaxSpreadPips*10); MaxSlippagePoints = (int)(MaxSlippagePips*10); TPPoints = (int)(TPPips*10); SLPoints = (int)(SLPips*10); // 初期化 runDate = iTime(NULL,PERIOD_M5,0); HideTestIndicators(true); return(INIT_SUCCEEDED); // 戻り値:初期化成功 } //+------------------------------------------------------------------+ //| OnDeinit(アンロード)イベント | //+------------------------------------------------------------------+ void OnDeinit(const int reason){ HideTestIndicators(false); // ---コメントの削除 Comment(""); } //+------------------------------------------------------------------+ //| OnTick(tick受信)イベント | //+------------------------------------------------------------------+ void OnTick(){ bool EAStopFlg = false; // EA停止状態フラグ bool AshiKakuteiFlg = false; // 足確定フラグ bool TradeAllowedErr = false; // 取引可能チェックフラグ bool TradeAllowedFlag = true; // 取引可能フラグ int resI = 0; // int型戻り値格納用 bool resB = false; // bool型戻り値格納用 bool InParameterErr = false; // パラメーターチェックフラグ CommentText = ""; // 足確定判定 if(iTime(NULL,PERIOD_M5,0) != runDate){ runDate = iTime(NULL,PERIOD_M5,0); AshiKakuteiFlg = true; }else{ AshiKakuteiFlg = false; } // 自動売買許可設定チェック if(IsTradeAllowed() == false && IsTesting() == false){ // 自動売買禁止設定の場合、エラーメッセージを出力し処理終了 CommentText += "自動売買禁止設定になっています。"; EAStopFlg = true; } // 取引可能な時間帯以外は処理をしない if(MarketInfo(Symbol(),MODE_TRADEALLOWED) != 1 && IsTesting() == false){ CommentText += "マーケットが閉まっているため取引不可です。"; EAStopFlg = true; } // EAが停止状態で無い場合以下処理を実施 if(EAStopFlg == false){ // 取引可能チェック(新規ポジションを取るかどうかの制御で決済は対象外) if(MaxSpreadPoints > 0 && MarketInfo(Symbol(),MODE_SPREAD) > MaxSpreadPoints){ TradeAllowedErr = true; CommentText += "許容スプレッド外のため新規エントリー不可" + "\r\n"; } if(TradeAllowedErr == true) TradeAllowedFlag = false; datetime NowDate = ServerToLocalTime(TimeCurrent()); datetime NowDate_WO_ST = ServerToLocalTime_WO_ST(TimeCurrent()); int NextTargetDay = 0; if(TimeDay(NowDate) <= 5){ NextTargetDay = 5; }else if(TimeDay(NowDate) > 5 && TimeDay(NowDate) <= 10){ NextTargetDay = 10; }else if(TimeDay(NowDate) > 10 && TimeDay(NowDate) <= 15){ NextTargetDay = 15; }else if(TimeDay(NowDate) > 15 && TimeDay(NowDate) <= 20){ NextTargetDay = 20; }else if(TimeDay(NowDate) > 20 && TimeDay(NowDate) <= 25){ NextTargetDay = 25; }else if(TimeDay(NowDate) > 25){ NextTargetDay = 99; //最終のゴトー日はエントリーしないように修正 99⇒98 } if(NextTargetDay == 99){ if(TimeMonth(NowDate) == 1 || TimeMonth(NowDate) == 3 || TimeMonth(NowDate) == 5 || TimeMonth(NowDate) == 7 || TimeMonth(NowDate) == 8 || TimeMonth(NowDate) == 10 || TimeMonth(NowDate) == 12){ NextTargetDay = 31; // NextTargetDay = 5; }else{ if(TimeMonth(NowDate) == 2){ if(TimeYear(NowDate)%400 == 0 || (TimeYear(NowDate)%4 == 0 && TimeYear(NowDate)%100 != 0)) NextTargetDay = 29; else NextTargetDay = 28; // if(TimeYear(NowDate)%400 == 0 || (TimeYear(NowDate)%4 == 0 && TimeYear(NowDate)%100 != 0)) NextTargetDay = 5; // else NextTargetDay = 5; }else{ NextTargetDay = 30; // NextTargetDay = 5; } } }//VictoryRoadは冬時間2:00,4:00 夏時間1:00,3:00にしている datetime NextTargetDate = StringToTime(IntegerToString(TimeYear(NowDate)) + "." + IntegerToString(TimeMonth(NowDate)) + "." + IntegerToString(NextTargetDay) + " 00:00"); // if(TimeDayOfWeek(NextTargetDate) == MONDAY || (TimeMonth(NextTargetDate) == 12 && (TimeDay(NextTargetDate) == 25 || TimeDay(NextTargetDate) == 31)) if((TimeMonth(NextTargetDate) == 12 && (TimeDay(NextTargetDate) == 25 || TimeDay(NextTargetDate) == 31)) || (TimeMonth(NextTargetDate) == 1 && (TimeDay(NextTargetDate) == 5 )) || (TimeMonth(NextTargetDate) == 5 && (TimeDay(NextTargetDate) == 5 )) ){ // 何もしない }else{ // 保有中のポジションの情報を取得 CalculateCurrentOrders(); bool BuyEntryFlg = false; bool SellEntryFlg = false; bool BuyCloseFlg = false; bool SellCloseFlg = false; if(TimeDayOfWeek(NextTargetDate) == SATURDAY || TimeDayOfWeek(NextTargetDate) == SUNDAY){ if(NextTargetDay <=25 && TimeDayOfWeek(NowDate) == FRIDAY && (TimeHour(NowDate) == 1 || TimeHour(NowDate) == 3)&& TimeMinute(NowDate) == 0 && Entry_Rule1(1)==1 ){ BuyEntryFlg = true; }else if(TimeDayOfWeek(NowDate) == FRIDAY && TimeHour(NowDate) >= 9 && TimeMinute(NowDate) == 55 ){ BuyCloseFlg = true; }else if(TimeMonth(NowDate) != 12 && TimeDay(NowDate) >=23 && TimeDay(NowDate) <=30 && TimeHour(NowDate_WO_ST) == 9 && TimeMinute(NowDate_WO_ST) == 15 && Entry_Rule1(2)==2){ SellEntryFlg = true; }else if(TimeHour(NowDate_WO_ST) == 15 && TimeMinute(NowDate_WO_ST) == 50){ SellCloseFlg = true; } } else if(TimeDayOfWeek(NextTargetDate) == MONDAY ){ if(NextTargetDay <=25 && TimeDayOfWeek(NowDate) == SATURDAY && (TimeHour(NowDate) == 1 || TimeHour(NowDate) == 3)&& TimeMinute(NowDate) == 0 && Entry_Rule1(1)==1 ){ BuyEntryFlg = true; }else if(TimeDayOfWeek(NowDate) == MONDAY && TimeHour(NowDate) >= 9 && TimeMinute(NowDate) == 55){ BuyCloseFlg = true; }else if(TimeMonth(NowDate) != 12 && TimeDay(NowDate) >=23 && TimeDay(NowDate) <=30 && TimeHour(NowDate_WO_ST) == 9 && TimeMinute(NowDate_WO_ST) == 15 && Entry_Rule1(2)==2){ SellEntryFlg = true; }else if( TimeHour(NowDate_WO_ST) == 15 && TimeMinute(NowDate_WO_ST) == 50){ SellCloseFlg = true; } }else if(TimeDay(NowDate) == NextTargetDay){ if(NextTargetDay <=25 && (TimeHour(NowDate) == 1 || TimeHour(NowDate) == 3 )&& TimeMinute(NowDate) == 0 && Entry_Rule1(1)==1 ){ BuyEntryFlg = true; }else if(TimeDay(NowDate) == NextTargetDay && TimeHour(NowDate) >= 9 && TimeMinute(NowDate) == 55){ BuyCloseFlg = true; }else if(TimeMonth(NowDate) != 12 && TimeDay(NowDate) >=23 && TimeDay(NowDate) <=30 && TimeHour(NowDate_WO_ST) == 9 && TimeMinute(NowDate_WO_ST) == 15 && Entry_Rule1(2)==2 ){ SellEntryFlg = true; }else if(TimeHour(NowDate_WO_ST) == 15 && TimeMinute(NowDate_WO_ST) == 50){ SellCloseFlg = true; } }else{ if(TimeMonth(NowDate) != 12 && TimeDay(NowDate) >=23 && TimeDay(NowDate) <=30 && TimeHour(NowDate_WO_ST) == 9 && TimeMinute(NowDate_WO_ST) == 15 && Entry_Rule1(2)==2 ){ SellEntryFlg = true; }else if(TimeHour(NowDate_WO_ST) == 15 && TimeMinute(NowDate_WO_ST) == 50){ SellCloseFlg = true; } } // 保有中のロング・ショートポジションがある場合、決済条件に一致したらクローズ処理 if(NowBuyCount > 0 && BuyCloseFlg == true){ resB = ClosePosition(OP_BUY); } if(NowSellCount > 0 && SellCloseFlg == true){ resB = ClosePosition(OP_SELL); } // 取引可能なステータスで、エントリー条件に一致したら新規ポジションをオーダー if(TradeAllowedFlag == true && AshiKakuteiFlg == true){ // if(NowBuyCount == 0 && BuyEntryFlg == true){ if(NowBuyCount <= 1 && BuyEntryFlg == true){ resI = OpenPosition(OP_BUY); }else if(NowSellCount == 0 && SellEntryFlg == true){ resI = OpenPosition(OP_SELL); } } } // エントリーしたポジションに対してTP/SLを設定 SetTPandSL(); } Comment(CommentText); } // ■■■ サブ関数 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ //+------------------------------------------------------------------+ //| アカウント認証チェック | //+------------------------------------------------------------------+ bool IsValidAccount(){ // ---口座認証機能ONの場合、認証アカウントもしくはDEMO口座の場合OK if(Ninsho == true && (AccountNumber() != AccountNo && IsDemo() == false)){ Alert("Account Not Certified"); return(false); }else{ return(true); } } //+------------------------------------------------------------------+ //| 設定時間帯チェック | //+------------------------------------------------------------------+ bool isSettingTime(datetime nowDate,int starthour,int startminute,int endhour,int endminute){ string errMsg = "開始時刻と終了時刻が同じ値です。異なる値を設定してください。"; // 時分を整数で表現する(例 8:30 ⇒ 830、12:15 ⇒ 1215) int startTime = starthour * 100 + startminute; int endTime = endhour * 100 + endminute; int currentTime = TimeHour(nowDate)*100 + TimeMinute(nowDate); // 開始時間と終了時間をともに0時0分で設定した場合(全時間OKとする) if(startTime == 0 && endTime == 0){ return(true); // 日をまたがないケース }else if(startTime < endTime){ if(currentTime >= startTime && currentTime < endTime){ return(true); } // 日をまたぐケース }else if(startTime > endTime){ if(currentTime < endTime || currentTime >= startTime){ return(true); } // 同一時間を指定したケース }else{ Print(errMsg); Alert(errMsg); return(false); } return(false); } //+------------------------------------------------------------------+ //| 保有中のポジションを計算 | //+------------------------------------------------------------------+ void CalculateCurrentOrders(){ // ローカル変数宣言 int icount = 0; // ループカウンタ // 初期化処理 NowBuyCount = 0; NowSellCount = 0; // 現在アカウントで保有しているポジション数分ループ処理を行う for(icount=0; icount 5*1000) { Print("OrderSend timeout."); break; } if(orderP == OP_BUY){ // ロングエントリーオーダー送信 RefreshRates(); res = OrderSend( Symbol(), // 現在の通貨ペア OP_BUY, // ロングエントリー(成行注文) EntryLot, // ロット設定 Ask, // 現在の買値で発注 MaxSlippagePoints, // スリップページ 0, // ストップロス設定:無し 0, // リミット設定:無し EAName, // コメント(EA名) MagicNumber, // マジックナンバー 0, // 有効期限:無し clrRed); // チャート上の注文矢印の色:赤 // エントリー失敗した場合、エラーログを出力する if(res < 0){ ErrCode = GetLastError(); Print("ロングエントリーエラー: ErrorCode=",ErrCode," ,EntryRate=",DoubleToString(Ask,Digits)," ,EntryLot=",EntryLot); if(ErrCode == ERR_NOT_ENOUGH_MONEY || ErrCode == ERR_LONGS_NOT_ALLOWED) break; // 指値・逆指値注文の際は下記処理をアンコメント /*if(ErrCode == ERR_INVALID_PRICE || ErrCode == ERR_INVALID_STOPS){ break; }*/ }else{ // エントリー処理が成功した場合、各種通知を行う msg = EAName + " : " + Symbol() + " Buy Order Open."; if(AlertNotice == on) Alert(msg); if(MailNotice == on) SendMail(EAName,msg); if(PushNotice == on) SendNotification(msg); NowBuyCount++; break; } } if(orderP == OP_SELL){ // ショートエントリーオーダー送信 RefreshRates(); res = OrderSend( Symbol(), // 現在の通貨ペア OP_SELL, // ショートエントリー(成行注文) EntryLot, // ロット設定 Bid, // 現在の売値で発注 MaxSlippagePoints, // スリップページ 0, // ストップロス設定:無し 0, // リミット設定:無し EAName, // コメント(EA名) MagicNumber, // マジックナンバー 0, // 有効期限:無し clrBlue); // チャート上の注文矢印の色:青 // エントリー失敗した場合、エラーログを出力する if(res < 0){ ErrCode = GetLastError(); Print("ショートエントリーエラー: ErrorCode=",ErrCode," ,EntryRate=",DoubleToString(Bid,Digits)," ,EntryLot=",EntryLot); if(ErrCode == ERR_NOT_ENOUGH_MONEY || ErrCode == ERR_SHORTS_NOT_ALLOWED) break; // 指値・逆指値注文の際は下記処理をアンコメント /*if(ErrCode == ERR_INVALID_PRICE || ErrCode == ERR_INVALID_STOPS){ break; }*/ }else{ // エントリー処理が成功した場合、各種通知を行う msg = EAName + " : " + Symbol() + " Sell Order Open."; if(AlertNotice == on) Alert(msg); if(MailNotice == on) SendMail(EAName,msg); if(PushNotice == on) SendNotification(msg); NowSellCount++; break; } } Sleep(100); } return res; } //+------------------------------------------------------------------+ //| ロット数自動計算 | //+------------------------------------------------------------------+ double CalcAutoLot(){ double AutoLot = 0; // 自動算出ロット数 double DivideAmt = 0; // 残高とクレジットの合算金額を取得 double ZCAmount = AccountBalance() + AccountCredit(); // ロット数を算出 if(ZCAmount > 0 && LotsIncreaceAmt > 0){ AutoLot = RoundDown(ZCAmount/LotsIncreaceAmt,0)*LotsIncreaceStep; }else{ AutoLot = 0; } // 算出したロット数の調整 AutoLot = NormalizeDouble(AutoLot,LotStepDigit); if(AutoLot <= MinLot){ AutoLot = MinLot; }else if(AutoLot >= MaxLot){ AutoLot = MaxLot; } return AutoLot; } //+------------------------------------------------------------------+ //| 切り捨てファンクション | //+------------------------------------------------------------------+ double RoundDown(double val,int digit){ return ((double)(int)(val * MathPow(10,digit))) / MathPow(10,digit); } //+------------------------------------------------------------------+ //| クローズ処理 | //+------------------------------------------------------------------+ bool ClosePosition(int orderP){ // ローカル変数宣言 int icount = 0; // ループカウンタ用 bool res = false; // OrderClose処理戻り値用 bool res2 = false; // 本ファンクション戻り値用 string msg = ""; // 通知メッセージ本文 bool BuyCloseFlg = false; // ロング決済済みフラグ bool SellCloseFlg = false; // ショート決済済みフラグ int ErrCode = 0; // エラーコード // 現在アカウントで保有しているポジション数分ループ処理を行う for(icount=OrdersTotal()-1; icount>=0; icount--){ // 注文プールからエントリー中の注文を選択する if(OrderSelect(icount,SELECT_BY_POS,MODE_TRADES) == false){ break; // 注文選択に失敗したらループ処理終了 } // 選択した注文の通貨ペア名を取得し、現在チャートの通貨ペア名と一致していないかチェック // 選択した注文のマジックナンバーを取得し、このEAのマジックナンバーと一致していないかチェック // 両方とも一致していた場合のみ決済処理実施 if(OrderSymbol() != Symbol()) continue; if(OrderMagicNumber() != MagicNumber) continue; // ループ処理開始時間(EA開始からのミリ秒)を取得 uint StartTime = GetTickCount(); while(true){ // ループ処理開始から5秒超経過したら強制的にリトライ処理終了 if(GetTickCount() - StartTime > 5*1000) { Print("OrderSend timeout."); break; } // ロングポジションのクローズ処理で、且つ選択した注文がロングポジションの場合 if(orderP == OP_BUY && OrderType() == OP_BUY){ // 処理中に大きくズレてしまった場合に備えて最新レートを取得し直し RefreshRates(); // 指定したチケットのポジションをクローズ res = OrderClose( OrderTicket(), // クローズするポジションのチケット OrderLots(), // クローズするロット数 Bid, // クローズ価格:現在の売値 MaxSlippagePoints, // スリップページ clrWhite); // チャート上の注文矢印の色:白 if(res == true){ BuyCloseFlg = true; NowBuyCount--; break; }else{ // クローズ失敗した場合、エラーログを出力する ErrCode = GetLastError(); Print("ロングクローズオーダーエラー: ErrorCode=",ErrCode," ,TicketNo=",OrderTicket()," ,CloseRate=",DoubleToString(Bid,Digits)," ,CloseLot=",OrderLots()); if(ErrCode == ERR_INVALID_TICKET) break; } // ショートポジションのクローズ処理で、且つ選択した注文がショートポジションの場合 }else if(orderP == OP_SELL && OrderType() == OP_SELL){ // 処理中に大きくズレてしまった場合に備えて最新レートを取得し直し RefreshRates(); // 指定したチケットのポジションをクローズ res = OrderClose( OrderTicket(), // クローズするポジションのチケット OrderLots(), // クローズするロット数 Ask, // クローズ価格:現在の買値 MaxSlippagePoints, // スリップページ clrWhite); // チャート上の注文矢印の色:白 if(res == true){ SellCloseFlg = true; NowSellCount--; break; }else{ // クローズ失敗した場合、エラーログを出力する ErrCode = GetLastError(); Print("ショートクローズオーダーエラー: ErrorCode=",ErrCode," ,TicketNo=",OrderTicket()," ,CloseRate=",DoubleToString(Ask,Digits)," ,CloseLot=",OrderLots()); if(ErrCode == ERR_INVALID_TICKET) break; } // 選択した注文がロング・ショートポジションの以外場合次の処理へ }else{ break; } Sleep(100); } } // クローズ処理が成功した場合、各種通知を行う if(BuyCloseFlg == true){ msg = EAName + " : " + Symbol() + " Buy Order Close."; if(AlertNotice == on) Alert(msg); if(MailNotice == on) SendMail(EAName,msg); if(PushNotice == on) SendNotification(msg); res2 = true; } if(SellCloseFlg == true){ msg = EAName + " : " + Symbol() + " Sell Order Close."; if(AlertNotice == on) Alert(msg); if(MailNotice == on) SendMail(EAName,msg); if(PushNotice == on) SendNotification(msg); res2 = true; } return res2; } //+------------------------------------------------------------------+ //| TP/SLセット処理 | //+------------------------------------------------------------------+ void SetTPandSL(){ bool res = true; // オーダーModify処理戻り値用 double LimitRate = 0; // TPレート double StopRate = 0; // SLレート int ErrCode = 0; // エラーコード int AdjPoint = 0; // 調整用ポイント数 for(int i=OrdersTotal()-1; i>=0; i--){ if(!OrderSelect(i,SELECT_BY_POS)) continue; if(OrderSymbol() != Symbol()) continue; if(OrderMagicNumber() != MagicNumber) continue; if(OrderTakeProfit() == 0 && OrderStopLoss() == 0 && (TPPoints > 0 || SLPoints > 0)){ if(OrderType() == OP_SELL){ if(TPPoints > 0){ LimitRate = OrderOpenPrice() - (TPPoints*Point()); // リミット価格= 約定価格 - 設定値pips数 }else{ LimitRate = 0; } if(SLPoints > 0){ StopRate = OrderOpenPrice() + (SLPoints*Point()); // ストップロス価格 = 約定価格 + 設定値pips数 }else{ StopRate = 0; } }else if(OrderType() == OP_BUY){ if(TPPoints > 0){ LimitRate = OrderOpenPrice() + (TPPoints*Point()); // リミット価格= 約定価格 + 設定値pips数 }else{ LimitRate = 0; } if(SLPoints > 0){ StopRate = OrderOpenPrice() - (SLPoints*Point()); // ストップロス価格 = 約定価格 - 設定値pips数 }else{ StopRate = 0; } }else{ continue; } LimitRate = NormalizeDouble(LimitRate,Digits); // リミット価格を正規化 StopRate = NormalizeDouble(StopRate ,Digits); // ストップロス価格を正規化 // ループ処理開始時間(EA開始からのミリ秒)を取得 uint StartTime = GetTickCount(); AdjPoint = 0; while(true){ // ループ処理開始から5秒超経過したら強制的にリトライ処理終了 if(GetTickCount() - StartTime > 5*1000) { Print("OrderModify timeout."); break; } RefreshRates(); res = OrderModify(OrderTicket(),OrderOpenPrice(),StopRate,LimitRate,OrderExpiration(),clrBlue); if(res == false){ ErrCode = GetLastError(); Print("TP/SLセット処理エラー: ErrorCode=",ErrCode," ,TP=",LimitRate," ,SL=",StopRate); // TP/SL値がストップレベル未満の場合は微調整する if(ErrCode == ERR_INVALID_STOPS){ int StopLevel = (int)MarketInfo(Symbol(),MODE_STOPLEVEL); if(OrderType() == OP_SELL){ if(LimitRate > 0 && (Bid - ((StopLevel+AdjPoint)*Point)) < LimitRate){ LimitRate = Bid - ((StopLevel+AdjPoint)*Point); } if(StopRate > 0 && (Ask + ((StopLevel+AdjPoint)*Point)) > StopRate){ StopRate = Ask + ((StopLevel+AdjPoint)*Point); } }else if(OrderType() == OP_BUY){ if(LimitRate > 0 && (Ask + ((StopLevel+AdjPoint)*Point)) > LimitRate){ LimitRate = Ask + ((StopLevel+AdjPoint)*Point); } if(StopRate > 0 && (Bid - ((StopLevel+AdjPoint)*Point)) < StopRate){ StopRate = Bid - ((StopLevel+AdjPoint)*Point); } } AdjPoint++; } }else{ break; } Sleep(100); } } } } //+------------------------------------------------------------------+ //| サーバータイム変換 | //+------------------------------------------------------------------+ datetime ServerToLocalTime(datetime ServerTime){ datetime LocalTime = 0; // サマータイム期間かどうかを判定して、渡されたサーバー時間からローカル時間を算出 if(JudgeDST == on && IsDST(TimeCurrent()) == true){ LocalTime = ServerTime + ((TimeDiff-1)*60*60); }else{ LocalTime = ServerTime + (TimeDiff*60*60); } return LocalTime; } //+------------------------------------------------------------------+ //| サーバータイム変換 ※サマータイム未考慮 | //+------------------------------------------------------------------+ datetime ServerToLocalTime_WO_ST(datetime ServerTime){ datetime LocalTime2 = 0; LocalTime2 = ServerTime + (TimeDiff*60*60); return LocalTime2; } //+------------------------------------------------------------------+ //| サマータイム判定 | //+------------------------------------------------------------------+ bool IsDST(datetime CurrentTime){ datetime StartDate; datetime EndDate; bool DST; string CurrentYear = (string)(TimeYear(CurrentTime)); if((int)CurrentYear >= 2007 && AccountStandard == USStandard){ StartDate = (datetime)(CurrentYear + ".3." + (string)(14 - TimeDayOfWeek((datetime)(CurrentYear + ".3.14")))); EndDate = (datetime)(CurrentYear + ".11." + (string)(7 - TimeDayOfWeek((datetime)(CurrentYear + ".11.7")))); }else{ if(AccountStandard == UKStandard){ StartDate = (datetime)(CurrentYear + ".3." + (string)(31 - TimeDayOfWeek((datetime)(CurrentYear + ".3.31")))); }else{ StartDate = (datetime)(CurrentYear + ".4." + (string)(7 - TimeDayOfWeek((datetime)(CurrentYear + ".4.7")))); } EndDate = (datetime)(CurrentYear + ".10." + (string)(31 - TimeDayOfWeek((datetime)(CurrentYear + ".10.31")))); } if(CurrentTime >= StartDate && CurrentTime < EndDate) DST = true; else DST = false; return DST; } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| エントリールール1 | //+------------------------------------------------------------------+ int Entry_Rule1(int LS) { //エントリールール1を差し替える時は、下記を差し替えて下さい。 if (LS==1 &&((Trend_Judge(Trend_period1_L,Trend_period2_L)>=2 && Kairi_Judge(Trend_period2_L)<= Kairi_Judge_percent1_L )|| Kairi_Judge(Trend_period2_L)<= -Kairi_Judge_percent2_L)) // if ((Trend_Judge()<=1 && Kairi_Judge()>= -Kairi_Judge_percent1 )|| Kairi_Judge()>= Kairi_Judge_percent2) { return(1); } // 売り else if (LS==2 &&((Trend_Judge(Trend_period1_S,Trend_period2_S)<=1 && Kairi_Judge(Trend_period2_S)>= -Kairi_Judge_percent1_S )|| Kairi_Judge(Trend_period2_S)>= Kairi_Judge_percent2_S)) // if ((Trend_Judge()<=1 && Kairi_Judge()>= -Kairi_Judge_percent1 )|| Kairi_Judge()>= Kairi_Judge_percent2) { return(2); } // 売り else { return(0); } //エントリールール1を差し替える時は、ココマデを差し替えて下さい。 } //+------------------------------------------------------------------+ int Trend_Judge(int period1,int period2) //int Trend_Judge() { double MA_Middle1 = iMA(NULL,PERIOD_H1,period1, 0, MODE_SMA, PRICE_CLOSE, 1); double MA_Long1 = iMA(NULL,PERIOD_H1,period2, 0, MODE_SMA, PRICE_CLOSE, 1); double MA_Middle2 = iMA(NULL,PERIOD_H1,period1, 0, MODE_SMA, PRICE_CLOSE, 3); double MA_Long2 = iMA(NULL,PERIOD_H1,period2, 0, MODE_SMA, PRICE_CLOSE, 3); int UP_Trend = 0; //アップトレンドを0~3段階評価 if (MA_Middle1 > MA_Long1) { UP_Trend = UP_Trend+1; } if (MA_Middle1-MA_Middle2 > 0) { UP_Trend = UP_Trend+1; } if (MA_Long1-MA_Long2 > 0) { UP_Trend = UP_Trend+1; } return(UP_Trend); } double Kairi_Judge(int period2) //double Kairi_Judge() { // 長期移動平均線に対し短期移動平均線が、指定%以上、上に乖離したら「売り」、下に乖離したら「買い」。 double MA1 = iMA(NULL,PERIOD_M5, 3, 0, MODE_SMA, PRICE_CLOSE, 1); double MA2 = iMA(NULL,PERIOD_H1, period2, 0, MODE_SMA, PRICE_CLOSE, 1); double Long_Kairi = (MA1-MA2)/iClose(NULL,PERIOD_M5,1)*100; return(Long_Kairi); }