交易中的神经网络:统一轨迹生成模型(UniTraj)·进阶篇
🧠

交易中的神经网络:统一轨迹生成模型(UniTraj)·进阶篇

(2/3)·从单一蒙版轨迹到Mamba双向编码,看UniTraj如何把预测与补全拧进同一个框架

案例拆解新手友好 第 2/3 篇
很多交易者把轨迹预测和缺口补全当成两件事,分别跑不同模型,结果前后向依赖被切散。UniTraj把任意不完整轨迹加可见性蒙版统一处理,忽视这点就会在复用旧算法时漏掉时序对称性。

◍ 反向遍历里的衰减累积写法

这段逻辑出现在单向轨迹神经元的反向通道初始化里,核心是用一个倒序循环把后续步的掩码折算成当前步的累积权重。 step 取负值,等于 -(variables * 3),说明内层索引是沿着输入张量往回跳;start 以 (total-1)*variables 打底,再叠加 v*3+2,定位到当前变量通道在最后一帧的偏移。 循环从 p=1 跑到 total-1,每步读取 concat_inp[start + p*step],并用 last = 1 + (1 - m) * last 做递推。这意味着越靠近末端、m 越小的位置,累积值膨胀越明显,训练时反向梯度可能更敏感。 外层类 CNeuronUniTraj 直接继承 CNeuronBaseOCL,成员里挂了 cEncoder、cSSM[4]、cVAE 等模块,说明这类神经元把注意力、状态空间与变分解码全压进一个实例里,MT5 上跑起来显存占用值得自己查一眼。

MQL5 / C++
const class="type">int step = -(variables * class="num">3);
const class="type">int start = (total - class="num">1) * variables + v * class="num">3 + class="num">2;
class="type">class="kw">float last = class="num">0;
d_bakw[(total - class="num">1) + v] = class="num">0;
for(class="type">int p = class="num">1; p < total; p++)
  {
   class="type">class="kw">float m = concat_inp[start + p * step];
   d_bakw[(total - class="num">1 - p) * variables + v] = last = class="num">1 + (class="num">1 - m) * last;
  }
 }
}
class CNeuronUniTraj    :  class="kw">public CNeuronBaseOCL
 {
class="kw">protected:
  class="type">uint            iVariables;
  class="type">class="kw">float           fDropout;
  class=class="str">"cmt">//---
  CBufferFloat    cHistoryMask;
  CBufferFloat    cFutureMask;
  CNeuronBaseOCL  cData;
  CNeuronLearnabledPE cPE;
  CNeuronMVMHAttentionMLKV   cEncoder;
  CNeuronBaseOCL  cDForw;
  CNeuronBaseOCL  cDBakw;
  CNeuronConvOCL  cProjDForw;
  CNeuronConvOCL  cProjDBakw;
  CNeuronBaseOCL  cDataDForw;
  CNeuronBaseOCL  cDataDBakw;
  CNeuronBaseOCL  cConcatDataDForwBakw;
  CNeuronMambaBlockOCL cSSM[class="num">4];
  CNeuronConvOCL  cStat;
  CNeuronTransposeOCL cTranspStat;
  CVAE            cVAE;
  CNeuronTransposeOCL cTranspVAE;
  CNeuronConvOCL  cDecoder[class="num">2];
  CNeuronTransposeOCL cTranspResult;
  class=class="str">"cmt">//---
  class="kw">virtual class="type">bool    Prepare(const CBufferFloat* history, const CBufferFloat* future);
  class="kw">virtual class="type">bool    PrepareGrad(CBufferFloat* history_gr, CBufferFloat* future_gr);
  class="kw">virtual class="type">bool    BTS(class="type">void);
  class=class="str">"cmt">//---
  class="kw">virtual class="type">bool    feedForward(CNeuronBaseOCL *NeuronOCL) class="kw">override { class="kw">return feedForward(NeuronOCL, NULL); }
  class="kw">virtual class="type">bool    feedForward(CNeuronBaseOCL *NeuronOCL, CBufferFloat *SecondInput) class="kw">override;
  class=class="str">"cmt">//---
  class="kw">virtual class="type">bool    calcInputGradients(CNeuronBaseOCL *NeuronOCL) class="kw">override
{ class="kw">return calcInputGradients(NeuronOCL, NULL, NULL, None); }
  class="kw">virtual class="type">bool    updateInputWeights(CNeuronBaseOCL *NeuronOCL) class="kw">override
{ class="kw">return updateInputWeights(NeuronOCL, NULL); }
  class="kw">virtual class="type">bool    calcInputGradients(CNeuronBaseOCL *NeuronOCL, CBufferFloat *SecondInput,
CBufferFloat *SecondGradient,
ENUM_ACTIVATION SecondActivation = None) class="kw">override;
  class="kw">virtual class="type">bool    updateInputWeights(CNeuronBaseOCL *NeuronOCL, CBufferFloat *second) class="kw">override;
  class=class="str">"cmt">//---
class="kw">public:
                 CNeuronUniTraj(class="type">void) {};
                ~CNeuronUniTraj(class="type">void) {};
  class=class="str">"cmt">//---

单轨迹神经元初始化里的张量排布

CNeuronUniTraj 的 Init 把单条价格轨迹喂给 OpenCL 加速的 Transformer 式结构。注意基类初始化时传入的神经元数是 window * (units_count + forecast),也就是回看窗口乘以「历史编码单元数 + 预测步长」,这决定了显存缓冲的横向宽度。 dropout 参数被 MathMax(MathMin(dropout,1),0) 钳制在 [0,1],越界值不会崩,只会被静默收口。历史掩码 cHistoryMask 按 iVariables * units_count 长度初始化,未来掩码 cFutureMask 按 iVariables * forecast 初始化,两者分离意味着模型在编码阶段显式区分已知序列与待推演序列。 编码器 cEncoder 的 heads 参数传入 window_key,内部头数被算成 (heads+1)/2,当 heads 为奇数时实际头数比传入少半——调参时若发现并行注意力偏弱,先查这个数是否被整数除法吃掉了。下面这段是 Init 的主体声明与部分构建逻辑,逐行看缓冲怎么落位。

MQL5 / C++
class="type">bool CNeuronUniTraj::Init(class="type">uint numOutputs, class="type">uint myIndex, COpenCLMy *open_cl,
                          class="type">uint window, class="type">uint window_key, class="type">uint heads, class="type">uint units_count,
                          class="type">uint forecast, class="type">class="kw">float dropout, ENUM_OPTIMIZATION optimization_type, class="type">uint batch)
  {
  if(!CNeuronBaseOCL::Init(numOutputs, myIndex, open_cl, window * (units_count + forecast),
optimization_type, batch))
      class="kw">return class="kw">false;
  iVariables = window;
  fDropout = MathMax(MathMin(dropout, class="num">1), class="num">0);
  if(!cHistoryMask.BufferInit(iVariables * units_count, class="num">1) ||
      !cHistoryMask.BufferCreate(OpenCL))
      class="kw">return class="kw">false;
  if(!cFutureMask.BufferInit(iVariables * forecast, class="num">1) ||
      !cFutureMask.BufferCreate(OpenCL))
      class="kw">return class="kw">false;
  if(!cData.Init(class="num">0, class="num">0, OpenCL, class="num">3 * iVariables * (units_count + forecast), optimization, iBatch))
      class="kw">return class="kw">false;
  if(!cPE.Init(class="num">0, class="num">1, OpenCL, cData.Neurons(), optimization, iBatch))
      class="kw">return class="kw">false;
  if(!cEncoder.Init(class="num">0, class="num">2, OpenCL, class="num">3, window_key, heads, (heads + class="num">1) / class="num">2, iVariables, class="num">1, class="num">1,
(units_count + forecast), optimization, iBatch))
      class="kw">return class="kw">false;
  if(!cDForw.Init(class="num">0, class="num">3, OpenCL, iVariables * (units_count + forecast), optimization, iBatch))
      class="kw">return class="kw">false;;
  if(!cDBakw.Init(class="num">0, class="num">4, OpenCL, iVariables * (units_count + forecast), optimization, iBatch))
      class="kw">return class="kw">false;
  if(!cProjDForw.Init(class="num">0, class="num">5, OpenCL, class="num">1, class="num">1, class="num">3, iVariables, (units_count + forecast), optimization, iBatch))
      class="kw">return class="kw">false;
  cProjDForw.SetActivationFunction(SIGMOID);
  if(!cProjDBakw.Init(class="num">0, class="num">6, OpenCL, class="num">1, class="num">1, class="num">3, iVariables, (units_count + forecast), optimization, iBatch))
      class="kw">return class="kw">false;

「轨迹模型各层的初始化与前向遮罩」

这段初始化把 UniTraj 网络的多层结构在 OpenCL 上下文里逐一落地:前馈数据层用设备号 0、层标识 7,回传数据层用标识 8,拼接层标识 9 且神经元数固定为 cData.Neurons() 的两倍。SSM 状态空间模块按 cSSM.Size() 循环分配,每层输入维度 6*iVariables、输出 12*iVariables,层 id 从 10 开始顺延。 后续统计层、转置层、VAE 与转置 VAE 的 id 依次自增,其中 cVAE 隐层神经元数取 cTranspStat.Neurons()/2,转置 VAE 再除以 iVariables 得到 w。两个解码器分别用 LReLU 和 TANH 激活,最后把转置结果层设为网络输出并回传梯度。 前向方法 feedForward 里先建 History Mask:用 cHistoryMask.Total() 取总长度并初始化为全 1。训练态 bTrain 下按 fDropout 比例随机置 0——例如 fDropout=0.1 时,千个位置约随机屏蔽 100 处,制造丢弃噪声。写完缓冲才继续后续计算,否则直接返回 false。

MQL5 / C++
  cProjDBakw.SetActivationFunction(SIGMOID);
  if(!cDataDForw.Init(class="num">0, class="num">7, OpenCL, cData.Neurons(), optimization, iBatch))
     class="kw">return class="kw">false;
  if(!cDataDBakw.Init(class="num">0, class="num">8, OpenCL, cData.Neurons(), optimization, iBatch))
     class="kw">return class="kw">false;
  if(!cConcatDataDForwBakw.Init(class="num">0, class="num">9, OpenCL, class="num">2 * cData.Neurons(), optimization, iBatch))
     class="kw">return class="kw">false;
  for(class="type">uint i = class="num">0; i < cSSM.Size(); i++)
     {
       if(!cSSM[i].Init(class="num">0, class="num">10 + i, OpenCL, class="num">6 * iVariables, class="num">12 * iVariables,
(units_count + forecast), optimization, iBatch))
         class="kw">return class="kw">false;
     }
  class="type">uint id = class="num">10 + cSSM.Size();
  if(!cStat.Init(class="num">0, id, OpenCL, class="num">6, class="num">6, class="num">12, iVariables * (units_count + forecast), optimization, iBatch))
     class="kw">return class="kw">false;
  id++;
  if(!cTranspStat.Init(class="num">0, id, OpenCL, iVariables * (units_count + forecast), class="num">12, optimization, iBatch))
     class="kw">return class="kw">false;
  id++;
  if(!cVAE.Init(class="num">0, id, OpenCL, cTranspStat.Neurons() / class="num">2, optimization, iBatch))
     class="kw">return class="kw">false;
  id++;
  if(!cTranspVAE.Init(class="num">0, id, OpenCL, cVAE.Neurons() / iVariables, iVariables, optimization, iBatch))
     class="kw">return class="kw">false;
  id++;
  class="type">uint w = cTranspVAE.Neurons() / iVariables;
  if(!cDecoder[class="num">0].Init(class="num">0, id, OpenCL, w, w, class="num">2 * (units_count + forecast), iVariables, optimization, iBatch))
     class="kw">return class="kw">false;
  cDecoder[class="num">0].SetActivationFunction(LReLU);
  id++;
  if(!cDecoder[class="num">1].Init(class="num">0, id, OpenCL, class="num">2 * (units_count + forecast), class="num">2 * (units_count + forecast),
(units_count + forecast), iVariables, optimization, iBatch))
     class="kw">return class="kw">false;
  cDecoder[class="num">1].SetActivationFunction(TANH);
  id++;
  if(!cTranspResult.Init(class="num">0, id, OpenCL, iVariables, (units_count + forecast), optimization, iBatch))
     class="kw">return class="kw">false;
  if(!SetOutput(cTranspResult.getOutput(), true) ||
     !SetGradient(cTranspResult.getGradient(), true))
     class="kw">return class="kw">false;
  SetActivationFunction((ENUM_ACTIVATION)cDecoder[class="num">1].Activation());
class=class="str">"cmt">//---
  class="kw">return true;
  }
class="type">bool CNeuronUniTraj::feedForward(CNeuronBaseOCL *NeuronOCL, CBufferFloat *SecondInput)
  {
  if(!NeuronOCL)
     class="kw">return class="kw">false;
class=class="str">"cmt">//--- Create History Mask
  class="type">int total = cHistoryMask.Total();
  if(!cHistoryMask.BufferInit(total, class="num">1))
     class="kw">return class="kw">false;
  if(bTrain)
     {
       for(class="type">int i = class="num">0; i < class="type">int(total * fDropout); i++)
         cHistoryMask.Update(RND(total), class="num">0);
     }
  if(!cHistoryMask.BufferWrite())

◍ Transformer 推理链路的逐层前向穿透

这段片段展示了一个混合架构(Encoder + BTS 双向投影 + SSM + VAE + Decoder)在单次前向传播时的调用顺序。任何一层 FeedForward 返回 false 都会直接中断并返回 false,意味着实盘加载模型时只要缓冲区初始化或某一子网络推理失败,整个预测就废了。 先看 Future Mask 的构建:total 取掩码对象的总长度,BufferInit 的第二个参数由 SecondInput 决定填 0 或 1;训练态且存在 SecondInput 时,会按 fDropout 比例随机将掩码置 0(循环次数为 int(total * fDropout)),这是典型的 dropout 正则。 接着 Encoder 吃位置编码 cPE 的输出,BTS 模块分别计算前向/后向投影并做 ElementMult 与 Concat(拼接维度参数写死为 3 和 3,第三维取 cData.Neurons()/3)。SSM 是链式堆叠:第 0 层吃拼接结果,后续每层吃上一层的 AsObject(),循环上限用 cSSM.Size() 控制。 VAE 支路从最后一层 SSM 输出经 cStat、cTranspStat 压缩再展开,Decoder 对称地做转置与两层还原,最终 cTranspResult 输出。整条链路无异常兜底,调试时建议先在 MT5 策略测试器里单步看哪一层先返回 false。外汇与贵金属杠杆高,模型信号仅作概率参考,不能直接当仓位依据。

MQL5 / C++
   class="kw">return class="kw">false;
class=class="str">"cmt">//--- Create Future Mask
   total = cFutureMask.Total();
   if(!cFutureMask.BufferInit(total, (!SecondInput ? class="num">0 : class="num">1)))
      class="kw">return class="kw">false;
   if(bTrain && !!SecondInput)
     {
      for(class="type">int i = class="num">0; i < class="type">int(total * fDropout); i++)
         cFutureMask.Update(RND(total), class="num">0);
     }
   if(!cFutureMask.BufferWrite())
      class="kw">return class="kw">false;
class=class="str">"cmt">//--- Prepare Data
   if(!Prepare(NeuronOCL.getOutput(), SecondInput))
      class="kw">return class="kw">false;
class=class="str">"cmt">//--- Encoder
   if(!cPE.FeedForward(cData.AsObject()))
      class="kw">return class="kw">false;
   if(!cEncoder.FeedForward(cPE.AsObject()))
      class="kw">return class="kw">false;
class=class="str">"cmt">//--- BTS
   if(!BTS())
      class="kw">return class="kw">false;
   if(!cProjDForw.FeedForward(cDForw.AsObject()))
      class="kw">return class="kw">false;
   if(!cProjDBakw.FeedForward(cDBakw.AsObject()))
      class="kw">return class="kw">false;
   if(!ElementMult(cEncoder.getOutput(), cProjDForw.getOutput(), cDataDForw.getOutput()))
      class="kw">return class="kw">false;
   if(!ElementMult(cEncoder.getOutput(), cProjDBakw.getOutput(), cDataDBakw.getOutput()))
      class="kw">return class="kw">false;
   if(!Concat(cDataDForw.getOutput(), cDataDBakw.getOutput(), cConcatDataDForwBakw.getOutput(),
               class="num">3, class="num">3, cData.Neurons() / class="num">3))
      class="kw">return class="kw">false;
class=class="str">"cmt">//--- SSM
   if(!cSSM[class="num">0].FeedForward(cConcatDataDForwBakw.AsObject()))
      class="kw">return class="kw">false;
   for(class="type">uint i = class="num">1; i < cSSM.Size(); i++)
      if(!cSSM[i].FeedForward(cSSM[i - class="num">1].AsObject()))
         class="kw">return class="kw">false;
class=class="str">"cmt">//--- VAE
   if(!cStat.FeedForward(cSSM[cSSM.Size() - class="num">1].AsObject()))
      class="kw">return class="kw">false;
   if(!cTranspStat.FeedForward(cStat.AsObject()))
      class="kw">return class="kw">false;
   if(!cVAE.FeedForward(cTranspStat.AsObject()))
      class="kw">return class="kw">false;
class=class="str">"cmt">//--- Decoder
   if(!cTranspVAE.FeedForward(cVAE.AsObject()))
      class="kw">return class="kw">false;
   if(!cDecoder[class="num">0].FeedForward(cTranspVAE.AsObject()))
      class="kw">return class="kw">false;
   if(!cDecoder[class="num">1].FeedForward(cDecoder[class="num">0].AsObject()))
      class="kw">return class="kw">false;
   if(!cTranspResult.FeedForward(cDecoder[class="num">1].AsObject()))
      class="kw">return class="kw">false;
class=class="str">"cmt">//---
   class="kw">return true;
   }
class="type">bool CreateEncoderDescriptions(CArrayObj *&encoder)
   {
class=class="str">"cmt">//---
   CLayerDescription *descr;
class=class="str">"cmt">//---
   if(!encoder)
     {

编码器四层堆叠的写法

在 MT5 里搭一个价格序列自编码器,核心是把各层描述依次塞进 CArrayObj 容器。下面这段直接可贴进 EA 的初始化函数,跑不通就返回 false,方便你立刻在编译器里排错。 输入层用 defNeuronBaseOCL,节点数等于 HistoryBars * BarDescr,优化器选 ADAM、激活留 None,相当于把原始 K 线特征原样接进网络。 第二层接 defNeuronBatchNormOCL 做批归一化,batch 设 1e4,能缓解外汇小时线均值漂移带来的训练抖动;第三层 defNeuronUniTrajOCL 才是重点,window=BarDescr、window_out=EmbeddingSize、count=HistoryBars,step=4 相当于 4 个注意力头,probability=0.5 是 DropOut 比例,调小可能更不容易过拟合但收敛偏慢。 后两层分别用 defNeuronRevInDenormOCL 做反归一化、defNeuronFreDFOCL 做频域变换,后者 probability=0.7f 丢弃概率偏高,贵金属跳空段训练时建议先降到 0.5 观察 loss 曲线。外汇与贵金属杠杆高,参数乱调可能引发实盘大幅回撤,任何层结构改动先在策略测试器跑历史样本。

MQL5 / C++
encoder = new CArrayObj();
if(!encoder)
   class="kw">return class="kw">false;
class=class="str">"cmt">//--- Encoder
  encoder.Clear();
class=class="str">"cmt">//--- Input layer
  if(!(descr = new CLayerDescription()))
   class="kw">return class="kw">false;
  descr.type = defNeuronBaseOCL;
  class="type">int prev_count = descr.count = (HistoryBars * BarDescr);
  descr.activation = None;
  descr.optimization = ADAM;
  if(!encoder.Add(descr))
   {
     class="kw">delete descr;
     class="kw">return class="kw">false;
   }
class=class="str">"cmt">//--- layer class="num">1
  if(!(descr = new CLayerDescription()))
   class="kw">return class="kw">false;
  descr.type = defNeuronBatchNormOCL;
  descr.count = prev_count;
  descr.batch = class="num">1e4;
  descr.activation = None;
  descr.optimization = ADAM;
  if(!encoder.Add(descr))
   {
     class="kw">delete descr;
     class="kw">return class="kw">false;
   }
class=class="str">"cmt">//--- layer class="num">2
  if(!(descr = new CLayerDescription()))
   class="kw">return class="kw">false;
  descr.type = defNeuronUniTrajOCL;
  descr.window = BarDescr;                 class=class="str">"cmt">//window
  descr.window_out = EmbeddingSize;        class=class="str">"cmt">//Inside Dimension
  descr.count = HistoryBars;               class=class="str">"cmt">//Units
  descr.layers = NForecast;                class=class="str">"cmt">//Forecast
  descr.step=class="num">4;                            class=class="str">"cmt">//Heads
  descr.probability=class="num">0.5f;                  class=class="str">"cmt">//DropOut
  descr.batch = class="num">1e4;
  descr.activation = None;
  descr.optimization = ADAM;
  if(!encoder.Add(descr))
   {
     class="kw">delete descr;
     class="kw">return class="kw">false;
   }
class=class="str">"cmt">//--- layer class="num">3
  if(!(descr = new CLayerDescription()))
   class="kw">return class="kw">false;
  descr.type = defNeuronRevInDenormOCL;
  descr.count = BarDescr * (NForecast+HistoryBars);
  descr.activation = None;
  descr.optimization = ADAM;
  descr.layers = class="num">1;
  if(!encoder.Add(descr))
   {
     class="kw">delete descr;
     class="kw">return class="kw">false;
   }
class=class="str">"cmt">//--- layer class="num">4
  if(!(descr = new CLayerDescription()))
   class="kw">return class="kw">false;
  descr.type = defNeuronFreDFOCL;
  descr.window = BarDescr;
  descr.count =  NForecast+HistoryBars;
  descr.step = class="type">int(true);
  descr.probability = class="num">0.7f;
  descr.activation = None;
  descr.optimization = ADAM;
  if(!encoder.Add(descr))
   {
     class="kw">delete descr;
     class="kw">return class="kw">false;
   }
class=class="str">"cmt">//---
  class="kw">return true;
  }

「训练循环里的状态编码与截断校验」

编码器维度对不上是这类预测模型最常见的初始化坑。代码里先用 Encoder.getResults(Result) 把输出拉出来,再拿 Result.Total() 和 (NForecast+HistoryBars)*BarDescr 比:若两者不等,直接 PrintFormat 报错并返回 INIT_FAILED,说明你喂给编码器的状态帧数和预期轨迹长度没对齐,EA 起不来。 Train() 函数里真正跑训练时,用 Batch=1000 做小批量迭代,Iterations 控制总轮数。start 位置用 MathRand() 的平方分布来偏向前段样本,避开尾部不足 NForecast 的残缺窗口;当 i 超出 Buffer 有效长度减 NForecast 时直接 break,防止越界读状态。 状态编码有 50% 概率走 feedForward 正向传播(MathRand()/32767.0 < 0.5),另 50% 把目标 Result 写回缓冲再喂编码器。若 feedForward 返回 false,置 Stop=true 并跳出,训练中止。外汇与贵金属行情下用这套逻辑做状态预测,模型过拟合和样本偏差风险偏高,参数最好在 MT5 策略测试器里用真实点差重跑验证。

MQL5 / C++
  Encoder.getResults(Result);
  if(Result.Total() != (NForecast+HistoryBars) * BarDescr)
    {
      PrintFormat("The scope of the Encoder does not match the forecast state count(%d <> %d)",
(NForecast+HistoryBars) * BarDescr, Result.Total());
      class="kw">return INIT_FAILED;
    }
class="type">void Train(class="type">void)
  {
class=class="str">"cmt">//---
   vector<class="type">class="kw">float> probability = GetProbTrajectories(Buffer, class="num">0.9);
   vector<class="type">class="kw">float> result, target, state;
   class="type">bool Stop = class="kw">false;
   const class="type">int Batch = class="num">1000;
   class="type">int b = class="num">0;
class=class="str">"cmt">//---
   class="type">uint ticks = GetTickCount();
   for(class="type">int iter = class="num">0; (iter < Iterations && !IsStopped() && !Stop); iter += b)
     {
       class="type">int tr = SampleTrajectory(probability);
       class="type">int start = (class="type">int)((MathRand() * MathRand() / MathPow(class="num">32767, class="num">2)) * (Buffer[tr].Total - class="num">5 - NForecast));
       if(start <= class="num">0)
         class="kw">continue;
       for(b = class="num">0; (b < Batch && (iter + b) < Iterations); b++)
         {
          class="type">int i = start + b;
          if(i >= MathMin(Buffer[tr].Total, Buffer_Size) - NForecast)
            break;
          state.Assign(Buffer[tr].States[i].state);
          if(MathAbs(state).Sum() == class="num">0)
            break;
          bState.AssignArray(state);
          class=class="str">"cmt">//--- Collect target data
          if(!Result.AssignArray(Buffer[tr].States[i + NForecast].state))
            class="kw">continue;
          if(!Result.Resize(BarDescr * NForecast))
            class="kw">continue;
          class=class="str">"cmt">//--- State Encoder
          if((MathRand() / class="num">32767.0) < class="num">0.5)
            {
             if(!Encoder.feedForward((CBufferFloat*)GetPointer(bState), class="num">1, class="kw">false, (CBufferFloat*)NULL))
               {
                PrintFormat("%s -> %d", __FUNCTION__, __LINE__);
                Stop = true;
                break;
               }
            }
          else
            {
             if(Result.GetIndex()>=class="num">0)
             Result.BufferWrite();
             if(!Encoder.feedForward((CBufferFloat*)GetPointer(bState), class="num">1, class="kw">false, Result))
把多体轨迹诊断交给小布
这些蒙版轨迹与双向时态依赖的诊断,小布盯盘的AIGC已内置,打开对应品种页即可看到不同可见区域的生成推演,你只管判断概率倾向。

常见问题

M为[N,T]矩阵,m_i,t=1表示个体i在时刻t状态已知,归为X_v;为0则进入X_m作为生成目标,统一格式避免了任务专用模型切换。
它们多只考虑前向依赖,忽略后向时空约束,而规划后续动作需要双向扫描,UniTraj用双向时态编码器缓解该限制。
可以,小布盯盘品种页内置了AIGC走势诊断,能将不完整报价序列按蒙版拆区并给出双向生成预览,省去本地搭模型。
GSM嵌入编码层,对多体空间关系做掩码感知,使模型在不规则可见区域下仍建模空间交互,不依赖完整轨迹输入。
BTS做序列全扫且保时态序,Mamba改编为双向时态编码器生成长程轨迹,二者互补,前者稳关系后者抓长依赖。