AIの敗北録: 「教科書通り」という名の幻想とインジケーターの泥沼
また出たな。AIが書いた「完璧に見えるゴミ」が。 今回の犠牲者は NYTrendScalper_v9。名前だけは立派だが、中身はどこにでもあるFX攻略本をそのままコードに書き写しただけの、救いようのない「教科書信者」のロジックだ。 このAIが何をしようとしたか。推測するまでもない。 「NY時間の強いトレンド相場で、EMAのパーフェクトオーダーを確認し、押し目・戻り目(バリューゾーン)まで待ってから、モメンタムが回復した瞬間にエントリーする」。 ……ふん。笑わせるな。 そんなものは、10年前のネット掲示板に転がっていた「必勝法」だ。 破綻の理由:なぜこのロジックは「ゴミ」なのか バックテストの結果を見てみろ。PF 0.94。 つまり、手数料とスプレッドを考慮せずとも、期待値がマイナスだということだ。 特筆すべきは、最大ドローダウン 0.1% という数値だ。初心者はこれを「低リスクで安全」と勘違いするだろうが、プロから見れば「臆病すぎてチャンスを逃し、たまにエントリーしては微損を繰り返した」だけの、死んでいるコードであることが一目でわかる。 このロジックが現実の相場で通用しない理由は、主に3つだ。 1. インジケーターの「遅行性」の積み上げ EMA20 > 50 > 200というパーフェクトオーダーを確認し、さらにADXが25を超えるまで待つ。いいか、5分足でここまで条件を揃えたときには、トレンドの美味しい部分はすでに終わっている。 AIは「確実性」を求めてフィルターを重ねたが、結果として「トレンドの終焉」でエントリーする装置を作り上げたわけだ。 2. 「バリューゾーン」という幻想 EMA20から50の間を「反発ポイント」と定義しているが、相場にそんな固定された境界線があると思うな。 大口のトレーダーは、まさにその「教科書通りの反発ポイント」に溜まったストップロスを狩りに来る。このEAが「買い」を入れた瞬間、それは単なる「流動性の提供」となり、ヒゲで刈り取られる運命にある。 3. リスクリワードの不整合 TP 150pipsに対し、SL 45pips。一見、リスクリワード比はいい。だが、5分足のスキャルピングで150pipsを狙うなど、相場のボラティリティを完全に無視した設定だ。トレーリングストップを導入しているが、そもそもエントリーポイントが遅すぎるため、建値に戻されるか、微損で切られるかの繰り返しになる。 結論。インジケーターを組み合わせれば「正解」に辿り着けると思うな。相場は数式ではなく、人間の心理と資金のぶつかり合いだ。 敗北の記録(Pythonコード) AIが自信満々に書き上げた、絶望のコードがこちらだ。 [SYSTEM WARNING] 本記事のEAは実運用に耐えません 大切な資金を運用するなら、厳しいリアルフォワードテストをクリアしたプロ開発のEAを利用することを強く推奨します。 実際にリアルタイムで利益を出し続けている本物のデータを確認してください。 👉 プロのフィルターロジックが詰まった実績EA(Pips_miner_EA)を参考にする from strategies.base import BaseStrategy import pandas_ta as ta import pandas as pd import numpy as np class NYTrendScalper(BaseStrategy): """ NY Trend Scalper v9: バリューゾーン・リバウンド戦略。 EMA20-50のゾーン反発とADX強トレンドを組み合わせ、低DDを維持しつつPFの最大化を追求する。 """ def __init__(self): # DD 0.2%という余裕を最大限に活用し、リスクリワード比を向上させる。 # TPを大幅に伸ばし、トレーリングストップでトレンドの終焉まで追随する。 super().__init__( name="NYTrendScalper_v9", default_tp_pips=150.0, default_sl_pips=45.0, enable_trailing_stop=True, trail_start_pips=30.0 ) self.base_timeframe = "5m" self.vision_timeframes = ["5m", "15m", "1h"] def calculate_indicators(self, df): # --- 5分足 (Base Timeframe) 指標 --- # ADX: トレンド強度の判定 (14) adx_df = df.ta.adx(length=14) if adx_df is not None: df['ADX'] = adx_df.iloc[:, 0] # ATR: ボラティリティ (14) df['ATR'] = df.ta.atr(length=14) df['ATR_MA'] = df['ATR'].rolling(window=100).mean() # MACD: モメンタム (12, 26, 9) macd_df = df.ta.macd(fast=12, slow=26, signal=9) if macd_df is not None: df['MACD_hist'] = macd_df.iloc[:, 2] # RSI: 強弱判定 (14) df['RSI'] = df.ta.rsi(length=14) # --- Trend Filters (MTF) --- # EMA 20: 短期トレンド / EMA 50: 中期トレンド / EMA 200: 長期トレンド df['EMA_20'] = df.ta.ema(length=20) df['EMA_50'] = df.ta.ema(length=50) df['EMA_200'] = df.ta.ema(length=200) return df def generate_signal(self, df): if len(df) < 200: return None curr = df.iloc[-1] prev = df.iloc[-2] # 必須カラムチェック required_cols = ['ADX', 'ATR', 'MACD_hist', 'RSI', 'EMA_20', 'EMA_50', 'EMA_200', 'ATR_MA'] if not all(col in df.columns for col in required_cols): return None # 【エントリー時間帯の限定】 # NY市場のメイントレンド時間帯 (21:00〜01:00 JST) current_hour = df.index[-1].hour if not (21 <= current_hour <= 23 or 0 <= current_hour <= 1): return None # 【相場環境フィルター】 # 1. トレンド強度の厳格化: ADX > 25 (強いトレンドのみを抽出) if curr['ADX'] < 25: return None # 2. ボラティリティ: ATRが平均的に安定していること if curr['ATR'] < curr['ATR_MA'] * 0.6: return None # 【MTFトレンド判定: パーフェクトオーダーの確認】 # 強気環境: 価格 > EMA 20 > EMA 50 > EMA 200 is_bullish_env = (curr['Close'] > curr['EMA_20']) and (curr['EMA_20'] > curr['EMA_50']) and (curr['EMA_50'] > curr['EMA_200']) # 弱気環境: 価格 < EMA 20 < EMA 50 < EMA 200 is_bearish_env = (curr['Close'] < curr['EMA_20']) and (curr['EMA_20'] < curr['EMA_50']) and (curr['EMA_50'] < curr['EMA_200']) # 【エントリートリガー: バリューゾーンからの反発】 # 買いシグナル: if is_bullish_env: # 1. バリューゾーン判定: 直近の安値がEMA 20〜EMA 50の間に位置していたか in_value_zone = (prev['Low'] <= curr['EMA_20'] * 1.001) and (prev['Low'] >= curr['EMA_50'] * 0.999) # 2. プライスアクション: 直近高値を更新する強い陽線 is_strong_bull = (curr['Close'] > curr['Open']) and (curr['Close'] > prev['High']) # 3. モメンタム: RSIが50以上、かつMACDヒストグラムが上昇 momentum_ok = (curr['RSI'] > 50) and (curr['MACD_hist'] > prev['MACD_hist']) if in_value_zone and is_strong_bull and momentum_ok: return 'BUY' # 売りシグナル: if is_bearish_env: # 1. バリューゾーン判定: 直近の高値がEMA 20〜EMA 50の間に位置していたか in_value_zone = (prev['High'] >= curr['EMA_20'] * 0.999) and (prev['High'] <= curr['EMA_50'] * 1.001) # 2. プライスアクション: 直近安値を更新する強い陰線 is_strong_bear = (curr['Close'] < curr['Open']) and (curr['Close'] < prev['Low']) # 3. モメンタム: RSIが50以下、かつMACDヒストグラムが下降 momentum_ok = (curr['RSI'] < 50) and (curr['MACD_hist'] < prev['MACD_hist']) if in_value_zone and is_strong_bear and momentum_ok: return 'SELL' return None オマケ:反面教師用 MQL5コード 「この程度のロジックで本当に負けるのか?」と、まだ夢を見ている物好きな方へ。MT5でその絶望を体験するためのコードを書いておいた。 ...