前回は 実際に注文を出す記述を、順を追って説明しました。
改めて前回の内容をおさらいをしておくと、
注文は、
・MqlTradeRequest構造体とMqlTradeResult構造体のインスタンスを宣言する。
↓
・MqlTradeRequest構造体の各メンバに必要な値を入れていく。
↓
・OrderSend関数を記述する。
というプロセスで記述していく。
ということをお伝えしました。
今回は 注文が無事約定し、有効化したポジションに対してストップロス(SL:損切り価格)とテイクプロフィット(TP:利益確定価格)を設定するプロセス についてお話ししたいと思います。
有効化したポジションにSLとTPを設定するにはTRADE_ACTION_SLTPを使う
有効化したポジションにSLとTPを設定するにはTRADE_ACTION_SLTPを使います。 この時、待機注文の修正を行うTRADE_ACTION_MODIFYとの混同に注意する必要があります。
また、前回の成行注文解説回では、SLとTPは設定しませんでしたが、そもそも論として、新規注文の時点でSLとTPは原則設定できる訳ですから、作るEAの戦略次第でコーディングが変わります。
ネッティングシステムでのSLTP設定
ネッティングシステム口座の場合、保有ポジションは1銘柄1つなのでポジションの確認は銘柄名(→.symbol)で確認します。従って、SLTP設定にあたり.positionへの値は入力不要です。
request.action =TRADE_ACTION_SLTP; // 取引操作タイプ
request.symbol =_Symbol; // シンボル
request.sl =ストップロス価格; // ポジションのStop Loss
request.tp =テイクプロフィット価格; // ポジションのTake Profit
OrderSend(request,result);
ヘッジングシステムでのSLTP設定設定
ヘッジングシステム口座の場合、1銘柄に対して複数のポジション保有が可能なので、SLTPの設定にあたっては、ポジション番号を正しく取得し.position に設定する事が必要になります。
ポジション番号の取得は、
- PositionGetTicket関数を使う。
- PositionGetInteger関数を使い、引数にPOSITION_TICKETを設定する
- MqlTradeResult構造体のメンバ変数 .orderの値を使う
などの手段を用います。
request.action =TRADE_ACTION_SLTP; // 取引操作タイプ
request.symbol =_Symbol; // シンボル
request.position=ポジション番号; // ポジション番号
request.sl =ストップロス価格; // ポジションのStop Loss
request.tp =テイクプロフィット価格; // ポジションのTake Profit
OrderSend(request,result);
実際に、SLとTPを付与する記述を書いてみる
SLTP設定に関する概略を説明したところで、実際にSLとTPを付与する記述を書いてみましょう。
※ネッティングシステム口座については、最初に説明した事以上に付け加えることもなく、現在大多数のブローカーが提供しているのヘッジングシステムであることもあり、これから先の記述は全てヘッジングシステムを前提とした記述です。
前回の成行注文解説回でつかった成り行き買い注文のコードに、SLとTPを設定する記述を追加していきます。
#property script_show_inputs
まずグローバル領域(関数の外の領域)にプロパティ命令である script_show_inputs
を記述します。この記述をしていると、スクリプト実行の前にプロパティウィンドウを表示してくれます。
ストップロスとテイクプロフィットを設定するにあたり、今回はinput変数を用います。
input int StopLoss=1000;
input int TakeProfit=1000;
void OnStart()
int型で、変数名をそれぞれStopLoss、TakeProfitとし、ポイントベース換算でSLTPを算出するので初期値は便宜的に1000としました。
※ポイントというのは、銘柄における値動きの一番小さい値を指します。ドル円などの対円通貨ペアであれば「0.001」が1ポイント、ユーロドル等の対円以外の通貨ペアでは「0.00001」が1ポイントとなっています。
続いては、新規成行注文が約定した後の記述を見ていきます。
OrderSend(request,result);
if(result.retcode==TRADE_RETCODE_PLACED ||result.retcode==TRADE_RETCODE_DONE)
{
Print("注文が成功しました。 リターンコード= ",result.retcode);
request.action = TRADE_ACTION_SLTP;
request.position = result.order;
SLとTPを設定したいので、.actionにはTRADE_ACTION_SLTPを設定します。
今回は.positionにはMqlTradeResult構造体のメンバ変数 .orderを代入しました。
成行注文の際は、オーダー番号とポジション番号は同じものが同時に割り振られるのでその性質を利用します。
※詳しいことは講座記事第61回の「メンバ変数 .orderにはオーダー番号が格納される」
の項目をご覧ください。
PositionSelectByTicket(result.order);
double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
PositionSelectByTicket関数
PositionSelectByTicket関数は、引数にポジション番号を指定することによって、指定ポジションの様々な情報を取得する作業を許可する関数です。PositionSelectByTicket関数の処理が正常に行われれば、以降
PositionGetDouble関数、PositionGetInteger関数、PositionGetString関数などの関数を使って指定ポジションの情報取得が可能になります。
先ほどもお伝えしたように、新規成行注文の際は、オーダー番号とポジション番号は同じものが同時に割り振られるのでPositionSelectByTicket関数の引数にresult.orderを記述することでポジション番号を記述した事と同じ意味になります。
なぜここで、PositionSelectByTicket関数を使っているかというと、この後SLとTPを設定する際に必要となる約定価格を取得する為です。
ポジションの約定価格はPositionGetDouble関数の引数に定数値「POSITION_PRICE_OPEN」を記述します。
取得した約定価格をdouble型の変数「openPrice」に格納し、晴れてSLTPを設定する準備が整いました。
※約定価格についてはMqlTradeResult構造体のメンバ変数 .priceを使うという方法もあります。
if文で、変数「TakeProfit」や「StopLoss」に0より大きい数値が入っているかを切り分けさせたうえで、メンバ変数 .sl と.tp にそれぞれストップロスとテイクプロフィットの値を代入していきます。
if(TakeProfit > 0)request.tp=openPrice+(TakeProfit*_Point);
if(StopLoss > 0)request.sl=openPrice-(StopLoss*_Point);
OrderSend(request,result);
すでに変数「openPrice」には約定価格が代入されているので、.tpにはopenPrice+(TakeProfit*_Point)、.slにはopenPrice-(StopLoss*_Point)を代入すればいいことになります。
*_Pointというのは、定義済み変数で、現在の銘柄における、値動きの一番小さい値を取得します。ドル円などの対円通貨ペアであれば「0.001」、ユーロドル等の対円以外の通貨ペアでは「0.00001」が返ってきます。
input変数「 StopLoss」「TakeProfit」には1000が入っているので、SL、TPともに約定価格から1000ポイント(100ピプス)上下に設定されたことになります。
※定義済み変数については↓の記事をご覧ください。
※なお、PositionSelectByTicket関数とはべつに、”EURUSD”や”USDJPY”などのシンボル名を引数として記述することによってポジション選択を行うPositionSelect関数という関数もあります。
PositionSelectByTicket関数は特定のポジションに対する操作や分析を行いたい時に便利なので、ヘッジングシステムで主に使われるのに対し、PositionSelect関数はある通貨ペアに関連するポジションの総合的な情報を得たい時や、そのポジションに対するアクションを取りたい時に使用します。主にネッティングシステムにおいて使用します。
全体のコード
全体のコードは以下のようになっています
#property script_show_inputs // スクリプトがインプットパラメータを表示するように設定します。
input int StopLoss=1000; // ストップロスの値を入力パラメータとして設定します。初期値は1000ポイントです。
input int TakeProfit=1000; // テイクプロフィットの値を入力パラメータとして設定します。初期値は1000ポイントです。
// スクリプトが開始されたときに呼ばれる関数
void OnStart()
{
// 取引要求と結果を格納するための構造体を初期化します。
MqlTradeRequest request={};
MqlTradeResult result={};
// 注文の詳細を設定します。
request.action=TRADE_ACTION_DEAL; // 即時取引を意味します。
request.type=ORDER_TYPE_BUY; // 注文タイプを「買い」に設定します。
request.symbol=_Symbol; // 注文する通貨ペア(シンボル)を現在のチャートのものに設定します。
request.volume=0.1; // 取引量(ロット数)を0.1に設定します。
request.type_filling=ORDER_FILLING_IOC; // 注文の実行方式を「即時またはキャンセル」に設定します。
request.price=SymbolInfoDouble(_Symbol,SYMBOL_ASK); // 現在のAsk価格を注文価格に設定します。
request.sl=0; // ストップロス価格を0に設定します(この段階では設定しません)。
request.tp=0; // テイクプロフィット価格を0に設定します(この段階では設定しません)。
request.deviation=3; // 許容するスリッページ(価格滑り)を3ポイントに設定します。
request.magic=1234; // 注文に識別子(マジックナンバー)を設定します。
// 注文を送信します。
OrderSend(request,result);
// 注文結果を確認します。
if(result.retcode==TRADE_RETCODE_PLACED || result.retcode==TRADE_RETCODE_DONE)
{
// 注文が成功した場合の処理
Print("注文が成功しました。 リターンコード= ", result.retcode);
request.action = TRADE_ACTION_SLTP; // アクションをストップロス/テイクプロフィットの設定に変更します。
request.position = result.order; // 注文のポジションIDを設定します。
// 注文のチケット番号でポジションを選択します。
PositionSelectByTicket(result.order);
// オープン価格を取得します。
double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
// テイクプロフィットを設定します。
if(TakeProfit > 0) request.tp = openPrice + (TakeProfit * _Point);
// ストップロスを設定します。
if(StopLoss > 0) request.sl = openPrice - (StopLoss * _Point);
// 変更したストップロス/テイクプロフィットの情報で注文を再送信します。
OrderSend(request, result);
}
else
{
// 注文が失敗した場合の処理
Print("注文が失敗しました。リターンコード= ", result.retcode);
}
//--- 関数の終了
}
↑上記のサンプルコードを実際に実行してみると・・・↓
新規成行注文が成立し、約定価格から上下1000ポイントにSLとTPが入っている事が確認できるかと思います。
まとめ
今回は 約定したポジションに対してSLとTPを設定する記述 について解説しました。
今回の記事では以下のことを学びました
- 有効化したポジションにSLとTPを設定するにはTRADE_ACTION_SLTPを使う。
- 待機注文の修正を行うTRADE_ACTION_MODIFYとの混同に注意する。
今回は以上になります。
最後までお読みいただきありがとうございました<m(__)m>
コメント