📘

神经符号系统在 MT5 里的落点

◍ 神经符号系统在 MT5 里的落点

神经符号化系统把可解释的符号规则(如突破前高入场)和神经网络的概率拟合放在一起,试图兼顾逻辑可控与行情适应。在 MT5 环境里,这类架构通常以外接 Python 推理 + MQL5 信号接收的方式跑,纯 MQL5 难以承载反向传播。 原文作者在 2025-10-31 发布的这一节被查看 635 次、评论 2 条,说明社区对「规则+网络」混合范式关注但落地案例少。想验证可行性,可先在 MT5 用 iCustom 接收外部特征,再对照神经网络输出的置信度做过滤。 外汇与贵金属杠杆高、滑点跳空频繁,神经符号系统给出的信号仍只是概率倾向,实盘前必须用历史样本做walk-forward验证。

规则当骨架,神经网络当肌肉

做算法交易的人大多卡在一个两难里:纯规则系统(头肩、双底这类形态硬编码进 EA)在震荡和变节行情里误报多得让人怀疑人生;纯神经网络(比如 LSTM 喂历史价)预测准度能看,但决策路径黑箱,一笔错单就是实打实的点差加滑点亏损。外汇和贵金属这类高杠杆品种,黑箱失控的代价尤其刺眼。 破局思路不是二选一,而是分层:用经典形态规则搭出系统的‘骨架’,保证逻辑可解释、可回测;再把神经网络当作‘肌肉’,只负责感知当前市场状态并做自适应权重调整。相当于一个熟手交易员,既背得下教科书形态,也懂得看流动性微调手感。 这种神经符号化结构在 MT5 生态里可以直接落地验证——把规则部分写成 MQL5 指标或 EA 框架,神经网络推理放 Python 端通过套接字回传信号。接下来几节会拆开架构和实测数据,你可以先想清楚自己最常用哪三个形态值得写成硬规则。

「把形态压成 0 和 1 再谈统计」

程序化视角下,图表形态不再是“双底”“旗形”这类视觉图例,而是一串二进制价格变动序列:1 代表该根 K 线收涨,0 代表收跌。比如 [1,1,0,1,0] 就是一段编码后的小趋势,可以直接丢进数组做模式匹配。 对每种形态,至少该算三个量:频率(历史出现次数)、胜率(出现后价格按预期方向移动的比例)、可靠性(综合前两者的惩罚型指标)。我实盘统计过 EURUSD H4 上的 [1,1,1,0,0],胜率 68%,年发生超 200 次——数字好看,但拿去跑前先想清楚是不是过度拟合的产物。 形态长度本身也是参数。3–4 根太短噪声炸裂,20–25 根虽稳却稀罕;我常用 5–8 根找平衡,个别品种 12 根也出过不错结果。预测窗口用 forecast_horizon 控制,回测里取前 6 根做特征对准确率和信号量最划算。 同一形态在波动率切换、亚盘美盘时段表现可能完全劈叉,所以裸统计只是门票。跨市场状态的行为差异,才逼出后面接神经网络的需要。

MQL5 / C++
pattern = tuple(np.where(data[&class="macro">#x27;close&class="macro">#x27;].diff() > class="num">0, class="num">1, class="num">0))
reliability = frequency * winrate * (class="num">1 - abs(class="num">0.5 - winrate))

◍ LSTM 加全连接:混合网怎么喂行情

系统的决策核心是一套混合神经网络:LSTM 层吃时间序列,全连接层吃形态统计特征。市场不是独立采样点,每个报价都带着前一根的惯性,LSTM 抓长期依赖比普通前馈网更稳。 Dropout 是防过拟合的硬屏障。早期没加这层时,模型在回测里零误差,实盘直接崩。训练时随机掐掉一部分神经元(第一层 0.4、第二层 0.3),逼网络学更粗粒度的形态而不是死记历史。 输入张量形状由三件事定:分析窗口 10 个时间步、基础特征(价格/量/指标)、形态提取特征数。拼出来是 (batch_size, 10, features),正好对上首层 LSTM 的胃口。首层 return_sequences=True 会把每一步的输出都吐给第二层,让它看全时间动态;二层只给最终状态,再进 Dense。 两个 Dense 层里,ReLU 那层解非线性,sigmoid 末层输出上涨概率。编译用 Adam 优化器加二元交叉熵,指标挂了 accuracy、precision、recall——既能看方向对不对,也能拆误报和漏报。外汇和贵金属波动非平稳、杠杆高风险,这套概率输出只作倾向参考,别当确定性信号。 我们也试过塞 CNN 找局部形态、上注意力机制,结论偏保守:网越复杂越难解释它为什么开仓,而交易里搞不懂逻辑就等于裸奔。简单透明比花哨重要。

MQL5 / C++
model = tf.keras.Sequential([
    tf.keras.layers.LSTM(class="num">256, input_shape=input_shape, return_sequences=True),
    tf.keras.layers.Dropout(class="num">0.4),
    tf.keras.layers.LSTM(class="num">128),
    tf.keras.layers.Dropout(class="num">0.3),
    tf.keras.layers.Dense(class="num">64, activation=&class="macro">#x27;relu&class="macro">#x27;),
    tf.keras.layers.Dense(class="num">1, activation=&class="macro">#x27;sigmoid&class="macro">#x27;)
])
model.compile(
    optimizer=&class="macro">#x27;adam&class="macro">#x27;,
    loss=&class="macro">#x27;binary_crossentropy&class="macro">#x27;,
    metrics=[&class="macro">#x27;accuracy&class="macro">#x27;, tf.keras.metrics.Precision(), tf.keras.metrics.Recall()]
)

把形态统计塞进神经网络的输入层

把经典图表形态接进神经网络,不是简单把信号拼到特征后面,而要先做一套预处理:每个时间点上构造多维向量,基础面放价格、成交量、RSI、MACD、布林带上下轨,再叠一层形态统计。 形态统计里最值得盯的是 reliability(可靠性)。它的算法不是只看胜率和次数,还乘了 (1 - abs(0.5 - 胜率均值)) 这一项——胜率越贴近 100% 或越贴近随机,这个值越被压低,能过滤掉统计上“太干净”的可疑样本。 不同形态长度不一样,直接喂网络会维度飘忽。代码里用 features_per_length=5 把每种形态都压成固定 5 维,总特征数 = 形态种类数 × 5,网络输入维度就恒定了。 市场背景单独成组:ATR 算波动、ADX 算趋势强度、再判市场阶段。高波动时系统倾向调高对形态可靠性的门槛,这是适应工况的一层保险。 多周期实盘常遇缺数。价格用前向填充,成交量用 24 根滚动均值补,形态特征 nan 直接转 -1,保证送进网络的矩阵不中断。外汇与贵金属杠杆高、跳空频繁,缺数处理不当会直接污染训练集。 下面这段是可直接拷去改的 Python 风格骨架(MQL5 端通常用 CSeries 或自定义缓冲实现同样逻辑):

MQL5 / C++
base_features = [
    &class="macro">#x27;close&class="macro">#x27;,   # Close price 
    &class="macro">#x27;volume&class="macro">#x27;,  # Volume
    &class="macro">#x27;rsi&class="macro">#x27;,     # Relative Strength Index
    &class="macro">#x27;macd&class="macro">#x27;,    # MACD
    &class="macro">#x27;bb_upper&class="macro">#x27;, &class="macro">#x27;bb_lower&class="macro">#x27;   # Bollinger Bands borders
]
pattern_stats = {
    &class="macro">#x27;winrate&class="macro">#x27;: np.mean(outcomes),   # Percentage of successful triggers
    &class="macro">#x27;frequency&class="macro">#x27;: len(outcomes),     # Occurrence frequency
    &class="macro">#x27;reliability&class="macro">#x27;: len(outcomes) * np.mean(outcomes) * (class="num">1 - abs(class="num">0.5 - np.mean(outcomes)))   # Reliability
}
def prepare_data(df):
    # We normalize the basic features using MinMaxScaler
    X_base = self.scaler.fit_transform(df[base_features].values)
    
    # For pattern statistics we use special normalization
    pattern_features = self.pattern_analyzer.extract_pattern_features(
        df, lookback=len(df)
    )
    
    class="kw">return np.column_stack((X_base, pattern_features))
def extract_pattern_features(self, data, lookback=class="num">100):
    features_per_length = class="num">5   # fixed number of features per pattern
    total_features = len(self.pattern_lengths) * features_per_length
    
    features = np.zeros((len(data) - lookback, total_features))
    # ... filling the feature array
market_features = {
    &class="macro">#x27;volatility&class="macro">#x27;: calculate_atr(data),   # Volatility via ATR
    &class="macro">#x27;trend_strength&class="macro">#x27;: calculate_adx(data),   # Trend strength via ADX
    &class="macro">#x27;market_phase&class="macro">#x27;: identify_market_phase(data)   # Market phase
}
# Fill in the blanks, taking into account the specifics of each feature
df[&class="macro">#x27;close&class="macro">#x27;] = df[&class="macro">#x27;close&class="macro">#x27;].fillna(method=&class="macro">#x27;ffill&class="macro">#x27;)   # for prices
df[&class="macro">#x27;volume&class="macro">#x27;] = df[&class="macro">#x27;volume&class="macro">#x27;].fillna(df[&class="macro">#x27;volume&class="macro">#x27;].rolling(class="num">24).mean())   # for volumes
pattern_features = np.nan_to_num(pattern_features, nan=-class="num">1)   # for pattern features

「信号如何落地成一张单」

把神经网络和形态识别拆开看,决策端其实只回答两个问题:现在能不能做,做多少。上游给的两路数据——模型输出的涨跌概率、形态统计的历史偏好——在这里被压缩成一条带置信度的指令。 第一道闸是市场状态过滤。交易时段之外直接弃权;点差超过 MAX_ALLOWED_SPREAD 不进场;ATR 突破 volatility_threshold 也退避。这是纯常识层,不依赖任何预测。 第二道是信号一致性。系统不要求全票通过,只要求形态里至少 60% 确认模型方向(ml_prediction > 0.5 算多头基准)。未达阈值就返回 None,不交易。

置信度用加权合成:base_confidence 取prediction - 0.5* 2,把 0.5 附近的模糊预测压到 0;再叠 30% 的形态历史表现权重,合成公式 0.7*base + 0.3*pattern。仓位大小由 confidence 反推。外汇与贵金属杠杆高,点差和波动突变频繁,这套过滤在流动性差的时段可能直接把所有信号掐掉。

下面这段 Python 伪代码就是决策函数的骨架,MT5 上用 MQL5 重写时,predict 换成 iCustom 取模型输出、pattern_analyzer 换成形态指标缓存即可。

MQL5 / C++
def get_trading_decision(self, market_data):
    # Get a forecast from the neural network
    prediction = self.model.predict(market_data)
    
    # Extract active patterns
    patterns = self.pattern_analyzer.get_active_patterns(market_data)
    
    # Basic check of market conditions
    if not self._market_conditions_ok():
        class="kw">return None  # Do not trade if something is wrong
        
    # Check the consistency of signals
    if not self._signals_aligned(prediction, patterns):
        class="kw">return None  # No consensus - no deal
        
    # Calculate the signal confidence
    confidence = self._calculate_confidence(prediction, patterns)
    
    # Determine the position size
    size = self._get_position_size(confidence)
    
    class="kw">return TradingSignal(
        direction=&class="macro">#x27;BUY&class="macro">#x27; if prediction > class="num">0.5 else &class="macro">#x27;SELL&class="macro">#x27;,
        size=size,
        confidence=confidence,
        patterns=patterns
    )

def _market_conditions_ok(self):
    # Check the time
    if not self.is_trading_session():
        class="kw">return False
        
    # Look at the spread
    if self.current_spread > self.MAX_ALLOWED_SPREAD:
        class="kw">return False
        
    # Check volatility
    if self.current_atr > self.volatility_threshold:
        class="kw">return False
    
    class="kw">return True

def _signals_aligned(self, ml_prediction, pattern_signals):
    # Define the basic direction
    ml_direction = ml_prediction > class="num">0.5
    
    # Count how many patterns confirm it
    confirming_patterns = sum(class="num">1 for p in pattern_signals 
                                    if p.predicted_direction == ml_direction)
    
    # At least class="num">60% of patterns need to be confirmed
    class="kw">return confirming_patterns / len(pattern_signals) >= class="num">0.6

def _calculate_confidence(self, prediction, patterns):
    # Baseline confidence from ML model
    base_confidence = abs(prediction - class="num">0.5) * class="num">2
    
    # Consider confirming patterns
    pattern_confidence = self._get_pattern_confidence(patterns)
    
    # Weighted average with empirically selected ratios
    class="kw">return (base_confidence * class="num">0.7 + pattern_confidence * class="num">0.3)

◍ 把这条线请下神坛

把经典形态和神经网络拼在一起,得到的不是点石成金的圣杯,而是一种更稳的定性框架:网络负责抓那些说不清的微妙市场关系,形态提供决策的基本骨架。我们在内部回测里看到,这种组合比纯技术分析、或单跑机器学习,结果更一致,但优势来自结构清晰,不是来自堆复杂度。 刻意的简单和可解释才是这条线的真正护城河。我们没上更复杂的架构,系统透明到能随时看懂每一步,市场一变就能手动改规则,这种掌控感在人人追复杂的圈子里反而成了竞争优势。 外汇和贵金属这类高杠杆品种,用这套思路也得认清:没有灵丹妙药,只有持续改工具这一条路。拿去在 MT5 接 Python 验证可以,但别把它当终极答案供着。

常见问题

可以。用规则先框定突破形态的有效性,再把形态编码为0/1特征喂给网络做概率过滤,实盘前先在历史数据回测假突破占比再调阈值。
先用价格行为规则定义形态边界,例如吞没形态需实体覆盖前根2/3以上,满足则标1否则0,再用统计确认该标记在历史样本中的分布偏度。
小布可自动把你看的品种按规则提取形态并编码,调用内置混合网给出概率信号,你只需在品种页核对输出与风控参数。
偏日内可试30~60根收盘序列,外层全连接接形态0/1向量;用滚动窗口验证不同长度下信号衰减点再固定。
概率仅代表倾向,外汇贵金属高风险,建议等下一根K线收盘价站上形态边界且风控位明确后再入场。