English Русский Español Deutsch 日本語 Português
preview
使用经典机器学习方法预测汇率:逻辑回归(logit)模型和概率回归(probit)模型

使用经典机器学习方法预测汇率:逻辑回归(logit)模型和概率回归(probit)模型

MetaTrader 5EA交易 |
144 9
Evgeniy Chernish
Evgeniy Chernish

引言

金融市场研究者始终面临一道难题:在众多数学模型中,如何挑选出能够预测交易品种未来走势的最佳方案?迄今为止,已涌现出大量此类模型。于是问题随之而来:面对方法浩如烟海,该如何避免迷失方向?初学者若想借助机器学习进行预测,又该从哪里入手、重点聚焦哪些模型?若将预测任务简化为一个二选一的问题——“明天的收盘价会高于今天吗?”——那么最顺理成章的选择便是二元分类模型。其中,逻辑回归(logit)和概率回归(probit)既简单又应用广泛。这些方法属于最常见的机器学习范式——有监督学习。

有监督学习的任务,则是教会模型把一组输入 {x}(预测变量或特征)映射到一组输出 {y}(目标或标签)。在本文中,我们只预测两种市场状态——货币对价格上涨或下跌。因此标签只有两类:y ∊ {1,0}。作为预测变量,我们使用价格模式,即经过标准化、并带有指定滞后的价格增量。这些数据将构成我们的 {x, y} 训练集,用于估计模型参数。基于训练好的分类器,预测模型被实现为称为LogitExpert的EA。


二元逻辑(logit)回归和概率(probit)回归

先简要回顾理论部分。最简单的二元选择模型是线性概率模型,其中成功事件的概率 P(yn=1|xn) 是解释变量的线性函数:

P(yn=1|xn) = w0*1 + w1x1 + w2x2 + … + wkxk

遗憾的是,这种模型存在一个严重缺陷:预测值可能大于 1 或小于 0,从而无法将其解释为概率。为解决这一问题,人们提出用已知的概率分布函数对线性函数的输出进行转换。

probit 模型基于标准正态分布 N(0,1):

P(yn=1|xn) = F(xnw)=μn

  • n —— 表示观测(样本)序号的下标,

  • yn —— 类别标签,

  • F( ) —— 正态分布函数(激活函数),

  • xn —— 特征向量,

  • w —— 模型参数向量,

  • xnw —— logit 或前激活值(特征向量与参数向量的点积)

xnw = w0*1 + w1x1 + w2x2 + … + wkxk

而 logit 模型则基于逻辑分布:

                                                            P(yn=1|xn) = L(xnw) = exp(xnw)/(1 + exp(xnw)) = μn

逻辑分布与正态分布的分布函数非常接近,在区间 [-1.2, 1.2] 内几乎重合。因此,除非概率接近 0 或 1,否则 logit 与 probit 模型往往给出相似的结果。将特征向量代入这些模型,我们就能计算出类别标签的概率,进而判断未来价格走势的方向概率。


准备数据

在估计模型参数之前,需要先定义特征,将其标准化,并以适当形式提供给寻找最优参数(即最小化损失函数)的函数。负责这一任务的函数是GetDataset:

  • InpCount_ —— 设置训练样本数量

  • lag_ —— 用于分析的特征数量(带滞后的价格增量)

  • string X —— 用于计算特征的货币对

  • string y —— 用于计算标签的货币对

  • int start —— 开始采集训练样本的K线编号

作为示例,我们使用货币对价格的滞后量作为特征。例如,若将参数 lag_ 设为 4,则特征为 x{return-4,return-3,return-2,return-1}},最终可获得 (InpCount_ - lag_) 个训练样本。

//+------------------------------------------------------------------+
//|Get data for analysis: features and corresponding labels          |
//+------------------------------------------------------------------+
bool GetDataset(int InpCount_,int lag_,int start,matrix &Input_X,vector & Target_y,string X,string y)
  {

   matrix rates;
   matrix target;
   target.CopyRates(y, PERIOD_CURRENT, COPY_RATES_OHLC, start+1, InpCount_);
   rates.CopyRates(X, PERIOD_CURRENT, COPY_RATES_OHLC, start+2, InpCount_-1);
   rates = rates.Transpose();
   target = target.Transpose();
   int Class_ [];
   ArrayResize(Class_,InpCount_);
   for(int i=0; i<InpCount_; i++)
     {
      if(target[i,3] >  target[i,0])
         Class_[i] = 1;
      else
         Class_[i] = 0;
     }

   vector label=vector::Zeros(InpCount_-lag_);
   for(int i=0; i<InpCount_-lag_; i++)
     {
      label[i] = Class_[i+lag_]; // class label
     }

   matrix returns=matrix::Zeros(InpCount_-lag_, lag_);
   for(int j=0; j<lag_; j++)
     {
      for(int i=0; i<InpCount_-lag_; i++)
        {
         returns[i,j] =rates[i+j,3] - rates[i+j,0]  ; // Input Data
        }
     }

   vector cols_mean=returns.Mean(0);
   vector cols_std=returns.Std(0);

   mean_ = cols_mean[lag_-1];
   std_ = cols_std[lag_-1];

   for(int j=0; j<lag_; j++)
     {
      for(int i=0; i<InpCount_-lag_; i++)
        {
         returns[i,j] = (returns[i,j] - cols_mean[lag_-1])/cols_std[lag_-1];
        }
     }
   Input_X = returns;
   Target_y = label;

   return true;
  }

在输出端,我们得到了特征矩阵 Input_X 与标签向量 Target_y。训练集构建完成后,接下来进入参数估计阶段。


模型参数估计

最常用的参数估计方法是最大似然法。在二元情形下,logit 与 probit 模型均假设因变量服从伯努利分布。若此假设成立,则对数似然函数可写为:

LLF

  • yn —— 类别标签,

  • μn —— 使用 logit 或 probit 回归得到的类别预测概率;

  • N —— 训练样本数量

为了估计参数,需要最大化该函数。然而在机器学习中通常以最小化损失函数为目标,且多数优化器均针对“最小化”进行配置,因此只需对对数似然函数取负号。结果即是所谓的负对数似然(NLL)。我们将使用L-BFGS 二阶拟牛顿优化算法来最小化损失函数,该算法已在Alglib库中实现。 这一数值方法通常用于求解 logit 与 probit 模型的参数。另一种常用的优化方法是迭代加权最小二乘法(IRLS)。

//+------------------------------------------------------------------+
//| Derived class from CNDimensional_Func                            |
//+------------------------------------------------------------------+
class CNDimensional_Logit : public CNDimensional_Func
  {
public:
                     CNDimensional_Logit(void) {}
                    ~CNDimensional_Logit(void) {}
   virtual void      Func(CRowDouble &w,double &func,CObject &obj);
  };

//+------------------------------------------------------------------+
//| Objective Function: Logit Negative loglikelihood                 |
//+------------------------------------------------------------------+
void CNDimensional_Logit::Func(CRowDouble &w,double &func,CObject &obj)
  {

   double LLF[],probit[],probitact[];
   vector logitact;
   ArrayResize(LLF,Rows_);
   ArrayResize(probit,Rows_);
   vector params=vector::Zeros(Cols_);

   for(int i = 0; i<Cols_; i++)
     {
      params[i] =  w[i]; // vector of parameters
     }

   vector logit=vector::Zeros(Rows_);
   logit = Input_X_gl.MatMul(params);

   for(int i=0; i <Rows_; i++)
     {
      probit[i] = logit[i];
     }

   if(probit_)
      MathCumulativeDistributionNormal(probit,0,1,probitact); // Probit activation
   else
      logit.Activation(logitact,AF_SIGMOID); // Logit activation

//--------------------to avoid NAN error when calculating logarithm ------------------------------------
   if(probit_)
     {
      for(int i = 0; i<Rows_; i++)
        {
         if(probitact[i]==1)
            probitact[i]= 0.999;
         if(probitact[i]==0)
            probitact[i]= 0.001;
        }
     }
   else
     {
      for(int i = 0; i<Rows_; i++)
        {
         if(logitact[i]==1)
            logitact[i]= 0.999;
         if(logitact[i]==0)
            logitact[i]= 0.001;
        }
     }
//-------------------------------------------------------------------------------------------------
   double L2_reg;
   if(L2_)
      L2_reg = 0.5 * params.Dot(params); //  L2_regularization
   else
      L2_reg =0;

//------------------ calculate loss function-------------------------------------------------------------
   if(probit_)
     {
      for(int i = 0; i<Rows_; i++)
        {

         LLF[i]=target_y_gl[i]*MathLog(probitact[i]) + (1-target_y_gl[i])*MathLog(1-probitact[i]) ;

         if(!MathIsValidNumber(LLF[i]))
           {
            break;
           }
        }
     }
   else
     {
      for(int i = 0; i<Rows_; i++)
        {

         LLF[i]=target_y_gl[i]*MathLog(logitact[i]) + (1-target_y_gl[i])*MathLog(1-logitact[i]);

         if(!MathIsValidNumber(LLF[i]))
           {
            break;
           }
        }
     }

   func = -MathSum(LLF) + L2_reg/(Rows_*C_); // Negative Loglikelihood + L2_regularization
//------------------------------------------------------------------------------------------------------
   func_ = func;
  }

然而,仅计算参数估计值并不足够;我们还希望获得这些估计值的标准误,以判断各个特征的显著性。

例如,流行的机器学习库 scikit-learn 在 logit 模型中并未提供这一信息。我已为 logit 与 probit 模型计算了标准差,因此可以直观地看到哪些具体特征对预测具有统计显著性。这也是我倾向于在 MQL 中自行编写 logit 模型代码,而非借助 ONNX 把现成机器学习包模型直接转换过来的原因之一。另一个原因是:我需要一个动态模型,能在每根 K 线或任意指定的时间框架上重新优化分类器参数。

不过,让我们回到损失函数。需要指出的是,它仍需进一步修正。要点在于:与先进的神经网络方法一样,我们的分类器也容易出现过拟合。其表现之一便是参数估计值异常偏大;为避免这一负面现象,需要一种能够限制估计值的方法。该方法即 L2 正则化:

NLL_L2

  • λ = 1/С , С = (0,1]

我们只需在现有损失函数中加上参数向量的 L2 范数平方,再乘上超参数 λ。λ 越大,对较大参数的惩罚越强,正则化效果也越明显。

负责估计分类器参数的函数为 FitLogitRegression:

  • bool L2 = false —— 默认关闭 L2 正则化;
  • double C = 1.0 —— 正则化强度超参数,值越小,对优化参数的限制越强;
  • bool probit = false —— 默认启用 logit 模型;
  • double alpha —— LR 统计量卡方分布的显著性水平 α

该函数以特征矩阵为输入,并为其增加一个取值恒为 1 的条件或哑变量。以便估计模型中的截距参数 w₀。除参数估计外,该函数还计算它们的协方差矩阵,用于求标准差。

//+------------------------------------------------------------------+
//| Finding the optimal parameters for the Logit or Probit model     |
//+------------------------------------------------------------------+
vector FitLogitRegression(matrix &input_X, vector &target_y,bool L2 = false, double C=1.0,bool probit = false,double alpha = 0.05)
  {
   L2_=L2;
   probit_ = probit;
   C_ = C;
   double              w[],s[];
   CObject             obj;
   CNDimensional_Logit ffunc;
   CNDimensional_Rep   frep;
   ulong Rows = input_X.Rows();
   ulong Cols = input_X.Cols();
   matrix One=matrix::Ones(int(Rows),int(Cols+1));
   for(int i=0;i<int(Cols); i++)
     {
      One.Col(input_X.Col(i),i+1);  // design matrix
     }
   input_X = One;
   Cols = input_X.Cols();
   Rows_ = int(Rows);
   Cols_ = int(Cols);
   Input_X_gl = input_X;
   target_y_gl = target_y;
   ArrayResize(w,int(Cols));
   ArrayResize(s,int(Cols));
//--- initialization
   ArrayInitialize(w,0.0);
   ArrayInitialize(s,1.0);
//--- optimization stop conditions
   double epsg=0.000001;
   double epsf=0.000001;
   double epsx=0.000001;
   double diffstep=0.000001;
   int maxits=0;
//------------------------------
   CMinLBFGSStateShell state;
   CMinLBFGSReportShell rep;
   CAlglib::MinLBFGSCreateF(1,w,diffstep,state);
   CAlglib::MinLBFGSSetCond(state,epsg,epsf,epsx,maxits);
   CAlglib::MinLBFGSSetScale(state,s);
   CAlglib::MinLBFGSOptimize(state,ffunc,frep,0,obj);
   CAlglib::MinLBFGSResults(state,w,rep);
   Print("TerminationType ="," ",rep.GetTerminationType());
   Print("IterationsCount ="," ",rep.GetIterationsCount());

   vector parameters=vector::Zeros(Cols);
   for(int i = 0; i<int(Cols); i++)
     {
      parameters[i]= w[i];
     }
   Print("Parameters = "," ",parameters);

//-------Likelihood Ratio Test LR-----------------------------------------
   double S = target_y.Sum();   // number of "success"
   ulong All = target_y.Size(); // all data
   double L0 = S*MathLog(S/All) + (All-S)*MathLog((All-S)/All); // Log-likelihood for the trivial model
 //  Print("L0 = ",L0);
 //  Print("LLF = ",func_);
   double LR;
   LR = 2*(-func_ - L0); // Likelihood Ratio Test LR
   int err;
   double Chi2 = MathQuantileChiSquare(1-alpha,Cols-1,err); // If H0 true ---> Chi2Distribution(alpha,v)
   Print("LR ",LR," ","Chi2 = ",Chi2);
//--------------------------------------------------------------------------------
//-------------- calculate if model significant or not
   if(LR > Chi2)
      ModelSignificant = true;
   else
      ModelSignificant = false;
//----------------------------------------------------

//-------------Estimation of the covariance matrix of parameters for the Probit model------------
   vector logit = input_X.MatMul(parameters);  //
   vector activation;
   logit.Activation(activation,AF_SIGMOID); // Logit activation
   double probit_SE[],probitact[];
   ArrayResize(probit_SE,Rows_);

   for(int i=0; i <Rows_; i++)
     {
      probit_SE[i] = logit[i];
     }

   if(probit_)
     {
      ulong size_parameters = parameters.Size();
      matrix CovProbit=matrix::Zeros(int(size_parameters),int(size_parameters));
      int err;
      vector a_=vector::Zeros(Rows_);
      vector b=vector::Zeros(Rows_);
      vector c=vector::Zeros(Rows_);
      vector xt=vector::Zeros(int(size_parameters));

      for(int i = 0; i<Rows_; i++)
        {
         a_[i] = MathPow((MathProbabilityDensityNormal(probit_SE[i],0,1,err)),2);
         b[i] = MathCumulativeDistributionNormal(probit_SE[i],0,1,err);
         c[i] = a_[i]/(b[i]*(1-b[i]));
         xt = input_X.Row(i);
         CovProbit = CovProbit + c[i]*xt.Outer(xt);
        }
      CovProbit = CovProbit.Inv();
      vector SE;
      SE = CovProbit.Diag(0);
      SE = MathSqrt(SE);  // standard errors of parameters
      Print("Probit_SE = ", SE);
     }
   else
     {
      //-------------Estimation of the covariance matrix of parameters for the Logit model------------
      vector v = vector::Zeros(Rows_);

      for(int i = 0; i<Rows_; i++)
        {
         v[i] = activation[i]*(1-activation[i]);
        }

      matrix R,Hesse,X,a,CovLogit;
      R.Diag(v,0);
      X = input_X.Transpose();
      a = X.MatMul(R);
      Hesse = a.MatMul(input_X);
      CovLogit = Hesse.Inv();
      vector SE;
      SE = CovLogit.Diag(0);
      SE = MathSqrt(SE); // standard errors of parameters
      Print("Logit_SE = ", SE);
      //-----------------------------------------------
     }
   return parameters;
  }

参数估计及其协方差矩阵计算完成后,我们便可进入预测阶段。


预测

负责预测类别标签(即生成买入或卖出信号)的函数是Trade_PredictedTarget。该函数接收已优化的参数作为输入,并输出预测的类别标签。随后 LogitExpert EA 根据预测结果生成开仓规则。规则十分简洁:若收到买入信号(signal = 1),则开立多头仓位;若已持有多头,则继续持有;若收到卖出信号,则立即平掉多头并开立空头仓位。

LogitExpert EA 的实现代码

//+------------------------------------------------------------------+
//|                                                  LogitExpert.mq5 |
//|                                                           Eugene |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Eugene"
#property link      "https://www.mql5.com"
#property version   "1.00"

#include <\LogitReg.mqh>
#include <Trade\Trade.mqh>
#include <Trade\PositionInfo.mqh>
CTrade m_trade;
CPositionInfo m_position;

sinput string   symbol_X       = "EURUSD";    // Input symbol
sinput string   symbol_y       = "EURUSD";    // Target symbol
input bool     _probit_        = false;       // Probit model
input  int      InpCount       = 20;          // Depth of history
input  int     _lag_           = 4;           // Number of features
input bool     _L2_            = false;       // L2_regularization
input double   _C_             = 1;           // C(0,1) inverse of regularization strength
input double   alpha_          = 0.05;        // Significance level Alpha (0,1)
input int      reoptimize_step = 2;           // Reoptimize step

#define MAGIC_NUMBER 23092024

int prev_bars = 0;
MqlTick ticks;
double min_lot;
vector params_;
matrix _Input_X;
vector _Target_y;
static int count_ = 0;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   m_trade.SetExpertMagicNumber(MAGIC_NUMBER);
   m_trade.SetTypeFillingBySymbol(Symbol());
   m_trade.SetMarginMode();
   min_lot = SymbolInfoDouble(Symbol(), SYMBOL_VOLUME_MIN);

   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   Print(__FUNCTION__," Deinitialization reason code = ",reason);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   if(!isnewBar(PERIOD_CURRENT))
      return;

   double step;
   step = count_ % reoptimize_step;
//------------------------------------Train Dataset-------------------------------------------------
   int start = 0;
   if(step == 0)
     {
      GetDataset(InpCount,_lag_,start,_Input_X,_Target_y,symbol_X,symbol_y);
      params_ = FitLogitRegression(_Input_X,_Target_y,_L2_,_C_,_probit_,alpha_);
     }
   count_ = count_+1;
//--------------------------------------------------------------------------------------------------

//--- Get trade signal
   int signal = Trade_PredictedTarget(params_,start,_lag_,InpCount,symbol_X);
   Comment("Trade signal: ",signal,"  ","ModelSignificant: ",ModelSignificant);  
//---------------------------------------------

//--- Open trades based on Signals
   SymbolInfoTick(Symbol(), ticks);
   if(signal==1)
     {
      if(!PosExists(POSITION_TYPE_BUY) && ModelSignificant)
        {
         m_trade.Buy(min_lot,Symbol(), ticks.ask);
         PosClose(POSITION_TYPE_SELL);
        }
      else
        {
         PosClose(POSITION_TYPE_SELL);
        }
     }
   else
     {
      if(!PosExists(POSITION_TYPE_SELL) && ModelSignificant)
        {
         m_trade.Sell(min_lot,Symbol(), ticks.bid);
         PosClose(POSITION_TYPE_BUY);
        }
      else
        {
         PosClose(POSITION_TYPE_BUY);
        }
     }
  }
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
//|   Function tracks the occurrence of a new bar event              |
//+------------------------------------------------------------------+
bool isnewBar(ENUM_TIMEFRAMES TF)
  {
   if(prev_bars == 0)
      prev_bars = Bars(Symbol(), TF);

   if(prev_bars != Bars(Symbol(), TF))
     {
      prev_bars = Bars(Symbol(), TF);
      return true;
     }

   return false;
  }

//+------------------------------------------------------------------+
//|Function determines whether there is an open buy or sell position |
//+------------------------------------------------------------------+
bool PosExists(ENUM_POSITION_TYPE type)
  {
   for(int i=PositionsTotal()-1; i>=0; i--)
      if(m_position.SelectByIndex(i))
         if(m_position.Symbol()==Symbol() && m_position.Magic() == MAGIC_NUMBER && m_position.PositionType()==type)
            return true;

   return false;
  }
//+------------------------------------------------------------------+
//|The function closes a long or short trade                         |
//+------------------------------------------------------------------+
void PosClose(ENUM_POSITION_TYPE type)
  {
   for(int i=PositionsTotal()-1; i>=0; i--)
      if(m_position.SelectByIndex(i))
         if(m_position.Symbol()==Symbol() && m_position.Magic() == MAGIC_NUMBER && m_position.PositionType()==type)
            if(!m_trade.PositionClose(m_position.Ticket()))
               printf("Failed to close position %d Err=%s",m_position.Ticket(),m_trade.ResultRetcodeDescription());
  }

这款 EA 与其他做法相比,有两处关键差异:第一,它允许每隔 reoptimize_step 根 K 线就对分类器参数做一次重新优化;第二,它不仅估计模型参数,还会计算这些参数的标准差——这一点常被忽视。仅仅在样本上找到“最优”参数是不够的,还必须检验这些参数乃至整体模型是否显著。若参数不显著,那么忽略这类交易信号反而更合理。

因此,该 EA 还内置了模型显著性检验流程。零假设 H₀:所有模型参数均为 0(H₀: w₁ = w₂ = w₃ = … = wₖ = 0);备择假设 H₁:至少有一个参数不为 0,即模型对预测有用。检验使用似然比(LR)统计量,它衡量设定模型与平凡模型之间的差异:


LR = 2(LLF – LLF0)

  • LLF —— 所求模型的对数似然值;

  • LLF₀ —— 零假设下平凡模型的对数似然值。

p₀ = Σ(yₙ = 1) / N —— 样本中“成功”的比例;

LLF0 = N(p0*Ln(p0) + (1- p0)*Ln(1 – p0))

LR 越大,说明完整模型相对常规模型越好。当零假设成立时,LR 统计量服从自由度 v = 特征数量 的 χ² 分布。若计算出的 LR 值落入拒绝域,即 LR > X2crit (α; v = lag_),则拒绝 H₀,此时交易信号被视为有效,EA 才会开仓。

这只是其中一种可行的场景。GBPUSD,日线:

回测GBPUSD日线

超参数

超参数

除了对分类器模型本身的参数进行评估之外,我们还需要评估许多超参数:

  • 历史深度
  • 特征数量
  • 显著性水平
  • 再优化步长

从 MetaTrader 5 的策略测试器中挑选这些超参数。一个可进一步提升 EA 表现的方案是构建历史深度参数与市场当前状态的依赖关系函数——即像我们对 logit 与 probit 模型参数所做的那样,让它也成为动态变量。不过,那将是另一个故事。提示一下,可参阅我的文章《作为时间序列非平稳性指标的双样本 Kolmogorov-Smirnov 检验》,其中探讨了构造“失序”指标的问题。


结论

在本文中,我们探讨了带有二元输出指标的回归模型,学习了如何估计这些模型的参数,并实现了用于测试与调参的 LogitExpert 交易 EA。其独特之处在于,它能够基于最新且最相关的数据,实时重训练分类器参数。

我们特别关注了参数标准误的估计,这要求我们计算 logit 与 probit 模型的协方差矩阵。

似然比准则被用来检验整个分类器模型方程的显著性,该统计量用于过滤掉统计上不可靠的交易信号。

本文由MetaQuotes Ltd译自俄文
原文地址: https://www.mql5.com/ru/articles/16029

附加的文件 |
LogitReg.mqh (22.43 KB)
LogitExpert.mq5 (10.94 KB)
最近评论 | 前往讨论 (9)
Stanislav Korotky
Stanislav Korotky | 4 10月 2024 在 16:41
Evgeniy Chernish #:
所有问题请向外汇市场和有效市场假说陛下提问。

这个标题有误导之嫌。

Evgeniy Chernish
Evgeniy Chernish | 4 10月 2024 在 17:12
Aleksey Nikolayev #:

谢谢你,有趣的好文章。

我认为,您已经可以尝试在一日游中使用基本数据了。这并不是批评文章,而是一种思维方式。我想知道如何将宏观经济数据与价格数据充分 "混合"。例如,问题在于它们的变化很少。也许,宏观经济也可以在某种程度上用于价格预处理--例如,从名义汇率到实际汇率的过渡。

谢谢您,阿列克谢!坦率地说,我从未对基本面产生过兴趣,这并不是因为它不能提供额外的信息,而仅仅是因为它不可能涵盖广阔的领域。这就是为什么我甚至还没有关注这个方向。
Evgeniy Chernish
Evgeniy Chernish | 4 10月 2024 在 17:17
Stanislav Korotky #:

因此,标题具有误导性。

为什么?它使用一个分类预测模型进行预测。它正确计算了输入模型的内容。那有什么问题?该模型不能击败天真的预测?我可没这么保证)。
Stanislav Korotky
Stanislav Korotky | 4 10月 2024 在 17:48
Evgeniy Chernish #:
为什么?它使用了一个分类预测模型来进行预测。它能正确计算输入模型的内容。那有什么问题?该模型不能击败天真的预测?我可没这么说)

"用传统方法预测汇率是不可能的......"

Evgeniy Chernish
Evgeniy Chernish | 4 10月 2024 在 18:20
Stanislav Korotky #:

"用传统方法预测汇率是不可能的......"

我根本没想到这是不可能的。我只是做了一个预测,并用 python 库检查了一下是否有误。也许有人会添加一些过滤器、自己的功能,也许有人会做得更好。而你马上就想到了不可能。
交易中的神经网络:对比形态变换器 交易中的神经网络:对比形态变换器
对比变换器在设计上基于单根烛条水平和整个形态来分析行情。这有助于提升行情趋势建模的品质。甚至,运用对比学习来统调烛条和形态的表示、促进自我调节,并提升预测的准确性。
从新手到专家:MQL5中的协作式调试指南 从新手到专家:MQL5中的协作式调试指南
问题解决法能为掌握复杂技能(如MQL5编程)构建高效路径。该方法让您在专注攻克问题的同时,潜移默化地提升技能水平。解决的难题越多,大脑积累的专业知识就越深厚。就我个人而言,调试是精通编程最有效的途径。本文将带你逐步梳理代码清理流程,并探讨将杂乱程序转化为简洁高效代码的核心技巧。阅读本文,洞悉其中的宝贵见解。
人工喷淋算法(ASHA) 人工喷淋算法(ASHA)
本文介绍了人工喷淋算法(Artificial Showering Algorithm,ASHA),这是一种为解决一般优化问题而开发的新型元启发式方法。基于对水流和积聚过程的模拟,该算法构建了理想场的概念,其中要求每个资源单元(水)找到最优解。我们将了解 ASHA 如何调整流和累积原则来有效地分配搜索空间中的资源,并查看其实现和测试结果。
交易中的神经网络:运用形态变换器进行市场分析 交易中的神经网络:运用形态变换器进行市场分析
当我们用模型分析市场形势时,我们主要关注蜡烛条。然而,人们早就知道烛条形态能有助于预测未来的价格走势。在本文中,我们将领略一种能将这两种方法集成的方式。