テクニカルバリデーション¶
概要¶
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時間足ブレイクアウト
-
VWAPブレイク
-
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本足)を実装 |