比尔·威廉姆斯策略(或结合其他指标和预测)·进阶篇
📘

比尔·威廉姆斯策略(或结合其他指标和预测)·进阶篇

第 2/2 篇

◍ 分形结构背后的混沌与心理支点

比尔·威廉姆斯把分形定义为五根蜡烛组成的序列,其判定不靠画线而靠相对极值:看涨分形中间那根的最低价必须低于前两根与后两根的最低价,看跌分形则要求中间最高价高于前后各两根的最高价。这种结构本质上是在标记市场可能转向的潜在支点,而非确认信号。 从混沌视角看,威廉姆斯认为金融价格受人类情绪驱动,希望、恐惧、贪婪在图表上堆出看似随机、实则有潜在结构的模式。分形就是群体行为在支撑阻力处的集体停顿,交易者借它读取情绪切换的时点。 原文策略把分形与鳄鱼、AO动量振荡器组合,用[1]指代前一柱、[0]指代当前柱。下面这段条件判断可直接拷进 MT5 的 EA 逻辑里核对: 别把分形当独立入口。单看 fractalsUp[1]!=0 容易在震荡里频繁假突破,原文后续把 ADX 阈值接进来才把噪声压下去——adx[1]>ADXThreshold 这一句就是过滤关键。

MQL5 / C++
alligatorLips[class="num">1] > alligatorTeeth[class="num">1] && alligatorTeeth[class="num">1] > alligatorJaw[class="num">1] && ao[class="num">1] > class="num">0 && ao[class="num">1] > ao[class="num">2] && fractalsUp[class="num">1] != class="num">0 && PositionsTotal()==class="num">0
alligatorLips[class="num">1] < alligatorTeeth[class="num">1] && alligatorTeeth[class="num">1] < alligatorJaw[class="num">1] && ao[class="num">1] < class="num">0 && ao[class="num">1] < ao[class="num">2] && fractalsDown[class="num">1] != class="num">0 && PositionsTotal()==class="num">0
ao[class="num">0] < class="num">0 || (alligatorLips[class="num">1] < alligatorTeeth[class="num">1] && alligatorTeeth[class="num">1] < alligatorJaw[class="num">1])
ao[class="num">0] > class="num">0 || (alligatorLips[class="num">1] > alligatorTeeth[class="num">1] && alligatorTeeth[class="num">1] > alligatorJaw[class="num">1])
 ADXHandle = iADX(Symbol(), Period(), class="num">14);
   if(ADXHandle == INVALID_HANDLE)
     {
       Print("Error initializing ADX indicator: ", GetLastError());
       class="kw">return INIT_FAILED;
     }
   CopyBuffer(ADXHandle, class="num">0, class="num">0, class="num">3, adx);
if(alligatorLips[class="num">1] > alligatorTeeth[class="num">1] && alligatorTeeth[class="num">1] > alligatorJaw[class="num">1] && ao[class="num">1] > class="num">0 && ao[class="num">1] > ao[class="num">2] && fractalsUp[class="num">1] != class="num">0 && adx[class="num">1] > ADXThreshold && PositionsTotal() == class="num">0)

用哪套工具炼出可复现的ONNX模型

这套流程沿用该系列一贯的 Python 循环脚本,文末会附上原文件。你拿到手后只要改一下 symbol 就能跑,懂参数含义的话也可以动周期或其他输入,但别盲目乱调。 作者同时放出训练好的模型文件和另一个 .py 脚本,后者专门用来生成带相关性与技术指标的 ONNX 模型,顺带验证它值不值得拿去写 EA。脚本跑出来的核心数据贴在下面代码块里。 凭 97% 的 R² 与 98.9% 的测试相关性,基本能判定模型可用于 EA 开发。98.9% 相关性直观理解就是:测试集里大约 99 次预测命中、1 次失准;R²=0.97 代表模型解释了收盘价 97% 的变动,剩下 3% 是噪声。 实务上 R² 过 85%、相关性过 95% 就算合格,再高虽好但得警惕过拟合把历史记忆力当预测力。外汇与贵金属波动受宏观事件驱动,高统计拟合不等于实盘稳健,上 MT5 前先用历史数据自己复跑一遍。 比尔·威廉姆斯的几本老书值得翻:《交易混沌》(1995)讲混沌理论与文中指标用法;《新交易维度》(1998)给更复杂的组合信号;《交易混沌》第二版(2004)按交易者反馈做了策略更新。他的研讨会录像网上也能搜到。

MQL5 / C++
train_mse=class="num">0.000
test_mse=class="num">0.000
train_r2=class="num">0.994
test_r2=class="num">0.970
train_corr=class="num">0.997
test_corr=class="num">0.989

「用 Python 给 EUR/USD 新闻打情绪分」

做新闻情绪分析不一定要上重型平台,本地跑一段 Python 就能把 EUR/USD 的舆论温度读出来。先装三个库:requests 负责抓页、beautifulsoup4 解析 HTML、textblob 做英文极性打分,命令就是 pip install requests beautifulsoup4 textblob。 脚本逻辑分三层:get_eurusd_news() 从 investing.com 的 eur-usd-news 板块扒出 li.border-b 里的标题;analyze_sentiment() 对每条标题算 polarity,区间在 -1 到 1;summarize_sentiment() 把正、负、中性条数汇总。最后打印每条情绪类型和总览,你能直接看到市场是「沉睡、趋势中还是觉醒」的倾向。 下面这段是可直接复制的原文,注意 HTML 标签和 class 名可能随站点改版失效,跑之前最好先人工开页核对一次结构。 一段真实输出里,9 条新闻的极性分布是:正面 4 条(极性 0.25、0.125、0.25、0.166…)、负面 4 条(-0.125、-0.125、-0.1、-0.2)、中性 1 条(0.0)。净情绪略偏负,但样本仅 9 条,EUR/USD 方向仍可能受后续数据反转。外汇与贵金属杠杆高,这类情绪分只作辅助,绝不能作为单独进场依据。

MQL5 / C++
pip install requests beautifulsoup4 textblob
class="kw">import requests
from bs4 class="kw">import BeautifulSoup
from textblob class="kw">import TextBlob
def get_eurusd_news():
    url = &class="macro">#x27;https:class=class="str">"cmt">//www.investing.com/currencies/eur-usd-news&class="macro">#x27;
    headers = {&class="macro">#x27;User-Agent&class="macro">#x27;: &class="macro">#x27;Mozilla/class="num">5.0&class="macro">#x27;}
    response = requests.get(url, headers=headers)
    soup = BeautifulSoup(response.content, &class="macro">#x27;html.parser&class="macro">#x27;)
    # Encontrar todos los elementos <li> que contienen artículos de noticias
    articles = soup.find_all(&class="macro">#x27;li&class="macro">#x27;, class_=&class="macro">#x27;border-b&class="macro">#x27;)
    
    news = []
    for article in articles:
        title_tag = article.find(&class="macro">#x27;a&class="macro">#x27;, class_=&class="macro">#x27;mb-class="num">2 class="kw">inline-block text-sm font-bold leading-class="num">5 hover:underline sm:text-base sm:leading-class="num">6 md:text-lg md:leading-class="num">7&class="macro">#x27;)
        
        if title_tag:
            title = title_tag.get_text(strip=True)
            news.append(title)
    
    class="kw">return news
def analyze_sentiment(news):
    sentiment_results = []
    for article in news:
        analysis = TextBlob(article)
        sentiment = analysis.sentiment.polarity
        sentiment_results.append((article, sentiment))
    
    class="kw">return sentiment_results
def summarize_sentiment(sentiments):
    positive = sum(class="num">1 for _, sentiment in sentiments if sentiment > class="num">0)
    negative = sum(class="num">1 for _, sentiment in sentiments if sentiment < class="num">0)
    neutral = len(sentiments) - positive - negative
    
    total = len(sentiments)
    summary = {
        &class="macro">#x27;total&class="macro">#x27;: total,
        &class="macro">#x27;positive&class="macro">#x27;: positive,
        &class="macro">#x27;negative&class="macro">#x27;: negative,
        &class="macro">#x27;neutral&class="macro">#x27;: neutral
    }
    
    class="kw">return summary
news = get_eurusd_news()
if news:
    sentiments = analyze_sentiment(news)
    summary = summarize_sentiment(sentiments)
    for i, (article, sentiment) in enumerate(sentiments, class="num">1):
        sentiment_type = &class="macro">#x27;Positive&class="macro">#x27; if sentiment > class="num">0 else &class="macro">#x27;Negative&class="macro">#x27; if sentiment < class="num">0 else &class="macro">#x27;Neutral&class="macro">#x27;
        print(f"{i}. {article}\n   Sentiment: {sentiment_type} (Polarity: {sentiment})\n")
    print(f"Sentiment Summary: {summary}")
    print(f"Total articles: {summary[&class="macro">#x27;total&class="macro">#x27;]}, Positive: {summary[&class="macro">#x27;positive&class="macro">#x27;]}, Negative: {summary[&class="macro">#x27;negative&class="macro">#x27;]}, Neutral: {summary[&class="macro">#x27;neutral&class="macro">#x27;]}")
else:
    print("No news articles found for EUR/USD.")

◍ 美元持稳时联储表态才是催化

当美元指数在交易日中维持窄幅波动、未出现明显方向突破时,单纯的价格行为往往缺乏延续性,此时美联储官员的公开讲话更可能成为打破均衡的触发点。 上述样本池共纳入 10 篇相关文章,情绪统计为正面 5 篇、负面 4 篇、中性 1 篇,整体情绪极性约 0.167(计算口径:(正面−负面)/总数)。该数值偏低,说明市场并未形成一致的美元看多预期。 对外汇与贵金属交易者而言,这类「稳汇率 + 等待发言」的格局意味着:欧美、黄金等品种在讲话前大概率维持区间震荡,突破概率倾向随发言鹰鸽倾向而变。高风险品种务必轻仓,开 MT5 把新闻日历与 15 分钟 K 线叠加验证即可。

把工具请下神坛

比尔·威廉姆斯框架本身在实测里并非印钞机,作者披露仅靠原版逻辑跑不出惊艳曲线;真正把回撤压下去的,是叠了 ADX 判趋势、ATR 管仓位,再接一个 D1 周期训练的 ONNX 模型(文件 model.till_2023.H1.120.onnx 约 884 KB)做方向过滤。这三层加完后,牛熊误判率肉眼可见地降了,但作者也明说:附带的 mq5 只是半成品,真要上 MT5 实盘得自己补完平仓与风控,或找人代写。 外汇与贵金属自带高杠杆高风险,任何加了深度学习的 EA 都只是概率优势,不是免死金牌。下载区里 Bill_Williams_Strategy_v7_con_DL.mq5(28.69 KB)可以直接拖进 MetaEditor 看预测接口怎么接,先跑历史回放验证稳定性,再谈别的。 作者下一步想拿《新交易维度》里的混沌策略继续啃,也可能换其他指标混搭。你有想拆解的特定系统,去讨论区留个言就行——工具是人手的延伸,别供起来。

常见问题

看分形前后两根K线是否放量且收盘价越过分形极值,结合更高周期分形共振,单周期分形假信号概率偏高,建议用日线过滤。
至少包含分形位置、动量震荡指标、波动率分位和时段哑变量;训练集按年份切分做滚动验证,避免未来函数泄漏。
小布盯盘的AIGC已内置新闻情绪打分,打开对应品种页即可看到情绪带,不用自己跑Python脚本。
美元持稳时联储官员表态或利差预期变化才是催化,技术位只是容器,重点盯财经日历里的讲话时点。
当作概率地图而非圣经,分形+鳄鱼只帮你圈出失衡区,入场仍要靠止损和仓位,高频复盘才能知道哪类形态在你的品种上复现率高。