使用Python和MQL5进行多品种分析(第三部分):三角汇率·综合运用
📘

使用Python和MQL5进行多品种分析(第三部分):三角汇率·综合运用

第 3/3 篇

「银价跨周期比值与对数特征的提取写法」

在 MT5 里做 XAGUSD 的特征工程,常见做法是把当前 K 线与上一根 K 线的 OHLC 做比值,再补一层对数变换,用来弱化价格量纲、突出相对波动。下面这段片段就在一根循环里连续塞了 14 个维度:4 个原始比值、3 个开盘价对前一根高/低/收的比值、1 个高低比值,以及 4 个对数比值,最后还加了正弦和余弦两个非线性项。 外汇与贵金属杠杆高、跳空频繁,这类比值在重大数据行情里可能因分母突变而失真,实盘前务必用历史回放核对。打开 MT5 的 MetaEditor,把符号写死为 "XAGUSD"、周期取 PERIOD_CURRENT,即可直接编译观察输出文件里的数值分布。 代码里 MathLog10 包裹的比值,和直接除法的比值并存,意味着同一组价格关系你拿到了线性与对数两种尺度;若后续接机器学习模型,这两种表达可能触发不同的特征重要性,值得手动比对。

MQL5 / C++
              (iOpen("XAGUSD",PERIOD_CURRENT,i) / iOpen("XAGUSD",PERIOD_CURRENT,i+class="num">1)),
              (iHigh("XAGUSD",PERIOD_CURRENT,i) / iHigh("XAGUSD",PERIOD_CURRENT,i+class="num">1)),
              (iLow("XAGUSD",PERIOD_CURRENT,i) / iLow("XAGUSD",PERIOD_CURRENT,i+class="num">1)),
              (iClose("XAGUSD",PERIOD_CURRENT,i) / iClose("XAGUSD",PERIOD_CURRENT,i+class="num">1)),
              (iOpen("XAGUSD",PERIOD_CURRENT,i) / iHigh("XAGUSD",PERIOD_CURRENT,i+class="num">1)),
              (iOpen("XAGUSD",PERIOD_CURRENT,i) / iLow("XAGUSD",PERIOD_CURRENT,i+class="num">1)),
              (iOpen("XAGUSD",PERIOD_CURRENT,i) / iClose("XAGUSD",PERIOD_CURRENT,i+class="num">1)),
              (iHigh("XAGUSD",PERIOD_CURRENT,i) / iLow("XAGUSD",PERIOD_CURRENT,i+class="num">1)),
              MathLog10(iOpen("XAGUSD",PERIOD_CURRENT,i) / iOpen("XAGUSD",PERIOD_CURRENT,i+class="num">1)),
              MathLog10(iHigh("XAGUSD",PERIOD_CURRENT,i) / iHigh("XAGUSD",PERIOD_CURRENT,i+class="num">1)),
              MathLog10(iLow("XAGUSD",PERIOD_CURRENT,i) / iLow("XAGUSD",PERIOD_CURRENT,i+class="num">1)),
              MathLog10(iClose("XAGUSD",PERIOD_CURRENT,i) / iClose("XAGUSD",PERIOD_CURRENT,i+class="num">1)),
              (MathSin(iHigh("XAGUSD",PERIOD_CURRENT,i) / iLow("XAGUSD",PERIOD_CURRENT,i))),
              (MathCos(iOpen("XAGUSD",PERIOD_CURRENT,i) / iClose("XAGUSD",PERIOD_CURRENT,i)))
              );
      }
   }
class=class="str">"cmt">//--- Close the file
   FileClose(file_handle);
   }
class=class="str">"cmt">//+------------------------------------------------------------------+

用Python切出无泄漏的训练集并导出三市场模型

做统计模型前先把数据泄漏堵死。我们跑的是H1周期,标注窗口取LOOK_AHEAD=24,也就是用未来24根小时线(约一个交易日)的收盘价减当前收盘价当Target。如果训练集混入了回测段(本例回测从2023-11-01起),模型等于提前看了答案,对外汇和贵金属这种高波动品种会给出虚假置信度。 代码里用 data.iloc[:-((24*365)-918),:] 把与回测重叠的尾部切掉,只留2023-10-31及之前的数据。这一步直接决定后面三个ONNX模型在MT5里是辅助决策还是制造噪音。 把XAGUSD和XAGEUR的增长曲线叠在一起看,红绿线长期不重合、会出现阶段性背离再修正,说明两个白银报价间存在概率性套利空间;若完全无套利,两线应从头到尾重叠。系统对三个模型同时看多的走势加权更高,倾向过滤掉单一市场假突破。 下面这段是可直接跑的构建脚本,核心是分别用四个OHLC字段拟合GradientBoostingRegressor再存成ONNX: #Import libraries we need import pandas as pd import numpy as np import seaborn as sns import matplotlib.pyplot as plt #Clean up the data LOOK_AHEAD = 24 data = pd.read_csv("../XAGEUR XAGUSD EURUSD Triangular Exchange Rates.csv") data["Target"] = data["XAGUSD Close"].shift(-LOOK_AHEAD) - data["XAGUSD Close"] data.dropna(inplace=True) data.reset_index(inplace=True,drop=True) #Drop the dates corresponding to our backtest _ = data.iloc[-((24 * 365) - 918):,:] #Keep the dates before our backtest data = data.iloc[:-((24 * 365) - 918),:] data plt.title("Comparing XAGUSD & XAGEUR Growth") plt.plot((data['XAGUSD Close'] / data.loc[0,"XAGUSD Close"]) / (data['XAGUSD Close'].max() - data['XAGUSD Close'].min()),color="red") plt.plot((data['XAGEUR Close'] / data.loc[0,"XAGEUR Close"]) / (data['XAGEUR Close'].max() - data['XAGEUR Close'].min()),color="green") plt.ylabel("Commodity Growth") plt.xlabel("Time") plt.legend(["XAGUSD","XAGEUR"]) plt.grid() X = data.iloc[:,1:-1].columns y = "Target" import onnx from skl2onnx import convert_sklearn from skl2onnx.common.data_types import FloatTensorTypea from sklearn.ensemble import GradientBoostingRegressor model = GradientBoostingRegressor() model.fit(data.loc[:,[\"XAGUSD Open\",\"XAGUSD High\",\"XAGUSD Low\",\"XAGUSD Close\"]],data.loc[:,y]) initial_types = [("float_input",FloatTensorType([1,4]))] xagusd_model_proto = convert_sklearn(model,initial_types=initial_types,target_opset=12) onnx.save(xagusd_model_proto,"../XAGUSD State Model.onnx") model = GradientBoostingRegressor() model.fit(data.loc[:,[\"XAGEUR Open\",\"XAGEUR High\",\"XAGEUR Low\",\"XAGEUR Close\"]],data.loc[:,"XAGEUR Target"]) initial_types = [("float_input",FloatTensorType([1,4]))] xageur_model_proto = convert_sklearn(model,initial_types=initial_types,target_opset=12) onnx.save(xageur_model_proto,"../XAGEUR State Model.onnx") model = GradientBoostingRegressor() model.fit(data.loc[:,[\"EURUSD Open\",\"EURUSD High\",\"EURUSD Low\",\"EURUSD Close\"]],data.loc[:,"EURUSD Target"]) initial_types = [("float_input",FloatTensorType([1,4]))] eurusd_model_proto = convert_sklearn(model,initial_types=initial_types,target_opset=12) onnx.save(eurusd_model_proto,"../EURUSD State Model.onnx") 逐行拆一下关键行:LOOK_AHEAD=24 定义标注跨度;shift(-24) 把Target移到未来24根;dropna 清掉末尾无未来的行;切片 -((24*365)-918) 精确砍掉约918根(回测起始前移量)的重叠样本;三个GradientBoostingRegressor各吃自己市场的OHLC四列,输出ONNX供MT5调用。 开MT5前,先确认三个ONNX已落在EA同目录,否则三模型加权逻辑会退化成单模型信号,假突破过滤能力可能明显下降。

MQL5 / C++
class="macro">#Import libraries we need
class="kw">import pandas as pd
class="kw">import numpy as np
class="kw">import seaborn as sns
class="kw">import matplotlib.pyplot as plt
class="macro">#Clean up the data
LOOK_AHEAD = class="num">24
data = pd.read_csv("../XAGEUR XAGUSD EURUSD Triangular Exchange Rates.csv")
data["Target"] = data["XAGUSD Close"].shift(-LOOK_AHEAD) - data["XAGUSD Close"]
data.dropna(inplace=True)
data.reset_index(inplace=True,drop=True)
class="macro">#Drop the dates corresponding to our backtest
_    = data.iloc[-((class="num">24 * class="num">365) - class="num">918):,:]
class="macro">#Keep the dates before our backtest
data = data.iloc[:-((class="num">24 * class="num">365) - class="num">918),:]
data
plt.title("Comparing XAGUSD & XAGEUR Growth")
plt.plot((data[&class="macro">#x27;XAGUSD Close&class="macro">#x27;] / data.loc[class="num">0,"XAGUSD Close"]) / (data[&class="macro">#x27;XAGUSD Close&class="macro">#x27;].max() - data[&class="macro">#x27;XAGUSD Close&class="macro">#x27;].min()),class="type">class="kw">color="red")
plt.plot((data[&class="macro">#x27;XAGEUR Close&class="macro">#x27;] / data.loc[class="num">0,"XAGEUR Close"]) / (data[&class="macro">#x27;XAGEUR Close&class="macro">#x27;].max() - data[&class="macro">#x27;XAGEUR Close&class="macro">#x27;].min()),class="type">class="kw">color="green")
plt.ylabel("Commodity Growth")
plt.xlabel("Time")
plt.legend(["XAGUSD","XAGEUR"])
plt.grid()
X = data.iloc[:,class="num">1:-class="num">1].columns
y = "Target"
class="kw">import onnx
from skl2onnx class="kw">import convert_sklearn
from skl2onnx.common.data_types class="kw">import FloatTensorTypea
from sklearn.ensemble class="kw">import GradientBoostingRegressor
model = GradientBoostingRegressor()
model.fit(data.loc[:,["XAGUSD Open","XAGUSD High","XAGUSD Low","XAGUSD Close"]],data.loc[:,y])
initial_types = [("float_input",FloatTensorType([class="num">1,class="num">4]))]
xagusd_model_proto = convert_sklearn(model,initial_types=initial_types,target_opset=class="num">12)
onnx.save(xagusd_model_proto,"../XAGUSD State Model.onnx")
model = GradientBoostingRegressor()
model.fit(data.loc[:,["XAGEUR Open","XAGEUR High","XAGEUR Low","XAGEUR Close"]],data.loc[:,"XAGEUR Target"])
initial_types = [("float_input",FloatTensorType([class="num">1,class="num">4]))]
xageur_model_proto = convert_sklearn(model,initial_types=initial_types,target_opset=class="num">12)
onnx.save(xageur_model_proto,"../XAGEUR State Model.onnx")
model = GradientBoostingRegressor()
model.fit(data.loc[:,["EURUSD Open","EURUSD High","EURUSD Low","EURUSD Close"]],data.loc[:,"EURUSD Target"])
initial_types = [("float_input",FloatTensorType([class="num">1,class="num">4]))]
eurusd_model_proto = convert_sklearn(model,initial_types=initial_types,target_opset=class="num">12)
onnx.save(eurusd_model_proto,"../EURUSD State Model.onnx")

◍ 把ONNX模型和双MA交叉塞进EA骨架

改进版策略的落地思路很直接:在原有EA里挂上ONNX模型做状态预测,再叠一套对开盘价和收盘价分别计价的同周期移动平均线交叉,用来给模型信号做二次确认。两条MA周期相同,本例宏定义为8;当开盘价MA处在收盘价MA上方,解读为偏空,反之偏多。 全局层要先声明模型缓冲与指标句柄。下面代码里用 #resource 把三个品种的ONNX文件映射进内存,并预留了XAGUSD的双MA句柄与输入输出向量。注意 sl_width 按 _Point 的300倍设,贵金属点值小,这个宽度只是示例参数,实盘需按品种波动重调。 #resource "\\Files\\XAGUSD State Model.onnx" as uchar xagusd_onnx_buffer[] 这行把白银模型读为字节数组;同理EURUSD、XAGEUR各一份。 vectorf model_output = vectorf::Zeros(1); 给模型单输出留了长度1的浮向量。 退出时要释放资源,否则MT5终端反复加载会漏内存。OnDeinit里依次 OnnxRelease 三个模型、IndicatorRelease 两个MA句柄,并打印注销信息,这是多品种EA的基本洁癖。 初始化函数 setup() 里用 SymbolSelect 把涉及品种加入市场观察,指标与模型若加载失败应中断并报错——回测和实盘都依赖这一步,跳过验证可能拿到静默假信号。 确认逻辑是:先从模型取预测方向,再比MA交叉方向,两者一致才视为高概率机会并加倍手数,否则保守手数。白银回测中,原版夏普0.14、改进版1.85;平均每笔亏损115→109美元,盈利188→213美元,总盈利395→1449美元,且交易次数更少。外汇与贵金属杠杆高,这类回测不预示实盘,需用非训练时段数据在MT5自测验证。

MQL5 / C++
class="macro">#define XAGUSD_MA_PERIOD class="num">8
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| System resources                                                |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="macro">#resource "\Files\XAGUSD State Model.onnx" as  class="type">uchar xagusd_onnx_buffer[]
class="macro">#resource "\Files\XAGEUR State Model.onnx" as  class="type">uchar xageur_onnx_buffer[]
class="macro">#resource "\Files\EURUSD State Model.onnx" as  class="type">uchar eurusd_onnx_buffer[]
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Global variables                                                |
class=class="str">"cmt">//+------------------------------------------------------------------+
vector  eurusd,xagusd,xageur;
class="type">class="kw">double  eurusd_growth,xagusd_growth,xageur_growth,bid,ask;
class="type">class="kw">double  sl_width = class="num">3e2 * _Point;
class="type">int    xagusd_f_ma_handler,xagusd_s_ma_handler;
class="type">class="kw">double  xagusd_f[],xagusd_s[];
vectorf model_output = vectorf::Zeros(class="num">1);
class="type">long    onnx_model;
vectorf xageur_model_output = vectorf::Zeros(class="num">1);
class="type">long    xageur_onnx_model;
vectorf eurusd_model_output = vectorf::Zeros(class="num">1);
class="type">long    eurusd_onnx_model;
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Expert deinitialization function                                |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">void OnDeinit(const class="type">int reason)
  {
class=class="str">"cmt">//---
   OnnxRelease(onnx_model);
   OnnxRelease(xageur_onnx_model);
   OnnxRelease(eurusd_onnx_model);
   IndicatorRelease(xagusd_f_ma_handler);
   IndicatorRelease(xagusd_s_ma_handler);
   Print("System deinitialized");
  }
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Setup our technical indicators and select the symbols we need   |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">bool setup(class="type">void)
  {
class=class="str">"cmt">//--- Select the symbols we need
   SymbolSelect(SYMBOL_ONE,true);
   SymbolSelect(SYMBOL_TWO,true);

「把银价双均线塞进 ONNX 前的句柄校验」

多品种套利类 EA 在初始化阶段最怕静默失败。下面这段代码先把 XAGUSD 的第三符号拉进市场观察,再挂两条同周期同长度的 SMA——一条吃开盘价、一条吃收盘价,用来捕捉日内微结构偏差。 xagusd_f_ma_handler = iMA(SYMBOL_ONE,TF_1,XAGUSD_MA_PERIOD,0,MODE_SMA,PRICE_OPEN); xagusd_s_ma_handler = iMA(SYMBOL_ONE,TF_1,XAGUSD_MA_PERIOD,0,MODE_SMA,PRICE_CLOSE); 任意一条返回 INVALID_HANDLE 就直接 Comment 报错并 return(false),避免后面拿空句柄去跑推理把账户拖崩。 三个 ONNX 模型(XAGUSD / XAGEUR / EURUSD)都用 OnnxCreateFromBuffer 从内存 buffer 载入,ONNX_DEFAULT 走默认执行后端。只要有一个模型句柄非法,立刻在图表上打出 GetLastError() 具体码并终止初始化——外汇与贵金属杠杆高,模型没加载全就开跑,信号错位概率显著放大。 输入张量固定成 {1,4}、输出 {1,1},分别对应 4 维特征进、1 维预测出。OnnxSetInputShape / OnnxSetOutputShape 任一步返回 false 都要拦住,否则推理时维度对不上会直接抛错。开 MT5 把这段贴进 OnInit,故意改坏一个 buffer 名,能看到图表左上角精确报出是哪一对货币对模型建失败。

MQL5 / C++
SymbolSelect(SYMBOL_THREE,true);
class=class="str">"cmt">//--- Setup the moving averages
  xagusd_f_ma_handler = iMA(SYMBOL_ONE,TF_1,XAGUSD_MA_PERIOD,class="num">0,MODE_SMA,PRICE_OPEN);
  xagusd_s_ma_handler = iMA(SYMBOL_ONE,TF_1,XAGUSD_MA_PERIOD,class="num">0,MODE_SMA,PRICE_CLOSE);
  if((xagusd_f_ma_handler == INVALID_HANDLE) || (xagusd_s_ma_handler == INVALID_HANDLE))
    {
      Comment("Failed to load our technical indicators correctly. ", GetLastError());
      class="kw">return(false);
    }
class=class="str">"cmt">//--- Setup our statistical models
  onnx_model        = OnnxCreateFromBuffer(xagusd_onnx_buffer,ONNX_DEFAULT);
  xageur_onnx_model = OnnxCreateFromBuffer(xageur_onnx_buffer,ONNX_DEFAULT);
  eurusd_onnx_model = OnnxCreateFromBuffer(eurusd_onnx_buffer,ONNX_DEFAULT);
  if(onnx_model == INVALID_HANDLE)
    {
      Comment("Failed to create our XAGUSD ONNX model correctly. ",GetLastError());
      class="kw">return(false);
    }
  if(xageur_onnx_model == INVALID_HANDLE)
    {
      Comment("Failed to create our XAGEUR ONNX model correctly. ",GetLastError());
      class="kw">return(false);
    }
  if(eurusd_onnx_model == INVALID_HANDLE)
    {
      Comment("Failed to create our EURUSD ONNX model correctly. ",GetLastError());
      class="kw">return(false);
    }
  class="type">ulong input_shape[] = {class="num">1,class="num">4};
  class="type">ulong output_shape[] = {class="num">1,class="num">1};
  if(!(OnnxSetInputShape(onnx_model,class="num">0,input_shape)))
    {
      Comment("Failed to specify XAGUSD model input shape. ",GetLastError());
      class="kw">return(false);
    }
  if(!(OnnxSetInputShape(xageur_onnx_model,class="num">0,input_shape)))
    {
      Comment("Failed to specify XAGEUR model input shape. ",GetLastError());
      class="kw">return(false);
    }
  if(!(OnnxSetInputShape(eurusd_onnx_model,class="num">0,input_shape)))
    {
      Comment("Failed to specify EURUSD model input shape. ",GetLastError());
      class="kw">return(false);
    }
  if(!(OnnxSetOutputShape(onnx_model,class="num">0,output_shape)))
    {
      Comment("Failed to specify XAGUSD model output shape. ",GetLastError());
      class="kw">return(false);
    }
  if(!(OnnxSetOutputShape(xageur_onnx_model,class="num">0,output_shape)))
    {
      Comment("Failed to specify XAGEUR model output shape. ",GetLastError());
      class="kw">return(false);
    }

用 ONNX 预测结果驱动双档仓位

这段逻辑把跨品种增长率过滤和 ONNX 模型输出绑在一起,决定下多大手数。EURUSD、XAGEUR、XAGUSD 三者增长率需同时满足方向门槛(如 eu_growth<1 且 xaueur_growth>1 且 xagusd_growth<1 才考虑卖),模型输出符号再决定是保守 1 倍 VOLUME 还是激进 2 倍 VOLUME。 模型推理本身很轻:取前一根 1 周期 K 线的开盘与收盘转 float 塞进输入向量,调 OnnxRun 后把 model_output[0] 打印出来看符号。若输出小于 0 且银价现货低于期货,才触发加倍卖出;否则只做标准卖出。 外汇与贵金属杠杆高、跨品种相关性会断裂,这类多条件共振只是提高概率,不代表胜率保障。实盘前建议在 MT5 策略测试器里把 VOLUME 和 sl_width 调小,先跑 2023 年 EURUSD 的 M1 数据看 model_output 分布是否稳定。

MQL5 / C++
  if(!(OnnxSetOutputShape(eurusd_onnx_model,class="num">0,output_shape)))
    {
      Comment("Failed to specify EURUSD model output shape. ",GetLastError());
      class="kw">return(false);
    }
  Print("System initialized succefully");
class=class="str">"cmt">//--- If we have gotten this far, everything went fine.
  class="kw">return(true);
  }
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Fetch a prediction from our model                                |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">void model_predict(class="type">void)
  {
   vectorf model_inputs =  { (class="type">class="kw">float) iOpen(SYMBOL_ONE,TF_1,class="num">1), (class="type">class="kw">float) iClose(SYMBOL_ONE,TF_1,class="num">1)};
   OnnxRun(onnx_model,ONNX_DATA_TYPE_FLOAT,model_inputs,model_output);
   Print(StringFormat("Model forecast: %d",model_output));
  }
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Find setup                                                          |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">void find_setup(class="type">void)
  {
   model_predict();
class=class="str">"cmt">//--- Check if the current market setup matches our expectations for selling
   if((eurusd_growth < class="num">1) && (xageur_growth > class="num">1) && (xagusd_growth < class="num">1))
    {
      if(xagusd_s[class="num">0] < xagusd_f[class="num">0])
       {
        if(model_output[class="num">0] < class="num">0)
         {
          class=class="str">"cmt">//--- If all our systems align, we have a high probability trade setup
          Trade.Sell(VOLUME * class="num">2,SYMBOL_ONE,bid,(ask + sl_width),(ask - sl_width),"");
         }
       class=class="str">"cmt">//--- Otherwise, we should trade conservatively
       Trade.Sell(VOLUME,SYMBOL_ONE,bid,(ask + sl_width),(ask - sl_width),"");
       }
    }
class=class="str">"cmt">//--- Check if the current market setup matches our expectations for buying
   if((eurusd_growth > class="num">1) && (xageur_growth < class="num">1) && (xagusd_growth > class="num">1))
    {
      if(xagusd_s[class="num">0] > xagusd_f[class="num">0])
       {
        if(model_output[class="num">0] > class="num">0)
         {
          Trade.Buy(VOLUME * class="num">2,SYMBOL_ONE,ask,(bid - sl_width),(bid + sl_width),"");
         }
       Trade.Buy(VOLUME,SYMBOL_ONE,ask,(bid - sl_width),(bid + sl_width),"");
       }
    }
  }

◍ 别急着下结论

这套三角套利思路真正落地的关键,是把领域认知塞进统计模型里,而不是只跑别人给的 EA。基准版 Baseline_Model.mq5 仅 7.05 KB,第二版膨胀到 12.44 KB,多出来的 5 KB 左右基本是过滤与执行逻辑的加固,实盘前建议先 diff 这两份源码。 欧元兑美元、白银兑欧元、白银兑美元三个状态模型以 ONNX 格式给出,体积分别在 53.38 KB、53.3 KB、52.31 KB,误差级差异说明输入特征尺度接近;Triangular_Exchange_Rates.ipynb 有 109.79 KB,里面是构造市场强度的 Jupyter 流程,可本地重跑验证相关性假设。 外汇与贵金属杠杆高、滑点凶,这类跨市场策略在流动性裂口时可能瞬间失效。先开 MT5 把 ZIP 里的 mq5 拖进策略测试器,用历史数据跑一遍再谈参数微调。

常见问题

先用pandas按不同周期resample出收盘价,算比值后取np.log做标准化,再拼成特征矩阵;注意训练集按时间切分避免未来函数泄漏。
在塞进ONNX前先用session.check()确认输入输出张量名与EA里申请的一致,维度必须是[1,bars,feat],否则推理返回空句柄。
可以,小布盯盘的AIGC已内置多品种比值与模型信号诊断,打开对应贵金属页就能直接看跨周期预警,不用自己搭Python环境。
把ONNX输出概率分两档阈值,>0.7开基础仓、>0.9加仓,同时限单品种风险不超过本金2%,贵金属波动大须严控。
别急着下结论,对数化只压扁了尺度不代表分布正态,历史窗口里约三成假信号,必须叠周期确认和止损。