市場取引アルゴリズム(EMA)
内容
はじめに
数値最適化の分野では、不確実性や多次元性を伴う複雑な問題を効果的に解決することを目的として、新しいアルゴリズムが継続的に開発されています。その中でも、集団ベースのメタヒューリスティック手法は特別な位置を占めています。自然現象や社会的プロセスを模倣することで、大域的最適解を探索する優れた能力を示しています。
しかし、すべての新しいアルゴリズムが競争力のある性能を達成できるわけではありません。本記事では、このような手法の代表例の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の主要な数式が示されています。上記の説明と数式に基づいて、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テスト関数におけるEMA

Forestテスト関数におけるEMA

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 | #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
警告: これらの資料についてのすべての権利はMetaQuotes Ltd.が保有しています。これらの資料の全部または一部の複製や再プリントは禁じられています。
この記事はサイトのユーザーによって執筆されたものであり、著者の個人的な見解を反映しています。MetaQuotes Ltdは、提示された情報の正確性や、記載されているソリューション、戦略、または推奨事項の使用によって生じたいかなる結果についても責任を負いません。
因果推論とアルゴリズム取引における回帰モデルの活用
多通貨エキスパートアドバイザーの開発(第28回):決済マネージャの追加
エラー 146 (「トレードコンテキスト ビジー」) と、その対処方法
初級から中級まで:オブジェクトイベント(I)
- 無料取引アプリ
- 8千を超えるシグナルをコピー
- 金融ニュースで金融マーケットを探索