English Русский 中文 Español Deutsch Português
preview
市場取引アルゴリズム(EMA)

市場取引アルゴリズム(EMA)

MetaTrader 5トレーディングシステム |
25 0
Andrey Dik
Andrey Dik


内容

  1. はじめに
  2. アルゴリズムの実装
  3. テスト結果


はじめに

数値最適化の分野では、不確実性や多次元性を伴う複雑な問題を効果的に解決することを目的として、新しいアルゴリズムが継続的に開発されています。その中でも、集団ベースのメタヒューリスティック手法は特別な位置を占めています。自然現象や社会的プロセスを模倣することで、大域的最適解を探索する優れた能力を示しています。

しかし、すべての新しいアルゴリズムが競争力のある性能を達成できるわけではありません。本記事では、このような手法の代表例の1つであり、株式市場のトレーダーの行動から着想を得た市場取引アルゴリズム(EMA, Exchange Market Algorithm)について詳しく分析します。このアルゴリズムは株式取引をシミュレーションします。市場参加者は、それぞれ異なる成功度を持ちながら、利益を最大化するためにさまざまな戦略を使用します。 


アルゴリズムの実装

アルゴリズムは、まず市場参加者(トレーダー)の集団を生成することから始まります。この集団は、その後3つの等しいグループに分割されます。各トレーダーには、探索空間内の開始位置がランダムに割り当てられます。この位置は、現在の株式ポートフォリオを表します。これらの位置は、許容される値の範囲全体に均等に分布します。

最初に各トレーダーの成功度(目的関数値の計算)を評価した後、集団全体を成功度の降順に並べ替え、3つのグループに分割します。

  • 第1グループ:エリート 最も成功した市場参加者で構成されます。彼らは最も利益の高いポジションを見つけたトレーダーです。重要な特徴として、エリートトレーダーは取引セッション全体を通じて自身のポジションを変更しません。他のトレーダーにとっての模範として機能します。 
  • 第2グループ:中間層 中程度の成功を収めた参加者です。彼らはエリートから学ぶことで自身のポジションを改善しようとしますが、同時に適度なリスクを取ることも許容します。 
  • 第3グループ:初心者 最も成功度の低い参加者で構成されます。彼らは状況を大きく改善するために、高いリスクを取ることをいとわないトレーダーです。

アルゴリズムの各反復は、異なる市場状態に対応する2つのフェーズから構成される1つの取引セッションを表します。

フェーズ1:バランス市場(安定した取引) 


安定した市場環境では、トレーダーはより成功している参加者を模倣することに基づいた保守的な戦略を使用します。 

中間層の行動 第2グループの各トレーダーは、エリートグループからランダムに1人のメンターを選択し、その方向へ徐々に自身のポジションを移動させます。この移動の範囲は吸収係数(r1 = 1.5)によって決定されます。この係数はアルゴリズムの進行に伴って適応的に減少します。移動は決定論的ではありません。市場判断の不確実性を再現するために、ランダムな乗数が使用されます。 

初心者層の行動 第3グループのトレーダーは、エリート層と中間層の両方から影響を受けます。各初心者トレーダーは、第1グループと第2グループからそれぞれ1人のメンターを選択します。そして、新しいポジションは両方のメンターの方向への移動を組み合わせて形成されます。これは、最も成功しているトレーダーからだけでなく、最近成績を改善した参加者からも同時に学習しようとする行動を表しています。

フェーズ2:変動市場(ボラティリティの高い取引)


不安定な市場環境では、トレーダーは新しい機会を探索するために、より積極的な戦略を使用します。 

中間層の探索行動 第2グループのトレーダーは、2つの戦略を組み合わせて使用します。50%の確率で、大域最良解(これまでの履歴上で最も成功したトレーダーの位置)を完全にコピーします。それ以外の場合は、エリートグループの重心周辺の領域を探索し、その位置に制御されたランダムノイズを加えます。ノイズの大きさはリスク係数(riskAlpha = 0.3)によって決定され、時間の経過とともに減少します。

初心者層の積極的な行動 第3グループは、最もリスクの高い戦略を使用します。

  • リスク係数(30%)と等しい確率で、トレーダーは現在のポジションを完全に忘れ、ランダムな位置から再開始する。
  • 35%の場合では、大きな探索半径を使用して現在位置周辺の広範囲探索を実行する。
  • 残りの場合では、対立学習が使用されます。トレーダーは最も悪い決定の中心とは反対方向へ移動し、失敗した領域から離れることを試みます。

EMAの重要な特徴は、その適応性にあります。反復が進むにつれて、減衰率はシグモイド関数に基づいて計算されます。この係数によって、初期段階における探索から、最終段階における既に発見された有望な解の活用への滑らかな移行が実現されます。

両方のフェーズが完了した後、重要な更新ステップが実行されます。エリート以外のすべてのトレーダーのポジションは、計算された新しい値に基づいて更新されます。一方、エリートトレーダーは現在のポジションを保持します。これにより、発見された最良解が維持されます。

その後、すべてのトレーダーについて新しい成功率(目的関数の値)が計算され、集団が再び並べ替えられます。そして、新たな大域最良解が決定されます。それでは、下の図でアルゴリズムの数式がどのようなものか見てみましょう。

ema_illustracion

図には、両方の市場モードにおける各グループの位置更新式を含む、EMAの主要な数式が示されています。上記の説明と数式に基づいて、EMAの擬似コードを作成することができます。

1. 初期化

  • N = 60人のトレーダーからなる集団を作成する(Nは3の倍数)
  • パラメータ設定:r₁ = 1.5、r₂ = 0.8、α = 0.3(リスク因子)
  • 各トレーダーをランダムなポジションで初期化する
  • グループサイズを決定する:m = N/3 = 20

2. メインループ

各反復 t = 1, 2, ..., T に対して、以下を実行する。

2.1 ランキング

  • すべてのトレーダーの適応度を評価する
  • 適合度レベルの高い順で並べ替え
  • グループに分ける
    • G₁ = {1, ..., m}:エリート
    • G₂ = {m+1, ..., 2m}:中間層
    • G₃ = {2m+1, ..., N}:初心者

2.2 パラメータの適応

  • progress = t / T
  • decay = 1 / (1 + exp(-10(progress - 0.5)))
  • r₁ᵃᵈᵃᵖᵗ = r₁ × (1 - decay × 0.5)
  • r₂ᵃᵈᵃᵖᵗ = r₂ × (1 - decay × 0.3)

2.3 バランスの取れた市場

  • G₁:位置が保存される
  • G₂:各i ∈ G₂について
    • ランダムリーダーk ∈ G₁を選択する
    • xᵢ = xᵢ + rand() × r₁ᵃᵈᵃᵖᵗ × (xₖ - xᵢ)
  • G₃:各i ∈ G₃について
    • リーダーk₁ ∈ G₁とk₂ ∈ G₂を選択する
    • xᵢ = xᵢ + rand() × r₁ᵃᵈᵃᵖᵗ × (xₖ₁ - xᵢ) + rand() × r₂ᵃᵈᵃᵖᵗ × (xₖ₂ - xᵢ)

2.4 変動市場

  • G₂:各i ∈ G₂について
    • rand() < 0.5の場合:xᵢ = xᵇᵉˢᵗ
    • それ以外の場合:xᵢ = center(G₁) + noise × α × (1 - decay × 0.5)
  • G₃:各i ∈ G₃について
    • rand() < αの場合:xᵢ = random_position()
    • それ以外の場合:rand() < 0.5 + α/2 ならば、xᵢ = xᵢ + big_disturbance
    • それ以外の場合:xᵢ = 2xᵢ - center(worst) + small_noise

2.5 更新

  • G₂とG₃の新しい位置を適用する
  • 大域最適解を更新する

3.結果を返す

見つかった最良解xᵇᵉˢᵗを返します。

これで、C_AOクラスを継承し、EMA最適化アルゴリズムを実装するC_AO_EMAクラスを作成できます。主なコンポーネントは以下の通りです。popSizeは集団サイズ(エージェント数)であり、r1、r2は異なるエージェントグループに対する吸収係数、riskAlphaはリスク係数です。次に、アルゴリズムの設定に使用するパラメータを初期化し、デフォルト値を割り当てます。

関数

  • SetParams():params配列からアルゴリズムパラメータの値を更新し、さらにこれらのパラメータが許容範囲内にあることを確認するための検証チェックを実行します。
  • Init():アルゴリズムを使用する前に初期化します。検索範囲(rangeMinP、rangeMaxP)、パラメータステップ(rangeStepP)、およびエポック数(epochsP)などのパラメータを受け取ります。
  • Moving():エージェントを探索空間内で移動させ、EMA アルゴリズムにおけるエージェント位置更新の主要なロジックを実装します。
  • Revision():エージェントの戦略を修正します。現在のエージェント位置を改善および変更するためのメカニズムが含まれます。
  • GetDecayRate():減衰率を返します。

変数

  • r1:エージェントグループの一つに対する吸収係数です。値が大きいほど、このグループのエージェントは他のエージェント、または「より良い」解へ強く引き寄せられます。
  • r2:別のエージェントグループに対する吸収係数です。
  • riskAlpha:エージェントが意思決定をおこなう際に、どの程度のリスクを取るかを決定するリスク係数です。
  • groupSize:集団を3つのグループに分割した場合の各グループのサイズです(popSize / 3)。
  • currentEpoch:現在のアルゴリズム反復回数のインデックスです。
  • totalEpochs:実行される総反復回数です。
  • tempPop:エージェントが移動する際に、新しい位置を一時的に保存するための配列です。S_AO_Agent型は、単一のエージェント(解候補)を定義する構造体です。

C_AO_EMAクラスは、数値最適化問題向けのEMAアルゴリズムを実装します。このアルゴリズムでは、個体群を複数のグループに分割し、それぞれ異なる戦略(r1およびr2の係数によって定義される)を適用します。また、riskAlphaによって、探索空間を広く探索することと、発見された「良い」解を利用することのバランスを調整します。Moving()およびRevision()関数には、最適化処理の主要なロジックが含まれます。Init()はアルゴリズムを初期化し、SetParams()によってパラメータ値を変更できます。

//————————————————————————————————————————————————————————————————————
class C_AO_EMA : public C_AO
{
  public: //----------------------------------------------------------
  ~C_AO_EMA () { }
  C_AO_EMA ()
  {
    ao_name = "EMA";
    ao_desc = "Exchange Market Algorithm";
    ao_link = "https://www.mql5.com/ja/articles/18605";

    popSize   = 60;     // Population size
    r1        = 1.5;    // Absorption coefficient for group 2
    r2        = 0.8;    // Absorption coefficient for group 3
    riskAlpha = 0.3;    // Risk factor

    ArrayResize (params, 4);

    params [0].name = "popSize";   params [0].val = popSize;
    params [1].name = "r1";        params [1].val = r1;
    params [2].name = "r2";        params [2].val = r2;
    params [3].name = "riskAlpha"; params [3].val = riskAlpha;
  }

  void SetParams ()
  {
    popSize   = (int)params [0].val;
    r1        = params      [1].val;
    r2        = params      [2].val;
    riskAlpha = params      [3].val;

    // Check the parameters validity
    if (popSize < 6) popSize = 6;
    if (popSize % 3 != 0) popSize = ((popSize / 3) + 1) * 3; // Multiple of 3
    if (r1 < 0.0) r1 = 0.0;
    if (r2 < 0.0) r2 = 0.0;
    if (riskAlpha < 0.0) riskAlpha = 0.0;
    if (riskAlpha > 1.0) riskAlpha = 1.0;
  }

  bool Init (const double &rangeMinP  [],
             const double &rangeMaxP  [],
             const double &rangeStepP [],
             const int     epochsP = 0);

  void Moving   ();
  void Revision ();

  //------------------------------------------------------------------
  double r1;         // Absorption coefficient 1
  double r2;         // Absorption coefficient 2
  double riskAlpha;  // Risk factor

  private: //---------------------------------------------------------
  int    groupSize;     // size of each group (popSize/3)
  int    currentEpoch;  // current epoch
  int    totalEpochs;   // total number of epochs

  S_AO_Agent tempPop []; // temporary population for storing new positions

  double GetDecayRate   ();
};
//————————————————————————————————————————————————————————————————————

Init初期化メソッドは、アルゴリズムを実行するための準備をおこなうことを目的としています。このメソッドは、探索パラメータの最小値、最大値、ステップ値の配列、およびエポック数(反復回数)を受け取ります。最初に、標準の初期化関数が呼び出されます。この関数では、探索範囲の設定およびその有効性の確認が処理されます。戻り値がfalseの場合、メソッドの初期化処理は終了します。

次に、各エージェントグループのサイズが計算されます。これは、個体群全体のサイズを3で割ることによって求められます。その後、現在のエポックカウンタが初期化され、アルゴリズムが実行される総エポック数が保存されます。続いて、一時的な集団用のメモリが確保されます。一時集団は、メイン個体群と同じサイズを持つエージェント配列です。ループ処理では、この一時配列内の各エージェントが、coords配列で指定された座標を使用して初期化されます。

これらすべての処理が正常に完了すると、戻り値としてtrueが返され、アルゴリズムが正常に実行準備を完了したことを示します。

//————————————————————————————————————————————————————————————————————
//--- Initialization
bool C_AO_EMA::Init (const double &rangeMinP  [],
                     const double &rangeMaxP  [],
                     const double &rangeStepP [],
                     const int epochsP = 0)
{
  if (!StandardInit (rangeMinP, rangeMaxP, rangeStepP)) return false;

  //------------------------------------------------------------------
  groupSize    = popSize / 3;
  currentEpoch = 0;
  totalEpochs  = epochsP;

  // Initialize the temporary population
  ArrayResize (tempPop, popSize);
  for (int i = 0; i < popSize; i++)
  {
    tempPop [i].Init (coords);
  }

  return true;
}
//————————————————————————————————————————————————————————————————————

Movingメソッドは、EMAアルゴリズムにおけるエージェントの進化処理を実装する主要な関数です。このメソッドは、探索空間内でエージェントの位置を変更する役割を担います。 初期設定(一度だけ実行)では、以下をおこないます。

  • アルゴリズムの最初の実行時には、すべてのエージェントの座標が指定された範囲(rangeMin、rangeMax)内でランダムに初期化されます。
  • 各エージェントの座標は、離散化ステップ(rangeStep)を考慮して調整されます。
  • revision変数にはtrueが設定され、このメソッドが次回以降呼び出された際に初期化処理が繰り返されないようにします。

エポックおよび減衰率の更新

  • 現在のエポックカウンタ(currentEpoch)がインクリメントされます。
  • decayRateが計算されます。この値は各エポックごとに減少し、アルゴリズムの適応的な動作に影響を与えます。

現在の集団のコピー :現在の集団aに存在するすべてのエージェントの座標および目的関数fの値が、一時集団tempPopにコピーされます。これは、現在の反復処理におけるすべての計算が完了するまで、tempPop上の変更が集団aへ影響を与えないようにするためです。

フェーズ1:バランスの取れた市場(吸収オペレータ) このフェーズでは、最良エージェントから情報を「吸収」するエージェントの動作をモデル化します。集団は3つのグループに分割されます。集団は3つのグループに分けられます。

  • グループ1(エリート): このグループのエージェント(インデックス0からgroupSize-1)は、この段階では変更されません。これらは最良のエージェントであり、その位置は維持されます。
  • グループ2(吸収オペレータ1):このグループのエージェント(インデックスgroupSizeから2*groupSize-1)は、位置を更新します。
    • このグループの各エージェントに対して、グループ1からランダムに「リーダー」が選択されます。
    • グループ2のエージェントの座標は、選択されたグループ1のリーダーの座標方向へ移動します。移動量はr1適応係数に依存し、decayRateを考慮して減少します。
    • 座標は探索範囲およびステップ値によって調整されます。
  • グループ3(吸収オペレータ2):このグループのエージェント(インデックス2*groupSizeからpopSize-1)は、位置を更新しますが、より積極的な動作をおこないます。
    • このグループの各エージェントに対して、2つのリーダーがランダムに選択されます。1つはグループ1から、もう1つはグループ2から選択されます。
    • グループ3のエージェントの座標は、選択された両方のリーダーに向かって移動します。この移動には、同じr1適応係数が使用されます。
    • 座標は探索範囲およびステップ値によって調整されます。

フェーズ2:変動市場(検索オペレータ):このフェーズでは、エージェントの探索行動をシミュレーションし、探索空間内の新しい領域を探索できるようにします。

  • グループ2(探索オペレータ1-中程度のリスク)
    • このグループの各エージェントの座標が更新されます。
    • 50%の確率で、座標はcBの値によって完全に置き換えられます。
    • それ以外の場合、座標は「エリート中心」(グループ1のエージェント座標の平均値)を基準として移動し、さらにノイズが追加されます。このノイズはriskAlpha、座標範囲、およびdecayRateに依存します。
    • 座標は探索範囲およびステップ値によって調整されます。
  • グループ3(検索オペレータ2-高リスク)
    • このグループの各エージェントの座標が更新されます。
    • riskAlphaの確率で、座標は範囲内のランダムな値によって完全に再初期化されます。これは非常にリスクの高い大規模探索を表します。
    • それ以外の場合、2番目の乱数が「0.5+riskAlpha/2.0」より小さい場合、「広範囲探索」が実行されます。この場合、座標はriskAlphaおよびdecayRateに依存する一定範囲内でランダムな量だけ移動します。
    • それ以外の場合、「対立学習」が適用されます。座標は反対方向へ移動し、さらに小さなランダムノイズが追加されます。
    • 座標は探索範囲およびステップ値によって調整されます。

変更内容のコピー :最後に、すべての計算が完了した後、tempPop内で更新されたエージェントの座標(グループ2およびグループ3)が、メイン集団aにコピーされます。グループ1の座標は変更されません(初期段階でコピー対象外となっているため、そのまま維持されます)。

一般的に、Movingメソッドは反復的な処理を実装しており、集団内のエージェントは、最良エージェントから「学習」すると同時に、異なるリスクレベルで探索空間を探索することによって位置を変化させます。 

//————————————————————————————————————————————————————————————————————
//--- Main loop of the algorithm
void C_AO_EMA::Moving ()
{
  // Initial setup
  if (!revision)
  {
    for (int i = 0; i < popSize; i++)
    {
      for (int c = 0; c < coords; c++)
      {
        a [i].c [c] = u.RNDfromCI (rangeMin [c], rangeMax [c]);
        a [i].c [c] = u.SeInDiSp (a [i].c [c], rangeMin [c], rangeMax [c], rangeStep [c]);
      }
    }

    revision = true;
    return;
  }

  currentEpoch++;
  double decayRate = GetDecayRate ();

  // Copy the current population to the temporary one
  for (int i = 0; i < popSize; i++)
  {
    ArrayCopy (tempPop [i].c, a [i].c, 0, 0, WHOLE_ARRAY);
    tempPop [i].f = a [i].f;
  }

  // PHASE 1: Balanced market (absorbing operators)

  // Group 1 (elite) - does not change
  // Indices: 0 ... groupSize-1

  // Group 2 - absorbing operator 1
  // Indices: groupSize ... 2*groupSize-1

  double adaptiveR1 = r1 * (1.0 - decayRate * 0.5);

  for (int i = groupSize; i < 2 * groupSize; i++)
  {
    // Each agent in group 2 selects a random leader from group 1
    int leaderIdx = u.RNDminusOne (groupSize);

    for (int c = 0; c < coords; c++)
    {
      tempPop [i].c [c] = a [i].c [c] + u.RNDprobab () * adaptiveR1 * (a [leaderIdx].c [c] - a [i].c [c]);
      tempPop [i].c [c] = u.SeInDiSp (tempPop [i].c [c], rangeMin [c], rangeMax [c], rangeStep [c]);
    }
  }

  // Group 3 - absorbing operator 2
  // Indices: 2*groupSize ... popSize-1

  adaptiveR1 = r1 * (1.0 - decayRate * 0.3);

  for (int i = 2 * groupSize; i < popSize; i++)
  {
    // Selection of leaders from groups 1 and 2
    int leader1Idx = u.RNDminusOne (groupSize);
    int leader2Idx = groupSize + u.RNDminusOne (groupSize);

    for (int c = 0; c < coords; c++)
    {
      tempPop [i].c [c] = a [i].c [c] +
                          u.RNDprobab () * adaptiveR1 * (a [leader1Idx].c [c] - a [i].c [c]) +
                          u.RNDprobab () * adaptiveR1 * (a [leader2Idx].c [c] - a [i].c [c]);

      tempPop [i].c [c] = u.SeInDiSp (tempPop [i].c [c], rangeMin [c], rangeMax [c], rangeStep [c]);
    }
  }

  // PHASE 2: Fluctuating market (search operators)

  // Group 2 - search operator 1 (moderate risk)
  for (int i = groupSize; i < 2 * groupSize; i++)
  {
    for (int c = 0; c < coords; c++)
    {
      double range = rangeMax [c] - rangeMin [c];

      if (u.RNDprobab () < 0.5)
      {
        tempPop [i].c [c] = cB [c];// tempPop [i].c [c] + delta;
      }
      else
      {
        // Search around the center of the elite
        double eliteCenter = 0.0;
        for (int j = 0; j < groupSize; j++)
        {
          eliteCenter += a [j].c [c];
        }
        eliteCenter /= (double)groupSize;

        double noise = riskAlpha * range * u.RNDfromCI (-0.5, 0.5) * (1.0 - decayRate * 0.5);
        tempPop [i].c [c] = eliteCenter + noise;
      }

      // Check boundaries
      tempPop [i].c [c] = u.SeInDiSp (tempPop [i].c [c], rangeMin [c], rangeMax [c], rangeStep [c]);
    }
  }

  // Group 3 - search operator 2 (high risk)
  for (int i = 2 * groupSize; i < popSize; i++)
  {
    for (int c = 0; c < coords; c++)
    {
      double range = rangeMax [c] - rangeMin [c];

      if (u.RNDprobab () < riskAlpha)
      {
        // Full reinitialization
        tempPop [i].c [c] = u.RNDfromCI (rangeMin [c], rangeMax [c]);
      }
      else
        if (u.RNDprobab () < 0.5 + riskAlpha / 2.0)
        {
          // Broad search
          double searchRadius = 2.0 * riskAlpha * range * (1.0 - decayRate * 0.3);
          double delta = u.RNDfromCI (-searchRadius, searchRadius);

          tempPop [i].c [c] = tempPop [i].c [c] + delta;
        }
        else
        {
          // Opposition-based training
          double worstCenter = 0.0;
          int worstCount = groupSize / 2;
          for (int j = popSize - worstCount; j < popSize; j++)
          {
            worstCenter += a [j].c [c];
          }
          worstCenter /= (double)worstCount;

          // Moving in the opposite direction from the worst ones
          tempPop [i].c [c] = 2.0 * tempPop [i].c [c] - worstCenter;

          // Add a little noise
          double noise = riskAlpha * range * u.RNDfromCI (-0.1, 0.1);
          tempPop [i].c [c] += noise;
        }

      // Check boundaries
      tempPop [i].c [c] = u.SeInDiSp (tempPop [i].c [c], rangeMin [c], rangeMax [c], rangeStep [c]);
    }
  }

  // Copying from the temporary population to the main one (except group 1)
  for (int i = groupSize; i < popSize; i++)
  {
    ArrayCopy (a [i].c, tempPop [i].c, 0, 0, WHOLE_ARRAY);
  }
}
//————————————————————————————————————————————————————————————————————

GetDecayRateメソッドは、減衰率を計算するために使用されます。この減衰率は、アルゴリズムの実行中に動作がどの程度変化するかを制御します。最初に、totalEpochsの値が「0」以下であるかを確認します。該当する場合は、ゼロ除算を回避し、安全な動作を保証するために0を返します。次に、現在までに経過したエポック数を総エポック数で割ることにより、探索の進行度を表すprogressを計算します。progressの値は、アルゴリズムの進行に伴って0から1まで増加します。

progressを使用して、このメソッドは指数形式のシグモイド関数に基づいた値を返します。この関数は、減衰係数を0から1へ滑らかに変化させる役割を持ちます。そのため、探索開始時(progressが0に近い場合)では値は0に近く、終了時(progressが1に近い場合)では1に近い値になります。この非線形的な移行は、空間探索と既に発見された解の活用との間のバランスを取るのに役立ちます。

具体的には、シグモイド関数 1 / (1 + exp(-10 * (progress - 0.5)))が使用されます。この形式では、最適化処理の中間付近(progress≈0.5)で急激な変化が発生します。その結果、アルゴリズムの実行中に係数がより動的に変化し、探索と利用の切り替えが効果的に行われます。

//————————————————————————————————————————————————————————————————————
//--- Get the decay rate
double C_AO_EMA::GetDecayRate ()
{
  if (totalEpochs <= 0) return 0.0;

  // Non-linear attenuation for better exploitation/exploration balance
  double progress = (double)currentEpoch / (double)totalEpochs;

  // Use the sigmoid function for a smooth transition
  return 1.0 / (1.0 + MathExp (-10.0 * (progress - 0.5)));
}
//————————————————————————————————————————————————————————————————————

Revisionメソッドは、EMAアルゴリズムにおいて、各反復処理でこれまでに得られた大域的最良解を更新する役割を担います。最初に、S_AO_Agent型の一時配列aTが作成されます。この配列はstaticとして宣言されています。staticとは、関数が最初に呼び出された時に一度だけ配列が作成され、その後の呼び出し間でも状態が保持されることを意味します。「ArrayResize(aT, popSize)」によって、この一時配列のサイズが変更され、popSize(個体群サイズ)分のエージェントを格納できるようになります。この配列はソート処理に使用されます。次に、補助オブジェクトuからSorting関数が呼び出されます。この関数は、メイン個体群であるa配列のエージェントを、適応度(目的関数fの値)に基づいて並べ替えます。 

重要: この処理の後、a配列は目的関数fの値が最も良いエージェントが先頭(インデックス0)になるように並べ替えられます。最小化問題の場合、これはfの値が最も小さいエージェントであり、最大化問題の場合はfの値が最も大きいエージェントになります。現在の個体群における最良エージェント(ソート後にa[0]に配置される)の座標が、cB配列にコピーされます。cB配列には、アルゴリズムによってこれまでに発見された最良解の座標が保存されます。さらに、最良エージェントの目的関数値が変数fBに代入されます。この変数には、最良解の座標cBに対応する目的関数値が保存されます。

//————————————————————————————————————————————————————————————————————
//--- Update the best solutions
void C_AO_EMA::Revision ()
{
  static S_AO_Agent aT []; ArrayResize (aT, popSize);
  u.Sorting (a, aT, popSize);
  ArrayCopy (cB, a [0].c, 0, 0, WHOLE_ARRAY);
  fB = a [0].f;
}
//————————————————————————————————————————————————————————————————————


テスト結果

テスト結果はまだ十分に満足できるものではありませんが、このアルゴリズムは動作しており、一定の探索能力を備えています。

EMA|Exchange Market Algorithm|60.0|1.5|0.8|0.3|
=============================
5 Hilly's; Func runs:10000; result:0.6706604188712635
25 Hilly's; Func runs:10000; result:0.42759923501764946
500 Hilly's; Func runs:10000; result:0.252217676777693
=============================
5 Forest's; Func runs:10000; result:0.7419215403847332
25 Forest's; Func runs:10000; result:0.38137087707323236
500 Forest's; Func runs:10000; result:0.19454127467011006
=============================
5 Megacity's; Func runs:10000; result:0.38769230769230767
25 Megacity's; Func runs:10000; result:0.21323076923076928
500 Megacity's; Func runs:10000; result:0.09672307692307769
=============================
All score:3.36596 (37.40%)

可視化の結果を見ると、低次元関数において結果のばらつきが確認できます。

Hilly

Hillyテスト関数におけるEMA

Forest

Forestテスト関数におけるEMA

Megacity

Megacityテスト関数におけるEMA

テスト後、EMAアルゴリズムは参考用として、集団最適化アルゴリズムのランキング表に追加されます。

# AO 説明 Hilly Hilly
ファイナル
Forest Forest
ファイナル
Megacity(離散) Megacity
ファイナル
ファイナル
結果

MAX
10p(5F) 50p(25F) 1000p(500F) 10p(5F) 50p(25F) 1000p(500F) 10p(5F) 50p(25F) 1000p(500F)
1 ANS across neighbourhood search 0.94948 0.84776 0.43857 2.23581 1.00000 0.92334 0.39988 2.32323 0.70923 0.63477 0.23091 1.57491 6.134 68.15
2 CLA コードロックアルゴリズム(joo) 0.95345 0.87107 0.37590 2.20042 0.98942 0.91709 0.31642 2.22294 0.79692 0.69385 0.19303 1.68380 6.107 67.86
3 AMOm 動物移動最適化m 0.90358 0.84317 0.46284 2.20959 0.99001 0.92436 0.46598 2.38034 0.56769 0.59132 0.23773 1.39675 5.987 66.52
4 (P+O)ES (P+O)進化戦略 0.92256 0.88101 0.40021 2.20379 0.97750 0.87490 0.31945 2.17185 0.67385 0.62985 0.18634 1.49003 5.866 65.17
5 CTA 彗星の尾アルゴリズム(joo) 0.95346 0.86319 0.27770 2.09435 0.99794 0.85740 0.33949 2.19484 0.88769 0.56431 0.10512 1.55712 5.846 64.96
6 TETA 時間進化移動アルゴリズム(joo) 0.91362 0.82349 0.31990 2.05701 0.97096 0.89532 0.29324 2.15952 0.73462 0.68569 0.16021 1.58052 5.797 64.41
7 SDSm 確率的拡散探索M 0.93066 0.85445 0.39476 2.17988 0.99983 0.89244 0.19619 2.08846 0.72333 0.61100 0.10670 1.44103 5.709 63.44
8 BOAm ビリヤード最適化アルゴリズムM 0.95757 0.82599 0.25235 2.03590 1.00000 0.90036 0.30502 2.20538 0.73538 0.52523 0.09563 1.35625 5.598 62.19
9 AAm アーチェリーアルゴリズムM 0.91744 0.70876 0.42160 2.04780 0.92527 0.75802 0.35328 2.03657 0.67385 0.55200 0.23738 1.46323 5.548 61.64
10 ESG 社会集団の進化(joo) 0.99906 0.79654 0.35056 2.14616 1.00000 0.82863 0.13102 1.95965 0.82333 0.55300 0.04725 1.42358 5.529 61.44
11 SIA 等方的焼きなまし(joo) 0.95784 0.84264 0.41465 2.21513 0.98239 0.79586 0.20507 1.98332 0.68667 0.49300 0.09053 1.27020 5.469 60.76
12 BBO 生物地理学に基づく最適化 0.94912 0.69456 0.35031 1.99399 0.93820 0.67365 0.25682 1.86867 0.74615 0.48277 0.17369 1.40261 5.265 58.50
13 ACS 人工協調探索 0.75547 0.74744 0.30407 1.80698 1.00000 0.88861 0.22413 2.11274 0.69077 0.48185 0.13322 1.30583 5.226 58.06
14 DA 弁証法的アルゴリズム 0.86183 0.70033 0.33724 1.89940 0.98163 0.72772 0.28718 1.99653 0.70308 0.45292 0.16367 1.31967 5.216 57.95
15 BHAm ブラックホールアルゴリズムM 0.75236 0.76675 0.34583 1.86493 0.93593 0.80152 0.27177 2.00923 0.65077 0.51646 0.15472 1.32195 5.196 57.73
16 ASO 無政府社会最適化 0.84872 0.74646 0.31465 1.90983 0.96148 0.79150 0.23803 1.99101 0.57077 0.54062 0.16614 1.27752 5.178 57.54
17 RFO ロイヤルフラッシュ最適化(joo) 0.83361 0.73742 0.34629 1.91733 0.89424 0.73824 0.24098 1.87346 0.63154 0.50292 0.16421 1.29867 5.089 56.55
18 AOSm 原子軌道探索M 0.80232 0.70449 0.31021 1.81702 0.85660 0.69451 0.21996 1.77107 0.74615 0.52862 0.14358 1.41835 5.006 55.63
19 TSEA 亀甲進化アルゴリズム(joo) 0.96798 0.64480 0.29672 1.90949 0.99449 0.61981 0.22708 1.84139 0.69077 0.42646 0.13598 1.25322 5.004 55.60
20 BSA バックトラッキング探索アルゴリズム 0.97309 0.54534 0.29098 1.80941 0.99999 0.58543 0.21747 1.80289 0.84769 0.36953 0.12978 1.34700 4.959 55.10
21 DE 差分進化 0.95044 0.61674 0.30308 1.87026 0.95317 0.78896 0.16652 1.90865 0.78667 0.36033 0.02953 1.17653 4.955 55.06
22 SRA レストラン経営達人アルゴリズム(joo) 0.96883 0.63455 0.29217 1.89555 0.94637 0.55506 0.19124 1.69267 0.74923 0.44031 0.12526 1.31480 4.903 54.48
23 CRO 化学反応の最適化 0.94629 0.66112 0.29853 1.90593 0.87906 0.58422 0.21146 1.67473 0.75846 0.42646 0.12686 1.31178 4.892 54.36
24 BIO 血液型遺伝最適化(joo) 0.81568 0.65336 0.30877 1.77781 0.89937 0.65319 0.21760 1.77016 0.67846 0.47631 0.13902 1.29378 4.842 53.80
25 BSA 鳥群アルゴリズム 0.89306 0.64900 0.26250 1.80455 0.92420 0.71121 0.24939 1.88479 0.69385 0.32615 0.10012 1.12012 4.809 53.44
26 DEA イルカのエコーロケーションアルゴリズム 0.75995 0.67572 0.34171 1.77738 0.89582 0.64223 0.23941 1.77746 0.61538 0.44031 0.15115 1.20684 4.762 52.91
27 HS ハーモニー検索 0.86509 0.68782 0.32527 1.87818 0.99999 0.68002 0.09590 1.77592 0.62000 0.42267 0.05458 1.09725 4.751 52.79
28 SSG 苗木の播種と育成 0.77839 0.64925 0.39543 1.82308 0.85973 0.62467 0.17429 1.65869 0.64667 0.44133 0.10598 1.19398 4.676 51.95
29 BCOm 細菌走化性最適化M 0.75953 0.62268 0.31483 1.69704 0.89378 0.61339 0.22542 1.73259 0.65385 0.42092 0.14435 1.21912 4.649 51.65
30 ABO アフリカ水牛の最適化 0.83337 0.62247 0.29964 1.75548 0.92170 0.58618 0.19723 1.70511 0.61000 0.43154 0.13225 1.17378 4.634 51.49
31 (PO)ES (PO)進化戦略 0.79025 0.62647 0.42935 1.84606 0.87616 0.60943 0.19591 1.68151 0.59000 0.37933 0.11322 1.08255 4.610 51.22
32 FBA フラクタルベースのアルゴリズム 0.79000 0.65134 0.28965 1.73099 0.87158 0.56823 0.18877 1.62858 0.61077 0.46062 0.12398 1.19537 4.555 50.61
33 TSm タブーサーチM 0.87795 0.61431 0.29104 1.78330 0.92885 0.51844 0.19054 1.63783 0.61077 0.38215 0.12157 1.11449 4.536 50.40
34 BSO ブレインストーム最適化 0.93736 0.57616 0.29688 1.81041 0.93131 0.55866 0.23537 1.72534 0.55231 0.29077 0.11914 0.96222 4.498 49.98
35 WOAm 鯨最適化アルゴリズムM 0.84521 0.56298 0.26263 1.67081 0.93100 0.52278 0.16365 1.61743 0.66308 0.41138 0.11357 1.18803 4.476 49.74
36 AEFA 人工電界アルゴリズム 0.87700 0.61753 0.25235 1.74688 0.92729 0.72698 0.18064 1.83490 0.66615 0.11631 0.09508 0.87754 4.459 49.55
37 AEO 人工生態系ベースの最適化アルゴリズム 0.91380 0.46713 0.26470 1.64563 0.90223 0.43705 0.21400 1.55327 0.66154 0.30800 0.28563 1.25517 4.454 49.49
38 CAm ラクダアルゴリズムM 0.78684 0.56042 0.35133 1.69859 0.82772 0.56041 0.24336 1.63149 0.64846 0.33092 0.13418 1.11356 4.444 49.37
39 ACOm 蟻コロニー最適化M 0.88190 0.66127 0.30377 1.84693 0.85873 0.58680 0.15051 1.59604 0.59667 0.37333 0.02472 0.99472 4.438 49.31
40 CMAES 共分散行列適応進化戦略 0.76258 0.72089 0.00000 1.48347 0.82056 0.79616 0.00000 1.61672 0.75846 0.49077 0.00000 1.24923 4.349 48.33
41 BFO-GA 細菌採食の最適化:Ga 0.89150 0.55111 0.31529 1.75790 0.96982 0.39612 0.06305 1.42899 0.72667 0.27500 0.03525 1.03692 4.224 46.93
42 SOA シンプル最適化アルゴリズム 0.91520 0.46976 0.27089 1.65585 0.89675 0.37401 0.16984 1.44060 0.69538 0.28031 0.10852 1.08422 4.181 46.45
43 ABHA 人工蜂の巣アルゴリズム 0.84131 0.54227 0.26304 1.64663 0.87858 0.47779 0.17181 1.52818 0.50923 0.33877 0.10397 0.95197 4.127 45.85
44 ACMO 大気雲モデルの最適化 0.90321 0.48546 0.30403 1.69270 0.80268 0.37857 0.19178 1.37303 0.62308 0.24400 0.10795 0.97503 4.041 44.90
45 ADAMm 適応モーメント推定M 0.88635 0.44766 0.26613 1.60014 0.84497 0.38493 0.16889 1.39880 0.66154 0.27046 0.10594 1.03794 4.037 44.85
EMA exchange_market_algorithm 0.67066 0.42759 0.25221 1.35046 0.74192 0.38137 0.19454 1.31783 0.38769 0.21323 0.09672 0.69764 3.366 37.40
RW ランダムウォーク 0.48754 0.32159 0.25781 1.06694 0.37554 0.21944 0.15877 0.75375 0.27969 0.14917 0.09847 0.52734 2.348 26.09


まとめ

提示されたEMAアルゴリズムは、基本的な探索能力を備えているものの、集団最適化アルゴリズムのランキング表で上位45位以内に入るほどの十分な性能は示していません。その単調な構造と、局所最適解に陥るというよく知られた問題を克服するための明確なメカニズムが不足している点から、いくつかの潜在的な問題が存在すると考えられます。 

機能面および適応的な動作制御に大幅な改善を加えない限り、EMAは複雑な最適化問題を解決するための可能性が限定された基本的なアルゴリズムに留まり、その結果、主要なメタヒューリスティクスの上位ランキングには入っていません。しかし、このアルゴリズムで提示されたアイデアは非常に興味深く、今後の発展のためのアイデアプールにおいて有望な要素となります。

タブ

図2:対応するテストに応じたアルゴリズムのカラーグラデーション

チャート

図3:アルゴリズムテスト結果のヒストグラム(0から100のスケール、高いほど良い)100は理論上の最大値であり、アーカイブには評価表を計算するためのスクリプトがあります。

EMAのメリットとデメリット

長所

  1. シンプルな実装

短所

  1. 収束精度が低い

この記事には、最新版のアルゴリズムコードを含むアーカイブが添付されています。記事の著者は、正統的なアルゴリズム定義の説明の絶対的な正確さについて責任を負いません。探索性能を向上させるために、それらの多くに変更が加えられています。記事に示された結論と判断は、実験結果に基づいています。


記事で使用されているプログラム

# 名前 種類 説明
1 #C_AO.mqh
インクルード
集団最適化アルゴリズムの親クラス
2 #C_AO_enum.mqh
インクルード
集団最適化アルゴリズムの列挙
3 TestFunctions.mqh
インクルード
テスト関数のライブラリ
4
TestStandFunctions.mqh
インクルード
テストスタンド関数ライブラリ
5
Utilities.mqh
インクルード
補助関数のライブラリ
6
CalculationTestResults.mqh
インクルード
比較表の結果を計算するスクリプト
7
Testing AOs.mq5
スクリプト すべての集団最適化アルゴリズムの統一テストスタンド
8
Simple use of population optimization algorithms.mq5
スクリプト
可視化せずに集団最適化アルゴリズムを使用する簡単な例
9
Test_AO_EMA.mq5
スクリプト EMAテストスタンド

MetaQuotes Ltdによってロシア語から翻訳されました。
元の記事: https://www.mql5.com/ru/articles/18605

添付されたファイル |
EMA.zip (242.9 KB)
因果推論とアルゴリズム取引における回帰モデルの活用 因果推論とアルゴリズム取引における回帰モデルの活用
アルゴリズム取引における回帰モデルの活用可能性について考察します。回帰モデルは、二値分類とは異なり、予測される価格変動を定量的に表現できるため、より柔軟な取引戦略を構築できます。
多通貨エキスパートアドバイザーの開発(第28回):決済マネージャの追加 多通貨エキスパートアドバイザーの開発(第28回):決済マネージャの追加
複数の戦略を並列で実行する場合、定期的にすべての未決済ポジションを決済し、戦略を最初から再開したい場合があります。しかし、現行のコードでは、この動作は手動でしか実現できません。そこで、この処理を自動化してみましょう。
エラー 146 (「トレードコンテキスト ビジー」) と、その対処方法 エラー 146 (「トレードコンテキスト ビジー」) と、その対処方法
この記事では、MT4において複数のEAの衝突をさける方法を扱います。ターミナルの操作、MQL4の基本的な使い方がわかる人にとって、役に立つでしょう。
初級から中級まで:オブジェクトイベント(I) 初級から中級まで:オブジェクトイベント(I)
チャート上のオブジェクトに何らかの変更が発生した際に、MetaTrader 5が生成する可能性のある6種類のイベントのうち、3つについて説明します。これらのイベントは、ユーザー操作という観点から非常に有用です。なぜなら、これらのイベントを理解していなければ、特定の目的でオブジェクトを管理しようとする際に、チャートの特定の構成を維持するために、より多くの作業を自分でおこなわなければならなくなるからです。