MQL5レシピ - オープンヘッジポジションのプロパティを取得しましょう

Denis Kirichenko | 6 11月, 2018

概論

比較的最近、MetaTrader 5取引端末に多方向に注文を開く機能が現れました。この注文計算システムを『ヘッジ』といいます。この注文システムの存在により、全ての最新の利点を活用しながら、MetaTrader 4から5に取引アルゴリズムを簡単に転送することができます。MetaTrader 5のヘッジに関する詳細については、『MetaTrader 5にヘッジポジション計算システムが追加されました。』という資料をご参照ください。

この記事では、『ヘッジ』システムで扱われるポジション集計のプロパティに焦点を当てます。


1. ヘッジポジションとタイプ

ヘッジ(累積)ポジションは、いくつかのマーケットオーダーによって形成されるマーケットポジションです。狭義では、ヘッジポジション(ヘッジ)には多方向の注文(売りと買い)が含まれます。とはいえ、広義での『ヘッジ』という言葉を使うことを提案したいと思います。同時に、ヘッジポジションも一方向の注文に集約することにしましょう。このアプローチは、MetaTrader 5端末の、一方向への注文も、別の方向への注文も可能であるという機能に起因します。

ポジションの集約を分類するには、いくつかの方法があります。おそらく、最も人気のある基準は、1つまたは他の集計ポジションを形成するマーケットオーダーのタイプによってポジションを区別する基準です。では、どのような注文でこういったポジションにすることができるでしょうか?以下の表1は種々の組み合わせを示しています。

タイプ 説明
1 Hedge buy 買いのみ
2 Hedge netting buy 『純粋な』買い
3 Hedge sell 売りのみ
4 Hedge netting sell 『純粋な』売り
5 Hedge locked ロック(完全なヘッジ)

表1ヘッジタイプ

これらのタイプについて簡単に説明します。集約したポジションに買いまたは売りの注文のみある場合(MetaTrader 4ターミナル)、hedge buyまたはhedge sellでポジションを計算します。ポジションに複数の注文(買いと売りの両方)がある場合は、どの注文がより多いかを調べます。買い注文の方が多い場合、hedge netting buyポジションになります。売り注文が多い場合、hedge netting sellとなります。より正確に言うならば、注文の数ではなく、そのボリュームについて言及する必要があります。仮にポジションに1.25ロットのボリュームの買い注文が1つあり、0.5ロットと0.6ロットの売り注文が2つあるとします。その結果、ポジションは0.15ロットの純買いポジション(hedge netting buy)になります。

1,25 – (0,5 + 0,6) = 0,15

取引量の観点から買いと売りのバランスをとる、ポジションが混在する特別な種類のものがロックです。

記載されている種類のヘッジは、次のようになります。

//+------------------------------------------------------------------+
//| Hedge type                                                  |
//+------------------------------------------------------------------+
enum ENUM_HEDGE_TYPE
  {
   HEDGE_BUY=0,          // buy
   HEDGE_SELL=1,         // sell   
   HEDGE_NETTING_BUY=2,  // netting buy   
   HEDGE_NETTING_SELL=3, // netting sell
   HEDGE_LOCKED=4,       // lock
  };


『ネッティング』のシステムに目を向けると、定義上累積的にそのポジションは、買いまたは売りの2つのタイプのうちの1つのみを参照することができます。識別子は、列挙値の1つ ENUM_POSITION_TYPEです。

1)POSITION_TYPE_BUY

2)POSITION_TYPE_SELL

『ヘッジ』システムでは、5種類の集約ポジションを取得します。

次のセクションでは、ヘッジポジションのプロパティを扱うクラスを作成します。


2. CHedgePositionInfoクラス

標準ライブラリには、オープンマーケットポジションのプロパティへのアクセスできるCPositionInfoクラスがあります。私たちの場合、このクラスは部分的にしか有用ではありません。というのも、これが処理するポジションは、別のマーケット注文(MetaTrader 4)として提示されるらです。そして私達には、集約ポジション(ヘッジ)を形成するすべてのポジションを一度に処理するクラスが必要です。

OOP-toolsを使って、CHedgePositionInfoクラスを作成してみましょう。

//+------------------------------------------------------------------+
//| Class CHedgePositionInfo                                         |
//| Purpose: Class for access to a hedge position info.              |  
//|              Derives from class CObject.                         |
//+------------------------------------------------------------------+
class CHedgePositionInfo : public CObject
  {
   //--- === Data members === --- 
private:
   ENUM_HEDGE_TYPE   m_type;
   double            m_volume;
   double            m_price;
   double            m_stop_loss;
   double            m_take_profit;
   ulong             m_magic;
   //--- objects
   CArrayLong        m_tickets;
   CSymbolInfo       m_symbol;
   CPositionInfo     m_pos_info;

   //--- === Methods === --- 
public:
   //--- constructor/destructor
   void              CHedgePositionInfo(void){};
   void             ~CHedgePositionInfo(void){};
   //--- initialization
   bool              Init(const string _symbol,const ulong _magic=0);
   //--- get methods
   CSymbolInfo      *Symbol(void)       {return GetPointer(m_symbol);};
   CArrayLong       *HedgeTickets(void) {return GetPointer(m_tickets);};
   CPositionInfo    *PositionInfo(void) {return GetPointer(m_pos_info);};
   ulong             Magic(void) const  {return m_magic;};
   //--- fast access methods to the integer hedge properties
   datetime          Time(void);
   ulong             TimeMsc(void);
   datetime          TimeUpdate(void);
   ulong             TimeUpdateMsc(void);
   ENUM_HEDGE_TYPE   HedgeType(void);
   //--- fast access methods to the double hedge properties
   double            Volume(double &_buy_volume,double &_sell_volume);
   double            PriceOpen(const ENUM_TRADE_TYPE_DIR _dir_type=TRADE_TYPE_ALL);
   double            StopLoss(const ENUM_TRADE_TYPE_DIR _dir_type=TRADE_TYPE_ALL);
   double            TakeProfit(const ENUM_TRADE_TYPE_DIR _dir_type=TRADE_TYPE_ALL);
   double            PriceCurrent(const ENUM_TRADE_TYPE_DIR _dir_type=TRADE_TYPE_ALL);
   double            Commission(const bool _full=false);
   double            Swap(void);
   double            Profit(void);
   double            Margin(void);
   //--- fast access methods to the string hedge properties
   string            TypeDescription(void);
   //--- info methods
   string            FormatType(string &_str,const uint _type) const;
   //--- select
   bool              Select(void);
   //--- state
   void              StoreState(void);
   bool              CheckState(void);

private:
   //--- calculation methods
   bool              AveragePrice(
                                  const SPositionParams &_pos_params,
                                  double &_avg_pr,
                                  double &_base_volume,
                                  double &_quote_volume
                                  );
   int               CheckLoadHistory(ENUM_TIMEFRAMES period,datetime start_date);
  };
//+------------------------------------------------------------------+


クラスデータの構成について少し触れたいと思います。

まず、ユニークなシンボルがあります。すなわちヘッジポジションには、任意の1つのシンボルのポジションを含めることができます。 CSymbolInfoクラスインスタンスを与える、m_symbolフィールドがシンボルを担当します。

第2に、マジック(m_magic)を必要なオーダーのフィルターとして設定することができます。このようにすることで、1つトレーディングアドバイザーが担当しているポジションを作成することが可能です。したがって、1つのシンボルで複数のヘッジを作成することができます。

また注文集計(m_tickets)のための動的配列もあります。ここにはヘッジポジションのチケットが入ります。

1つの選択したポジション(MetaTrader 4でのマーケットオーダー)のプロパティを取得する機能は、CPositionInfo(m_pos_info)クラスのインスタンスに割り当てられます。

ヘッジのその他のプロパティは、その状態を評価するために必要です。

クラスを構築するための基礎として、CPositionInfoクラスの論理が採用されたことに注目することは重要です。 そして、それはとても自然なことです。したがって、新しいクラスには、整数プロパティ、doubleプロパティなどを返すメソッドがあります。もちろん、特別なメソッドもあります。


2.1初期化メソッド

クラスの機能を使用する前に、対応するインスタンスを初期化する必要があります。この方法は、第1にアドバイザーがヘッジシステム内で正確に動作し、第2に希望するシンボルが選択され、マジックナンバーが設定されているかをチェックします。

//+------------------------------------------------------------------+
//| Initialization                                                   |
//+------------------------------------------------------------------+
bool CHedgePositionInfo::Init(const string _symbol,const ulong _magic=0)
  {
//--- account margin mode
   ENUM_ACCOUNT_MARGIN_MODE margin_mode=(ENUM_ACCOUNT_MARGIN_MODE)AccountInfoInteger(ACCOUNT_MARGIN_MODE);
   if(margin_mode!=ACCOUNT_MARGIN_MODE_RETAIL_HEDGING)
     {
      Print(__FUNCTION__+": no retail hedging!");
      return false;
     }
   if(!m_symbol.Name(_symbol))
     {
      Print(__FUNCTION__+": a symbol not selected!");
      return false;
     }
   ENUM_SYMBOL_CALC_MODE  symbol_calc_mode=(ENUM_SYMBOL_CALC_MODE)SymbolInfoInteger(_symbol,SYMBOL_TRADE_CALC_MODE);
   if(symbol_calc_mode!=SYMBOL_CALC_MODE_FOREX)
     {
      Print(__FUNCTION__+": only for Forex mode!");
      return false;
     }
   m_magic=_magic;
//---
   return true;
  }
//+------------------------------------------------------------------+

このメソッドは、後続のヘッジクラス機能の使用に必須です。このメソッドでは、マージン計算モードがチェックされることに注意してください。『ヘッジ』と一致しない場合、メソッドはfalseを返します。また、契約価格を計算する方法もチェックされます。私たちはForex契約のみ取り扱うことにします。


2.2整数プロパティ

整数プロパティへのアクセスは、メソッドを使用して実行されます。

  1. datetime                   Time(void);
  2. ulong                        TimeMsc(void);
  3. datetime                   TimeUpdate(void);
  4. ulong                        TimeUpdateMsc(void);
  5. ENUM_HEDGE_TYPE   HedgeType(void).

例として、CHedgePositionInfo::Time()メソッドのコードを見てみましょう。

//+------------------------------------------------------------------+
//| Get  the hedge open time                                         |
//+------------------------------------------------------------------+
datetime CHedgePositionInfo::Time(void)
  {
   datetime hedge_time=WRONG_VALUE;
   int hedge_pos_num=m_tickets.Total();
//--- if any positions
   if(hedge_pos_num>0)
     {
      //--- find the first opened position
      for(int pos_idx=0;pos_idx<hedge_pos_num;pos_idx++)
        {
         ulong curr_pos_ticket=m_tickets.At(pos_idx);
         if(curr_pos_ticket<LONG_MAX)
            if(m_pos_info.SelectByTicket(curr_pos_ticket))
              {
               datetime curr_pos_time=m_pos_info.Time();
               if(curr_pos_time>0)
                 {
                  if(hedge_time==0)
                     hedge_time=curr_pos_time;
                  else
                    {
                     if(curr_pos_time<hedge_time)
                        hedge_time=curr_pos_time;
                    }
                 }
              }
        }
     }
//---
   return hedge_time;
  }
//+------------------------------------------------------------------+

ヘッジの開始時間、つまりヘッジの最初のポジションを取得するには、すべてのポジションを通過して、 一番早いものを見つける必要があります。

しかし、ヘッジを変更した時間、つまり最後の変更があったポジションを取得するには、以前のメソッドを少し修正する必要があります。

//+------------------------------------------------------------------+
//| Get  the hedge update time                                       |
//+------------------------------------------------------------------+
datetime CHedgePositionInfo::TimeUpdate(void)
  {
   datetime hedge_time_update=0;
   int hedge_pos_num=m_tickets.Total();
//--- if any positions
   if(hedge_pos_num>0)
     {
      //--- find the first opened position
      for(int pos_idx=0;pos_idx<hedge_pos_num;pos_idx++)
        {
         ulong curr_pos_ticket=m_tickets.At(pos_idx);
         if(curr_pos_ticket<LONG_MAX)
            if(m_pos_info.SelectByTicket(curr_pos_ticket))
              {
               //--- get the current position update time
               datetime curr_pos_time_update=m_pos_info.TimeUpdate();
               if(curr_pos_time_update>0)
                  if(curr_pos_time_update>hedge_time_update)
                     hedge_time_update=curr_pos_time_update;
              }
        }
     }
//---
   return hedge_time_update;
  }
//+------------------------------------------------------------------+

ヘッジの種類を識別するメソッドは、以下のように符号化されます。

//+------------------------------------------------------------------+
//| Get  the hedge type                                              |
//+------------------------------------------------------------------+
ENUM_HEDGE_TYPE CHedgePositionInfo::HedgeType(void)
  {
   ENUM_HEDGE_TYPE curr_hedge_type=WRONG_VALUE;
   int hedge_pos_num=m_tickets.Total();
//--- if any positions
   if(hedge_pos_num>0)
     {
      //--- get the volumes      
      double total_vol,buy_volume,sell_volume;
      buy_volume=sell_volume=0.;
      total_vol=this.Volume(buy_volume,sell_volume);
      //--- define a hedge type
      if(buy_volume>0. && sell_volume>0.)
        {
         if(buy_volume>sell_volume)
            curr_hedge_type=HEDGE_NETTING_BUY;
         else if(buy_volume<sell_volume)
            curr_hedge_type=HEDGE_NETTING_SELL;
         else
            curr_hedge_type=HEDGE_LOCKED;
        }
      else if(buy_volume>0. && sell_volume==0.)
         curr_hedge_type=HEDGE_BUY;
      else if(buy_volume==0. && sell_volume>0.)
         curr_hedge_type=HEDGE_SELL;
     }
//---
   return curr_hedge_type;
  };
//+------------------------------------------------------------------+

ヘッジの種類は、買いおよび売りのボリュームの違いによります。最初にヘッジが、実際に狭義のものであるかどうかをチェックします。買いの量と売りの量が等しい場合、ヘッジは完全なものです。不均等である場合、部分的なヘッジを扱っていることになります。

その後ヘッジが買いか売りのみによって表されていないかどうかをチェックします。


2.3Doubleプロパティ

ダブルプロパティへのアクセスは、以下のメソッドによって実行されます。

  1.    double            Volume(double &_buy_volume,double &_sell_volume);
  2.    double            PriceOpen(void);
  3.    double            StopLoss(void);
  4.    double            TakeProfit(void);
  5.    double            PriceCurrent(void);
  6.    double            Commission(void);
  7.    double            Swap(void);
  8.    double            Profit(void);
  9.    double            Margin(void).

ヘッジ量を判別するメソッドが、リンク形式のパラメータを持っていることは簡単にわかります。この実装では、ヘッジ自体のボリュームとそのコンポーネント(買いと売り)の両方を即座に取得することができます。

//+------------------------------------------------------------------+
//| Get  the hedge volume                                            |
//+------------------------------------------------------------------+
double CHedgePositionInfo::Volume(double &_buy_volume,double &_sell_volume)
  {
   double total_vol=0.;
   int hedge_pos_num=m_tickets.Total();
//--- if any positions
   if(hedge_pos_num>0)
     {
      _buy_volume=_sell_volume=0.;
      //--- get the buy\sell volumes      
      for(int pos_idx=0;pos_idx<hedge_pos_num;pos_idx++)
        {
         ulong curr_pos_ticket=m_tickets.At(pos_idx);
         if(curr_pos_ticket<LONG_MAX)
            if(m_pos_info.SelectByTicket(curr_pos_ticket))
              {
               ENUM_POSITION_TYPE curr_pos_type=m_pos_info.PositionType();
               double curr_pos_vol=m_pos_info.Volume();
               if(curr_pos_vol>0.)
                 {
                  //--- for a buy position
                  if(curr_pos_type==POSITION_TYPE_BUY)
                     _buy_volume+=curr_pos_vol;
                  //--- else for a sell position
                  else if(curr_pos_type==POSITION_TYPE_SELL)
                     _sell_volume+=curr_pos_vol;
                 }
              }
        }
      total_vol=_buy_volume-_sell_volume;
     }
//---
   return total_vol;
  }
//+------------------------------------------------------------------+

価格プロパティを操作するための補助メソッドCHedgePositionInfo::AveragePrice()が作成されました。価格レベルのタイプに応じてヘッジの平均価格を考慮するコードのブロックは以下の通りです。

//--- if the hedge volumes calculated
if(hedge_base_volume!=0. && hedge_quote_volume!=0.)
  {
   _avg_pr=fabs(hedge_quote_volume/hedge_base_volume);
   _base_volume=hedge_base_volume;
   _quote_volume=hedge_quote_volume;
   return true;
  }

アプローチは、見積通貨におけるヘッジの最終価値と基本通貨におけるヘッジの最終価値との比率です。

後で例を使って作業するときに、実際の計算をしてみましょう。

スワップおよび利益を得るためのメソッドは、ヘッジの各ポジションの対応する指標を集計し、合計金額を返します。手数料を取得するメソッドは、オープンポジションに参加した取引を分析します。手数料の額をどのように計算するかをパラメータを通して選択することができます。エントリ取引だけで取得する場合は、デフォルトのパラメータをそのまま使用します。エントリとクローズの手数料を計算する必要がある場合、パラメーターはtrueと等しくなければなりません。後者のメソッドはいくつかの理由から、大体のものであることに注意してください。まず、選択されたポジションを閉じることができます。すると、DEAL_ENTRY_OUT_BYタイプの取引が出現します。これらに対して手数料は請求されません。第2に、もし口座の通貨が基本通貨と一致しない場合、レートの変動時にエントリとクローズの価格が異なる場合があります。

//+------------------------------------------------------------------+
//| Get  the hedge commission                                        |
//+------------------------------------------------------------------+
double CHedgePositionInfo::Commission(const bool _full=false)
  {
   double hedge_commission=0.;
   int hedge_pos_num=m_tickets.Total();
//--- if any positions
   if(hedge_pos_num>0)
      for(int pos_idx=0;pos_idx<hedge_pos_num;pos_idx++)
        {
         ulong curr_pos_ticket=m_tickets.At(pos_idx);
         if(curr_pos_ticket<LONG_MAX)
            if(m_pos_info.SelectByTicket(curr_pos_ticket))
              {
               long curr_pos_id=m_pos_info.Identifier();
               if(curr_pos_id>0)
                  //--- retrieve the history of deals associated with the selected position 
                  if(HistorySelectByPosition(curr_pos_id))
                    {
                     CDealInfo curr_deal;
                     int deals_num=HistoryDealsTotal();
                     for(int deal_idx=0;deal_idx<deals_num;deal_idx++)
                        if(curr_deal.SelectByIndex(deal_idx))
                          {
                           ENUM_DEAL_ENTRY curr_deal_entry=curr_deal.Entry();
                           if(curr_deal_entry==DEAL_ENTRY_IN)
                             {
                              double curr_deal_commission=NormalizeDouble(curr_deal.Commission(),2);
                              if(curr_deal_commission!=0.)
                                {
                                 double fac=1.;
                                 if(_full) fac=2.;
                                 hedge_commission+=(fac*curr_deal_commission);
                                }
                             }
                          }

                    }
              }
        }
//---
   return hedge_commission;
  }
//+------------------------------------------------------------------+

クラスにはCHedgePositionInfo::Margin()というメソッドがあり、ヘッジポジションのマージンの値を判定することができます。実際、このメソッドはプログラムするのが最も難しいものでした。未決済ポジションと保留中の注文のマージンのサイズを正しく判別するメソッドに関して、1つの記事が書けるほどです。


2.3.1ヘッジポジションに関する権利

開発者が示しているように、多方向のポジションの場合、ブローカーによって決定されるマージンの計算方法が2つあります。最初の方法は基本的な計算に基づいており、2番目の方法は最大の側面で実装されています。

私は第2の計算方法に出会えなかったことを認めます。それにもかかわらず、これをプログラムします。しかし、まず最初にマージンの計算を含むもっと複雑なアルゴリズムを持つ最初の方法を検討することを提案します。

  1. カバーされていないボリューム
  2. ヘッジボリューム(ヘッジマージンが示されている場合)
  3. 保留中の注文

この記事のマージンは、Retail Forex、Futuresをモデルに計算しています。保留中のオーダーのマージンの計算は考慮されていません。

ヘッジポジションのマージンを計算するには、以下のパラメータに関する情報が必要です。

  1. デポジット通貨。原則として、口座は米ドル(USD)、ユーロ(EUR)、ポンド(GBP)、フラン(CHF)で表示されます。
  2. マージン通貨。原則として、これはシンボルの基本通貨です。たとえば、EURUSDの場合はユーロ(EUR)、AUDNZDの場合は豪ドル(AUD)です。
  3. レバレッジのサイズ。

また、端末の[貿易]タブの残高明細では、預金通貨にマージン価格が表示されます。したがって、計算の結果は、預金通貨のマージンの値である必要があります。

マージン通貨が預金通貨と一致しない可能性があるため、計算アルゴリズムにはいくつかのオプションがあります。

  1. 預金通貨がヘッジポジションシンボルに基本通貨として存在する場合。ドル口座でUSDCHFを取引している場合など。
  2. ヘッジポジションシンボルに預金通貨が引用通貨の形式で存在する場合。ドル口座でEURUSDを取引している場合など。
  3. 預金通貨がヘッジポジションのシンボルにないとき。AUDNZDをドル口座で取引している場合など。

最初のオプションは最も簡単に計算でき、最後は最も難しいです。会計作業をして、各オプションの例を考えましょう。

最初のオプション

USDCHFシンボル(図1)に5つのポジションが開かれているドル口座(デポジット)があるとします。


USDCHFペアの市場ポジション

図1 USDCHFペアの市場ポジション


基本パラメータ:

口座通貨 - USD。

マージン通貨 - USD。

レバレッジサイズ - 1:100。

3つの買いポジションがあります。ポジションの総額は5.55ロットであり、価値基準で55万5千ドルです。そして、2つの売りポジションがあります。ポジションの総量は7.5ロットであり、金額は75万ドルです。

A)カバーされていないボリュームの計算

カバーされていないボリュ​​ームは1.95ロットまたは19万5千ドルです。これは買い以上に売りが大きいため、売りとなります。しかしながら、この場合は加重平均価格を計算する必要がないため、買いや売りは全く重要ではありません。

この金額からのマージンは、レバレッジを考慮して計算されます。

$195 000 / 100 = $1 950。

B)ヘッジボリュームの計算

ヘッジボリュームは、5.55ロットまたは55万5千ドルです。

この金額からのマージンは、レバレッジを考慮して計算されます。

$555 000 / 100 = $5 550。

グロスマージンは、カバーされていないボリュームのマージンとヘッジボリュームのマージンの合計として計算されます。

$1 950 + $5 550 = $7 500

『マージン』インジケータの取引端末に表示されるのはこの値です。

2番目のオプション

EURUSDシンボル(図2)に対して5つのポジションが開かれているドル口座(デポジット)があるとします。


EURUSDの市場ポジション

図2 EURUSDペアの市場ポジション

基本パラメータ:

  • 口座通貨 - USD。
  • マージン通貨 - EUR。
  • レバレッジサイズ - 1:300。

3つの買いポジションがあります。ポジションの総額は5.55ロットであり、価格では55万5千ユーロまたは64万5617.20ドルである。加重平均購入価格は1.163274ドルです。

2つの売りポジションがあります。ポジションの総量は7.50ロットで、価格では75万ユーロまたは87万2,409ドルです。加重平均販売価格は1.163212ドルです。

すべてのポジションを表2で表示します。

Type Volume Price Value, $
buy 1.75 1.16329 203 575.75
buy 2.55 1.16329 296 638.95
buy 1.25 1.16322 145 402.50
sell 3.00 1.16323 348 969.00
sell 4.50 1.16320 523 440.00
Total 13.05 1.1632385 1 518 026.20

表2 EURUSDペアの市場ポジション


全部で5つのポジションがあります。ポジション総額は13.05ロットで、価格面では130万5千ユーロまたは151万8,026.20ドルです。ポジションの加重平均価格は1.16324ドルです。

A)カバーされていないボリュームの計算

カバーされていないボリュームは1.95ロットまたは19万5千ユーロです。これは買い以上に売りが大きいため、売りとなります。したがって、このボリュームの値を決定するには、加重平均販売価格を使用します。

$1.163212 * €195 000 = $226 826.34。

この金額からのマージンは、レバレッジを考慮して計算されます。

$226 826.34 / 300 = $756.09。

B)ヘッジボリュームの計算

ヘッジボリュームは5.55ロットまたは55万5千ユーロです。このボリュームの価値を決定するために、すべてのポジションの加重平均価格を取得します。

$1.1632385 * €555 000 = $645 597.35。

この金額からのマージンは、レバレッジを考慮して計算されます。

$645 597.35 / 300 = $2 151,99。

理論的には、総マージンは次のようになります。

$756.09 + $2 151.99 = $2 908.08。

しかし、端末では$ 1 832.08という値が見えます。

実際には、カバーされていないボリュームの場合、ツールの仕様の『ヘッジドマージン』パラメータの値が考慮されます。これが契約のサイズより小さければ、いくつかの乗数が取得されます。この場合、指定されたパラメータによって、値が5万に設定されます。したがって、

ヘッジボリュームの価格 = $ 1.1632385 *€555 000 /(100 000/50 000)= $ 322 798.67。

ヘッジボリュームのマージン= $ 322,798.67 / 300 = $ 1,076.00。

合計額:$ 756.09 + $ 1 076.00 = $ 1 832.08。この値は端末に対応しています。

3番目のオプション

AUDNZDシンボルのために5つのポジションが開かれているドル口座(デポジット)があるとします(図3)。


AUDNZDクロスでの市場ポジション

図3 AUDNZDクロスの市場ポジション

基本パラメータ:

  • 口座通貨 - USD。
  • マージン通貨 - AUD。
  • レバレッジサイズ - 1:300。

3つの買いポジションがあります。ポジション総額は5.55ロットであり、額面55万5千豪ドルまたは40万442.35ドルです。加重平均購入価格は$ 0.7215178です。

2つの売りポジションがあります。ポジションの総量は7.50ロットに相当し、額面75万豪ドルまたは54万1,035.00ドルです。加重平均販売価格は$ 0.72138です。

すべてのポジションを表3で表示します。

Type Volume Price Value, $
buy 1.75 0.72152 126 266.00
buy 2.55 0.72152 183 987.60
buy 1.25 0.72151 90 188.75
sell 3.00 0.72144 216 432.00
sell 4.50 0.72134 324 603.00
Total 13.05 0.72144 941 477.35

図3 AUDNZDクロスの市場ポジション


Price列には、AUDNZDシンボルではなく、AUDUSDシンボルでのポジションの価格が表示されています。これは、アカウントの通貨で取引された金額を即座に評価するためです。この場合、勘定通貨とマージン通貨が表示されるペアのティックと相場の履歴を参照する必要があります。したがって、計算値は実際の値とは多少異なる場合があります。

全部で5つのポジションがあります。ポジションの総量は13.05ロットで、価格面では130万5千豪ドルまたは94万1,477.35ドルです。ポジションの加重平均価格は$ 0.72144です。

A)カバーされていないボリュームの計算

カバーされていないボリュームは、1.95ロットまたは19万5千豪ドルです。これは買い以上に売りが大きいため、売りとなります。したがって、このボリュームの値を決定するには、加重平均販売価格を使用します。

$ 0.72138 * A $ 195,000 = $ 140 669.10。

この金額からのマージンは、レバレッジを考慮して計算されます。

$140 669.10 / 300 = $468.90.

B)ヘッジボリュームの計算

ヘッジボリュームは5.55ロットまたは55万5千豪ドルです。この金額の価値を決定するために、『ヘッジマージン』パラメータの価格を考慮して、すべてのポジションの加重平均価格を採用します。

$ 0.72144 * A $ 555,000 /(100,000 / 50,000)= $ 200 199.21。

この金額からのマージンは、レバレッジを考慮して計算されます。

$200 199.21/ 300 = $667.33.

合計額:$ 468.90 + $ 667.33 = $ 1 136.23。図3に従って、これが端末のものと一致しているかチェックします。


2.4その他のプロパティ

クラスにはまだ、ヘッジの状態を持つStoreState()とCheckState()を扱うメソッドがあります。通常のポジションと同様に、タイプ、数量、開始価格、ストップロス価格、および利益を取得することによって決定されます。

テキストプロパティTypeDescription()の単一メソッドは、ヘッジタイプを文字列として返します。

特に注目すべきは、Select()ヘッジポジション選択メソッドです。メソッドコードを以下に示します。

//+------------------------------------------------------------------+
//| Selects hedge positions                                          |
//+------------------------------------------------------------------+
bool CHedgePositionInfo::Select(void)
  {
   string hedge_symbol=m_symbol.Name();
//--- clear all positions 
   m_tickets.Shutdown();
//--- collect positions
   int pos_num=PositionsTotal();
   for(int pos_idx=0;pos_idx<pos_num;pos_idx++)
      if(m_pos_info.SelectByIndex(pos_idx))
        {
         string curr_pos_symbol=m_pos_info.Symbol();
         //--- select by symbol
         if(!StringCompare(hedge_symbol,curr_pos_symbol))
           {
            //--- if to select by magic
            bool is_the_same_magic=true;
            if(m_magic>0)
              {
               long curr_pos_magic=m_pos_info.Magic();
               if(m_magic!=curr_pos_magic)
                  is_the_same_magic=false;
              }
            if(is_the_same_magic)
              {
               ulong curr_pos_ticket=m_pos_info.Ticket();
               if(curr_pos_ticket>0)
                  if(!m_tickets.Add(curr_pos_ticket))
                    {
                     PrintFormat(__FUNCTION__+": failed to add #%d ticket!",curr_pos_ticket);
                     return false;
                    }
              }
           }
        }
//---
   return m_tickets.Total()>0;
  }
//+------------------------------------------------------------------+

このメソッドの主な目的は、ヘッジを構成するポジションのチケットを更新することです。これらのシンボルがヘッジシンボルとマッチしている場合、ここに市場ポジションが入ります。また、マジックのような選択フィルタを追加することもできます。


3.例

私達はヘッジポジションのプロパティで動作するクラスを作成しました。このセクションでは、実際的な例を扱うことを提案します。簡単なスクリプトから始めましょう。


3.1テストスクリプト

ヘッジのプロパティに関する『エキスパート』タブの情報がログに記録されるTest_hedge_properties.mq5スクリプトは練習用に作成されました。

デポジットを計算する最初のオプションでは、USDCHFシンボルに5つのポジションがありました(図1)。スクリプトを実行し、ログ内で次の情報を取得します。

2018.09.03 18:51:37.078 Test_hedge_properties (AUDNZD,H1)       ---== Hedge properties==---
2018.09.03 18:51:37.078 Test_hedge_properties (AUDNZD,H1)       Symbol: USDCHF
2018.09.03 18:51:37.078 Test_hedge_properties (AUDNZD,H1)       Positions total = 5
2018.09.03 18:51:37.078 Test_hedge_properties (AUDNZD,H1)               1) #293972991 buy 1.75 USDCHF 0.97160000
2018.09.03 18:51:37.078 Test_hedge_properties (AUDNZD,H1)               2) #293974150 buy 2.55 USDCHF 0.97142000
2018.09.03 18:51:37.078 Test_hedge_properties (AUDNZD,H1)               3) #293974889 sell 3.00 USDCHF 0.97157000
2018.09.03 18:51:37.078 Test_hedge_properties (AUDNZD,H1)               4) #293975329 sell 4.50 USDCHF 0.97164000
2018.09.03 18:51:37.078 Test_hedge_properties (AUDNZD,H1)               5) #293976289 buy 1.25 USDCHF 0.97205000
2018.09.03 18:51:37.078 Test_hedge_properties (AUDNZD,H1)       Magic: 0
2018.09.03 18:51:37.078 Test_hedge_properties (AUDNZD,H1)       Time: 2018.08.29 17:15:44
2018.09.03 18:51:37.078 Test_hedge_properties (AUDNZD,H1)       Time in msc: 1535562944628
2018.09.03 18:51:37.078 Test_hedge_properties (AUDNZD,H1)       Update time: 2018.08.29 17:20:35
2018.09.03 18:51:37.078 Test_hedge_properties (AUDNZD,H1)       Update time in msc: 1535563235034
2018.09.03 18:51:37.078 Test_hedge_properties (AUDNZD,H1)       Type: HEDGE_NETTING_SELL
2018.09.03 18:51:37.078 Test_hedge_properties (AUDNZD,H1)       Type description: hedge netting sell
2018.09.03 18:51:37.078 Test_hedge_properties (AUDNZD,H1)       Volume: -1.95
2018.09.03 18:51:37.078 Test_hedge_properties (AUDNZD,H1)       Buy volume: 5.55
2018.09.03 18:51:37.078 Test_hedge_properties (AUDNZD,H1)       Sell volume: 7.50
2018.09.03 18:51:37.078 Test_hedge_properties (AUDNZD,H1)       Open price: 0.97159
2018.09.03 18:51:37.078 Test_hedge_properties (AUDNZD,H1)       Sl-price: -1.00000
2018.09.03 18:51:37.078 Test_hedge_properties (AUDNZD,H1)       Tp-price: -1.00000
2018.09.03 18:51:37.078 Test_hedge_properties (AUDNZD,H1)       Current price: 0.96956
2018.09.03 18:51:37.078 Test_hedge_properties (AUDNZD,H1)       Commission: 0.00
2018.09.03 18:51:37.078 Test_hedge_properties (AUDNZD,H1)       Swap: -35.79
2018.09.03 18:51:37.078 Test_hedge_properties (AUDNZD,H1)       Profit: 409.77
2018.09.03 18:51:37.078 Test_hedge_properties (AUDNZD,H1)       Margin: 7500.00

第2のオプションでは、EURUSD上のポジションのプロパティが処理されました(図2)。スクリプトを実行した後、次の情報を取得しました。

2018.09.03 18:55:09.469 Test_hedge_properties (AUDNZD,H1)       ---== Hedge properties==---
2018.09.03 18:55:09.469 Test_hedge_properties (AUDNZD,H1)       Symbol: EURUSD
2018.09.03 18:55:09.469 Test_hedge_properties (AUDNZD,H1)       Positions total = 5
2018.09.03 18:55:09.469 Test_hedge_properties (AUDNZD,H1)               1) #119213986 buy 1.75 EURUSD 1.16329000
2018.09.03 18:55:09.469 Test_hedge_properties (AUDNZD,H1)               2) #119214003 buy 2.55 EURUSD 1.16329000
2018.09.03 18:55:09.469 Test_hedge_properties (AUDNZD,H1)               3) #119214004 buy 1.25 EURUSD 1.16322000
2018.09.03 18:55:09.469 Test_hedge_properties (AUDNZD,H1)               4) #119214011 sell 3.00 EURUSD 1.16323000
2018.09.03 18:55:09.469 Test_hedge_properties (AUDNZD,H1)               5) #119214021 sell 4.50 EURUSD 1.16320000
2018.09.03 18:55:09.469 Test_hedge_properties (AUDNZD,H1)       Magic: 0
2018.09.03 18:55:09.469 Test_hedge_properties (AUDNZD,H1)       Time: 2018.08.31 16:38:10
2018.09.03 18:55:09.469 Test_hedge_properties (AUDNZD,H1)       Time in msc: 1535733490531
2018.09.03 18:55:09.469 Test_hedge_properties (AUDNZD,H1)       Update time: 2018.08.31 16:38:49
2018.09.03 18:55:09.469 Test_hedge_properties (AUDNZD,H1)       Update time in msc: 1535733529678
2018.09.03 18:55:09.469 Test_hedge_properties (AUDNZD,H1)       Type: HEDGE_NETTING_SELL
2018.09.03 18:55:09.469 Test_hedge_properties (AUDNZD,H1)       Type description: hedge netting sell
2018.09.03 18:55:09.469 Test_hedge_properties (AUDNZD,H1)       Volume: -1.95
2018.09.03 18:55:09.469 Test_hedge_properties (AUDNZD,H1)       Buy volume: 5.55
2018.09.03 18:55:09.469 Test_hedge_properties (AUDNZD,H1)       Sell volume: 7.50
2018.09.03 18:55:09.469 Test_hedge_properties (AUDNZD,H1)       Open price: 1.16303
2018.09.03 18:55:09.469 Test_hedge_properties (AUDNZD,H1)       Sl-price: -1.00000
2018.09.03 18:55:09.469 Test_hedge_properties (AUDNZD,H1)       Tp-price: -1.00000
2018.09.03 18:55:09.469 Test_hedge_properties (AUDNZD,H1)       Current price: 1.16198
2018.09.03 18:55:09.469 Test_hedge_properties (AUDNZD,H1)       Commission: 0.00
2018.09.03 18:55:09.469 Test_hedge_properties (AUDNZD,H1)       Swap: -37.20
2018.09.03 18:55:09.469 Test_hedge_properties (AUDNZD,H1)       Profit: 206.60
2018.09.03 18:55:09.469 Test_hedge_properties (AUDNZD,H1)       Margin: 1832.08

第3のオプションでは、AUDNZDシンボルのポジションを扱いました(図3)。スクリプトは、次の情報をログに出力します。

2018.09.03 18:47:25.369 Test_hedge_properties (EURUSD,H1)       ---== Hedge properties==---
2018.09.03 18:47:25.369 Test_hedge_properties (EURUSD,H1)       Symbol: AUDNZD
2018.09.03 18:47:25.369 Test_hedge_properties (EURUSD,H1)       Positions total = 5
2018.09.03 18:47:25.369 Test_hedge_properties (EURUSD,H1)               1) #119214062 buy 1.75 AUDNZD 1.08781000
2018.09.03 18:47:25.369 Test_hedge_properties (EURUSD,H1)               2) #119214068 buy 2.55 AUDNZD 1.08783000
2018.09.03 18:47:25.369 Test_hedge_properties (EURUSD,H1)               3) #119214071 buy 1.25 AUDNZD 1.08785000
2018.09.03 18:47:25.369 Test_hedge_properties (EURUSD,H1)               4) #119214083 sell 3.00 AUDNZD 1.08773000
2018.09.03 18:47:25.369 Test_hedge_properties (EURUSD,H1)               5) #119214092 sell 4.50 AUDNZD 1.08757000
2018.09.03 18:47:25.369 Test_hedge_properties (EURUSD,H1)       Magic: 0
2018.09.03 18:47:25.369 Test_hedge_properties (EURUSD,H1)       Time: 2018.08.31 16:39:41
2018.09.03 18:47:25.369 Test_hedge_properties (EURUSD,H1)       Time in msc: 1535733581113
2018.09.03 18:47:25.369 Test_hedge_properties (EURUSD,H1)       Update time: 2018.08.31 16:40:07
2018.09.03 18:47:25.369 Test_hedge_properties (EURUSD,H1)       Update time in msc: 1535733607241
2018.09.03 18:47:25.369 Test_hedge_properties (EURUSD,H1)       Type: HEDGE_NETTING_SELL
2018.09.03 18:47:25.369 Test_hedge_properties (EURUSD,H1)       Type description: hedge netting sell
2018.09.03 18:47:25.369 Test_hedge_properties (EURUSD,H1)       Volume: -1.95
2018.09.03 18:47:25.369 Test_hedge_properties (EURUSD,H1)       Buy volume: 5.55
2018.09.03 18:47:25.369 Test_hedge_properties (EURUSD,H1)       Sell volume: 7.50
2018.09.03 18:47:25.369 Test_hedge_properties (EURUSD,H1)       Open price: 1.08708
2018.09.03 18:47:25.369 Test_hedge_properties (EURUSD,H1)       Sl-price: -1.00000
2018.09.03 18:47:25.369 Test_hedge_properties (EURUSD,H1)       Tp-price: -1.00000
2018.09.03 18:47:25.369 Test_hedge_properties (EURUSD,H1)       Current price: 1.09314
2018.09.03 18:47:25.369 Test_hedge_properties (EURUSD,H1)       Commission: 0.00
2018.09.03 18:47:25.369 Test_hedge_properties (EURUSD,H1)       Swap: -21.06
2018.09.03 18:47:25.369 Test_hedge_properties (EURUSD,H1)       Profit: -779.45
2018.09.03 18:47:25.369 Test_hedge_properties (EURUSD,H1)       Margin: 1136.23

Test_hedge_properties.mq5のスクリプトコードは、アーカイブからダウンロードできます。


3.1ヘッジプロパティパネル

ここでの作業は複雑になります。標準ライブラリを使用して、私たちはHedgePropertiesEA.mq5アドバイザーを作成し、選択されたヘッジポジションのプロパティを表示するパネルをチャート上に表示します。

これらの目的のために、CAppDialog標準クラスの子孫になるCHedgeDialogクラスを作成します。後者の助けを借りて、パネルウィンドウの最小化と復元、パネル要素の変更処理など、典型的なタスクをプログラムする必要性を取り除きます。

//+------------------------------------------------------------------+
//| Class CHedgeDialog                                               |
//| Purpose: Class for displaying a hedge position info.             |  
//|              Derives from class CAppDialog.                      |
//+------------------------------------------------------------------+
class CHedgeDialog : private CAppDialog
  {
   //--- === Data members === --- 
private:
   CArrayString      m_symbols_arr;
   //--- controls
   CLabel            m_labels[FIELDS_NUM+1];
   CEdit             m_edits[FIELDS_NUM];
   CComboBox         m_combo;
   bool              m_to_refresh;
   //--- === Methods === --- 
public:
   //--- constructor/destructor
   void              CHedgeDialog(void) {};
   void             ~CHedgeDialog(void) {};
   //--- initialization
   bool              Init(void);
   void              Deinit(const int _reason);
   //--- processing
   void              OnChartEvent(const int _id,
                                  const long &_lparam,
                                  const double &_dparam,
                                  const string &_sparam);
   void              OnTradeEvent(void);
   //---
private:
   int               HedgeSymbols(void);
   void              RefreshPanel(void);
  };
//+------------------------------------------------------------------+

エキスパートコード内のクラスのインスタンスは、初期化、初期化イベント、スケジュールイベント、および取引操作に関連するイベントを呼出しおよび処理します。

ヘッジポジションプロパティパネルを図4に示します。

ヘッジポジションプロパティパネル

図4 ヘッジポジションのプロパティパネル

主なメソッドの1つはCHedgeDialog :: RefreshPanel()です。これは、いわば『動力』で必要に応じて、パネル情報フィールドを更新します。コーディングとテストのいくつかの困難さは、ヘッジの数が変更された場合に引き起こされました。この場合、ドロップダウンリストの一意の文字を変更し、OnChartEvent()ハンドラ呼び出しの無限ループに入る必要はありません。この為に長さが1秒のハンドラへの連続コールの制限を使用しました。

//--- check the limit for refreshing
if(!m_to_refresh)
  {
   uint last_cnt=GetTickCount();
   static uint prev_cnt=0;
   uint msc_elapsed=last_cnt-prev_cnt;
   prev_cnt=last_cnt;
   if(msc_elapsed>1000)
      m_to_refresh=true;
   else
      return;
  }

HedgePropertiesEA.mq5アドバイザーのフルコードはアーカイブファイルで参照できます。


まとめ

MetaTrader 5取引端末は、この段階では、マルチマーケットだけでなく、さまざまなポジション計算システムの使用もできます。このような機能は、取引アイデアの実装と形式化のためのツールを大幅に拡大します。

この記事が、MetaTrader 4からMetaTrader 5へ自分の戦略を移したい人にとって興味深いものになることを願っています。