
自動売買で保有ポジションを選択するにはどうしたらいいの?
OrderSelect関数とは
自動売買システムに保有ポジションを決済させたいですよね!
決済するためには、保有ポジションを選択する必要があります。
そこで OrderSelect関数を使いましょう。
OrderSelect関数は、保有ポジションを1つ選択する関数です。
選択することで、そのポジションの情報を取得することができます。
例えば、以下の情報を取得できます。
・注文種別
・ロット数
・チケット番号
・注文日時 etc…
ちなみに OrderSelect関数は、あくまで保有ポジションを選択するだけの関数です。
OrderSelect関数を使って、情報を取得することはできないので、ご注意ください。
またOrderSelect関数は、保有ポジションの情報を取得するだけでなく、決済するときにも必ず使用する関数です。
自動売買ではトレードの基本となる関数なので、基本的な書き方をマスターしましょう。
OrderSelect関数の書き方
OrderSelect関数の書き方は、関数の書き方と同じです。
もし関数の使い方をマスターしていない方は、こちらの記事が参考になります。
基本的な書き方
OrderSelect関数の基本的な書き方は以下の通りです。
分かりやすいように、引数は省略しています。
bool OrderSelect( ①, ②, ③);
返り値は bool型で、引数は3つあります。
まずは返り値から見ていきましょう。
返り値(戻り値)
OrderSelect関数の返り値は、bool型です。
「true」または「false」が返ってきます。
数値にすると「1」または「0」が返ってきます。
正常にポジションを選択できた場合は、「true」が返ってきます。
正常にポジションを選択できなかった場合は、「false」が返ってきます。
このように OrderSelect関数は、bool型が返り値となっています。
引数
OrderSelect関数の引数は3つです。
まずは一覧で見てみましょう。
| 番号 | データ型 | 引数名 | 内容 |
| ① | int | index | 以下のどちらかを設定 ・インデックス ・チケット番号 |
| ② | int | select | 以下から選択方法を設定(上記のindexに合わせる) ・インデックス ・チケット番号 |
| ③ | int | pool | 以下のどちらかを設定 ・現在保有しているポジション ・過去保有していたポジション |
1つ1つ見ていきながら、一緒に OrderSelect関数を作っていきましょう。
①index
indexは、ポジションを選択するために、ポジションの番号を設定します。
番号には以下の2種類があります。
・インデックス
・チケット番号
インデックスとは、注文するときに自動的に割り振られた識別番号です。
保有しているポジションが1つの場合、「0」が割り振られます。
その後、ポジションが増えるごとに 1、2、3・・・と順番に割り振られる番号になります。
チケット番号とは、現在・過去に関わらず、ポジションに自動的に割り振られた固有番号です。
チケット番号は、ポジションによって全て異なっているため、同じ番号のポジションはありません。
そのため桁数が多く、FX会社によって異なりますが、8桁くらいの番号になります。
たいていの自動売買システムは、インデックスを使用しています。
インデックスの方が分かりやすいので、インデックスを使用すると良いでしょう。
bool select = OrderSelect( 0, ②, ③);
②select
selectは OrderSelect関数がポジションを選択するときの、選択方法を設定します。
こちらも以下の2つから選びます。
・インデックス(SELECT_BY_POS)
・チケット番号(SELECT_BY_TICKET)
もし ①index の引数で、インデックス番号を設定している場合、「SELECT_BY_POS」を選択します。
チケット番号を設定している場合、「SELECT_BY_TICKET」を選択します。
このように ①index の設定内容によって決まるので、してほしい選択方法を設定しましょう。
ここでは、インデックス番号を設定しますので、以下のように書きます。
bool select = OrderSelect( 0, SELECT_BY_POS, ③);
③pool
poolは、どんな状態のポジションから選択したいのかを設定します。
設定値は以下の2つです。
・現在のポジションから選択(MODE_TRADES)
・過去のポジションから選択(MODE_HISTORY)
例えば、現在保有しているポジションまたは、予約しているポジションから選択したい場合は、「MODE_TRADES」を設定します。
過去に決済したポジションまたは、キャンセルしたポジションから選択したい場合は、「MODE_HISTORY」を設定します。
ここでは、保有ポジションから選択したいので、以下のように書きます。
bool select = OrderSelect( 0, SELECT_BY_POS, MODE_TRADES);
OrderSelect関数の具体的な使い方(サンプルあり)
OrderSelect関数の基本的な書き方を解説しましたが、ここからは具体的な使い方について解説していきます。
OrderSelect関数はポジションを1つだけ選択する関数なので、for文を使って全てのポジションを選択する方法がよく使われます。
そのとき、for分の条件式に保有ポジション数が必要となりますので、OrdersTotal関数と組み合わせて使う場合が多いです。
例えば以下のようなプログラムです。
//保有ポジションを一つずつチェックしていく
for( int i = OrdersTotal() - 1; i >= 0; i--)
{
//保有ポジションを一つ選択
if( OrderSelect( i, SELECT_BY_POS, MODE_TRADES))
{
//ここにポジションを操作するプログラムを書く
}
}
上記のように、for文で1つずつポジションを選択し、ポジションを決済させたり、情報を取得したりします。
この書き方は、自動売買を作るときによく使う書き方なので、どこかにコピーしておくと良いでしょう。
OrdersTotal関数の詳しい使い方は、こちらの記事が参考になります。
OrderSelect関数の実用的なプログラム例
ここからは、OrderSelect関数を使った実用的なプログラム例をいくつかご紹介します。
実際のEA開発でよく使うパターンなので、ぜひ参考にしてみてください。
例1:自分のEAのポジションだけを選択する
複数のEAを同時に稼働させている場合、自分のEAが出した注文だけを対象にしたいですよね。
そんなときは、マジックナンバーと通貨ペアで絞り込む方法が定番です。
// マジックナンバーの定義(EAごとに固有の番号を設定する)
#define MAGIC_NUMBER 12345
//+------------------------------------------------------------------+
//| 自分のEAが保有しているポジション数をカウントする関数 |
//+------------------------------------------------------------------+
int CountMyPositions()
{
int count = 0; // カウント用の変数を初期化
// 保有ポジションを後ろから順にチェックしていく
for(int i = OrdersTotal() - 1; i >= 0; i--)
{
// ポジションを1つ選択する
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
// マジックナンバーが自分のEAのものかチェック
if(OrderMagicNumber() != MAGIC_NUMBER) continue;
// 通貨ペアが現在のチャートと一致しているかチェック
if(OrderSymbol() != Symbol()) continue;
// 両方一致した場合のみカウントを増やす
count++;
}
}
return count; // 自分のEAのポジション数を返す
}
//+------------------------------------------------------------------+
//| OnTick:ティックごとに呼ばれる関数 |
//+------------------------------------------------------------------+
void OnTick()
{
// 自分のEAのポジション数を取得
int myPositions = CountMyPositions();
// ログに出力して確認する
Print("自分のEAの保有ポジション数: ", myPositions);
// ポジションがなければ新規注文を検討する、など
if(myPositions == 0)
{
// ここにエントリー条件を書く
}
}
このようにマジックナンバーと通貨ペアの2つでフィルタリングすることで、他のEAや手動トレードのポジションを誤って操作するのを防ぐことができます。
EA開発では必須テクニックなので、覚えておきましょう。
例2:保有ポジションをすべて決済する
特定の条件になったときに、自分のEAの保有ポジションをすべて一括決済したい場面はよくあります。
以下は、OrderSelect関数とOrderClose関数を組み合わせた全決済のプログラムです。
// マジックナンバーの定義
#define MAGIC_NUMBER 12345
//+------------------------------------------------------------------+
//| 自分のEAの保有ポジションをすべて決済する関数 |
//+------------------------------------------------------------------+
void CloseAllMyPositions()
{
// 後ろから順にループする(決済するとインデックスがずれるため)
for(int i = OrdersTotal() - 1; i >= 0; i--)
{
// ポジションを1つ選択する
if(!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) continue;
// 自分のEAのマジックナンバーでなければスキップ
if(OrderMagicNumber() != MAGIC_NUMBER) continue;
// 現在のチャートの通貨ペアでなければスキップ
if(OrderSymbol() != Symbol()) continue;
// 注文種別を取得する
int type = OrderType();
// 買いポジション(OP_BUY)の場合
if(type == OP_BUY)
{
// Bid価格で決済する
bool result = OrderClose(
OrderTicket(), // チケット番号
OrderLots(), // ロット数
MarketInfo(Symbol(), MODE_BID), // 現在のBid価格
3, // スリッページ(3ポイント)
clrRed // チャート上の矢印の色
);
// 決済結果をログに出力
if(result)
Print("買いポジション決済成功: チケット=", OrderTicket());
else
Print("買いポジション決済失敗: エラー=", GetLastError());
}
// 売りポジション(OP_SELL)の場合
else if(type == OP_SELL)
{
// Ask価格で決済する
bool result = OrderClose(
OrderTicket(), // チケット番号
OrderLots(), // ロット数
MarketInfo(Symbol(), MODE_ASK), // 現在のAsk価格
3, // スリッページ(3ポイント)
clrBlue // チャート上の矢印の色
);
// 決済結果をログに出力
if(result)
Print("売りポジション決済成功: チケット=", OrderTicket());
else
Print("売りポジション決済失敗: エラー=", GetLastError());
}
}
}
//+------------------------------------------------------------------+
//| OnTick:ティックごとに呼ばれる関数 |
//+------------------------------------------------------------------+
void OnTick()
{
// 例:金曜日の22時以降になったら全決済する(週末持ち越し防止)
if(DayOfWeek() == 5 && Hour() >= 22)
{
CloseAllMyPositions();
}
}
ポイントは、for文を後ろから回している点です。
決済するとインデックス番号がずれるため、前から回すとポジションを飛ばしてしまう場合があります。
必ず後ろから(OrdersTotal() – 1 から 0 に向かって)ループさせましょう。
例3:保有ポジションの合計損益を計算する
自分のEAの保有ポジション全体の損益を把握して、一定の利益・損失に達したら全決済する──そんなロジックを組むときに使えるプログラムです。
// マジックナンバーの定義
#define MAGIC_NUMBER 12345
//+------------------------------------------------------------------+
//| 自分のEAの保有ポジション合計損益を取得する関数 |
//| 戻り値:合計損益(通貨単位。例:ドル口座なら米ドル) |
//+------------------------------------------------------------------+
double GetTotalProfit()
{
double totalProfit = 0.0; // 合計損益を格納する変数
// 保有ポジションを後ろから順にチェック
for(int i = OrdersTotal() - 1; i >= 0; i--)
{
// ポジションを選択する
if(!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) continue;
// マジックナンバーが異なればスキップ
if(OrderMagicNumber() != MAGIC_NUMBER) continue;
// 通貨ペアが異なればスキップ
if(OrderSymbol() != Symbol()) continue;
// 買い or 売りポジションのみ対象(待機注文は除外する)
if(OrderType() != OP_BUY && OrderType() != OP_SELL) continue;
// OrderProfit()で含み損益、OrderSwap()でスワップ、
// OrderCommission()で手数料を取得し、すべて合算する
totalProfit += OrderProfit() + OrderSwap() + OrderCommission();
}
return totalProfit; // 合計損益を返す
}
//+------------------------------------------------------------------+
//| OnTick:ティックごとに呼ばれる関数 |
//+------------------------------------------------------------------+
void OnTick()
{
// 合計損益を取得
double profit = GetTotalProfit();
// チャート左上にコメントとして表示
Comment("合計損益: ", DoubleToString(profit, 2), " ", AccountCurrency());
// 例:合計利益が5000円以上になったら全決済
if(profit >= 5000.0)
{
Print("目標利益に到達!全決済を実行します。合計損益=", profit);
// ここで全決済関数(例2のCloseAllMyPositions)を呼び出す
// CloseAllMyPositions();
}
// 例:合計損失が-3000円以下になったら損切り全決済
if(profit <= -3000.0)
{
Print("損切りラインに到達!全決済を実行します。合計損益=", profit);
// ここで全決済関数(例2のCloseAllMyPositions)を呼び出す
// CloseAllMyPositions();
}
}
OrderProfit()で含み損益、OrderSwap()でスワップポイント、OrderCommission()で取引手数料を取得できます。
これら3つを合算することで、実質的な損益を正確に把握することができます。
まとめ
OrderSelect関数は、保有ポジションを1つ選択する関数です。
選択したポジションの情報取得や決済を行うために、必ず使用する重要な関数です。
今回のポイントをまとめると以下の通りです。
・OrderSelect関数は保有ポジションを1つ選択する関数
・返り値はbool型(true / false)
・引数は「インデックスまたはチケット番号」「選択方法」「ポジションの状態」の3つ
・for文とOrdersTotal関数を組み合わせて使うのが基本
・マジックナンバーと通貨ペアでフィルタリングするのが実践的
・ループは必ず後ろから回す(決済時のインデックスずれ防止)
OrderSelect関数は自動売買の基本中の基本となる関数です。
ぜひ今回ご紹介したサンプルコードを参考に、実際にプログラムを書いて動かしてみてください。




