分析交易所价格的二进制代码(第一部分):技术分析的新视角(基础篇)
「从二进制层看报价流」
MT5 里每一笔 tick 并非只能从 IndicatorBuffers 里拿收盘价,它底层是二进制事件流。把报价当成连续序列去拟合,往往会漏掉撮合层的跳变噪声。
- 年 9 月 22 日发布的这套思路,在 715 次社区浏览、2 条反馈的样本下,倾向认为:直接解析 tick 二进制比只看 OHLC 更能暴露流动性断层。外汇与贵金属点差跳扩时,这种断层概率显著上升,属高风险观察项。
要验证很简单:开 MT5 自编脚本,用 CopyTicks 抓原始流,别急着算均线,先看相邻 tick 的间隔分布。
把行情当成一段可读的代码流
看比特币那段时间,暴涨暴跌里有些波动组合反复出现,像字母拼成单词一样。这引出一个念头:把价格变动直接编码成二进制序列,也许能读出市场想说的东西。 技术分析本来就在找形态,K线本身也是一种价格波动的编码。市场全天不停吐出数字,本质上就是一条巨大的信息流,只是大多数人只用肉眼扫形态。 这个实验的做法是:从最基础的价格涨跌,到复杂组合形态,全部转成 0/1 序列,再回头找里面重复出现的规律。视角偏门,但外汇和贵金属这类高波动品种上,用 MT5 导出的tick或分钟数据跑一遍,往往能看出肉眼漏掉的频率特征。 打开你的 MT5,随便拉一张 XAUUSD 的 M5 图,把每根K线相较前根的涨跌标成 1 和 0,先攒够 500 根以上,下一步才有得读。
◍ 把涨跌拆成 0 和 1 的原始编码
价格波动本质上只有两种状态:涨或跌、强或弱、过线或不过线。把这种二元判断直接写成 0/1 序列,比画趋势线更接近计算机的底层逻辑。比如连续三根 K 线「涨、跌、涨」,最朴素的编码就是 101,不需要任何指标辅助。 只盯单根 K 线的涨跌太单薄,真正有信息量的是叠加维度:波动幅度够不够大、成交量是否站上均线、价格在 MA 上方还是下方。这些都可以各自变成一位二进制,拼起来就是一段描述该根 K 线的「特征字」。 我在 BTC 的小时图上做过粗筛,单纯用涨跌位生成的序列常出现类似摩尔斯电码的节奏块——连续 3~5 根同向后接一根反向,这种局部形态在波动率放大段出现概率明显偏高。外汇和贵金属波动更碎,直接套用前要明白这类品种高风险、序列噪声更大。 跨周期对照才显威力:同一段 101 在小时图是噪音,放到日线或周线可能是一条完整波段。把它当成数据矩阵的一行,每根 K 线占一列,你就能用 MT5 导出的 CSV 自己跑频次统计。
「把报价流压成 0 和 1 的几种切法」
把 MT5 里的连续报价看成复古游戏的像素点,思路就通了:不画曲线,只问「这段是上还是下、猛还是弱、量厚还是薄」,然后全部编码成 0/1 序列。作者在 BTC/USD 上做实验,因为加密市场没有财报股息,只剩群体心理写进数字里,反而最适合验证这套二进制视角。 接 MT5 后,移动平均线附近出现「101」序列,在比特币高波动段常先于剧烈摆动——像是市场试完水才起跳。ETH/USD 小时图上,「000」低波动序列之后,强烈波动概率提升约 23%,这不算铁律,但值得自己跑一遍。 成交量维度更有意思:BTC/USD 的 4 小时图上,连续三根高量 K 线编码成「111」时,常在重大行情前冒头,像鲸鱼赛前热身。下面这段 Python 把价格窗口哈希成助记词、并接 MT5 取收盘价算 SMA 穿越,可直接抄去改 symbol 验证。 别把正态当圣经 某些二进制组合在强波动前出现频率高于概率论预期,这是经验现象不是印钞机;外汇贵金属杠杆高,验证时先用模拟盘。
def encode_price_movement(self, prices): normalized = ((prices - np.min(prices)) / (np.max(prices) - np.min(prices)) * class="num">255).astype(np.uint8) data = bytes(normalized) entropy = hashlib.sha256(data).digest() mnemonic = self.mnemo.to_mnemonic(entropy) class="kw">return mnemonic def analyze_words_frequency(self, prices): price_diff = np.diff(prices) bullish_mnemonics = [] bearish_mnemonics = [] for i in range(len(price_diff)): window = prices[max(class="num">0, i-class="num">4):i+class="num">1] if len(window) < class="num">5: class="kw">continue mnemonic = self.encode_price_movement(window) if price_diff[i] > class="num">0: bullish_mnemonics.extend(mnemonic.split()) else: bearish_mnemonics.extend(mnemonic.split()) class="kw">import MetaTrader5 as mt5 class="kw">import numpy as np def encode_ma_crossings(symbol, timeframe, ma_period=class="num">20): # Connect to the terminal if not mt5.initialize(): print("MT5 initialization error") class="kw">return None # Get data rates = mt5.copy_rates_from_pos(symbol, timeframe, class="num">0, class="num">1000) prices = np.array([rate[class="num">4] for rate in rates]) # Use Close prices # Calculate SMA and program crossover ma = np.convolve(prices, np.ones(ma_period)/ma_period, mode=&class="macro">#x27;valid&class="macro">#x27;) crossings = prices[ma_period-class="num">1:] > ma mt5.shutdown() class="kw">return np.where(crossings, class="num">1, class="num">0) def encode_momentum(symbol, timeframe, threshold=class="num">0.02): if not mt5.initialize(): class="kw">return None # Load data from MT5 rates = mt5.copy_rates_from_pos(symbol, timeframe, class="num">0, class="num">1000) prices = np.array([rate[class="num">4] for rate in rates]) # Calculate price changes
用 Python 给 MT5 量价打标签
想让 AIGC 模型吃进 MT5 的历史行情,第一步是把原始价格与成交量转成可训练的离散信号。下面这段脚本直接从终端拉取最近 1000 根 K 线,分别编码动量方向与量能高低。 价格变动率用相邻收盘价差分再除以前一价得到,threshold 设多大取决于品种波动特性,黄金 H1 上 0.0015 往往能滤掉噪声。strong_moves 把绝对变动超阈值的标记为 True,momentum 数组里只在这些位置写入正负一,其余留零,相当于给趋势段打方向标签。 成交量维度另算:用长度 20 的均匀卷积核滑出均量线,volumes[19:] 与 avg_volume 逐位比较,高于均量记 1、低于记 0。回测观察,EURUSD M15 在 volume_code 连续 3 根等于 1 且 momentum 同号时,后续 5 根延续原方向的概率偏高,但外汇杠杆品种风险大,信号失效也常见。 两个函数结尾都调 mt5.shutdown() 释放终端连接,避免在 Jupyter 里反复初始化拖慢内核。复制代码前确认已 pip 装好 MetaTrader5 与 numpy,且 MT5 客户端登录了对应账户。
price_changes = np.diff(prices) / prices[:-class="num">1] # Program strong movements strong_moves = np.abs(price_changes) > threshold momentum = np.zeros_like(price_changes) momentum[strong_moves] = np.sign(price_changes[strong_moves]) mt5.shutdown() class="kw">return momentum class="kw">import MetaTrader5 as mt5 class="kw">import numpy as np from class="type">class="kw">datetime class="kw">import class="type">class="kw">datetime def encode_volume_patterns(symbol, timeframe): if not mt5.initialize(): class="kw">return None # Take volume data rates = mt5.copy_rates_from_pos(symbol, timeframe, class="num">0, class="num">1000) volumes = np.array([rate[class="num">5] for rate in rates]) # Calculate average volume for the last class="num">20 bars avg_volume = np.convolve(volumes, np.ones(class="num">20)/class="num">20, mode=&class="macro">#x27;valid&class="macro">#x27;) # Code: class="num">1 for volume above average and class="num">0 - for below volume_code = volumes[class="num">19:] > avg_volume mt5.shutdown() class="kw">return np.where(volume_code, class="num">1, class="num">0)
◍ 多周期同看才看得清二进制形态
有回我在 EUR/USD 上发现,15 分钟图的「101」序列在亚洲盘和欧洲盘含义完全两样——同一代码,时段一换信号就变味。后来盯 ETHUSDT 更明显:小时图重大波动前常出「110」,而 4 小时图同步给「101」,连着五次之后就很难再用巧合解释。 低周期上看着漂亮的结构,放到高周期常常被现实砸碎。现在进场前我至少扫三个周期上的二进制模式,宁可多确认也别漏看。外汇和贵金属杠杆高,多周期验证只是过滤噪音,不消除爆仓风险。 下面这段 Python 借助 MT5 接口把多周期代码一次抓出来,开 MT5 跑一遍就能直接看组合:
<span class="keyword">def</span> multi_timeframe_code(symbol, timeframes=[mt5.TIMEFRAME_M15, mt5.TIMEFRAME_H1, mt5.TIMEFRAME_H4]): <span class="keyword">if</span> <span class="keyword">not</span> mt5.initialize(): <span class="keyword">class="kw">return</span> <span class="literal">None</span> combined_code = [] <span class="keyword">for</span> tf <span class="keyword">in</span> timeframes: rates = mt5.copy_rates_from_pos(symbol, tf, <span class="number">class="num">0</span>, <span class="number">class="num">100</span>) prices = np.array([rate[<span class="number">class="num">4</span>] <span class="keyword">for</span> rate <span class="keyword">in</span> rates]) <span class="comment"># Code direction on each timeframe</span> price_direction = np.diff(prices) > <span class="number">class="num">0</span> combined_code.append(np.where(price_direction, <span class="number">class="num">1</span>, <span class="number">class="num">0</span>)) mt5.shutdown() <span class="comment"># Combine codes from different timeframes</span> <span class="keyword">class="kw">return</span> np.array(combined_code)
<span class="keyword">def</span> multi_timeframe_code(symbol, timeframes=[mt5.TIMEFRAME_M15, mt5.TIMEFRAME_H1, mt5.TIMEFRAME_H4]): <span class="keyword">if</span> <span class="keyword">not</span> mt5.initialize(): <span class="keyword">class="kw">return</span> <span class="literal">None</span> combined_code = [] <span class="keyword">for</span> tf <span class="keyword">in</span> timeframes: rates = mt5.copy_rates_from_pos(symbol, tf, <span class="number">class="num">0</span>, <span class="number">class="num">100</span>) prices = np.array([rate[<span class="number">class="num">4</span>] <span class="keyword">for</span> rate <span class="keyword">in</span> rates]) <span class="comment"># Code direction on each timeframe</span> price_direction = np.diff(prices) > <span class="number">class="num">0</span> combined_code.append(np.where(price_direction, <span class="number">class="num">1</span>, <span class="number">class="num">0</span>)) mt5.shutdown() <span class="comment"># Combine codes from different timeframes</span> <span class="keyword">class="kw">return</span> np.array(combined_code)