取引におけるニューラルネットワーク:暗号通貨市場向けメモリ拡張コンテキスト認識学習(MacroHFT)
はじめに
金融市場は、その広いアクセス性と高い利益可能性から、多くの投資家を引きつけます。利用可能なすべての資産クラスの中でも、暗号資産はその極端なボラティリティにより、短期間で大きな利益を生む独自の機会を提供します。さらに、24時間365日の取引サイクルがあるため、トレーダーはさまざまな時間帯で市場の変化を捉えることができます。しかし、このボラティリティは利益の機会を提供するだけでなく、同時に大きなリスクも伴うため、より高度な管理戦略の使用が必要です。
暗号資産市場で利益を最大化するために、トレーダーはしばしば高頻度取引(HFT)を用います。これは、超高速での注文執行に基づくアルゴリズム取引の一形態です。HFTは従来の金融市場で長く支配的な存在であり、最近では暗号資産市場でも広く利用されるようになっています。HFTはその高速性だけでなく、膨大な量のデータをリアルタイムで処理できる点に特徴があり、暗号市場のようなスピード重視の環境では欠かせません。
強化学習(RL)手法は、複雑な逐次意思決定問題に対応できるため、金融分野で注目を集めています。RLアルゴリズムは多次元データを処理でき、複数のパラメータを考慮し、変化する環境に適応することが可能です。しかし、低頻度取引では大きな進展が見られる一方で、高頻度暗号資産市場向けの効果的なアルゴリズムはまだ開発途上にあります。これらの市場は高いボラティリティ、不安定性、そして長期的戦略と短期的対応のバランスを求められるという特徴があります。
暗号通貨の既存のHFTアルゴリズムは、いくつかの課題に直面しており、その有効性を制限しています。第一に、市場が均一で定常的なシステムであると見なされることが多く、多くのアルゴリズムはトレンド分析にのみ依存し、ボラティリティを無視しています。このアプローチはリスク管理を複雑化させ、予測精度を低下させます。第二に、多くの戦略は限られた市場特徴に過度に適合しており、新しい条件への適応力を低下させます。最後に、個々の取引ポリシーは市場の急激な変化に対応する柔軟性に欠けることが多く、高頻度環境では致命的な欠点となります。
これらの課題に対する潜在的な解決策として、論文「 MacroHFT:Memory Augmented Context-aware Reinforcement Learning On High Frequency Trading」で提案されたMacroHFTがあります。MacroHFTは、高頻度暗号資産取引(分足)向けに特化した、コンテキスト認識型強化学習に基づく革新的フレームワークです。MacroHFTは意思決定の質を向上させるために、マクロ経済およびコンテキスト情報を統合します。プロセスは大きく2つの段階に分かれます。第一の段階は市場分類です。ここでは、トレンドやボラティリティ指標に基づいて市場を分類します。各カテゴリに対して専門のサブエージェントを訓練することで、現在の状況に応じて戦略を動的に調整できるようにします。これにより、サブエージェントは柔軟性を持ち、局所的な市場特性を考慮することが可能になります。
第二の段階では、ハイパーエージェントがサブエージェントの戦略を統合し、市場の動態に応じて最適な配分をおこないます。メモリモジュールを備えており、最近の経験を考慮して安定的かつ適応的な取引戦略を構築します。この構造により、市場の急変に対する耐性が向上し、リスクへの曝露が軽減されます。
MacroHFTアルゴリズム
MacroHFTフレームワークは、暗号資産市場向けに特化した革新的なアルゴリズム取引プラットフォームであり、高いボラティリティと急激な変動を特徴としています。このフレームワークは強化学習手法に基づいており、市場の挙動を分析・予測できる適応型アルゴリズムの構築を可能にします。主要な考え方は、特定の市場シナリオに最適化された専門のサブエージェントを統合し、それらを調整して全体の一貫性と効率性を確保するハイパーエージェントを組み合わせることです。
極端なボラティリティや急激な市場変化の状況では、単一の強化学習エージェントに依存するだけでは不十分です。市場の状況はあまりにも速く予測不能に変化するため、単一アルゴリズムでは適応が間に合わないことがあります。これに対処するため、MacroHFTフレームワークでは複数の専門サブエージェントを導入しており、それぞれ異なる市場環境に対応するよう訓練されています。これにより、より柔軟で適応的なシステムを構築することが可能になります。
基本原理は、市場データをトレンドとボラティリティという2つの主要なパラメータでセグメント化・分類することにあります。市場データは固定長ブロックに分割され、学習およびテストの両方に使用されます。各ブロックには市場状況タイプを識別するラベルが付与され、サブエージェントの訓練プロセスが簡略化されます。
ラベル付けプロセスは次の2つのステップで構成されます。
- トレンドラベリング:各データブロックはローパスフィルターを通して処理され、ノイズを除去し主要な価格方向を強調します。その後、線形回帰を適用し、傾きがトレンド指標として使用されます。これに基づき、トレンドはポジティブ(強気市場)、ニュートラル(横ばい)、ネガティブ(弱気市場)に分類されます。
- ボラティリティラベリング:各ブロック内の平均価格変動を計算してボラティリティを推定します。これらの値はデータ分布の分位数を用いて、高、中、低の3つのカテゴリに分類されます。
このようにして、各データブロックにはトレンドとボラティリティの2つのラベルが付与されます。結果として、トレンドタイプ(強気、ニュートラル、弱気)とボラティリティレベル(高、中、低)を組み合わせた六つの市場条件カテゴリが得られます。このセグメンテーションにより、各サブエージェントを特定の条件に最適化して学習するための6つの学習サブセットが生成されます。同じラベリング手法は、学習セットから得られた閾値を使用してテストデータにも適用され、性能評価の公正性が確保されます。
各サブエージェントは6つのデータサブセットのいずれかで学習され、対応するカテゴリでテストされます。このプロセスにより、特定の環境に特化したモデルが生成されます。たとえば、あるサブエージェントは強気かつ高ボラティリティ市場で最も性能を発揮し、別のサブエージェントは弱気かつ低ボラティリティ市場で優れた性能を示します。このモジュール型アーキテクチャにより、システムは進化する市場条件に動的に適応でき、性能が大幅に向上します。
サブエージェントの学習には、Double Deep Q-Network (DDQN)手法を採用しています。DDQNは、市場指標、コンテキスト要因、トレーダーのポジションを考慮する二重構造のアーキテクチャを持ちます。これらのデータストリームは個別のニューラルネットワーク層を通して処理され、統合された表現にマージされます。さらにAdaptive Layer Normalization (AdaLN) Block(適応型レイヤー正規化ブロック)がこの表現を洗練し、市場の微妙なニュアンスを考慮して柔軟かつ精密な意思決定を可能にします。
MacroHFTはこのようにして、6つのサブエージェントを作成し、それぞれが異なる市場シナリオに特化します。これらのサブエージェントの戦略はハイパーエージェントによって統合され、暗号資産市場の動的条件下でもシステムの効率性と適応性を確保します。
ハイパーエージェントはサブエージェントの出力を統合し、リアルタイムの市場動態に適応可能な柔軟で効率的なポリシーを形成します。サブエージェントの意思決定はSoftmaxベースのメタポリシーで統合され、単一のサブエージェントへの依存を減らし、システム全体の知見を反映します。
ハイパーエージェントの主要な利点のひとつは、トレンドおよびボラティリティ指標を活用した迅速な意思決定です。これにより、市場変化に即応できます。しかし、従来の高レベルのマルコフ決定過程(MDP)ベースの訓練手法は、報酬の変動が大きく、極端な市場事象が稀であるという課題に直面します。これらの課題に対処するため、ハイパーエージェントにはメモリモジュールが組み込まれています。
メモリモジュールは、状態と行動のキーベクトルを格納する固定サイズのテーブルとして実装されています。新しい経験は一段階のQ値推定を計算して追加され、テーブルが容量に達すると古い記録は破棄され、最も関連性の高い情報が保持されます。推論時には、現在の状態と格納されたキー間のL2距離を計算して最も関連性の高いエントリを取得し、最終値はメモリデータの重み付き和として算出されます。
このメモリの仕組みは、ハイパーエージェントの行動評価も強化します。損失関数にメモリアライメント項を組み込むことで、記憶された値と現在の予測を整合させます。これにより、システムは安定した取引戦略を学習し、市場の急変にも効果的に対応できるようになります。
MacroHFTは、汎用性の高い設計アーキテクチャを持つため、さまざまな金融市場に適用可能な取引フレームワークです。もともとは暗号資産向けに開発されましたが、その手法やアルゴリズムは株式や商品など他の資産クラスにも適応できます。
MacroHFTフレームワークのオリジナルの可視化図を以下に示します。

MQL5での実装
MacroHFTフレームワークの理論的側面を分析した後、このセクションでは本稿の実践的な部分として、提案されたアプローチをMQL5を用いて実装した例を示します。
この実装では、階層型モデルアーキテクチャという中核的な概念は維持しつつ、コンポーネント構成および学習プロセスに大きな変更を加えています。まず、トレンドやボラティリティ水準に基づいてラベル付けされたブロックへ、訓練データとテストデータを手動で分割する手法を廃止します。次に、モデル学習を2つの明確な段階に分離することはおこないません。その代わりに、ハイパーエージェントとサブエージェントの同時学習を、単一の反復的プロセスの中で実装します。学習中、ハイパーエージェントは環境状態を自律的に分類し、それに応じて各エージェントに役割を割り当てられるものと仮定します。
また、ハイパーエージェントには従来のテーブルベースのメモリは使用せず、FinConフレームワークの一部として開発された三層構造のメモリオブジェクトを採用します。さらに、サブエージェントの機能を効率的に実装するため、以前に開発した、より高度なアーキテクチャを持つアナリストエージェントを統合することにしました。このようにしてMacroHFTフレームワークの実装作業は、まずハイパーエージェントの作成から始まります。
ハイパーエージェントの構築
著者らが提供したMacroHFTフレームワークの説明によれば、ハイパーエージェントは現在の環境状態を分析し、それをメモリに格納されたオブジェクトと比較したうえで、分析対象状態の分類を表す確率分布を出力します。この分類は、市場のトレンドやボラティリティを示すものとなります。得られた確率分布は、最終的な取引判断に対する各サブエージェントの寄与度を決定するために使用されます。最終判断は、現在の市場状況との整合性に応じてサブエージェントの出力に重み付けを行うことで生成されます。この手法により、意思決定プロセス全体が支配的な市場要因に応じて動的に適応できるようになります。
言い換えると、メモリに保存された過去の状態コンテキストを考慮しながら、現在の市場環境を分析できる状態分類コンポーネントを構築する必要があります。これは、市場パラメータの時系列と現在の状況との相関を分析することで実現されます。過去の状態は、長期的なトレンドや潜在的なパターンを明らかにし、現在の市場状態をより精度高く分類することを可能にします。
本記事では、このようなハイパーエージェントをCNeuronMacroHFTHyperAgentというオブジェクトとして実装します。その構造を以下に示します。
class CNeuronMacroHFTHyperAgent : public CNeuronSoftMaxOCL { protected: CNeuronMemoryDistil cMemory; CNeuronRMAT cStatePrepare; CNeuronTransposeOCL cTranspose; CNeuronConvOCL cScale; CNeuronBaseOCL cMLP[2]; //--- virtual bool feedForward(CNeuronBaseOCL *NeuronOCL) override; virtual bool updateInputWeights(CNeuronBaseOCL *NeuronOCL) override; virtual bool calcInputGradients(CNeuronBaseOCL *NeuronOCL) override; public: CNeuronMacroHFTHyperAgent(void) {}; ~CNeuronMacroHFTHyperAgent(void) {}; //--- virtual bool Init(uint numOutputs, uint myIndex, COpenCLMy *open_cl, uint window, uint window_key, uint units_count, uint heads, uint layers, uint agents, uint stack_size, ENUM_OPTIMIZATION optimization_type, uint batch); //--- virtual int Type(void) override const { return defNeuronMacroHFTHyperAgent; } //--- virtual bool Save(int const file_handle) override; virtual bool Load(int const file_handle) override; //--- virtual bool WeightsUpdate(CNeuronBaseOCL *source, float tau) override; virtual void SetOpenCL(COpenCLMy *obj) override; //--- virtual bool Clear(void) override; };
Softmax層の実装は親クラスとして使用されます。この関数はMacroHFTフレームワークの著者によって提案されたもので、確率分布を計算するために用いられます。これは、最終的な意思決定に対する各サブエージェントの寄与度を決定するうえで重要な役割を果たし、モデルの精度と適応性の両立を保証します。
ハイパーエージェントの構造には、標準的な仮想メソッド群と、現在の環境状態を分析するアルゴリズムの基盤となる複数の内部オブジェクトが含まれています。これらのコンポーネントの機能については、ハイパーエージェントのクラスメソッドを実装する過程で詳細に検討します。
すべての内部オブジェクトは静的として宣言されているため、コンストラクタとデストラクタを空のままにすることができます。これらの宣言済みおよび継承されたオブジェクトの初期化は、Initメソッド内でおこなわれます。このメソッドは、生成されるオブジェクトのアーキテクチャを一意に定義する複数の定数パラメータを受け取ります。
bool CNeuronMacroHFTHyperAgent::Init(uint numOutputs, uint myIndex, COpenCLMy *open_cl, uint window, uint window_key, uint units_count, uint heads, uint layers, uint agents, uint stack_size, ENUM_OPTIMIZATION optimization_type, uint batch) { if(!CNeuronSoftMaxOCL::Init(numOutputs, myIndex, open_cl, agents, optimization_type, batch)) return false; SetHeads(1); //--- int index = 0;
メソッド本体では、通常通り親クラスの該当メソッドを呼び出します。この場合は、 Softmax関数層です。結果ベクトルの想定サイズは使用されるサブエージェントの数に対応しており、この値は呼び出し側プログラムからメソッドのパラメータとして渡されます。
次に、内部オブジェクトの初期化に進みます。まず、メモリモジュールを初期化します。
int index = 0; if(!cMemory.Init(0, 0, OpenCL, window, window_key, units_count, heads, stack_size, optimization, iBatch)) return false;
分析対象となる環境状態を表すデータ内の依存関係を検出するために、相対位置エンコーディングを備えたtransformerを使用します。
index++; if(!cStatePrepare.Init(0, index, OpenCL, window, window_key, units_count, heads, layers, optimization, iBatch)) return false;
次のステップでは、分析された環境状態を、サブエージェント数と同じ次元数を持つ部分空間へ射影します。この処理には、すべての重要なデータ特性を保持できる効率的な射影メカニズムが必要です。一見すると、標準的な全結合層や畳み込み層を使用できそうですが、入力がマルチモーダルな時系列データであることを考慮すると、重要な情報を含む単変量系列の構造を保持することが極めて重要です。過度な集約によってこれらの情報が失われる可能性があるためです。
先の処理では、相対エンコーディング付きtransformerを用いて時間ステップ間の依存関係を分析しました。次に、この処理を補完するため、個々の単変量系列の詳細を保持する必要があります。そのために、まずデータを転置し、後続の処理で単変量系列を扱いやすくします。
index++; if(!cTranspose.Init(0, index, OpenCL, units_count, window, optimization, iBatch)) return false;
次に、畳み込み層を適用します。この層は単変量系列から空間的および時間的特徴を抽出し、解釈性を向上させます。非線形性は双曲線正接関数(tanh)によって導入されます。
index++; if(!cScale.Init(4 * agents, index, OpenCL, 3, 1, 1, units_count - 2, window, optimization, iBatch)) return false; cScale.SetActivationFunction(TANH);
この段階の後、主要なデータ圧縮フェーズに進みます。次元削減のために、二層構造のMLPアーキテクチャを使用します。第一層では予備的なデータ削減を行い、冗長な相関やノイズを除去します。Leaky ReLU (LReLU)活性化関数を使用することで、変換における線形性を防ぎます。第二層では最終的な圧縮をおこない、後続の解析に最適化されたデータ表現を生成します。
index++; if(!cMLP[0].Init(agents, index, OpenCL, 4 * agents, optimization, iBatch)) return false; cMLP[0].SetActivationFunction(LReLU); index++; if(!cMLP[1].Init(0, index, OpenCL, agents, optimization, iBatch)) return false; cMLP[0].SetActivationFunction(None); //--- return true; }
このアプローチにより、情報保持とモデル簡素化のバランスが確保され、高頻度取引環境におけるハイパーエージェントの有効性が高まります。
処理されたデータは、その後、先に初期化された親クラスの仕組みを通じて確率空間へと変換されます。この時点で、メソッドは呼び出し側プログラムに対して論理的な成功値を返すことができ、初期化プロセスが完了します。
初期化が完了したら、次にfeedForwardメソッド内でのフォワードパスアルゴリズムの実装に進みます。ここではすべてがシンプルでわかりやすいです。
bool CNeuronMacroHFTHyperAgent::feedForward(CNeuronBaseOCL *NeuronOCL) { if(!cMemory.FeedForward(NeuronOCL)) return false;
このメソッドは、分析対象の環境状態を記述するマルチモーダルテンソルを含む、ソースデータオブジェクトへのポインタを引数として受け取ります。このポインタは直ちにメモリモジュールの対応するメソッドへ渡されます。この段階で、環境の静的な記述は直近の動的情報によって拡張され、より完全かつ最新の表現が生成されます。この時間的コンテキストを統合することで、システム内で進行中の変化をより正確に追跡でき、その後の処理アルゴリズムの効率が向上します。
前段階で処理されたデータはアテンションブロックへ渡され、分析対象系列内の異なる時間点間の依存関係が特定されます。この処理により、隠れた関係性が明らかになり、その後の価格変動予測の精度が向上します。
if(!cStatePrepare.FeedForward(cMemory.AsObject())) return false;
その後、データの圧縮に進みます。まず、前段階の解析結果を転置します。
if(!cTranspose.FeedForward(cStatePrepare.AsObject())) return false;
次に、畳み込み層を用いて個々の単変量系列を圧縮し、それらの構造情報を保持します。
if(!cScale.FeedForward(cTranspose.AsObject())) return false;
続いて、MLPを使用して、分析された環境状態をあらかじめ定義された次元数の部分空間へ射影します。
if(!cMLP[0].FeedForward(cScale.AsObject())) return false; if(!cMLP[1].FeedForward(cMLP[0].AsObject())) return false;
次に、得られた値を確率空間へ写像する必要があります。これは、親クラスに実装された対応するSoftmaxメソッドを呼び出し、処理済みの結果を渡すことで実現されます。
return CNeuronSoftMaxOCL::feedForward(cMLP[1].AsObject()); }
次に、操作の論理結果を呼び出し元に返して、メソッドの実行を完了します。
ご覧のとおり、ハイパーエージェントの順伝播アルゴリズムは、直線的で分かりやすい構造を持っています。バックプロパゲーションメソッドのアルゴリズムも同様に線形的であり、個別に学習することが比較的容易です。
以上で、ハイパーエージェントの動作原理に関する概要説明を終了します。このクラスのすべてのメソッドを含む完全なソースコードは、さらなる学習や実践的な応用に関心のある方のために、添付ファイルとして提供されています。次へ移りましょう。ここからは、エージェントを統合した統一フレームワークへの組み込みについて説明します。
MacroHFTフレームワークの構築
この段階では、サブエージェントおよびハイパーエージェントの個別オブジェクトはすでに用意されています。次のステップとして、それらを統合された一貫性のある構造にまとめ、モデルコンポーネント間のデータ交換アルゴリズムを実装していきます。この役割を担うのがCNeuronMacroHFTオブジェクトであり、データ処理ワークフロー全体の管理と最適化をおこないます。新しいオブジェクトの構造を以下に示します。
class CNeuronMacroHFT : public CNeuronBaseOCL { protected: CNeuronTransposeOCL cTranspose; CNeuronFinConAgent caAgetnts[6]; CNeuronMacroHFTHyperAgent cHyperAgent; CNeuronBaseOCL cConcatenated; //--- virtual bool feedForward(CNeuronBaseOCL *NeuronOCL) override; virtual bool updateInputWeights(CNeuronBaseOCL *NeuronOCL) override; virtual bool calcInputGradients(CNeuronBaseOCL *NeuronOCL) override; public: CNeuronMacroHFT(void) {}; ~CNeuronMacroHFT(void) {}; //--- virtual bool Init(uint numOutputs, uint myIndex, COpenCLMy *open_cl, uint window, uint window_key, uint units_count, uint heads, uint layers, uint stack_size, uint nactions, ENUM_OPTIMIZATION optimization_type, uint batch); //--- virtual int Type(void) override const { return defNeuronMacroHFT; } //--- virtual bool Save(int const file_handle) override; virtual bool Load(int const file_handle) override; //--- virtual bool WeightsUpdate(CNeuronBaseOCL *source, float tau) override; virtual void SetOpenCL(COpenCLMy *obj) override; //--- virtual bool Clear(void) override; };
この新しいオブジェクトには、従来どおりオーバーライド可能な仮想メソッド群が含まれており、機能実装に高い柔軟性を提供します。内部オブジェクトの中では、ハイパーエージェントが中心的な調整役を果たし、6 つのサブエージェントが入力データのさまざまな側面を処理します。内部オブジェクトの詳細な機能や相互作用のロジックについては、クラスメソッドを構築しながら順に解説していきます。
すべての内部オブジェクトは静的に宣言されています。これにより、クラスのコンストラクタおよびデストラクタを空のままにすることが可能となります。宣言済みおよび継承されたオブジェクトの初期化は Init メソッド内でおこなわれます。このメソッドは、生成されるオブジェクトのアーキテクチャを明確に定義する複数の定数パラメータを受け取ります。
bool CNeuronMacroHFT::Init(uint numOutputs, uint myIndex, COpenCLMy *open_cl, uint window, uint window_key, uint units_count, uint heads, uint layers, uint stack_size, uint nactions, ENUM_OPTIMIZATION optimization_type, uint batch) { if(!CNeuronBaseOCL::Init(numOutputs, myIndex, open_cl, nactions, optimization_type, batch)) return false;
メソッドの本体では、通常どおり、同じ名前を持つ親クラスのメソッドを呼び出します。このメソッドは、継承されたオブジェクトやインターフェースの初期化処理をすでに実装しています。このケースでは、親クラスは全結合層であり、外部モデルコンポーネントとやり取りするための基本インターフェースのみを使用します。新しいオブジェクトの出力は、市場環境の分析結果に基づいてモデルの最終的な行動テンソルを生成する必要があるため、親クラスの初期化メソッドにはエージェントの行動空間の次元数を指定します。
オリジナルの MacroHFT フレームワークでは、サブエージェントを市場トレンドとボラティリティに基づいて分割することが提案されていました。しかし本実装では、市場の視野に基づく分割を採用します。サブエージェントは、分析対象となる市場データの異なる投影を受け取ります。これらの投影を生成するために、データ転置層を使用します。
int index = 0; if(!cTranspose.Init(0, index, OpenCL, units_count, window, optimization, iBatch)) return false;
次にサブエージェントを初期化します。前半のサブエージェントは入力データの元の表現を分析し、後半のサブエージェントは転置された表現を処理します。この初期化処理は、2 つの連続したループによって構成されます。
uint half = (caAgetnts.Size() + 1) / 2; for(uint i = 0; i < half; i++) { index++; if(!caAgetnts[i].Init(0, index, OpenCL, window, window_key, units_count, heads, stack_size, nactions, optimization, iBatch)) return false; } for(uint i = half; i < caAgetnts.Size(); i++) { index++; if(!caAgetnts[i].Init(0, index, OpenCL, units_count, window_key, window, heads, stack_size, nactions, optimization, iBatch)) return false; }
続いて、元の市場データ表現を分析するハイパーエージェントを初期化します。
index++; if(!cHyperAgent.Init(0, index, OpenCL, window, window_key, units_count, heads, layers, caAgetnts.Size(), stack_size, optimization, iBatch)) return false;
MacroHFTアルゴリズムに従い、次にサブエージェントの出力を重み付きで加算する必要があります。ここで用いられる重みは、ハイパーエージェントによって生成されます。この処理は、サブエージェントの結果行列とハイパーエージェントが提供する重みベクトルを乗算することで簡単に実現できます。しかしこの実装では、サブエージェントの出力が個別のオブジェクトとして保存されているため、それらを 1 つの行列にまとめるための連結用オブジェクトを追加で作成します。
index++; if(!cConcatenated.Init(0, index, OpenCL, caAgetnts.Size()*nactions, optimization, iBatch)) return false; //--- return true; }
行列乗算自体はフィードフォワード処理中に実行されます。ここでは初期化処理の成否を呼び出し元に返し、Initメソッドを終了します。
次に、feedForwardメソッド内でフィードフォワードアルゴリズムを実装します。従来どおり、このメソッドは入力データオブジェクトへのポインタを受け取り、まずそれを転置します。
bool CNeuronMacroHFT::feedForward(CNeuronBaseOCL *NeuronOCL) { if(!cTranspose.FeedForward(NeuronOCL)) return false;
続いて、サブエージェントの半分は元の環境状態表現を処理し、残りの半分は転置された投影を処理します。
uint total = caAgetnts.Size(); uint half = (total + 1) / 2; for(uint i = 0; i < half; i++) if(!caAgetnts[i].FeedForward(NeuronOCL)) return false;
for(uint i = half; i < total; i++) if(!caAgetnts[i].FeedForward(cTranspose.AsObject())) return false;
ハイパーエージェントも同時に元のデータを分析します。
if(!cHyperAgent.FeedForward(NeuronOCL)) return false;
次に、すべてのサブエージェントの結果を1つの行列に集約します。
if(!Concat(caAgetnts[0].getOutput(), caAgetnts[1].getOutput(), caAgetnts[2].getOutput(), caAgetnts[3].getOutput(), cConcatenated.getPrevOutput(), Neurons(), Neurons(), Neurons(), Neurons(), 1) || !Concat(cConcatenated.getPrevOutput(), caAgetnts[4].getOutput(), caAgetnts[5].getOutput(), cConcatenated.getOutput(), 4 * Neurons(), Neurons(), Neurons(), 1)) return false;
生成された行列では、各行が1つのサブエージェントの出力に対応します。正しく重み付き和を計算するために、ハイパーエージェントから得られた重みベクトルをこの結果行列に乗算します。
if(!MatMul(cHyperAgent.getOutput(), cConcatenated.getOutput(), Output, 1, total, Neurons(), 1)) return false; //--- return true; }
この行列乗算の結果は、親クラスから継承された外部インターフェースバッファに書き込まれます。処理の論理結果を呼び出し元に返し、メソッドを終了します。
構造的な変更が導入されているにもかかわらず、フィードフォワードアルゴリズムはMacroHFTフレームワークの元の概念的ロジックを完全に保持している点に注意してください。ただし、学習プロセスについては同様ではなく、次に説明します。
前述のとおり、MacroHFTフレームワークの著者らは、市場トレンドとボラティリティに基づいて学習データセットを分割し、各サブエージェントを個別に学習させていました。しかし、この実装では、すべてのエージェントを同時に学習させるアプローチを採用します。この処理は、このクラスのバックプロパゲーションメソッド内で実装されます。
まず、モデル全体の出力への影響度に応じて、内部オブジェクトおよび入力データに誤差勾配を分配するアルゴリズムを構築します。この機能はcalcInputGradientsメソッド内に実装されます。
bool CNeuronMacroHFT::calcInputGradients(CNeuronBaseOCL *NeuronOCL) { if(!NeuronOCL) return false;
このメソッドは、フィードフォワード段階で使用されたのと同じ入力データオブジェクトへのポインタを受け取りますが、今回は対応する誤差勾配を渡す必要があります。メソッドの冒頭でポインタの妥当性を確認します。オブジェクトが存在しなければ、データを書き込むことはできず、その後の処理は無意味になるためです。
誤差勾配の流れはフィードフォワード処理を逆方向にたどります。フォワードパスがサブエージェント結果と重みベクトルの行列乗算で終了したのに対し、バックプロパゲーションは同じ演算を通じた勾配分配から始まります。
uint total = caAgetnts.Size(); if(!MatMulGrad(cHyperAgent.getOutput(), cHyperAgent.getGradient(), cConcatenated.getOutput(), cConcatenated.getGradient(), Gradient, 1, total, Neurons(), 1)) return false;
このステップでは、勾配が 2 つの情報ストリームに分割される点が重要です。1 つ目はハイパーエージェントの勾配フローであり、これを通じて誤差を直接入力データレベルまで伝播できます。
if(!NeuronOCL.calcHiddenGradients(cHyperAgent.AsObject())) return false;
2 つ目はサブエージェントの勾配フローです。行列乗算による勾配分配の結果、連結オブジェクトのレベルで誤差値が得られます。モデル出力への寄与が大きかったサブエージェントほど、大きな誤差勾配を受け取ります。これにより、ハイパーエージェントによる環境状態分類に基づいて、学習中にサブエージェントの役割を動的に割り当てることが可能になります。
続いて、得られた勾配値をデータのデコンカテネーション処理によって各サブエージェントに分配します。
if(!DeConcat(cConcatenated.getPrevOutput(), caAgetnts[4].getGradient(), caAgetnts[5].getGradient(), cConcatenated.getGradient(), 4 * Neurons(), Neurons(), Neurons(), 1) || !DeConcat(caAgetnts[0].getGradient(), caAgetnts[1].getGradient(), caAgetnts[2].getGradient(), caAgetnts[3].getGradient(), cConcatenated.getPrevOutput(), Neurons(), Neurons(), Neurons(), Neurons(), 1)) return false;
その後、各サブエージェントの計算経路に沿って、誤差勾配を入力データレベルまで伝播させます。ここで、2つの重要なポイントに注意する必要があります。1つ目は、入力データオブジェクトの勾配バッファにはすでにハイパーエージェントからの情報が含まれており、これを保持する必要がある点です。そのため、一時的に別のバッファへポインタを切り替え、既存データの上書きを防ぎます。
CBufferFloat *temp = NeuronOCL.getGradient(); if(!temp || !NeuronOCL.SetGradient(cTranspose.getPrevOutput(), false)) return false;
2つ目は、すべてのサブエージェントが直接入力データとやり取りするわけではない点です。半分のサブエージェントは転置データを処理しているため、勾配分配時にもこれを考慮する必要があります。フォワードパスと同様に、2 つの連続したループを用います。最初のループでは、元の入力表現を扱うサブエージェントを処理し、勾配を入力レベルまで伝播させ、既存の勾配と加算します。
uint half = (total + 1) / 2; for(uint i = 0; i < half; i++) { if(!NeuronOCL.calcHiddenGradients(caAgetnts[i].AsObject())) return false; if(!SumAndNormilize(temp, NeuronOCL.getGradient(), temp, 1, false, 0, 0, 0, 1)) return false; }
2つ目のループはこれを反映したもので、転置層を通じた勾配伝播という追加ステップを含みます。このループは残りのサブエージェントを処理します。
for(uint i = half; i < total; i++) { if(!cTranspose.calcHiddenGradients(caAgetnts[i].AsObject()) || !NeuronOCL.calcHiddenGradients(cTranspose.AsObject())) return false; if(!SumAndNormilize(temp, NeuronOCL.getGradient(), temp, 1, false, 0, 0, 0, 1)) return false; }
すべてのループ処理が正常に完了した後、元のデータバッファポインタを復元します。最後に、メソッドの成功結果を呼び出し元に返します。
以上で、新しいMacroHFTフレームワーク調整オブジェクトにおけるメソッド構築アルゴリズムの解説は終了です。紹介されているすべてのクラスとそのメソッドの完全なソースコードは添付ファイルに含まれています。
本記事ではここまでがフォーマット上の限界ですが、作業はまだ終わっていません。少し休憩を取り、次回の記事で続きをおこないましょう。次回は実装を完成させ、実際の歴史的市場データを用いて開発したアプローチの性能評価を行います。
結論
本記事では、高頻度暗号資産取引における有望なソリューションであるMacroHFTフレームワークについて検討しました。このフレームワークは、マクロ経済的コンテキストとローカルな市場ダイナミクスの両方を取り入れており、複雑かつボラティリティの高い市場環境の中でリターンの最大化を目指すプロトレーダーにとって強力なツールとなります。
実践セクションでは、 MQL5を用いてフレームワークの中核コンポーネントを独自に解釈し、実装を行いました。次回の記事では、この作業を完成させるとともに、実際の過去の市場データを用いて、実装したアプローチの有効性を厳密に検証していきます。
参照文献
記事で使用されているプログラム
| # | 名前 | 種類 | 説明 |
|---|---|---|---|
| 1 | Research.mq5 | EA | 事例収集用EA |
| 2 | ResearchRealORL.mq5 | EA | Real-ORL法を用いたサンプル収集用EA |
| 3 | Study.mq5 | EA | モデル学習用EA |
| 4 | Test.mq5 | EA | モデルテスト用EA |
| 5 | Trajectory.mqh | クラスライブラリ | システム状態とモデルアーキテクチャ記述構造 |
| 6 | NeuroNet.mqh | クラスライブラリ | ニューラルネットワークを作成するためのクラスのライブラリ |
| 7 | NeuroNet.cl | ライブラリ | OpenCLプログラムコード |
MetaQuotes Ltdによってロシア語から翻訳されました。
元の記事: https://www.mql5.com/ru/articles/16975
警告: これらの資料についてのすべての権利はMetaQuotes Ltd.が保有しています。これらの資料の全部または一部の複製や再プリントは禁じられています。
この記事はサイトのユーザーによって執筆されたものであり、著者の個人的な見解を反映しています。MetaQuotes Ltdは、提示された情報の正確性や、記載されているソリューション、戦略、または推奨事項の使用によって生じたいかなる結果についても責任を負いません。
市場シミュレーション(第4回):C_Ordersクラスの作成(I)
エラー 146 (「トレードコンテキスト ビジー」) と、その対処方法
取引におけるニューラルネットワーク:概念強化を備えたマルチエージェントシステム(最終回)
- 無料取引アプリ
- 8千を超えるシグナルをコピー
- 金融ニュースで金融マーケットを探索