947 lines
No EOL
70 KiB
MQL4
947 lines
No EOL
70 KiB
MQL4
//+------------------------------------------------------------------+
|
||
//| 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);
|
||
} |