【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開発入門

AIの敗北録: 過剰フィルターという名の「完璧主義的な自殺」

また出たよ。最近のAIが書き出す「いかにも正解っぽく見えるゴミ」だ。 今回の標本は、NY市場のボラティリティを狙ったという『NYStructureTrend』。 ロジックを紐解けば、長期EMAで環境認識をし、短期EMAへのプルバックを待ち、出来高を確認し、直近高値・安値のブレイクでエントリーする……という、FXの入門書に書いてある「正解」を全部盛り込んだような構成だ。 AIはきっとこう思ったんだろう。「条件を重ねれば重ねるほど、勝率は上がり、リスクは減る」と。 だが、相場の本質を理解していない人間(とAI)が陥る最大の罠がここにある。 破綻の理由:フィルターの積み上げによる「取引機会の絶滅」 まずはこの絶望的なバックテスト結果を見てくれ。 取引回数: 0回 プロフィットファクター (PF): 0.00 最大ドローダウン: 0.0% 笑わせるな。ドローダウン0%? それは「勝った」のではなく、「戦場にすら立てなかった」ということだ。 なぜこうなったか? 技術的に解説してやる。このEAは**「フィルターの過剰積載」**で自死したんだ。 時間帯の極端な制限: JST 21:00〜23:00の2時間のみ。 環境認識の硬直化: EMA200の傾きと価格位置という、遅行指標による二重チェック。 プルバックの厳格な定義: EMA20に「接近または下回ること」というピンポイントな要求。 出来高のハードル: 平均の80%以上の出来高を要求。 構造的ブレイクの確定: さらに直近2本の高値を抜けるというトリガー。 これらすべてが「同時に」成立する確率を計算してみろ。 「トレンドが出ていて、かつ、ちょうどいいタイミングで押し目を作り、かつ、十分な出来高があり、かつ、タイミングよく直近高値を抜ける」……そんな都合のいいタイミングが、5分足のわずか2時間枠の中で、2年間一度も起きなかったということだ。 AIは「期待値」ではなく「条件の整合性」だけを追い求めた。 実際の相場はもっと泥臭い。インジケーターが完璧に整うのを待っていたら、美味しいところは全部食い尽くされている。裁量トレーダーが意識するのは「条件の合致」ではなく「相場のリズム」と「不均衡」だ。 このコードは、教科書を丸暗記して試験には満点を取るが、実戦では一歩も動けない臆病者の思考そのものだ。 失敗したPythonコード [SYSTEM WARNING] 本記事のEAは実運用に耐えません 大切な資金を運用するなら、厳しいリアルフォワードテストをクリアしたプロ開発のEAを利用することを強く推奨します。 実際にリアルタイムで利益を出し続けている本物のデータを確認してください。 👉 プロのフィルターロジックが詰まった実績EA(White Bear Z USDJPY)を参考にする from strategies.base import BaseStrategy import pandas as pd import pandas_ta as ta class NYStructureTrend(BaseStrategy): """ NY市場オープン時間帯の構造的転換を狙う戦略。 EMA200の傾きで環境を定義し、EMA20へのプルバック後、出来高を伴う直近高値/安値更新でエントリーする。 """ def __init__(self): # NY市場のボラティリティに合わせ、SLを20pipsに広げて「呼吸」をさせ、TPを35pipsに設定 super().__init__(name="NY_Structure_Trend", default_tp_pips=35.0, default_sl_pips=20.0) self.base_timeframe = "5m" self.vision_timeframes = ["5m", "15m", "1h"] # パラメータ self.slow_ema_period = 200 # 長期トレンド方向 self.fast_ema_period = 20 # 価値領域(プルバック基準) self.vol_ma_period = 20 # 出来高平均判定用 def calculate_indicators(self, df): """ テクニカル指標の計算。 """ # 長期EMA (環境認識) df['ema_slow'] = ta.ema(df['Close'], length=self.slow_ema_period) # 短期EMA (プルバック基準) df['ema_fast'] = ta.ema(df['Close'], length=self.fast_ema_period) # 出来高の移動平均 (ボラティリティ・流動性判定) df['vol_ma'] = df['Volume'].rolling(window=self.vol_ma_period).mean() return df def generate_signal(self, df): """ 最新の足に基づいて売買シグナルを生成する。 """ if len(df) < self.slow_ema_period + 5: return None curr = df.iloc[-1] prev = df.iloc[-2] prev_prev = df.iloc[-3] # --- 時間帯フィルタ (JST 21:00 - 23:00) --- current_time_jst = df.index[-1].tz_localize('UTC').tz_convert('Asia/Tokyo') hour = current_time_jst.hour if not (21 <= hour < 23): return None # --- 1. MTF環境認識 (トレンドの方向性と強さ) --- # EMA200が明確に上向きであり、価格がその上にあること is_bullish_env = (curr['Close'] > curr['ema_slow']) and (curr['ema_slow'] > prev['ema_slow']) # EMA200が明確に下向きであり、価格がその下にあること is_bearish_env = (curr['Close'] < curr['ema_slow']) and (curr['ema_slow'] < prev['ema_slow']) # --- 2. 出来高フィルター (本物の動きかどうかの判定) --- # 現在の出来高が平均の80%以上であることを条件とし、死んだ相場を排除 has_volume = curr['Volume'] > (curr['vol_ma'] * 0.8) # --- 3. プライスアクション・トリガー (構造的ブレイク) --- # 【BUYトリガー】 # A. 強気環境であること # B. プルバック: 前回の足の安値がEMA20に接近、または下回った(押し目の形成) # C. 構造的ブレイク: 今回の終値が「前回と前々回の足の最高値」を上抜いた(反転の確定) bullish_pullback = prev['Low'] <= prev['ema_fast'] * 1.0005 bullish_breakout = curr['Close'] > max(prev['High'], prev_prev['High']) # 【SELLトリガー】 # A. 弱気環境であること # B. プルバック: 前回の足の高値がEMA20に接近、または上回った(戻りの形成) # C. 構造的ブレイク: 今回の終値が「前回と前々回の足の最低値」を下抜いた(反転の確定) bearish_pullback = prev['High'] >= prev['ema_fast'] * 0.9995 bearish_breakout = curr['Close'] < min(prev['Low'], prev_prev['Low']) # --- シグナル確定 --- if has_volume and is_bullish_env and bullish_pullback and bullish_breakout: return 'BUY' if has_volume and is_bearish_env and bearish_pullback and bearish_breakout: return 'SELL' return None オマケ(MQL5変換) 「こんなに厳格な条件なら、MT5の高速バックテストで10年分回せば1回くらいはエントリーするだろう」という、絶望的な好奇心を持つ物好きな方のために、MQL5に書き換えておいた。 ...

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

AIの敗北録: 5本の足で『構造』と呼ぶ傲慢さとEMA200の呪い

深夜2時。またAIが「完璧なロジックを生成しました!」みたいな顔してゴミを量産してる。 今回もまた、教科書通りの「それっぽい」手法を盛り込んだだけの、実戦完全無視なボツEAが爆誕した。 今回のターゲットは**「NYオープン時間帯の構造的ブレイクアウト」**。 Pythonコードを眺める限り、AIの思考回路はこうだ。 「NY時間はボラが出る(常識) → EMA200でトレンド方向を固定する(教科書1ページ目) → 直近のレンジを抜けた方向にエントリーする(初心者向け手法) → でも大陽線・大陰線は『クライマックス』だから避ける(ここが致命的な勘違い)」 ……いや、NY時間のボラティリティを狙っておいて、強い動きを「クライマックス」として排除するってどういう脳内回路だよ。正気か? 絶望のバックテスト結果 PF: 0.86(はい、勝ち少ない。手数料とスプレッドで死ぬパターン) 最大ドローダウン: 0.1%(一見低く見えるが、単にリスクを取りすぎていないか、取引回数に対して期待値が低すぎて資金がじりじりと削られただけの結果) 不合格理由: 10年間間のPFが1.2を余裕で下回った。 技術的な「破綻」ポイント:なぜ負けるのか 1. 「構造(Structure)」の定義が幼稚園レベル lookback_period = 5。5分足の5本分、つまり「直近25分間の高値・安値」を構造と呼んでいる。 おい、それは「構造」じゃなくてただの「ノイズ」だ。相場の構造(Structure)を語るなら、最低でも1時間足や4時間足の意識されるレベルを追え。25分のレンジブレイクなんて、スプレッドの変動レベルで簡単にダマシに合う。 2. 自殺志願のような「クライマックス・フィルタ」 body_size < (curr['atr'] * 2.5) ここがこのコードの最大のギャグ。NY時間のブレイクアウト戦略において、最も利益が出るのは「強い方向感が出たとき」だ。それを「実体が大きすぎるから天井/底かも」という妄想でフィルタリングしている。 つまり、**「本当に強いトレンドが出たときだけエントリーを回避し、迷いのある弱い動きのときだけエントリーする」**という、負けるためだけの完璧なロジックが完成している。天才か。 3. 固定TP/SLの思考停止 TP 30 / SL 15 という固定ピプス設定。 ボラティリティが激しく変動するNY時間に、ATRを計算しておきながら利確・損切りにそれを反映させない。これじゃあ、ボラが大きい日は一瞬で狩られ、ボラが小さい日は利確まで届かずに戻ってくる。 結論:このEAは**「トレンドの初動を逃し、ノイズに飛び乗り、正解の波だけを拒絶する」**という、トレードにおける禁忌を全て詰め込んだ芸術作品である。 敗北のコード(Python) [SYSTEM WARNING] 本記事のEAは実運用に耐えません 大切な資金を運用するなら、厳しいリアルフォワードテストをクリアしたプロ開発のEAを利用することを強く推奨します。 実際にリアルタイムで利益を出し続けている本物のデータを確認してください。 ...

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

AIの敗北録: 【教科書的なトレンドフォローとレンジブレイクの絶望的なミスマッチ】

またAIが「完璧なロジック」を自称してゴミを量産した。 今回の被験体は、NYオープンという相場のボラティリティが最大化する時間帯を狙った「レンジブレイクアウト戦略」だ。Pythonコードを見る限り、AIの意図は明確だった。 環境認識: EMA50とEMA200のパーフェクトオーダーでトレンド方向を固定。 トリガー: 直近1時間の高値・安値を終値でブレイク。 フィルター: EMA200からの乖離を制限し、「高値掴み・安値掴み」を防止。 時間限定: NYオープン(JST 21-23時)という、最も「動きがある」時間帯に限定。 一見すると、リスク管理とトレンドフォローを兼ね備えた堅実な戦略に見える。だが、結果は惨敗。PF 0.84という、時間をかけて資金を溶かす典型的な「負けパターン」に陥った。 なぜこのロジックは「ゴミ」なのか 結論から言えば、「遅行指標によるトレンド判定」と「短期レンジブレイク」の相性が最悪だからだ。 1. 遅行性のダブルパンチ EMA50とEMA200のパーフェクトオーダーを確認してエントリーする。この時点で、5分足レベルのトレンドは既に中盤から終盤に差し掛かっていることが多い。そこにさらに「直近1時間の高値ブレイク」という条件を加えるため、エントリータイミングは常に「トレンドの天井・底」付近になる。 2. NYオープンの「ダマシ」を正解だと思い込んでいる NYオープン時間帯は、方向感を決める前の激しい上下振幅(ウィップソー)が頻発する。12本(1時間)程度の狭いレンジをブレイクしたからといって、それがトレンドの継続を意味することは少ない。むしろ、AIが「完璧なトレンドだ」と判定して飛び乗った瞬間が、大口の利益確定による反転ポイントになるという皮肉な結果を招いている。 3. 最大ドローダウン 0.1% の正体 一見、最大DD 0.1%という数字は驚異的な安定感に見える。だが、クオンツ的に見ればこれは「リスクを取っていない」のではなく、**「損切り(SL 15pips)が浅すぎて、方向性が出る前に速攻で切られている」**だけのことだ。PF 0.84という数値が示す通り、勝ちを伸ばせず、負けを頻発させているだけ。安定して負けているだけである。 AIは「教科書に書いてある条件」を組み合わせれば勝てると信じているようだが、相場は足し算で解決するほど単純ではない。 失敗したPythonコード [SYSTEM WARNING] 本記事のEAは実運用に耐えません 大切な資金を運用するなら、厳しいリアルフォワードテストをクリアしたプロ開発のEAを利用することを強く推奨します。 実際にリアルタイムで利益を出し続けている本物のデータを確認してください。 👉 プロのフィルターロジックが詰まった実績EA(Pips_miner_EA)を参考にする from strategies.base import BaseStrategy import pandas as pd import pandas_ta as ta class NYRangeBreakout(BaseStrategy): """ NYオープン時間帯に特化したMTFレンジブレイクアウト戦略。 EMA 50/200による強力なトレンドフィルターを掛け、 直近1時間(12本分)の最高値/最安値を終値でブレイクした瞬間のみにエントリーを絞る。 """ def __init__(self): # 勝率と利益のバランスを最適化した設定 super().__init__(name="NYRangeBreakout", default_tp_pips=25.0, default_sl_pips=15.0) self.base_timeframe = "5m" self.vision_timeframes = ["5m", "15m", "1h"] def calculate_indicators(self, df): """ MTFトレンド判定およびブレイクアウト判定用の指標を計算。 """ # 中期トレンドフィルター (15m相当) df['ema_mid'] = ta.ema(df['Close'], length=50) # 長期トレンドフィルター (1h相当) df['ema_long'] = ta.ema(df['Close'], length=200) # 直近12本(1時間分)の最高値と最安値を計算 (ブレイクアウト判定用) # shift(1)することで、現在の足を含めない「直近の壁」を定義する df['range_high'] = df['High'].rolling(window=12).max().shift(1) df['range_low'] = df['Low'].rolling(window=12).min().shift(1) return df def generate_signal(self, df): """ NYオープン時間帯に、MTFトレンドが一致し、かつ1時間レンジをブレイクした時にシグナルを出す。 """ if len(df) < 200: return None # 最新の足を取得 current_bar = df.iloc[-1] # --- 時間帯判定 (JST 21:00 - 23:00) --- # JST 21:00 = UTC 12:00 / JST 23:00 = UTC 14:00 current_hour = current_bar.name.hour if not (12 <= current_hour < 14): return None # --- 変数抽出 --- close = current_bar['Close'] ema_m = current_bar['ema_mid'] ema_l = current_bar['ema_long'] range_h = current_bar['range_high'] range_l = current_bar['range_low'] # --- エントリーロジック --- # BUY: # 1. MTF環境認識: 価格 > EMA50 > EMA200 (完璧な上昇トレンドの並び) # 2. ブレイク判定: 終値が直近12本(1時間)の最高値を明確に上抜けた if (close > ema_m) and (ema_m > ema_l): if close > range_h: # 乖離フィルター: 長期EMAから離れすぎている場合は飛び乗りと判断 if close < ema_l * 1.01: return 'BUY' # SELL: # 1. MTF環境認識: 価格 < EMA50 < EMA200 (完璧な下降トレンドの並び) # 2. ブレイク判定: 終値が直近12本(1時間)の最安値を明確に下抜けた if (close < ema_m) and (ema_m < ema_l): if close < range_l: # 乖離フィルター if close > ema_l * 0.99: return 'SELL' return None オマケ:MQL5への変換 「この絶望感をMT5で体感したい」という物好きな方のために、上記ロジックをMQL5に移植した。検証環境でぜひ、資金がじわじわと削られていく快感を味わってほしい。 ...

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

AIの敗北録: 過剰適合の幻想と致命的な型エラー

導入:AIが夢見た「完璧なブレイクアウト」 今回のボツEAは、AIが「ボラティリティの凝縮から拡散への転換点」を捉えようとして設計した、いわゆるボラティリティ・スクイーズ戦略です。 Pythonコードから読み取れるAIの意図は以下の通りです。 長期的な方向性の確認: 線形回帰の傾き(Slope)と効率比(Efficiency Ratio)を用いて、「ノイズではない明確なトレンド」があることを確認する。 エネルギーの蓄積を検知: 短期ボラティリティと長期ボラティリティの比率を算出し、相場が「スクイーズ(凝縮)」状態にあることを定義する。 構造的なブレイクアウト: スクイーズ期間中の高値・安値を更新し、かつ「強すぎず弱すぎない」適度なモメンタム(Impulse Intensity)を伴って抜けた瞬間にエントリーする。 理論だけを見れば、非常に「クオンツらしく」知的なアプローチに見えます。しかし、結果は無残なものでした。 破綻の解説:知的な装いをした「ただのゴミ」 このEAが敗北した理由は、単なるコードのバグだけではありません。行動経済学的な観点から見れば、これは**「コントロールの錯覚(Illusion of Control)」**に陥った典型的な事例です。 1. 致命的な実装ミス(技術的破綻) まず、このEAはバックテストにすら到達していません。 Execution Error: 'numpy.float64' object has no attribute 'shift' という、あまりにも初歩的なエラーで自爆しています。generate_signal関数内で、単一の行(Series)であるlast['squeeze_high']に対して.shift(1)を呼び出そうとしています。.shift()は pandas の Series や DataFrame のメソッドであり、数値(float64)に対しては使えません。 AIは「過去のデータを参照する」という概念をコードに盛り込みましたが、「今、自分が扱っている変数が『配列』なのか『単一の値』なのか」という型定義の意識が完全に欠落していたのです。 2. 過剰適合(Overfitting)の罠 仮にバグを修正したとしても、このロジックが現実の相場で通用する可能性は極めて低いです。 vol_ratio < 0.85 er_l > 0.25 0.7 < impulse_rel < 3.0 pds > 0.6 これらの数値(しきい値)はどこから来たのでしょうか?根拠のない「魔法の数字」を並べてフィルターを重ねる行為は、過去データに無理やり合わせた**カーブフィッティング(過剰適合)**そのものです。フィルターを増やせば増やすほど、バックテストの数字は綺麗になりますが、未知の相場(アウトオブサンプル)では全く機能しません。 3. 「ダマシ」への無知 ボラティリティ・スクイーズ後のブレイクアウトは、機関投資家にとって絶好の「流動性狩り(ストップ狩り)」の標的です。AIは「適度なインパルス(Impulse)」でダマシを回避できると考えていたようですが、現実の市場では、最も「正しそうに見えるブレイク」こそが、逆方向に突き抜ける罠になることが多々あります。 このEAは、数学的な美しさに酔いしれ、相場の本質である**「不確実性と騙し合い」**という心理的側面を完全に無視した、机上の空論に過ぎなかったと言えるでしょう。 Pythonコードの公開(失敗作) [SYSTEM WARNING] 本記事のEAは実運用に耐えません 大切な資金を運用するなら、厳しいリアルフォワードテストをクリアしたプロ開発のEAを利用することを強く推奨します。 実際にリアルタイムで利益を出し続けている本物のデータを確認してください。 ...

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

AIの敗北録: 統計的アノマリーという幻想と「過剰エンジニアリング」の末路

またAIが「完璧な聖杯」を夢見て、壮大なゴミを生成してくれた。 今回の被験体は、名付けて**「Symmetry-Based Vacuum Expansion (SVE)」**。 名前だけ見れば、ヘッジファンドのクオンツが深夜のホワイトボードで書き殴ったような、いかにも「凄そうな」雰囲気を出している。 ロジックの意図をPythonコードから読み解くと、AIは「相場のエネルギー蓄積(Coiling)からの爆発的解放(Vacuum Expansion)」を捉えようとしたらしい。具体的には、ローソク足の「実体比率(Symmetry)」で方向性を確認し、「価格変化率のZスコア(Velocity Z-Score)」で統計的な異常値を検知し、さらに「中央値からの乖離(Tension)」で高値掴みを回避するという、三段構えのフィルターを構築している。 なるほど、理屈は立っている。だが、相場は数式通りに動くほど親切ではない。 惨敗の分析:なぜこのロジックは「ゴミ」なのか バックテストの結果を見てみよう。 プロフィットファクター (PF): 0.92。 結論から言えば、手数料とスプレッドを考慮すれば、このEAを動かすことは「電子的な寄付」に等しい。最大ドローダウンが0.1%という数値だけを見れば「安全」に見えるかもしれないが、これは単にリスクを取りすぎていない(あるいは取引機会を絞りすぎている)だけであり、期待値が1を割っている以上、運用すればするほど口座残高は緩やかに、しかし確実に死に至る。 技術的な破綻理由は主に3点だ。 1. 「Zスコア > 2.0」という遅効性の罠 AIはZスコアを用いて「統計的な異常値(Vacuum)」をトリガーにした。しかし、Zスコアが2.0を超えるということは、すでに価格が急激に動いた後であることを意味する。 つまり、このEAは「爆発の瞬間」ではなく、「爆発しきった後の末端」でエントリーしている。典型的な「追っかけ買い・売り」だ。 2. 「対称性(Symmetry)」という名のノイズ 実体とヒゲの比率で方向性を判定しているが、5分足レベルでのこの数値は極めてノイズが多い。強いトレンドが出ている時こそヒゲが出ることも多く、このフィルターがあるせいで、真のトレンド発生時にエントリーを拒否し、レンジ内の小さなボラティリティに反応するという本末転倒な挙動を繰り返していたと推測される。 3. 絶望的なTP/SL比 TP 20pips / SL 15pips。 統計的アノマリーを狙う戦略でありながら、利確幅が極めて狭い。Zスコアで捉えた「爆発」に乗るなら、本来はトレンドを伸ばすべきだが、このEAは小刻みに利確しようとした。結果として、たまに発生する大きな逆行(ダマシ)で利益をすべて吐き出し、PF 0.92という絶望的な数字に落ち着いたわけだ。 要するに、「凝った指標を組み合わせれば勝てる」というAI特有の過剰エンジニアリングの典型例である。 失敗したPythonコード AIが自信満々に書き出した、美しくも役に立たないコードがこちらだ。 [SYSTEM WARNING] 本記事のEAは実運用に耐えません 大切な資金を運用するなら、厳しいリアルフォワードテストをクリアしたプロ開発のEAを利用することを強く推奨します。 実際にリアルタイムで利益を出し続けている本物のデータを確認してください。 👉 プロのフィルターロジックが詰まった実績EA(White Bear Z USDJPY)を参考にする import pandas as pd import numpy as np from strategies.base import BaseStrategy class SVEStrategy(BaseStrategy): """ Symmetry-Based Vacuum Expansion (SVE) Strategy This strategy identifies high-probability impulse moves by detecting the transition from a 'Coiling' state to a 'Vacuum Expansion' state, synchronized across multiple timeframes using Body-to-Range Symmetry and Velocity Z-Scores. """ def __init__(self): # Optimized TP/SL to capture the initial impulse and exit before mean reversion super().__init__(name="SVE_Vacuum_Expansion_Quant", default_tp_pips=20.0, default_sl_pips=15.0) self.base_timeframe = "5m" self.vision_timeframes = ["5m", "15m", "1h"] # Window settings self.macro_window = 12 # 1h equivalent self.meso_window = 3 # 15m equivalent self.stat_window = 20 # Window for Z-score and volatility self.tension_limit = 0.5 # Maximum allowed tension to prevent chasing def calculate_indicators(self, df): """ Compute Symmetry Conviction, Velocity Z-Score, and Macro Tension. """ # --- 1. Symmetry Conviction (Body-to-Range Ratio) --- df['range'] = df['High'] - df['Low'] df['body'] = df['Close'] - df['Open'] df['symmetry'] = df['body'] / (df['range'] + 1e-9) # MTF Symmetry: Average conviction over meso and macro windows df['symmetry_meso'] = df['symmetry'].rolling(window=self.meso_window).mean() df['symmetry_macro'] = df['symmetry'].rolling(window=self.macro_window).mean() # --- 2. Velocity Z-Score (The Vacuum Trigger) --- # Calculate the raw velocity (rate of change) df['velocity'] = df['Close'].diff(1) df['vel_mean'] = df['velocity'].rolling(window=self.stat_window).mean() df['vel_std'] = df['velocity'].rolling(window=self.stat_window).std() df['vel_zscore'] = (df['velocity'] - df['vel_mean']) / (df['vel_std'] + 1e-9) # --- 3. Macro Tension & Equilibrium --- # Use median of midpoints for a robust equilibrium df['midpoint'] = (df['High'] + df['Low']) / 2 df['macro_median'] = df['midpoint'].rolling(window=self.macro_window).median() # Macro Range for tension normalization df['macro_max'] = df['High'].rolling(window=self.macro_window).max() df['macro_min'] = df['Low'].rolling(window=self.macro_window).min() df['macro_range'] = df['macro_max'] - df['macro_min'] # Tension: Distance from equilibrium relative to macro range df['tension'] = (df['Close'] - df['macro_median']).abs() / (df['macro_range'] + 1e-9) # --- 4. Macro Directional Vector --- df['macro_vector'] = df['Close'].diff(self.macro_window) return df def generate_signal(self, df): """ Generate signals based on the synchronicity of Tension, Symmetry, and Vacuum Velocity. """ if len(df) < self.macro_window + 5: return None last = df.iloc[-1] prev = df.iloc[-2] # --- Entry Conditions: The Triple Convergence --- # 1. Tension Filter: Only enter when price is relatively close to equilibrium # This prevents "buying the top" or "selling the bottom" is_low_tension = last['tension'] < self.tension_limit # 2. Symmetry Synchronization: All timeframes must show conviction in the same direction # Bullish Symmetry: Current, Meso, and Macro are all positively biased symmetry_bullish = ( last['symmetry'] > 0.3 and last['symmetry_meso'] > 0.1 and last['symmetry_macro'] > 0.05 ) # Bearish Symmetry: Current, Meso, and Macro are all negatively biased symmetry_bearish = ( last['symmetry'] < -0.3 and last['symmetry_meso'] < -0.1 and last['symmetry_macro'] < -0.05 ) # 3. Vacuum Trigger: Velocity Z-score must spike (Statistical anomaly) # We look for a significant jump in velocity relative to the recent past vacuum_bullish = last['vel_zscore'] > 2.0 vacuum_bearish = last['vel_zscore'] < -2.0 # 4. Macro Alignment: Trade in the direction of the 1h vector macro_bullish = last['macro_vector'] > 0 macro_bearish = last['macro_vector'] < 0 # --- Final Execution Logic --- # BUY: Macro UP + Low Tension + Symmetry BULLISH + Vacuum BULLISH if macro_bullish and is_low_tension and symmetry_bullish and vacuum_bullish: # Final confirmation: Candle must be bullish and close near the high if last['Close'] > last['Open']: return 'BUY' # SELL: Macro DOWN + Low Tension + Symmetry BEARISH + Vacuum BEARISH if macro_bearish and is_low_tension and symmetry_bearish and vacuum_bearish: # Final confirmation: Candle must be bearish and close near the low if last['Close'] < last['Open']: return 'SELL' return None オマケ:反面教師としてのMQL5変換 「こんなゴミのようなロジックを、あえてMT5で動かして絶望を味わいたい」という物好きな方のために、MQL5に移植しておいた。 統計的な計算(Zスコアや中央値)をMQL5で実装するのは少々手間だが、その手間こそが「この戦略に価値がないこと」を再認識させる良い修行になるだろう。 ...

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