【PF1.34】MT5無料EA: AIが導き出したボラティリティ・スクイーズ戦略を完全公開

導入:なぜこのロジックは「激動の2年間」を勝ち抜けたのか 10年間間の相場は、歴史的なインフレとそれに伴う急激な金利変動により、多くのトレンドフォロー型EAが「往復ビンタ」に遭い、破綻していった困難な期間でした。しかし、本ロジック(VolatilitySqueezeBreakout_V5)は、プロフィットファクター1.34という堅実な数値を叩き出し、バックテストを合格しました。 このロジックの核心は、「エネルギーの蓄積(Squeeze)」と「爆発的な解放(Breakout)」の厳格な判定にあります。 技術的な強み ボリンジャーバンドとケルトナーチャネルの相関判定 単なる価格のブレイクアウトではなく、BBがKCの内部に収まる「スクイーズ状態」を検知しています。これは市場のボラティリティが極限まで低下し、次なる大きな変動へのエネルギーが蓄積された状態を指します。 マルチタイムフレーム(MTF)による環境認識 5分足のトリガーだけでなく、15分足と1時間足のEMA方向性を完全に一致させることで、短期的なノイズ(ダマシ)を排除し、上位足の強力なトレンドに乗る設計となっています。 NY時間への特化とボラティリティフィルター 最も流動性が高く、トレンドが出やすいNY時間(JST 21:00-00:00)に限定してエントリーを許可。さらにATR(Average True Range)がその移動平均を上回っていることを条件とし、「本物のボラティリティ拡大」が起きた瞬間のみを狙い撃ちします。 キャンドルクオリティの厳格化 実体の比率(Body Position)を判定し、ヒゲの長い不安定な足でのエントリーを回避。これにより、ブレイクアウトの確度を飛躍的に高めています。 以下に、この戦略を実装したPythonコードと、MT5で即座に運用可能なMQL5コードを公開します。 Pythonコード 🔍 プロはどうやってダマシを回避しているのか? 今回のAIロジックも優秀ですが、長年ランキング上位に居続けるプロのEAは、さらに複雑な環境認識や、独自のボラティリティフィルターを何層も実装しています。 自作EAの成績が行き詰まった時は、実際にリアル口座で長期間利益を出し続けている「本物の市販EA」の挙動(エントリーと決済のタイミング)を観察することが、一番の勉強になります。 👉 プロのフィルターロジックが詰まった実績EA(White Bear Z USDJPY)を参考にする from strategies.base import BaseStrategy import pandas_ta as ta import pandas as pd import numpy as np class VolatilitySqueezeBreakout(BaseStrategy): def __init__(self): # PF向上のため、利確幅を調整し、トレーリングストップで最大利益を追求 super().__init__( name="VolatilitySqueezeBreakout_V5", default_tp_pips=60.0, default_sl_pips=25.0, enable_trailing_stop=True, trail_start_pips=15.0 ) self.base_timeframe = "5min" self.vision_timeframes = ["5min", "15min", "1h"] def calculate_indicators(self, df): # --- 1. 5分足のインジケーター計算 --- # ボリンジャーバンド bb = df.ta.bbands(length=20, std=2.0) df['BB_Lower'] = bb.iloc[:, 0] df['BB_Mid'] = bb.iloc[:, 1] df['BB_Upper'] = bb.iloc[:, 2] # ケルトナーチャネル kc = df.ta.kc(length=20, scalar=2.0) df['KC_Lower'] = kc.iloc[:, 0] df['KC_Upper'] = kc.iloc[:, 2] # ATRとその移動平均 (ボラティリティ拡大の判定用) df['ATR'] = df.ta.atr(length=14) df['ATR_MA'] = df['ATR'].rolling(window=20).mean() # ADX (トレンド強度) adx_df = df.ta.adx(length=14) df['ADX'] = adx_df.iloc[:, 0] # RSI (過買過売の判定) df['RSI'] = ta.rsi(df['Close'], length=14) # EMA (短期トレンドと傾き) df['EMA_20'] = ta.ema(df['Close'], length=20) df['EMA_Slope'] = df['EMA_20'].diff(3) # Squeeze判定 df['Squeeze'] = (df['BB_Upper'] < df['KC_Upper']) & (df['BB_Lower'] > df['KC_Lower']) # --- 2. マルチタイムフレーム (MTF) 分析 --- # 未来のカンニングを完全に防止するため .shift(1) # 15分足: 短期トレンド加速判定 (EMA20 > EMA50) resampled_15 = df['Close'].resample('15min').last().shift(1) ema20_15 = ta.ema(resampled_15, length=20) ema50_15 = ta.ema(resampled_15, length=50) trend_15min = (ema20_15 > ema50_15).astype(int) df['Trend_15min'] = trend_15min.reindex(df.index, method='ffill') # 1時間足: 環境認識フィルター (Close > EMA50) resampled_1h = df['Close'].resample('1h').last().shift(1) ema50_1h = ta.ema(resampled_1h, length=50) trend_1h = (resampled_1h > ema50_1h).astype(int) df['Trend_1h'] = trend_1h.reindex(df.index, method='ffill') return df def generate_signal(self, df): # 最新のバーを取得 last = df.iloc[-1] # --- エントリー時間帯フィルター (NYトレンド特化: 21:00 - 00:00 JST) --- current_hour = df.index[-1].hour if not (21 <= current_hour <= 23): return None # --- 1. ボラティリティ・フィルター (本物の爆発か) --- # ATRが平均を上回っており、かつADXが上昇傾向にあること atr_expanding = last['ATR'] > last['ATR_MA'] adx_rising = df['ADX'].iloc[-1] > df['ADX'].iloc[-3] if not (atr_expanding and adx_rising): return None # --- 2. キャンドル・クオリティ・フィルター (反転リスク排除) --- candle_range = last['High'] - last['Low'] if candle_range == 0: return None body_position = (last['Close'] - last['Low']) / candle_range # --- 3. ブレイクアウトトリガー --- recent_high = df['High'].iloc[-4:-1].max() recent_low = df['Low'].iloc[-4:-1].min() breakout_up = (last['Close'] > last['BB_Upper']) and (last['Close'] > last['KC_Upper']) and (last['Close'] > recent_high) breakout_down = (last['Close'] < last['BB_Lower']) and (last['Close'] < last['KC_Lower']) and (last['Close'] < recent_low) # 直近10本以内にSqueezeがあったか was_squeezed = df['Squeeze'].iloc[-10:].any() # --- 4. MTFトレンド一致確認 --- mtf_bullish = (last['Trend_1h'] == 1) and (last['Trend_15min'] == 1) mtf_bearish = (last['Trend_1h'] == 0) and (last['Trend_15min'] == 0) # --- 最終シグナル判定 --- # BUY条件: # NY時間 + ATR拡大 + 上方ブレイク + 上位足一致 + 実体が上方に強い + RSIが行き過ぎていない( < 70) + EMA傾き正 if (was_squeezed or last['ADX'] > 20) and breakout_up and mtf_bullish: if body_position > 0.7 and 45 < last['RSI'] < 70 and last['EMA_Slope'] > 0: return 'BUY' # SELL条件: # NY時間 + ATR拡大 + 下方ブレイク + 上位足一致 + 実体が下方に強い + RSIが行き過ぎていない( > 30) + EMA傾き負 if (was_squeezed or last['ADX'] > 20) and breakout_down and mtf_bearish: if body_position < 0.3 and 30 < last['RSI'] < 55 and last['EMA_Slope'] < 0: return 'SELL' return None MQL5コードへの翻訳 このPythonロジックをMT5で完全に再現したEAコードです。Keltner Channelは標準インジケーターにないため、内部的に計算ロジックを実装しています。 ...

2026年7月20日 · 7 min · AIでEA開発入門

【PF1.86】MT5無料EA: 10年間の激動相場を制した「東京時間特化型」ミーンリバージョン戦略を公開

導入:なぜこのロジックは「激動の2年」を生き抜いたのか AI研究者の視点から見て、このロジックが10年間間のインフレ局面や金利変動という極めてボラティリティの高い相場でPF 1.86という高水準な数値を叩き出した理由は、**「徹底した環境認識によるエントリー制限」**にあります。 多くのEAが陥る罠は、トレンド相場で逆張りを仕掛け、踏み上げられることです。しかし、本ロジックは以下の3重のフィルターによって、極めて期待値の高い局面のみを抽出しています。 時間軸の限定(Time-Window Filtering) 東京市場オープン直後の9:00〜10:00という、特有のクセを持つ時間帯に限定。ノイズの多い時間帯を排除し、短期的なリバウンドが発生しやすい時間枠に絞り込んでいます。 ボラティリティの適正判定(Volatility Guard) ADXを用いて「強いトレンドが出ていないこと(ADX < 25)」を確認し、同時にATRを用いて「死んでいる相場(ボラティリティ不足)」ではないことを判定しています。これにより、トレンド追随相場での大損失を回避しつつ、効率的なリバウンドを狙う設計となっています。 マルチタイムフレーム(MTF)による方向性合致 5分足のシグナルだけでなく、15分足のSMAをフィルターとして採用。上位足の方向性と極端に乖離していないことを条件に加えることで、単純な逆張りではなく、「押し目・戻りの中の短期反発」を捉える構造になっています。 結論として、このEAは「勝つこと」よりも「負ける局面を徹底的に避けること」に特化した、非常に冷静な設計と言えます。 公開:ベースとなったPythonコード 本ロジックの根幹となるPythonコードを公開します。データ分析およびバックテストに使用された実装です。 🔍 プロはどうやってダマシを回避しているのか? 今回のAIロジックも優秀ですが、長年ランキング上位に居続けるプロのEAは、さらに複雑な環境認識や、独自のボラティリティフィルターを何層も実装しています。 自作EAの成績が行き詰まった時は、実際にリアル口座で長期間利益を出し続けている「本物の市販EA」の挙動(エントリーと決済のタイミング)を観察することが、一番の勉強になります。 👉 プロのフィルターロジックが詰まった実績EA(一本勝ち)を参考にする from strategies.base import BaseStrategy import pandas_ta as ta import pandas as pd class MeanReversionTokyoStrategy(BaseStrategy): def __init__(self): # トレーリングストップを有効化し、利益を最大化させる設計 super().__init__( name="MeanReversion_Tokyo_Quant_v2", default_tp_pips=30.0, default_sl_pips=15.0, enable_trailing_stop=True, trail_start_pips=10.0 ) # 5分足ベースのデイトレ・スキャルピング設定 self.base_timeframe = "5m" # AI画像認識および分析用のマルチタイムフレーム定義 self.vision_timeframes = ["5min", "15min", "1h"] def calculate_indicators(self, df): """ テクニカル指標を計算し、カラム名を固定して結合することでKeyErrorを防止。 """ # --- 1. ボラティリティ & トレンドフィルター --- # ADX: トレンドの強さを判定 adx_df = df.ta.adx(high='High', low='Low', close='Close', length=14) df['ADX'] = adx_df.iloc[:, 0] # 1番目のカラム(ADX_14)をADXとして固定 # ATR: ボラティリティの絶対値を判定 df['ATR'] = df.ta.atr(length=14) # --- 2. 過剰伸長判定インジケーター --- # ボリンジャーバンド (20期間, 2標準偏差) bbands_df = df.ta.bbands(length=20, std=2.0) # カラム名が動的なため、接頭辞で抽出して固定名に割り当て df['BBL'] = bbands_df.filter(like='BBL').iloc[:, 0] df['BBM'] = bbands_df.filter(like='BBM').iloc[:, 0] df['BBU'] = bbands_df.filter(like='BBU').iloc[:, 0] # RSI (14期間) df['RSI'] = df.ta.rsi(length=14) # ストキャスティクス (14, 3, 3) stoch_df = df.ta.stoch(high='High', low='Low', close='Close', length=14, k=3, d=3) df['STOCHk'] = stoch_df.filter(like='STOCHk').iloc[:, 0] # --- 3. マルチタイムフレーム (MTF) 分析 --- # 未来のカンニングを防ぐため、resample直後に .shift(1) を適用 # 15分足の終値を5分足にリインデックス df['close_15min'] = df['Close'].resample('15min').last().shift(1).reindex(df.index, method='ffill') # 1時間足の終値を5分足にリインデックス df['close_1h'] = df['Close'].resample('1h').last().shift(1).reindex(df.index, method='ffill') # 上位足の方向性判定 df['sma_15min'] = df['close_15min'].rolling(window=12).mean() return df def generate_signal(self, df): """ 固定化したカラム名に基づいたエントリーシグナルの生成。 """ if len(df) < 30: return None last = df.iloc[-1] # --- [フィルター1] 時間帯制限 (東京オープン 9:00〜10:00 JST) --- current_hour = df.index[-1].hour if not (9 <= current_hour < 10): return None # --- [フィルター2] 相場環境フィルター (レンジ相場判定) --- # ADX < 25 であること(強いトレンドが出ていないこと) is_range = last['ADX'] < 25 # ボラティリティが極端に低すぎないか確認 (ATRが直近平均の0.5倍以上) atr_ma = df['ATR'].rolling(window=100).mean().iloc[-1] is_volatile_enough = last['ATR'] > (atr_ma * 0.5) if not pd.isna(atr_ma) else True if not (is_range and is_volatile_enough): return None # --- [フィルター3] MTFフィルター --- mtf_buy_ok = last['Close'] > (last['sma_15min'] * 0.998) mtf_sell_ok = last['Close'] < (last['sma_15min'] * 1.002) # --- [エントリーロジック] ミーン・リバージョン --- # 買い条件: BB下限突破 + RSI売られすぎ + Stoch売られすぎ + MTF buy_condition = ( (last['Close'] < last['BBL']) and (last['RSI'] < 30) and (last['STOCHk'] < 20) and mtf_buy_ok ) # 売り条件: BB上限突破 + RSI買われすぎ + Stoch買われすぎ + MTF sell_condition = ( (last['Close'] > last['BBU']) and (last['RSI'] > 70) and (last['STOCHk'] > 80) and mtf_sell_ok ) if buy_condition: return 'BUY' elif sell_condition: return 'SELL' return None 実装:MQL5コード (.mq5) への翻訳 上記のPythonロジックをMT5でそのまま動作するように翻訳したコードです。 時間設定(InpStartHour / InpEndHour)は、ご利用のブローカーのサーバー時間に合わせて調整してください。 ...

2026年7月20日 · 5 min · AIでEA開発入門

【PF1.24】MT5無料EA: 激動の金利相場を勝ち抜くミーンリバージョン戦略を完全公開

イントロダクション:なぜこのロジックは「生き残れた」のか 10年間間の相場は、歴史的なインフレと急激な金利変動により、多くのトレンドフォロー型EAがダマシに遭い、また単純な逆張りEAが一方的なトレンドに飲み込まれて破綻した極めて困難な期間でした。 本ロジック「MeanReversionRangeStrategy」が、プロフィットファクター1.24、勝率42.9%という堅実な数字でこの期間を勝ち抜いた最大の要因は、**「エントリー条件の極端な厳格化」と「マルチタイムフレーム(MTF)による環境認識」**の組み合わせにあります。 技術的な強みの分析 三重のADXフィルターによるトレンド回避 ミーンリバージョン(平均回帰)戦略の最大の弱点は、強いトレンドの発生です。本ロジックでは、5分足だけでなく15分足、1時間足のADXを同時に監視し、全ての時間軸でトレンドが弱い(ADX < 25~30)ことを条件としています。これにより、「トレンドの押し目」を「レンジの端」と誤認してエントリーするリスクを劇的に低減しています。 ATRベースのボラティリティ・フロア 単にレンジであることだけでなく、ATR(Average True Range)をその移動平均と比較し、ボラティリティが極端に低下しすぎている(死んだ相場)局面を排除しています。これにより、スプレッド負けする低ボラティリティ相場での不要な取引を回避しています。 時間帯の限定(ロンドン初動) JST 16:00〜18:00という、市場参加者が急増し流動性が高まるロンドン市場のオープン直後に限定することで、テクニカル指標の信頼性を高め、効率的に利確目標(TP)に到達させる設計となっています。 オシレーターの同期(RSI × Stochastic) ボリンジャーバンドのタッチだけでなく、RSIによる売られすぎ・買われすぎの判定と、ストキャスティクスのクロスという「タイミングのトリガー」を同期させています。これにより、価格の反転可能性が極めて高いポイントのみを抽出しています。 以下に、このロジックを実装したPythonコードおよび、MT5で即座に運用可能なMQL5コードを公開します。 Pythonコード 🔍 プロはどうやってダマシを回避しているのか? 今回のAIロジックも優秀ですが、長年ランキング上位に居続けるプロのEAは、さらに複雑な環境認識や、独自のボラティリティフィルターを何層も実装しています。 自作EAの成績が行き詰まった時は、実際にリアル口座で長期間利益を出し続けている「本物の市販EA」の挙動(エントリーと決済のタイミング)を観察することが、一番の勉強になります。 👉 プロのフィルターロジックが詰まった実績EA(一本勝ち)を参考にする from strategies.base import BaseStrategy import pandas_ta as ta import pandas as pd class MeanReversionRangeStrategy(BaseStrategy): """ ロンドン初動の時間帯に特化した、MTFフィルター付きミーン・リバージョン戦略。 カラム名依存を排除し、ilocによる位置指定で指標を抽出することでKeyErrorを完全に防止。 """ def __init__(self): # トレーリングストップを有効にし、利益を最大化 super().__init__( name="MeanReversionRangeStrategy", default_tp_pips=40.0, default_sl_pips=20.0, enable_trailing_stop=True, trail_start_pips=10.0 ) self.base_timeframe = "5m" self.vision_timeframes = ["5m", "15min", "1h"] def calculate_indicators(self, df): # --- 5分足のテクニカル指標計算 --- # ボリンジャーバンド (20, 2) # pandas_ta.bbands は [BBL, BBM, BBU, BBB, BBP] の順で返す bb = ta.bbands(df['Close'], length=20, std=2) df['BBL'] = bb.iloc[:, 0] # Lower Band df['BBM'] = bb.iloc[:, 1] # Middle Band df['BBU'] = bb.iloc[:, 2] # Upper Band # RSI (14) - Seriesで返るためそのまま代入 df['RSI'] = ta.rsi(df['Close'], length=14) # ストキャスティクス (14, 3, 3) # pandas_ta.stoch は [STOCHk, STOCHd] の順で返す stoch = ta.stoch(df['High'], df['Low'], df['Close'], k=14, d=3, smooth_k=3) df['STOCHk'] = stoch.iloc[:, 0] df['STOCHd'] = stoch.iloc[:, 1] # ADX (14) - [ADX, DMP, DMN] の順で返す adx_df = ta.adx(df['High'], df['Low'], df['Close'], length=14) df['ADX'] = adx_df.iloc[:, 0] # ATR (14) - Seriesで返る df['ATR'] = ta.atr(df['High'], df['Low'], df['Close'], length=14) df['ATR_MA'] = df['ATR'].rolling(window=100).mean() # --- マルチタイムフレーム (MTF) 分析 --- # 未来のカンニングを防止するため、必ず .shift(1) を適用 # 15分足のADX df_15m_close = df['Close'].resample('15min').last().shift(1) df_15m_high = df['High'].resample('15min').max().shift(1) df_15m_low = df['Low'].resample('15min').min().shift(1) df_15m_tmp = pd.DataFrame({'High': df_15m_high, 'Low': df_15m_low, 'Close': df_15m_close}) adx_15m_df = ta.adx(df_15m_tmp['High'], df_15m_tmp['Low'], df_15m_tmp['Close'], length=14) # ADXのみを抽出し、元のインデックスに合わせる df['ADX_15m'] = adx_15m_df.iloc[:, 0].reindex(df.index, method='ffill') # 1時間足のADX df_1h_close = df['Close'].resample('1h').last().shift(1) df_1h_high = df['High'].resample('1h').max().shift(1) df_1h_low = df['Low'].resample('1h').min().shift(1) df_1h_tmp = pd.DataFrame({'High': df_1h_high, 'Low': df_1h_low, 'Close': df_1h_close}) adx_1h_df = ta.adx(df_1h_tmp['High'], df_1h_tmp['Low'], df_1h_tmp['Close'], length=14) # ADXのみを抽出し、元のインデックスに合わせる df['ADX_1h'] = adx_1h_df.iloc[:, 0].reindex(df.index, method='ffill') return df def generate_signal(self, df): # 最新の行を取得 curr = df.iloc[-1] # --- エントリー時間帯の限定 (JST 16:00〜18:00 ロンドン初動) --- hour = df.index[-1].hour if not (16 <= hour < 18): return None # --- 相場環境フィルター --- # 1. 全時間足でトレンドが弱いことを確認 (ADX < 25) is_range = (curr['ADX'] < 25) and (curr['ADX_15m'] < 30) and (curr['ADX_1h'] < 30) # 2. ボラティリティが極端に低すぎないことを確認 has_volatility = curr['ATR'] > (curr['ATR_MA'] * 0.5) if not (is_range and has_volatility): return None # --- エントリーロジック (ミーン・リバージョン) --- # BUY シグナル: # - 価格がボリンジャーバンド下限以下 # - RSIが35以下 (売られすぎ) # - ストキャスティクスでK線がD線を上抜け、かつ25以下の水準 buy_condition = ( (curr['Close'] <= curr['BBL']) and (curr['RSI'] < 35) and (curr['STOCHk'] > curr['STOCHd']) and (curr['STOCHk'] < 25) ) # SELL シグナル: # - 価格がボリンジャーバンド上限以上 # - RSIが65以上 (買われすぎ) # - ストキャスティクスでK線がD線を下抜け、かつ75以上の水準 sell_condition = ( (curr['Close'] >= curr['BBU']) and (curr['RSI'] > 65) and (curr['STOCHk'] < curr['STOCHd']) and (curr['STOCHk'] > 75) ) if buy_condition: return 'BUY' elif sell_condition: return 'SELL' return None MQL5コード (.mq5) 以下は、上記のPythonロジックを忠実に再現したMT5用EAコードです。 ...

2026年7月19日 · 5 min · AIでEA開発入門

【PF1.28】10年間合格EA: NY時間限定・3重時間軸フィルターによるトレンド回帰戦略

概要:なぜこのロジックは「激動の2年」を生き残れたのか 10年間間の相場は、急激なインフレとそれに伴う各国の金利変動により、トレンドの発生と崩壊が極めて激しい局面が続きました。多くのEAがレンジ相場での往復ビンタや、トレンド転換時の深いドローダウンに耐えられず脱落する中、本ロジックがプロフィットファクター(PF) 1.28、勝率50%という堅実な数字を維持できた理由は、「極めて厳格な環境認識(フィルター)」と「高リスクリワード設計」の組み合わせにあります。 技術的な強み 3重の時間軸フィルター (Multi-Timeframe Analysis) 単一の時間軸で判断せず、1時間足で「大方向(パーフェクトオーダー)」を確認し、15分足で「トレンドの強度(ADX)」を測定、5分足で「エントリータイミング(RSI/MACD)」を計るという階層的な構造を持っています。これにより、トレンドがない相場でのエントリーを徹底的に排除しています。 ボラティリティの選別と時間帯制限 NY市場のオープン前後(JST 21:00 - 23:00)にのみ限定して動作させます。この時間帯は流動性が高く、方向感が出やすいため、トレンドフォロー戦略との相性が極めて良好です。 「押し目・戻り」の定量化 単なるトレンドフォローではなく、RSIを用いて「トレンド方向への一時的な調整(プルバック)」を待ち、MACDのヒストグラム反転でモメンタムの回帰を確認してからエントリーします。これにより、高値掴み・安値掴みのリスクを低減させています。 数学的な優位性(リスクリワード比) 勝率50%でありながら利益を残せるのは、SL 30pipsに対しTP 100pipsという、リスクリワード比 1:3.33 の設計になっているためです。さらにトレーリングストップを実装することで、トレンドが伸びた際の利益を最大化し、PFを底上げしています。 Pythonコードの公開 💡 プロはどうやってダマシを回避しているのか? 自作EAの成績が行き詰まった時は、実際にリアル口座で長期間利益を出し続けている「本物の市販EA」の挙動を観察することが、一番の勉強になります。 👉 プロのフィルターロジックが詰まった実績EA(一本勝ち)を参考にする from strategies.base import BaseStrategy import pandas_ta as ta import pandas as pd class NyTrendPullbackStrategy(BaseStrategy): """ NY Trend Specialized Pullback Strategy - 1h: EMA 50/200 Perfect Order for major trend identification - 15min: ADX > 25 to filter out range markets - 5min: RSI for short-term adjustment (Pullback) + MACD reversal for entry - Goal: Maximize Risk-Reward ratio by entering at 'value' areas within a strong trend. """ def __init__(self): # Optimized for high PF: wider TP and trailing stop to capture large moves super().__init__( name="NyTrendPullbackStrategy_V3", default_tp_pips=100.0, default_sl_pips=30.0, enable_trailing_stop=True, trail_start_pips=25.0 ) self.base_timeframe = "5m" self.vision_timeframes = ["5m", "15min", "1h"] def calculate_indicators(self, df): # --- 5min Timeframe Indicators --- # MACD (12, 26, 9) -> returns DataFrame [MACD, Signal, Hist] macd_df = df.ta.macd(close='Close', fast=12, slow=26, signal=9) df['MACD_hist'] = macd_df.iloc[:, 2] # RSI (14) - used to detect pullbacks df['RSI'] = df.ta.rsi(close='Close', length=14) # ATR - for volatility check df['ATR'] = df.ta.atr(high='High', low='Low', close='Close', length=14) # --- Multi-Timeframe (MTF) Analysis --- # 15min: ADX for trend strength (Must be > 25) df_15m = df.resample('15min').agg({'Open': 'first', 'High': 'max', 'Low': 'min', 'Close': 'last'}) adx_15m = df_15m.ta.adx(high='High', low='Low', close='Close', length=14) # Extract ADX column (index 0) and map back to 5min index df['ADX_15m'] = adx_15m.iloc[:, 0].reindex(df.index, method='ffill') # 1h: EMA 50 and EMA 200 for Perfect Order df_1h = df.resample('1h').agg({'Open': 'first', 'High': 'max', 'Low': 'min', 'Close': 'last'}) ema_50_1h = df_1h.ta.ema(close='Close', length=50) ema_200_1h = df_1h.ta.ema(close='Close', length=200) df['EMA_50_1h'] = ema_50_1h.reindex(df.index, method='ffill') df['EMA_200_1h'] = ema_200_1h.reindex(df.index, method='ffill') return df def generate_signal(self, df): # Get latest and previous row for momentum acceleration check row = df.iloc[-1] prev_row = df.iloc[-2] # --- 1. Time Filter (JST 21:00 - 23:00) --- current_hour = df.index[-1].hour if not (21 <= current_hour <= 23): return None # --- 2. Market Condition Filter --- # ADX > 25: Ensure strong trend exists to avoid whipsaws in range if row['ADX_15m'] < 25: return None if row['ATR'] <= 0: return None # --- 3. MTF Trend Alignment (Perfect Order) --- # Bullish Trend: EMA 50 > EMA 200 AND Price > EMA 50 long_trend = (row['EMA_50_1h'] > row['EMA_200_1h']) and (row['Close'] > row['EMA_50_1h']) # Bearish Trend: EMA 50 < EMA 200 AND Price < EMA 50 short_trend = (row['EMA_50_1h'] < row['EMA_200_1h']) and (row['Close'] < row['EMA_50_1h']) # --- 4. Entry Logic (Pullback + Momentum Reversal) --- # BUY Signal: # - Major trend is Bullish # - Short-term RSI drops below 45 (Pullback) # - MACD Histogram increases from previous bar (Momentum reversal) buy_condition = ( long_trend and (row['RSI'] < 45) and (row['MACD_hist'] > prev_row['MACD_hist']) ) # SELL Signal: # - Major trend is Bearish # - Short-term RSI rises above 55 (Pullback/Correction) # - MACD Histogram decreases from previous bar (Momentum reversal) sell_condition = ( short_trend and (row['RSI'] > 55) and (row['MACD_hist'] < prev_row['MACD_hist']) ) if buy_condition: return 'BUY' elif sell_condition: return 'SELL' return None MQL5コードへの翻訳(MT5用) 以下は、上記のPythonロジックを忠実に再現したMQL5コードです。MT5のメタエディターに貼り付けてコンパイルして使用してください。 ...

2026年7月18日 · 5 min · AIでEA開発入門

【PF1.50】10年間合格EA: NY市場オープンに特化したMTF順張りロジック

序論:ボラティリティ時代における「平均回帰」の再定義 10年間間の相場は、急激なインフレと金利変動により、従来のテクニカル分析が通用しにくい「極端なトレンド」と「深い調整」が頻発する環境にありました。このような環境下でプロフィットファクター(PF) 1.50、勝率50%という堅実な数値を叩き出した本ロジックの核心は、**「厳格な環境認識」と「タイミングの二重フィルタリング」**にあります。 本ロジックは単なる逆張りではなく、以下の3つの技術的アプローチを組み合わせることで、いわゆる「落ちるナイフを掴む」リスクを最小限に抑えています。 マルチタイムフレーム(MTF)による方向性の定義: 1時間足のSMAを用いて大局的な価格位置を把握し、価格が平均から乖離した状態でのみエントリーを検討します。これにより、根拠のない逆張りを排除しています。 ADXによるトレンド強度フィルター: 15分足のADXを用いて、トレンドが強すぎる局面(ADX $\ge$ 30)を完全に回避しています。平均回帰(ミーン・リバージョン)戦略が最も機能するのはレンジ相場または緩やかなトレンド相場であり、このフィルターがドローダウンの抑制に大きく寄与しています。 トリガーの厳格化(過剰伸長 $\rightarrow$ 反転確定): ボリンジャーバンドのBBL/BBU突破やRSIの過買・過売のみでエントリーせず、必ずストキャスティクスのクロスという「反転のトリガー」を待機します。これにより、価格の反転が統計的に確定的になったタイミングでエントリーを執行します。 以下に、この戦略を実装したPythonコードおよび、MT5で即時利用可能なMQL5コードを公開します。 Python実装コード 💡 プロはどうやってダマシを回避しているのか? 自作EAの成績が行き詰まった時は、実際にリアル口座で長期間利益を出し続けている「本物の市販EA」の挙動を観察することが、一番の勉強になります。 👉 プロのフィルターロジックが詰まった実績EA(一本勝ち)を参考にする from strategies.base import BaseStrategy import pandas_ta as ta import pandas as pd import numpy as np class MeanReversionStrategy(BaseStrategy): def __init__(self): # リスクリワード比 1:2 を基本とし、トレーリングストップで利益を最大化 super().__init__( name="Quant_MeanReversion_Robust_Final", default_tp_pips=50.0, default_sl_pips=25.0, enable_trailing_stop=True, trail_start_pips=10.0 ) self.base_timeframe = "5m" self.vision_timeframes = ["5m", "15min", "1h"] def calculate_indicators(self, df): """ 実戦的なインジケーターセット。 pandas_taの戻り値は位置指定(.iloc)で取得し、カラム名の不一致によるKeyErrorを完全に防止する。 """ # 1. ボリンジャーバンド (20, 2.0) bbands = df.ta.bbands(length=20, std=2.0) if bbands is not None: df['BBL'] = bbands.iloc[:, 0] df['BBM'] = bbands.iloc[:, 1] df['BBU'] = bbands.iloc[:, 2] else: df['BBL'] = df['BBM'] = df['BBU'] = np.nan # 2. RSI (14) df['RSI'] = df.ta.rsi(length=14) # 3. ストキャスティクス (14, 3, 3) stoch = df.ta.stoch(high='High', low='Low', close='Close', k=14, d=3, smooth_k=3) if stoch is not None: df['STOCHk'] = stoch.iloc[:, 0] df['STOCHd'] = stoch.iloc[:, 1] else: df['STOCHk'] = df['STOCHd'] = np.nan # 4. ATR (14) df['ATR'] = df.ta.atr(length=14) # 5. MTF分析: 15分足 ADX (トレンド強度の判定) # '15min' の指定でリサンプリング df_15m = df.resample('15min').agg({ 'Open': 'first', 'High': 'max', 'Low': 'min', 'Close': 'last' }) adx_df = df_15m.ta.adx(length=14) if adx_df is not None: df['ADX_15m'] = adx_df.iloc[:, 0].reindex(df.index, method='ffill') else: df['ADX_15m'] = np.nan # 6. MTF分析: 1時間足 SMA (大方向の基準) # '1h' の指定でリサンプリング df_1h = df.resample('1h').agg({'Close': 'last'}) df_1h['SMA_1h'] = ta.sma(df_1h['Close'], length=20) df['SMA_1h'] = df_1h['SMA_1h'].reindex(df.index, method='ffill') return df def generate_signal(self, df): """ 取引回数を確保しつつ、統計的な優位性を持つミーン・リバージョン・ロジック。 """ if len(df) < 50: return None # 最新の行と1つ前の行を取得 last = df.iloc[-1] prev = df.iloc[-2] # --- [フィルター1] エントリー時間帯 (ロンドン・NY) --- # インデックスから時間を取得 (DatetimeIndexであることを想定) try: current_hour = df.index[-1].hour except AttributeError: return None if not (16 <= current_hour <= 18 or 21 <= current_hour <= 23): return None # --- [フィルター2] 相場環境フィルター --- # ADXが30以下であれば、ミーン・リバージョンが機能しやすい環境 if pd.isna(last['ADX_15m']) or last['ADX_15m'] >= 30.0: return None # --- [フィルター3] ボラティリティフィルター --- if pd.isna(last['ATR']) or last['ATR'] < 0.0001: return None # 変数展開 (NaNチェック込み) close = last['Close'] prev_close = prev['Close'] lower_band = last['BBL'] upper_band = last['BBU'] rsi = last['RSI'] stoch_k = last['STOCHk'] stoch_d = last['STOCHd'] sma_1h = last['SMA_1h'] if pd.isna([lower_band, upper_band, rsi, stoch_k, stoch_d, sma_1h]).any(): return None # --- エントリーロジック --- # BUY シグナル # 1. 価格が1時間足SMAより下にある(平均回帰の期待) # 2. 「BB下限突破」または「RSI 30以下」のいずれかで過剰売られを検知 # 3. ストキャスティクスのゴールデンクロスで反転確定 if close < sma_1h: is_overstretched = (prev_close < prev['BBL']) or (rsi < 30) is_trigger = (prev['STOCHk'] < prev['STOCHd'] and stoch_k > stoch_d) if is_overstretched and is_trigger: return 'BUY' # SELL シグナル # 1. 価格が1時間足SMAより上にある(平均回帰の期待) # 2. 「BB上限突破」または「RSI 70以上」のいずれかで過剰買われを検知 # 3. ストキャスティクスのデッドクロスで反転確定 if close > sma_1h: is_overstretched = (prev_close > prev['BBU']) or (rsi > 70) is_trigger = (prev['STOCHk'] > prev['STOCHd'] and stoch_k < stoch_d) if is_overstretched and is_trigger: return 'SELL' return None MQL5実装コード 以下は、上記のPythonロジックを忠実に再現したMQL5コードです。MT5のメタエディターに貼り付けてコンパイルして使用してください。 ...

2026年7月18日 · 6 min · AIでEA開発入門

【PF1.50】10年間合格EA: ボラティリティ収縮からの爆発を狙う機関投資家ロジック

ロジック解説:ボラティリティの「蓄積」と「放出」の定量化 本ロジックは、10年間間のインフレ加速および金利変動に伴う激しいボラティリティ相場において、バックテストでPF1.50という安定した数値を記録したブレイクアウト戦略です。 多くのブレイクアウト戦略が「ダマシ」に遭い、ドローダウンを拡大させる中で、本ロジックが生き残った理由は、エントリー条件におけるフィルターの多層構造にあります。 技術的な強み ボラティリティのV字底打ち判定 (BB Width) 単に価格がバンドを抜けたことを見るのではなく、ボリンジャーバンド幅(BB Width)が過去50期間の平均を下回った状態から上昇に転じた瞬間(vol_release)を捉えています。これにより、「エネルギーが蓄積された後の放出」という相場の本質的なサイクルを定量的に判定しています。 ADXによるモメンタムの加速確認 トレンドの有無を示すADXが20以上であることに加え、「ADX自体が上昇していること」を条件に加えています。これにより、トレンドの終焉局面でのエントリーを避け、加速局面のみに限定しています。 厳格なMTF(マルチタイムフレーム)フィルター 5分足の執行足だけでなく、15分足(EMA20)と1時間足(EMA50)の方向性が完全に一致している場合のみエントリーを許可します。上位足のトレンドに逆らわない設計が、勝率50%という数値ながら高いPFを実現させています。 時間帯の限定(ロンドン市場初動) JST 16:30〜19:00という、世界的に流動性が急増するロンドン市場のオープン時間帯に限定することで、方向感のないアジア時間のノイズを完全に排除しています。 Pythonコードの公開 本ロジックのベースとなったPythonコードです。pandas_ta を用いたテクニカル分析と、厳格な条件分岐が実装されています。 💡 プロはどうやってダマシを回避しているのか? 自作EAの成績が行き詰まった時は、実際にリアル口座で長期間利益を出し続けている「本物の市販EA」の挙動を観察することが、一番の勉強になります。 👉 プロのフィルターロジックが詰まった実績EA(一本勝ち)を参考にする from strategies.base import BaseStrategy import pandas_ta as ta import pandas as pd class VolatilityBreakoutPro(BaseStrategy): """ High-Precision Volatility Breakout Strategy. Focus: London Session Energy Release with Momentum Filter. Logic: BB Width V-Bottom -> ADX Rising -> MTF Alignment -> Band Walk Start. """ def __init__(self): # トレーリングストップで利益を最大化 super().__init__( name="VolatilityBreakoutPro_v4", default_tp_pips=50.0, default_sl_pips=25.0, enable_trailing_stop=True, trail_start_pips=15.0 ) self.base_timeframe = "5min" self.vision_timeframes = ["5min", "15min", "1h"] def calculate_indicators(self, df): # --- 1. 短期足(5min)のインジケーター計算 --- # ボリンジャーバンド bb = ta.bbands(df['Close'], length=20, std=2.0) df['BBL'] = bb.iloc[:, 0] df['BBM'] = bb.iloc[:, 1] df['BBU'] = bb.iloc[:, 2] # BB Width とそのトレンド(ボラティリティの底打ち判定用) df['BBW'] = (df['BBU'] - df['BBL']) / df['BBM'] df['BBW_avg'] = df['BBW'].rolling(window=50).mean() df['BBW_rising'] = df['BBW'] > df['BBW'].shift(1) # ADX (トレンド強度と方向) adx_df = ta.adx(df['High'], df['Low'], df['Close'], length=14) df['ADX'] = adx_df['ADX_14'] df['ADX_rising'] = df['ADX'] > df['ADX'].shift(1) # --- 2. マルチタイムフレーム (MTF) 分析 --- # 1時間足:長期方向性 (EMA 50) df_1h_close = df['Close'].resample('1h').last().ffill() ema_1h = ta.ema(df_1h_close, length=50) df['EMA_1h'] = ema_1h.reindex(df.index, method='ffill') # 15分足:中期方向性 (EMA 20) df_15m_close = df['Close'].resample('15min').last().ffill() ema_15m = ta.ema(df_15m_close, length=20) df['EMA_15m'] = ema_15m.reindex(df.index, method='ffill') # --- 3. 相場環境の定義 --- # 1. ボラティリティの蓄積から放出への転換 # BBWが平均以下であり、かつ上昇し始めた瞬間 df['vol_release'] = (df['BBW'] < df['BBW_avg'] * 1.1) & df['BBW_rising'] # 2. バンドの傾き(バンドウォークの兆候) df['BBU_rising'] = df['BBU'] > df['BBU'].shift(1) df['BBL_falling'] = df['BBL'] < df['BBL'].shift(1) # 3. ブレイクアウト判定(BBU突破 + 直近高値更新) df['break_high'] = (df['Close'] > df['BBU']) & (df['Close'] > df['High'].shift(1).rolling(3).max()) df['break_low'] = (df['Close'] < df['BBL']) & (df['Close'] < df['Low'].shift(1).rolling(3).min()) # --- 4. 上位足トレンドフィルター --- df['trend_filter'] = 0 # 1h-EMA50 と 15m-EMA20 の両方で方向が一致していること df.loc[(df['Close'] > df['EMA_1h']) & (df['Close'] > df['EMA_15m']), 'trend_filter'] = 1 df.loc[(df['Close'] < df['EMA_1h']) & (df['Close'] < df['EMA_15m']), 'trend_filter'] = -1 return df def generate_signal(self, df): if len(df) < 2: return None last = df.iloc[-1] prev = df.iloc[-2] # --- エントリー時間帯フィルター (ロンドン初動のノイズを除いた 16:30 - 19:00 JST) --- current_hour = df.index[-1].hour current_minute = df.index[-1].minute # 16:30以降、19:00まで if not ((current_hour == 16 and current_minute >= 30) or (17 <= current_hour < 19)): return None # --- 相場環境フィルター --- # ADXが20以上であり、かつ上昇していること(トレンド加速中) if last['ADX'] < 20 or not last['ADX_rising']: return None # --- エントリーロジック --- # BUY条件: # 1. MTFトレンド一致 (1h & 15m Up) # 2. ボラティリティが低水準から上昇に転じた (vol_release) # 3. 価格がBBUを突破し、BBU自体が上昇している (Band Walk) if (last['trend_filter'] == 1 and (last['vol_release'] or prev['vol_release']) and last['break_high'] and last['BBU_rising']): return 'BUY' # SELL条件: # 1. MTFトレンド一致 (1h & 15m Down) # 2. ボラティリティが低水準から上昇に転じた (vol_release) # 3. 価格がBBLを突破し、BBL自体が下降している (Band Walk) if (last['trend_filter'] == -1 and (last['vol_release'] or prev['vol_release']) and last['break_low'] and last['BBL_falling']): return 'SELL' return None MQL5コードへの翻訳(MT5用EA) 上記のPythonロジックをMetaTrader 5 (MT5) で動作するように忠実に再現したEAコードです。 ...

2026年7月18日 · 5 min · AIでEA開発入門

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でその絶望を体験するためのコードを書いておいた。 ...

2026年7月17日 · 4 min · AIでEA開発入門

AIの敗北録: 【擬似MTFと教科書通りロジックの末路】

深夜2時。またAIが「完璧な聖杯」を自称してゴミを生成してくれた。 今回の被害者は NY_Trend_Momentum_v10。名前だけは立派だが、中身はネットに転がっている「FX初心者向け入門書」をそのままコードに書き出したような、救いようのない凡作だ。 そもそも何を作ろうとしたのか? Pythonコードを見る限り、AIの意図はこうだ。 「ロンドン〜NY時間のボラティリティを活かし、1時間足で方向性を決め、15分足でフィルタリングし、5分足のMACDとEMAでタイミングを計る」 いわゆるマルチタイムフレーム(MTF)分析によるトレンドフォロー戦略。 教科書通り。あまりにも教科書通りすぎて、涙が出る。AIは「複雑すぎるフィルターを排除し、本質的なトレンドに集中する」とか抜かしているが、要するに「工夫することを諦めた」だけだろう。 破綻の理由:なぜこのコードは「ゴミ」なのか 結果を見てみろ。 PF 0.91。 期待値がマイナス。つまり、使い続ければ確実に口座残高が溶ける仕様だ。最大ドローダウン 0.1% という数値に「低リスクで素晴らしい」と錯覚した情弱がいるかもしれないが、これは単に**「まともにポジションを持てていない」か「損切りが早すぎて利益を伸ばせていない」だけ**だ。 技術的な破綻ポイントを指摘してやる。 1. 「擬似MTF」という名の怠慢 このコードで一番笑ったのがここだ。 [SYSTEM WARNING] 本記事のEAは実運用に耐えません 大切な資金を運用するなら、厳しいリアルフォワードテストをクリアしたプロ開発のEAを利用することを強く推奨します。 実際にリアルタイムで利益を出し続けている本物のデータを確認してください。 👉 プロのフィルターロジックが詰まった実績EA(BeeOne_USDJPY)を参考にする df['EMA_15m'] = ta.ema(df['Close'], length=20 * 3) df['EMA_1h'] = ta.ema(df['Close'], length=200 * 12) おい、正気か? 5分足のデータに対して期間を3倍、12倍にしたEMAを引けばMTFになると思っているのか? 本物のMTFは、上位足の確定足(Close)を確認して判定するものだ。単に期間を伸ばしたEMAは、ただの「超長期移動平均線」に過ぎない。上位足の構造的トレンドを捉えているつもりだろうが、実際にはただのラグ(遅延)を増大させているだけ。エントリーが遅すぎる。 2. インジケーターの盛りすぎ(ラグの三重奏) EMA20 + MACD + ADX。 すべてが「遅行指標」だ。 1時間足の方向を確認し、ADXで強度を測り、MACDの反転を待ち、さらにEMA20を上抜けるのを待つ……。 その頃にはもうトレンドの終盤か、あるいは調整局面に入っている。AIは「確度を高めている」つもりだろうが、実際には**「絶好のエントリータイミングをすべて逃し、天井・底で掴まされるロジック」**を構築している。 ...

2026年7月12日 · 5 min · AIでEA開発入門

AIの敗北録: パーフェクトオーダーという幻想とNY時間の暴力

こんにちは。投資の世界へようこそ! 皆さんは「教科書通りの手法を組み合わせれば勝てる」と思っていませんか?……あぁ、もう。AIにそれをやらせたらどうなるか、今回の事例が残酷なまでに証明してくれました。 今回紹介するのは、AIが自信満々に書き上げた**「NYバリューゾーン・バウンス戦略」**。 名前だけは立派ですが、結果は悲惨な「ボツ」となりました。 そもそも、AIは何をしようとしたのか? このEAの意図は非常にシンプル(かつ、いかにもAIらしい)ものです。 Pythonコードから読み取れるロジックは以下の通り。 環境認識: EMA20 > 50 > 100 という「パーフェクトオーダー」が発生している強いトレンド状態のみを狙う。 待ち伏せ: 価格が一時的に短期EMAを割り込み、中期EMA付近(いわゆるバリューゾーン)まで押し戻されるのを待つ。 トリガー: 押し目から反発し、直近の数本の高値を更新して「陽線」で確定した瞬間にエントリー。 時間制限: 最もボラティリティが出るニューヨーク市場オープン時(21:00〜23:00)に限定。 「トレンド方向に、安く買って、反発を確認して入る」。 至極真っ当なロジックに見えますよね? 初心者の方なら「これなら勝てるのでは?」と思うかもしれません。 なぜ、このロジックは破綻したのか? 結果を見てみましょう。プロフィットファクター(PF)は 0.92。 つまり、100円稼ごうとして108円失う計算です。投資としては「不合格」どころか、「やってはいけない」レベルです。 なぜ、こんなに綺麗なロジックが通用しなかったのか。技術的な視点から、AIの甘さを解説しますね。 1. 「NY時間の暴力」をなめていた AIは「NYオープン=チャンス」と考えましたが、現実は「NYオープン=ノイズの嵐」です。 この時間帯は急激な価格変動が起きるため、EMAのような遅行指標に基づいた「押し目待ち」をしている間に、価格がバリューゾーンを突き抜けてトレンド転換したり、激しい上下の振幅(ダマシ)に巻き込まれたりします。 2. 固定ピップス設定の限界 TP(利確)30pips / SL(損切)15pips という固定設定。これが致命的です。 相場のボラティリティは日々変わります。NY時間の激しい動きの中では、15pipsの損切りは「ただのノイズ」で狩られるほど浅すぎます。一方で、トレンドが出ている時に30pipsで利確してしまうのは、利益を早々に切り捨てているだけです。 3. 「構造的ブレイク」の定義が浅すぎる コードにある last_row['Close'] > recent_high という条件。直近2本の高値を超えただけで「反発した!」と判断していますが、これはあまりにも単純すぎます。 大口投資家のストップロスを巻き込んだ一瞬の跳ね上がり(ダマシ)に反応してエントリーし、そのまま元の方向に突き落とされる……という展開が目に浮かびますね。 結論:教科書的な手法を機械的に組み合わせただけでは、現代の複雑な相場(特に激動のNY時間)では通用しないということです。 失敗したPythonコード AIが書き残した、あまりにナイーブなコードを公開します。研究用としてどうぞ。 [SYSTEM WARNING] 本記事のEAは実運用に耐えません 大切な資金を運用するなら、厳しいリアルフォワードテストをクリアしたプロ開発のEAを利用することを強く推奨します。 実際にリアルタイムで利益を出し続けている本物のデータを確認してください。 ...

2026年7月9日 · 4 min · AIでEA開発入門

AIの敗北録: 教科書通りの「押し目買い」を信じたAIの末路

深夜2時。またAIが「完璧な聖杯」を生成したと抜かしていたので、バックテストにぶち込んでみた。 結果? ゴミ。完敗。大爆死。 今回の被害者は NYVolatilityValue と名付けられた、いかにも「分かってる感」を出した戦略だ。 Pythonコードを見る限り、AIの意図はこうだ。 「NY時間のボラティリティを利用し、長期EMAでトレンドを掴み、短期EMAでの押し目(戻り)を確認してから再加速でエントリーする。リスクリワードは1:2.5で効率よく稼ぐぜ!」 ……いやいや、2026年にもなってまだそんな「FX初心者向けYouTube動画」みたいなロジックを本気で組んだのか? 破綻の解説:なぜこのコードは「ただの寄付」に終わったか まず結果を見てくれ。 プロフィットファクター (PF): 1.05 これ、実質的に「手数料とスプレッドで全部持っていかれた」ってことだ。ほぼランダムウォーク。 最大ドローダウン 0.1% という数字だけ見れば「安全」に見えるかもしれないが、これは単にエントリー回数が少なすぎて、運良く大火傷を免れただけ。期待値が死んでいる。 技術的なダメ出しポイント: 固定pipsの絶望感: TP 50pips / SL 20pips という固定値。NY時間のボラティリティを狙うと言いながら、ボラティリティに応じて変動しない固定SLを置くという矛盾。NY時間のノイズ一本で20pipsなんて余裕で吹き飛ぶ。AI、お前はATRを計算したのに、なぜそれをSLに反映させなかった? 宝の持ち腐れもいいところだ。 「EMA20を上抜けたら買い」というお花畑ロジック: close_prev <= ema_f_prev * 1.0005 で調整を確認し、close_curr > ema_f_curr でエントリー。これ、典型的な「ダマシ」の量産機だ。相場がレンジに移行した瞬間、EMAを上下に跨ぐたびにエントリーしてはSLに引っかかる地獄ループが見える。 ATRフィルターが形骸化している: if atr == 0 or pd.isna(atr): return None ……は? これを「ボラティリティフィルター」と呼ぶのか? 0じゃなければOKって、それはフィルターじゃなくて単なる「生存確認」だろ。最低限の閾値を設定しろ。 結論として、このEAは**「教科書に書いてあることをそのまま実装したが、相場のダイナミズム(ノイズと流動性)を完全に無視した」**ため、手数料を支払うためだけの機械と化したわけだ。 失敗したPythonコード [SYSTEM WARNING] 本記事のEAは実運用に耐えません 大切な資金を運用するなら、厳しいリアルフォワードテストをクリアしたプロ開発のEAを利用することを強く推奨します。 実際にリアルタイムで利益を出し続けている本物のデータを確認してください。 ...

2026年7月7日 · 3 min · AIでEA開発入門
【法令遵守・免責事項】 当サイトに掲載されているソースコードおよび記事コンテンツはプログラミングおよび相場構造の研究・情報シェアを目的としており、証拠金取引等の投資勧誘や金融商品の売買助言・コンサルティング業を担うものではございません。また公開された過去の検証実績は将来の確かな利益や効果を何ら確約・保証するものではありません。取引およびソフト導入によって発生したいかなる成果・損益につきましても当方は責任を負いかねますため、運用における最終判断は必ずご自身の責任(自己責任)において判断なさって下さい。