2009/02/03

Mizutori_EAの説明(カスタムユーザー向け④)


前回の続きです。
※ご指示頂きましたので修正しました。(2009/2/11)
ここからは、注文・決済・注文の変更になりますが、汎用性を高くするために多くの無駄な作業が含まれています
※不具合が見つかりました。不具合の場所を赤字で書いておきます。
◆ ポジションの決済 ◆
void ClosePositions(int Close_Type ,int Oder_Type ,int MagicNumber)
【void型の関数は、処理後の値がない関数(処理値を返さない関数です。)】
【ClosePositionsという名前の自作関数で、決済タイプ(0:1つだけ決済する、1;すべて決済する)決済する注文の種別、マジックナンバー、を受けて処理を行います。】
{【①まで有効】
int Error ;
RefreshRates();
【値を最新のものにする。】
for(int i=OrdersTotal()-1;i>=0;i--)【注文がある分繰り返す】
{【②まで有効】
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES) == false) break ; //注文ポジションの選択
【注文が、なければ処理を脱出する。】
if(OrderMagicNumber() != MagicNumber) continue; //マジックナンバー
【マジックナンバーが異なれば処理をスキップする。】
{ 【③まで有効】※不要かもしれません。
int type = OrderType();
【その注文のタイプを確認する。BUY or SELL】
if((type == OP_BUY && Oder_Type==SIGNAL_CLOSEBUY)||(type==OP_SELL && Oder_Type==SIGNAL_CLOSESELL))
【決済指示が来ている注文のタイプとその注文が同じタイプか確認し、同じタイプであるなら④内の処理を行う。】
{【④まで有効】
switch(type)【注文のタイプ別分儀】
{【⑤まで有効】
買ポジションに対する処理
case OP_BUY:【BUY注文の場合】
OrderClose(OrderTicket(), OrderLots(), Bid, Slippage, MediumSeaGreen);
 【決済注文を行う(この注文のチケットナンバー、この注文のロット数、売値、スリペ、チャート上の決済位置の印の色)】
Error = GetLastError();
【上記処理のエラーをErrorに格納】
if(Error!=0){Print("Close Positions Error OrderTicket = ", OrderTicket());}else{【⑥まで有効】
【もし、処理時にエラーがあれば、エラー報告しなければ以下の処理を行う。】
if (SignalMail) SendMail("[Signal Alert]", "[" + Symbol() + "] " + DoubleToStr(Bid, Digits) + " Close Buy");
【メールを送るようになっていれば、(   )内の文面でメールを送る。】
if(SignalAlert)Alert("[Signal Alert]", "[" + Symbol() + "] " + DoubleToStr(Bid, Digits) + " Close Buy");
【アラート設定がなされていれば、(  )内の文面でアラートを発生させる。】
}⑥
if(Close_Type==0){return(0);}
【1つだけ決済する場合は、この関数を終了する。】
break;【swithchからの脱出】
売りポジションに対する処理
case OP_SELL: 【SLL注文の場合】
OrderClose(OrderTicket(), OrderLots(), Ask, Slippage, DarkOrange);
【決済注文を行う(この注文のチケットナンバー、この注文のロット数、買値、スリペ、チャート上の決済位置の印の色)
Error = GetLastError();
【上記処理のエラーをErrorに格納】
if(Error!=0){Print("Close Positions Error OrderTicket = ", OrderTicket());}else{【⑦まで有効】
【もし、処理時にエラーがあれば、エラー報告しなければ以下の処理を行う。】
if (SignalMail) SendMail("[Signal Alert]", "[" + Symbol() + "] " + DoubleToStr(Ask, Digits) + " Close Sell");
【メールを送るようになっていれば、(   )内の文面でメールを送る。】
if(SignalAlert)Alert("[Signal Alert]", "[" + Symbol() + "] " + DoubleToStr(Ask, Digits) + " Close Sell");
【アラート設定がなされていれば、(  )内の文面でアラートを発生させる。】
}⑦
if(Close_Type==0){return(0);}
【1つだけ決済する場合は、この関数を終了する。】
break; 【swithchからの脱出】
}⑤
}④
}③
}②
}①
【処理値を返さなくていいので、return()がありません。】
◆ポジションの注文 ◆
void OrderPositions(int Order,int pok1,int pok2,int MagicNumber)
【戻り値のないOrderPositionsという名前の自作関数で、注文の種別、現在のBUY注文の数、現在のSELL注文数、マジックナンバーを受けて処理する。】
{ 【①まで有効】
//-------ロット数の計算
double StopLossLevel =0;
double Stp=0;
int pos = MathAbs(pok1 - pok2);
【現在の注文数をposに格納】
double Lots = 0;
if(Lot_Management){Lots=lotSizeCalc(pos);}else{Lots=Fixed_Lots;}
【ロット調整を行う場合は、lotSizeCalc自作関数を実行し、Lotsに格納。ロット調整をしない場合は、Fixed_Lots(指示値)をLotsに格納】
if(Order==SIGNAL_BUY)
【BUY注文の場合{②}内の処理を行う】
{【②まで有効】
Ticket=0;
if(AccountFreeMarginCheck(Symbol(),OP_BUY,Lots)<=0 || GetLastError()==134){【③まで有効】
【余剰証拠金を確認し、不足している場合{③}内を処理】
Print("We have no money. Free Margin = ", AccountFreeMargin());
【残高不足であることを記載する。】
return(0);【自作関数の終了】}
if (UseStopLoss){Stp= Ask-StopLoss*Point ;}else Stp = 0.0;
【損切り値を設定する場合、損切り値をstpに格納、設定しない場合は、stpに0を格納】
if (UseTakeProfit) TakeProfitLevel = Ask + (TPf*Point) ; else TakeProfitLevel = 0.0;
【利食い値を設定する場合、利食い値をTakeProfitLevelに格納、設定しない場合は、TakeProfitLevelに0を格納】
for(int bt=1;bt<= Order_Challenge ;bt++)【Order_Challenge(指示値)分{④}内を繰り返す】
{【④まで有効】
Ticket = OrderSend(Symbol(), OP_BUY, Lots, Ask, Slippage*Point, Stp, TakeProfitLevel, "Buy(#" + MagicNumber + ")", MagicNumber, 0, DodgerBlue);
現在の通貨ペア、BUY注文、注文数、買値、スリペ、損切り値、利食い値、履歴に(Buy(#マジックナンバー))と記入、マジックナンバー、現在の時間、チャート上に記載される色を指示し、注文する。また、注文状況をTicketに格納】
if(Ticket > 0) 【注文が処理されたら】{【⑤まで有効】
if (OrderSelect(Ticket, SELECT_BY_TICKET, MODE_TRADES)) {【⑥まで有効】
【注文がされているか再度確認するために、注文を確認し、注文がされていれば】
Print("BUY order opened : ", OrderOpenPrice());
【(BUY order open 約定金額)と履歴に残す】
if (SignalMail) SendMail("[Signal Alert]", "[" + Symbol() + "] " + DoubleToStr(Ask, Digits) + "@"+DoubleToStr(Lots,2)+"@ Open Buy");
【メール設定されていれば、( )内の文面でメールを送る。】
if(SignalAlert) Alert ("[Signal Alert]", "[" + Symbol() + "] " + DoubleToStr(Ask, Digits) + "@"+DoubleToStr(Lots,2)+"@ Open Buy");
【アラート設定されていれば、( )内の文面でアラートを表示する。】
break ;【処理を抜け出す。】
⑥} else { ⇒ ⑥}⑤}else{⑦ 【不具合発見です。既設(赤部)だと1度目の注文確認で真、2回目の確認で偽にならないと、エラー報告が発生しないようになっています。変更が必要です。】
【変更内容は、1度目の確認が偽ならエラー処理をする。というものです。】
【2回目の確認は、本来注文の呼び出しがメインのため、エラー処理なしとしてみました。】
if(SignalAlert) Alert("Error opening BUY order : ", GetLastError());
【アラート設定がなされている場合、( )内を表示(エラー報告)】
Sleep(5000);//5秒間停止
【5秒間停止】
}【上記不具合のため、削除】
}⑦
}④
}③
if(Order==SIGNAL_SELL)
【SELL注文の場合{⑦}内の処理を行う】
{【⑦まで有効】
Ticket=0;
if(AccountFreeMarginCheck(Symbol(),OP_SELL,Lots)<=0 || GetLastError()==134){【⑧まで有効】
【余剰証拠金を確認し、不足している場合{⑧}内を処理】
Print("We have no money. Free Margin = ", AccountFreeMargin());
【残高不足であることを記載する。】
return(0); 【自作関数の終了】}⑧
if (UseStopLoss){Stp= Bid+StopLoss*Point ;}else Stp = 0.0;
【損切り値を設定する場合、損切り値をstpに格納、設定しない場合は、stpに0を格納】
if (UseTakeProfit) TakeProfitLevel = Bid - (TPf*Point) ; else TakeProfitLevel = 0.0;
【利食い値を設定する場合、利食い値をTakeProfitLevelに格納、設定しない場合は、TakeProfitLevelに0を格納】
for(int sc = 1;sc<= Order_Challenge ;sc++)【Order_Challenge(指示値)分{⑨}内を繰り返す】
{【⑨まで有効】
Ticket = OrderSend(Symbol(), OP_SELL, Lots, Bid, Slippage*Point, Stp, TakeProfitLevel, "Sell(#" + MagicNumber + ")", MagicNumber, 0, DeepPink);
【現在の通貨ペア、SELL注文、注文数、売値、スリペ、損切り値、利食い値、履歴に(Buy(#マジックナンバー))と記入、マジックナンバー、現在の時間、チャート上に記載される色を指示し、注文する。また、注文状況をTicketに格納】
if(Ticket > 0) 【注文が処理されたら】{【⑩まで有効】
if (OrderSelect(Ticket, SELECT_BY_TICKET, MODE_TRADES)) {【⑪まで有効】
【注文がされているか再度確認するために、注文を確認し、注文がされていれば】
Print("SELL order opened : ", OrderOpenPrice());
【(SELL order open 約定金額)と履歴に残す】
if (SignalMail) SendMail("[Signal Alert]", "[" + Symbol() + "] " + DoubleToStr(Bid, Digits) + "@"+Lots+"@ Open Sell");
【メール設定されていれば、( )内の文面でメールを送る。】
if(SignalAlert) Alert ("[Signal Alert]", "[" + Symbol() + "] " + DoubleToStr(Bid, Digits) + "@"+Lots+"@ Open Sell");
【アラート設定されていれば、( )内の文面でアラートを表示する。】
break ; 【return(0);の方がいいかもしれません。】
⑪} else { ⇒ ⑪}⑩}else{⑫ 【不具合発見です。既設(赤部)だと1度目の注文確認で真、2回目の確認で偽にならないと、エラー報告が発生しないようになっています。変更が必要です。】

【変更内容は、1度目の確認が偽ならエラー処理をする。というものです。】
【2回目の確認は、本来注文の呼び出しがメインのため、エラー処理なしとしてみました。】

if(SignalAlert) Alert("Error opening SELL order : ", GetLastError());
【アラート設定がなされている場合、( )内を表示(エラー報告)】
Sleep(5000);//5秒間停止
【5秒間停止】
} 【上記不具合のため、削除】
}⑫
}⑨
}②
}①
◆ Stoplossの変更(注文の変更)◆
void Changes_Stoploss(int MagicNumber,int pos)
【戻り値のないChanges_Stoplossという自作関数で、マジックナンバー、ナンピン回数を受けて処理します。】
{【①まで有効】
int Error ;
int Total = OrdersTotal()-1;
【注文数の合計をTotalに格納】
int K = Total-pos+1;※不具合処理のため削除
for(int i=Total;i>=K;i--) ⇒ for(int i=0;i> Total;i++) ※不具合発生のため変更
{【②まで有効】
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES) == false) break ; //注文ポジションの選択
【注文の呼び出し、及び 注文がなければ、処理を脱出】
if(OrderMagicNumber() != MagicNumber) continue; //マジックナンバー
【マジックナンバーが異なればスキップ】
{ 【③まで有効】※たぶん要らない
int type = OrderType();
【その注文タイプをtypeに格納】
switch(type)【注文タイプの分儀】
{【④まで有効】
//買ポジションに対する処理
case OP_BUY:【BUY注文の場合】
OrderModify(OrderTicket(),OrderOpenPrice(),OrderStopLoss( )-Point*StopStep,OrderTakeProfit(),0,Yellow);
【注文の変更(注文番号、注文値、損切り値、利食い値、時刻、黄色)で変更を行う】
Error = GetLastError();
【エラーをErrorに格納】
if(Error!=0){Print("Changes Stoploss Error OrderTicket = ", OrderTicket());}
【エラーがあるなら、履歴に残す】
break;【処理を脱出】
//売りポジションに対する処理
case OP_SELL:【SELL注文の場合】
OrderModify(OrderTicket(),OrderOpenPrice(),OrderStopLoss( )+Point*StopStep,OrderTakeProfit(),0,Yellow);
【注文の変更(注文番号、注文値、損切り値、利食い値、時刻、黄色)で変更を行う】
Error = GetLastError();
【エラーをErrorに格納】
if(Error!=0){Print("Changes Stoploss Error OrderTicket = ", OrderTicket());}
【エラーがあるなら、履歴に残す】
break; 【SELL注文の場合】
}④
}③
}②
} ①
//+---------------------------------------------------------------- END ------------------------------------------------------------------+

2 件のコメント :

ayb さんのコメント...

はじめまして。aybと申します。
Mizutori掲示板いつも楽しく読ませてもらっています。

今回のポジション注文における }else { ⇒ } への修正の件で素人ながらの質問なのですが、

修正前は、

if( 注文再度確認 )
{ 約定履歴送信 }
else
{ エラー報告送信 }

で注文再度確認が真ならば約定履歴送信、偽ならばエラー送信する・・・ですよね。
なんか修正前のロジックでもうまくいきそうな気がしますが・・・^^;
何故「1度目の注文確認で真、2回目の確認で偽にならないと、エラー報告が発生しないようになってしまう」
のでしょうか?

確かに24.0で一週間ほどFTしていますがエラー送信は一回も出てなかったですね。


理論的に分からなかったので投稿させていただきした^^;

bighope さんのコメント...

aybさんへ
ほんとですね。確かにおかしいですね。
修正しておきます。
ありがとうございます。
まだあると思いますので、見つけられたらコメントしてやってください。

旅行に出ていたため、ご連絡が遅れました。