![Эластичная чистая регрессия с использованием покоординатного спуска в MQL5](https://c.mql5.com/2/58/Elastic_net_regression_using_coordinate_descent_in_MQL5_600x314.jpg)
Эластичная чистая регрессия с использованием покоординатного спуска в MQL5
Введение
Эластичная чистая регрессия (elastic net regression) сочетает в себе лучшие качества техник гребня и лассо (ridge and lasso) для построения общих линейных моделей. Ее применение позволяет минимизировать один из главных недостатков регрессии — переобучение (overfitting). Это особенно актуально для разработки торговой стратегии, поскольку известно, что наиболее распространенная причина плохой производительности или неудачи стратегии заключается в том, что шум принимается за модель. В этой статье будет представлена реализация эластичной чистой регрессии, которая использует метод оптимизации по покоординатному спуску (coordinate descent) на чистом MQL5. Ближе к концу статьи мы продемонстрируем практическое применение этого метода посредством разработки простой прогнозной стратегии на основе скользящего среднего.
Регуляризация
При построении прогнозных моделей цель состоит в том, чтобы создать образец, который сможет распознать некую уникальную закономерность, которую можно будет использовать для использования в реальных условиях. Чтобы сделать это эффективно, мы должны убедиться, что модель "изучает" соответствующие шаблоны на основе обучающих данных. Очевидно, легче сказать, чем сделать. Обычно модель получает ненужную информацию (шум), что в конечном итоге ухудшает ее производительность при использовании. Регуляризация — это процесс, используемый для минимизации последствий переобучения.
Метод лассо (LASSO, Least Absolute Shrinkage and Selection Operator - оператор наименьшего абсолютного сжатия и выбора) помогает уменьшить смещение обучения за счет подавления избыточных предикторов, когда модель определяется слишком большим количеством оптимизируемых переменных. Тем самым модель упрощается.
При гребневой регрессии коэффициенты уравнения регрессии минимизируются, чтобы отодвинуть их от оптимума. Это помогает обобщить модель, сохраняя при этом все предикторы.
И лассо, и гребневая регрессия отличаются характером применяемого штрафного слагаемого (penalty term). Штрафное слагаемое эластичной чистой регрессии представляет собой комбинацию абсолютного значения и квадрата коэффициентов, взвешенных по двум гиперпараметрам: альфа и лямбда.
Таким образом, альфа контролирует тип регуляризации. Когда альфа равен нулю, штрафной член сводится к норме l2. Если альфа равен 1, штрафная функция становится нормой l1. Указание альфа от 0 до 1 позволяет строить линейные модели, которые в определенной степени сочетают в себе качества гребневой регрессии и лассо, что определяется гиперпараметром лямбда, который контролирует степень регуляризации.
Такие модели могут оказаться полезными при разработке торговых стратегий, где мы часто слепо применяем множество предикторов в надежде найти какую-то комбинацию, которая принесет прибыль. Используя эластичную чистую регрессию, мы можем минимизировать переобучение, а также отделить бесполезные индикаторы от тех, которые имеют значительный прогностический потенциал. И мы можем сделать это, не беспокоясь о том, как индикаторы связаны друг с другом. Это звучит даже слишком хорошо, чтобы быть правдой.
Поокординантый спуск
Покоординатный спуск (coordinate descent) — это метод оптимизации, который хорошо подходит для мультипараметрической оптимизации. Сложная многомерная задача оптимизации сводится к набору одномерных задач. Достигается путем итеративной минимизации каждого отдельного измерения функции при сохранении статических значений функции в других измерениях. В Интернете есть множество ресурсов, которые могут дать более подробные объяснения. Здесь мы заинтересованы в его применении к разработке стратегии.
Для наших целей метод покоординатного спуска будет использоваться двумя способами при реализации эластичной сетевой регрессии. Сначала он будет использоваться для определения оптимальной лямбды на основе фиксированной альфа, указанной пользователем. Как только это будет сделано, метод оптимизации вызывается снова для работы с бета-коэффициентами уравнения регрессии. Давайте углубимся в код, чтобы увидеть, как это достигается.
Класс CCoordinateDescent
//+------------------------------------------------------------------+ //| Coordinate Descent optimization class | //+------------------------------------------------------------------+ class CCoordinateDescent { private: bool m_initialized; // Was everything legal and allocs successful? double m_beta[]; // Beta coefs (m_nvars of them) double m_explained; // Fraction of variance m_explained by model; computed by Train() double m_xmeans[]; // Mean of each X predictor double m_xscales[]; // And standard deviation double m_ymean; // Intercept (mean of Y) double m_yscale; // Standard deviation of Y int m_nvars ; // Number of variables int m_observs ; // Number of cases bool m_covarupdates ; // Does user want (often faster) covariance update method? int m_nlambda ; // Reserve space for this many m_beta sets for saving by TrainLambda() (may be zero) double m_lambdabeta_matrix[]; // Saved m_beta coefs (m_nlambda sets of m_nvars of them) double m_lambdas[]; // Lambdas tested by TrainLambda() double m_x_matrix[]; // Normalized (mean=0, std=1) X; m_observs by m_nvars double m_y[]; // Normalized (mean=0, std=1) Y double m_resid[]; // Residual double m_xinner_matrix[]; // Nvars square inner product matrix if m_covarupdates double m_yinner[]; // Nvars XY inner product vector if m_covarupdates public: //constructor CCoordinateDescent(const int num_predictors, const int num_observations, const bool use_covariance_updates, const int num_lambdas_to_trial) ; //desctructor ~CCoordinateDescent(void) ; //Accessor methods for private properties double GetYmean(void) { return m_ymean; } double GetYscale(void) { return m_yscale;} double GetExplainedVariance(void) { return m_explained;} double GetXmeansAt(const int index) { if(index>=0 && index<ArraySize(m_xmeans)) return m_xmeans[index]; else return 0;} double GetXscalesAt(const int index) { if(index>=0 && index<ArraySize(m_xscales)) return m_xscales[index]; else return 0;} double GetBetaAt(const int index) { if(index>=0 && index<ArraySize(m_beta)) return m_beta[index]; else return 0;} double GetLambdaAt(const int index) { if(index>=0 && index<ArraySize(m_lambdas)) return m_lambdas[index]; else return 0;} double GetLambdaBetaAt(const int index) { if(index>=0 && index<ArraySize(m_lambdabeta_matrix)) return m_lambdabeta_matrix[index]; else return 0;} double GetLambdaThreshold(const double alpha) ; //Set model parameters and raw input data bool SetData(const int begin, const int num_observations, double &xx_matrix[], double &yy[]) ; //Training routines void Train(const double alpha, const double lambda, const int maxits, const double convergence_criterion, const bool fast_test, const bool warm_start) ; void TrainLambda(const double alpha, const int maxits, const double convergence_criterion, const bool fast_test, const double maxlambda, const bool print_steps) ; } ;
Класс CCordinateDescent определен в файле COordinateDescent.mqh. Его конструктор является параметрическим и используется для указания важных особенностей модели, но прежде чем мы углубимся в эту тему, необходимо решить некоторые важные вопросы, касающиеся конкретной конструкции используемых данных.
Библиотека, которую мы укажем, не будет использовать какие-либо уникальные типы данных, такие как новые матричные и векторные типы MQL5. Это сделано для обеспечения совместимости с mql4. Поскольку нет возможности динамически определять многомерные массивы, матрицы будут представлены как обычные плоские массивы. Пример — лучший способ проиллюстрировать конструкцию.
Предположим, мы хотим определить матрицу с 4 строками и 3 столбцами. Мы создадим массив размером 4, умноженным на 3, то есть 12. Члены этого массива будут расположены так, как если бы они выглядели при использовании встроенного матричного типа данных. То есть в нашем примере сначала указываются члены первой строки, затем второй и так далее. Фрагмент кода ниже иллюстрирует создание матрицы 4 на 3, где каждое значение в столбце одинаково.
int rows=4, columns=3; double our_matrix[]; ArrayResize(our_matrix,rows*columns); /* Creating matrix with columns of 1s,2s,3s */ for(int i = 0; i<rows; i++) for(int j=0; j<columns; j++) our_matrix[i*columns+j]=j+1; ArrayPrint(our_matrix);
Вывод из ArrayPrint.
KP 0 13:01:32.445 Construct(GBPUSD,D1) 1.00000 2.00000 3.00000 1.00000 2.00000 3.00000 1.00000 2.00000 3.00000 1.00000 2.00000 3.00000
При обходе массива в матричном виде у нас есть индекс строки * количество столбцов + индекс столбца. Все случаи, когда требуются такие конструкции массива, обозначаются суффиксом _matrix, применяемым либо к имени переменной класса, либо к имени параметра функции.
Использование этой конструкции означает, что при передаче матриц функциям необходимо зарезервировать несколько параметров функции для указания размеров конкретной матрицы. Я уверен, всё сказанное станет понятнее, когда мы доберемся до применения класса ближе к концу статьи. Пользователи могут свободно создавать дочерние библиотеки, если не заинтересованы в межплатформенной переносимости. Вернемся к описанию класса.
//+------------------------------------------------------------------+ //|Constructor | //+------------------------------------------------------------------+ CCoordinateDescent::CCoordinateDescent( const int num_predictors, // Number of predictor variables const int num_observations, // Number of cases we will be training const bool use_covariance_updates, // Use fast covariance updates rather than slow naive method const int num_lambdas_to_trial // Number of m_lambdas we will be using in training )
Параметрический конструктор требует 4 параметра:
- num_predictors задает количество переменных, это количество предикторов или индикаторов, каждый набор индикаторов будет занимать столбец во внутренней матрице данных.
- num_observations указывает объем данных, который должен ожидать объект. Это может быть количество строк или точное количество элементов, доступных в каждом наборе переменных/предикторов/индикаторов.
- use_covariance_updates — это логический параметр, который в идеале следует использовать, когда количество num_observations превышает количество num_predictors. Установка true обеспечивает значительное улучшение времени выполнения. Эту опцию следует учитывать только в том случае, если num_observations > num_predictors.
- num_lambdas_to_trial устанавливает максимальное количество вариантов лямбды, которые будут проверены в процессе обучения.
Конструктор просто подготавливает внутренние структуры данных для получения всех необходимых данных.
{ m_nvars = num_predictors ; m_observs = num_observations ; m_covarupdates = use_covariance_updates ; m_nlambda = num_lambdas_to_trial ; m_initialized=true; m_ymean=m_yscale=m_explained=0; if(m_nvars<0 || m_observs<0 || m_nlambda<0) { m_initialized=false; Print("Invalid parameter value, neither num_predictors ,num_observations, nor num_lambdas_to_trial can be negative"); return; } if(ArrayResize(m_x_matrix,m_observs*m_nvars)<m_observs*m_nvars || ArrayResize(m_y,m_observs)<m_observs || ArrayResize(m_xmeans,m_nvars)<m_nvars || ArrayResize(m_xscales,m_nvars)<m_nvars || ArrayResize(m_beta,m_nvars)<m_nvars || ArrayResize(m_resid,m_observs)<m_observs) m_initialized=false; //---conditional allocation if(m_covarupdates) { if(ArrayResize(m_xinner_matrix,m_nvars*m_nvars)<m_nvars*m_nvars|| ArrayResize(m_yinner,m_nvars)<m_nvars) m_initialized=false; } //--- if(m_nlambda>0) { if(ArrayResize(m_lambdabeta_matrix,m_nlambda*m_nvars)<m_nlambda*m_nvars || ArrayResize(m_lambdas,m_nlambda)<m_nlambda) m_initialized=false; } //---return immediately if any error if(!m_initialized) Print("Memory allocation error ", GetLastError()); }
После создания экземпляра CCordinateDescent нам необходимо собрать все предикторы и целевые значения для предварительной обработки. Это делается методом SetData. Его первый параметр — это начальный индекс, показывающий, где в массивах, которые будут переданы этому методу, следует начать сбор данных. Такой способ помогает при дальнейшем проведении перекрестной проверки.
//+------------------------------------------------------------------+ //|Get and standardize the data | //| Also compute inner products if covar_update | //+------------------------------------------------------------------+ bool CCoordinateDescent::SetData( const int begin, // Starting index in full database for getting m_observs of training set const int num_observations,// Number of cases in full database (we wrap back to the start if needed) double &xx_matrix[], // Full database (num_observations rows, m_nvars columns) double &yy[] // Predicted variable vector, num_observations long )
num_observations — имя параметра, уже встречающееся в конструкторе. Здесь оно используется немного по-другому. Если здесь установлено меньшее значение, чем то, которое использовалось при создании экземпляра объекта, это дает возможность вернуться к первому значению в массиве после достижения этой позиции индекса. Если такая функциональность не требуется, установите для нее то же значение, которое использовалось при вызове конструктора. Только не устанавливайте его на ноль или ниже. Это приведет к ошибке.
Следующий обязательный параметр xx_matrix — это массив с уже упомянутым особым расположением матриц. Здесь мы вводим необработанные показатели. Он должен иметь размер, указанный при вызове конструктора, то есть num_observations * num_predictors.
Последний параметр yy представляет собой массив соответствующих целевых значений.
Метод стандартизирует оба входных массива перед копированием их во внутренние буферы объектов.
{ if(!m_initialized) return false; // parameter checks if(begin<0 || num_observations<0) { Print("Invalid parameter value: neither begin nor num_observations can be negative"); return false; } //--- invalid a if(ArraySize(xx_matrix)<(m_observs*m_nvars) || ArraySize(yy)<m_observs) { Print("Insufficient data supplied relative to object specification"); return false; } //--- int icase, ivar, jvar, k,xptr; double sum, xm, xs, diff; /* Standardize X */ for(ivar=0 ; ivar<m_nvars ; ivar++) { xm = 0.0 ; for(icase=0 ; icase<m_observs ; icase++) { k = (icase + begin) % num_observations ; xm += xx_matrix[k*m_nvars+ivar] ; } xm /= m_observs ; m_xmeans[ivar] = xm ; xs = 1.e-60 ; // Prevent division by zero later for(icase=0 ; icase<m_observs ; icase++) { k = (icase + begin) % num_observations ; diff = xx_matrix[k*m_nvars+ivar] - xm ; xs += diff * diff ; } xs = sqrt(xs / m_observs) ; m_xscales[ivar] = xs ; for(icase=0 ; icase<m_observs ; icase++) { k = (icase + begin) % num_observations ; m_x_matrix[icase*m_nvars+ivar] = (xx_matrix[k*m_nvars+ivar] - xm) / xs ; } } /* Standardize Y */ m_ymean = 0.0 ; for(icase=0 ; icase<m_observs ; icase++) { k = (icase + begin) % num_observations ; m_ymean += yy[k] ; } m_ymean /= m_observs ; m_yscale = 1.e-60 ; // Prevent division by zero later for(icase=0 ; icase<m_observs ; icase++) { k = (icase + begin) % num_observations ; diff = yy[k] - m_ymean ; m_yscale += diff * diff ; } m_yscale = sqrt(m_yscale / m_observs) ; for(icase=0 ; icase<m_observs ; icase++) { k = (icase + begin) % num_observations ; m_y[icase] = (yy[k] - m_ymean) / m_yscale ; } /* If user requests covariance updates, compute required inner products We store the full m_xinner_matrix matrix for faster addressing later, even though it is symmetric. We handle both unweighted and weighted cases here. */ if(m_covarupdates) { for(ivar=0 ; ivar<m_nvars ; ivar++) { xptr = ivar ; // Do XiY sum = 0.0 ; for(icase=0 ; icase<m_observs ; icase++) sum += m_x_matrix[xptr+icase*m_nvars] * m_y[icase] ; m_yinner[ivar] = sum / m_observs ; // Do XiXj for(jvar=0 ; jvar<m_nvars ; jvar++) { if(jvar == ivar) m_xinner_matrix[ivar*m_nvars+jvar] = 1.0 ; // Recall that X is standardized else if(jvar < ivar) // Matrix is symmetric, so just copy m_xinner_matrix[ivar*m_nvars+jvar] = m_xinner_matrix[jvar*m_nvars+ivar] ; else { sum = 0.0 ; for(icase=0 ; icase<m_observs ; icase++) sum += m_x_matrix[xptr+icase*m_nvars] * m_x_matrix[icase*m_nvars+jvar] ; m_xinner_matrix[ivar*m_nvars+jvar] = sum / m_observs ; } } } // For ivar } //--- return true; }
Если SetData завершается успешно и возвращает true, пользователь может вызвать Train() или TrainLambda() в зависимости от того, что он хочет сделать.
//+------------------------------------------------------------------+ //|Core training routine | //+------------------------------------------------------------------+ void CCoordinateDescent::Train( const double alpha, // User-specified alpha, (0,1) (0 problematic for descending lambda) const double lambda, // Can be user-specified, but usually from TrainLambda() const int maxits, // Maximum iterations, for safety only const double convergence_criterion, // Convergence criterion, typically 1.e-5 or so const bool fast_test, // Base convergence on max m_beta change vs m_explained variance? const bool warm_start // Start from existing m_beta, rather than zero? )
В методе Train() происходит основная оптимизация. Здесь указываются тип регуляризации (альфа) и степень регуляризации (лямбда), а также тип проводимого теста сходимости (fast_test) и требуемой точностью для достижения сходимости (convergence_criterion).
- Параметр maxits является отказоустойчивым и предотвращает неоправданное время выполнения процедуры. Для него следует установить достаточно большое значение, например 1000 или более.
- warm_start указывает, начинать ли тренировку с бета-весами, инициализированными нулевым значением, или нет.
{ if(!m_initialized) return; if(alpha<0 || alpha>1) { Print("Invalid parameter value: Legal values for alpha are between 0 and 1 inclusive"); return; } if(lambda<0) { Print("Invalid parameter value: lambda accepts only positive values"); return; } if(maxits<=0) { Print("Invalid parameter value: maxist accepts only non zero positive values"); return; } int i, iter, icase, ivar, kvar, do_active_only, active_set_changed, converged,xptr ; double residual_sum, S_threshold, argument, new_beta, correction, update_factor ; double sum, explained_variance, crit, prior_crit, penalty, max_change, Xss, YmeanSquare ; /* Initialize */ S_threshold = alpha * lambda ; // Threshold for the soft-thresholding operator S() do_active_only = 0 ; // Begin with a complete pass prior_crit = 1.0e60 ; // For convergence test if(warm_start) // Pick up with current betas? { if(! m_covarupdates) // If not using covariance updates, must recompute residuals { for(icase=0 ; icase<m_observs ; icase++) { xptr = icase * m_nvars ; sum = 0.0 ; for(ivar=0 ; ivar<m_nvars ; ivar++) sum += m_beta[ivar] * m_x_matrix[xptr+ivar] ; m_resid[icase] = m_y[icase] - sum ; } } } else // Not warm start, so initial betas are all zero { for(i=0 ; i<m_nvars ; i++) m_beta[i] = 0.0 ; for(i=0 ; i<m_observs ; i++) // Initial residuals are just the Y variable m_resid[i] = m_y[i] ; } // YmeanSquare will remain fixed throughout training. // Its only use is for computing m_explained variance for the user's edification. YmeanSquare = 1.0 ; /* Outmost loop iterates until converged or user's maxits limit hit */ for(iter=0 ; iter<maxits ; iter++) { /* Pass through variables */ active_set_changed = 0 ; // Did any betas go to/from 0.0? max_change = 0.0 ; // For fast convergence test for(ivar=0 ; ivar<m_nvars ; ivar++) // Descend on this m_beta { if(do_active_only && m_beta[ivar] == 0.0) continue ; Xss = 1 ; // X was standardized update_factor = Xss + lambda * (1.0 - alpha) ; if(m_covarupdates) // Any sensible user will specify this unless m_observs < m_nvars { sum = 0.0 ; for(kvar=0 ; kvar<m_nvars ; kvar++) sum += m_xinner_matrix[ivar*m_nvars+kvar] * m_beta[kvar] ; residual_sum = m_yinner[ivar] - sum ; argument = residual_sum + Xss * m_beta[ivar] ; // Argument to S() [MY FORMULA] } else // Use slow definitional formula (okay if m_observs < m_nvars) { residual_sum = 0.0 ; xptr = ivar ; // Point to column of this variable for(icase=0 ; icase<m_observs ; icase++) residual_sum += m_x_matrix[xptr+icase*m_nvars] * m_resid[icase] ; // X_ij * RESID_i residual_sum /= m_observs ; argument = residual_sum + m_beta[ivar] ; // Argument to S() ; (Eq 8) } // Apply the soft-thresholding operator S() if(argument > 0.0 && S_threshold < argument) new_beta = (argument - S_threshold) / update_factor ; else if(argument < 0.0 && S_threshold < -argument) new_beta = (argument + S_threshold) / update_factor ; else new_beta = 0.0 ; // Apply the update, if changed, and adjust the residual if using naive or weighted updates // This is also used to update the fast convergence criterion correction = new_beta - m_beta[ivar] ; // Will use this to adjust residual if using naive updates if(fabs(correction) > max_change) max_change = fabs(correction) ; // Used for fast convergence criterion if(correction != 0.0) // Did this m_beta change? { if(! m_covarupdates) // Must we update the residual vector (needed for naive methods)? { xptr = ivar ; // Point to column of this variable for(icase=0 ; icase<m_observs ; icase++) // Update residual for this new m_beta m_resid[icase] -= correction * m_x_matrix[xptr+icase*m_nvars] ; } if((m_beta[ivar] == 0.0 && new_beta != 0.0) || (m_beta[ivar] != 0.0 && new_beta == 0.0)) active_set_changed = 1 ; m_beta[ivar] = new_beta ; } } // For all variables; a complete pass /* A pass (complete or active only) through variables has been done. If we are using the fast convergence test, it is simple. But if using the slow method... Compute m_explained variance and criterion; compare to prior for convergence test If the user requested the covariance update method, we must compute residuals for these. */ if(fast_test) // Quick and simple test { if(max_change < convergence_criterion) converged = 1 ; else converged = 0 ; } else // Slow test (change in m_explained variance) which requires residual { if(m_covarupdates) // We have until now avoided computing residuals { for(icase=0 ; icase<m_observs ; icase++) { xptr = icase * m_nvars ; sum = 0.0 ; for(ivar=0 ; ivar<m_nvars ; ivar++) sum += m_beta[ivar] * m_x_matrix[xptr+ivar] ; // Cumulate predicted value m_resid[icase] = m_y[icase] - sum ; // Residual = true - predicted } } sum = 0.0 ; // Will cumulate squared error for convergence test for(i=0 ; i<m_observs ; i++) sum += m_resid[i] * m_resid[i] ; crit = sum / m_observs ; // MSE component of optimization criterion explained_variance = (YmeanSquare - crit) / YmeanSquare ; // Fraction of Y m_explained penalty = 0.0 ; for(i=0 ; i<m_nvars ; i++) penalty += 0.5 * (1.0 - alpha) * m_beta[i] * m_beta[i] + alpha * fabs(m_beta[i]) ; penalty *= 2.0 * lambda ; // Regularization component of optimization criterion crit += penalty ; // This is what we are minimizing if(prior_crit - crit < convergence_criterion) converged = 1 ; else converged = 0 ; prior_crit = crit ; } /* After doing a complete (all variables) pass, we iterate on only the active set (m_beta != 0) until convergence. Then we do a complete pass. If the active set does not change, we are done: If a m_beta goes from zero to nonzero, by definition the active set changed. If a m_beta goes from nonzero to another nonzero, then this is a theoretical flaw in this process. However, if we just iterated the active set to convergence, it is highly unlikely that we would get anything other than a tiny move. */ if(do_active_only) // Are we iterating on the active set only? { if(converged) // If we converged do_active_only = 0 ; // We now do a complete pass } else // We just did a complete pass (all variables) { if(converged && ! active_set_changed) break ; do_active_only = 1 ; // We now do an active-only pass } } // Outer loop iterations /* We are done. Compute and save the m_explained variance. If we did the fast convergence test and covariance updates, we must compute the residual in order to get the m_explained variance. Those two options do not require regular residual computation, so we don't currently have the residual. */ if(fast_test && m_covarupdates) // Residuals have not been maintained? { for(icase=0 ; icase<m_observs ; icase++) { xptr = icase * m_nvars ; sum = 0.0 ; for(ivar=0 ; ivar<m_nvars ; ivar++) sum += m_beta[ivar] * m_x_matrix[xptr+ivar] ; m_resid[icase] = m_y[icase] - sum ; } } sum = 0.0 ; for(i=0 ; i<m_observs ; i++) sum += m_resid[i] * m_resid[i] ; crit = sum / m_observs ; // MSE component of optimization criterion m_explained = (YmeanSquare - crit) / YmeanSquare ; // This variable is a member of the class }
По мере наблюдений мы также вычисляем долю объясненной целевой дисперсии. Когда используется тест медленной сходимости (для fast_test установлено значение false), сходимость достигается, когда изменение от одной итерации к следующей меньше указанного значения критерия сходимости.
В противном случае, если используется быстрый метод, сходимость достигается, когда максимальное изменение корректировки бета среди всех бета меньше критерия сходимости.
//+------------------------------------------------------------------+ //|Compute minimum lambda such that all betas remain at zero | //+------------------------------------------------------------------+ double CCoordinateDescent::GetLambdaThreshold(const double alpha) { if(!m_initialized) return 0; if(alpha>1 || alpha<0) { Print("Invalid parameter for Alpha, legal values are between 0 and 1 inclusive"); return 0; } int ivar, icase,xptr ; double thresh, sum; thresh = 0.0 ; for(ivar=0 ; ivar<m_nvars ; ivar++) { xptr = ivar ; sum = 0.0 ; for(icase=0 ; icase<m_observs ; icase++) sum += m_x_matrix[xptr+icase*m_nvars] * m_y[icase] ; sum /= m_observs ; sum = fabs(sum) ; if(sum > thresh) thresh = sum ; } return thresh / (alpha + 1.e-60) ; }
GetLambdaThreshold() требует одного входного параметра, определяющего тип регуляризации. Этот метод возвращает вычисленное значение лямбды, для которого все соответствующие бета-версии равны нулю. Идея состоит в том, что такое значение было бы хорошим началом поиска оптимального лямбда-гиперпараметра для данной альфа.
Фактическая оптимизация лямбды выполняется с помощью TrainLambda(). Он имеет параметры функции, аналогичные Train(). Пользователь может указать начальное значение лямбды через maxlambda. Установка значения 0 или меньше автоматически задействует GetlambdaThreshold() для установки истинного начального значения. Основной цикл неоднократно вызывает Train() и сохраняет бета-версии для каждой лямбды в течение максимума итераций m_nlambda, указанных в вызове конструктора.
//+----------------------------------------------------------------------------------------+ //| Multiple-lambda training routine calls Train() repeatedly, saving each m_beta vector | | //+----------------------------------------------------------------------------------------+ void CCoordinateDescent::TrainLambda( const double alpha, // User-specified alpha, (0,1) (0 problematic for descending lambda) const int maxits, // Maximum iterations, for safety only const double convergence_criterion, // Convergence criterion, typically 1.e-5 or so const bool fast_test, // Base convergence on max m_beta change vs m_explained variance? const double maxlambda, // Starting lambda, or negative for automatic computation const bool print_steps // Print lambda/m_explained table? ) { if(!m_initialized) return; int ivar, ilambda, n_active ; double lambda, min_lambda, lambda_factor,max_lambda=maxlambda; string fprint ; if(m_nlambda <= 1) return ; /* Compute the minimum lambda for which all m_beta weights remain at zero This (slightly decreased) will be the lambda from which we start our descent. */ if(max_lambda <= 0.0) max_lambda = 0.999 * GetLambdaThreshold(alpha) ; min_lambda = 0.001 * max_lambda ; lambda_factor = exp(log(min_lambda / max_lambda) / (m_nlambda-1)) ; /* Repeatedly train with decreasing m_lambdas */ if(print_steps) { fprint+="\nDescending lambda path..."; } lambda = max_lambda ; for(ilambda=0 ; ilambda<m_nlambda ; ilambda++) { m_lambdas[ilambda] = lambda ; // Save in case we want to use later Train(alpha, lambda, maxits, convergence_criterion, fast_test,(bool)ilambda) ; for(ivar=0 ; ivar<m_nvars ; ivar++) m_lambdabeta_matrix[ilambda*m_nvars+ivar] = m_beta[ivar] ; if(print_steps) { n_active = 0 ; for(ivar=0 ; ivar<m_nvars ; ivar++) { if(fabs(m_beta[ivar]) > 0.0) ++n_active ; } fprint+=StringFormat("\n %8.4lf %4d %12.4lf", lambda, n_active, m_explained) ; } lambda *= lambda_factor ; } if(print_steps) Print(fprint); }
Наш класс покоординатного спуска завершен. Далее нам нужен инструмент для проведения перекрестной проверки, чтобы настроить лямбда-гиперпараметр.
Функция OptimizeLambda
//+------------------------------------------------------------------------------------------+ //| Cross-validation training routine calls TrainLambda() repeatedly to optimize lambda | //+------------------------------------------------------------------------------------------+ double OptimizeLambda( int n_observations, // Number of cases in full database int n_predictors, // Number of variables (columns in database) int n_folds, // Number of folds bool covar_updates, // Does user want (usually faster) covariance update method? int n_lambda, // This many out_lambdas tested by lambda_train() (must be at least 2) double alpha, // User-specified alpha, (0,1) (0 problematic for descending lambda) int maxits, // Maximum iterations, for safety only double convergence_criterion, // Convergence criterion, typically 1.e-5 or so bool fast_test, // Base convergence on max beta change vs explained variance? double &in_matrix[], // Full database (n_observations rows, n_predictors columns) double &in_targets[], // Predicted variable vector, n_observations long double &out_lambdas[], // Returns out_lambdas tested by lambda_train() double &out_lambda_OOS[], // Returns OOS explained for each of above out_lambdas bool print_output = false // show full output )
Его основная цель — реализовать обучение перекрестной проверке для автоматического выбора лямбда-гиперпараметра. Большинство входных параметров имеют знакомые имена, поскольку процедура использует оптимизацию спуска по координатам.
Эту функцию можно дополнительно использовать, когда пользователь не уверен, какое значение лямбды использовать. Перекрестная проверка — это метод настройки гиперпараметров. Чтобы использовать его, мы, очевидно, потребуем передать те же данные обучения, которые в конечном итоге будут использованы для построения полной регрессионной модели.
in_matrix — это входные данные для матрицы предикторов, in_targets — для соответствующих целей. В дополнение к этим входным массивам нам также необходимо предоставить еще два массива. out_lambdas и out_lambda_OOS — это массивы, которые будут содержать более подробную информацию о процессе перекрестной проверки.
Последний параметр указывает, следует ли отображать результаты в терминале.
{ int i_IS, n_IS, i_OOS, n_OOS, n_done, ifold ; int icase, ivar, ilambda, ibest, k,coefs ; double pred, sum, diff, max_lambda, Ynormalized, YsumSquares, best,work[] ; CCoordinateDescent *cd ; if(n_lambda < 2) return 0.0 ; /* Use the entire dataset to find the max lambda that will be used for all descents. Also, copy the normalized case weights if there are any. */ cd = new CCoordinateDescent(n_predictors, n_observations, covar_updates, n_lambda) ; cd.SetData(0, n_observations, in_matrix, in_targets) ; // Fetch the training set for this fold max_lambda = cd.GetLambdaThreshold(alpha) ; delete cd ; if(print_output) PrintFormat("%s starting for %d folds with max lambda=%.9lf",__FUNCTION__, n_folds, max_lambda) ; i_IS = 0 ; // Training data starts at this index in complete database n_done = 0 ; // Number of cases treated as OOS so far for(ilambda=0 ; ilambda<n_lambda ; ilambda++) out_lambda_OOS[ilambda] = 0.0 ; // Will cumulate across folds here YsumSquares = 0.0 ; // Will cumulate to compute explained fraction /* Process the folds */ for(ifold=0 ; ifold<n_folds ; ifold++) { n_OOS = (n_observations - n_done) / (n_folds - ifold) ; // Number OOS (test set) n_IS = n_observations - n_OOS ; // Number IS (training set) i_OOS = (i_IS + n_IS) % n_observations ; // OOS starts at this index // Train the model with this IS set cd = new CCoordinateDescent(n_predictors, n_IS, covar_updates, n_lambda) ; cd.SetData(i_IS, n_observations, in_matrix, in_targets) ; // Fetch the training set for this fold cd.TrainLambda(alpha, maxits, convergence_criterion, fast_test, max_lambda,print_output) ; // Compute the complete set of betas (all out_lambdas) // Compute OOS performance for each lambda and sum across folds. // Normalization of X and Y is repeated, when it could be done once and saved. // But the relative cost is minimal, and it is simpler doing it this way. for(ilambda=0 ; ilambda<n_lambda ; ilambda++) { out_lambdas[ilambda] = cd.GetLambdaAt(ilambda) ; // This will be the same for all folds coefs = ilambda * n_predictors ; sum = 0.0 ; for(icase=0 ; icase<n_OOS ; icase++) { k = (icase + i_OOS) % n_observations ; pred = 0.0 ; for(ivar=0 ; ivar<n_predictors ; ivar++) pred += cd.GetLambdaBetaAt(coefs+ivar) * (in_matrix[k*n_predictors+ivar] - cd.GetXmeansAt(ivar)) / cd.GetXscalesAt(ivar) ; Ynormalized = (in_targets[k] - cd.GetYmean()) / cd.GetYscale() ; diff = Ynormalized - pred ; if(ilambda == 0) YsumSquares += Ynormalized * Ynormalized ; sum += diff * diff ; } out_lambda_OOS[ilambda] += sum ; // Cumulate for this fold } // For ilambda delete cd ; n_done += n_OOS ; // Cumulate OOS cases just processed i_IS = (i_IS + n_OOS) % n_observations ; // Next IS starts at this index } // For ifold /* Compute OOS explained variance for each lambda, and keep track of the best */ best = -1.e60 ; for(ilambda=0 ; ilambda<n_lambda ; ilambda++) { out_lambda_OOS[ilambda] = (YsumSquares - out_lambda_OOS[ilambda]) / YsumSquares ; if(out_lambda_OOS[ilambda] > best) { best = out_lambda_OOS[ilambda] ; ibest = ilambda ; } } if(print_output) PrintFormat("\n%s ending with best lambda=%9.9lf explained=%9.9lf",__FUNCTION__, out_lambdas[ibest], best) ; return out_lambdas[ibest] ; } //+------------------------------------------------------------------+
Функция использует локальный экземпляр CCordinateDescent для проверки набора лямбда-выражений. Количество тестируемых лямбд задается параметром n_lambda функции. Протестированные лямбды начинаются с максимума, рассчитанного путем вызова GetLambdaThreshold(). После каждой итерации тестирования предыдущее значение лямбды немного уменьшается. Каждый лямбда-тест генерирует новые бета-коэффициенты, которые используются для расчета доли объясненной дисперсии. Все это делается для каждой свертки. Результаты всех сверток анализируются и выбирается лучший. Лямбда, давшая лучший результат, возвращается как оптимальная.
Мы описали все утилиты кода. Пришло время заставить их работать.
Пример
Чтобы продемонстрировать практическое применение этого метода, мы будем использовать его для построения модели, которая предсказывает изменение цены к следующему бару на основе совокупности длинных и коротких скользящих средних. Мы хотим найти набор скользящих средних, которые наиболее полезны для прогнозирования изменения цены следующего бара.
Мы снабжаем модель индикаторами, рассчитанными на основе логарифмически преобразованных необработанных цен, целевыми значениями которых являются логарифмические разницы. Нам нужен индикатор, который преобразует необработанные цены, чтобы другие индикаторы (в данном случае скользящее среднее) могли ссылаться на него. Индикатор логарифмических цен показан ниже.
//+------------------------------------------------------------------+ //| LogPrices.mq5 | //| Copyright 2023, MetaQuotes Software Corp. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2023, MetaQuotes Software Corp." #property link "https://www.mql5.com" #property version "1.00" #property indicator_separate_window #property indicator_buffers 1 #property indicator_plots 1 //--- plot Log #property indicator_label1 "Log" #property indicator_type1 DRAW_LINE #property indicator_color1 clrTurquoise #property indicator_style1 STYLE_SOLID #property indicator_width1 1 //--- indicator buffers double LogBuffer[]; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- indicator buffers mapping SetIndexBuffer(0,LogBuffer,INDICATOR_DATA); //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Custom indicator iteration function | //+------------------------------------------------------------------+ int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[]) { //--- for(int i=(prev_calculated>0)?prev_calculated-1:0; i<rates_total; i++) LogBuffer[i]=(price[i]>0)?log(price[i]):0; //--- return value of prev_calculated for next call return(rates_total); } //+------------------------------------------------------------------+
Программа обучения будет реализована в виде скрипта. Начнем с указания основных включаемых файлов и входных данных скрипта. Входные данные позволяют пользователю настраивать различные аспекты программы в соответствии со своими потребностями. Сюда входит возможность устанавливать даты для промежутков времени обучения и тестирования.
//+------------------------------------------------------------------+ //| ElasticNetRegressionModel_MA.mq5 | //| Copyright 2023, MetaQuotes Software Corp. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2023, MetaQuotes Software Corp." #property link "https://www.mql5.com" #property version "1.00" #resource "\\Indicators\\LogPrices.ex5" #include<CoordinateDescent.mqh> #include<ErrorDescription.mqh> #property script_show_inputs //--- input parameters input uint MA_period_inc=2; //MA lookback increment input uint Num_MA_periods=30; //Num of lookbacks input double Alpha=0.5; input int AppliedPrice=PRICE_CLOSE; input ENUM_MA_METHOD MaMethod=MODE_EMA; input ENUM_TIMEFRAMES tf=PERIOD_D1; //time frame input uint BarsLookAhead=1; input uint Num_Folds = 10; //Num of Folds for cross validation input uint MaximumIterations=1000; input datetime TrainingSampleStartDate=D'2019.12.31'; input datetime TrainingSampleStopDate=D'2022.12.31'; input datetime TestingSampleStartDate=D'2023.01.02'; input datetime TestingSampleStopDate=D'2023.06.30'; input string SetSymbol=""; input bool UseCovarUpdates=true; input bool UseFastTest=true; input bool UseWarmStart=false; input int NumLambdasToTest=50; input bool ShowFullOutPut=false; //print full output to terminal
Важными опциями пользовательского ввода являются входные данные MA_ period_inc, которые устанавливают приращения периода. Num_Ma_ periods определяет количество скользящих средних, которые будут переданы в алгоритм. Значения индикатора, которые будут использоваться в качестве предикторов, будут представлять собой разницу между длинной и короткой скользящей средней. Короткая скользящая средняя рассчитывается как половина периода результирующей длинной скользящей средней. Длинная скользящая средняя определяется путем увеличения на MA_period_inc в Num_MA_period раз.
Num_Folds определяет количество сверток, которые будут использоваться функцией Optimizelambda во время перекрестной проверки.
Названия других входных данных говорят сами за себя.
Скрипт начинается с перечисления наборов данных обучения и тестирования. Размер локальных буферов изменяется в зависимости от выбранных пользователем данных.
//+------------------------------------------------------------------+ //|global integer variables | //+------------------------------------------------------------------+ int size_insample, //training set size size_outsample, //testing set size size_observations, //size of of both training and testing sets combined size_lambdas, //number of lambdas to be tested size_predictors, //number of predictors maxperiod, //maximum lookback price_handle=INVALID_HANDLE, //log prices indicator handle long_ma_handle=INVALID_HANDLE, //long moving average indicator handle short_ma_handle=INVALID_HANDLE;//short moving average indicator handle //+------------------------------------------------------------------+ //|double global variables | //+------------------------------------------------------------------+ double prices[], //array for log transformed prices targets[], //differenced prices kept here predictors_matrix[], //flat array arranged as matrix of all predictors_matrix ie size_observations by size_predictors longma[], //long ma indicator values Lambdas[], //calculated lambdas kept here Lambdas_OOS[], //calculated out of sample lambdas are here shortma[], //short ma indicator values Lambda; //initial optimal lambda value //+------------------------------------------------------------------+ //| Coordinate descent pointer | //+------------------------------------------------------------------+ CCoordinateDescent *cdmodel; //coordinate descent pointer //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { //get relative shift of is and oos sets int teststart,teststop,trainstart,trainstop; teststart=iBarShift(SetSymbol!=""?SetSymbol:NULL,tf,TestingSampleStartDate); teststop=iBarShift(SetSymbol!=""?SetSymbol:NULL,tf,TestingSampleStopDate); trainstart=iBarShift(SetSymbol!=""?SetSymbol:NULL,tf,TrainingSampleStartDate); trainstop=iBarShift(SetSymbol!=""?SetSymbol:NULL,tf,TrainingSampleStopDate); //check for errors from ibarshift calls if(teststart<0 || teststop<0 || trainstart<0 || trainstop<0) { Print(ErrorDescription(GetLastError())); return; } //---set the size of the sample sets size_observations=(trainstart - teststop) + 1 ; size_outsample=(teststart - teststop) + 1; size_insample=(trainstart - trainstop) + 1; maxperiod=int(Num_MA_periods*MA_period_inc); size_insample-=maxperiod; size_lambdas=NumLambdasToTest; size_predictors=int(Num_MA_periods); //---check for input errors if(size_lambdas<=0 || size_insample<=0 || size_outsample<=0 || size_predictors<=0 || maxperiod<=0 || BarsLookAhead<=0) { Print("Invalid inputs "); return; } //--- Comment("resizing buffers...");
Массивы, которые будут переданы экземпляру CCordinateDescent, подготавливаются и заполняются: это целевой массив и матрица предикторов.
//---allocate memory if(ArrayResize(targets,size_observations)<(int)size_observations || ArrayResize(predictors_matrix,size_observations*size_predictors)<int(size_observations*size_predictors) || ArrayResize(Lambdas,size_lambdas)<(int)size_lambdas || ArrayResize(Lambdas_OOS,size_lambdas)<(int)size_lambdas || ArrayResize(shortma,size_observations)<(int)size_observations || ArrayResize(longma,size_observations)<(int)size_observations || ArrayResize(prices,size_observations+BarsLookAhead)<int(size_observations+BarsLookAhead)) { Print("ArrayResize error ",ErrorDescription(GetLastError())); return; } //--- Comment("getting price predictors_matrix..."); //---set prices handle price_handle=iCustom(SetSymbol!=""?SetSymbol:NULL,tf,"::Indicators\\LogPrices.ex5",AppliedPrice); if(price_handle==INVALID_HANDLE) { Print("invalid logprices handle ",ErrorDescription(GetLastError())); return; } //--- Comment("getting indicators..."); //----calculate the full collection of predictors_matrix int longmaperiod,shortmaperiod,prevshort,prevlong; int k=0; //--- prevlong=prevshort=0; //--- for(uint iperiod=0; iperiod<Num_MA_periods; iperiod++) { longmaperiod=(int)(iperiod+1)*int(MA_period_inc); shortmaperiod = (longmaperiod>=2)?int(longmaperiod/2):longmaperiod; ResetLastError(); int try=10; while(try) { long_ma_handle=iMA(SetSymbol!=""?SetSymbol:NULL,tf,longmaperiod,0,MaMethod,price_handle); short_ma_handle=iMA(SetSymbol!=""?SetSymbol:NULL,tf,shortmaperiod,0,MaMethod,price_handle); if(long_ma_handle==INVALID_HANDLE || short_ma_handle==INVALID_HANDLE) try--; else break; } Comment("copying buffers for short ",shortmaperiod," long ",longmaperiod); if(CopyBuffer(long_ma_handle,0,teststop,size_observations,longma)<=0 || CopyBuffer(short_ma_handle,0,teststop,size_observations,shortma)<=0) { Print("error copying to ma buffers ",GetLastError()); return; } for(int i=0 ; i<int(size_observations) ; i++) predictors_matrix[i*size_predictors+k] = shortma[i]-longma[i]; ++k ; if(long_ma_handle!=INVALID_HANDLE && short_ma_handle!=INVALID_HANDLE && IndicatorRelease(long_ma_handle) && IndicatorRelease(short_ma_handle)) { long_ma_handle=short_ma_handle=INVALID_HANDLE; prevlong=longmaperiod; prevshort=shortmaperiod; } } //--- Comment("filling target buffer..."); //--- ResetLastError(); if(CopyBuffer(price_handle,0,teststop,size_observations+BarsLookAhead,prices)<int(size_observations+BarsLookAhead)) { Print("error copying to price buffer , ",ErrorDescription(GetLastError())); return; } //--- for(int i=0 ; i<int(size_observations); i++) targets[i] = prices[i+BarsLookAhead]-prices[i]; //---
Настройка лямбды производится в зависимости от значения Alpha. Когда альфа меньше или равна нулю, оптимальная лямбда не рассчитывается. Результатом будет модель, напоминающая стандартную линейную регрессию без какой-либо регуляризации.
//--- Comment("optional lambda tuning..."); //--- if(Alpha<=0) Lambda=0; else //train Lambda=OptimizeLambda(size_insample,size_predictors,(int)Num_Folds,UseCovarUpdates,size_lambdas,Alpha,(int)MaximumIterations,1.e-9,UseFastTest,predictors_matrix,targets,Lambdas,Lambdas_OOS,ShowFullOutPut); //---
После завершения обучения объектом CCordinateDescent результаты могут быть дополнительно выведены на терминал.
Comment("coordinate descent engagement..."); //---initialize CD object cdmodel=new CCoordinateDescent(size_predictors,size_insample,UseCovarUpdates,0); //--- if(cdmodel==NULL) { Print("error creating Coordinate Descent object "); return; } //---set the parameters and data cdmodel.SetData(0,size_insample,predictors_matrix,targets); //--- Print("optimal lambda ",DoubleToString(Lambda)); //---train the model cdmodel.Train(Alpha,Lambda,(int)MaximumIterations,1.e-7,UseFastTest,UseWarmStart); //--- Print("explained variance ",cdmodel.GetExplainedVariance()); //---optionally output results of training here if(ShowFullOutPut) { k=0; string output; for(uint iperiod=0; iperiod<Num_MA_periods; iperiod++) { longmaperiod=(int)(iperiod+1)*int(MA_period_inc); output+=StringFormat("\n%5d ", longmaperiod) ; shortmaperiod = (longmaperiod>=2)?int(longmaperiod/2):longmaperiod; output+=StringFormat(",%5d ,%9.9lf ", shortmaperiod,cdmodel.GetBetaAt(k)); ++k; } Print(output); } //---
Выходные данные программы будут отображаться в столбцах: первый столбец показывает период длинного скользящего среднего, второй отображает соответствующее короткое скользящее среднее и, наконец, указывается значение бета для этого конкретного предиктора. Если отображается ноль, это означает, что предиктор был отброшен.
double sum=0.0; //cumulated predictions double pred; //a prediction int xptr; k=size_observations - (size_insample+maxperiod) - 1; //--- Comment("test the model..."); //---do the out of sample test for(int i=k ; i<size_observations ; i++) { xptr = i*size_predictors ; pred = 0.0 ; for(int ivar=0 ; ivar<int(size_predictors) ; ivar++) pred += cdmodel.GetBetaAt(ivar) * (predictors_matrix[xptr+ivar] - cdmodel.GetXmeansAt(ivar)) / cdmodel.GetXscalesAt(ivar) ; pred = pred * cdmodel.GetYscale() + cdmodel.GetYmean() ; // Unscale prediction to get it back in original Y domain if(pred > 0.0) sum += targets[i] ; else if(pred < 0.0) sum -= targets[i] ; } //--- PrintFormat("OOS total return = %.5lf (%.3lf percent)",sum, 100.0 * (exp(sum) - 1.0)) ; //--- delete cdmodel; //--- Comment("");
Программа завершается после проверки производительности за выбранный период тестирования. Пользователи должны учитывать, что значение производительности, отображаемое в конце программы, не является показателем истинной производительности, поскольку многое не принимается во внимание. Эти цифры следует использовать по сравнению с другими результатами, полученными при использовании различных наборов параметров программы.
Вывод ниже показывает результаты, когда Alpha равно 0. Как говорилось ранее, когда альфа равна 0, регуляризация отсутствует, модель строится с использованием всех предоставленных предикторов, ни один из них не исключен.
DH 0 19:58:47.521 ELN_MA (GBPUSD,D1) optimal lambda 0.00000000 HP 0 19:58:47.552 ELN_MA (GBPUSD,D1) explained variance 0.9914167039554915 ID 0 19:58:47.552 ELN_MA (GBPUSD,D1) FF 0 19:58:47.552 ELN_MA (GBPUSD,D1) 2 , 1 ,1.85143599128379721108e+00 JJ 0 19:58:47.552 ELN_MA (GBPUSD,D1) 4 , 2 ,-2.44139247803866465958e+00 MR 0 19:58:47.552 ELN_MA (GBPUSD,D1) 6 , 3 ,2.32230838054034549600e+00 HF 0 19:58:47.552 ELN_MA (GBPUSD,D1) 8 , 4 ,-2.35763762038486313077e-01 FJ 0 19:58:47.552 ELN_MA (GBPUSD,D1) 10 , 5 ,-5.12822602346063693979e-01 MP 0 19:58:47.552 ELN_MA (GBPUSD,D1) 12 , 6 ,-2.63526268082343251287e-01 CF 0 19:58:47.552 ELN_MA (GBPUSD,D1) 14 , 7 ,-4.66454472659737495732e-02 FN 0 19:58:47.552 ELN_MA (GBPUSD,D1) 16 , 8 ,6.22551516067148258404e-02 KP 0 19:58:47.552 ELN_MA (GBPUSD,D1) 18 , 9 ,9.45364603399752728707e-02 JK 0 19:58:47.552 ELN_MA (GBPUSD,D1) 20 , 10 ,8.71627177974267641769e-02 JM 0 19:58:47.552 ELN_MA (GBPUSD,D1) 22 , 11 ,6.43970377784374714558e-02 CG 0 19:58:47.552 ELN_MA (GBPUSD,D1) 24 , 12 ,3.92137206481772693234e-02 FI 0 19:58:47.552 ELN_MA (GBPUSD,D1) 26 , 13 ,1.74528224486318189745e-02 HS 0 19:58:47.552 ELN_MA (GBPUSD,D1) 28 , 14 ,1.04642691815316421500e-03 PG 0 19:58:47.552 ELN_MA (GBPUSD,D1) 30 , 15 ,-9.98741520244338966406e-03 RM 0 19:58:47.552 ELN_MA (GBPUSD,D1) 32 , 16 ,-1.64348263919291276425e-02 CS 0 19:58:47.552 ELN_MA (GBPUSD,D1) 34 , 17 ,-1.93143258653755492404e-02 QI 0 19:58:47.552 ELN_MA (GBPUSD,D1) 36 , 18 ,-1.96075858211104264717e-02 FO 0 19:58:47.552 ELN_MA (GBPUSD,D1) 38 , 19 ,-1.81510403514190954422e-02 RD 0 19:58:47.552 ELN_MA (GBPUSD,D1) 40 , 20 ,-1.56082180218151990447e-02 PJ 0 19:58:47.552 ELN_MA (GBPUSD,D1) 42 , 21 ,-1.24793265043600110076e-02 HP 0 19:58:47.552 ELN_MA (GBPUSD,D1) 44 , 22 ,-9.12541199880392318866e-03 MF 0 19:58:47.552 ELN_MA (GBPUSD,D1) 46 , 23 ,-5.79584482050124645547e-03 DL 0 19:58:47.552 ELN_MA (GBPUSD,D1) 48 , 24 ,-2.65399377323665905393e-03 PP 0 19:58:47.552 ELN_MA (GBPUSD,D1) 50 , 25 ,2.00883928121427593472e-04 RJ 0 19:58:47.552 ELN_MA (GBPUSD,D1) 52 , 26 ,2.71594753051577000869e-03 IL 0 19:58:47.552 ELN_MA (GBPUSD,D1) 54 , 27 ,4.87097208116808733092e-03 IF 0 19:58:47.552 ELN_MA (GBPUSD,D1) 56 , 28 ,6.66787159270224374930e-03 MH 0 19:58:47.552 ELN_MA (GBPUSD,D1) 58 , 29 ,8.12292277995673578372e-03 NR 0 19:58:47.552 ELN_MA (GBPUSD,D1) 60 , 30 ,9.26111235731779183777e-03 JG 0 19:58:47.568 ELN_MA (GBPUSD,D1) OOS total return = 3.42660 (2977.187 percent)
Ниже приведены выходные данные при Alpha равном 0,1. Интерес представляют значения бета по сравнению с предыдущим прогоном. Нулевые значения бета показывают, что соответствующий предиктор был отброшен.
NP 0 19:53:32.412 ELN_MA (GBPUSD,D1) optimal lambda 0.00943815 HH 0 19:53:32.458 ELN_MA (GBPUSD,D1) explained variance 0.9748473636648924 GL 0 19:53:32.458 ELN_MA (GBPUSD,D1) GN 0 19:53:32.458 ELN_MA (GBPUSD,D1) 2 , 1 ,1.41004781317849103850e+00 MR 0 19:53:32.458 ELN_MA (GBPUSD,D1) 4 , 2 ,-6.98106822708694618740e-01 DJ 0 19:53:32.458 ELN_MA (GBPUSD,D1) 6 , 3 ,0.00000000000000000000e+00 NL 0 19:53:32.458 ELN_MA (GBPUSD,D1) 8 , 4 ,1.30221271072762545540e-01 MG 0 19:53:32.458 ELN_MA (GBPUSD,D1) 10 , 5 ,1.13824982442231326107e-01 DI 0 19:53:32.458 ELN_MA (GBPUSD,D1) 12 , 6 ,0.00000000000000000000e+00 IS 0 19:53:32.458 ELN_MA (GBPUSD,D1) 14 , 7 ,0.00000000000000000000e+00 NE 0 19:53:32.458 ELN_MA (GBPUSD,D1) 16 , 8 ,0.00000000000000000000e+00 GO 0 19:53:32.458 ELN_MA (GBPUSD,D1) 18 , 9 ,0.00000000000000000000e+00 JP 0 19:53:32.458 ELN_MA (GBPUSD,D1) 20 , 10 ,0.00000000000000000000e+00 DH 0 19:53:32.458 ELN_MA (GBPUSD,D1) 22 , 11 ,-3.69006880128594713653e-02 OM 0 19:53:32.458 ELN_MA (GBPUSD,D1) 24 , 12 ,-2.43715386443472993572e-02 LS 0 19:53:32.458 ELN_MA (GBPUSD,D1) 26 , 13 ,-3.50967791710741789518e-03 DK 0 19:53:32.458 ELN_MA (GBPUSD,D1) 28 , 14 ,0.00000000000000000000e+00 LM 0 19:53:32.458 ELN_MA (GBPUSD,D1) 30 , 15 ,0.00000000000000000000e+00 KG 0 19:53:32.458 ELN_MA (GBPUSD,D1) 32 , 16 ,0.00000000000000000000e+00 RI 0 19:53:32.458 ELN_MA (GBPUSD,D1) 34 , 17 ,0.00000000000000000000e+00 ES 0 19:53:32.458 ELN_MA (GBPUSD,D1) 36 , 18 ,0.00000000000000000000e+00 PE 0 19:53:32.458 ELN_MA (GBPUSD,D1) 38 , 19 ,0.00000000000000000000e+00 KO 0 19:53:32.458 ELN_MA (GBPUSD,D1) 40 , 20 ,0.00000000000000000000e+00 NQ 0 19:53:32.458 ELN_MA (GBPUSD,D1) 42 , 21 ,0.00000000000000000000e+00 QK 0 19:53:32.458 ELN_MA (GBPUSD,D1) 44 , 22 ,0.00000000000000000000e+00 PM 0 19:53:32.458 ELN_MA (GBPUSD,D1) 46 , 23 ,0.00000000000000000000e+00 GG 0 19:53:32.458 ELN_MA (GBPUSD,D1) 48 , 24 ,0.00000000000000000000e+00 OI 0 19:53:32.458 ELN_MA (GBPUSD,D1) 50 , 25 ,0.00000000000000000000e+00 PS 0 19:53:32.458 ELN_MA (GBPUSD,D1) 52 , 26 ,0.00000000000000000000e+00 RE 0 19:53:32.458 ELN_MA (GBPUSD,D1) 54 , 27 ,1.14149417738317331301e-03 FO 0 19:53:32.458 ELN_MA (GBPUSD,D1) 56 , 28 ,3.18638349345921325848e-03 IQ 0 19:53:32.458 ELN_MA (GBPUSD,D1) 58 , 29 ,3.87574752936066481077e-03 KK 0 19:53:32.458 ELN_MA (GBPUSD,D1) 60 , 30 ,3.16472282935538083357e-03 QN 0 19:53:32.474 ELN_MA (GBPUSD,D1) OOS total return = 3.40954 (2925.133 percent)
Далее мы просматриваем выходные данные, когда Alpha равно 0,9. На этот раз мы выделяем выходные данные LambdaOptimize. В первом столбце указано протестированное значение лямбда, во втором столбце показано количество предикторов, включенных в модель, а в последнем столбце показана доля объясненного отклонения от теста для определенной свертки. В скрипте мы указали 10 сверток, значит есть десять таблиц этих данных.
ME 0 19:57:21.630 ELN_MA (GBPUSD,D1) OptimizeLambda starting for 10 folds with max lambda=1.048683301 JE 0 19:57:21.833 ELN_MA (GBPUSD,D1) RO 0 19:57:21.833 ELN_MA (GBPUSD,D1) Descending lambda path... RE 0 19:57:21.833 ELN_MA (GBPUSD,D1) 1.0487 0 0.0000 NM 0 19:57:21.833 ELN_MA (GBPUSD,D1) 0.9108 1 0.2009 ND 0 19:57:21.833 ELN_MA (GBPUSD,D1) 0.7910 1 0.3586 RL 0 19:57:21.833 ELN_MA (GBPUSD,D1) 0.6870 1 0.4813 LD 0 19:57:21.833 ELN_MA (GBPUSD,D1) 0.5967 1 0.5764 OL 0 19:57:21.833 ELN_MA (GBPUSD,D1) 0.5182 1 0.6499 KG 0 19:57:21.833 ELN_MA (GBPUSD,D1) 0.4501 1 0.7065 LO 0 19:57:21.833 ELN_MA (GBPUSD,D1) 0.3909 1 0.7500 JG 0 19:57:21.833 ELN_MA (GBPUSD,D1) 0.3395 1 0.7833 QO 0 19:57:21.833 ELN_MA (GBPUSD,D1) 0.2949 1 0.8088 OF 0 19:57:21.833 ELN_MA (GBPUSD,D1) 0.2561 1 0.8282 CN 0 19:57:21.833 ELN_MA (GBPUSD,D1) 0.2224 1 0.8431 CF 0 19:57:21.833 ELN_MA (GBPUSD,D1) 0.1932 1 0.8544 HN 0 19:57:21.833 ELN_MA (GBPUSD,D1) 0.1678 1 0.8630 LI 0 19:57:21.833 ELN_MA (GBPUSD,D1) 0.1457 1 0.8695 GQ 0 19:57:21.833 ELN_MA (GBPUSD,D1) 0.1266 1 0.8744 LI 0 19:57:21.833 ELN_MA (GBPUSD,D1) 0.1099 2 0.8788 QQ 0 19:57:21.833 ELN_MA (GBPUSD,D1) 0.0955 2 0.8914 PH 0 19:57:21.833 ELN_MA (GBPUSD,D1) 0.0829 2 0.9019 IP 0 19:57:21.833 ELN_MA (GBPUSD,D1) 0.0720 2 0.9098 EH 0 19:57:21.833 ELN_MA (GBPUSD,D1) 0.0625 2 0.9159 RP 0 19:57:21.833 ELN_MA (GBPUSD,D1) 0.0543 2 0.9205 EK 0 19:57:21.833 ELN_MA (GBPUSD,D1) 0.0472 3 0.9325 HS 0 19:57:21.833 ELN_MA (GBPUSD,D1) 0.0410 2 0.9424 NK 0 19:57:21.833 ELN_MA (GBPUSD,D1) 0.0356 2 0.9467 HS 0 19:57:21.833 ELN_MA (GBPUSD,D1) 0.0309 2 0.9500 KJ 0 19:57:21.833 ELN_MA (GBPUSD,D1) 0.0268 2 0.9525 JR 0 19:57:21.833 ELN_MA (GBPUSD,D1) 0.0233 3 0.9556 GJ 0 19:57:21.833 ELN_MA (GBPUSD,D1) 0.0202 3 0.9586 NR 0 19:57:21.833 ELN_MA (GBPUSD,D1) 0.0176 4 0.9610 CM 0 19:57:21.833 ELN_MA (GBPUSD,D1) 0.0153 3 0.9635 CE 0 19:57:21.833 ELN_MA (GBPUSD,D1) 0.0133 4 0.9656 OM 0 19:57:21.833 ELN_MA (GBPUSD,D1) 0.0115 3 0.9677 PE 0 19:57:21.833 ELN_MA (GBPUSD,D1) 0.0100 3 0.9689 QL 0 19:57:21.833 ELN_MA (GBPUSD,D1) 0.0087 5 0.9707 CD 0 19:57:21.833 ELN_MA (GBPUSD,D1) 0.0075 4 0.9732 RL 0 19:57:21.833 ELN_MA (GBPUSD,D1) 0.0066 5 0.9745 ND 0 19:57:21.833 ELN_MA (GBPUSD,D1) 0.0057 5 0.9756 NO 0 19:57:21.833 ELN_MA (GBPUSD,D1) 0.0049 4 0.9767 HG 0 19:57:21.833 ELN_MA (GBPUSD,D1) 0.0043 4 0.9776 IO 0 19:57:21.833 ELN_MA (GBPUSD,D1) 0.0037 5 0.9784 EG 0 19:57:21.833 ELN_MA (GBPUSD,D1) 0.0032 6 0.9793 KN 0 19:57:21.833 ELN_MA (GBPUSD,D1) 0.0028 6 0.9808 DF 0 19:57:21.833 ELN_MA (GBPUSD,D1) 0.0024 8 0.9825 HN 0 19:57:21.833 ELN_MA (GBPUSD,D1) 0.0021 6 0.9840 PF 0 19:57:21.833 ELN_MA (GBPUSD,D1) 0.0018 7 0.9847 OQ 0 19:57:21.833 ELN_MA (GBPUSD,D1) 0.0016 7 0.9855 OI 0 19:57:21.833 ELN_MA (GBPUSD,D1) 0.0014 5 0.9862 DQ 0 19:57:21.833 ELN_MA (GBPUSD,D1) 0.0012 7 0.9867 MI 0 19:57:21.833 ELN_MA (GBPUSD,D1) 0.0010 8 0.9874 KS 0 19:57:22.068 ELN_MA (GBPUSD,D1) OF 0 19:57:22.068 ELN_MA (GBPUSD,D1) Descending lambda path... OL 0 19:57:22.068 ELN_MA (GBPUSD,D1) 1.0487 0 0.0000 RG 0 19:57:22.068 ELN_MA (GBPUSD,D1) 0.9108 1 0.2006 PO 0 19:57:22.068 ELN_MA (GBPUSD,D1) 0.7910 1 0.3583 JG 0 19:57:22.068 ELN_MA (GBPUSD,D1) 0.6870 1 0.4810 RO 0 19:57:22.068 ELN_MA (GBPUSD,D1) 0.5967 1 0.5761 NF 0 19:57:22.068 ELN_MA (GBPUSD,D1) 0.5182 1 0.6495 RN 0 19:57:22.068 ELN_MA (GBPUSD,D1) 0.4501 1 0.7061 OF 0 19:57:22.068 ELN_MA (GBPUSD,D1) 0.3909 1 0.7496 RN 0 19:57:22.068 ELN_MA (GBPUSD,D1) 0.3395 1 0.7829 LI 0 19:57:22.068 ELN_MA (GBPUSD,D1) 0.2949 1 0.8084 NQ 0 19:57:22.068 ELN_MA (GBPUSD,D1) 0.2561 1 0.8279 OI 0 19:57:22.068 ELN_MA (GBPUSD,D1) 0.2224 1 0.8427 JQ 0 19:57:22.068 ELN_MA (GBPUSD,D1) 0.1932 1 0.8540 LH 0 19:57:22.068 ELN_MA (GBPUSD,D1) 0.1678 1 0.8626 QP 0 19:57:22.068 ELN_MA (GBPUSD,D1) 0.1457 1 0.8691 MH 0 19:57:22.068 ELN_MA (GBPUSD,D1) 0.1266 1 0.8741 IP 0 19:57:22.068 ELN_MA (GBPUSD,D1) 0.1099 3 0.8794 NK 0 19:57:22.068 ELN_MA (GBPUSD,D1) 0.0955 2 0.8929 PS 0 19:57:22.068 ELN_MA (GBPUSD,D1) 0.0829 2 0.9029 NK 0 19:57:22.068 ELN_MA (GBPUSD,D1) 0.0720 2 0.9106 RS 0 19:57:22.068 ELN_MA (GBPUSD,D1) 0.0625 2 0.9164 JJ 0 19:57:22.068 ELN_MA (GBPUSD,D1) 0.0543 3 0.9225 MR 0 19:57:22.068 ELN_MA (GBPUSD,D1) 0.0472 3 0.9348 KJ 0 19:57:22.068 ELN_MA (GBPUSD,D1) 0.0410 2 0.9433 MR 0 19:57:22.068 ELN_MA (GBPUSD,D1) 0.0356 2 0.9474 KM 0 19:57:22.068 ELN_MA (GBPUSD,D1) 0.0309 2 0.9506 JE 0 19:57:22.068 ELN_MA (GBPUSD,D1) 0.0268 2 0.9529 FM 0 19:57:22.068 ELN_MA (GBPUSD,D1) 0.0233 3 0.9559 KE 0 19:57:22.068 ELN_MA (GBPUSD,D1) 0.0202 3 0.9589 DL 0 19:57:22.068 ELN_MA (GBPUSD,D1) 0.0176 3 0.9616 CD 0 19:57:22.068 ELN_MA (GBPUSD,D1) 0.0153 3 0.9636 ML 0 19:57:22.068 ELN_MA (GBPUSD,D1) 0.0133 3 0.9663 CD 0 19:57:22.068 ELN_MA (GBPUSD,D1) 0.0115 3 0.9678 KO 0 19:57:22.068 ELN_MA (GBPUSD,D1) 0.0100 4 0.9691 EG 0 19:57:22.068 ELN_MA (GBPUSD,D1) 0.0087 5 0.9719 RO 0 19:57:22.068 ELN_MA (GBPUSD,D1) 0.0075 5 0.9737 KG 0 19:57:22.068 ELN_MA (GBPUSD,D1) 0.0066 4 0.9751 IN 0 19:57:22.068 ELN_MA (GBPUSD,D1) 0.0057 5 0.9763 MF 0 19:57:22.068 ELN_MA (GBPUSD,D1) 0.0049 4 0.9774 FN 0 19:57:22.068 ELN_MA (GBPUSD,D1) 0.0043 4 0.9784 EF 0 19:57:22.068 ELN_MA (GBPUSD,D1) 0.0037 5 0.9792 QQ 0 19:57:22.068 ELN_MA (GBPUSD,D1) 0.0032 6 0.9802 NI 0 19:57:22.068 ELN_MA (GBPUSD,D1) 0.0028 7 0.9818 HQ 0 19:57:22.068 ELN_MA (GBPUSD,D1) 0.0024 7 0.9834 EI 0 19:57:22.068 ELN_MA (GBPUSD,D1) 0.0021 5 0.9847 HP 0 19:57:22.068 ELN_MA (GBPUSD,D1) 0.0018 6 0.9854 KH 0 19:57:22.068 ELN_MA (GBPUSD,D1) 0.0016 7 0.9861 FP 0 19:57:22.068 ELN_MA (GBPUSD,D1) 0.0014 5 0.9866 GH 0 19:57:22.068 ELN_MA (GBPUSD,D1) 0.0012 6 0.9871 PS 0 19:57:22.068 ELN_MA (GBPUSD,D1) 0.0010 7 0.9877 MH 0 19:57:22.318 ELN_MA (GBPUSD,D1) EL 0 19:57:22.318 ELN_MA (GBPUSD,D1) Descending lambda path... CF 0 19:57:22.318 ELN_MA (GBPUSD,D1) 1.0487 1 0.0003 HN 0 19:57:22.318 ELN_MA (GBPUSD,D1) 0.9108 1 0.2020 IF 0 19:57:22.318 ELN_MA (GBPUSD,D1) 0.7910 1 0.3597 QQ 0 19:57:22.318 ELN_MA (GBPUSD,D1) 0.6870 1 0.4824 GI 0 19:57:22.318 ELN_MA (GBPUSD,D1) 0.5967 1 0.5775 LQ 0 19:57:22.318 ELN_MA (GBPUSD,D1) 0.5182 1 0.6510 JI 0 19:57:22.318 ELN_MA (GBPUSD,D1) 0.4501 1 0.7076 OP 0 19:57:22.318 ELN_MA (GBPUSD,D1) 0.3909 1 0.7511 NH 0 19:57:22.318 ELN_MA (GBPUSD,D1) 0.3395 1 0.7845 MP 0 19:57:22.318 ELN_MA (GBPUSD,D1) 0.2949 1 0.8100 IH 0 19:57:22.318 ELN_MA (GBPUSD,D1) 0.2561 1 0.8294 CS 0 19:57:22.318 ELN_MA (GBPUSD,D1) 0.2224 1 0.8443 QK 0 19:57:22.318 ELN_MA (GBPUSD,D1) 0.1932 1 0.8556 IS 0 19:57:22.318 ELN_MA (GBPUSD,D1) 0.1678 1 0.8641 QK 0 19:57:22.318 ELN_MA (GBPUSD,D1) 0.1457 1 0.8707 ER 0 19:57:22.318 ELN_MA (GBPUSD,D1) 0.1266 1 0.8756 QJ 0 19:57:22.318 ELN_MA (GBPUSD,D1) 0.1099 2 0.8805 GR 0 19:57:22.318 ELN_MA (GBPUSD,D1) 0.0955 2 0.8928 LJ 0 19:57:22.318 ELN_MA (GBPUSD,D1) 0.0829 2 0.9032 FE 0 19:57:22.318 ELN_MA (GBPUSD,D1) 0.0720 2 0.9111 HM 0 19:57:22.318 ELN_MA (GBPUSD,D1) 0.0625 2 0.9171 LE 0 19:57:22.318 ELN_MA (GBPUSD,D1) 0.0543 2 0.9217 OM 0 19:57:22.318 ELN_MA (GBPUSD,D1) 0.0472 3 0.9315 GD 0 19:57:22.318 ELN_MA (GBPUSD,D1) 0.0410 3 0.9421 EL 0 19:57:22.318 ELN_MA (GBPUSD,D1) 0.0356 2 0.9472 HD 0 19:57:22.318 ELN_MA (GBPUSD,D1) 0.0309 2 0.9505 DL 0 19:57:22.318 ELN_MA (GBPUSD,D1) 0.0268 2 0.9530 OG 0 19:57:22.318 ELN_MA (GBPUSD,D1) 0.0233 3 0.9558 JO 0 19:57:22.318 ELN_MA (GBPUSD,D1) 0.0202 3 0.9588 OG 0 19:57:22.318 ELN_MA (GBPUSD,D1) 0.0176 4 0.9612 CO 0 19:57:22.318 ELN_MA (GBPUSD,D1) 0.0153 3 0.9638 MF 0 19:57:22.318 ELN_MA (GBPUSD,D1) 0.0133 4 0.9659 LN 0 19:57:22.318 ELN_MA (GBPUSD,D1) 0.0115 3 0.9680 FF 0 19:57:22.318 ELN_MA (GBPUSD,D1) 0.0100 4 0.9694 PN 0 19:57:22.318 ELN_MA (GBPUSD,D1) 0.0087 5 0.9709 RI 0 19:57:22.318 ELN_MA (GBPUSD,D1) 0.0075 4 0.9738 JQ 0 19:57:22.318 ELN_MA (GBPUSD,D1) 0.0066 5 0.9751 KI 0 19:57:22.318 ELN_MA (GBPUSD,D1) 0.0057 5 0.9763 GQ 0 19:57:22.318 ELN_MA (GBPUSD,D1) 0.0049 4 0.9774 MH 0 19:57:22.318 ELN_MA (GBPUSD,D1) 0.0043 4 0.9783 QP 0 19:57:22.318 ELN_MA (GBPUSD,D1) 0.0037 4 0.9791 DH 0 19:57:22.318 ELN_MA (GBPUSD,D1) 0.0032 5 0.9800 QP 0 19:57:22.318 ELN_MA (GBPUSD,D1) 0.0028 6 0.9812 LK 0 19:57:22.318 ELN_MA (GBPUSD,D1) 0.0024 7 0.9827 GS 0 19:57:22.318 ELN_MA (GBPUSD,D1) 0.0021 8 0.9842 OK 0 19:57:22.318 ELN_MA (GBPUSD,D1) 0.0018 6 0.9853 IS 0 19:57:22.318 ELN_MA (GBPUSD,D1) 0.0016 7 0.9861 DJ 0 19:57:22.318 ELN_MA (GBPUSD,D1) 0.0014 6 0.9869 RR 0 19:57:22.318 ELN_MA (GBPUSD,D1) 0.0012 6 0.9874 PJ 0 19:57:22.318 ELN_MA (GBPUSD,D1) 0.0010 7 0.9879 DQ 0 19:57:22.568 ELN_MA (GBPUSD,D1) PK 0 19:57:22.568 ELN_MA (GBPUSD,D1) Descending lambda path... KQ 0 19:57:22.568 ELN_MA (GBPUSD,D1) 1.0487 1 0.0004 FI 0 19:57:22.568 ELN_MA (GBPUSD,D1) 0.9108 1 0.2021 IP 0 19:57:22.568 ELN_MA (GBPUSD,D1) 0.7910 1 0.3598 KH 0 19:57:22.568 ELN_MA (GBPUSD,D1) 0.6870 1 0.4825 LP 0 19:57:22.568 ELN_MA (GBPUSD,D1) 0.5967 1 0.5777 RH 0 19:57:22.568 ELN_MA (GBPUSD,D1) 0.5182 1 0.6511 IS 0 19:57:22.568 ELN_MA (GBPUSD,D1) 0.4501 1 0.7078 KK 0 19:57:22.568 ELN_MA (GBPUSD,D1) 0.3909 1 0.7512 JS 0 19:57:22.568 ELN_MA (GBPUSD,D1) 0.3395 1 0.7846 OK 0 19:57:22.568 ELN_MA (GBPUSD,D1) 0.2949 1 0.8101 KR 0 19:57:22.568 ELN_MA (GBPUSD,D1) 0.2561 1 0.8295 CJ 0 19:57:22.568 ELN_MA (GBPUSD,D1) 0.2224 1 0.8444 CR 0 19:57:22.568 ELN_MA (GBPUSD,D1) 0.1932 1 0.8557 FJ 0 19:57:22.568 ELN_MA (GBPUSD,D1) 0.1678 1 0.8643 QE 0 19:57:22.568 ELN_MA (GBPUSD,D1) 0.1457 1 0.8708 GM 0 19:57:22.568 ELN_MA (GBPUSD,D1) 0.1266 1 0.8757 OE 0 19:57:22.568 ELN_MA (GBPUSD,D1) 0.1099 2 0.8808 NM 0 19:57:22.568 ELN_MA (GBPUSD,D1) 0.0955 2 0.8931 CD 0 19:57:22.568 ELN_MA (GBPUSD,D1) 0.0829 2 0.9034 IL 0 19:57:22.568 ELN_MA (GBPUSD,D1) 0.0720 2 0.9113 KD 0 19:57:22.568 ELN_MA (GBPUSD,D1) 0.0625 2 0.9173 DL 0 19:57:22.568 ELN_MA (GBPUSD,D1) 0.0543 2 0.9218 RG 0 19:57:22.568 ELN_MA (GBPUSD,D1) 0.0472 3 0.9319 IO 0 19:57:22.568 ELN_MA (GBPUSD,D1) 0.0410 3 0.9424 NG 0 19:57:22.568 ELN_MA (GBPUSD,D1) 0.0356 2 0.9474 CO 0 19:57:22.568 ELN_MA (GBPUSD,D1) 0.0309 2 0.9507 OF 0 19:57:22.568 ELN_MA (GBPUSD,D1) 0.0268 2 0.9532 CN 0 19:57:22.568 ELN_MA (GBPUSD,D1) 0.0233 3 0.9560 DF 0 19:57:22.568 ELN_MA (GBPUSD,D1) 0.0202 3 0.9590 PN 0 19:57:22.568 ELN_MA (GBPUSD,D1) 0.0176 3 0.9613 QI 0 19:57:22.568 ELN_MA (GBPUSD,D1) 0.0153 3 0.9639 PQ 0 19:57:22.568 ELN_MA (GBPUSD,D1) 0.0133 4 0.9659 JI 0 19:57:22.568 ELN_MA (GBPUSD,D1) 0.0115 3 0.9681 GQ 0 19:57:22.568 ELN_MA (GBPUSD,D1) 0.0100 4 0.9694 LH 0 19:57:22.568 ELN_MA (GBPUSD,D1) 0.0087 6 0.9710 LP 0 19:57:22.568 ELN_MA (GBPUSD,D1) 0.0075 5 0.9738 LH 0 19:57:22.568 ELN_MA (GBPUSD,D1) 0.0066 4 0.9751 QP 0 19:57:22.568 ELN_MA (GBPUSD,D1) 0.0057 4 0.9763 MK 0 19:57:22.568 ELN_MA (GBPUSD,D1) 0.0049 5 0.9774 OS 0 19:57:22.568 ELN_MA (GBPUSD,D1) 0.0043 5 0.9783 CK 0 19:57:22.568 ELN_MA (GBPUSD,D1) 0.0037 5 0.9791 JS 0 19:57:22.568 ELN_MA (GBPUSD,D1) 0.0032 5 0.9801 DJ 0 19:57:22.568 ELN_MA (GBPUSD,D1) 0.0028 7 0.9813 DR 0 19:57:22.568 ELN_MA (GBPUSD,D1) 0.0024 7 0.9828 HJ 0 19:57:22.568 ELN_MA (GBPUSD,D1) 0.0021 7 0.9843 NR 0 19:57:22.568 ELN_MA (GBPUSD,D1) 0.0018 6 0.9853 KM 0 19:57:22.568 ELN_MA (GBPUSD,D1) 0.0016 7 0.9860 NE 0 19:57:22.568 ELN_MA (GBPUSD,D1) 0.0014 5 0.9867 IM 0 19:57:22.568 ELN_MA (GBPUSD,D1) 0.0012 6 0.9872 GE 0 19:57:22.568 ELN_MA (GBPUSD,D1) 0.0010 8 0.9878 JO 0 19:57:22.740 ELN_MA (GBPUSD,D1) RQ 0 19:57:22.740 ELN_MA (GBPUSD,D1) Descending lambda path... PK 0 19:57:22.740 ELN_MA (GBPUSD,D1) 1.0487 1 0.0003 DS 0 19:57:22.740 ELN_MA (GBPUSD,D1) 0.9108 1 0.2021 GK 0 19:57:22.740 ELN_MA (GBPUSD,D1) 0.7910 1 0.3598 MS 0 19:57:22.740 ELN_MA (GBPUSD,D1) 0.6870 1 0.4825 MJ 0 19:57:22.740 ELN_MA (GBPUSD,D1) 0.5967 1 0.5776 PR 0 19:57:22.740 ELN_MA (GBPUSD,D1) 0.5182 1 0.6511 NJ 0 19:57:22.740 ELN_MA (GBPUSD,D1) 0.4501 1 0.7077 MR 0 19:57:22.740 ELN_MA (GBPUSD,D1) 0.3909 1 0.7512 IM 0 19:57:22.740 ELN_MA (GBPUSD,D1) 0.3395 1 0.7845 RE 0 19:57:22.740 ELN_MA (GBPUSD,D1) 0.2949 1 0.8100 MM 0 19:57:22.740 ELN_MA (GBPUSD,D1) 0.2561 1 0.8295 HE 0 19:57:22.740 ELN_MA (GBPUSD,D1) 0.2224 1 0.8443 FL 0 19:57:22.740 ELN_MA (GBPUSD,D1) 0.1932 1 0.8556 CD 0 19:57:22.740 ELN_MA (GBPUSD,D1) 0.1678 1 0.8642 OL 0 19:57:22.740 ELN_MA (GBPUSD,D1) 0.1457 1 0.8708 ID 0 19:57:22.740 ELN_MA (GBPUSD,D1) 0.1266 1 0.8757 DO 0 19:57:22.740 ELN_MA (GBPUSD,D1) 0.1099 2 0.8807 DG 0 19:57:22.740 ELN_MA (GBPUSD,D1) 0.0955 2 0.8928 GO 0 19:57:22.740 ELN_MA (GBPUSD,D1) 0.0829 2 0.9032 HG 0 19:57:22.740 ELN_MA (GBPUSD,D1) 0.0720 2 0.9112 NN 0 19:57:22.740 ELN_MA (GBPUSD,D1) 0.0625 2 0.9172 FF 0 19:57:22.740 ELN_MA (GBPUSD,D1) 0.0543 2 0.9218 JN 0 19:57:22.740 ELN_MA (GBPUSD,D1) 0.0472 3 0.9313 MF 0 19:57:22.740 ELN_MA (GBPUSD,D1) 0.0410 3 0.9419 RQ 0 19:57:22.740 ELN_MA (GBPUSD,D1) 0.0356 2 0.9472 CI 0 19:57:22.740 ELN_MA (GBPUSD,D1) 0.0309 2 0.9505 PQ 0 19:57:22.740 ELN_MA (GBPUSD,D1) 0.0268 2 0.9531 LI 0 19:57:22.740 ELN_MA (GBPUSD,D1) 0.0233 3 0.9558 PP 0 19:57:22.740 ELN_MA (GBPUSD,D1) 0.0202 4 0.9588 QH 0 19:57:22.740 ELN_MA (GBPUSD,D1) 0.0176 3 0.9612 PP 0 19:57:22.740 ELN_MA (GBPUSD,D1) 0.0153 3 0.9638 DH 0 19:57:22.740 ELN_MA (GBPUSD,D1) 0.0133 4 0.9657 GS 0 19:57:22.740 ELN_MA (GBPUSD,D1) 0.0115 3 0.9680 IK 0 19:57:22.740 ELN_MA (GBPUSD,D1) 0.0100 4 0.9694 DS 0 19:57:22.740 ELN_MA (GBPUSD,D1) 0.0087 5 0.9708 GK 0 19:57:22.740 ELN_MA (GBPUSD,D1) 0.0075 5 0.9737 MR 0 19:57:22.740 ELN_MA (GBPUSD,D1) 0.0066 4 0.9750 PJ 0 19:57:22.740 ELN_MA (GBPUSD,D1) 0.0057 4 0.9762 RR 0 19:57:22.740 ELN_MA (GBPUSD,D1) 0.0049 5 0.9773 RJ 0 19:57:22.740 ELN_MA (GBPUSD,D1) 0.0043 5 0.9782 FE 0 19:57:22.740 ELN_MA (GBPUSD,D1) 0.0037 5 0.9790 GM 0 19:57:22.740 ELN_MA (GBPUSD,D1) 0.0032 5 0.9800 FE 0 19:57:22.740 ELN_MA (GBPUSD,D1) 0.0028 6 0.9812 OM 0 19:57:22.740 ELN_MA (GBPUSD,D1) 0.0024 7 0.9827 ID 0 19:57:22.740 ELN_MA (GBPUSD,D1) 0.0021 7 0.9842 KL 0 19:57:22.740 ELN_MA (GBPUSD,D1) 0.0018 6 0.9852 ND 0 19:57:22.740 ELN_MA (GBPUSD,D1) 0.0016 6 0.9860 LL 0 19:57:22.740 ELN_MA (GBPUSD,D1) 0.0014 5 0.9867 GG 0 19:57:22.740 ELN_MA (GBPUSD,D1) 0.0012 6 0.9872 IO 0 19:57:22.740 ELN_MA (GBPUSD,D1) 0.0010 7 0.9877 KD 0 19:57:23.052 ELN_MA (GBPUSD,D1) OH 0 19:57:23.052 ELN_MA (GBPUSD,D1) Descending lambda path... RR 0 19:57:23.052 ELN_MA (GBPUSD,D1) 1.0487 1 0.0002 DJ 0 19:57:23.052 ELN_MA (GBPUSD,D1) 0.9108 1 0.2019 LR 0 19:57:23.052 ELN_MA (GBPUSD,D1) 0.7910 1 0.3596 JM 0 19:57:23.052 ELN_MA (GBPUSD,D1) 0.6870 1 0.4823 ME 0 19:57:23.052 ELN_MA (GBPUSD,D1) 0.5967 1 0.5775 RM 0 19:57:23.052 ELN_MA (GBPUSD,D1) 0.5182 1 0.6509 LE 0 19:57:23.052 ELN_MA (GBPUSD,D1) 0.4501 1 0.7076 FL 0 19:57:23.052 ELN_MA (GBPUSD,D1) 0.3909 1 0.7510 GD 0 19:57:23.052 ELN_MA (GBPUSD,D1) 0.3395 1 0.7844 HL 0 19:57:23.052 ELN_MA (GBPUSD,D1) 0.2949 1 0.8099 RD 0 19:57:23.052 ELN_MA (GBPUSD,D1) 0.2561 1 0.8293 RO 0 19:57:23.052 ELN_MA (GBPUSD,D1) 0.2224 1 0.8442 FG 0 19:57:23.052 ELN_MA (GBPUSD,D1) 0.1932 1 0.8555 KO 0 19:57:23.052 ELN_MA (GBPUSD,D1) 0.1678 1 0.8641 DG 0 19:57:23.052 ELN_MA (GBPUSD,D1) 0.1457 1 0.8706 RN 0 19:57:23.052 ELN_MA (GBPUSD,D1) 0.1266 1 0.8755 DF 0 19:57:23.052 ELN_MA (GBPUSD,D1) 0.1099 2 0.8804 HN 0 19:57:23.052 ELN_MA (GBPUSD,D1) 0.0955 2 0.8927 GF 0 19:57:23.052 ELN_MA (GBPUSD,D1) 0.0829 2 0.9031 OQ 0 19:57:23.052 ELN_MA (GBPUSD,D1) 0.0720 2 0.9110 MI 0 19:57:23.052 ELN_MA (GBPUSD,D1) 0.0625 2 0.9170 IQ 0 19:57:23.052 ELN_MA (GBPUSD,D1) 0.0543 2 0.9216 DI 0 19:57:23.052 ELN_MA (GBPUSD,D1) 0.0472 3 0.9316 LP 0 19:57:23.052 ELN_MA (GBPUSD,D1) 0.0410 3 0.9422 OH 0 19:57:23.052 ELN_MA (GBPUSD,D1) 0.0356 2 0.9472 NP 0 19:57:23.052 ELN_MA (GBPUSD,D1) 0.0309 2 0.9505 RH 0 19:57:23.052 ELN_MA (GBPUSD,D1) 0.0268 2 0.9530 ES 0 19:57:23.052 ELN_MA (GBPUSD,D1) 0.0233 3 0.9558 LK 0 19:57:23.052 ELN_MA (GBPUSD,D1) 0.0202 3 0.9588 ES 0 19:57:23.052 ELN_MA (GBPUSD,D1) 0.0176 4 0.9612 DK 0 19:57:23.052 ELN_MA (GBPUSD,D1) 0.0153 3 0.9637 HR 0 19:57:23.052 ELN_MA (GBPUSD,D1) 0.0133 4 0.9658 JJ 0 19:57:23.052 ELN_MA (GBPUSD,D1) 0.0115 3 0.9680 MR 0 19:57:23.052 ELN_MA (GBPUSD,D1) 0.0100 4 0.9693 CJ 0 19:57:23.052 ELN_MA (GBPUSD,D1) 0.0087 6 0.9709 RE 0 19:57:23.052 ELN_MA (GBPUSD,D1) 0.0075 5 0.9737 LM 0 19:57:23.052 ELN_MA (GBPUSD,D1) 0.0066 4 0.9750 IE 0 19:57:23.052 ELN_MA (GBPUSD,D1) 0.0057 4 0.9762 OM 0 19:57:23.052 ELN_MA (GBPUSD,D1) 0.0049 5 0.9773 GD 0 19:57:23.052 ELN_MA (GBPUSD,D1) 0.0043 5 0.9782 CL 0 19:57:23.052 ELN_MA (GBPUSD,D1) 0.0037 5 0.9790 CD 0 19:57:23.052 ELN_MA (GBPUSD,D1) 0.0032 5 0.9799 DL 0 19:57:23.052 ELN_MA (GBPUSD,D1) 0.0028 7 0.9812 JG 0 19:57:23.052 ELN_MA (GBPUSD,D1) 0.0024 7 0.9827 HO 0 19:57:23.052 ELN_MA (GBPUSD,D1) 0.0021 6 0.9843 CG 0 19:57:23.052 ELN_MA (GBPUSD,D1) 0.0018 5 0.9852 LO 0 19:57:23.052 ELN_MA (GBPUSD,D1) 0.0016 7 0.9860 EF 0 19:57:23.052 ELN_MA (GBPUSD,D1) 0.0014 5 0.9867 JN 0 19:57:23.052 ELN_MA (GBPUSD,D1) 0.0012 6 0.9872 EF 0 19:57:23.052 ELN_MA (GBPUSD,D1) 0.0010 8 0.9877 KM 0 19:57:23.302 ELN_MA (GBPUSD,D1) CG 0 19:57:23.302 ELN_MA (GBPUSD,D1) Descending lambda path... EM 0 19:57:23.302 ELN_MA (GBPUSD,D1) 1.0487 1 0.0003 ID 0 19:57:23.302 ELN_MA (GBPUSD,D1) 0.9108 1 0.2021 NL 0 19:57:23.302 ELN_MA (GBPUSD,D1) 0.7910 1 0.3598 PD 0 19:57:23.302 ELN_MA (GBPUSD,D1) 0.6870 1 0.4825 HL 0 19:57:23.302 ELN_MA (GBPUSD,D1) 0.5967 1 0.5776 MG 0 19:57:23.302 ELN_MA (GBPUSD,D1) 0.5182 1 0.6511 GO 0 19:57:23.302 ELN_MA (GBPUSD,D1) 0.4501 1 0.7077 PG 0 19:57:23.302 ELN_MA (GBPUSD,D1) 0.3909 1 0.7512 MO 0 19:57:23.302 ELN_MA (GBPUSD,D1) 0.3395 1 0.7846 KF 0 19:57:23.302 ELN_MA (GBPUSD,D1) 0.2949 1 0.8100 HN 0 19:57:23.302 ELN_MA (GBPUSD,D1) 0.2561 1 0.8295 HF 0 19:57:23.302 ELN_MA (GBPUSD,D1) 0.2224 1 0.8444 PN 0 19:57:23.302 ELN_MA (GBPUSD,D1) 0.1932 1 0.8557 JI 0 19:57:23.302 ELN_MA (GBPUSD,D1) 0.1678 1 0.8642 FQ 0 19:57:23.302 ELN_MA (GBPUSD,D1) 0.1457 1 0.8708 DI 0 19:57:23.302 ELN_MA (GBPUSD,D1) 0.1266 1 0.8757 PQ 0 19:57:23.302 ELN_MA (GBPUSD,D1) 0.1099 2 0.8804 LH 0 19:57:23.302 ELN_MA (GBPUSD,D1) 0.0955 2 0.8927 KP 0 19:57:23.302 ELN_MA (GBPUSD,D1) 0.0829 2 0.9031 DH 0 19:57:23.302 ELN_MA (GBPUSD,D1) 0.0720 2 0.9111 JP 0 19:57:23.302 ELN_MA (GBPUSD,D1) 0.0625 2 0.9171 NK 0 19:57:23.302 ELN_MA (GBPUSD,D1) 0.0543 2 0.9217 PS 0 19:57:23.302 ELN_MA (GBPUSD,D1) 0.0472 3 0.9316 HK 0 19:57:23.302 ELN_MA (GBPUSD,D1) 0.0410 3 0.9422 CS 0 19:57:23.302 ELN_MA (GBPUSD,D1) 0.0356 2 0.9472 JJ 0 19:57:23.302 ELN_MA (GBPUSD,D1) 0.0309 2 0.9505 ER 0 19:57:23.302 ELN_MA (GBPUSD,D1) 0.0268 2 0.9531 RJ 0 19:57:23.302 ELN_MA (GBPUSD,D1) 0.0233 3 0.9559 GR 0 19:57:23.302 ELN_MA (GBPUSD,D1) 0.0202 3 0.9589 LM 0 19:57:23.302 ELN_MA (GBPUSD,D1) 0.0176 3 0.9612 EE 0 19:57:23.302 ELN_MA (GBPUSD,D1) 0.0153 3 0.9638 LM 0 19:57:23.302 ELN_MA (GBPUSD,D1) 0.0133 4 0.9658 NE 0 19:57:23.302 ELN_MA (GBPUSD,D1) 0.0115 3 0.9680 IL 0 19:57:23.302 ELN_MA (GBPUSD,D1) 0.0100 4 0.9693 OD 0 19:57:23.302 ELN_MA (GBPUSD,D1) 0.0087 6 0.9709 EL 0 19:57:23.302 ELN_MA (GBPUSD,D1) 0.0075 4 0.9737 GD 0 19:57:23.302 ELN_MA (GBPUSD,D1) 0.0066 4 0.9751 NO 0 19:57:23.302 ELN_MA (GBPUSD,D1) 0.0057 4 0.9763 CG 0 19:57:23.302 ELN_MA (GBPUSD,D1) 0.0049 5 0.9773 KO 0 19:57:23.302 ELN_MA (GBPUSD,D1) 0.0043 5 0.9782 PG 0 19:57:23.302 ELN_MA (GBPUSD,D1) 0.0037 4 0.9790 FN 0 19:57:23.302 ELN_MA (GBPUSD,D1) 0.0032 5 0.9800 PF 0 19:57:23.302 ELN_MA (GBPUSD,D1) 0.0028 7 0.9812 NN 0 19:57:23.302 ELN_MA (GBPUSD,D1) 0.0024 7 0.9827 LF 0 19:57:23.302 ELN_MA (GBPUSD,D1) 0.0021 7 0.9842 RQ 0 19:57:23.302 ELN_MA (GBPUSD,D1) 0.0018 6 0.9852 HI 0 19:57:23.302 ELN_MA (GBPUSD,D1) 0.0016 7 0.9860 PQ 0 19:57:23.302 ELN_MA (GBPUSD,D1) 0.0014 6 0.9867 NI 0 19:57:23.302 ELN_MA (GBPUSD,D1) 0.0012 6 0.9872 QP 0 19:57:23.302 ELN_MA (GBPUSD,D1) 0.0010 8 0.9877 EK 0 19:57:23.537 ELN_MA (GBPUSD,D1) QM 0 19:57:23.537 ELN_MA (GBPUSD,D1) Descending lambda path... PG 0 19:57:23.537 ELN_MA (GBPUSD,D1) 1.0487 1 0.0002 NO 0 19:57:23.537 ELN_MA (GBPUSD,D1) 0.9108 1 0.2019 NG 0 19:57:23.537 ELN_MA (GBPUSD,D1) 0.7910 1 0.3596 PO 0 19:57:23.537 ELN_MA (GBPUSD,D1) 0.6870 1 0.4823 KF 0 19:57:23.537 ELN_MA (GBPUSD,D1) 0.5967 1 0.5775 HN 0 19:57:23.537 ELN_MA (GBPUSD,D1) 0.5182 1 0.6509 KF 0 19:57:23.537 ELN_MA (GBPUSD,D1) 0.4501 1 0.7075 LN 0 19:57:23.537 ELN_MA (GBPUSD,D1) 0.3909 1 0.7510 II 0 19:57:23.537 ELN_MA (GBPUSD,D1) 0.3395 1 0.7844 RQ 0 19:57:23.537 ELN_MA (GBPUSD,D1) 0.2949 1 0.8099 PI 0 19:57:23.537 ELN_MA (GBPUSD,D1) 0.2561 1 0.8293 HQ 0 19:57:23.537 ELN_MA (GBPUSD,D1) 0.2224 1 0.8442 DH 0 19:57:23.537 ELN_MA (GBPUSD,D1) 0.1932 1 0.8555 FP 0 19:57:23.537 ELN_MA (GBPUSD,D1) 0.1678 1 0.8640 FH 0 19:57:23.537 ELN_MA (GBPUSD,D1) 0.1457 1 0.8706 HP 0 19:57:23.537 ELN_MA (GBPUSD,D1) 0.1266 1 0.8755 FK 0 19:57:23.537 ELN_MA (GBPUSD,D1) 0.1099 2 0.8804 RS 0 19:57:23.537 ELN_MA (GBPUSD,D1) 0.0955 2 0.8927 IK 0 19:57:23.537 ELN_MA (GBPUSD,D1) 0.0829 2 0.9031 IS 0 19:57:23.537 ELN_MA (GBPUSD,D1) 0.0720 2 0.9110 KJ 0 19:57:23.537 ELN_MA (GBPUSD,D1) 0.0625 2 0.9170 OR 0 19:57:23.537 ELN_MA (GBPUSD,D1) 0.0543 2 0.9216 FJ 0 19:57:23.537 ELN_MA (GBPUSD,D1) 0.0472 3 0.9316 CR 0 19:57:23.537 ELN_MA (GBPUSD,D1) 0.0410 3 0.9421 QM 0 19:57:23.537 ELN_MA (GBPUSD,D1) 0.0356 2 0.9472 DE 0 19:57:23.537 ELN_MA (GBPUSD,D1) 0.0309 2 0.9505 PM 0 19:57:23.537 ELN_MA (GBPUSD,D1) 0.0268 2 0.9530 KE 0 19:57:23.537 ELN_MA (GBPUSD,D1) 0.0233 3 0.9558 NL 0 19:57:23.537 ELN_MA (GBPUSD,D1) 0.0202 3 0.9588 KD 0 19:57:23.537 ELN_MA (GBPUSD,D1) 0.0176 4 0.9612 FL 0 19:57:23.537 ELN_MA (GBPUSD,D1) 0.0153 3 0.9637 RD 0 19:57:23.537 ELN_MA (GBPUSD,D1) 0.0133 4 0.9658 HO 0 19:57:23.537 ELN_MA (GBPUSD,D1) 0.0115 3 0.9680 CG 0 19:57:23.537 ELN_MA (GBPUSD,D1) 0.0100 4 0.9693 EO 0 19:57:23.537 ELN_MA (GBPUSD,D1) 0.0087 6 0.9709 HG 0 19:57:23.537 ELN_MA (GBPUSD,D1) 0.0075 5 0.9737 NN 0 19:57:23.537 ELN_MA (GBPUSD,D1) 0.0066 4 0.9750 OF 0 19:57:23.537 ELN_MA (GBPUSD,D1) 0.0057 4 0.9762 QN 0 19:57:23.537 ELN_MA (GBPUSD,D1) 0.0049 5 0.9773 QF 0 19:57:23.537 ELN_MA (GBPUSD,D1) 0.0043 5 0.9782 EQ 0 19:57:23.537 ELN_MA (GBPUSD,D1) 0.0037 5 0.9790 HI 0 19:57:23.537 ELN_MA (GBPUSD,D1) 0.0032 5 0.9800 FQ 0 19:57:23.537 ELN_MA (GBPUSD,D1) 0.0028 7 0.9812 PI 0 19:57:23.537 ELN_MA (GBPUSD,D1) 0.0024 7 0.9827 JP 0 19:57:23.537 ELN_MA (GBPUSD,D1) 0.0021 6 0.9843 MH 0 19:57:23.537 ELN_MA (GBPUSD,D1) 0.0018 5 0.9852 MP 0 19:57:23.537 ELN_MA (GBPUSD,D1) 0.0016 6 0.9860 KH 0 19:57:23.537 ELN_MA (GBPUSD,D1) 0.0014 5 0.9867 HS 0 19:57:23.537 ELN_MA (GBPUSD,D1) 0.0012 6 0.9872 KK 0 19:57:23.537 ELN_MA (GBPUSD,D1) 0.0010 8 0.9877 PP 0 19:57:23.880 ELN_MA (GBPUSD,D1) HD 0 19:57:23.880 ELN_MA (GBPUSD,D1) Descending lambda path... GN 0 19:57:23.880 ELN_MA (GBPUSD,D1) 1.0487 1 0.0000 DF 0 19:57:23.880 ELN_MA (GBPUSD,D1) 0.9108 1 0.2018 FQ 0 19:57:23.880 ELN_MA (GBPUSD,D1) 0.7910 1 0.3595 JI 0 19:57:23.880 ELN_MA (GBPUSD,D1) 0.6870 1 0.4822 HQ 0 19:57:23.880 ELN_MA (GBPUSD,D1) 0.5967 1 0.5773 RI 0 19:57:23.880 ELN_MA (GBPUSD,D1) 0.5182 1 0.6508 EP 0 19:57:23.880 ELN_MA (GBPUSD,D1) 0.4501 1 0.7074 MH 0 19:57:23.880 ELN_MA (GBPUSD,D1) 0.3909 1 0.7509 NP 0 19:57:23.880 ELN_MA (GBPUSD,D1) 0.3395 1 0.7842 MH 0 19:57:23.880 ELN_MA (GBPUSD,D1) 0.2949 1 0.8097 JS 0 19:57:23.880 ELN_MA (GBPUSD,D1) 0.2561 1 0.8292 OK 0 19:57:23.880 ELN_MA (GBPUSD,D1) 0.2224 1 0.8440 OS 0 19:57:23.880 ELN_MA (GBPUSD,D1) 0.1932 1 0.8553 IK 0 19:57:23.880 ELN_MA (GBPUSD,D1) 0.1678 1 0.8639 MR 0 19:57:23.880 ELN_MA (GBPUSD,D1) 0.1457 1 0.8704 RJ 0 19:57:23.880 ELN_MA (GBPUSD,D1) 0.1266 1 0.8754 KR 0 19:57:23.880 ELN_MA (GBPUSD,D1) 0.1099 2 0.8804 NJ 0 19:57:23.880 ELN_MA (GBPUSD,D1) 0.0955 2 0.8928 PE 0 19:57:23.880 ELN_MA (GBPUSD,D1) 0.0829 2 0.9031 PM 0 19:57:23.880 ELN_MA (GBPUSD,D1) 0.0720 2 0.9110 FE 0 19:57:23.880 ELN_MA (GBPUSD,D1) 0.0625 2 0.9170 GM 0 19:57:23.880 ELN_MA (GBPUSD,D1) 0.0543 2 0.9215 ID 0 19:57:23.880 ELN_MA (GBPUSD,D1) 0.0472 3 0.9318 LL 0 19:57:23.880 ELN_MA (GBPUSD,D1) 0.0410 3 0.9423 HD 0 19:57:23.880 ELN_MA (GBPUSD,D1) 0.0356 2 0.9472 ML 0 19:57:23.880 ELN_MA (GBPUSD,D1) 0.0309 2 0.9505 IG 0 19:57:23.880 ELN_MA (GBPUSD,D1) 0.0268 2 0.9530 FO 0 19:57:23.880 ELN_MA (GBPUSD,D1) 0.0233 3 0.9558 CG 0 19:57:23.880 ELN_MA (GBPUSD,D1) 0.0202 3 0.9588 FO 0 19:57:23.880 ELN_MA (GBPUSD,D1) 0.0176 4 0.9612 KF 0 19:57:23.880 ELN_MA (GBPUSD,D1) 0.0153 3 0.9637 HN 0 19:57:23.880 ELN_MA (GBPUSD,D1) 0.0133 4 0.9659 KF 0 19:57:23.880 ELN_MA (GBPUSD,D1) 0.0115 3 0.9679 NN 0 19:57:23.880 ELN_MA (GBPUSD,D1) 0.0100 4 0.9693 DI 0 19:57:23.880 ELN_MA (GBPUSD,D1) 0.0087 6 0.9710 QQ 0 19:57:23.880 ELN_MA (GBPUSD,D1) 0.0075 5 0.9737 CI 0 19:57:23.880 ELN_MA (GBPUSD,D1) 0.0066 4 0.9750 JQ 0 19:57:23.880 ELN_MA (GBPUSD,D1) 0.0057 4 0.9762 HH 0 19:57:23.880 ELN_MA (GBPUSD,D1) 0.0049 5 0.9773 HP 0 19:57:23.880 ELN_MA (GBPUSD,D1) 0.0043 5 0.9782 LH 0 19:57:23.880 ELN_MA (GBPUSD,D1) 0.0037 5 0.9790 DP 0 19:57:23.880 ELN_MA (GBPUSD,D1) 0.0032 5 0.9799 KK 0 19:57:23.880 ELN_MA (GBPUSD,D1) 0.0028 7 0.9812 LS 0 19:57:23.880 ELN_MA (GBPUSD,D1) 0.0024 7 0.9828 OK 0 19:57:23.880 ELN_MA (GBPUSD,D1) 0.0021 6 0.9843 DS 0 19:57:23.880 ELN_MA (GBPUSD,D1) 0.0018 5 0.9852 DJ 0 19:57:23.880 ELN_MA (GBPUSD,D1) 0.0016 6 0.9860 ER 0 19:57:23.880 ELN_MA (GBPUSD,D1) 0.0014 5 0.9866 RJ 0 19:57:23.880 ELN_MA (GBPUSD,D1) 0.0012 7 0.9872 OR 0 19:57:23.880 ELN_MA (GBPUSD,D1) 0.0010 7 0.9877 EN 0 19:57:24.130 ELN_MA (GBPUSD,D1) IS 0 19:57:24.130 ELN_MA (GBPUSD,D1) Descending lambda path... EI 0 19:57:24.130 ELN_MA (GBPUSD,D1) 1.0487 1 0.0005 EP 0 19:57:24.130 ELN_MA (GBPUSD,D1) 0.9108 1 0.2023 RH 0 19:57:24.130 ELN_MA (GBPUSD,D1) 0.7910 1 0.3600 LP 0 19:57:24.130 ELN_MA (GBPUSD,D1) 0.6870 1 0.4827 PH 0 19:57:24.130 ELN_MA (GBPUSD,D1) 0.5967 1 0.5778 QS 0 19:57:24.130 ELN_MA (GBPUSD,D1) 0.5182 1 0.6513 OK 0 19:57:24.130 ELN_MA (GBPUSD,D1) 0.4501 1 0.7079 PS 0 19:57:24.130 ELN_MA (GBPUSD,D1) 0.3909 1 0.7514 PK 0 19:57:24.130 ELN_MA (GBPUSD,D1) 0.3395 1 0.7847 OR 0 19:57:24.130 ELN_MA (GBPUSD,D1) 0.2949 1 0.8102 DJ 0 19:57:24.130 ELN_MA (GBPUSD,D1) 0.2561 1 0.8297 ER 0 19:57:24.130 ELN_MA (GBPUSD,D1) 0.2224 1 0.8445 GJ 0 19:57:24.130 ELN_MA (GBPUSD,D1) 0.1932 1 0.8558 JE 0 19:57:24.130 ELN_MA (GBPUSD,D1) 0.1678 1 0.8644 GM 0 19:57:24.130 ELN_MA (GBPUSD,D1) 0.1457 1 0.8709 LE 0 19:57:24.130 ELN_MA (GBPUSD,D1) 0.1266 1 0.8759 JM 0 19:57:24.130 ELN_MA (GBPUSD,D1) 0.1099 2 0.8808 DD 0 19:57:24.130 ELN_MA (GBPUSD,D1) 0.0955 2 0.8929 OL 0 19:57:24.130 ELN_MA (GBPUSD,D1) 0.0829 2 0.9033 HD 0 19:57:24.130 ELN_MA (GBPUSD,D1) 0.0720 2 0.9113 FL 0 19:57:24.130 ELN_MA (GBPUSD,D1) 0.0625 2 0.9173 FG 0 19:57:24.130 ELN_MA (GBPUSD,D1) 0.0543 2 0.9219 RO 0 19:57:24.130 ELN_MA (GBPUSD,D1) 0.0472 3 0.9312 MG 0 19:57:24.130 ELN_MA (GBPUSD,D1) 0.0410 3 0.9418 JO 0 19:57:24.130 ELN_MA (GBPUSD,D1) 0.0356 2 0.9473 EF 0 19:57:24.130 ELN_MA (GBPUSD,D1) 0.0309 2 0.9506 GN 0 19:57:24.130 ELN_MA (GBPUSD,D1) 0.0268 2 0.9531 QF 0 19:57:24.130 ELN_MA (GBPUSD,D1) 0.0233 4 0.9559 HN 0 19:57:24.130 ELN_MA (GBPUSD,D1) 0.0202 4 0.9589 QI 0 19:57:24.130 ELN_MA (GBPUSD,D1) 0.0176 3 0.9613 HQ 0 19:57:24.130 ELN_MA (GBPUSD,D1) 0.0153 3 0.9639 RI 0 19:57:24.130 ELN_MA (GBPUSD,D1) 0.0133 4 0.9658 OQ 0 19:57:24.130 ELN_MA (GBPUSD,D1) 0.0115 3 0.9681 JH 0 19:57:24.130 ELN_MA (GBPUSD,D1) 0.0100 5 0.9695 KP 0 19:57:24.130 ELN_MA (GBPUSD,D1) 0.0087 4 0.9709 NH 0 19:57:24.130 ELN_MA (GBPUSD,D1) 0.0075 4 0.9738 CP 0 19:57:24.130 ELN_MA (GBPUSD,D1) 0.0066 5 0.9752 NK 0 19:57:24.130 ELN_MA (GBPUSD,D1) 0.0057 5 0.9764 CS 0 19:57:24.130 ELN_MA (GBPUSD,D1) 0.0049 4 0.9774 RK 0 19:57:24.130 ELN_MA (GBPUSD,D1) 0.0043 5 0.9783 LS 0 19:57:24.130 ELN_MA (GBPUSD,D1) 0.0037 4 0.9792 GJ 0 19:57:24.130 ELN_MA (GBPUSD,D1) 0.0032 5 0.9801 NR 0 19:57:24.130 ELN_MA (GBPUSD,D1) 0.0028 7 0.9812 PJ 0 19:57:24.130 ELN_MA (GBPUSD,D1) 0.0024 7 0.9827 RR 0 19:57:24.130 ELN_MA (GBPUSD,D1) 0.0021 7 0.9842 KM 0 19:57:24.130 ELN_MA (GBPUSD,D1) 0.0018 6 0.9853 EE 0 19:57:24.130 ELN_MA (GBPUSD,D1) 0.0016 7 0.9861 NM 0 19:57:24.130 ELN_MA (GBPUSD,D1) 0.0014 6 0.9867 OE 0 19:57:24.130 ELN_MA (GBPUSD,D1) 0.0012 6 0.9873 KL 0 19:57:24.130 ELN_MA (GBPUSD,D1) 0.0010 7 0.9878 HG 0 19:57:24.146 ELN_MA (GBPUSD,D1) PG 0 19:57:24.146 ELN_MA (GBPUSD,D1) OptimizeLambda ending with best lambda=0.001048683 explained=0.987563916
Обратите внимание, что когда лямбда максимальна, количество активных предикторов равно нулю, и это значение увеличивается по мере уменьшения лямбды на каждой итерации. Количество выбранных предикторов увеличивается или уменьшается по мере того, как алгоритм решает, какое значение лямбда является лучшим. Полученная модель в конечном итоге отбрасывает еще несколько значений индикаторов, которые она считает ненужными.
PE 0 19:57:24.177 ELN_MA (GBPUSD,D1) optimal lambda 0.00104868 GM 0 19:57:24.287 ELN_MA (GBPUSD,D1) explained variance 0.9871030095923066 DK 0 19:57:24.287 ELN_MA (GBPUSD,D1) NS 0 19:57:24.287 ELN_MA (GBPUSD,D1) 2 , 1 ,1.70372722883263016946e+00 RG 0 19:57:24.287 ELN_MA (GBPUSD,D1) 4 , 2 ,-1.67483731989555195696e+00 QO 0 19:57:24.287 ELN_MA (GBPUSD,D1) 6 , 3 ,1.07905337481491181428e+00 PQ 0 19:57:24.287 ELN_MA (GBPUSD,D1) 8 , 4 ,0.00000000000000000000e+00 HJ 0 19:57:24.287 ELN_MA (GBPUSD,D1) 10 , 5 ,0.00000000000000000000e+00 LN 0 19:57:24.287 ELN_MA (GBPUSD,D1) 12 , 6 ,-1.81038986082938974098e-01 DF 0 19:57:24.287 ELN_MA (GBPUSD,D1) 14 , 7 ,0.00000000000000000000e+00 OH 0 19:57:24.287 ELN_MA (GBPUSD,D1) 16 , 8 ,0.00000000000000000000e+00 FR 0 19:57:24.287 ELN_MA (GBPUSD,D1) 18 , 9 ,0.00000000000000000000e+00 CE 0 19:57:24.287 ELN_MA (GBPUSD,D1) 20 , 10 ,0.00000000000000000000e+00 FO 0 19:57:24.287 ELN_MA (GBPUSD,D1) 22 , 11 ,0.00000000000000000000e+00 IQ 0 19:57:24.287 ELN_MA (GBPUSD,D1) 24 , 12 ,0.00000000000000000000e+00 HK 0 19:57:24.287 ELN_MA (GBPUSD,D1) 26 , 13 ,0.00000000000000000000e+00 OM 0 19:57:24.287 ELN_MA (GBPUSD,D1) 28 , 14 ,0.00000000000000000000e+00 GG 0 19:57:24.287 ELN_MA (GBPUSD,D1) 30 , 15 ,0.00000000000000000000e+00 HI 0 19:57:24.287 ELN_MA (GBPUSD,D1) 32 , 16 ,0.00000000000000000000e+00 ES 0 19:57:24.287 ELN_MA (GBPUSD,D1) 34 , 17 ,0.00000000000000000000e+00 RE 0 19:57:24.287 ELN_MA (GBPUSD,D1) 36 , 18 ,0.00000000000000000000e+00 CO 0 19:57:24.287 ELN_MA (GBPUSD,D1) 38 , 19 ,0.00000000000000000000e+00 HQ 0 19:57:24.287 ELN_MA (GBPUSD,D1) 40 , 20 ,0.00000000000000000000e+00 IK 0 19:57:24.287 ELN_MA (GBPUSD,D1) 42 , 21 ,0.00000000000000000000e+00 FM 0 19:57:24.287 ELN_MA (GBPUSD,D1) 44 , 22 ,0.00000000000000000000e+00 CG 0 19:57:24.287 ELN_MA (GBPUSD,D1) 46 , 23 ,0.00000000000000000000e+00 LI 0 19:57:24.287 ELN_MA (GBPUSD,D1) 48 , 24 ,0.00000000000000000000e+00 DS 0 19:57:24.287 ELN_MA (GBPUSD,D1) 50 , 25 ,0.00000000000000000000e+00 CE 0 19:57:24.287 ELN_MA (GBPUSD,D1) 52 , 26 ,0.00000000000000000000e+00 JO 0 19:57:24.287 ELN_MA (GBPUSD,D1) 54 , 27 ,0.00000000000000000000e+00 MQ 0 19:57:24.287 ELN_MA (GBPUSD,D1) 56 , 28 ,0.00000000000000000000e+00 HK 0 19:57:24.287 ELN_MA (GBPUSD,D1) 58 , 29 ,0.00000000000000000000e+00 IM 0 19:57:24.287 ELN_MA (GBPUSD,D1) 60 , 30 ,0.00000000000000000000e+00 PD 0 19:57:24.287 ELN_MA (GBPUSD,D1) OOS total return = 3.42215 (2963.528 percent)
Заключение
Эластичная чистая регрессия весьма примечательна с точки зрения своих возможностей. Но это не волшебное средство, поскольку для определения модели используется ряд критических переменных, которые требуют уточнения. Помимо типа регуляризации, который необходимо выбрать, пользователю еще предстоит разобраться с другими аспектами, такими как критерий сходимости. Несмотря на эти недостатки, нельзя отрицать, что это полезный инструмент.Имя файла | Описание |
---|---|
MQL5\Indicators\LogPrices.mq5 | Индикатор для логарифмического преобразования необработанных цен. Его хэндл можно передать при вызове другого индикатора. |
MQL5\Include\CoordinateDescent.mqh | Файл include, содержащий определение класса CCoordinateDescent, а также функцию OptimizeLambda(). |
MQL5\Scripts\ELN_MA.mq5 | Пример скрипта, который применяет эластичную сеть для построения прогнозной модели на основе нескольких индикаторов скользящего среднего. |
Перевод с английского произведен MetaQuotes Ltd.
Оригинальная статья: https://www.mql5.com/en/articles/11350
![Графический интерфейс: советы и рекомендации по созданию графической библиотеки на MQL](https://c.mql5.com/2/58/gui_tips_and_tricks_avatar.png)
![Нейросети — это просто (Часть 73): АвтоБоты прогнозирования ценового движения](https://c.mql5.com/2/64/Neural_networks_are_easy_jPart_73u__AutoBots_for_predicting_price_movement_LOGO.png)
![Популяционные алгоритмы оптимизации: Бинарный генетический алгоритм (Binary Genetic Algorithm, BGA). Часть I](https://c.mql5.com/2/65/Population_optimization_algorithms_Binary_Genetic_Algorithm_aBGAz__LOGO-transformed.png)
![Разметка данных в анализе временных рядов (Часть 2):Создаем наборы данных с маркерами тренда с помощью Python](https://c.mql5.com/2/58/Make_datasets_with_trend_markers_using_Python_Avatar.png)
![MQL5 - Язык торговых стратегий для клиентского терминала MetaTrader 5](https://c.mql5.com/i/registerlandings/logo-2.png)
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
Статью прочитал с большим интересом, но в конце создалось такое впечатление, что у автора внезапно закончились буквы на клавиатуре и он оставил статью не дописанной.
"Ближе к концу статьи мы продемонстрируем практическое применение этого метода посредством разработки простой прогнозной стратегии на основе скользящего среднего."
Я так и не понял:
1. В чём заключается демонстрация прогнозной стратегии???
2. Где хоть какой нибудь прогноз, хоть чего нибудь?
//---
Запустил скрипт, в настройках изменил только даты и таймфрейм, получил в лог такую запись:
Объясните мне, что мне должны рассказать эти цифры.
Как то странно выглядит работа индикатора.
Красная линия строится по ценам low, жёлтая по ценам high.
Почему в некоторых местах high ниже low?
Как то странно выглядит работа индикатора.
Красная линия строится по ценам low, жёлтая по ценам high.
Почему в некоторых местах high ниже low?
Вы же в курсе, что индикаторы в одном подокне не приводятся к одному и тому же масштабу, если не задать его явно одинаковым?
Вы же в курсе, что индикаторы в одном подокне не приводятся к одному и тому же масштабу, если не задать его явно одинаковым?
Ага. Немного затупил. Всё норм. Спасибо.