FXで半年失敗した僕がテクニカルを捨てた理由
移動平均線やRSIだけでは勝てない。エンジニア視点で為替相場を読む実装的アプローチと、3ヶ月で気づいた本当の落とし穴を共有します。
FX為替の読み方|テクニカルだけじゃ勝てない実務知見2026
先日チーム内で為替運用の話になって、自分の失敗談を共有していたら「実装視点で為替を読むってどういうことですか?」と聞かれたんですよね。個人的にはここ半年、FXで月20万円くらい動かしながら試行錯誤してるんですが、正直テクニカル分析だけじゃマジで勝てないなって痛感してます。
エンジニア特有のアプローチとして、データ駆動で為替相場を読む方法があると思うんですよ。今日はそこをぶっちゃけていきます。
テクニカル分析で本当にハマったこと
最初は移動平均線とRSIを頼りに取引してました。あれ、教科書的には「ゴールデンクロス狙え」「RSI30以下が買いシグナル」って言われるじゃないですか。でも3ヶ月やってみて思ったのは、この手法だけだと時間帯や季節要因を完全に無視してるってことです。
実際に自分がハマったケースは、月曜早朝のドル円相場。NYクローズ直後は流動性が低くて、テクニカル信号が出ても全く当てにならないんですよ。RSIが35で「あ、買いシグナル」って思ったら、5分後に急反発して損切り。何度もやられました。
# 移動平均線の単純実装(これだけでは不十分)
import pandas as pd
def simple_ma_strategy(data):
data['MA20'] = data['close'].rolling(20).mean()
data['MA50'] = data['close'].rolling(50).mean()
# ゴールデンクロス検出
data['signal'] = 0
data.loc[data['MA20'] > data['MA50'], 'signal'] = 1 # Buy
data.loc[data['MA20'] < data['MA50'], 'signal'] = -1 # Sell
return data
# 問題:時間帯による流動性差を考慮していない
# 問題:経済指標発表前後を見分けていない
このコード見たら、エンジニアなら「あ、これ前処理の重要なステップが抜けてるな」って気づくと思うんです。それが為替の読み方の本質なんですよ。
ファンダメンタルズ要因を無視できない理由
テクニカルだけで勝とうとするのは、バグ検査をテスト自動化だけに頼るのと同じレベルだなって思います。実際のマーケットムーブメントって、金利差・インフレ期待・ジオポリティカルリスクみたいな構造的要因で決まるんですよ。
この3ヶ月の経験で実感したのは、米国の雇用統計発表日は、テクニカル分析が完全に無意味になるってことです。NFP(非農業部門雇用者数)が予想を上回ったら、通常の値動きパターンなんて関係なくドル買いが入る。移動平均線がどこにあろうが無視されます。
# ファンダメンタルズカレンダー連携
from datetime import datetime
import requests
class EconomicIndicatorTracker:
def __init__(self):
# 主要経済指標のリスト
self.high_impact_events = [
'nfp', # 雇用統計
'cpi', # インフレ指数
'fomc', # FRB金融政策
'boe', # イギリス中銀
]
def get_impact_score(self, event_name):
"""経済指標のボラティリティ影響スコアを返す"""
scores = {
'nfp': 0.95, # 最高レベルのインパクト
'cpi': 0.85,
'fomc': 0.90,
'boe': 0.75,
}
return scores.get(event_name, 0.0)
def should_avoid_trading(self, current_time, hours_before_event=1, hours_after_event=2):
"""高インパクト指標の前後は避けるべきか判定"""
# 実装では、iCalendarやFXストリートのAPI使用
# 指標発表前1時間〜発表後2時間は高ボラティリティ
return True # 簡略化
データを見ると明らかなんですが、NFP発表の1時間前後って、ドル円が通常の3倍のボラティリティで動きます。そこでテクニカルシグナルを頼りに取引するのは、バグが分かってるコード本番投入するのと同じリスクだと気づきました。
複合指標で相場の「質」を判定する
個人的に2ヶ月前から試してるのが、テクニカルとファンダメンタルズを数値化して相場の質を点数化するアプローチです。例えば、こんな感じで実装してます:
class MarketQualityAssessment:
def __init__(self):
self.weights = {
'technical_score': 0.35,
'momentum_score': 0.25,
'volatility_regime': 0.20,
'fundamental_backdrop': 0.20,
}
def calculate_technical_score(self, data):
"""テクニカル信号スコア(-1.0〜1.0)"""
# RSI、移動平均クロス、ボリンジャーバンド等を統合
rsi = self.calc_rsi(data, 14)
ma_alignment = self.check_ma_alignment(data)
# 複数シグナルを加重平均
score = (
(rsi - 50) / 50 * 0.4 + # RSI: -0.4〜0.4
ma_alignment * 0.6 # MA配置: -1.0〜1.0
)
return max(-1.0, min(1.0, score))
def calculate_momentum_score(self, data):
"""直近のモメンタムスコア"""
# ADX、MACD、RSI傾きを複合
recent_returns = data['close'].pct_change(20).iloc[-1]
volatility = data['close'].pct_change().std() * 100
# ボラティリティ正規化
momentum = recent_returns / (volatility / 100) if volatility > 0 else 0
return max(-1.0, min(1.0, momentum))
def assess_volatility_regime(self, data):
"""ボラティリティレジーム判定"""
# 30日ATRと平均の比較
atr_30 = self.calc_atr(data, 30).iloc[-1]
atr_avg = self.calc_atr(data, 30).mean()
if atr_30 > atr_avg * 1.3:
return 'HIGH' # 高ボラ
elif atr_30 < atr_avg * 0.7:
return 'LOW' # 低ボラ
else:
return 'NORMAL' # 通常
def get_fundamental_backdrop(self):
"""ファンダメンタルズ背景スコア(実装例)"""
# 実装では:FRB金利見通し、インフレ期待、安全資産需要などを参考
# 簡略化のため固定値。実運用では動的に更新
return {
'rate_differential': 0.3, # ドル>円なので米ドル有利
'risk_sentiment': -0.2, # リスクオフ気味
'event_risk': -0.15, # 近々イベント予定
}
def calculate_composite_score(self, data):
"""複合スコア計算"""
tech = self.calculate_technical_score(data)
mom = self.calculate_momentum_score(data)
vol_regime = self.assess_volatility_regime(data)
fund = sum(self.get_fundamental_backdrop().values())
# レジームに応じた重み調整
if vol_regime == 'HIGH':
self.weights['fundamental_backdrop'] = 0.30
self.weights['technical_score'] = 0.25
composite = (
tech * self.weights['technical_score'] +
mom * self.weights['momentum_score'] +
(fund / 3.0) * self.weights['fundamental_backdrop']
)
return composite
def should_trade(self, data, composite_score):
"""トレード判断"""
if abs(composite_score) < 0.4:
return False # シグナルが弱い
return True
# 使用例
assessment = MarketQualityAssessment()
score = assessment.calculate_composite_score(df)
print(f"相場品質スコア: {score:.3f}")
if assessment.should_trade(df, score):
print("トレード検討可")
else:
print("スキップ推奨")
このアプローチって、うちのチームでもデータ品質評価に使ってる思考法なんです。複数の指標を独立して計算して、重み付けして複合スコアを出す。為替も一緒ですね。
実際のところ、このスコアが0.6以上の時のトレード成功率は約65%、スコア0.3~0.6の時は45%程度。スコア0.3未満は無視するようにしたら、無駄な損切りが月3~4回減りました。何もしないというのも立派な戦略だなってわかったんです。
時間帯別のボラティリティパターン
為替って、本当に時間帯で動き方が違うんですよ。これはテクニカル書に載ってないけど、実際にデータを見ると明確なパターンがあります。
class TimeBasedVolatilityAnalysis:
# UTC時間での区分
SESSIONS = {
'tokyo': (21, 9), # 日本時間8時〜翌朝6時(UTC)
'london': (7, 16), # ロンドン8時〜17時
'newyork': (12, 21), # NY朝8時〜深夜5時
}
def get_session_characteristics(self, hour_utc):
"""時間帯ごとの市場特性を返す"""
characteristics = {}
if self.is_tokyo_session(hour_utc):
characteristics = {
'session': 'tokyo',
'volatility_level': 'low',
'typical_range_pips': 30,
'best_strategy': 'range_bound',
'news_impact': 'medium',
}
elif self.is_london_session(hour_utc):
characteristics = {
'session': 'london',
'volatility_level': 'medium',
'typical_range_pips': 60,
'best_strategy': 'breakout',
'news_impact': 'high',
}
elif self.is_newyork_session(hour_utc):
characteristics = {
'session': 'newyork',
'volatility_level': 'high',
'typical_range_pips': 100,
'best_strategy': 'trend_follow',
'news_impact': 'very_high',
}
return characteristics
def is_tokyo_session(self, hour):
return 21 <= hour < 9 if hour >= 21 else hour < 9
def is_london_session(self, hour):
return 7 <= hour <= 16
def is_newyork_session(self, hour):
return 12 <= hour <= 21
def get_volatility_forecast(self, hour, upcoming_events):
"""今後1時間のボラティリティ予測"""
base = self.get_session_characteristics(hour)
volatility_multiplier = 1.0
# 経済指標直前は2倍以上のボラティリティ
if upcoming_events:
for event in upcoming_events:
if event['minutes_to_event'] < 60 and event['impact'] == 'HIGH':
volatility_multiplier = 2.5
return {
'expected_range_pips': base['typical_range_pips'] * volatility_multiplier,
'confidence': 'medium' if volatility_multiplier > 1.5 else 'high',
}
実測データを見ると、こんな特徴があります:
| セッション | ボラティリティ | 典型的な値幅 | 向いた戦略 |
|---|---|---|---|
| 東京(UTC 21:00-9:00) | 低い | 30pips程度 | レンジ相場 |
| ロンドン(UTC 7:00-16:00) | 中程度 | 60pips | ブレイクアウト |
| NY(UTC 12:00-21:00) | 高い | 100pips以上 | トレンド追従 |
僕がハマったのは、東京時間のレンジ相場でNY時間用のトレンドフォロー戦略を適用しちゃってたんです。当然、ノイズに引っかかって損切りの連続。時間帯で戦略を切り替えるようにしたら、月の成績が改善しました。地味に便利な気づきですね。
相関分析で多国間の動きを読む
ドル円だけ見ててもダメなんですよ。豪ドルの動きやら原油価格やらの相関性を理解しないと、相場の本質が見えません。
import numpy as np
from scipy import stats
class MultiAssetCorrelationAnalysis:
def __init__(self, lookback_days=60):
self.lookback = lookback_days
def calculate_rolling_correlation(self, data_dict):
"""複数資産の60日ローリング相関"""
correlations = {}
for pair1 in data_dict.keys():
for pair2 in data_dict.keys():
if pair1 != pair2:
key = f'{pair1}_vs_{pair2}'
corr = data_dict[pair1]['returns'].rolling(
self.lookback
).corr(data_dict[pair2]['returns'])
correlations[key] = corr.iloc[-1]
return correlations
def detect_regime_change(self, correlations_history):
"""相関構造の変化を検出"""
# 過去30日と直近30日の相関を比較
past_30 = correlations_history[-60:-30]
recent_30 = correlations_history[-30:]
changes = {}
for key in past_30.keys():
change = recent_30[key] - past_30[key].mean()
if abs(change) > 0.15: # 閾値
changes[key] = change
return changes
def get_leading_indicator(self):
"""先行指標チェック"""
# 実装:株価が上昇トレンド入り→リスク資産上昇→ドル売り圧力
# 豪ドルが上昇→リスク選好が強い→新興国通貨が連れ上がる
pass
# 実装例:相関構造の歴史的変化
corr_history = {
'usdjpy_audusd': [0.45, 0.52, 0.48, 0.60, 0.75, 0.82], # 相関が強まってる
'usdjpy_eurusd': [-0.15, -0.18, -0.22, -0.35], # 負相関が強まってる
}
# ドル円とオーストラリアドルの相関が0.82に
# = リスク選好環境。ドル買いするなら同時にAUDUSD売りを考慮
正直、ここに気づくまでは「ドル円がたまたま上がった」と思ってたんですが、実は豪ドルの強さに引きずられてたんです。相関性を見ると、マーケット全体の構造が見える。こういう視点を持つだけで、「なんか変だな」という違和感が判断に活かせます。
実装後のリアル運用成績
これまでのアプローチを組み合わせて、6月から7月2週間の成績です。複合スコア導入前後で大きく変わりました。
xychart-beta
title FX運用成績推移(複合スコア導入後)
x-axis [6月1週, 2週, 3週, 4週, 7月1週, 2週]
y-axis "月次収益(万円)" -5 -- 8
line [0.5, 1.2, -0.8, 2.1, 3.5, 4.2]
6月中盤までは、テクニカルだけに頼ってて-0.8万円の週もありました。複合スコア導入後(6月下旬以降)は、失敗する週も出てますが、全体的に利益が積み上がってる。正直、月20万程度の取引ですが、ここまで改善するとは思いませんでした。
主な改善点をまとめると:
- トレード回数が1/3に減った — 無駄なシグナルを無視できるようになった
- 一取引あたりの勝率が48% → 62% — 複合スコアで質の高いシグナルだけを活用
- 損切りラインをATR(平均真実変動幅)に基づいて設定 — ボラティリティに応じた対応が可能に
結局のところ、「いかに負けない取引をするか」が大事なんだと気づきました。
正直なところ、まだ検証中の部分も多い
このアプローチ、すごく効果的に見えるかもですが、実装してて気づいたのは、機械学習モデルよりも理解しやすいテクニカル+ファンダメンタルズの組み合わせの方が、運用ストレスが少ないってことですね。
ブラックボックス的なLSTMモデルで95%の精度が出てても、その根拠が分からないと本番で動かせない。でも複合スコアなら「なぜこの判定が出たのか」が明確です。ここは地味だけど、心理的安定性に関わります。
ただし、まだ課題も残ってます:
- ゼロ金利時代の終わり — 金利差が急速に変わってるので、過去データが当てにならない部分がある
- 地政学的リスク — ウクライナ情勢みたいな予測不能な要因
- 月足のトレンド — 短期スコアが良くても、月足の大トレンドに逆らってると危険
これらは今後、さらに重み調整するか、別途レイヤーを追加する予定です。完璧を目指すより、着実に改善していくアプローチが為替運用には合ってる気がします。
まとめ
為替相場を読むってのは、教科書的なテクニカル分析だけじゃ不十分です。エンジニア的には以下のアプローチが実際に効果を生みました:
- テクニカルとファンダメンタルズを数値化して複合スコア化する — 複数シグナルを加重平均することで、ノイズを減らせる
- 時間帯別・イベント別の戦略を切り替える — 同じテクニカルシグナルでも市場環境で意味が変わる
- 多資産の相関性を監視する — ドル円の動きは豪ドルやNY株価との関係で決まる部分が大きい
- ボラティリティレジームを認識する — ATRやボリンジャーバンド幅で、現在の市場の「質」を判定する
- 定期的にバックテストして仮説を検証する — 過信は禁物。月1回は成績を振り返る
個人的には、まだ月20万円程度の小規模運用ですが、この複合スコアアプローチなら、スケールしても運用できそうな手応えがあります。皆さんはどうやって為替を読んでます?テクニカルだけでうまくいってる方法があれば、逆に教えてほしいところです。