English Русский Español Deutsch Português
preview
MQL5での量子ニューラルネットワーク(第1回):インクルードファイルの作成

MQL5での量子ニューラルネットワーク(第1回):インクルードファイルの作成

MetaTrader 5エキスパートアドバイザー |
23 8
Yevgeniy Koshtenko
Yevgeniy Koshtenko

眠ることも、パニックになることもなく、何千もの市場パターンを同時に分析できるトレーダーを想像してみてください。さらに、そのトレーダーが象のような記憶力、天才的な直感、そして瞬時に学習する能力まで持っているとしたらどうでしょう。SFのように聞こえませんか?ようこそ、MQL5における量子ニューラルネットワークの世界へ。

私たちが今日構築するものは、単純な機械学習をはるかに超えています。それは、量子力学と人工知能の融合を、MetaTrader 5上で実行可能なコードとして具現化したものです。私たちのアーキテクチャは、単に価格変動を予測するだけではありません。人間の意識では到達できないレベルで市場を理解します。 


記憶の捉え方を変える革命

人間の脳は、複数の種類の記憶を同時に利用しています。経験豊富なトレーダーがチャートを見ると、過去に似た状況を瞬時に思い出し、現在のコンテキストを分析し、次に何が起こる可能性があるのかを直感的に理解します。この原理が、ContextAnalyzerの基礎となっています。これは、人間の直感をデジタルのかたちで再現することを目指した革新的なコンポーネントです。

私たちの記憶システムは5つのレベルで動作し、それぞれが異なる役割を担います。短期記憶は、市場で瞬間的に発生する変化、つまり個々のティックや価格変動を捉えます。中期記憶は、時間足や日足レベルのトレンドに関する情報を蓄積します。長期記憶は、数か月から数年にわたって形成される基本的なパターンを保存します。

しかし、本当の魔法が始まるのはエピソード記憶からです。これは、ボラティリティの急激な上昇、予想外のニュース、トレンドの変化など、本当に重要な出来事が発生したときだけ活性化されます。こうした瞬間は特に強く記憶に刻まれ、独自の「記憶」を形成します。そしてシステムは、それらを将来、類似した状況を認識するために利用します。

このアーキテクチャは、短期から長期まで異なる時間軸の記憶を統合し、市場のダイナミクスに適応します。アテンション機構とTransformerによって重要な情報の選択と抽象化をおこない、状態空間モデルが時間的依存関係を処理します。そして、ContextAnalyzerがボラティリティを考慮しながら記憶情報を統合します。量子プロセッサはシグナルを増幅すると同時にノイズを抑制し、MetaVerificationModelが予測の信頼性を検証します。このアーキテクチャ全体が、自己調整機能と組み込みの批判的評価機能を備えたシステムとして機能します。


量子力学の動作原理

従来のニューラルネットワークは、情報を基本的に線形に処理します。データは入力から出力へ、複数の変換処理を順番に通過していきます。私たちのシステムは根本的に異なる方法で動作します。ここでは、量子力学の原理である重ね合わせ、干渉、共鳴を応用します。

異なるレベルの記憶が互いに作用すると、光の波が互いに強め合ったり打ち消し合ったりするのと同じように、干渉パターンが形成されます。こうした干渉から、各コンポーネントを単純に足し合わせるだけでは得られない創発的な特性が生まれます。

double resonance_factor = 1.0 + 0.5 * MathCos(input_val * linear_context * M_PI);
double interference = 0.3 * MathSin(short_context * medium_context * 2.0 * M_PI) +
                     0.2 * MathCos(long_context * episodic_context * M_PI) +
                     0.1 * MathSin(pattern_context * input_val * 3.0 * M_PI);

これらの数式は、単なる数学的な計算ではありません。それらは、市場における異なる「現実の層」がどのように共鳴し合い、複雑な調波を形成するのかを表現しています。そして私たちのシステムは、こうした調波を認識し、予測に利用することを目指します。


Transformerによるアーキテクチャの革新

現代AIの中心にあるのがアテンション機構です。これは、ノイズを無視しながら、本当に重要な情報にモデルの注意を集中させる能力です。UShapeTransformerは、この考え方をさらに発展させています。

すべての楽器の音を同時に聞き、それぞれがどのように相互作用しているのかを理解できるオーケストラの指揮者を想像してみてください。アテンション機構も同様に動作します。入力シーケンス内の各要素について、他のすべての要素との関係に基づいて、その重要度を計算します。

void Forward(Matrix &input_matrix, Matrix &output_matrix)
{
    // Create matrices of queries, keys, and values
    MatrixMultiply(input_matrix, W_q, Q);
    MatrixMultiply(input_matrix, W_k, K);
    MatrixMultiply(input_matrix, W_v, V);
    
    // Calculate attention weights
    for(int i = 0; i < seq_len; i++)
    {
        for(int j = 0; j < seq_len; j++)
        {
            double dot_product = 0.0;
            for(int k = 0; k < d_model; k++)
                dot_product += Q.Get(i, k) * K.Get(j, k);
            attention_weights.Set(i, j, dot_product / MathSqrt(d_model));
        }
    }
}

U字型のアーキテクチャでは、さらに複雑な処理が加わります。まず情報がエンコーダを通過します。エンコーダは入力データを圧縮・抽象化し、最も重要な特徴を強調します。その後、デコーダがこの情報を再構築します。ただし、単純に元の情報を復元するのではなく、コンテキストと深い関連性に関する情報を加味した形で再構築します。


コードの錬金術:デジタル脳の作成

基盤:Matrix構造
どのような複雑な構造も、まず強固な基盤から始まります。私たちの場合、その基盤となるのがMatrix構造体です。これは単なる数値のコンテナではありません。多次元データを管理するためのインテリジェントなシステムとして機能します。

struct Matrix
{
    double data[];
    int rows, cols;

    void Init(int r, int c)
    {
        rows = r;
        cols = c;
        ArrayResize(data, r * c);
        ArrayInitialize(data, 0.0);
    }

    double Get(int r, int c)
    {
        if(r < 0 || r >= rows || c < 0 || c >= cols) return 0.0;
        return data[r * cols + c];
    }

    void Set(int r, int c, double val)
    {
        if(r < 0 || r >= rows || c < 0 || c >= cols) return;
        data[r * cols + c] = val;
    }

    void Random(double range = 0.5)
    {
        for(int i = 0; i < ArraySize(data); i++)
            data[i] = (MathRand() / 32767.0 - 0.5) * 2.0 * range;
    }
}

一見すると、単純な構造に思えるかもしれません。しかし、その根底にあるのは安全性と信頼性を重視する設計思想です。データへのアクセスはすべて検証され、各処理は厳密に管理されます。これは特に金融システムにおいて極めて重要です。たった1つのミスが、実際の金銭的損失につながる可能性があるからです。

StateSpaceModel:過去を記憶し、未来を見据える
市場には記憶があります。昨日起きたことが今日の市場に影響を与え、今日起きていることが明日の可能性を左右します。StateSpaceModelは、この基本的な原理を数学的な形で表現します。

struct StateSpaceModel
{
    Matrix A, B, C;  // State, input, and output matrices
    Matrix state;    // Current state of the system
    int input_size, state_size;

    void ProcessSequence(Matrix &_input, Matrix &output)
    {
        output.Init(_input.rows, _input.cols);
        
        for(int t = 0; t < _input.rows; t++)
        {
            // Extract the current input vector
            Matrix input_row;
            input_row.Init(1, _input.cols);
            for(int j = 0; j < _input.cols; j++)
                input_row.Set(0, j, _input.Get(t, j));

            // Update internal state
            Matrix new_state;
            new_state.Init(1, state_size);
            
            // state = A * state + B * input
            for(int i = 0; i < state_size; i++)
            {
                double sum = 0.0;
                for(int k = 0; k < state_size; k++)
                    sum += A.Get(i, k) * state.Get(0, k);
                
                for(int k = 0; k < _input.cols; k++)
                    sum += B.Get(k, i) * input_row.Get(0, k);
                    
                new_state.Set(0, i, sum);
            }
            
            state = new_state;

            // Calculate output: output = C * state
            for(int j = 0; j < _input.cols; j++)
            {
                double sum = 0.0;
                for(int k = 0; k < state_size; k++)
                    sum += C.Get(k, j) * state.Get(0, k);
                output.Set(t, j, sum);
            }
        }
    }
}

このモデルの魅力は、そのシンプルさと強力な表現力にあります。3つの行列によって、システムが時間とともにどのように変化するのかが決定されます。行列Aは内部ダイナミクスを表します。つまり、過去の状態が将来の状態にどのような影響を与えるのかを記述します。行列Bは外部からの影響、すなわち新しいデータがシステムの状態をどのように変化させるのかを定義します。行列Cは、システムの内部状態が外部から観測されるデータとしてどのように現れるのかを表します。

ContextAnalyzer:デジタル化された直感
私たちのシステムの中で最も複雑かつ革新的なコンポーネントがContextAnalyzerです。ここでこそ本当の魔法が起こります。生データが「理解」へと変換されるのです。

void ProcessWithContext(Matrix &_input, Matrix &output)
{
    output.Init(_input.rows, _input.cols);

    static Matrix short_term_memory, medium_term_memory, long_term_memory;
    static Matrix episodic_memory, pattern_memory;
    static bool memory_initialized = false;
    static int sequence_counter = 0;
    static double importance_buffer[100];
    static int buffer_index = 0;

    if(!memory_initialized)
    {
        short_term_memory.Init(5, context_size);
        medium_term_memory.Init(50, context_size);
        long_term_memory.Init(10, context_size);
        episodic_memory.Init(20, context_size);
        pattern_memory.Init(15, context_size);
        
        // Initialize all memory types
        ArrayInitialize(short_term_memory.data, 0.0);
        ArrayInitialize(medium_term_memory.data, 0.0);
        ArrayInitialize(long_term_memory.data, 0.0);
        ArrayInitialize(episodic_memory.data, 0.0);
        ArrayInitialize(pattern_memory.data, 0.0);
        ArrayInitialize(importance_buffer, 0.0);
        
        memory_initialized = true;
    }

    sequence_counter++;

    // Analyze input data characteristics
    double input_volatility = 0.0;
    double input_magnitude = 0.0;
    double input_complexity = 0.0;

    // Calculate volatility, magnitude, and complexity
    for(int i = 0; i < _input.rows; i++)
    {
        double row_sum = 0.0, row_variance = 0.0;
        for(int j = 0; j < _input.cols; j++)
        {
            double val = _input.Get(i, j);
            row_sum += val;
            input_magnitude += MathAbs(val);
        }

        double row_mean = row_sum / _input.cols;
        for(int j = 0; j < _input.cols; j++)
        {
            double val = _input.Get(i, j);
            row_variance += (val - row_mean) * (val - row_mean);
        }

        input_volatility += MathSqrt(row_variance / _input.cols);

        // Evaluate complexity through change analysis
        for(int j = 1; j < _input.cols; j++)
        {
            if(MathAbs(_input.Get(i, j) - _input.Get(i, j-1)) > 0.1)
                input_complexity += 1.0;
        }
    }

    input_volatility /= _input.rows;
    input_magnitude /= (_input.rows * _input.cols);
    input_complexity /= (_input.rows * (_input.cols - 1));

システムは、入力されるデータの性質を常に分析します。ボラティリティが高い場合には短期記憶への注意が強まり、複雑なパターンが現れるとエピソード記憶やパターン記憶が活性化されます。これらは固定的なルールではなく、現在の市場状況に応じて動的に変化する重みです。

そして、ここから最も興味深い処理が始まります。異なる種類の記憶の間で量子的な相互作用が発生します。

// Dynamic calculation of weights for different memory types
double short_weight = 0.4 + 0.4 * input_volatility;
double medium_weight = 0.3 + 0.2 * (1.0 - input_volatility);
double long_weight = 0.2 + 0.3 * (1.0 - input_volatility);
double episodic_weight = 0.1 + 0.3 * input_complexity;
double pattern_weight = 0.15 + 0.25 * input_complexity;

// Normalize weights
double total_weight = short_weight + medium_weight + long_weight + episodic_weight + pattern_weight;
short_weight /= total_weight;
medium_weight /= total_weight;
long_weight /= total_weight;
episodic_weight /= total_weight;
pattern_weight /= total_weight;

for(int i = 0; i < _input.rows; i++)
{
    for(int j = 0; j < _input.cols; j++)
    {
        double input_val = _input.Get(i, j);
        double context_idx = j % context_size;

        // Extract context from different memory types
        double short_context = short_term_memory.Get(sequence_counter % 5, context_idx);
        double medium_context = medium_term_memory.Get(sequence_counter % 50, context_idx);
        double long_context = long_term_memory.Get(sequence_counter % 10, context_idx);
        double episodic_context = episodic_memory.Get(sequence_counter % 20, context_idx);
        double pattern_context = pattern_memory.Get(sequence_counter % 15, context_idx);

        // Linear combination of contexts
        double linear_context = short_weight * short_context +
                               medium_weight * medium_context +
                               long_weight * long_context +
                               episodic_weight * episodic_context +
                               pattern_weight * pattern_context;

        // Quantum effects: resonance and interference
        double resonance_factor = 1.0 + 0.5 * MathCos(input_val * linear_context * M_PI);
        double interference = 0.3 * MathSin(short_context * medium_context * 2.0 * M_PI) +
                             0.2 * MathCos(long_context * episodic_context * M_PI) +
                             0.1 * MathSin(pattern_context * input_val * 3.0 * M_PI);

        double nonlinear_factor = 1.0 + input_volatility * MathSin(linear_context * 2.0 * M_PI);

        // Integrate all effects
        double integrated_context = linear_context * resonance_factor * nonlinear_factor + interference;

        // Determine the strength of contextual influence
        double context_strength = 0.4 + 0.3 * input_complexity;
        double final_output = (1.0 - context_strength) * input_val + context_strength * integrated_context;

        output.Set(i, j, final_output);
    }
}

これらは単なる数学的な演算ではありません。それぞれの数式には、深い意味があります。共鳴は、現在のデータが蓄積されたコンテキストと「同期」したときに発生します。干渉は、異なる時間スケールの間に生じる複雑な相互作用のパターンを形成します。非線形要素はシステムに適応性を与え、市場環境の変化に応じて柔軟に反応できるようにします。

学習・適応システム
真の知性は、記憶する能力だけで示されるものではありません。学習し、適応する能力こそが重要です。私たちのシステムは、入力される情報の重要度を常に分析し、それに応じて記憶を更新します。

// Evaluate the importance of current data
double importance = input_volatility + input_complexity + MathAbs(input_val);
importance_buffer[buffer_index] = importance;
buffer_index = (buffer_index + 1) % 100;

double avg_importance = 0.0;
for(int k = 0; k < 100; k++) avg_importance += importance_buffer[k];
avg_importance /= 100.0;

// Adaptive learning rate
double learning_rate = (importance > avg_importance) ? 0.3 : 0.05;

// Update different memory types at different speeds
double new_short = short_context * (1.0 - 0.4) + final_output * 0.4;
short_term_memory.Set(sequence_counter % 5, context_idx, new_short);

double new_medium = medium_context * (1.0 - 0.1) + final_output * 0.1;
medium_term_memory.Set(sequence_counter % 50, context_idx, new_medium);

double new_long = long_context * (1.0 - 0.02) + final_output * 0.02;
long_term_memory.Set(sequence_counter % 10, context_idx, new_long);

// Episodic memory is activated only for important events
if(importance > avg_importance * 1.5)
{
    double new_episodic = episodic_context * 0.7 + final_output * 0.3;
    episodic_memory.Set(sequence_counter % 20, context_idx, new_episodic);
}

// Pattern memory is updated when correlations are detected
double pattern_correlation = input_val * linear_context;
if(MathAbs(pattern_correlation) > 0.1)
{
    double pattern_update = pattern_correlation * learning_rate;
    double new_pattern = pattern_context * 0.9 + pattern_update * 0.1;
    pattern_memory.Set(sequence_counter % 15, context_idx, new_pattern);
}

システムは、まるで生きた生物のように機能します。単に情報を蓄積するのではなく、何が重要で、何を無視できるのかを判断します。重要な出来事は長く記憶され、日常的なデータはすぐに忘れられます。繰り返し現れるパターンはより強く記憶され、ランダムノイズは除去されます。

MetaVerificationModel:疑う技術
機械学習における主要な問題の1つが、モデルの過信です。入力データに一貫性がなかったり、十分な情報が含まれていなかったりする場合でも、システムが高い「確信度」を持つ予測を出力することがあります。MetaVerificationModelは、批判的思考の層を追加することで、この問題を解決します。

struct MetaVerificationModel
{
    Matrix meta_weights;
    Matrix meta_output_weights;

    void Init()
    {
        int meta_input_size = FEATURES_COUNT + 1 + 3; // features + forecast + metrics
        meta_weights.Init(meta_input_size, 16);
        meta_weights.Random(0.3);
        meta_output_weights.Init(16, 1);
        meta_output_weights.Random(0.5);
    }

    double Forward(double &original_features[], double first_model_prediction, double &error_metrics[])
    {
        // Forming the meta input
        double meta_input[];
        int total_input_size = ArraySize(original_features) + 1 + ArraySize(error_metrics);
        ArrayResize(meta_input, total_input_size);

        // Copy the original features
        for(int i = 0; i < ArraySize(original_features); i++)
            meta_input[i] = original_features[i];

        // Add the main model forecast
        meta_input[ArraySize(original_features)] = first_model_prediction;

        // Add error metrics
        for(int i = 0; i < ArraySize(error_metrics); i++)
            meta_input[ArraySize(original_features) + 1 + i] = error_metrics[i];

        // Forward propagation through the hidden layer
        double hidden[];
        ArrayResize(hidden, 16);

        for(int i = 0; i < 16; i++)
        {
            double sum = 0.0;
            for(int j = 0; j < ArraySize(meta_input) && j < meta_weights.cols; j++)
                sum += meta_input[j] * meta_weights.Get(j, i);
            hidden[i] = Tanh(sum);
        }

        // Calculate the final output
        double output = 0.0;
        for(int i = 0; i < 16; i++)
            output += hidden[i] * meta_output_weights.Get(i, 0);

        return Sigmoid(output); // Return confidence from 0 to 1
    }
}

メタモデルは、元のデータとメインモデルの予測だけでなく、誤差の履歴、現在の品質指標、市場の値動きのパターンも分析します。そして、基礎となるモデルが誤りを起こしやすい状況を識別することを学習し、それに応じて予測に対する確信度を引き下げます。

記憶のバランス調整
システムを効率的に動作させるうえで重要な要素の1つが、異なる種類の記憶を適切に設定することです。市場にはそれぞれ固有の特性があるため、すべての市場に適用できる万能な設定は存在しません。

暗号資産のようにボラティリティの高い市場では、短期記憶とエピソード記憶の影響を強める必要があります。システムは急激な変化に素早く反応すると同時に、極端な市場イベントを記憶しておく必要があります。一方、国債のように比較的安定した金融商品では、長期記憶とパターン記憶により大きな重みを与えるべきです。

// Adaptive adjustment of memory weights depending on the instrument
void AdaptMemoryWeights(string symbol)
{
    if(StringFind(symbol, "BTC") >= 0 || StringFind(symbol, "ETH") >= 0)
    {
        // Settings for cryptocurrencies
        short_term_base_weight = 0.5;
        episodic_base_weight = 0.25;
        long_term_base_weight = 0.1;
    }
    else if(StringFind(symbol, "USD") >= 0)
    {
        // Forex settings
        short_term_base_weight = 0.35;
        medium_term_base_weight = 0.35;
        long_term_base_weight = 0.2;
    }
    // And so on for different types of assets
}

自己診断システム
インテリジェントなシステムは、自らの限界を理解する必要があります。そこで、モデルの動作におけるさまざまな側面を監視する自己診断機能を実装します。

void RunDiagnostics()
{
    static int diagnostic_counter = 0;
    diagnostic_counter++;
    
    if(diagnostic_counter % 1000 == 0) // every thousand ticks
    {
        // Entropy analysis in different types of memory
        double short_entropy = context_analyzer.CalculateMemoryEntropy(short_term_memory);
        double long_entropy = context_analyzer.CalculateMemoryEntropy(long_term_memory);
        double pattern_entropy = context_analyzer.CalculateMemoryEntropy(pattern_memory);
        
        // If short-term memory is too chaotic and long-term memory is too stable
        if(short_entropy > 2.5 && long_entropy < 0.5)
        {
            Print("DIAGNOSIS: Memory imbalance detected. Increasing connectivity.");
            // Increase interaction between memory types
            interference_strength += 0.1;
        }
        
        // If the system becomes too conservative
        if(pattern_entropy < 0.3)
        {
            Print("DIAGNOSIS: The system is too conservative. Adding exploratory noise.");
            exploration_noise += 0.05;
        }
        
        // Analyze forecast quality
        double recent_accuracy = prediction_history.GetRecentAccuracy(50);
        if(recent_accuracy < 0.4)
        {
            Print("DIAGNOSIS: Low accuracy of forecasts. Activating retraining mode.");
            learning_rate_multiplier = 1.5;
            confidence_threshold += 0.1; // Raise the bar for confidence
        }
    }
}



量子的効果の実践

このシステムで最も興味深い点は、異なる構成要素間の量子力学に着想を得た相互作用です。ここでは、それらが実際にどのように機能するのかを見ていきます。

共鳴は、入力されるデータが保存されている記憶と同じ「周波数」に「同調」したときに発生します。これによりシグナルが増幅される効果が生まれ、重要なパターンがより明確になる一方で、ノイズは抑制されます。

干渉は、相互検証の仕組みとして機能します。異なる種類の記憶が互いに一致すると、全体のシグナルが強化されます。一方、それらが互いに矛盾する場合には、「破壊的干渉」が発生し、その結果、システムは予測に対してより慎重になります。

// Example of analysis of quantum effects
void AnalyzeQuantumEffects(double input_val, double linear_context)
{
    double resonance = MathCos(input_val * linear_context * M_PI);
    
    if(MathAbs(resonance) > 0.8)
    {
        if(resonance > 0)
            Print("QUANTUM EFFECT: Strong constructive resonance detected");
        else
            Print("QUANTUM EFFECT: Strong destructive resonance detected");
    }
    
    // Analyze interference patterns
    double interference_pattern = AnalyzeInterferencePattern();
    if(MathAbs(interference_pattern) > threshold)
    {
        Print("QUANTUM EFFECT: Complex interference pattern detected");
        // The market may be in a transitional state
    }
}


取引における人工知能の哲学

私たちの量子ニューラルネットワークの構築は、知性の本質や金融市場の予測可能性について、深い問いを投げかけます。機械は本当に市場を「理解」できるのでしょうか。それとも、データの中に存在する複雑な相関関係を検出しているだけなのでしょうか。私たちは、そのどちらでもない第三の道を提案します。それは、単にパターンを記憶したり相関関係を見つけたりするだけではないアーキテクチャです。私たちのシステムは、市場の現実を多層的に表現します。そして、それぞれのレベルが知覚と分析における固有の役割を担います。

  • 短期記憶は、市場参加者のセンチメントにおける瞬間的な変化、つまり個々のティックや価格変動を捉えます。これは、瞬間的なインパルスを敏感に検知するレーダーのようなものです。

  • 中期記憶は、時間足や日足で形成されるトレンドやサイクルを追跡し、市場の値動きがどのように発展しているのか、そのパターンを識別します。

  • 長期記憶は、数か月から数年にわたって形成される基本的な経済パターンを保存し、システムに戦略的な視点を与えます。

  • エピソード記憶は、ボラティリティの急激な上昇、予想外のニュース、トレンドの変化など、固有で重要なイベントを捉えます。これらの「記憶」によって、システムは類似したシナリオが再び発生する可能性を予測できるようになります。

  • パターン記憶はデジタル化された直感のように機能し、異なる時間軸や市場環境にまたがって繰り返し現れる深層的な構造を抽出します。

量子的効果である共鳴、干渉、コヒーレンスは、ここに新たな複雑性のレベルを加えます。これらによって、システムは不確実性を障害ではなく、価値ある情報源として捉えることが可能になります。量子粒子が複数の状態の重ね合わせとして存在するように、私たちのネットワークも複数の可能な市場シナリオを同時に考慮できます。そして、意味のあるシグナルを増幅し、ノイズを抑制します。これにより、不確実性そのものが学習のための手段へと変わり、システムは市場が持つカオス的な性質に適応できるようになります。


MQL5組み込み行列の利点:自転車から宇宙船へ

当初、私たちのシステムは独自に実装した行列演算に依存していました。これは、いわば車輪を一から作り直すようなものでした。しかし、MQL5の開発者は、組み込みの行列型とベクトル型に加えて、<matrix.mqh>ライブラリまで提供しており、私たちの「自転車」を高性能な宇宙船へと変えてくれました。ネイティブの行列演算を利用することで、コード量を大幅に削減すると同時に、コードの可読性と処理性能を大きく向上させることができました。

MQL5組み込み行列の利点

  • 高い処理性能:行列乗算などの演算は、プロセッサのベクトル命令を利用するため、手作業でループ処理を実装する場合と比べて数倍高速に実行できます。

  • 信頼性:組み込み型を使用することで、インデックス処理に伴うエラーを防ぎ、数値的な安定性を確保できます。これは、わずかな計算誤差が損失につながる可能性のある金融計算において特に重要です。

  • 簡潔さと明瞭さ:コードを数学的な表記に近い形で記述できるため、開発や保守が容易になります。たとえば、行列乗算のために複雑なループを記述する代わりに、Q = input @ W_qと書くだけで済みます。

  • 機械学習向け既製ツール:RandUniform、Exp、Sigmoid、ReLUなどの関数が用意されているため、低レベルの計算処理ではなく、より高レベルのロジックに集中できます。

  • 最適化されたメモリ管理:組み込み型によってメモリ確保の回数を抑えられるため、リアルタイムで大量の市場データを処理する場合に特に有効です。

例として、組み込み型を使用するとコードがどのように変わるのかを見てみましょう。

使用前  使用後 
   void Forward(Matrix &input_matrix, Matrix &output_matrix)
   {
      int seq_len = input_matrix.rows;
      
      Matrix Q, K, V;
      Q.Init(seq_len, d_model);
      K.Init(seq_len, d_model);
      V.Init(seq_len, d_model);

      // Simple matrix multiplication Q = input * W_q
      for(int i = 0; i < seq_len; i++)
      {
         for(int j = 0; j < d_model; j++)
         {
            double q_sum = 0.0, k_sum = 0.0, v_sum = 0.0;
            for(int k = 0; k < d_model; k++)
            {
               double input_val = input_matrix.Get(i, k);
               q_sum += input_val * W_q.Get(k, j);
               k_sum += input_val * W_k.Get(k, j);
               v_sum += input_val * W_v.Get(k, j);
            }
            Q.Set(i, j, q_sum);
            K.Set(i, j, k_sum);
            V.Set(i, j, v_sum);
         }
      }

      // Calculate attention weights
      Matrix attention_weights;
      attention_weights.Init(seq_len, seq_len);

      for(int i = 0; i < seq_len; i++)
      {
         double max_score = -DBL_MAX;
         
         // Calculate scores
         for(int j = 0; j < seq_len; j++)
         {
            double score = 0.0;
            for(int k = 0; k < d_model; k++)
               score += Q.Get(i, k) * K.Get(j, k);
            
            score /= MathSqrt(d_model);
            attention_weights.Set(i, j, score);
            if(score > max_score) max_score = score;
         }

         // Softmax
         double sum_exp = 0.0;
         for(int j = 0; j < seq_len; j++)
         {
            double exp_val = MathExp(attention_weights.Get(i, j) - max_score);
            attention_weights.Set(i, j, exp_val);
            sum_exp += exp_val;
         }

         if(sum_exp > 0)
         {
            for(int j = 0; j < seq_len; j++)
               attention_weights.Set(i, j, attention_weights.Get(i, j) / sum_exp);
         }
      }

      // Apply weights to values
      output_matrix.Init(seq_len, d_model);
      for(int i = 0; i < seq_len; i++)
      {
         for(int j = 0; j < d_model; j++)
         {
            double sum = 0.0;
            for(int k = 0; k < seq_len; k++)
               sum += attention_weights.Get(i, k) * V.Get(k, j);
            output_matrix.Set(i, j, sum);
         }
      }
   }

   matrix Forward(const matrix &input_data)
   {
      // Calculate Q, K, V
      matrix Q = input_data.MatMul(W_q);
      matrix K = input_data.MatMul(W_k);
      matrix V = input_data.MatMul(W_v);
      
      // Apply quantum effects
      Q = quantum_proc.ApplyQuantumEffects(Q, input_data);
      K = quantum_proc.ApplyQuantumEffects(K, input_data);
      
      // Calculate attention weights
      matrix scores = Q.MatMul(K.Transpose()) / MathSqrt((double)d_model);
      
      // Softmax across rows
      for(ulong i = 0; i < scores.Rows(); i++)
      {
         vector row = scores.Row(i);
         
         // Find the maximum value for numerical stability
         double max_val = row.Max();
         
         // Subtract the maximum and apply the exponential element-wise
         for(ulong j = 0; j < row.Size(); j++)
         {
            row[j] = MathExp(row[j] - max_val);
         }
         
         // Normalize (divide by the sum)
         double sum = row.Sum();
         row = row / sum;
         
         // Write back to the matrix
         scores.Row(row, i);
      }
      
      // Apply to values and output projection
      matrix attention_output = scores.MatMul(V);
      return attention_output.MatMul(W_o);
   }
   

最適化後の完全なコードは、添付のQuantumNeuralMQL.mqhファイルに収録されています。

MQL5の機能を十分に理解することが、複雑なニューラルネットワークを構築するうえで重要な鍵となりました。基本的な演算を独自に実装することに時間を費やすのではなく、ContextAnalyzerQuantumProcessorのような革新的なアーキテクチャの開発に集中できます。MQL5のドキュメント、特に行列演算などの機能について学ぶことで、数学的に複雑なアルゴリズムを効率的に実装する道が開かれます。その結果、ニューラルネットワークの構築は、単に生産的な作業になるだけでなく、非常に興味深く、やりがいのある開発作業になります。

最後に、コードが正常に動作することを確認するため、簡単なスクリプトを使用します。

//+------------------------------------------------------------------+
//| Usage example                                                    |
//+------------------------------------------------------------------+
// Using in EA:
SimpleQuantumNeural neural_net;

int OnInit()
{
   neural_net.Init();
   return INIT_SUCCEEDED;
}

void OnTick()
{
   double features[];
   if(MarketDataCollector::CollectSimpleFeatures(_Symbol, PERIOD_H1, 10, features))
   {
      double prediction[];
      neural_net.Forward(features, prediction);
      
      if(ArraySize(prediction) > 0)
      {
         double signal = prediction[0];
         Comment("Quantum signal: ", DoubleToString(signal, 4));
         
         if(signal > 0.6)
         {
            // Buy
         }
         else if(signal < 0.4)
         {
            // Sell
         }
      }
   }
   
   // Diagnostics
   static int counter = 0;
   counter++;
   if(counter % 100 == 0)
      neural_net.PrintDiagnostics();
}




結論

このシステムは、単なるアルゴリズムではありません。自ら学習し、適応し、市場に対する独自の理解を発展させていくことができる自己学習型の構造です。

主要コンポーネント

  • 行列:数学的基盤
  • 状態空間モデル:時間に沿ったダイナミクス
  • Transformer:アテンションと一般化
  • ContextAnalyzer:多層的な洞察
  • MetaVerificationModel:結論の検証

最大の効果は、これらのモジュールが相互に作用することによって生まれます。記事の第2部では、実際のシステムの使用例、設定、最適化について取り上げます。取引における新しい形のAIへの移行は、まだ始まったばかりです。

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

添付されたファイル |
QuantumPredict.mq5 (51.1 KB)
最後のコメント | ディスカッションに移動 (8)
削除済み | 10 7月 2025 において 15:12

記事に掲載されていたスクリプトは、インクルードファイルを置き換えた後、ようやくコンパイルできました。そうしないと、ニューラルネットワークが認識されません。おそらく、記事を最後まで読み終えないまま、それを「エキスパート」セクションにアップロードしてしまったからでしょう。

//#include <Shtenco_SimpleQuantumNeural.mqh>
#include  <QuantumNeuralMQL.mqh>

でも、結局、何を何を使ってテストすればいいのか、さっぱり分かりません :) まるで宿題みたいですね――ボットを完成させること?
Yevgeniy Koshtenko
Yevgeniy Koshtenko | 11 7月 2025 において 14:32
Maxim Dmitrievsky #:

記事のスクリプトは、インクルードファイルを置き換えた後、ようやくコンパイルできました。そうしないと、ニューラルネットワークが認識されません。おそらく、記事を最後まで読み終える前に「エキスパート」セクションにアップロードしてしまったからでしょう。


でも、結局、何を何を使ってテストすればいいのかさっぱり分かりません :) まるで宿題みたいですね――ボットを完成させること?

こんにちは、マキシムさん!今、ファイルを置き換えました。記事の異なるバージョン間でインクルードファイルを混同していました。

ボットについては、次のパートでこのニューラルネットワークを使ったシンプルなボットを紹介します)

削除済み | 11 7月 2025 において 15:22
Yevgeniy Koshtenko #:

こんにちは、マキシム!今、ファイルを差し替えました。記事の異なるバージョン間でインクルードファイルを取り違えていました。

ボットについてですが、次のパートではこのNSを使ったシンプルなボットを紹介する予定です)

よろしく、いいね、ちょっといじってみよう :)

10748356
10748356 | 29 7月 2025 において 15:17
この記事のコンセプトは素晴らしく、興味深いものです。システムの量子的な性質を十分に理解できましたし、MQL5コミュニティで見つけた中で、これが初めての試みだと思います。素晴らしいですね。ぜひ続けてください。
Renat Akhtyamov
Renat Akhtyamov | 29 7月 2025 において 17:53
Maxim Dmitrievsky #:

記事のスクリプトは、インクルードファイルを置き換えた後、ようやくコンパイルできました。そうしないと、ニューラルネットワークが認識されません。おそらく、記事を最後まで読み終える前に「エキスパート」セクションにアップロードしてしまったからでしょう。


でも、結局、何を基にテストすればいいのかさっぱり分かりません :) まるで宿題みたいですね――ボットを完成させること?
Yevgeniy Koshtenko#:

え、何が問題なんですか? まさにトランスフォーマーこそが、かつて自然言語処理技術を飛躍的に前進させたのです。以前のRNNと比べれば、これは確かに優れています。将来的には、量子コンピューティングとニューラルネットワークの融合が見られるようになると思います。 論文にあるように、モデルの12個のコピーが円環状に配置された「リングメタニューラルネットワーク」アーキテクチャは順調に進展しており、まるでブースト効果のように互いの結果を向上させ、互いの出力、信頼度、誤差から学習しています。 こちらは事前学習すら行っていないテストですが、単にオンラインで学習しているだけです……


2017年のデータを使ったテストですか?

なぜ24年や25年ではないのですか?

市場シミュレーション:ポジション表示(III) 市場シミュレーション:ポジション表示(III)
以前の記事では、ZOrderプロパティに値を設定する必要がある場合があることについて説明しました。しかし、なぜでしょうか。チャートにオブジェクトを追加する多くのコードが、このプロパティを使用していない、より正確に言えば、このプロパティに値を定義していないからです。すべてのプログラマーが何をすべきか、あるいはすべきでないか、また、どのようにコードを書くべきか、あるいは書くべきでないかを私が決めるために、ここにいるわけではありません。私は、読者の皆さん、そしてこれらの処理が内部でどのように動作しているのかを本当に理解したいすべての方々に対して、実際に舞台裏で何が起こっているのかを示すために、ここにいます。
取引におけるニューラルネットワーク:データ固有の依存性なしに時系列を一般化する(コアモデルモジュール) 取引におけるニューラルネットワーク:データ固有の依存性なしに時系列を一般化する(コアモデルモジュール)
Mamba4Castフレームワークについての理解をさらに深めていきます。今回は、提案されたアプローチの実践的な実装について詳しく見ていきます。Mamba4Castは、新しい時系列データごとに長時間の事前適応を目的として設計されたものではなく、すぐに導入して使用することを目的として設計されています。ゼロショット予測という概念により、モデルは追加学習やハイパーパラメータの調整をおこなうことなく、実世界のデータに対して高品質な予測を生成できます。
エラー 146 (「トレードコンテキスト ビジー」) と、その対処方法 エラー 146 (「トレードコンテキスト ビジー」) と、その対処方法
この記事では、MT4において複数のEAの衝突をさける方法を扱います。ターミナルの操作、MQL4の基本的な使い方がわかる人にとって、役に立つでしょう。
市場シミュレーション(第24回):ポジション表示(II) 市場シミュレーション(第24回):ポジション表示(II)
取引サーバー上の未決済ポジションを、インジケータを使って、できるだけシンプルかつ実用的な方法で追跡する方法を紹介します。これは、必ずしもすべてをエキスパートアドバイザー(EA)に移す必要はないことを示すため、段階を追って説明していきます。皆さんの多くは、何らかの理由で、このような処理をEAでおこなうことに慣れているかもしれません。しかし、実際には、そのやり方にはそれほど十分な根拠があるわけではありません。なぜなら、この実装を発展させていくにつれて、この目的のためにさまざまな種類のインジケータを作成したり、実装したりできることが明らかになるからです。