gryps2/EA-code/Yoritsugu/EA510_v07.mq4
super.admin ae3f0ebf03 convert
2025-05-30 14:58:21 +02:00

947 lines
No EOL
70 KiB
MQL4
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//+------------------------------------------------------------------+
//| 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<OrdersTotal(); icount++){
// 注文プールからエントリー中の注文を選択する
if(OrderSelect(icount,SELECT_BY_POS,MODE_TRADES) == false){
break; // 注文選択に失敗したらループ処理終了
}
// 選択した注文の通貨ペア名・マジックナンバーが現在チャートの通貨ペア名・EAマジックナンバーと一致しているもののみ処理
if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber){
// 選択した注文がロングポジションの場合
if(OrderType()==OP_BUY){
// 注文数を取得
NowBuyCount++;
}
// 選択した注文がショートポジションの場合
if(OrderType()==OP_SELL){
// 注文数を取得
NowSellCount++;
}
}
}
}
//+------------------------------------------------------------------+
//| オーダー処理 |
//+------------------------------------------------------------------+
int OpenPosition(int orderP){
// ローカル変数宣言
int res = 0; // オーダー送信戻り値用
double EntryLot = 0; // オーダー用ロット
string msg = ""; // 通知メッセージ本文
int ErrCode = 0; // エラーコード
// オーダーロット数を算出
if(FukuriOnOff == on){
EntryLot = CalcAutoLot();
}else{
EntryLot = DefaultLots;
}
// ループ処理開始時間(EA開始からのミリ秒)を取得
uint StartTime = GetTickCount();
while(true){
// ループ処理開始から5秒超経過したら強制的にリトライ処理終了
if(GetTickCount() - StartTime > 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);
}