MT4のポートフォリオトレード

transcendreamer | 3 10月, 2016


新たなサイクルが始まる
Publius Vergilius Maro, Eclogues

イントロダクション

ポートフォリオの原理は古くから知られています。いくつかに資金を多様化することで、投資家はポートフォリオ全体の損失のリスクを低減し、利益の伸びがよりスムーズになります。最初のポートフォリオの数学的モデルはハリー・マーコウィッツによって提案され、ポートフォリオ理論は、1950年に勢いを得ました。1980年代に、モルガン・スタンレーの研究チームは、マーケット・ニュートラル戦略のグループの道を開く最初のスプレッドトレード戦略を開発しました。現代ポートフォリオ理論は多様で、単一の記事ですべてのポートフォリオ戦略を説明することは困難です。そのため、MT4プラットフォームで可能な実装に伴う、戦略のほんの一部をここでは扱います。

この記事に適用されるいくつかの定義は以下のとおりです。

  • ポートフォリオ(バスケット、合成器) - 算出された最適のボリュームを持つ複数のトレーディングポジションのセット。ポジションは、共通の財務結果として追跡され、クローズされ、保有したままになります。
  • ポートフォリオ(バスケット、合成器)の調整 - 損失を最小化するか、または中間結果を修正するために、ポートフォリオのボリュームを変更します。
  • 合成ボリューム - 合成ポジションの数(ポートフォリオが買い・売りの数)。
  • 仮想利益/損失 - 一定の時間間隔内のポジションを保持したときに得ることができます。

古典的な投資ポートフォリオは、通常の株式相場で適用されます。ほとんどのポートフォリオが投機的であるので、このようなアプローチは、外国為替に合いません。若干異なるトレードがされています。外国為替に関して、ポートフォリオのトレードは、多通貨戦略はポートフォリオであり、実際には多通貨のトレードです。シンボルが独立してトレードされ、ダイナミクスが追跡されていない場合、シンボルトレードです。単一のトレード口座でトレードした場合、いくつかの独立したシステムは、戦略のポートフォリオです。ここでは、狭義のポートフォリオトレードを検討し - 合成ポジションは、いくつかのシンボルの外に形成され、その後管理されます。


原理

ポートフォリオの開発は、2段階で構成されています:シンボルを選択し、ロットと方向を計算します。ここでは、アルゴリズムのサンプルと一緒にいくつかの簡単なポートフォリオの開発メソッドについて説明します。特に、基礎として通常最小2乗法(OLS)、主成分分析(PCA)を提案します。さらに詳しい情報です:

ポートフォリオを開発する場合、ポートフォリオグラフの動作を定義することが必要です。ポートフォリオグラフは、一定の時間間隔内のポートフォリオに含まれるすべてのポジションの合計利益の変化を表しています。ポートフォリオの最適化は、ポートフォリオの挙動をフィッティングロットや方向の組み合わせの検索です。ポートフォリオは明確にマークトレンドや関数のグラフのようになり、そのチャート属性を持つようにするため、タスクに応じて、必要になることがあります。

3つのポートフォリオの種類(トレンド、フラット、関数):


ポートフォリオは、以下の式で表すことができます。

A*k1 + B*k2 + C*k3 + ... = F,

ただし

A、B、Cは...ポートフォリオのシンボルに対応しています

K1、K2、K3...シンボルロット( 正ー買い、負ー売り)

F -(時系列ポイントの値によって設定された)ターゲット関数

ゼロの定数項を持つ多変量線形回帰式です。そのルーツは、シンプルにOLSを使用して見つけることができます。まず、時系列は価格・ポイントが資産通貨にもたらされるべき互換性の意味をなすべきです。この場合、各時系列の各要素は、特定の時間に適切なシンボルの単一ロットの仮想の利益値を表します。予備的な価格、対数を使用した価格差は、通常、統計的なアプリケーションタスクに推奨されています。全体的なシンボルダイナミクスデータが途中で破壊されるので、有害である可能性があります。

目標関数は、ポートフォリオのグラフタイプを定義します。目標関数値は、予め各点で計算されるべきです。シンプルな成長ポートフォリオ(トレンド・ポートフォリオ)を開発する場合、目標のポートフォリオには、0, 1*S, 2*S, 3*S, と所定の間隔上の各バーで増加する必要があります。OLSアルゴリズムは、A、B、C、...総和を目的関数のグラフを繰り返します。OLSアルゴリズムは、直列和と目的関数との間の2乗偏差の和を最小にします。標準的な統計作業です。既製のライブラリを使用することができるので、アルゴリズムの詳細な理解は必要ありません。

また、ターゲット関数にゼロ(フラットポートフォリオ)が含まれているかもしれません。この場合、追加の比総和リミット(例:K1+ K2+ K3+···=1)に追加されるべきゼロ根で回帰方程式を解きます。代替案は、いつものように最適化されていながら、-1の割合を受け、目標関数を作る式の項を移動させることです。この場合、拡散されたポートフォリオを作成し、選択された機器にバスケットを同一視します。最後に、より高度なPCAアルゴリズムを、ポートフォリオを開発するために使用することができます。ポートフォリオの最小残差分散を有する点群断面超平面に対応する係数ベクトルを算出する共分散行列を適用します。既製のライブラリを使用することができるので、ここでも、詳細にアルゴリズムを理解する必要はありません。


アルゴリズム

MQL言語を用いて上記のすべてのアイデアを実装します。MT4に適合よいALGLIB数学ライブラリを使用します。問題はそのインストール時に発生する可能性があります。いくつかのターミナルがPCにインストールされている場合、別のターミナルのデータフォルダに配置されている場合、コンパイラは、ライブラリが表示されませんので、正しいデータフォルダーを見つけることは非常に重要です。

ALGLIBライブラリのインストール:

  1. download the library (https://www.mql5.com/ja/code/11077), unpack zip file;
  2. Mathディレクトリを見つけます。
  3. ライブラリに追加すべきMТ4を立ち上げます
  4. メニューコマンドを選択:Open Data Folder
  5. MQL4とIncludeサブフォルダを開きます。
  6. ターミナルのフォルダを含めるためMathフォルダをコピー。
  7. 結果を確認:*.mhqファイルは、 MQL4\Include\Math\Alglibに含めなければなりません。
最初のキーステージ:資産通貨への価格ポイントから時系列の変換。任意の時点でコントラクト価格を計算するために特別な関数を記述する必要があります。最後のグラフバーの正しい点の価格を提供するので、従来のマーケティング関数は適していません。問題は、一部のシンボルの点価格は常に変動して偏差が必然的に履歴に表示されていることです。したがって、ポートフォリオにおける著しい不均衡を避けるために、データ系列に変換することが重要です。

コントラクト価格を計算するサンプル関数を以下に示します。

double ContractValue(string symbol,datetime time,int period)
  {
   double value=MarketInfo(symbol,MODE_LOTSIZE);                     //ロットサイズを受け取る
   string quote=SymbolInfoString(symbol,SYMBOL_CURRENCY_PROFIT);     // 計算通貨を受け取る

   if(quote!="USD")                                                  //計算通貨がUSDではない場合、変換を実行
     {
      string direct=FX_prefix+quote+"USD"+FX_postfix;                // 計算通貨の直接の引用を形成
      if(MarketInfo(direct,MODE_POINT)!=0)                           //  存在の確認
        {
         int shift=iBarShift(direct,period,time);                    //時間によってバーを見つける
         double price=iClose(direct,period,shift);                   //足のクオートを受け取る
         if(price>0) value*=price;                                   // 価格を計算
        }
      else
        {
         string indirect=FX_prefix+"USD"+quote+FX_postfix;           //計算通貨の逆引用符を形成
         int shift=iBarShift(indirect,period,time);                  // 時間から足を見つける
         double price=iClose(indirect,period,shift);                 // バー引用
         if(price>0) value/=price;                                   // 価格を計算
        }
     }

   if(Chart_Currency!="USD")                                         //ターゲット通貨がUSDでない場合、変換
     {
      string direct=FX_prefix+Chart_Currency+"USD"+FX_postfix;       //ターゲット通貨の直接の引用を形成
      if(MarketInfo(direct,MODE_POINT)!=0)                           //  存在の確認
        {
         int shift=iBarShift(direct,period,time);                    //時間によってバーを見つける
         double price=iClose(direct,period,shift);                   //足のクオートを受け取る
         if(price>0) value/=price;                                   // 価格を計算
       }
      else
        {
         string indirect=FX_prefix+"USD"+Chart_Currency+FX_postfix;  //ターゲット通貨の逆引用符を形成
         int shift=iBarShift(indirect,period,time);                  // 時間から足を見つける
         double price=iClose(indirect,period,shift);                 // バー引用
         if(price>0) value*=price;                                   // 価格を計算
        }
     }

   return(value);
  }

この関数は、常に使用されます。通貨ペア、指数、先物およびCFDトレードで動作します。また、いくつかのブローカーによって適用されたシンボルのプレフィックスとポストフィックス(FX_prefix, FX_postfix)を考慮します。この結果は、ターゲット通貨(Chart_Currency)に変換されます。現在のシンボル価格でリターン関数値を乗算した場合、多くのシンボルの価格を取得します。ロットを考慮し、ポートフォリオ内のすべてのコントラクト価格を合計した後、ポートフォリオ全体の価格を取得します。時間の価格差により関数値を乗算した場合、その価格変更時に発生した利益または損失を受けます。

次のステップでは、個々のロットのコントラクトの仮想の利益を計算しています。2次元のサイズが一定数に制限することが可能であるが、最初の次元は、算出区間内の点のインジケーターである2次元配列として実装されたシンボルの量で、そのポートフォリオは、明らかに超えることはありません。

double EQUITY[][100];     // バーのある最初の次元

まず、(計算された区間の左境界上の)すべてのシンボルの初期価格を保存する必要があります。そして、最初と最後の価格との差が区間の各ポイントで計算され、コントラクト価格が乗算されます。ループ内の1つの時間間隔だけ右にシフト:

   for(int i=0; i<variables+constants; i++)                              //ポートフォリオシンボルループ(変数とモデルの定数)
     {
      int shift=iBarShift(SYMBOLS[i],Timeframe,zero_time);               //ゼロ点の時間によってバーインデックスを受け取る
      opening[i]=iClose(SYMBOLS[i],Timeframe,shift);                     //バーの価格を受信して、配列に保存
     }

   points=0;                                                             //変数でポイントを計算する
   datetime current_time=zero_time;                                      //ゼロ点からループを開始
   while(current_time<=limit_time)                                       // 最適化の間隔の時間ラベルに沿って通過
     {
      bool skip_bar=false;
      for(int i=0; i<variables+constants; i++)                           //ポートフォリオシンボルループ(変数やモデル定数)
         if(iBarShift(SYMBOLS[i],Timeframe,current_time,true)==-1)       // シンボルのバーの存在を確認
            skip_bar=true;                                               //バーが存在しない場合は、他のシンボルにをスキップ
      if(!skip_bar)                                                      // バーは全てのシンボル間で同期されている場合は運転を継続
        {
         points++;                                                       //1によってポイントの数を増やす
         TIMES[points-1]=current_time;                                   // メモリ内に格納する時間ラベル
         for(int i=0; i<variables+constants; i++)                        //メイン利益計算ループポイント
           {
            int shift=iBarShift(SYMBOLS[i],Timeframe,current_time);      //時間によってバーインデックスを受け取る
            closing[i]=iClose(SYMBOLS[i],Timeframe,shift);               //バーの価格を受け取る
            double CV=ContractValue(SYMBOLS[i],current_time,Timeframe);  //価格を計算
            profit[i]=(closing[i]-opening[i])*CV;                        // 価格差やコストによって利益を計算
            EQUITY[points-1,i]=profit[i];                                //利益値を保存
           }
        }
      current_time+=Timeframe*60;                                        //次の時間間隔にシフト
     }

zero_time — 計算された間隔の時間、 limit_time — 計算された間隔右側の境界の時間、Timeframe - 作業時間枠の1つのバーの数、points — 計算された間隔で検出されたポイントの合計数厳格なルールは、上記の例で使用されています。一定時間のラベルのバーが一つのシンボルに存在しない場合は、ポジションがスキップされ、次のものに形成されています。異なるシンボル上のデータのずれがポートフォリオに重大な歪みを引き起こす可能性があるので、時間のラベルを管理することは、予備データの準備が非常に重要です。

3つのシンボルと独立した関数(平方根パラボリック)用のサンプル・ポートフォリオデータ:

DATE/TIME AUDJPY GBPUSD EURCAD MODEL
03.08.16 14:00 0 0 0 0
03.08.16 15:00 -61,34 -155 -230,06 10,21
03.08.16 16:00 -82,04 -433 -219,12 14,43
03.08.16 17:00 -39,5 -335 -356,68 17,68
03.08.16 18:00 147,05 -230 -516,15 20,41
03.08.16 19:00 169,73 -278 -567,1 22,82
03.08.16 20:00 -14,81 -400 -703,02 25
03.08.16 21:00 -109,76 -405 -753,15 27
03.08.16 22:00 -21,74 -409 -796,49 28,87
03.08.16 23:00 51,37 -323 -812,04 30,62
04.08.16 00:00 45,43 -367 -753,36 32,27
04.08.16 01:00 86,88 -274 -807,34 33,85
04.08.16 02:00 130,26 -288 -761,16 35,36
04.08.16 03:00 321,92 -194 -1018,51 36,8
04.08.16 04:00 148,58 -205 -927,15 38,19
04.08.16 05:00 187 -133 -824,26 39,53
04.08.16 06:00 243,08 -249 -918,82 40,82
04.08.16 07:00 325,85 -270 -910,46 42,08
04.08.16 08:00 460,02 -476 -907,67 43,3
04.08.16 09:00 341,7 -671 -840,46 44,49


用意したデータを最適化モデルに送信します。最適化はALGLIBライブラリからLRBuildZ, LSFitLinearC 、 PCABuildBasis関数を使用して行います。この関数は、シンプルにライブラリ自体だけでなく、公式プロジェクトのウェブサイトの内側に記載されています。 http://www.alglib.net/dataanalysis/linearregression.phpと:http://www.alglib.net/dataanalysis/principalcomponentsanalysis.php

まず、ライブラリを確認します。

#include <Math\Alglib\alglib.mqh>

次に、モデルの特徴を考慮したコードの断片を、各最適化モデルに設定する必要があります。まずは、サンプルのトレンドモデルを調べてみましょう:

   if(Model_Type==trend)
     {
      int info,i,j;                                                                                  // 作業変数を定義
      CLinearModelShell LM;                                                                          //特別なオブジェクト・モデルを定義
      CLRReportShell AR;                                                                             //特別なオブジェクトのレポートを定義
      CLSFitReportShell report;                                                                      // 別のオブジェクトを定義します
      CMatrixDouble MATRIX(points,variables+1);                                                      //すべてのデータを格納するための行列を定義
      if(Model_Growth==0) { Alert("Zero model growth!"); error=true; return; }                       // verify the model parameters
      for(j=0; j<points; j++)                                                                        //最適化の間隔ポイントによって目標関数を計算
        {
         double x=(double)j/(points-1)-Model_Phase;                                                  //X座標を計算
         if(Model_Absolute) x=MathAbs(x);                                                            //必要に応じて左右対称のモデルを作る
         MODEL[j]=Model_Growth*x;                                                                    // Y座標を計算
        }
      double zero_shift=-MODEL[0]; if(zero_shift!=0) for(j=0; j<points; j++) MODEL[j]+=zero_shift;   // ゼロ点に垂直モデルをシフト
      for(i=0; i<variables; i++) for(j=0; j<points; j++) MATRIX[j].Set(i,EQUITY[j,i]);               // マトリックスへのシンボルデータをダウンロード
      for(j=0; j<points; j++) MATRIX[j].Set(variables,MODEL[j]);                                     //行列にモデルデータをダウンロード 
      CAlglib::LRBuildZ(MATRIX,points,variables,info,LM,AR);                                         // 回帰計算を起動します
      if(info<0) { Alert("Error in regression model!"); error=true; return; }                        // 結果を確認
      CAlglib::LRUnpack(LM,ROOTS,variables);                                                         // 平方根を受け取る
     }

最初は、複雑に見えるかもしれませんが、基本的に簡単です。開始時に、線形トレンド関数を算出し、MODEL配列に配置されています。モデルの成長パラメータは、全体の計算区間(ポートフォリオは資産通貨に成長する必要があります)の成長値を設定します。Model_AbsoluteとModel_Phaseのパラメータはオプションであり、現段階では重要です。行列は、計算(MATRIX)に作成されます。EQUITY配列と同様に、MODEL配列からの目標関数値から全てのコントラクトの仮想利益のデータは行列の最後の行にダウンロードされます。独立した回帰式の変数は、「変数」に格納されます。LRBuildZ関数は計算を実行するために後で呼び出されます。その後、回帰方程式の根はLRUnpack関数を使用してROOTS配列に書き込まれます。既製の関数を使用することができ、すべての複雑な数学は、ライブラリ内にあります。正確にすべてのコールを設定し、準備中のデータを保存します。

同一のコードの断片は、任意の関数に使用することができます。ターゲット関数を持つMODEL配列の内容を交換してください。サンプルの平方根パラボリック関数の計算を以下に示します。

      for(j=0; j<points; j++)                               //最適化の間隔ポイントによって目標関数を計算
        {
         double x=(double)j/(points-1)-Model_Phase;         // X軸値を計算
         int sign=(int)MathSign(x);                         ////シンボルを定義する
         if(Model_Absolute) sign=1;                         // 必要に応じてモデルを対称にします
         MODEL[j]=sign*Model_Growth*MathSqrt(MathAbs(x));   // Y軸値を計算
        }

線形トレンドと調和振動の和を表す関数の例は次のとおりです。

      for(j=0; j<points; j++)                                     // 最適化の間隔ポイントによって目標関数を計算
        {
         double x=(double)j/(points-1)*Model_Cycles-Model_Phase;  // X軸値を計算
         if(Model_Absolute) x=MathAbs(x);                         // 必要に応じてモデルを対称にします
         MODEL[j]=Model_Amplitude*MathSin(2*M_PI*x);              // Y軸の値を計算します
        }

上記の例では、発振振幅(Model_Amplitudeパラメータを使用して)と トレンドサイズ(Model_Growthパラメータを使用)を管理することが可能です。振動の位相シフトは、Model_Phaseを使用して行われている間、発振サイクルの数は、Model_Cyclesによって設定されます。

また、垂直シフト関数は計算が正しいことを確認するため、ゼロ点でゼロに等しくなるようにする実行する必要があります。

   double zero_shift=-MODEL[0];   //ゼロ点でのモデル値を読み込む
   if(zero_shift!=0)              // 必ずゼロでないことを確認してください
      for(j=0; j<points; j++)     //すべての間隔のポイントに沿って通過
         MODEL[j]+=zero_shift;    //すべてのモデル点をシフト

シンプルにカスタム関数を開発することを可能にします。タスクとのトレードの設定に応じて任意の関数型を作成することができます。より複雑な関数型は、相場が関数に従うことが義務付けられていないので、最適なソリューションを選択することです。ここでは、関数は近似値です。

フラットなポートフォリオを返すために、目的関数を必要としません。2つのシンボルのバスケットのスプレッドを作成する場合、参照バスケットは合計として行列の最後の列に対象の関数として使用され、ダウンロードされている間、最適化されたバスケットは、マトリックスの主要部分にダウンロードされます:

   for(i=0; i<variables; i++)                    // 最適化されたバスケットのシンボルによってサイクル
      for(j=0; j<points; j++)                    //計算された間隔の点によってサイクル
         MATRIX[j].Set(i,EQUITY[j,i]);           // 行列の列に最適化されたバスケットのアップロードシンボル値
   for(i=variables; i<variables+constants; i++)  // //参照バスケットシンボルによってサイクル
      for(j=0; j<points; j++)                    //計算された間隔の点によってサイクル
         MODEL[j]+=EQUITY[j,i]*LOTS[i];          //行列の最後の列への参照バスケットのアップロードシンボル値

LSFitLinearC関数が計算された期間内にゼロの周りにできるだけ対称的なポートフォリオを作るサンプルフラットポートフォリオの計算は次のとおりです。

   if(Model_Type==fitting)
     {
      int info,i,j;                                                                        //作業変数を定義
      CLSFitReportShell report;                                                            //特別なオブジェクト・モデルを定義
      CMatrixDouble CONSTRAIN(1,variables+1);                                              // リニア制限の行列を定義します
      CMatrixDouble MATRIX(points,variables);                                              //すべてのデータを格納するための行列を定義
      ArrayInitialize(MODEL,0);                                                            // ゼロでモデルを埋めます
      CONSTRAIN[0].Set(variables,1);                                                       //制限を設定する
      for(i=0; i<variables; i++) CONSTRAIN[0].Set(i,1);                                    // 根の合計が1に等しくなければなりません
      for(i=0; i<variables; i++) for(j=0; j<points; j++) MATRIX[j].Set(i,EQUITY[j,i]);     // マトリックスへのシンボルデータをダウンロード
      CAlglib::LSFitLinearC(MODEL,MATRIX,CONSTRAIN,points,variables,1,info,ROOTS,report);  //OLSを用いた最適化モデルを計算
      if(info<0) { Alert("Error in linear fitting model!"); error=true; return; }          // 結果を確認
     }

PCA法を用いて、最小分散を有する平坦なポートフォリオを計算する重要な例です。ポートフォリオグラフは可能な限り計算区間内で圧縮し、PROBuild基底関数は、比率を計算します。

   if(Model_Type==principal)
     {
      int info,i,j;                                                                        //作業変数を定義
      double VAR[];                                                                        // 分散配列を定義
      ArrayResize(VAR,variables);                                                          //必要な次元に配列を変換する
      CMatrixDouble VECTOR(variables,variables);                                           //係数ベクトルの行列を定義 
      CMatrixDouble MATRIX(points,variables);                                              //すべてのデータを格納するための行列を定義
      for(i=0; i<variables; i++) for(j=0; j<points; j++) MATRIX[j].Set(i,EQUITY[j,i]);     // マトリックスへのシンボルデータをアップロード
      CAlglib::PCABuildBasis(MATRIX,points,variables,info,VAR,VECTOR);                     //PCAを使用して直交基底を計算
      if(info<0) { Alert("Error in principal component model!"); error=true; return; }     //結果をチェック
      for(i=0; i<variables; i++) ROOTS[i]=VECTOR[i][variables-1];                          //最適な比率をアップロード
     }

数学に圧倒されても、心配しないでください。すでに述べたように、すべての数学的な詳細を理解する必要はありません。一般的な、一連のステージです。

1 ポートフォリオシンボルの仮想利益の計算
2 目的関数値を計算
3 ロットの最適化アルゴリズム
4 ポートフォリオボリュームの正規化
5 ポートフォリオを使ってグラフ計算およびトレード

多くの手順を使用して、最適な比率のROOTS配列を取得しと、ロット比率をオンにします。スケーリングと丸め:これを行うには、正規化が必要です。必要なスケールを設定すると、トレードするロットが便利になります。ブローカーの要件に合わせて容量を参照する必要があります。時には、ポートフォリオ全体のマージンによって正規化を実行することが推奨されていますが、(個々のシンボルのマージンが変化し、変更できるので)、このメソッドは重大な欠点があります。したがって、ポートフォリオの価格またはそのボラティリティによって正規化を実行します。

ポートフォリオの価格で正規化アルゴリズムの簡単な例を示します。

      double total_value=0;                                                                         // ポートフォリオの価格の変数を定義
      for(int i=0; i<variables+constants; i++)                                                      //すべてのポートフォリオシンボルに沿って通過
         total_value+=closing[i]*ContractValue(SYMBOLS[i],limit_time,Timeframe)*MathAbs(LOTS[i]);   //計算と価格のコンポーネントを合計

      if(total_value==0) { Alert("Zero portfolio value!"); error=true; return; }                    // 必ず結果がゼロでないことを確認してください
      scale_volume=Portfolio_Value/total_value;                                                     // スケーリング比を見つけます

      for(int i=0; i<variables+constants; i++)                                                      // もう一度、すべてのポートフォリオシンボルに沿って通過
         LOTS[i]=NormalizeDouble(LOTS[i]*scale_volume,Lots_Digits);                                 //必要な合計で失われた変換

LOTS[i]は=<s0> NormalizeDouble</s0>(LOTS[O] *スケールのボリューム、たくさん桁)。<s1>//必要な合計金額に失われた変換</s1>Portfolio_Value - 必要なポートフォリオの価格、TOTAL_VALUE - デフォルト率とポートフォリオ全体の価格、scale_volume - スケーリング比、Lots_Digits - ロット容量、LOTS - トレードの適切なロット値の配列。

ロットの値は、最終的なポートフォリオの構造を形成します。正のロットはロングポジションに、負のロットはショートポジションに対応しています。ポートフォリオの構造から、そのグラフをプロットし、ポートフォリオにトレーディングオペレーションを行うことができます。正規化後のサンプル・ポートフォリオの構造は次のとおりです。

Symbol AUDJPY GBPUSD EURCAD
Lot -0,07 -0,11 -0,11

ポートフォリオグラフの閉じる価格でプロットし、別々のインジケータサブウィンドウに表示されます。ポートフォリオグラフを構築するために、各チャートのバーに別々のシンボルの仮想の利益が以前に計算されているのと同じメソッドで計算する必要があります。しかし、割り当てられたロットを考慮に入れます。

   for(int j=draw_begin; j>=draw_end; j--)                                                   //描画間隔内のチャートのバーによってサイクル
     {
      double profit=0;                                                                       //値で始まる
      for(int i=0; i<variables; i++)                                                         //すべてのシンボルに沿って通過
        {
         if(Fast_Period>0 && Slow_Period>0 && number!=N_TOTAL)                               //補助チェックを実行
           {
            int shift=iBarShift(SYMBOLS[i],Period(),Time[j]);                                //時間によってバーインデックスを取得
            double CV=ContractValue(SYMBOLS[i],Time[j],Period());                            //落札価格を計算
            double fast=iMA(SYMBOLS[i],Period(),Fast_Period,0,MODE_SMA,PRICE_CLOSE,shift);   //スロー平均値を計算
            double slow=iMA(SYMBOLS[i],Period(),Slow_Period,0,MODE_SMA,PRICE_CLOSE,shift);   //ファスト平均値を計算
            profit+=(fast-slow)*CV*LOTS[i];                                                  // 振動モデルを計算
           }
         else
           {
            int shift=iBarShift(SYMBOLS[i],Period(),Time[j]);                                //時間によってバーインデックスを受け取る
            double closing=iClose(SYMBOLS[i],Period(),shift);                                // ポイントにシンボル価格を受け取ります
            double CV=ContractValue(SYMBOLS[i],Time[j],Period());                            //落札価格を計算
            profit+=(closing-OPENINGS[i])*CV*LOTS[i];                                        //価格差やコストによって利益を計算
           }
        }
      BUFFERS[number].buffer[j]=NormalizeDouble(profit,2);                                   // インジケータ配列に利益値を保存
     }

draw_beginとdraw_end:このコードでは、チャートが最初と最後のバーの間にプロットされていることがわかります。ポートフォリオ値は、価格コントラクト価格を乗じ、以前に計算されたように計算されるすべてのシンボルで利益/損失の和に等しいです。インジケータバッファ、書式設定などに関連するテクニカル的な側面をスキップしています。サンプルの既製ポートフォリオインジケーターは、以下のセクションに記載されています。

ここでは、添付のターゲット関数グラフでサンプルポートフォリオグラフ構築(インジケータ下のサブウインドウ)を調べることができます。

 

ここでは、平方根のパラボリックは、基準点に対して対称に作られた(Model_Absolute=true)目的関数として使用されています。ポートフォリオグラフは内と算出された区間のうち、両方の目的関数ラインに沿って移動する傾向がある一方で、計算された区間の境界は、赤い点線で示されています。

適用移動平均、トレンドラインとレベルを含む通常のシンボル価格チャートに似たポートフォリオグラフの技術的な分析を行うことができます。トレード関数は、フラット、買われ過ぎ、売られ過ぎ、収束- 発散、ブレイクアウト、トレンドインパルスのポートフォリオのグラフ上の特定のトレードのセットアップを形成するため、ポートフォリオの構造を選択することを可能にします。トレードセットアップの品質は、ポートフォリオ構成、最適化メソッド、目的関数と、選択履歴セグメントによって影響されます。

適切なトレードを選択するために、ポートフォリオのボラティリティを知る必要があります。ポートフォリオチャートが最初に資産通貨に基づいているので、「十字」カーソルモードを使用すると、その通貨で直接ポートフォリオの変動範囲と潜在的なドローダウンの深さを評価することができます。

トレードシステムは、ポートフォリオの行動特性に基づいて統計を設定する必要があります。ポートフォリオの動作が最適化区間外に劇的に変化する可能性があるという事実に言及していません。トレンドはフラットに、フラットはトレンドになるかもしれません。トレードシステムは、また、ポートフォリオの特性が変化するトレンドがあることを考慮する必要があります。この問題は、以下に説明します。

ポートフォリオとトレーディングオペレーションは、計算されたボリュームを持つすべてのポートフォリオのシンボルを売り/ワンタイム買いで構成される。ポートフォリオの構造データを取得する合成ポジションを準備し、利益を固定し、損失を限定するなど、すべてのルーチン作業を実行するための特別なEAにすることが妥当でしょう。EAの操作に関する以下の条項が適用されます:ロング合成ポートフォリオのポジションと(ロング・ポジションおよびその逆に置換されます)ショート合成ポートフォリオのポジション。EAは、蓄積合成ボリュームを追跡、ならびにポートフォリオ・ネッティングと変換を実行することができるはずです。サンプルEAは、次のセクションで考えられています。

以下のポートフォリオEAのサンプルの最小限のインターフェイスは、次のとおりです。


 

時々、いくつかのポートフォリオではないものを構築することが必要です。最もシンプルな場合、2つのポートフォリオを比較するために必要とされます。一部のタスクは、特定のパターンを含むポートフォリオのセットで得られたヒストリーセグメント上に構築されるポートフォリオ全体のシリーズを必要とします。そのようなタスクを実現するために、特定のテンプレートに従ってポートフォリオを生成するアルゴリズムが必要とされます。このようなインジケータの実装例は、次のセクションで見つけることができます。ここで、その最も重要な運用関数を説明します。

例えば、複数のポートフォリオのデータを格納する構造体配列を配置する必要があります。

struct MASSIVE                     //複数のデータ型を含む構造体を定義する
  {
   string symbol[MAX_SYMBOLS];     //ポートフォリオシンボルのテキスト配列
   double lot[MAX_SYMBOLS];        //ロットの数値配列
   string formula;                 //ポートフォリオ式の文字列
   double direction;               //ポートフォリオ方向属性
   double filter;                  // filter属性
  };

MASSIVE PORTFOLIOS[DIM_SIZE];      //ポートフォリオのグループの構造体配列を作成

このコードでは、DIM_SIZEはポートフォリオを格納するための最大サイズを設定します。構造は次のように編成されている:symbol — ポートフォリオシンボル列、lot — ポートフォリオシンボルにたくさんの配列、formula — ポートフォリオ式テキスト文字列、direction — シンボルポートフォリオ方向を(長いか短い)、filter — フィルター属性(含まれる/除外)。構造体配列を適用すると、別々の配列を使用するよりも便利で合理的です。

構造体配列はまた、ポートフォリオグラフ・バッファ・配列を格納するために作成することができます。

struct STREAM{double buffer[];};     // 数値配列を含む構造を定義
STREAM BUFFERS[DIM_SIZE];            //構造体配列を作成

セット内のポートフォリオは、そのシンボルの組み合わせによって異なります。組み合わせは、特定のルールに従って予め定義されるか、または生成することができます。ポートフォリオのセットで作業するタスクに応じて、いくつかの段階を含むことができます。では、ここでのステージの次のシーケンスを考えてみましょう:

1 個別のポートフォリオのチャートの計算
2 ゼロ点でポートフォリオのセットを組み合わせます
3 ゼロレベルを基準にポートフォリオを逆転
4 ポートフォリオのセットにフィルタを適用します
5 要約 - スーパーポートフォリオを形成します
まず、セット内の個別のポートフォリオは、先に説明した原理に従って計算されます。ゼロ時点でのポートフォリオを組み合わせることは、分析を容易にするために必要とされます。すべてのポートフォリオがゼロに等しくなる点が、選択されます。ゼロレベルを基準にポートフォリオを逆にし、分析をシンプル化することが有用です。ロットが反転された後、立ち下がりのポートフォリオは、成長します。セット内のフィルタリングポートフォリオは、他のポートフォリオに設定された相対的な範囲内で、ゼロからいくつかの基準によって成長速度を最高のポートフォリオを選択します。よって、最高のポートフォリオが選択され、ポートフォリオのバスケット、またはスーパーポートフォリオ(ポートフォリオの重ね合わせ)になります。 

下の画像は、手順を示しています。


 

垂直シフトポートフォリオを結合するために使用されます。-1を掛けたときにポートフォリオが逆になります。最後に、フィルタは、ソートおよび値でサンプリングすることにより適用されます。アルゴリズムの詳細な説明は、巨大になることを避けるために、ここで提供されていません。

後述の原理に従った構成ポートフォリオのサンプルセットは、次のとおりです。

 

このグラフは、短い期間でPCAモデルによって計算されたポートフォリオのセットを示しています。赤い破線として算出区間の境界が示されています。ここでは、最適化の間隔側に設定し、ポートフォリオの拡大を見ることができます。フィルタアプリケーションのモーメントは紫色の点線でマークされている一方で、ゼロ点は、左の最適化間隔の境界で選択されています。太線はスーパーポートフォリオの最もアクティブなポートフォリオから成り、ゼロ点からの概要を説明します。

分析の追加の可能性はポートフォリオを提供して組み合わせると、トレード戦略を開発し、別および他のアプローチに移動し、ポートフォリオのねじれを待って、ポートフォリオの組の収束・発散、ポートフォリオの間に広がります。


実装例

この記事に記載されているメソッドは、ポートフォリオのインジケーターと半自動化EAとして実装されています。ここでは、説明書のソースコードをダウンロードして、ニーズに適応させることができます。

  • ポートフォリオモデラー - ポートフォリオ開発者およびオプティマイザ。設定可能なパラメータを持ついくつかの最適化モデルの種類を提供しています。また、自身のモデルとターゲット関数を追加することができます。ポートフォリオのテクニカル分析、ならびに様々なチャートの書式設定オプションの基本的なツールもあります。

  • ポートフォリオマルチグラフ - ポートフォリオのジェネレーターは、同じモデルとパラメータとポートフォリオだけでなく、スーパーポートフォリオを作成するための追加オプションで設定します。

  • ポートフォリオ・マネージャー - EAポートフォリオとスーパーポートフォリオを扱います。ポートフォリオのインジケーターと連動して動作と同様に、仮想オーダーのグラフィカルラインに基づいて、ポートフォリオ補正関数とオートトレーディング・モードを持つ合成ポジションを管理することができます。

ダウンロードリンク: https://www.mql5.com/ja/code/11859 (ロシア語)


トレード戦略

合成に基づいた多くのトレード戦略があります。ポートフォリオのトレード戦略を作成する際に役立つ、いくつかの基本的なアイデアを考えてみましょう。同時に、リスクと制限を忘れるわけにはいきません。

ポートフォリオを生成する古典的なアプローチは、上昇を期待してポートフォリオに成長可能性を持つ割安資産を識別して含めることです。ポートフォリオのボラティリティが含まれるボラティリティの合計よりも常に低いです。このアプローチは、株式相場には良いのですが、通貨は、通常の株式とは異なり、持続的な成長を示すものではないので、外国為替上では制限された使用です。

ウォーレン・バフェットの長期ポートフォリオは次のとおりです。

 

標準的な投資ポートフォリオで作業する場合、慎重に価格下方への移動中に買いをするために、現在の資産状況を評価する必要があります。

2相関のシンボルの広がりを作成 - 投機的なポートフォリオトレードの最も簡単なオプションは、ペアのトレードです。高い相関通貨ペアは共和分を持っていないので、外国為替では、このアプローチは大幅に制限されています。ここでは、「壊れたスプレッド」を扱います。共通通貨とのペアは、通常、スプレッドに含まれているため、このようなペアのトレードは、合成クロスレートになります。この種のペアトレードは非常に悪い考えです。スプレッドによって反対のポジションを開いた後、時々曲線が再び収束する前に非常に長い時間を待たなければなりません。

高度な相関ペアとその段階的かつ必然的な発散の例は次のとおりです。

 

3つ以上の通貨ペアがスプレッドに含まれている場合は、このアプローチの開発は、多国間スプレッドトレードです。組み合わせのオプションより大きな数の広がりを作成することが容易にあるので、既にペアトレードよりも優れています。ただし、同じリスクが残ります:スプレッドが発散して、再度収束することがない。穏やかな相場で良いスプレッドリターンを達成するのは簡単ですが、ニュースは、しばらく後に急速かつ不可逆的な発散を引き起こします。スプレッドで数を増やす場合は、ニュース・リリース時に大きな可能性が関与しているので、発散確率は、同様に増加します。平らな相場で動作するので、極めて有害な戦略となり、再び収束を待ちます。

下記のニュースリリース中のサンプルの動作は次のとおりです。

 

スプレッドトレードは、資産間の基本的な接続がある場合に、株式や為替相場でより多くの機会があります。しかし、配当日または先物コントラクト満了時のスプレッド格差に対する保証はまだありません。スプレッドは、相場指数と先物で構成することができますが、為替トレードの特徴を考慮しなければなりません。

周期的に関連する通貨ペア(例えば、EURUSD、GBPUSD-EURGBP)を選択し、バランスのとれたスプレッドを形成するために使用されるときにスプレッドトレードのデッドエンドブランチマルチロックによって表されます。このケースでは、全体のスプレッドと手数料が高すぎるので、トレードすることは不可能です。不平衡負荷にビットをしようとすると、コストが十分に高いままで、スプレッドトレードと矛盾します。

バランスのとれたマルチロックの一例です。総スプレッドは2つの赤い線で示されています:

 

スプレッドトレードの欠点により、モデルをトレンドに切り替えてください。より高いレベルでの利益と訂正し、終了時に次のようにエントリーします。一見すると、すべてが十分にここに調和のとれたように思われます。

良好なトレンドモデルの一例は次のとおりです。

 

しかし、トレンドモデルは、シンプルで便利ではない場合があります。時には、ポートフォリオがさらに成長することを拒否し、時には大幅にダウンになります。ここでは、「壊れたトレンド」を扱います。短期および中期的なモデルでかなり頻繁に発生します。トレード効率はここで相場のフレーズに大きく依存します。相場がトレンドであると、システムがうまく動作します。相場が平坦である場合、多数の損失が発生する可能性があります。

下に鋭いトレンドを見ることができます:

 

伝統的なアプローチを再考してください。スプレッドブレイクアウトとトレンド反転のトレードメソッドを見てみましょう。一般的な仮定では、ポートフォリオの不安定性を回避することができないので、メソッドを学ぶべきです。

拡散ブレイクアウトの設定をするために、強力な動きを見越して最小限の非常にコンパクトな短周期の広がりを作成する必要があります。ポートフォリオのボラティリティを、「アウトバースト」圧縮します。加速拡散ブレイクアウトの場合、トレードセッションを開始する前に、ニュースにセットアップを形成することができます。PCAの最適化メソッドは、ボラティリティの圧縮に最適です。この設定では、拡散境界から移動するときにブレイクアウトが発生するため、エントリが既に定義されています。

境界がハイライトされ拡散チャネルを持つ短周期拡散チャネルからのサンプルの決済は、次のとおりです。

 

このメソッドの利点:短周期スプレッドはチャート上で頻繁にあり、ブレイクアウト後のボラティリティは、多くの場合、スプレッド幅を超えています。欠点:スプレッドはニュースリリース中に展開され、価格が上に移動し、数回上下するとき形成されます。保守的なエントリは、補正時のスプレッドを出た後の代替として提案することができます。

トレンド反転の設定を作成するには、トレンドモデルも同様に回転運動やポートフォリオの価格水準が追跡されます。移動方向が明確に定義されていますが、トレンドが反転するときは事前に分かりません。内部トレンドラインの交差、逆補正やロールバックは保守的なエントリに追跡されます。外部のトレンドラインとロールバックに触れることは積極的なエントリに追跡されます。

外部と内部の線でトレンドポートフォリオの例は次のとおりです。

 

このメソッドの利点:優れたエントリー価格、利便性、極端な価格の不安定性は、セットアップで動作します。短所:ポートフォリオの価格が原因で、トレンドが上がることがあります。この状況を改善するために、複数のレベルからの分別エントリーすることができます。

同様の設定は平方根パラボリック関数モデルを用いて実施することができます。周知の特性に基づいている価格は、相場の分布範囲の理論的なリミットに達した場合、そのさらなる移動が妨げられます。他のケースと同様に、目標の最適化関数は、現在の相場の流通に調整されます。相場が通常のガウス分布を特色にしていた場合、時間ベースの平方根の法則は常に持って完璧に働いたが、相場の分布は、その自然の中でフラクタルであるため、状況の調整が必要となるでしょう。

エドガー・ピーターズの書籍に詳細があります。

  • キャピタル・マーケッツにおけるカオスとオーダー
  • フラクタル相場分析

パラボリック関数から離れるポートフォリオの例は次のとおりです。

 

このセットアップでは、中期的なボラティリティに適応するのに最適です。しかし、シンプルにトレンドのセットアップの場合と同様に、ポートフォリオの価格が原因で根本的な要因に上方に移動することができます。相場は、任意の目的関数の振る舞いに従うことを義務付けられていませんが、どちらか同様に逸脱する義務があります。2重性は常に残ります。すべてのトレードのセットアップは、相場中立型の絶対的な意味ではありませんが、テクニカル分析のいくつかのフォームに基づいています。

トレンドとフラットの2重の性質を以下に見ることができます。トレンドモデルは、より大きなスケールでの不均一なフラットのようになります。

 

ポートフォリオを開発する場合は別にシンボルコンビネーションモデルタイプから、推定区間の境界のポジションは非常に重要です。ポートフォリオを構成するとき、境界線を移動し、結果を比較することは有用かもしれません。境界の良い選択は、トレードのセットアップの点でより適しているポートフォリオを見つけることができます。ポートフォリオポジションがドローダウンに入った場合、既存のポジションを閉じずに、ポートフォリオを補正することができます。境界をシフトすると変化する状況に適応ポートフォリオ曲線を変更します。ポジションは、ポートフォリオを再配置した後に応じて修正する必要があります。ドローダウンが減少することを意味するものではありませんが、補正されたポートフォリオは、より効率的になる可能性があります。

いくつかのポートフォリオ・セットの特性やトレードシステムでの適用可能性を検討してみましょう。

ポートフォリオの最初のプロパティはゼロ点からの距離にポートフォリオのセットの拡張、または発散するために設定します。このプロパティを使用するのが自然と合理的であろう:上昇ポートフォリオの売買落下。

ポートフォリオの組を拡大するサンプルは、次のとおりです。

 

第2の特性 - ポートフォリオセット圧縮(収束)が - 前のものとは反対です。展開後に発生します。拡張および圧縮サイクルは、拡張の疑惑最高度に達した後、セットの中心に戻るのを見越して、合成ポジションを開くために使用できることを示唆しています。しかし、拡張最高度は、常に変化し、設定された曲線の拡大の最終的な境界を予測することは不可能です。

ポートフォリオのサンプル圧縮セットは、次のとおりです。

 

様々な標的関数、ろ過パラメータ、反転および組み合わせを提供して適用し、効率的なトレードのセットアップを検索します。トレードやトレードロールバック:一般的に、全ての設定は、2つのクラスに分けることができます。

ポートフォリオ・セットのシフトを有する第一のタイプのトレード設定の例は次のとおりです。

 

マルチトレンドモデルに基づいて、ロールバックトレードのセットアップを以下に示します。

 

別の定期的なポートフォリオのプロパティは、設定されたツイスト(自己交差)です。相場動向の変化に対応します。ポートフォリオの拡大を見越してトレードする場合、ねじれはセットの再配置を必要とする負の効果です。他のメソッドについては、いくつかのポートフォリオ曲線の交差が再生アウトポートフォリオを識別するために使用することができます。その距離は、目標関数に設定され、レベル、ポジションを移動し考慮する必要があります。

複数回ひねりセットの例は以下のとおりです。

 

トレードシステムの重要な部分ですが、今までボリューム管理の問題までに注意していません。一般的に、以下のアプローチを記述することができます。

  • 単一の合成ポジション(最もシンプルな場合)トレード
  • ボリュームを分割する(レベルによって拡張エントリー)
  • 上昇ポートフォリオに追加する(トレンドによってピラミッド)
  • ドローダウンでポートフォリオに追加する(ポジションの平均化)
  • 補正後のポートフォリオに追加する(メソッド)
  • 反転(拡大戦略)後のポートフォリオに追加
  • 新しいポートフォリオに追加する(ポートフォリオ統合)
  • 複合アプローチ(いくつかのアプローチを組み合わせ)

特定のボリューム管理メソッドは、トレードシステムの特徴を考慮して選択する必要があります。利益とドローダウンを計画する際には、計算は、ポートフォリオのボラティリティに基づいている必要があります。最もシンプルなケースでは、ポートフォリオの変動性は、特定のセグメント内のグラフの移動範囲として評価することができます。最適化の間隔内が、前の履歴にだけでなくだけでなく、ボラティリティを評価するためにはるかに優れています。ポートフォリオの変動を知ることは、一連のポジションで最大合計ドローダウンの理論値を計算することが可能です。あまりにも頻繁に積極的にボリュームが追加します。トレード口座上のポートフォリオ・カバレッジに割り当てられた総資金は、すべての追加ポジションが不利な動きを耐えることができなければなりません。

マルチポートフォリオトレードは、体系的なポートフォリオ選択と統合を意味します。別のものが追加されている場合、ポートフォリオの正の分散効果が顕著な違いがあってもよいです。ポートフォリオが相関している場合には、両方が、好ましくない場合にドローダウンで自分自身を見つけることができるので、負の効果を有していてもよいです。通常は、相関のポートフォリオを追加することは避けるべきです。一見すると、相関ポートフォリオ間のトレードスプレッドは非常に有望であると思われるかもしれませんが、綿密に検討すると、このようなスプレッドは通常のスプレッドと何ら変わりがないことを示しています。

様々な決済戦略は、マルチポートフォリオトレードに適用することができます。

  • すべてのポートフォリオの合計結果によって閉じます
  • グループの総合結果によりポートフォリオのグループを閉じます
  • 特定のポートフォリオのターゲットとリミットによって決済。

いくつかの戦略については、エントリポイントは非常に重要です。この戦略は、トレンド反転や補正、エントリに適した期間前に極端な価格を適用した場合、非常に短いです。他の戦略は、システムおよびポートフォリオ選択の原則を追加するポジションの最適な計算に依存しています。この場合、個々のポートフォリオはドローダウンでエントリーすることができますが、連結シリーズ内の他の(より効率的な)ポートフォリオは、全体的な結果を調整します。


結論

ポートフォリオトレードの利点:最適化は、好みに応じてポートフォリオ曲線を作成するだけでなく、トレードセットアップを形成し、同様の価格チャート上のトレードシンボルをトレードすることができます。しかし、従来の資産を売買するトレーディング・ポートフォリオとは異なり、受動的なトレーダーになります。(現在の価格チャートを受け入れるか、または使用しないようにすることができます。)状況が進化するにつれて、トレーダーは、新たな相場の状況に自分のポートフォリオを調整することができます。

ポートフォリオトレードの欠点:М30と下のチャート上の大きなスプレッドは、日中スキャルピングを適用できない妨げているが、すべてのインジケーターはポートフォリオに適用することはできません。

一般に、トレードではなく、具体的なアプローチがあります。ここでは、ポートフォリオの特性や作業メソッドの概要を行いました。ポートフォリオのトレードシステムのより深い研究を行いたい場合は、相場の分布特性が特殊な統計パッケージを検討する必要があり、一方で、MT5プラットフォームを使用することをお勧めします。