本記事では、東京仲値(9:55)×「五十日(ごとうび)」の需給偏りを利用した、初心者でも実装可能なUSD/JPYのデイトレ戦略を徹底解説します。一般論ではなく、明確な取引ルールと検証方法、さらにMQL4の完全自動売買EAまで載せています。証券口座(FX口座)をこれから開く方に向けて、基本のフローも最後にまとめました。難しい理論や専門用語は平易に説明しながら、「毎朝やるべき具体的手順」に落とし込みます。
本記事のテーマと結論
テーマは「東京時間9:55の仲値(なかね)決定に向けて偏りやすい実需フローを観察し、その直後の短時間に発生しやすい反転(リバーサル)を狙う」ことです。特に、5と0の付く営業日(五十日)や月末最終営業日は、実需のドル買い・円売り(またはその逆)が集中しやすく、9:30〜9:55に一方向へ進んだ価格が、10:00前後に一時的に戻る現象が見られることがあります。本記事は、この短時間の戻りを機械的ルールで捉える手法を提示します。
なぜ機能し得るのか(需給メカニズム)
- 実需フローの集中:輸入企業の支払い、運用機関の為替ヘッジなどが仲値(9:55)に向けて取り引きされることがあります。
- 注文の一極集中による一方向ドリフト:9:30〜9:55にかけて、価格が一方向に滑りやすい「ドリフト」が起きる日があります。
- イベント後の反転:仲値通過後は実需フローが一巡し、短時間のポジション解消(利食い・巻き戻し)で反転が起きやすくなります。
- 五十日・月末の強化:支払い・受け取りが集中しやすい日取りでは、この傾向が強まりやすいと考えられます。
重要なのは、常に起きるわけではない点です。従って機械的なルールとリスク管理(損切り・時間指定のクローズ)を徹底し、「平均して期待値がプラスか」という視点で運用します。
戦略の全体像
本戦略は逆張りです。9:55に向けて価格が一方向へ走った場合、通過直後の短時間で逆方向に取りにいく設計です。下記はデフォルトの考え方です。
- 対象:USD/JPY(MT4で最も一般的)。
- 日付フィルター:五十日(5/10/15/20/25日)と月末最終営業日を優先。他の日でも稼働可だが、まずは上記に限定。
- 時間帯:9:30〜9:55の値動きを観察し、9:55直後〜10:05でトレード。
- 方向:9:30→9:55で上昇幅が規定以上ならショート、下落幅が規定以上ならロング。
- エントリー:9:55:05以降、短期平均(例:1分足の移動平均)割れ/超えなどの微条件を満たした瞬間。
- 手仕舞い:時間指定クローズ(10:05)、もしくは利確/損切りの価格到達で決済。
具体的な売買ルール(ベーシック版)
- 判定足:1分足。
- ドリフト計測:9:30の価格と9:55の価格の差(pips)。
上方向ドリフト=(9:55のBid − 9:30のBid)が+X pips以上。
下方向ドリフト=(9:55のBid − 9:30のBid)が−X pips以下。 - エントリー方向:
上方向ドリフト時 → 9:55:05以降にショート(戻り取り)。
下方向ドリフト時 → 9:55:05以降にロング(戻り取り)。 - トリガー:直近5本の平均価格(SMA5)に対するクロスで発動(より保守的)。
- 損切り/利確:
損切り(SL)=7〜10pips、初期値は9pips。
利確(TP)=8〜12pips、初期値は10pips。
時間指定クローズ=10:05:00に成行決済(どちらか先に当たればそちら優先)。 - フィルター:
スプレッドが2.0pips以下、約定拒否が少ない口座。
重要指標(例:日本のCPI、米雇用統計など)が9:30〜10:10に被る日は停止。
ATR(14)が極端に低い/高い日は停止(例:5分足ATR(14)が1.0〜3.0pipsの範囲を推奨)。 - 同日複数回の禁止:1日最大1トレード。
バリエーション(上級者向け)
- 事前追随→ノーポジ→反転狙い:9:50までにドリフト方向へ小ロットで追随し、9:54でクローズ。その後は逆張りのみ。
- バンド条件:ボリンジャー±1σ/±2σタッチをトリガー条件に組み替える。
- 出来高代替:FXは板・出来高が不明確なため、ティック数を出来高代替に。9:50〜9:55にティック数が閾値超えで条件強化。
想定ケーススタディ
以下はイメージしやすいようにした数値例です(実際の値動きとは異なります)。
- ケースA(上昇→反転):9:30=151.20、9:55=151.38(+18pips)。9:55:10にSMA5割れでショート、TP=10pips到達(151.28)で利確。
- ケースB(下落→反転):9:30=150.80、9:55=150.62(−18pips)。9:55:12にSMA5上抜けでロング、10:05タイムアウト決済で+4pips。
- ケースC(ノートレード):9:30↔9:55の差が±8pips未満で条件未達、見送り。
バックテストの進め方(MT4)
- データ:USDJPYの1分足ヒストリカルを入手し、プラットフォームに取り込みます。
- タイムゾーン:ブローカー時間と日本時間(JST)のズレを固定パラメータで吸収します(例:JSTOffsetHours=+7など)。
- 対象日:まずは五十日と月末最終営業日のみで検証。次に全営業日に拡大。
- 評価指標:勝率、平均損益、プロフィットファクター(PF)、最大ドローダウン(DD)、1トレード期待値。
- コスト前後:スプレッドと想定スリッページ(例:0.3〜0.8pips)を加味した成績を必ず確認します。
- ロバスト性:X(ドリフト閾値)、TP/SL、クローズ時刻を±20%で振り、成績が大きく崩れないか確認します。
- モンテカルロ:エントリー順序やスリッページをランダム化してばらつきを評価します。
MQL4 EA(完全自動売買コード)
以下のEAは、ブローカー時間からJST(日本時間)オフセットを入力してローカルに日本時間を推定し、五十日/最終営業日条件と9:55→10:05の逆張りルールを実装します。MT4のストラテジーテスターで1分足に対して検証してください。
//+------------------------------------------------------------------+
//| EA Name : GotobiFixReversalEA.mq4 |
//| Purpose : Tokyo fixing (09:55 JST) reversal on gotobi & EOM |
//| Symbol : USDJPY (5-digit brokers supported) |
//| Timeframe: M1 |
//+------------------------------------------------------------------+
#property strict
extern double Lots = 0.10;
extern int DriftPips = 15; // X pips threshold between 09:30 and 09:55
extern int TPpips = 10;
extern int SLpips = 9;
extern int JSTOffsetHours = 7; // BrokerTime + offset = JST (e.g., 7 or 8)
extern bool OnlyGotobiAndEOM = true; // true: trade only on gotobi & EOM
extern int SMA_Period = 5; // trigger using SMA cross
extern int EntryDelaySeconds = 5; // enter at or after 09:55:05
extern int CloseHourJST = 10; // time-based close at 10:05 JST
extern int CloseMinuteJST = 5;
extern double MaxSpreadPips = 2.0;
extern bool OneTradePerDay = true;
datetime lastTradeDay = 0;
int pt; // point-to-pip scaler
int init(){
pt = (int)MathRound( (MarketInfo(Symbol(), MODE_POINT) == 0.001 || MarketInfo(Symbol(), MODE_DIGITS)==3) ? 10 :
(MarketInfo(Symbol(), MODE_POINT) == 0.00001 || MarketInfo(Symbol(), MODE_DIGITS)==5) ? 10 : 1 );
return(0);
}
int deinit(){ return(0); }
int start(){
if(Bars < 1000) return(0);
if(IsTradeAllowed()==false) return(0);
// Spread check
double spreadPips = (MarketInfo(Symbol(), MODE_SPREAD) / pt);
if(spreadPips > MaxSpreadPips) return(0);
// Compute current JST time
datetime nowBT = TimeCurrent();
datetime nowJST = nowBT + JSTOffsetHours*3600;
int y, m, d, hh, mm, ss;
TimeToStruct(nowJST, y, m, d, hh, mm, ss);
// One trade per day guard
if(OneTradePerDay){
if(TimeDay(lastTradeDay)==d && TimeMonth(lastTradeDay)==m && TimeYear(lastTradeDay)==y) return(0);
}
// Filter: only on gotobi & end-of-month business day if set
if(OnlyGotobiAndEOM){
if(!IsGotobiOrEOM(y,m,d)) return(0);
}
// Trading window: entry on/after 09:55:05 JST; close at 10:05 JST
bool isEntryWindow = (hh==9 && (mm>=55)) || (hh==10 && mm==0 && ss<=30);
bool isTimeToForceClose = (hh>CloseHourJST) || (hh==CloseHourJST && mm>=CloseMinuteJST);
// Calculate drift from 09:30 to 09:55 JST using M1 close
double drift = 0.0;
bool driftReady = GetDriftPips(y,m,d, drift);
// Manage open position: force-close at 10:05 JST
ManageOpenPositions(isTimeToForceClose);
if(!driftReady) return(0);
// Trigger: SMA cross confirmation
double sma = iMA(NULL, PERIOD_M1, SMA_Period, 0, MODE_SMA, PRICE_CLOSE, 0);
double prev = iMA(NULL, PERIOD_M1, SMA_Period, 0, MODE_SMA, PRICE_CLOSE, 1);
double price = Bid;
int dir = 0; // 1=long, -1=short
if(drift >= DriftPips) dir = -1;
if(drift <= -DriftPips) dir = 1;
if(dir==0) return(0);
// SMA cross in direction of reversal
bool trigger = false;
if(dir==-1){ // want short
if(prev <= Close[1] && sma > Close[0]) trigger = true; // simple mean reversion flip
// Alternate: use price crossing SMA
if(Close[1] <= prev && Close[0] >= sma) trigger = true;
}else if(dir==1){ // want long
if(prev >= Close[1] && sma < Close[0]) trigger = true;
if(Close[1] >= prev && Close[0] <= sma) trigger = true;
}
if(isEntryWindow && trigger){
if(OneTradePerDay && lastTradeDay!=0){
if(TimeDay(lastTradeDay)==d && TimeMonth(lastTradeDay)==m && TimeYear(lastTradeDay)==y) return(0);
}
OpenReversalTrade(dir);
lastTradeDay = nowJST;
}
return(0);
}
// Compute drift (pips) from 09:30 to 09:55 JST
bool GetDriftPips(int y, int m, int d, double &driftPips){
datetime t0930 = MakeJST(y,m,d,9,30,0);
datetime t0955 = MakeJST(y,m,d,9,55,0);
int i0930 = iBarShift(NULL, PERIOD_M1, t0930, true);
int i0955 = iBarShift(NULL, PERIOD_M1, t0955, true);
if(i0930<0 || i0955<0) return(false);
double p0930 = iClose(NULL, PERIOD_M1, i0930);
double p0955 = iClose(NULL, PERIOD_M1, i0955);
double pipDiv = (pt==10) ? 0.001 : 0.01; // for JPY pairs with 3/5 digits
driftPips = (p0955 - p0930)/pipDiv;
return(true);
}
void OpenReversalTrade(int dir){
double pipDiv = (pt==10) ? 0.001 : 0.01;
double sl = SLpips * pipDiv;
double tp = TPpips * pipDiv;
if(dir==-1){ // short
double ask = Ask;
int ticket = OrderSend(Symbol(), OP_SELL, Lots, Bid, 20,
NormalizeDouble(ask + sl, Digits),
NormalizeDouble(Bid - tp, Digits),
"GotobiFixReversalEA", 0, 0, clrRed);
}else if(dir==1){ // long
double bid = Bid;
int ticket = OrderSend(Symbol(), OP_BUY, Lots, Ask, 20,
NormalizeDouble(bid - sl, Digits),
NormalizeDouble(Ask + tp, Digits),
"GotobiFixReversalEA", 0, 0, clrBlue);
}
}
void ManageOpenPositions(bool forceClose){
for(int i=OrdersTotal()-1; i>=0; i--){
if(!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) continue;
if(OrderSymbol()!=Symbol()) continue;
if(OrderMagicNumber()!=0 && OrderMagicNumber()!=0){} // keep default
if(forceClose){
if(OrderType()==OP_BUY) OrderClose(OrderTicket(), OrderLots(), Bid, 30, clrYellow);
if(OrderType()==OP_SELL) OrderClose(OrderTicket(), OrderLots(), Ask, 30, clrYellow);
}
}
}
// Helpers
bool IsGotobiOrEOM(int y,int m,int d){
if(d==5 || d==10 || d==15 || d==20 || d==25) return(true);
// last business day of month (Mon-Fri)
int lastD = LastBizDay(y,m);
if(d==lastD) return(true);
return(false);
}
int LastBizDay(int y,int m){
int d = DaysInMonth(y,m);
while(IsWeekend(y,m,d)) d--;
return(d);
}
bool IsWeekend(int y,int m,int d){
datetime dt = StrToTime(StringFormat("%04d.%02d.%02d 00:00",y,m,d));
int wd = TimeDayOfWeek(dt);
return (wd==0 || wd==6);
}
int DaysInMonth(int y,int m){
if(m==1||m==3||m==5||m==7||m==8||m==10||m==12) return 31;
if(m==4||m==6||m==9||m==11) return 30;
// February
bool leap = ( (y%4==0 && y%100!=0) || (y%400==0) );
return leap ? 29 : 28;
}
datetime MakeJST(int y,int m,int d,int hh,int mm,int ss){
datetime jst = StrToTime(StringFormat("%04d.%02d.%02d %02d:%02d:%02d",y,m,d,hh,mm,ss));
return jst - JSTOffsetHours*3600 + TimeCurrent(); // align to broker time base
}
void TimeToStruct(datetime t, int &y,int &m,int &d,int &hh,int &mm,int &ss){
string s = TimeToStr(t, TIME_DATE|TIME_SECONDS);
// format: YYYY.MM.DD HH:MM:SS
y = StrToInteger(StringSubstr(s,0,4));
m = StrToInteger(StringSubstr(s,5,2));
d = StrToInteger(StringSubstr(s,8,2));
hh= StrToInteger(StringSubstr(s,11,2));
mm= StrToInteger(StringSubstr(s,14,2));
ss= StrToInteger(StringSubstr(s,17,2));
}
//+------------------------------------------------------------------+
パラメータ解説と初期値の目安
DriftPips | 15 | 9:30→9:55の絶対変化量。10〜20の間で調整します。 |
TPpips / SLpips | 10 / 9 | 時間指定決済と併用。市場状態で微調整。 |
JSTOffsetHours | 7 | ブローカー時間→JSTの差分。夏時間で8になる場合あり。 |
OnlyGotobiAndEOM | true | まずは有利とされる日付に限定し、慣れたら全営業日に拡張。 |
MaxSpreadPips | 2.0 | コスト管理の肝。これ以上は原則停止。 |
OneTradePerDay | true | 過剰取引防止。日次1回に制限。 |
よくある失敗と対策
- タイムゾーン設定ミス:JSTOffsetHoursを季節で見直します。
- スプレッド拡大への無警戒:東京午前でも銘柄やブローカーにより拡大します。MaxSpreadPipsを守ります。
- イベント日無視:重要指標や要人発言が近いと挙動が崩れます。経済カレンダーを確認します。
- 過剰最適化:狭い期間でパラメータを最適化し過ぎない。ロバスト性テストを必ず実施します。
ブローカー/口座の基本選定
MT4が使えて、USD/JPYのスプレッドが安定して狭く、約定品質が良い口座を選びます。国内外問わず、デモ口座→小額リアルの順で確認しましょう。スキャルピング可否、約定拒否の頻度、約定スピードは実運用前に必ずチェックします。
初心者向け・口座開設の流れ
- FX会社の公式サイトから口座開設申込み(本人確認書類・マイナンバー等)。
- 審査完了後、ログイン情報が送付されます。
- MT4をPCへインストールし、デモ口座でUSD/JPYの操作に慣れます。
- 入金後はまず0.01〜0.10ロットで小さく運用し、スプレッドやスリッページを体感します。
- バックテストとフォワードテストの両方で、想定通りの挙動を確認してからロットを段階的に増やします。
毎朝のチェックリスト(テンプレ)
- 今日は五十日/月末最終営業日か?
- 重要指標・要人発言予定はないか?
- スプレッドは2.0pips以下か?
- 9:30→9:55のドリフトが±15pips以上あるか?
- 10:05の時間指定クローズ設定は有効か?
期待値の考え方(簡易)
期待値EVは、EV=勝率×平均利益−(1−勝率)×平均損失−コストで見積もります。TP/SLを対等(例:10pips/9pips)とし、コスト(スプレッド+スリッページ)を1.0〜1.5pipsと仮定して、勝率が50%を少し超えるだけでもトータルでプラスになり得ます。勝率とリスクリワードの両方を微調整し、PF>1.1〜1.3を最低ライン、DD(最大ドローダウン)は許容範囲に収まるよう管理します。
よくある質問(FAQ)
Q1:五十日以外の日は動かしませんか?
A:最初は限定した方が分かりやすいですが、慣れてきたら全営業日に拡張してもかまいません。過去検証で優位性が残るか必ず確認してください。
Q2:夏時間でJSTとのズレが変わります。
A:JSTOffsetHoursを季節ごとに見直してください。テスターでは複数パターンを比較しましょう。
Q3:損切りが続きます。
A:ドリフト閾値(DriftPips)を引き上げる、またはイベント日をより厳しく除外してください。ロットは常に資金に対して小さく保ちます。
用語ミニ解説
- 仲値(なかね):銀行が顧客向けに提示する当日の対顧客基準レート。日本時間9:55前後に決定されます。
- 五十日(ごとうび):5の倍数日(5、10、15、20、25日)を指す商習慣。資金決済が集中しやすいといわれます。
- PF(プロフィットファクター):総利益÷総損失。1を超えるほど戦略が利益体質である目安。
TradingView(任意)での可視化補助
必要であれば、以下のシンプルなPine Script v5で9:55ラインとドリフト計測を視覚化できます(裁量検証用)。
//@version=5
indicator("Tokyo Fix Drift Helper", overlay=true)
jst = input.session("0900-1500", "Tokyo Cash Session")
fixTime = input.time(defval=timestamp("Asia/Tokyo", year, month, dayofmonth, 9, 55), title="Fixing Time")
i930 = input.time(defval=timestamp("Asia/Tokyo", year, month, dayofmonth, 9, 30), title="Start Drift")
plot(vline(time == fixTime), title="09:55")
plot(vline(time == i930), title="09:30")
まとめ
「東京仲値×五十日リバーサル」は、短時間・明確ルール・低回数という特徴から、初心者でも学びやすい戦略です。機械的な執行とコスト管理、そしてイベント回避を徹底し、必ずバックテストと小ロットのフォワードテストから始めてください。コツは、日次1回・時間指定・コスト厳守の3点です。
コメント