//+------------------------------------------------------------------+ //| MovingAverageJP.mq4 | //| Copyright 2015, yuki. | //| http:yukifx.web.fc2.com/ | //+------------------------------------------------------------------+ #property copyright "Copyright 2015, yuki." // 作成者名 #property link "https://yukifx.web.fc2.com/" // Webサイトリンク #property version "1.00" // バージョン #property strict // 厳格なコンパイルモード #property description "移動平均サンプルEA" // EA説明文 #define MAGICMA 20150520 // EA識別用マジックナンバー // 入力パラメータ宣言 input double Lots = 0.1; // ロット数[分解能:10万通貨] input int MovingPeriod = 12; // 移動平均期間 input int MovingShift = 6; // 移動平均シフト //+------------------------------------------------------------------+ //| OnInit(初期化)イベント | //+------------------------------------------------------------------+ int OnInit() { return(INIT_SUCCEEDED); // 戻り値:初期化成功 } //+------------------------------------------------------------------+ //| OnDeinit(アンロード)イベント | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { // 処理無し } //+------------------------------------------------------------------+ //| OnTick(tick受信)イベント | //+------------------------------------------------------------------+ void OnTick() { if ( IsDemo() == false ) { // デモ口座かチェック // リアル口座の場合、エラーメッセージを出力し、処理終了 MessageBox("実際に新規オーダーするので、デモ口座で動作させて下さい。","エラー",MB_ICONEXCLAMATION); return; // 処理終了 } if ( IsTradeAllowed() == false ) { // 自動売買許可設定チェック // 自動売買禁止設定の場合、エラーメッセージを出力し処理終了 MessageBox("自動売買禁止設定になっています","エラー",MB_ICONEXCLAMATION); return; // 処理終了 } if ( Bars < 100 ) { // チャート上のバー数が100本未満の場合、処理終了 return; } // 現在保有中のポジション数をチェック if ( CalculateCurrentOrders() ==0) { // ポジション保有していない場合 CheckForOpen(); // オーダー処理を行う } else { // ポジション保有している場合 CheckForClose(); // クローズ処理を行う } } // ■■■ サブ関数 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ //+------------------------------------------------------------------+ //| 保有中のポジションを計算 | //+------------------------------------------------------------------+ int CalculateCurrentOrders( void ) { // ローカル変数宣言 int buys=0; // ロングポジション保有数 int sells=0; // ショートポジション保有数 int icount; // ループカウンタ // 現在アカウントで保有しているポジション数分ループ処理を行う for ( icount = 0 ; icount < OrdersTotal() ; icount++) { // 注文プールからエントリー中の注文を選択する if( OrderSelect(icount,SELECT_BY_POS,MODE_TRADES) == false) { break; // 注文選択に失敗したらループ処理終了 } // 選択した注文の通貨ペア名を取得し、現在チャートの通貨ペア名と一致しているかチェック // 選択した注文のマジックナンバーを取得し、このEAのマジックナンバーと一致しているかチェック // 上記の両方の条件に一致した場合のみif文内の処理を行う if( OrderSymbol() == Symbol() && OrderMagicNumber() == MAGICMA) { if(OrderType()==OP_BUY) { // 選択した注文がロングポジションの場合 buys++; // ローカル変数buysをインクリメント(1加算) } if(OrderType()==OP_SELL) { // 選択した注文がショートポジションの場合 sells++; // ローカル変数sellsをインクリメント(1加算) } } } // 関数戻り値を設定 if( buys > 0) { // ロングポジション保有数が1つ以上の場合 return(buys); // ローカル変数buysの値を関数戻り値として返す } else { // ロングポジション保有数が0以下の場合 return(-sells); // ローカル変数sellsに負符号をつけて、関数戻り値として返す } } //+------------------------------------------------------------------+ //| オーダー処理 | //+------------------------------------------------------------------+ void CheckForOpen() { // ローカル変数宣言 double ma; // 単純移動平均用 int res; // オーダー送信戻り値用 double entrylot; // オーダー用ロット if( Volume[0] > 1) { // 現在のtick出来高が2以上の場合は関数処理終了 return; } if ( IsDemo() == false ) { // デモ口座かチェック // リアル口座の場合、エラーメッセージを出力し、処理終了 MessageBox("実際に新規オーダーするので、デモ口座で動作させて下さい。","エラー",MB_ICONEXCLAMATION); return; // 処理終了 } entrylot = NormalizeDouble(Lots,1); // 入力パラメータのロット数を、小数点第一位で正規化 // テクニカルインジケータ:移動平均の値を算出 ma = iMA( NULL, // 現在の通貨ペア 0, // 現在の時間軸 MovingPeriod, // 入力パラメ―タで指定した移動平均期間 MovingShift, // 入力パラメータで指定した移動平均シフト MODE_SMA, // 平滑化タイプ:単純移動平均 PRICE_CLOSE, // 終値で算出 0); // シフト:無し // 1つ前のバーの始値が移動平均値より大きい 且つ // 1つ前のバーの終値が移動平均値よりも小さい場合 if( Open[1] > ma && Close[1] < ma) { // ショートエントリーオーダー送信 res = OrderSend( Symbol(), // 現在の通貨ペア OP_SELL, // ショートエントリー(成行注文) entrylot, // ロット設定 Bid, // 現在の売値で発注 3, // スリップページ 0, // ストップロス設定:無し 0, // リミット設定:無し "ショート", // コメント MAGICMA, // マジックナンバー 0, // 有効期限:無し clrRed); // チャート上の注文矢印の色:赤 return; // 関数処理終了 } // 1つ前のバーの始値が移動平均値より小さい 且つ // 1つ前のバーの終値が移動平均値よりも大きい場合 if ( Open[1] < ma && Close[1] > ma ) { res = OrderSend( Symbol(), // 現在の通貨ペア OP_BUY, // ロングエントリー(成行注文) entrylot, // ロット設定 Ask, // 現在の買値で発注 3, // スリップページ 0, // ストップロス設定:無し 0, // リミット設定:無し "ロング", // コメント MAGICMA, // マジックナンバー 0, // 有効期限:無し clrBlue); // チャート上の注文矢印の色:青 return; // 関数処理終了 } } //+------------------------------------------------------------------+ //| クローズ処理 | //+------------------------------------------------------------------+ void CheckForClose() { // ローカル変数宣言 double ma; // 単純移動平均用 int icount; // ループカウンタ用 bool ret; // クローズ処理戻り値用 if ( Volume[0] > 1 ) { // 現在のtick出来高が2以上の場合は関数処理終了 return; } // テクニカルインジケータ:移動平均の値を算出 ma = iMA( NULL, // 現在の通貨ペア 0, // 現在の時間軸 MovingPeriod, // 入力パラメ―タで指定した移動平均期間 MovingShift, // 入力パラメータで指定した移動平均シフト MODE_SMA, // 平滑化タイプ:単純移動平均 PRICE_CLOSE, // 終値で算出 0); // シフト:無し // 現在アカウントで保有しているポジション数分ループ処理を行う for( icount = 0; icount < OrdersTotal(); icount++) { // 注文プールからエントリー中の注文を選択する if( OrderSelect( icount, SELECT_BY_POS, MODE_TRADES ) == false ) { break; // 注文選択に失敗したらループ処理終了 } // 選択した注文の通貨ペア名を取得し、現在チャートの通貨ペア名と一致していないかチェック // 選択した注文のマジックナンバーを取得し、このEAのマジックナンバーと一致していないかチェック // 上記のいずれかの条件に一致した場合のみif文内の処理を行う if( OrderMagicNumber() != MAGICMA || OrderSymbol() != Symbol()) { continue; // 次のループ処理を行う } // 選択した注文がロングポジションの場合 if( OrderType() == OP_BUY) { // 1つ前のバーの始値が移動平均値より大きい 且つ // 1つ前のバーの終値が移動平均値よりも小さい場合 if( Open[1] > ma && Close[1] < ma ) { // 指定したチケットのポジションをクローズ ret = OrderClose( OrderTicket(), // クローズするポジションのチケット OrderLots(), // クローズするロット数 Bid, // クローズ価格:現在の売値 3, // スリップページ clrWhite); // チャート上の注文矢印の色:白 // クローズ失敗した場合、エラーログを出力する if( ret == false ){ Print("オーダークローズエラー:エラーコード=",GetLastError()); } } // ループ処理終了 break; } // 選択した注文がショートポジションの場合 if( OrderType() == OP_SELL) { // 1つ前のバーの始値が移動平均値より小さい 且つ // 1つ前のバーの終値が移動平均値よりも大きい場合 if( Open[1] < ma && Close[1] > ma ) { // 指定したチケットのポジションをクローズ ret = OrderClose( OrderTicket(), // クローズするポジションのチケット OrderLots(), // クローズするロット数 Ask, // クローズ価格:現在の買値 3, // スリップページ clrWhite); // チャート上の注文矢印の色:白 // クローズ失敗した場合、エラーログを出力する if( ret == false ){ Print("オーダークローズエラー:エラーコード=",GetLastError()); } } // ループ処理終了 break; } } }