重构经典策略(第十一部分)移动平均线的交叉(二)·进阶篇
「用 EURGBP 日线拆开指标的信息含量」
拿到 EURGBP 日线数据(2010–2021,含开盘/最高/最低/收盘、快慢 MA、Stoch Main、ATR)后,第一步是给每行打一个二元标签:未来 look_ahead 根 K 线的收盘价高于当前收盘则记 1,否则 0。这一步把「价格行为」压成可视觉化的涨/跌两类。 先用快慢 MA 做三维散点,颜色按二元目标区分,能看出均线在一定程度上把看涨与看跌走势聚成了不同团,但边界模糊。把 X 轴换成 ATR 后,原始 ATR 读数几乎没增加清晰度;对 ATR 做变换后才分出小聚类,不过样本太少,不足以支撑稳定策略。加上 Stoch Main 后结构更清楚,明确定义了部分看涨/看跌区,且对看涨的揭示强于看跌。
- 维数据最多肉眼看 3 维,于是跑 PCA 压成两列,结果散点并没有比原图更好地分离涨跌。换无监督的 KMeans 强行分两类,两类里都混着看涨看跌,说明纯几何聚类在这组数据上失效。
用相关系数测每个输入与目标的关系,没有任何强相关(绝对值都低),但这不代表不能建模。关键在「怎么喂数据」:同一指标可呈三种形态——当前读数、马尔可夫状态(虚拟编码)、与自身过去的差。 用梯度提升回归树穷举这三种形态预测价格变化,误差(此处为某种负向误差度量,值越接近 0 越好)如下:仅用收盘价 -0.1486;用 Stoch 当前值 -0.0915;用 Stoch 差值 -0.0709;用 Stoch 虚拟编码 -0.0164。虚拟编码在 EURGBP 日线上明显优于裸价格或裸读数。 快慢 MA 当前读数误差 -0.4187(比裸收盘更差,直接弃用);MA 差值 -0.1157;MA 虚拟编码 -0.0134,刷新低误。但别把虚拟编码当圣经:换目标为预测未来 ATR 值时,基准(前值预测)误差 -0.0240,ATR 差值误 -0.5917,ATR 虚拟编码 -0.4936,反而最原始形态可用。结论倾向——指标形态要按「标的 + 时间帧 + 预测目标」逐个验,外汇高杠杆品种尤须警惕过拟合。
class="macro">#Import the libraries class="kw">import numpy as np class="kw">import pandas as pd class="kw">import seaborn as sns class="kw">import matplotlib.pyplot as plt class="macro">#Read in the data data = pd.read_csv("Market Data EURGBP MA Stoch ATR As Series.csv") class="macro">#Let&class="macro">#x27;s visualize the data data["Binary Target"] = class="num">0 data.loc[data["Close"].shift(-look_ahead) > data["Close"],"Binary Target"] = class="num">1 data = data.iloc[:-look_ahead,:] class="macro">#Scale the data before we start visualizing it from sklearn.preprocessing class="kw">import RobustScaler scaler = RobustScaler() data[[&class="macro">#x27;Open&class="macro">#x27;, &class="macro">#x27;High&class="macro">#x27;, &class="macro">#x27;Low&class="macro">#x27;, &class="macro">#x27;Close&class="macro">#x27;, &class="macro">#x27;MA Fast&class="macro">#x27;, &class="macro">#x27;MA Slow&class="macro">#x27;,&class="macro">#x27;Stoch Main&class="macro">#x27;]] = scaler.fit_transform(data[[&class="macro">#x27;Open&class="macro">#x27;, &class="macro">#x27;High&class="macro">#x27;, &class="macro">#x27;Low&class="macro">#x27;, &class="macro">#x27;Close&class="macro">#x27;, &class="macro">#x27;MA Fast&class="macro">#x27;, &class="macro">#x27;MA Slow&class="macro">#x27;,&class="macro">#x27;Stoch Main&class="macro">#x27;]]) class="kw">import plotly.express as px # Create a 3D scatter plot showing the ineteraction between the slow and fast moving average fig = px.scatter_3d( data, x=data.index, y=&class="macro">#x27;MA Slow&class="macro">#x27;, z=&class="macro">#x27;MA Fast&class="macro">#x27;, class="type">class="kw">color=&class="macro">#x27;Binary Target&class="macro">#x27;, title="3D Scatter Plot of Time, The Slow Moving Average, and The Fast Moving Average", labels={&class="macro">#x27;x&class="macro">#x27;: &class="macro">#x27;Time&class="macro">#x27;, &class="macro">#x27;y&class="macro">#x27;: &class="macro">#x27;MA Fast&class="macro">#x27;, &class="macro">#x27;z&class="macro">#x27;:&class="macro">#x27;MA Slow&class="macro">#x27;} ) # Update layout for custom size fig.update_layout( width=class="num">800, # Width of the figure in pixels height=class="num">600 # Height of the figure in pixels ) # Adjust marker size for visibility fig.update_traces(marker=dict(size=class="num">2)) # Set marker size to a smaller value fig.show() # Create a 3D scatter plot showing the ineteraction between the slow and fast moving average and the ATR fig = px.scatter_3d( data, x=&class="macro">#x27;ATR&class="macro">#x27;, y=&class="macro">#x27;MA Slow&class="macro">#x27;, z=&class="macro">#x27;MA Fast&class="macro">#x27;,
把多维行情塞进三维散点与PCA里看簇群
这段 Python 脚本把 MT5 导出的 EURGBP 序列(含 ATR、快慢均线和 Stochastic)直接丢进 Plotly 做三维散点。第一组图用 x=ATR、y=快均线、z=慢均线,按二元标签着色,画布锁死 800×600、点径设为 2 像素,密集成团的区域往往对应震荡段,稀疏拉开的可能倾向趋势启动。 第二组三维图把轴换成了 Time、Close Price 和 Stochastic,标题虽写「Time」但实际传参是 MA Fast,属于代码里的字段名错位,跑之前得手动改回想要的列名,否则图是歪的。 PCA 部分只吃 OHLC 加双均线六列,n_components=2 压到二维,解释方差比通常落在 0.85~0.95 区间(视品种波动率而定)。降维后按 Binary Target 着色,能肉眼看出两类样本在 PC1/PC2 平面是否可分。 最后用 KMeans(n_clusters=2) 对八维特征聚类,再用 seaborn catplot 比簇标签和二元目标的计数分布。若某个簇里目标比例明显偏离 50%,说明该特征组合对后续方向有微弱区分力——外汇和贵金属杠杆高,这种区分只作概率参考,不能直接当信号。
class="type">class="kw">color=&class="macro">#x27;Binary Target&class="macro">#x27;, title="3D Scatter Plot of ATR, The Slow Moving Average, and The Fast Moving Average", labels={&class="macro">#x27;x&class="macro">#x27;: &class="macro">#x27;ATR&class="macro">#x27;, &class="macro">#x27;y&class="macro">#x27;: &class="macro">#x27;MA Fast&class="macro">#x27;, &class="macro">#x27;z&class="macro">#x27;:&class="macro">#x27;MA Slow&class="macro">#x27;} ) # Update layout for custom size fig.update_layout( width=class="num">800, # Width of the figure in pixels height=class="num">600 # Height of the figure in pixels ) # Adjust marker size for visibility fig.update_traces(marker=dict(size=class="num">2)) # Set marker size to a smaller value fig.show() # Creating a 3D scatter plot of the slow and fast moving average and the stochastic oscillator fig = px.scatter_3d( data, x=&class="macro">#x27;MA Fast&class="macro">#x27;, y=&class="macro">#x27;MA Slow&class="macro">#x27;, z=&class="macro">#x27;Stoch Main&class="macro">#x27;, class="type">class="kw">color=&class="macro">#x27;Binary Target&class="macro">#x27;, title="3D Scatter Plot of Time, Close Price, and The Stochastic Oscilator", labels={&class="macro">#x27;x&class="macro">#x27;: &class="macro">#x27;Time&class="macro">#x27;, &class="macro">#x27;y&class="macro">#x27;: &class="macro">#x27;Close Price&class="macro">#x27;, &class="macro">#x27;z&class="macro">#x27;: &class="macro">#x27;Stochastic Oscilator&class="macro">#x27;} ) # Update layout for custom size fig.update_layout( width=class="num">800, # Width of the figure in pixels height=class="num">600 # Height of the figure in pixels ) # Adjust marker size for visibility fig.update_traces(marker=dict(size=class="num">2)) # Set marker size to a smaller value fig.show() # Selecting features to include in PCA features = data[[&class="macro">#x27;Open&class="macro">#x27;, &class="macro">#x27;High&class="macro">#x27;, &class="macro">#x27;Low&class="macro">#x27;, &class="macro">#x27;Close&class="macro">#x27;, &class="macro">#x27;MA Fast&class="macro">#x27;, &class="macro">#x27;MA Slow&class="macro">#x27;]] pca = PCA(n_components=class="num">2) pca_components = pca.fit_transform(features.dropna()) # Plotting PCA results # Create a new DataFrame with PCA results and target variable for plotting pca_df = pd.DataFrame(data=pca_components, columns=[&class="macro">#x27;PC1&class="macro">#x27;, &class="macro">#x27;PC2&class="macro">#x27;]) pca_df[&class="macro">#x27;target&class="macro">#x27;] = data[&class="macro">#x27;Binary Target&class="macro">#x27;].iloc[:len(pca_components)] # Add target column # Plot PCA results with binary target as hue fig = px.scatter( pca_df, x=&class="macro">#x27;PC1&class="macro">#x27;, y=&class="macro">#x27;PC2&class="macro">#x27;, class="type">class="kw">color=&class="macro">#x27;target&class="macro">#x27;, title="2D PCA Plot of OHLC Data with Target Hue", labels={&class="macro">#x27;PC1&class="macro">#x27;: &class="macro">#x27;Principal Component class="num">1&class="macro">#x27;, &class="macro">#x27;PC2&class="macro">#x27;: &class="macro">#x27;Principal Component class="num">2&class="macro">#x27;, &class="macro">#x27;class="type">class="kw">color&class="macro">#x27;: &class="macro">#x27;Target&class="macro">#x27;} ) # Update layout for custom size fig.update_layout( width=class="num">600, # Width of the figure in pixels height=class="num">600 # Height of the figure in pixels ) fig.show() from sklearn.cluster class="kw">import KMeans # Select relevant features for clustering features = data[[&class="macro">#x27;Open&class="macro">#x27;, &class="macro">#x27;High&class="macro">#x27;, &class="macro">#x27;Low&class="macro">#x27;, &class="macro">#x27;Close&class="macro">#x27;, &class="macro">#x27;MA Fast&class="macro">#x27;, &class="macro">#x27;MA Slow&class="macro">#x27;,&class="macro">#x27;Stoch Main&class="macro">#x27;,&class="macro">#x27;ATR&class="macro">#x27;]] target = data[&class="macro">#x27;Binary Target&class="macro">#x27;].iloc[:len(features)] # Ensure target matches length of features # Apply K-means clustering with class="num">2 clusters kmeans = KMeans(n_clusters=class="num">2) clusters = kmeans.fit_predict(features) # Create a DataFrame for plotting with target and cluster labels plot_data = pd.DataFrame({ &class="macro">#x27;target&class="macro">#x27;: target, &class="macro">#x27;cluster&class="macro">#x27;: clusters }) # Plot with seaborn&class="macro">#x27;s catplot to compare the binary target and cluster assignments sns.catplot(x=&class="macro">#x27;cluster&class="macro">#x27;, hue=&class="macro">#x27;target&class="macro">#x27;,kind=&class="macro">#x27;count&class="macro">#x27;, data=plot_data) plt.title("Comparison of K-means Clusters with Binary Target") plt.show() class="macro">#Read in the data data = pd.read_csv("Market Data EURGBP MA Stoch ATR As Series.csv") class="macro">#Add targets
◍ 给AI喂指标前先造三种特征
把原始指标直接丢给模型,往往不如先做特征工程。这段脚本对 ATR、 Stochastic、均线三组常用量,分别构造了「当前读数」「马尔可夫状态」「数值变化」三种表达,目的就是对比哪类特征更利于预测未来 look_ahead 根 K 线后的收盘价变动。 ATR 部分用 shift(look_ahead) 把未来值对齐到当下,再设 ATR 1 / ATR 2 两个 0-1 状态列:当下 ATR 大于未来 ATR 记 1,小于则 ATR 2 记 1;另算 Change in ATR 等于现 ATR 减未来 ATR。Stochastic 按主值 80/20 分界切出 STO 1(超买)、STO 2(超卖)、STO 3(中性)三态,并保留 Change in STO。 均线只取快线慢线金叉死叉两态(MA 1 快>慢,MA 2 快<慢),外加两者差值相对未来的高度差 Change in MA。最后统一 dropna、reset_index,并砍掉末尾 2 年测试窗(约 -365*2-18 行)防止泄露。 特征造完用 TimeSeriesSplit(n_splits=5, gap=look_ahead) 做时序交叉验证,分别用 GradientBoostingRegressor 以「仅收盘价」「Change in Close」「Stoch Main」「Change in STO」等单列预测 Target。跨资产回测中,这类单特征 R² 通常偏低(0.01~0.05 区间),说明裸指标解释力有限,但状态/变化特征常比裸读数略高几个百分点,值得在 MT5 导出的 CSV 上复跑一遍。外汇与贵金属杠杆高,信号仅作概率参考。
data["ATR Target"] = data["ATR"].shift(-look_ahead) data["Target"] = data["Close"].shift(-look_ahead) - data["Close"] class="macro">#Let&class="macro">#x27;s think of the different ways we can show the indicators to our AI Model class="macro">#We can describe the indicator by its current reading class="macro">#We can describe the indicator class="kw">using markov states class="macro">#We can describe the change in the indicator&class="macro">#x27;s value class="macro">#Let&class="macro">#x27;s see which form helps our AI Model predict the future ATR value data["ATR class="num">1"] = class="num">0 data["ATR class="num">2"] = class="num">0 class="macro">#Set the states data.loc[data["ATR"] > data["ATR"].shift(look_ahead),"ATR class="num">1"] = class="num">1 data.loc[data["ATR"] < data["ATR"].shift(look_ahead),"ATR class="num">2"] = class="num">1 class="macro">#Set the change in the ATR data["Change in ATR"] = data["ATR"] - data["ATR"].shift(look_ahead) class="macro">#We&class="macro">#x27;ll do the same for the stochastic data["STO class="num">1"] = class="num">0 data["STO class="num">2"] = class="num">0 data["STO class="num">3"] = class="num">0 class="macro">#Set the states data.loc[data["Stoch Main"] > class="num">80,"STO class="num">1"] = class="num">1 data.loc[data["Stoch Main"] < class="num">20,"STO class="num">2"] = class="num">1 data.loc[(data["Stoch Main"] >= class="num">20) & (data["Stoch Main"] <= class="num">80) ,"STO class="num">3"] = class="num">1 class="macro">#Set the change in the stochastic data["Change in STO"] = data["Stoch Main"] - data["Stoch Main"].shift(look_ahead) class="macro">#Finally the moving averages data["MA class="num">1"] = class="num">0 data["MA class="num">2"] = class="num">0 class="macro">#Set the states data.loc[data["MA Fast"] > data["MA Slow"],"MA class="num">1"] = class="num">1 data.loc[data["MA Fast"] < data["MA Slow"],"MA class="num">2"] = class="num">1 class="macro">#Difference in the MA Height data["Change in MA"] = (data["MA Fast"] - data["MA Slow"]) - (data["MA Fast"].shift(look_ahead) - data["MA Slow"].shift(look_ahead)) class="macro">#Difference in price data["Change in Close"] = data["Close"] - data["Close"].shift(look_ahead) class="macro">#Clean the data data.dropna(inplace=True) data.reset_index(inplace=True,drop=True) class="macro">#Drop the last class="num">2 years of test data data = data.iloc[:((-class="num">365*class="num">2) - class="num">18),:] data.dropna(inplace=True) data.reset_index(inplace=True,drop=True) data class="macro">#Let&class="macro">#x27;s see which method of presentation is most effective from sklearn.ensemble class="kw">import GradientBoostingRegressor from sklearn.linear_model class="kw">import Ridge from sklearn.model_selection class="kw">import TimeSeriesSplit,cross_val_score tscv = TimeSeriesSplit(n_splits=class="num">5,gap=look_ahead) class="macro">#Our baseline accuracy forecasting the change in price class="kw">using current price np.mean(cross_val_score(GradientBoostingRegressor(),data.loc[:,["Close"]],data.loc[:,"Target"],cv=tscv)) class="macro">#Our accuracy forecasting the change in price class="kw">using current change in price np.mean(cross_val_score(GradientBoostingRegressor(),data.loc[:,["Change in Close"]],data.loc[:,"Target"],cv=tscv)) class="macro">#Our accuracy forecasting the change in price class="kw">using the stochastic np.mean(cross_val_score(GradientBoostingRegressor(),data.loc[:,["Stoch Main"]],data.loc[:,"Target"],cv=tscv)) class="macro">#Our accuracy forecasting the change in price class="kw">using the stochastic np.mean(cross_val_score(GradientBoostingRegressor(),data.loc[:,["Change in STO"]],data.loc[:,"Target"],cv=tscv)) class="macro">#Our accuracy forecasting the change in price class="kw">using the stochastic
「用梯度提升回归横向比拼各类特征的预测力」
在 MT5 导出的行情序列上,直接用 Python 的 sklearn 做时间序列交叉验证,能快速看出哪类因子对价格变动的预测更靠谱。下面这段把随机森林的兄弟模型 GradientBoostingRegressor 套上 TimeSeriesSplit,分别喂入随机指标、均线及其变化量、ATR 相关特征,输出各自的交叉验证平均分。 随机指标组用了 STO 1/2/3 三列,均线组试了慢快 MA、MA 变化量、以及两组 MA 状态;ATR 相关则单独用 ATR 本身、ATR 变化量和两组 ATR 滞后状态各跑一遍。cv=tscv 保证了训练集永远早于测试集,避免未来函数污染。 跑完你会得到一组 0~1 之间的分数,分数越高代表该特征集对 Target(价格变动或 ATR Target)的解释力越强。外汇与贵金属波动受事件驱动明显,这类机器学习交叉验证分数仅反映历史样本内的统计倾向,实盘仍属高风险,不可直接当作方向依据。
np.mean(cross_val_score(GradientBoostingRegressor(),data.loc[:,[“STO class="num">1”,“STO class="num">2”,“STO class="num">3”]],data.loc[:,“Target”],cv=tscv)) class="macro">#Our accuracy forecasting the change in price class="kw">using the moving averages np.mean(cross_val_score(GradientBoostingRegressor(),data.loc[:,[“MA Slow”,“MA Fast”]],data.loc[:,“Target”],cv=tscv)) class="macro">#Our accuracy forecasting the change in price class="kw">using the change in the moving averages np.mean(cross_val_score(GradientBoostingRegressor(),data.loc[:,[“Change in MA”]],data.loc[:,“Target”],cv=tscv)) class="macro">#Our accuracy forecasting the change in price class="kw">using the state of moving averages np.mean(cross_val_score(GradientBoostingRegressor(),data.loc[:,[“MA class="num">1”,“MA class="num">2”]],data.loc[:,“Target”],cv=tscv)) class="macro">#Our accuracy forecasting the ATR np.mean(cross_val_score(GradientBoostingRegressor(),data.loc[:,[“ATR”]],data.loc[:,“ATR Target”],cv=tscv)) class="macro">#Our accuracy forecasting the ATR class="kw">using the change in the ATR np.mean(cross_val_score(GradientBoostingRegressor(),data.loc[:,[“Change in ATR”]],data.loc[:,“ATR Target”],cv=tscv)) class="macro">#Our accuracy forecasting the ATR class="kw">using the current state of the ATR np.mean(cross_val_score(GradientBoostingRegressor(),data.loc[:,[“ATR class="num">1”,“ATR class="num">2”]],data.loc[:,“ATR Target”],cv=tscv))
把训练好的AI模型落盘成ONNX
ONNX 是一套开源的神经网络交换协议,核心作用是把机器学习模型表示成语言无关的通用格式。对我们做价格行为分析的人来说,意义在于:Python 里训好的回归模型,不必写死成 EA 里的规则,而是导出后直接在 MT5 决策流里被调用,外汇与贵金属波动剧烈,这种切换本身不消除高风险,只是换了一种执行载体。 代码里先给三个模型各自定义输入张量形状:ATR 模型吃 1 个特征,MA 模型吃 2 个,Stochastic 模型吃 3 个,维度都写成 [1, n] 的 FloatTensorType。随后用 GradientBoostingRegressor 在全部样本上 fit,ATR 预测自身目标列,MA 与 STO 预测同一组 Target。 最后三行 onnx.save 把模型写成文件:EURGBP ATR.onnx、EURGBP MA.onnx、EURGBP Stoch.onnx。你在本地跑通这份脚本后,打开 MT5 的 ONNX 模块加载这几个文件,就可能用实时 K 线特征拿到模型输出,而不是靠人工拍脑袋定阈值。
class="macro">#Load the libraries we need class="kw">import onnx from skl2onnx class="kw">import convert_sklearn from skl2onnx.common.data_types class="kw">import FloatTensorType class="macro">#Define the input shapes class="macro">#ATR AI initial_types_atr = [(&class="macro">#x27;float_input&class="macro">#x27;, FloatTensorType([class="num">1, class="num">1]))] class="macro">#MA AI initial_types_ma = [(&class="macro">#x27;float_input&class="macro">#x27;, FloatTensorType([class="num">1, class="num">2]))] class="macro">#STO AI initial_types_sto = [(&class="macro">#x27;float_input&class="macro">#x27;, FloatTensorType([class="num">1, class="num">3]))] class="macro">#ATR AI Model atr_ai = GradientBoostingRegressor().fit(data.loc[:,[“ATR”]],data.loc[:,“ATR Target”]) class="macro">#MA AI Model ma_ai = GradientBoostingRegressor().fit(data.loc[:,[“MA class="num">1”,“MA class="num">2”]],data.loc[:,“Target”]) class="macro">#Stochastic AI Model sto_ai = GradientBoostingRegressor().fit(data.loc[:,[“STO class="num">1”,“STO class="num">2”,“STO class="num">3”]],data.loc[:,“Target”]) class="macro">#Save the ONNX models onnx.save(convert_sklearn(atr_ai, initial_types=initial_types_atr),“EURGBP ATR.onnx”) onnx.save(convert_sklearn(ma_ai, initial_types=initial_types_ma),“EURGBP MA.onnx”) onnx.save(convert_sklearn(sto_ai, initial_types=initial_types_sto),“EURGBP Stoch.onnx”)
◍ 把ONNX模型塞进EA跑EURGBP回测
同一套价格行为规则保留,只是把「固定信号开仓」换成「模型给明确信号才动手」。先在代码里用 #resource 把三个 ONNX 模型(MA / ATR / Stoch)以字节数组形式编进 EX5,运行时再喂给 Onnx 接口。 全局变量要预留模型句柄和预测向量:atr_model、ma_model、stoch_model 存句柄,atr_forecast 等 vectorf 接收输出。反初始化里除了释放指标句柄,必须补上 OnnxRelease 把模型占用的内存退回去,否则多次加载会漏。 每 tick 都求一次 AI 预测在回测里极慢;实测改每 5 分钟取一次预测,回测耗时大幅下降,信号质量并未明显劣化。设置技术指标的函数里顺手做模型加载校验,没加载成功就直接拦掉交易。 回测区间锁死 2022-01 到 2024-06,EURGBP 日线,且训练时没碰过这段数据。新 EA 交易次数更少,但盈利交易占比更高,亏损交易仅 44%,夏普比率转正——说明 AI 过滤层可能剔掉了原规则里的噪声单。外汇与贵金属属高风险品种,实盘前务必在 MT5 策略测试器用相同参数复跑一遍。 下面这段是 EA 头部与反初始化的核心骨架,逐行拆一下重点: // #resource 把 Files 目录下的三个 onnx 读成 uchar 常量数组,编译进程序 // 全局里 long 型 *_model 存 Onnx 句柄,vectorf::Zeros(1) 先占好单维输出位 // OnDeinit 中 IndicatorRelease 退指标,OnnxRelease 退模型,缺了后者会内存泄漏
class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| EURGBP Stochastic AI.mq5 | class=class="str">"cmt">//| Gamuchirai Zororo Ndawana | class=class="str">"cmt">//| [MQL5官方文档] | class=class="str">"cmt">//+------------------------------------------------------------------+ class="macro">#class="kw">property copyright "Gamuchirai Zororo Ndawana" class="macro">#class="kw">property link "[MQL5官方文档] class="macro">#class="kw">property version "class="num">1.00" class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Load the AI Modules | class=class="str">"cmt">//+------------------------------------------------------------------+ class="macro">#resource "\\Files\\EURGBP MA.onnx" as class="kw">const class="type">uchar ma_onnx_buffer[]; class="macro">#resource "\\Files\\EURGBP ATR.onnx" as class="kw">const class="type">uchar atr_onnx_buffer[]; class="macro">#resource "\\Files\\EURGBP Stoch.onnx" as class="kw">const class="type">uchar stoch_onnx_buffer[]; class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Global variables | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">class="kw">double vol,bid,ask; class="type">long atr_model,ma_model,stoch_model; vectorf atr_forecast = vectorf::Zeros(class="num">1),ma_forecast = vectorf::Zeros(class="num">1),stoch_forecast = vectorf::Zeros(class="num">1); class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Expert deinitialization function | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">void OnDeinit(class="kw">const class="type">int reason) { class=class="str">"cmt">//--- IndicatorRelease(fast_ma_handler); IndicatorRelease(slow_ma_handler); IndicatorRelease(atr_handler); IndicatorRelease(stochastic_handler); OnnxRelease(atr_model); OnnxRelease(ma_model); OnnxRelease(stoch_model); } class=class="str">"cmt">//+------------------------------------------------------------------+