MetaQuotes社のMoving AverageのサンプルEAを解説(識別番号20131111)(MQL4)

MetaQuotes社のMoving AverageのサンプルEAをコメント解説しています。

//+------------------------------------------------------------------+
//|                                               Moving Average.mq4 |
//|                   Copyright 2005-2014, MetaQuotes Software Corp. |
//|                                              http://www.mql4.com |
//+------------------------------------------------------------------+
#property copyright   "2005-2014, MetaQuotes Software Corp."
#property link        "http://www.mql4.com"
#property description "移動平均線EA"
#property description "日本語翻訳-最大ポジション保有数は1つ"

//--- 定数のマジックナンバー
#define MAGICMA  20131111

//--- 入力変数(外部変数)
//--- ロット数
input double Lots          =0.1;
//--- リスクロット調整(%)
input double MaximumRisk   =0.02;
//--- ロット減少調整数値
input double DecreaseFactor=3;
//--- 移動平均線の期間
input int    MovingPeriod  =12;
//--- 移動平均線のシフト
input int    MovingShift   =6;
//+------------------------------------------------------------------+
//| 保有中のポジションの計算                                              |
//+------------------------------------------------------------------+
int CalculateCurrentOrders(string symbol){
	//--- ポジションの数を0で初期化(買、売)
	int buys=0,sells=0;

	//--- 全ての保有中&待機中のポジションを検索
	for(int i=0;i< OrdersTotal();i++){
		//--- ポジションを選択出来なければループを抜ける
		if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) break;
		//--- 注文時の通貨ペアとマジックナンバーを検証
		if(OrderSymbol()==Symbol() && OrderMagicNumber()==MAGICMA){
			//--- ポジションが買ポジションならばbuysに+1
			if(OrderType()==OP_BUY)  buys++;
			//--- ポジションが売りポジションならばsellsに+1
			if(OrderType()==OP_SELL) sells++;
		}
	}//ループ終了
	
	//--- ポジションの数を返す
	if(buys>0) return(buys);   //--- 買いポジションの数
	else       return(-sells); //--- 売りポジションの数(-をつけて返す)
}
//+------------------------------------------------------------------+
//| ロットの計算                                                        |
//+------------------------------------------------------------------+
double LotsOptimized(){
	double lot=Lots;
	int    orders=HistoryTotal();     // 全ポジション履歴
	int    losses=0;                  // 負数を入れる変数(0で初期化)
	//--- 余剰証拠金×リスク%÷1000の答えを少数点第1位に丸める
	lot=NormalizeDouble(AccountFreeMargin()*MaximumRisk/1000.0,1);
	//--- ロットの減少調整数値がが0以上ならば
	if(DecreaseFactor>0){
		for(int i=orders-1;i>=0;i--){
			//--- ポジションの履歴がない場合ループを抜ける
			if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)==false){
				Print("Error in history!");
				break;
			}
			
			//--- 注文時の通貨ペアと開いて選択している通貨ペアが違う
			//--- 又は
			//--- 保留中の注文の削除履歴の場合。次へ
			if(OrderSymbol()!=Symbol() || OrderType()>OP_SELL) continue;
			
			//--- 利益が出ていたらループを抜ける
			if(OrderProfit()>0) break;
			//--- 損失ならlossesに+1
			if(OrderProfit()<0) losses++;
		}//ループ終了
		
		//--- 連敗が1より多ければ
		if(losses>1){
			//--- ロットの数を再調整
			lot=NormalizeDouble(lot-lot*losses/DecreaseFactor,1);
		}
	}
	//--- ロット数が0.1未満なら0.1をロットにする
	if(lot<0.1) lot=0.1;
	//--- ロット数を返す
	return(lot);
}
//+------------------------------------------------------------------+
//| エントリー関数                                                      |
//+------------------------------------------------------------------+
void CheckForOpen(){
	//--- 移動平均線の値を格納する変数を宣言
	double ma;
	//--- 注文の返り値を入れる変数を宣言
	int    res;
	
	//--- 現在の出来高が1より大きければ処理終了
	if(Volume[0]>1) return;
	
	//--- 移動平均線の値を取得
	ma=iMA(NULL,0,MovingPeriod,MovingShift,MODE_SMA,PRICE_CLOSE,0);
	
	//--- 売りのエントリー条件
	if(Open[1]>ma && Close[1]< ma){
		//--- エントリー      
		res=OrderSend(Symbol(),OP_SELL,LotsOptimized(),Bid,3,0,0,"",MAGICMA,0,Red);
		return;
	}
	//--- 買いのエントリー条件
	if(Open[1]< ma && Close[1]>ma){
		//--- エントリー
		res=OrderSend(Symbol(),OP_BUY,LotsOptimized(),Ask,3,0,0,"",MAGICMA,0,Blue);
		return;
	}
}
//+------------------------------------------------------------------+
//| クローズ関数                                                        |
//+------------------------------------------------------------------+
void CheckForClose(){
	//移動平均線の値を入れる変数を宣言
	double ma;
	//--- 現在の出来高が1より大き場合は処理終了
	if(Volume[0]>1) return;
	
	//--- 移動平均線の値を取得
	ma=iMA(NULL,0,MovingPeriod,MovingShift,MODE_SMA,PRICE_CLOSE,0);
	
	//--- 全ての保有中&待機中のポジションを検索
	for(int i=0;i< OrdersTotal();i++){
		//--- ポジションを選択できない場合ループを抜ける
		if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) break;
		
		//--- 注文時の通貨ペアとマジックナンバーが一致していない場合次へ
		if(OrderMagicNumber()!=MAGICMA || OrderSymbol()!=Symbol()) continue;
		
		//--- 買ポジションなら
		if(OrderType()==OP_BUY){
			//--- 決済条件
			if(Open[1]>ma && Close[1]< ma){
				//--- 決済処理
				if(!OrderClose(OrderTicket(),OrderLots(),Bid,3,White)){
					//--- 決済に失敗した場合にエラーを吐く
					Print("OrderClose error ",GetLastError());
				}
			}
			break;
		}
		//--- 売ポジションなら
		if(OrderType()==OP_SELL){
			//--- 決済条件
			if(Open[1]< ma && Close[1]>ma){
				//--- 決済処理
				if(!OrderClose(OrderTicket(),OrderLots(),Ask,3,White)){
					//--- 決済に失敗ならエラーを吐く
					Print("OrderClose error ",GetLastError());
				}
			}
			break;
		}
	}//ループ終了
}
//+------------------------------------------------------------------+
//| OnTick function                                                  |
//+------------------------------------------------------------------+
void OnTick(){
//--- バーの数が100未満又は、自動売買が許可されていない場合処理終了
	if(Bars< 100 || IsTradeAllowed()==false) return;
	
	//--- ポジションを保有していない場合はエントリー関数を呼ぶ
	if(CalculateCurrentOrders(Symbol())==0){
		CheckForOpen();
	//--- ポジションを保有してたらクローズ関数を呼ぶ
	}else{                                    
		CheckForClose();
	} 
}
//+------------------------------------------------------------------+

シェアする

  • このエントリーをはてなブックマークに追加

フォローする