本記事で公開しているライブラリーは公開当時のままで、古くなっております。最新版のライブラリーはメルマガ登録いただくことでダウンロードできます。
注文変更はトレイリングストップで活躍する
注文時から利食いや損切り等の価格を変更する、MQL4の標準関数にOrderModify()があります。
このくだり、OrderSend()、OrderClose()及びOrderDelete()と一緒なので以下割愛です。OrderModify()が失敗した時を考慮した注文変更関数を紹介します。
//+------------------------------------------------------------------+
//|【関数】信頼できる注文変更 |
//| |
//|【引数】 IN OUT 引数名 説明 |
//| --------------------------------------------------------- |
//| ○ aTicket チケット番号 |
//| ○ aPrice 待機注文の新しい仕掛け価格 |
//| ○ aStoploss 損切り価格 |
//| ○ aTakeprofit 利食い価格 |
//| ○ aExpiration 待機注文の有効期限 |
//| △ aArrow_color チャート上の矢印の色 |
//| |
//|【戻値】true :正常終了 |
//| false:異常終了 |
//| |
//|【備考】△:既定値あり |
//+------------------------------------------------------------------+
bool orderModifyReliable(int aTicket, double aPrice, double aStoploss,
double aTakeprofit, datetime aExpiration, color aArrow_color = CLR_NONE)
{
bool result = false;
int startTime = GetTickCount();
Print("Attempted orderModifyReliable(#" + aTicket + ", " + aPrice
+ ", SL:"+ aStoploss + ", TP:" + aTakeprofit + ", Expiration:"
+ TimeToStr(aExpiration) + ", ArrowColor:" + aArrow_color + ")");
bool selected = OrderSelect(aTicket, SELECT_BY_TICKET, MODE_TRADES);
string symbol = OrderSymbol();
int type = OrderType();
double digits = MarketInfo(symbol, MODE_DIGITS);
double price = NormalizeDouble(OrderOpenPrice(), digits);
double stoploss = NormalizeDouble(OrderStopLoss(), digits);
double takeprofit = NormalizeDouble(OrderTakeProfit(), digits);
aPrice = NormalizeDouble(aPrice, digits);
aStoploss = NormalizeDouble(aStoploss, digits);
aTakeprofit = NormalizeDouble(aTakeprofit, digits);
double stopLevel = MarketInfo(symbol, MODE_STOPLEVEL)
* MarketInfo(symbol, MODE_POINT);
double freezeLevel = MarketInfo(symbol, MODE_FREEZELEVEL)
* MarketInfo(symbol, MODE_POINT);
while(true){
if(IsStopped()){
Print("Trading is stopped!");
return(-1);
}
if(GetTickCount() - startTime > MAX_RETRY_TIME * MILLISEC_2_SEC){
Print("Retry attempts maxed at " + MAX_RETRY_TIME + "sec");
return(-1);
}
double ask = NormalizeDouble(MarketInfo(symbol, MODE_ASK), digits);
double bid = NormalizeDouble(MarketInfo(symbol, MODE_BID), digits);
// 仕掛け/損切り/利食いがストップレベル未満かフリーズレベル以下の場合、エラー
if(type == OP_BUY){
if(MathAbs(bid - aStoploss) < stopLevel){
Print("StopLevel: SL was too close to brokers min distance (" + stopLevel + ")");
return(-1);
}else if(MathAbs(aTakeprofit - bid) < stopLevel){
Print("StopLevel: TP was too close to brokers min distance (" + stopLevel + ")");
return(-1);
}else if(MathAbs(bid - aStoploss) <= freezeLevel){
Print("FreezeLevel: SL was too close to brokers min distance (" + stopLevel + ")");
return(-1);
}else if(MathAbs(aTakeprofit - bid) <= freezeLevel){
Print("FreezeLevel: TP was too close to brokers min distance (" + stopLevel + ")");
return(-1);
}
}else if(type == OP_SELL){
if(MathAbs(aStoploss - ask) < stopLevel){
Print("StopLevel: SL was too close to brokers min distance (" + stopLevel + ")");
return(-1);
}else if(MathAbs(ask - aTakeprofit) < stopLevel){
Print("StopLevel: TP was too close to brokers min distance (" + stopLevel + ")");
return(-1);
}else if(MathAbs(aStoploss - ask) <= freezeLevel){
Print("FreezeLevel: SL was too close to brokers min distance (" + stopLevel + ")");
return(-1);
}else if(MathAbs(ask - aTakeprofit) <= freezeLevel){
Print("FreezeLevel: TP was too close to brokers min distance (" + stopLevel + ")");
return(-1);
}
}else if(type == OP_BUYLIMIT){
if(MathAbs(ask - aPrice) < stopLevel && (aPrice != 0.0 && aPrice != price)){
Print("StopLevel: OpenPrice was too close to brokers min distance ("
+ stopLevel + ")");
return(-1);
}else if(MathAbs(aPrice - aStoploss) < stopLevel &&
((aPrice != 0.0 && aPrice != price) ||
(aStoploss != 0.0 && aStoploss != stoploss))){
Print("StopLevel: SL was too close to brokers min distance (" + stopLevel + ")");
return(-1);
}else if(MathAbs(aTakeprofit - aPrice) < stopLevel &&
((aPrice != 0.0 && aPrice != price) ||
(aTakeprofit != 0.0 && aTakeprofit != takeprofit))){
Print("StopLevel: TP was too close to brokers min distance (" + stopLevel + ")");
return(-1);
}else if(MathAbs(ask - aPrice) <= freezeLevel && (aPrice != 0.0 && aPrice != price)){
Print("FreezeLevel: OpenPrice was too close to brokers min distance ("
+ stopLevel + ")");
return(-1);
}
}else if(type == OP_SELLLIMIT){
if(MathAbs(aPrice - bid) < stopLevel && (aPrice != 0.0 && aPrice != price)){
Print("StopLevel: OpenPrice was too close to brokers min distance ("
+ stopLevel + ")");
return(-1);
}else if(MathAbs(aStoploss - aPrice) < stopLevel &&
((aPrice != 0.0 && aPrice != price) ||
(aStoploss != 0.0 && aStoploss != stoploss))){
Print("StopLevel: SL was too close to brokers min distance (" + stopLevel + ")");
return(-1);
}else if(MathAbs(aPrice - aTakeprofit) < stopLevel &&
((aPrice != 0.0 && aPrice != price) ||
(aTakeprofit != 0.0 && aTakeprofit != takeprofit))){
Print("StopLevel: TP was too close to brokers min distance (" + stopLevel + ")");
return(-1);
}else if(MathAbs(aPrice - bid) <= freezeLevel &&
(aPrice != 0.0 && aPrice != price)){
Print("FreezeLevel: OpenPrice was too close to brokers min distance ("
+ stopLevel + ")");
return(-1);
}
}else if(type == OP_BUYSTOP){
if(MathAbs(aPrice - ask) < stopLevel
&& (aPrice != 0.0 && aPrice != price)){
Print("StopLevel: OpenPrice was too close to brokers min distance ("
+ stopLevel + ")");
return(-1);
}else if(MathAbs(aPrice - aStoploss) < stopLevel &&
((aPrice != 0.0 && aPrice != price) ||
(aStoploss != 0.0 && aStoploss != stoploss))){
Print("StopLevel: SL was too close to brokers min distance ("
+ stopLevel + ")");
return(-1);
}else if(MathAbs(aTakeprofit - aPrice) < stopLevel &&
((aPrice != 0.0 && aPrice != price) ||
(aTakeprofit != 0.0 && aTakeprofit != takeprofit))){
Print("StopLevel: TP was too close to brokers min distance ("
+ stopLevel + ")");
return(-1);
}else if(MathAbs(aPrice - ask) <= freezeLevel &&
(aPrice != 0.0 && aPrice != price)){
Print("FreezeLevel: OpenPrice was too close to brokers min distance ("
+ stopLevel + ")");
return(-1);
}
}else if(type == OP_SELLSTOP){
if(MathAbs(bid - aPrice) < stopLevel && (aPrice != 0.0 && aPrice != price)){
Print("StopLevel: OpenPrice was too close to brokers min distance ("
+ stopLevel + ")");
return(-1);
}else if(MathAbs(aStoploss - aPrice) < stopLevel &&
((aPrice != 0.0 && aPrice != price) ||
(aStoploss != 0.0 && aStoploss != stoploss))){
Print("StopLevel: SL was too close to brokers min distance (" + stopLevel + ")");
return(-1);
}else if(MathAbs(aPrice - aTakeprofit) < stopLevel &&
((aPrice != 0.0 && aPrice != price) ||
(aTakeprofit != 0.0 && aTakeprofit != takeprofit))){
Print("StopLevel: TP was too close to brokers min distance (" + stopLevel + ")");
return(-1);
}else if(MathAbs(bid - aPrice) <= freezeLevel &&
(aPrice != 0.0 && aPrice != price)){
Print("FreezeLevel: OpenPrice was too close to brokers min distance ("
+ stopLevel + ")");
return(-1);
}
}
if(IsTradeContextBusy()){
Print("Must wait for trade context");
}else{
result = OrderModify(aTicket, aPrice, aStoploss, aTakeprofit, aExpiration, aArrow_color);
if(result){
Print("Success! Ticket #", aTicket, " order modified, details follow");
selected = OrderSelect(aTicket, SELECT_BY_TICKET, MODE_TRADES);
OrderPrint();
return(result);
}
int err = GetLastError();
// 一時的エラーの場合はリトライするが、恒常的エラーの場合は処理中断(リトライしてもエラーになるため)
if(err == ERR_NO_ERROR ||
err == ERR_COMMON_ERROR ||
err == ERR_SERVER_BUSY ||
err == ERR_NO_CONNECTION ||
err == ERR_TRADE_TIMEOUT ||
err == ERR_INVALID_PRICE ||
err == ERR_PRICE_CHANGED ||
err == ERR_OFF_QUOTES ||
err == ERR_BROKER_BUSY ||
err == ERR_REQUOTE ||
err == ERR_TRADE_CONTEXT_BUSY){
Print("Temporary Error: " + err + " " + ErrorDescription(err) + ". waiting");
}else{
Print("Permanent Error: " + err + " " + ErrorDescription(err) + ". giving up");
return(result);
}
// 最適化とバックテスト時はリトライは不要
if(IsOptimization() || IsTesting()){
return(result);
}
}
Sleep(SLEEP_TIME * MILLISEC_2_SEC);
}
return(result);
}
orderSendReliable()と殆ど同じ作りですね。違いは待機注文の時だけ有効になるaPriceの考慮(オープンポジションの変更の場合、aPrice=0.0になりますので、その点の考慮)があるぐらいでしょうか。
サンプルEA
関数だけではイメージが沸きづらいと思いますので、サンプルEAを載せておきます。
