リターンの多くは「どこで買ってどこで売るか」ではなく、「どう約定させたか」で決まります。たとえば期待値+0.5%の優位性を持つ戦略でも、執行の粗さで毎回0.2%余計に滑れば、ほぼ無価値になります。本稿は、個人投資家でも今日から改善できる実務的な執行最適化ガイドです。VWAP/TWAP/POVといった代表的アルゴの設計思想、使い分け、KPI、そして実装までを具体的に示します。
- 1. 執行コストの全体像:Implementation Shortfall(IS)
- 2. VWAP/TWAP/POVの定義と使い分け
- 3. マイクロストラクチャ入門:なぜ滑るのか
- 4. 時間帯別出来高曲線の自作(無料データでOK)
- 5. 価格インパクトの簡易モデルとサイズ最適化
- 6. 注文分割アルゴの設計(実装指針)
- 7. 具体例:1000株の買いを60分で執行
- 8. 板・指値・滞留時間の実務レシピ
- 9. KPI運用:何を測って改善するか
- 10. 市場別Tips(株・FX・暗号資産)
- 11. MQL4で動かす:VWAPインジケータと簡易TWAP実行EA
- 12. よくある落とし穴と対策
- 13. ミニマム運用チェックリスト
- 14. まとめ:執行は「再現可能な技術」
1. 執行コストの全体像:Implementation Shortfall(IS)
Implementation Shortfall(IS)は発注前の「理想価格」から最終実現価格までの差を金額化した指標です。手数料、スプレッド、価格インパクト、未約定リスクを一つにまとめて計測します。式は簡潔です。
IS = 実現価額合計 − ベンチマーク価額合計
(買いの場合:正のISはコスト増、売りの場合:正のISはコスト減)
個人投資家が最初にやるべきことは、毎トレードでISを記録して平均・分散を出すことです。平均ISが改善すれば、同じ戦略でも年間SharpeやCAGRが自然に向上します。
2. VWAP/TWAP/POVの定義と使い分け
2-1. VWAP(出来高加重平均価格)
VWAPは「その日の出来高で重み付けした平均価格」です。理論的には、反対側に自然発生的なフローが多い時間帯で多く約定させるため、価格インパクトを抑えやすい設計です。
VWAP_t = (Σ_{i=1..t} 価格_i × 出来高_i) / (Σ_{i=1..t} 出来高_i)
実運用では、時間帯別出来高曲線(例:5分足×78本=取引時間全体)を事前に推定し、その配分比率に従って子注文をスケジュールします。
2-2. TWAP(時間加重平均価格)
一定時間に均等分割で発注する最もシンプルな手法。出来高プロファイルが読めない銘柄、クリプトのように24時間で出来高の偏りが緩いペア、または少額・短時間の執行に向きます。
2-3. POV(Percent of Volume)
市場出来高の一定割合(例:3%)になるように発注量を可変させる方法です。流動性のノイズに追随でき、板が厚い時間は多く、薄い時間は少なく出すため、インパクト抑制に有効です。
2-4. 使い分けの実務目安
- 板が薄く一撃で動きやすい:VWAP or POV
- 超短時間・小額・高速で終わらせたい:TWAP
- 出来高に日中周期が強い(U字型):VWAP
- 出来高が読めずノイズが多い:POV(小さな%から)
3. マイクロストラクチャ入門:なぜ滑るのか
滑り(スリッページ)の主要因は、①スプレッド、②板の厚みと順番待ち、③価格インパクト、④約定の機会損失です。指値中心+短い滞留時間+分割が基本形。ニュース時やオークション直後はインパクトが跳ねやすいので、執行速度を落として様子を見るのが定石です。
4. 時間帯別出来高曲線の自作(無料データでOK)
日足の出来高と5分足の出来高を用意し、過去20営業日の各5分バケットの出来高を合計→1日に正規化すると、あなた専用の「U字型曲線」が作れます。株式なら寄り・引けの比重が高く、FXならロンドン・NY時間、暗号資産なら週末・深夜帯の偏りも把握できます。
配分比率_k = (過去N日の5分出来高_kの合計) / (過去N日の1日出来高の合計)
子注文量_k = 総発注量 × 配分比率_k
配分比率は月次で更新。イベント(決算、経済指標)日は直近5日のみで再推定するなど、外れ値耐性を持たせましょう。
5. 価格インパクトの簡易モデルとサイズ最適化
経験則として、インパクト ≒ k × (発注量/当日出来高)^α(0.5≲α≲1)。小口分割で(発注量/当日出来高)を下げれば期待インパクトも低下します。ただし子注文数が増えるほど機会損失(置き去りリスク)が増えるので、分割数の最適点を探ることが重要です。
6. 注文分割アルゴの設計(実装指針)
6-1. 共通パラメータ
- 総数量Q、許容スリッページS、最長時間T、1子注文の最小サイズq_min
- 執行スタイル:VWAP/TWAP/POV(%)
- 発注タイプ:指値/成行/指値→n秒後に成行へフェイルオーバー
- キルスイッチ:ISが閾値超過、VIX急騰、ニュース検知で停止
6-2. TWAPの骨格
区間をM等分し、各区間で q = Q/M を発注
待機時間 = T/M、約定比率が低ければ次区間へ繰越し
6-3. VWAPの骨格
時間帯別出来高配分 w_k を事前推定
各バケットで q_k = Q × w_k を発注(q_k >= q_min に丸め)
板の厚さによって指値の距離と滞留時間を調整
6-4. POVの骨格
リアルタイム出来高 V_t を推定し、q_t = % × V_t
板が急に薄くなったら % を自動で逓減、厚くなれば逓増
7. 具体例:1000株の買いを60分で執行
前提:平均スプレッド0.5円、出来高20万株/時、板の最良気配は各200株。
一括成行なら、最良気配を一気に食い上げインパクトが大きい。
TWAP(10分×6回×約167株)なら、各回の板吸収で平均約定価格はVWAPに近づく。
VWAPなら寄り直後と引け前に比重を置けるため、実需フローに埋め込めてさらにインパクト低下が期待できます。
8. 板・指値・滞留時間の実務レシピ
- 指値はベストビッド/アスクから1〜3ティック内側。滞留3〜15秒で成行化。
- 気配厚が薄いときはサイズを半分に分割、約定率が50%未満なら滞留延長。
- 寄りの最初の2〜3分、引けの直前5分は特別扱い(オークションや大口の流れ)。
- ニュース・指標前後は発注比率を1/3に落とし、出来高増を待ってから再開。
9. KPI運用:何を測って改善するか
- IS(円/株、%):小さいほど良い
- VWAP対比(bp):負の値(買い)が理想
- 約定率(%)、平均滞留時間(秒)
- スプレッド捕捉率(%):指値でスプレッドの何割を獲得できたか
- 置き去り回数:価格が基準から閾値以上離れたために約定を諦めた回数
10. 市場別Tips(株・FX・暗号資産)
株式
寄り・引けに比重。板が薄い小型株はPOV小さめ(1〜2%)から。PTSやダークに無理に当てに行かず、まずは可視板での品質を固める。
FX
MT4のVolumeはティック回数であり真の出来高ではありませんが、相対的な流動性の強弱を見るには十分です。ロンドン/NYの重なる時間に配分比率を厚く。
暗号資産
資金調達(Funding)の決済時刻や先物のロール時刻は板が荒れます。POVは小刻みに、TWAPは区間を短めに。ステーブルの乖離が出るときは成行化を控える。
11. MQL4で動かす:VWAPインジケータと簡易TWAP実行EA
11-1. セッションVWAP(インジケータ)
//+------------------------------------------------------------------+
//| Session VWAP (tick volume based) |
//+------------------------------------------------------------------+
#property indicator_separate_window
#property indicator_buffers 1
#property indicator_color1 clrDodgerBlue
double vwap[];
int OnInit(){
SetIndexBuffer(0,vwap);
IndicatorShortName("Session VWAP (tick vol)");
return(INIT_SUCCEEDED);
}
int OnCalculate(const int rates_total,
const int prev_calculated,
const datetime &time[],
const double &open[],
const double &high[],
const double &low[],
const double &close[],
const long &tick_volume[],
const long &volume[],
const int &spread[]){
double pv=0, vv=0;
datetime d0 = iTime(NULL, PERIOD_D1, 0);
for(int i=rates_total-1; i>=0; i--){
if(time[i] < d0){ pv=0; vv=0; d0=iTime(NULL, PERIOD_D1, iBarShift(NULL,PERIOD_D1,time[i])); }
double tp = (high[i]+low[i]+close[i])/3.0;
double v = (double)tick_volume[i];
pv += tp * v;
vv += v;
vwap[i] = (vv>0? pv/vv : tp);
}
return(rates_total);
}
11-2. 簡易TWAP実行EA(学習用)
//+------------------------------------------------------------------+
//| Simple TWAP Executor (for learning) |
//+------------------------------------------------------------------+
#property strict
input double Lots = 0.10;
input int Parts = 6; // 分割数
input int IntervalSec = 600; // 10分
input int SlippagePoints = 10;
input bool BuyNotSell = true;
input int Magic = 20250917;
int executed = 0;
int OnInit(){ EventSetTimer(IntervalSec); return(INIT_SUCCEEDED); }
void OnDeinit(const int reason){ EventKillTimer(); }
void OnTimer(){
if(executed >= Parts) return;
double price = (BuyNotSell? SymbolInfoDouble(_Symbol,SYMBOL_ASK)
: SymbolInfoDouble(_Symbol,SYMBOL_BID));
int digits = (int)SymbolInfoInteger(_Symbol,SYMBOL_DIGITS);
double lotstep = SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_STEP);
double minlot = SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN);
double each = MathMax(NormalizeDouble(Lots/Parts,2), minlot);
each = MathFloor(each/lotstep)*lotstep;
int type = (BuyNotSell? OP_BUY : OP_SELL);
int ticket = OrderSend(_Symbol, type, each, price, SlippagePoints, 0, 0, "TWAP", Magic, 0, clrNONE);
if(ticket > 0) executed++;
}
実弾運用では、指値→滞留→成行のフェイルオーバー、スプレッド監視、ニュース時間帯の自動停止、最大ISの上限などを追加しましょう。
12. よくある落とし穴と対策
- 分割し過ぎて置き去り:価格のドリフトが強いときは区間を短くし、フェイルオーバーを早く。
- 板の見かけ厚に騙される:氷山や誘い指値に注意。約定履歴で本当に食われているか確認。
- クリプトの手数料無視:メイカー/テイカー料でISが逆転することがある。メイカー比率を高める。
- 寄り前・引け前のオークション軽視:配分比率の再学習を定期的に。
13. ミニマム運用チェックリスト
- 基準(ベンチマーク)を決める:VWAPか開場直後価格か
- IS・VWAP対比・約定率をロギング
- 出来高曲線を月次更新、イベント日は直近で再推定
- 子注文の滞留時間とサイズの上下限を設定
- キルスイッチ条件(IS、スプレッド、ニュース)
14. まとめ:執行は「再現可能な技術」
テクニカルやファンダの優位性は、執行の粗さで簡単に失われます。逆に、執行のKPIとアルゴを整えるだけで、期待リターンが目に見えて改善します。VWAP/TWAP/POVという基本フォームを持ち、データで配分比率を学習し、KPIで検証する。この地味な積み上げこそが、長期の超過収益を支えます。
コメント