コンテンツにスキップ

テクニカルバリデーション

概要

Technical Validator は、UWフロー検知後にテクニカル条件の成立を確認するモジュールです。

設計理念

フロー検知だけでエントリーせず、「重要ラインのブレイクアウト」を確認してからエントリーする。


アーキテクチャ

graph LR
    A[UWフロー検知] --> B[Flow Validator]
    B --> C[WATCHING状態]
    C --> D[Technical Validator]
    D --> E{条件成立?}
    E -->|Yes| F[ENTRY_TRIGGERED]
    E -->|No| G[継続監視]
    G --> D

重要ライン検出

検出対象

ライン種別 計算方法 優先度
200 EMA 日足200期間EMA ★★★
50 EMA 日足50期間EMA ★★☆
VWAP 当日出来高加重平均 ★★★
前日高値/安値 前日のHigh/Low ★★☆
需要エリア 過去20日の高出来高ゾーン ★★☆

需要エリア検出

def detect_demand_zones(
    bars: List[ChartBar],
    lookback: int = 20,
    volume_threshold: float = 2.0
) -> List[DemandZone]:
    """
    需要エリア(Demand Zone)を検出

    条件:
    - 出来高が平均の2倍以上
    - 価格が反発したポイント
    """
    avg_volume = sum(b.volume for b in bars) / len(bars)
    zones = []

    for i, bar in enumerate(bars):
        if bar.volume >= avg_volume * volume_threshold:
            # 反発ポイントかチェック
            if _is_reversal_point(bars, i):
                zones.append(DemandZone(
                    price_low=bar.low,
                    price_high=bar.high,
                    strength=bar.volume / avg_volume
                ))

    return zones

ブレイクアウト確認

確認ロジック

def confirm_breakout(
    bars: List[ChartBar],
    key_level: float,
    direction: str,
    confirmation_bars: int = 2
) -> bool:
    """
    ブレイクアウトを確認(ダマシ回避)

    条件:
    - 2本の足で確定(confirmation_bars=2)
    - 終値ベースで判定
    """
    recent_bars = bars[-confirmation_bars:]

    if direction == "UP":
        # 全ての足が重要ラインより上で終値
        return all(bar.close > key_level for bar in recent_bars)
    else:  # DOWN
        return all(bar.close < key_level for bar in recent_bars)

出来高確認

def confirm_volume(
    current_volume: float,
    avg_volume: float,
    threshold: float = 1.5
) -> bool:
    """
    ブレイクアウト時の出来高を確認

    条件:
    - 平均出来高の1.5倍以上
    """
    return current_volume >= avg_volume * threshold

実装詳細

core/technical_validator.py

@dataclass
class KeyLevel:
    """重要ライン"""
    price: float
    type: str  # "EMA_200", "EMA_50", "VWAP", "DEMAND_ZONE", etc.
    strength: float  # 0.0-1.0

@dataclass
class TechnicalValidation:
    """テクニカル検証結果"""
    is_valid: bool
    key_levels: List[KeyLevel]
    breakout_confirmed: bool
    volume_confirmed: bool
    trigger_price: Optional[float]
    reason: str

class TechnicalValidator:
    """テクニカル条件検証エンジン"""

    def __init__(self, config: TechnicalValidatorConfig = None):
        self.config = config or TechnicalValidatorConfig()

    def detect_key_levels(
        self,
        symbol: str,
        daily_bars: List[ChartBar],
        intraday_bars: List[ChartBar]
    ) -> List[KeyLevel]:
        """重要ラインを検出"""
        levels = []

        # 1. EMA
        ema_200 = calculate_ema(daily_bars, 200)
        levels.append(KeyLevel(ema_200, "EMA_200", 1.0))

        ema_50 = calculate_ema(daily_bars, 50)
        levels.append(KeyLevel(ema_50, "EMA_50", 0.8))

        # 2. VWAP
        vwap = calculate_vwap(intraday_bars)
        levels.append(KeyLevel(vwap, "VWAP", 0.9))

        # 3. 前日高値/安値
        prev_high = daily_bars[-2].high
        prev_low = daily_bars[-2].low
        levels.append(KeyLevel(prev_high, "PREV_HIGH", 0.7))
        levels.append(KeyLevel(prev_low, "PREV_LOW", 0.7))

        # 4. 需要エリア
        demand_zones = detect_demand_zones(daily_bars)
        for zone in demand_zones:
            levels.append(KeyLevel(
                (zone.price_low + zone.price_high) / 2,
                "DEMAND_ZONE",
                min(zone.strength / 3, 1.0)
            ))

        return levels

    def validate(
        self,
        symbol: str,
        current_price: float,
        direction: str,
        daily_bars: List[ChartBar],
        intraday_bars: List[ChartBar]
    ) -> TechnicalValidation:
        """テクニカル条件を検証"""

        # 1. 重要ライン検出
        key_levels = self.detect_key_levels(symbol, daily_bars, intraday_bars)

        # 2. 最も近い重要ラインを特定
        nearest_level = self._find_nearest_level(
            current_price, key_levels, direction
        )

        # 3. ブレイクアウト確認
        breakout_confirmed = False
        if nearest_level:
            breakout_confirmed = confirm_breakout(
                intraday_bars,
                nearest_level.price,
                direction,
                confirmation_bars=self.config.confirmation_bars
            )

        # 4. 出来高確認
        volume_confirmed = confirm_volume(
            intraday_bars[-1].volume,
            self._calculate_avg_volume(intraday_bars),
            self.config.volume_threshold
        )

        # 5. 総合判定
        is_valid = breakout_confirmed and volume_confirmed

        return TechnicalValidation(
            is_valid=is_valid,
            key_levels=key_levels,
            breakout_confirmed=breakout_confirmed,
            volume_confirmed=volume_confirmed,
            trigger_price=nearest_level.price if nearest_level else None,
            reason=self._build_reason(breakout_confirmed, volume_confirmed)
        )

すなっちゃん流ブレイクアウト

典型的なパターン

  1. 1時間足ブレイクアウト

    日付: 2023-10-17
    銘柄: AMD
    コメント: "$AMD 1時間足ブレイクアウトテスト中"
    

  2. VWAPブレイク

    日付: 2023-07-20
    銘柄: NFLX
    コメント: "vwap超え狙い"
    

  3. 200EMA反発

    日付: 2023-07-20
    銘柄: PTON
    コメント: "11.64(200EMA)に上昇中"
    


設定パラメータ

Gemini推奨値

パラメータ 説明
confirmation_bars 2 ブレイク確認に必要な足数
volume_threshold 1.5 平均出来高の倍率
demand_zone_lookback 20 需要エリア検出期間(日)
demand_zone_volume_threshold 2.0 需要エリア出来高閾値

ペーパートレードでの使用

# run_paper_trading.py

async def _watch_technical(self, ctx: TradeContext):
    """テクニカル条件を監視"""

    while ctx.state == TradeState.WATCHING_TECHNICAL:
        # 日足・5分足データ取得
        daily_bars = await self._get_daily_bars(ctx.symbol)
        intraday_bars = await self._get_5min_bars(ctx.symbol)
        current_price = intraday_bars[-1].close

        # テクニカル検証
        validation = self.technical_validator.validate(
            symbol=ctx.symbol,
            current_price=current_price,
            direction=ctx.initial_flow.direction,
            daily_bars=daily_bars,
            intraday_bars=intraday_bars
        )

        if validation.is_valid:
            logger.info(f"[{ctx.symbol}] テクニカル条件成立")
            logger.info(f"  ブレイク価格: ${validation.trigger_price:.2f}")
            logger.info(f"  出来高: 確認済み")

            self.state_machine.on_technical_trigger(ctx.symbol)
            await self._execute_entry(ctx)
            return

        # 1分待機
        await asyncio.sleep(60)

ログ出力例

[TSLA] テクニカル検証:
  重要ライン検出:
    - EMA_200: $245.30 (強度: 1.00)
    - EMA_50: $252.15 (強度: 0.80)
    - VWAP: $248.50 (強度: 0.90)
    - PREV_HIGH: $255.00 (強度: 0.70)

  現在価格: $256.20
  方向: UP
  最寄りライン: PREV_HIGH ($255.00)

  ブレイクアウト: ✅ 確認済み (2本の足で$255超え)
  出来高: ✅ 確認済み (平均の1.8倍)

  結果: VALID - エントリートリガー成立

関連ファイル

ファイル 役割
core/technical_validator.py テクニカル検証エンジン
core/momentum.py EMA/VWAP計算
core/trade_state_machine.py 状態機械連携
scripts/run_paper_trading.py ペーパートレード統合

更新履歴

日付 変更内容
2025-11-29 Gemini分析に基づき実装
2025-11-29 需要エリア検出を追加
2025-11-29 ブレイク確認ロジック(2本足)を実装