//+------------------------------------------------------------------+
//|                                    Aki0307_Window_Open_00X_2.mq4 |
//|                                        Copyright ｩ 2009, Aki0307 |
//|                                  http://aki0307.blog.shinobi.jp/ |
//+------------------------------------------------------------------+
#property copyright "Copyright ｩ 2009, Aki0307"
#property link      "http://aki0307.blog.shinobi.jp/"

//エントリーするPip
extern int iEntryPip=20;

//スリップページ
extern int iSlip=3;

//ロット数
extern double dLots=0.1;

// マジックNo
extern int iMagicNo = 0517001;

//オープンする曜日
extern int iOpenDayOfWeek=1;

//オープンする時間
extern int iOpenTimeHour=6;

//クローズする曜日
extern int iCloseDayOfWeek=3;

//マネーマネージメント用
extern bool bMM = false;
extern double dRisk = 1.0;
extern double dVs_Usd = 0.01;
extern double dMax_Lots = 50.0;
extern double dMin_Lots = 0.1;

//注文リトライ用
extern int iRetry_Cnt = 1;
extern int iWait_Time = 10;

// 時間足用
datetime dtTimeFrame = 0;

//エントリーするPip(実態)
double dEntryPip=0.0;

//ロット数(実態)
double dEntry_Lots=0.1;

// エントリーフラグ
bool bEntryFlg = false;

// ロングフラグ（falseならショート）
bool bLong = false;

//リミット値(実態)
double dEntry_Limits=0.0;


// ログファイル名
string sLogFileName = "";


////////////////////////////////////////////////////////////////////
// expert initialization function
////////////////////////////////////////////////////////////////////
int init(){
    dEntryPip = iEntryPip * Point;

    // ファイル名を生成する（EA名+YYYYMMDD)
    sLogFileName = "Aki0307_Window_Open_00X_"+TimeYear(TimeLocal())+TimeMonth(TimeLocal())+TimeDay(TimeLocal())+".csv";

    return(0);
}

////////////////////////////////////////////////////////////////////
// expert deinitialization function
////////////////////////////////////////////////////////////////////
int deinit(){
   return(0);
}

////////////////////////////////////////////////////////////////////
// expert start function
////////////////////////////////////////////////////////////////////
int start(){

    int iDayOfWeek = 0;
    int iRet = 0;

    // 有効チェック
    if(IsConnected() != TRUE){
        return (0);
    }

    // トレード可能チェック
    if(IsTradeContextBusy() != false){
        return (0);
    }

    // 今の時間を取得時間足に変化があると中に入る
    if(dtTimeFrame<iTime(NULL,0,0)) {
        dtTimeFrame=iTime(NULL,0,0);
        
        // 曜日を取得
        iDayOfWeek = TimeDayOfWeek(TimeCurrent());

        // クローズ曜日と時間か判定
        if(iCloseDayOfWeek == iDayOfWeek){
            Ordclose();
        }

        //エントリー曜日か？
        if(iOpenDayOfWeek == iDayOfWeek){

            //1本前の終値と現在の足の始値がエントリPipより離れていたらフラグを出す
            if(Close[1] < Open[0]){
                if(Open[0] - Close[1] >= dEntryPip){
                    Ordclose();
                    call_MM();
                    bEntryFlg = true;
                    bLong = false;
                    dEntry_Limits = Close[1];
//                    Aki0307_OrderSend(Symbol(), OP_SELL, dEntry_Lots, Bid, iSlip, 0.0, Close[1], "売り注文", iMagicNo, 0, Blue);
                }
            }else{
                if(Close[1] - Open[0] >= dEntryPip){
                    Ordclose();
                    call_MM();
                    bEntryFlg = true;
                    bLong = true;
                    dEntry_Limits = Close[1] + Ask - Bid;
//                    Aki0307_OrderSend(Symbol(), OP_BUY, dEntry_Lots, Ask, iSlip, 0.0, Close[1] + Ask - Bid, "買い注文", iMagicNo, 0, Blue);
                }
            }
        }
    }

    if(bEntryFlg == true){
        // 曜日と時間を取得
        iDayOfWeek = TimeDayOfWeek(TimeCurrent());
        int iTimeHour = TimeHour(TimeCurrent());

        if(iOpenDayOfWeek == iDayOfWeek && iOpenTimeHour == iTimeHour){
            if(bLong == true){
                iRet = Aki0307_OrderSend(Symbol(), OP_BUY, dEntry_Lots, Ask, iSlip, 0.0, dEntry_Limits, "買い注文", iMagicNo, 0, Blue);
                if(iRet != -1){
                    bEntryFlg = false;
                }
            } else {
                iRet = Aki0307_OrderSend(Symbol(), OP_SELL, dEntry_Lots, Bid, iSlip, 0.0, dEntry_Limits, "売り注文", iMagicNo, 0, Blue);
                if(iRet != -1){
                    bEntryFlg = false;
                }
            }
        } else {
            bEntryFlg = false;
        }

    }

    Aki0307_PrintDetails();
    return(0);
}
//+------------------------------------------------------------------+
////////////////////////////////////////////////////////////////////
// EA状態表示
////////////////////////////////////////////////////////////////////
void  Aki0307_PrintDetails()
{
   string sComment   = "";
   string sp         = "----------------------------------------\n";
   string NL         = "\n";
	string sDirection = "";
   sComment = "Aki0307_Window_Open_001" + NL;
   sComment = sComment + sp;   
   sComment = sComment + "Open[1]=" + DoubleToStr(Open[1],Digits) + " | "; 
   sComment = sComment + "Close[1]=" + DoubleToStr(Close[1],Digits) + " | "; 
   sComment = sComment + "High[1]=" + DoubleToStr(High[1],Digits) + " | "; 
   sComment = sComment + "Low[1]=" + DoubleToStr(Low[1],Digits) + NL; 
   sComment = sComment + sp;   
   sComment = sComment + "Open[0]=" + DoubleToStr(Open[0],Digits) + " | "; 
   sComment = sComment + "Close[0]=" + DoubleToStr(Close[0],Digits) + " | "; 
   sComment = sComment + "High[0]=" + DoubleToStr(High[0],Digits) + " | "; 
   sComment = sComment + "Low[0]=" + DoubleToStr(Low[0],Digits) + NL; 
   sComment = sComment + sp;   
   Comment(sComment);
}

////////////////////////////////////////////////////////////////////
// OrderSend機能（リトライ機能つき）
////////////////////////////////////////////////////////////////////
int Aki0307_OrderSend(string sSymbol, int iCmd, double dVolume, double dPrice, int iSlippage, double dStoploss, double dTakeprofit, string sComment="", int iMagic=0, datetime dExpiration=0, color cColor=CLR_NONE){
    // 復帰値
    int iRet = 0;
    // 現在の価格
    int iBid = Bid;

    //ファイルハンドル
    int iHandle=0; 

    int iErrorCode = 0;

    // リトライ回数に関係なく、指定されたパラメータでOrderSendを呼び出す
    iRet = OrderSend(sSymbol, iCmd, dVolume, dPrice, iSlippage, dStoploss, dTakeprofit, sComment, iMagic, dExpiration, cColor);
    if(iRet == -1){
        iErrorCode = GetLastError();
        Print("Aki0307_OrderSend Error:",iErrorCode);
        iHandle = FileOpen(sLogFileName,FILE_READ|FILE_WRITE|FILE_CSV,'\t');
        FileSeek(iHandle, 0, SEEK_END);
        FileWrite(iHandle,TimeToStr(TimeCurrent(), TIME_DATE),TimeToStr(TimeCurrent(), TIME_SECONDS), "Aki0307_OrderSend", sSymbol, iCmd, dVolume, dPrice, iSlippage, dStoploss, dTakeprofit, sComment, iMagic, dExpiration, cColor, iErrorCode);
        FileClose(iHandle);

        // 1回目のOrderSendがエラーになったら、通るまでリトライ回数分OrderSendを呼び出す
        for(int iCnt = 0; iCnt < iRetry_Cnt; iCnt++){
            //まずは間隔をあける
            Sleep(iWait_Time);

            // OrderSend呼び出し。注文価格は、現在の価格と現在の最新価格との差を反映させる
            iRet = OrderSend(sSymbol, iCmd, dVolume, dPrice + iBid - MarketInfo(sSymbol, MODE_BID), iSlippage, dStoploss, dTakeprofit, sComment, iMagic, dExpiration, cColor);
            if(iRet == -1){
                iErrorCode = GetLastError();
                Print("Aki0307_OrderSend Error:",iErrorCode," iCnt:", iCnt);
                iHandle = FileOpen(sLogFileName,FILE_READ|FILE_WRITE|FILE_CSV,'\t');
                FileSeek(iHandle, 0, SEEK_END);
                FileWrite(iHandle,TimeToStr(TimeCurrent(), TIME_DATE),TimeToStr(TimeCurrent(), TIME_SECONDS), "Aki0307_OrderSendRetry", iCnt, sSymbol, iCmd, dVolume, dPrice + iBid - MarketInfo(sSymbol, MODE_BID), iSlippage, dStoploss, dTakeprofit, sComment, iMagic, dExpiration, cColor, iErrorCode);
                FileClose(iHandle);
            } else {
                iHandle = FileOpen(sLogFileName,FILE_READ|FILE_WRITE|FILE_CSV,'\t');
                FileSeek(iHandle, 0, SEEK_END);
                FileWrite(iHandle,TimeToStr(TimeCurrent(), TIME_DATE),TimeToStr(TimeCurrent(), TIME_SECONDS), "Aki0307_OrderSendRetryOK", iCnt, sSymbol, iCmd, dVolume, dPrice + iBid - MarketInfo(sSymbol, MODE_BID), iSlippage, dStoploss, dTakeprofit, sComment, iMagic, dExpiration, cColor);
                FileClose(iHandle);
                iCnt = iRetry_Cnt;
            }
            // 現在の価格を置き換え
            iBid = MarketInfo(sSymbol, MODE_BID);
        }
    }

    return(iRet);
}
////////////////////////////////////////////////////////////////////
// 注文とポジションのクローズ
////////////////////////////////////////////////////////////////////
int Ordclose(){
    // 持っている注文数を取得
    int iTotal = OrdersTotal();

    // 注文があればポジションクローズと注文のキャンセルを実施
    if(iTotal > 0){
        for(int i = iTotal -1; i >= 0; i-- ){
            // オーダー特定
            bool bSelected = OrderSelect(i, SELECT_BY_POS, MODE_TRADES);
            // マジックNoを判定して、自分が出したオーダーかチェック
            if(bSelected == true && OrderMagicNumber() == iMagicNo){
                // オーダーの種類を特定
                int iType = OrderType();
                switch(iType){
                    // Longポジション
                    case OP_BUY:
                        Aki0307_OrderClose(OrderTicket(), OrderLots(), Bid, iSlip, LawnGreen);
                        break;
                    // Shortポジション
                    case OP_SELL:
                        Aki0307_OrderClose(OrderTicket(), OrderLots(), Ask, iSlip, LawnGreen);
                        break;
                    // 注文中（指値買、指値売、逆指値買、逆指値売）
                    case OP_BUYLIMIT:
                    case OP_BUYSTOP:
                    case OP_SELLLIMIT:
                    case OP_SELLSTOP:
                        Aki0307_OrderDelete(OrderTicket());
                        break;
                }
            }
        }
    }
}
////////////////////////////////////////////////////////////////////
// OrderClose機能（リトライ機能つき）
////////////////////////////////////////////////////////////////////
bool Aki0307_OrderClose(int iTicket, double dLots, double dPrice, int iSlippage, color cColor=CLR_NONE){
    // 復帰値
    bool bRet = false;
    // 現在の価格
    int iBid = Bid;

    //ファイルハンドル
    int iHandle=0; 

    int iErrorCode = 0;

    // リトライ回数に関係なく、指定されたパラメータでOrderCloseを呼び出す
    bRet = OrderClose(iTicket, dLots, dPrice, iSlippage, cColor);
    if(bRet == false){
        iErrorCode = GetLastError();
        Print("Aki0307_OrderClose Error:",iErrorCode);
        iHandle = FileOpen(sLogFileName,FILE_READ|FILE_WRITE|FILE_CSV,'\t');
        FileSeek(iHandle, 0, SEEK_END);
        FileWrite(iHandle,TimeToStr(TimeCurrent(), TIME_DATE),TimeToStr(TimeCurrent(), TIME_SECONDS), "Aki0307_OrderClose", iTicket, dLots, dPrice, iSlippage, cColor, iErrorCode);
        FileClose(iHandle);

        // 1回目のOrderCloseがエラーになったら、通るまでリトライ回数分OrderCloseを呼び出す
        for(int iCnt = 0; iCnt < iRetry_Cnt; iCnt++){
            //まずは間隔をあける
            Sleep(iWait_Time);

            // OrderClose呼び出し。注文価格は、現在の価格と現在の最新価格との差を反映させる
            bRet = OrderClose(iTicket, dLots, dPrice + iBid - MarketInfo(Symbol(), MODE_BID), iSlippage, cColor);
            if(bRet == false){
                iErrorCode = GetLastError();
                Print("Aki0307_OrderClose Error:",iErrorCode," iCnt:", iCnt);
                iHandle = FileOpen(sLogFileName,FILE_READ|FILE_WRITE|FILE_CSV,'\t');
                FileSeek(iHandle, 0, SEEK_END);
                FileWrite(iHandle,TimeToStr(TimeCurrent(), TIME_DATE),TimeToStr(TimeCurrent(), TIME_SECONDS), "Aki0307_OrderCloseRetry", iCnt, iTicket, dLots, dPrice + iBid - MarketInfo(Symbol(), MODE_BID), iSlippage, cColor, iErrorCode);
                FileClose(iHandle);
            } else {
                iHandle = FileOpen(sLogFileName,FILE_READ|FILE_WRITE|FILE_CSV,'\t');
                FileSeek(iHandle, 0, SEEK_END);
                FileWrite(iHandle,TimeToStr(TimeCurrent(), TIME_DATE),TimeToStr(TimeCurrent(), TIME_SECONDS), "Aki0307_OrderCloseRetryOK", iCnt, iTicket, dLots, dPrice + iBid - MarketInfo(Symbol(), MODE_BID), iSlippage, cColor);
                FileClose(iHandle);
                iCnt = iRetry_Cnt;
            }
            // 現在の価格を置き換え
            iBid = MarketInfo(Symbol(), MODE_BID);
        }
    }

    return(bRet);
}

////////////////////////////////////////////////////////////////////
// OrderDelete機能（リトライ機能つき）
////////////////////////////////////////////////////////////////////
bool Aki0307_OrderDelete(int iTicket, color cColor=CLR_NONE){
    // 復帰値
    bool bRet = false;

    //ファイルハンドル
    int iHandle=0; 

    int iErrorCode = 0;

    // リトライ回数に関係なく、指定されたパラメータでOrderDeleteを呼び出す
    bRet = OrderDelete(iTicket, cColor);
    if(bRet == false){
        iErrorCode = GetLastError();
        Print("Aki0307_OrderDelete Error:",iErrorCode);
        iHandle = FileOpen(sLogFileName,FILE_READ|FILE_WRITE|FILE_CSV,'\t');
        FileSeek(iHandle, 0, SEEK_END);
        FileWrite(iHandle,TimeToStr(TimeCurrent(), TIME_DATE),TimeToStr(TimeCurrent(), TIME_SECONDS), "Aki0307_OrderDelete", iTicket, cColor, iErrorCode);
        FileClose(iHandle);

        // 1回目のOrderDeleteがエラーになったら、通るまでリトライ回数分OrderDeleteを呼び出す
        for(int iCnt = 0; iCnt < iRetry_Cnt; iCnt++){
            //まずは間隔をあける
            Sleep(iWait_Time);

            // OrderDelete呼び出し。
            bRet = OrderDelete(iTicket, cColor);
            if(bRet == false){
                iErrorCode = GetLastError();
                Print("Aki0307_OrderDelete Error:",iErrorCode," iCnt:", iCnt);
                iHandle = FileOpen(sLogFileName,FILE_READ|FILE_WRITE|FILE_CSV,'\t');
                FileSeek(iHandle, 0, SEEK_END);
                FileWrite(iHandle,TimeToStr(TimeCurrent(), TIME_DATE),TimeToStr(TimeCurrent(), TIME_SECONDS), "Aki0307_OrderDeleteRetry", iCnt, iTicket, cColor, iErrorCode);
                FileClose(iHandle);
            } else {
                iHandle = FileOpen(sLogFileName,FILE_READ|FILE_WRITE|FILE_CSV,'\t');
                FileSeek(iHandle, 0, SEEK_END);
                FileWrite(iHandle,TimeToStr(TimeCurrent(), TIME_DATE),TimeToStr(TimeCurrent(), TIME_SECONDS), "Aki0307_OrderDeleteRetryOK", iCnt, iTicket, cColor);
                FileClose(iHandle);
                iCnt = iRetry_Cnt;
            }
        }
    }

    return(bRet);
}

////////////////////////////////////////////////////////////////////
// マネーマネージメント
////////////////////////////////////////////////////////////////////
double call_MM(){
    if(bMM == true){
        dEntry_Lots = AccountEquity()*dVs_Usd/100000*dRisk;
        dEntry_Lots = MathMin(dMax_Lots,MathMax(dMin_Lots,dEntry_Lots));
        dEntry_Lots = NormalizeDouble(dEntry_Lots,1);
    }else{
        dEntry_Lots = dLots;
    }

    return(dEntry_Lots);
}

