ホーム » 初心者向けEA講座 » 02.初心者向け MQL5 学習プラン » 3-1. Hedgeモードのポジション管理(Position vs Order)

3-1. Hedgeモードのポジション管理(Position vs Order)

02.初心者向け MQL5 学習プラン

Hedgeモードの概要

Hedgeモード(両建てモード)は、同一通貨ペアで買いポジションと売りポジションを同時に保有できる取引モードです。これは、Nettingモード(ネッティングモード)と対比される取引方式です。

HedgeとNettingモードの比較
項目Hedgeモードの特徴Nettingモードの特徴
ポジション管理同一通貨ペアで複数のポジションを同時に保有可能同一通貨ペアのポジションは自動的に相殺され、1つの純ポジションとして管理される
ストップロス・テイクプロフィット各ポジションに異なるストップロスやテイクプロフィットを設定可能1つのポジションとして管理されるため、個別設定は不可
リスク分散リスク分散が可能で、不利な状況でも損失を軽減できるリスク分散は難しいが、ポジションが単純化される
ボラティリティ活用市場のボラティリティを活用し、両方向の動きから利益を得る機会があるボラティリティ活用は難しいが、取引がシンプル
取引プロセス複数ポジションを管理する必要があり、取引が複雑になる場合がある取引の簡素化と決済プロセスの効率化が図れる
コスト削減両建てによる取引コスト(手数料やスプレッド)が増加する可能性あり送金手数料、事務コスト、決済資金、為替リスクの削減効果がある

Hedgeモードは、MT4での取引と似た方式で馴染みやすく多くのFX会社で採用されており、MT5などの取引プラットフォームでも利用可能です。トレーダーは市場の状況や戦略のニーズに応じて、柔軟な取引を実行することができます。

ただし、Hedgeモードを効果的に活用するには、適切なリスク管理と高度な取引スキルが必要です。初心者トレーダーは、Hedgeモードの複雑性を十分に理解してから使用することが重要です。

なお、HedgeモードとNettingモードは口座ごとに設定されており、トレーダーが自由に切り替えることはできません。取引を始める前に、使用する口座のモードを確認することが重要です。

Point
多くの口座を見てきたわけではありませんが、MT5口座でHedgeモード以外を見たことがないので、基本的にはMT4と同じポジション管理と考えてよいと思います。

Order(オーダー)とは何か?

Order(オーダー)とは、未約定の注文のことを指します。これは市場に出された指示であり、特定の条件が満たされたときに実行されます。主なオーダータイプは以下の通りです:

  1. 成行注文(Market Order)
    現在の市場価格で即時に約定する注文。
  2. 指値注文(Limit Order)
    指定した価格またはそれより有利な価格で約定する注文。
  3. 逆指値注文(Stop Order)
    指定した価格に達したときに成行注文として執行される注文。

MQL5では、OrderSend()関数を使用してオーダーを発注します。この関数では、注文の種類や数量、価格などを指定できます。

Position(ポジション)とは何か?

Position(ポジション)とは、すでに約定済みの取引を指します。つまり、市場で実際に保有している状態です。ポジションには以下の2種類があります:

  1. 買いポジション(ロング)
    価格上昇を期待して保有するポジション。
  2. 売りポジション(ショート)
    価格下落を期待して保有するポジション。

MQL5では、PositionSelect()関数を使って特定のポジションを選択し、PositionGetDouble()PositionGetInteger()などを使って詳細情報を取得します。

OrderとPositionの違い

OrderとPositionには明確な違いがあります。それぞれ以下のように区別されます:

項目Order(オーダー)Position(ポジション)
状態未約定の注文約定済みの取引
管理方法OrderSend()で発注PositionSelect()で選択後に操作
リスク約定するまでリスクなし市場変動による損益が発生

Hedgeモードでは、この違いを正確に理解し、それぞれを適切に管理することが重要です。

Hedgeモードにおけるポジション管理の重要性

Hedgeモードでは、同一通貨ペアで複数のポジションを持つことができるため、適切なポジション管理が非常に重要です。以下がその理由です:

  1. リスク管理
    複数のポジションを持つことで全体のリスクが増大する可能性があります。各ポジションごとのリスク評価が必要です。
  2. 収益最適化
    異なる戦略によるポジション間の相互作用を考慮しながら、収益最大化を目指します。
  3. 複雑性への対応
    多数のポジションを同時に管理することは単一ポジションよりも難しいため、自動化や整理された管理手法が求められます。

具体的なポジション管理手法

Hedgeモードで効果的なポジション管理を行うためには、以下の手法が役立ちます:

  1. 識別と追跡
    各ポジションにユニークな識別子(チケット番号など)を割り当てて追跡します。
  2. リスク分散
    異なる戦略や時間軸で取引し、リスク集中を避けます。
  3. 自動化
    MQL5スクリプトやEAによる自動化で効率的な管理を実現します。

MQL5での実装例

以下は、Hedgeモードでポジションを管理する簡単なコード例です。
1つめは、単純にポジションが無ければ買い(BUY)エントリーして、ポジションがある場合は反対側のエントリーをします。
エントリーしたら手動で決済してみて動きを確認してみて動作を理解してみてください。

#property copyright "Your Name"
#property link      "https://www.example.com"
#property version   "1.00"
#property strict

#include <Trade\Trade.mqh>

CTrade g_trade;

input double Lots = 0.01;      // 取引量

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{
   return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
}

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
{
   if(0 == PositionsTotal())
   {
      // ポジションがない場合、新規ポジションをオープン
      g_trade.Buy(Lots, Symbol(), 0, 0, 0, "Hedge Buy");
      Print("新規ポジションをオープン(買い)");
   }
   else if(1 == PositionsTotal())
   {
      // 1つのポジションがある場合、反対方向でヘッジ
      ulong ticket = PositionGetTicket(0);
      if(PositionSelectByTicket(ticket))
      {
         ENUM_POSITION_TYPE positionType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
         
         if(POSITION_TYPE_BUY == positionType)
         {
            g_trade.Sell(Lots, Symbol(), 0, 0, 0, "Hedge Sell");
            Print("ヘッジポジションをオープン(売り)");
         }
         else if(POSITION_TYPE_SELL == positionType)
         {
            g_trade.Buy(Lots, Symbol(), 0, 0, 0, "Hedge Buy");
            Print("ヘッジポジションをオープン(買い)");
         }
      }
   }
}
ソースコードの解説
行番号ソースコード解説
1#property copyright “Your Name”プログラムの著作権情報を定義します。 “Your Name” はユーザーの名前に変更することができます。
2#property link “https://www.example.com”プログラムに関連するウェブリンクを定義します。リンク先のURLを設定します。
3#property version “1.00”プログラムのバージョン情報を定義します。この場合はバージョン「1.00」です。
4#property strict厳格モードを有効にします。これにより、型チェックやエラーチェックが強化されます。
6#includeTrade.mqh ライブラリをインクルードします。このライブラリは、取引に関する関数を提供します。
8CTrade g_trade;CTrade クラスのインスタンス g_trade を宣言します。このインスタンスを使って、取引操作を実行します。
10input double Lots = 0.01;ユーザーが入力する変数 Lots を定義します。取引量を決定するための変数で、デフォルト値は 0.01 ロットです。
15int OnInit()OnInit 関数の開始です。Expert Advisor(EA)の初期化処理を行うための関数です。
16{OnInit 関数の開始。
17return(INIT_SUCCEEDED);初期化が成功したことを示す定数 INIT_SUCCEEDED を返します。
18}OnInit 関数の終了。
23void OnDeinit(const int reason)OnDeinit 関数の開始です。EAが終了する際に呼び出され、終了処理を行うための関数です。
24{OnDeinit 関数の開始。
25}OnDeinit 関数の終了。
30void OnTick()OnTick 関数の開始です。ティックごとに呼ばれる関数で、ここで売買判断を行います。
31{OnTick 関数の開始。
32if(0 == PositionsTotal())ポジションがない場合の条件文です。PositionsTotal() は現在開いているポジションの数を返します。
33{if 条件文の開始。
35g_trade.Buy(Lots, Symbol(), 0, 0, 0, “Hedge Buy”);g_trade を使用して買いポジションをオープンします。取引量は Lots で、シンボルは現在の通貨ペアです。
36Print(“新規ポジションをオープン(買い)”);ポジションが開かれたことをコンソールに出力します。
37}if 条件文の終了。
38else if(1 == PositionsTotal())既に1つポジションがある場合の条件文です。
39{else if 条件文の開始。
41ulong ticket = PositionGetTicket(0);最初のポジションのチケット番号を取得します。チケット番号はポジションを一意に識別するために使われます。
42if(PositionSelectByTicket(ticket))チケット番号でポジションを選択します。選択したポジションの情報を取得するための条件文です。
43{if 条件文の開始。
44ENUM_POSITION_TYPE positionType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);現在のポジションのタイプ(買い・売り)を取得し、positionType に格納します。
45}if 条件文の終了。
46if(POSITION_TYPE_BUY == positionType)現在のポジションが買いの場合の条件文です。
47{if 条件文の開始。
48g_trade.Sell(Lots, Symbol(), 0, 0, 0, “Hedge Sell”);反対方向(売り)のポジションを開きます。取引量は Lots で、シンボルは現在の通貨ペアです。
49Print(“ヘッジポジションをオープン(売り)”);ヘッジポジションをオープンしたことをコンソールに出力します。
50}if 条件文の終了。
51else if(POSITION_TYPE_SELL == positionType)現在のポジションが売りの場合の条件文です。
52{else if 条件文の開始。
53g_trade.Buy(Lots, Symbol(), 0, 0, 0, “Hedge Buy”);反対方向(買い)のポジションを開きます。取引量は Lots で、シンボルは現在の通貨ペアです。
54Print(“ヘッジポジションをオープン(買い)”);ヘッジポジションをオープンしたことをコンソールに出力します。
55}else if 条件文の終了。
56}if 条件文の終了。
57}else if 条件文の終了。
58}OnTick 関数の終了。

次の例は決済です。
このコードでは、すべてのオープン中のポジションについてループ処理し、それぞれに応じたロジックを適用しています。また、一部利益確定として部分決済も行っています。
エントリーは勝手にしないので、1.0ロットなど数回半分に割り切れるポジションをエントリーしてみてください。一定の利益で半分ずつ決済していきますが割り切れない(端数がでる)と決済出来ない問題がおきますので、なぜ決済できなくなるかを含めて理解できるようになると良いです。

#property copyright "Your Name"
#property link      "https://www.example.com"
#property version   "1.00"
#property strict

#include <Trade\Trade.mqh>

CTrade g_trade;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{
   // 初期化処理をここに記述
   return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   // 終了処理をここに記述
}

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
{
   // 全てのオープンポジションをループ処理
   for(int nPositionIndex = PositionsTotal() - 1; nPositionIndex >= 0; nPositionIndex--)
   {
      ulong ulTicket = PositionGetTicket(nPositionIndex);
      if(PositionSelectByTicket(ulTicket))
      {
         double dPositionProfit = PositionGetDouble(POSITION_PROFIT);
         ENUM_POSITION_TYPE ePositionType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
         double dPositionVolume = PositionGetDouble(POSITION_VOLUME);
         
         // ポジションタイプごとの処理
         if(ePositionType == POSITION_TYPE_BUY)
         {
            // 買いポジションの場合
            Print("買いポジション: 利益 = ", dPositionProfit);
         }
         else if(ePositionType == POSITION_TYPE_SELL)
         {
            // 売りポジションの場合
            Print("売りポジション: 利益 = ", dPositionProfit);
         }
         
         // 利益が一定額以上なら部分決済
         if(dPositionProfit > 100)
         {
            g_trade.PositionClosePartial(ulTicket, dPositionVolume / 2);
            Print("ポジションの一部を決済しました: チケット = ", ulTicket);
         }
      }
   }
}
ソースコードの解説
行番号コード説明
1#property copyright "Your Name"EAの著作権情報を指定。
2#property link "https://www.example.com"EAに関連するウェブサイトのリンクを指定。
3#property version "1.00"EAのバージョン情報を設定。
4#property strict厳密な型チェックを適用し、コードの安全性を向上。
6#include <Trade\Trade.mqh>CTrade クラスを使用するためのヘッダーファイルをインクルード。
8CTrade g_trade;CTrade クラスのインスタンス g_trade を作成(トレード処理用)。
13int OnInit()初期化関数 OnInit の定義。
14{OnInit 関数の開始。
16return(INIT_SUCCEEDED);初期化が成功したことを示すリターン値。
17}OnInit 関数の終了。
22void OnDeinit(const int reason)EA終了時の処理を記述する関数 OnDeinit の定義。
23{OnDeinit 関数の開始。
25}OnDeinit 関数の終了。
30void OnTick()ティックごと(価格更新ごと)に実行される OnTick 関数の定義。
31{OnTick 関数の開始。
33for(int nPositionIndex = PositionsTotal() - 1; nPositionIndex >= 0; nPositionIndex--)すべてのオープンポジションをループ処理。
34{for ループの開始。
35ulong ulTicket = PositionGetTicket(nPositionIndex);ポジションのチケット番号を取得。
36if(PositionSelectByTicket(ulTicket))ポジション選択が成功した場合の処理開始
37{ポジション選択成功時の処理ブロック開始。
38double dPositionProfit = PositionGetDouble(POSITION_PROFIT);ポジションの現在の利益を取得。
39ENUM_POSITION_TYPE ePositionType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);ポジションの種類(買い or 売り)を取得。
40double dPositionVolume = PositionGetDouble(POSITION_VOLUME);ポジションの取引量(ロット数)を取得。
43if(ePositionType == POSITION_TYPE_BUY)買いポジションの場合の処理開始
44{買いポジションの処理ブロック開始。
46Print("買いポジション: 利益 = ", dPositionProfit);買いポジションの利益を表示。
47}買いポジションの処理終了
48else if(ePositionType == POSITION_TYPE_SELL)売りポジションの場合の処理開始
49{売りポジションの処理ブロック開始。
51Print("売りポジション: 利益 = ", dPositionProfit);売りポジションの利益を表示。
52}売りポジションの処理終了
55if(dPositionProfit > 100)利益が100を超えた場合の部分決済処理開始
56{部分決済の処理ブロック開始。
57g_trade.PositionClosePartial(ulTicket, dPositionVolume / 2);ポジションの半分を決済。
58Print("ポジションの一部を決済しました: チケット = ", ulTicket);部分決済の実行をログに出力。
59}部分決済の処理終了
60}ポジション選択成功時の処理終了
61}forループの処理終了
62}OnTick 関数の終了。

まとめと今後の展望

Hedgeモードでは、OrderとPositionという異なる概念を正しく理解し、それぞれを適切に扱うことが重要です。特に複数のポジション管理が求められる場面では、自動化や整理された手法によって効率的かつ安全な運用が可能になります。

今後はさらに高度な戦略やリスク管理技術について学びながら、自分自身のEA開発スキルを磨いていきましょう!

用語集

用語説明
Hedgeモード同一通貨ペアで買いと売り両方のポジションを同時保有できる取引モード
Order未約定状態の注文
Position約定済みで保有中の取引
PositionSelect()特定のポジション選択関数
PositionGetDouble()ポジション情報取得関数(小数値データ用)
PositionsTotal()現在保有中の全オープンポジション数取得
PositionClosePartial()部分決済用関数

コメント

タイトルとURLをコピーしました