# ── RAPTOR (v2 supervised) ───────────────────────────────────────────
# Whale copy-follow — quality-first hot-streak follower. SINGLE wallet,
# SINGLE recipe, ONE supervised scanner.
#
# Ported from senpi-skills/raptor (producer v4.0.1, config v3.1) to the v2
# supervised external-scanner contract. The producer daemon is gone: the
# runtime supervises ./scanners/scan.py and calls scan(inputs, ctx) every
# `interval_seconds` (180s). All gates + scoring tiers preserved exactly;
# see scan.py + scoring.py.
#
# DOC-vs-CODE: the SKILL/README docs in senpi-skills are STALE (they say
# trader gate $2M / concentration 0.40). The CODE (config v3.1 + producer
# constants) is authoritative and is what this port uses: trader delta gate
# $500k, position gate $100k, concentration 0.35, SM minPct 2 / minTraders 10,
# whale entry-discipline 5%, minScore 6.
name: raptor-tracker
version: 2.0.0
group: raptor                       # agent-facing handle (harmless for single-wallet)
description: >
  RAPTOR — Hot Streak Follower (whale copy-follow). Starts from
  discovery_get_top_traders (WEEKLY, ELITE/RELIABLE weekly winners, unrealized
  delta-pnl >= $500k), takes each whale's strongest position by |delta_pnl|
  (>= $100k) with concentration >= 0.35, confirms smart-money alignment
  (pct >= 2 / traders >= 10, direction match) and whale entry-discipline (skip
  if price ran > 5% from the whale's entry), then additively scores (max ~16)
  and emits the SINGLE best candidate per tick if score >= 6. Conviction-scaled
  leverage (7/8/10x) + margin (25%/35%). DSL: 6h hard timeout, weak_peak
  60m@2.5, dead_weight 40m, 5-tier phase2 ladder.

strategy:
  wallet: "${RAPTOR_WALLET}"
  slots: 2                          # source slots 2 (raptor still emits <=1 signal/tick — see scan.py)
  margin_pct: 25                    # source margin_pct 25 (% of account per slot; scan.py carries the exact marginPct)
  default_leverage: 7               # source leverage.default 7 (conviction-tier 7/8/10x in scan.py, clamped per-asset)
  trading_risk: moderate            # source trading_risk moderate
  enabled: true

scanners:
  - name: position_tracker          # built-in: feeds DSL exit engine
    type: position_tracker
    interval_seconds: 10            # source position_tracker interval 10s

  - name: raptor_signals            # supervised external scanner
    type: external_scanner
    path: ./scanners
    entrypoint: scan.py
    interval_seconds: 180           # source producer_daemon interval_seconds 180 (3min)
    timeout_seconds: 120            # source tick_timeout 120
    default_signal_validity_seconds: 360   # 2x tick; pass-through gate re-scores next tick
    state_history_max_count: 200    # holds the per-(trader,asset) 4h event-dedup map records
    inputs:
      # ── trader-pool + position gates (config.hotStreak) ──
      qualityPoolSize: 20           # discovery_get_top_traders limit
      positionsFetchLimit: 10       # scan the top-10 quality traders' positions
      minDeltaPnl: 500000           # trader unrealized delta-pnl gate ($500k — CODE, not stale $2M docs)
      minPositionPnl: 100000        # strongest-position |delta_pnl| gate ($100k)
      minConcentration: 0.35        # best/total |delta_pnl| concentration gate (0.35 — CODE, not stale 0.40)
      # ── smart-money alignment (config.smAlignment) ──
      minSmPct: 2.0                 # SM pct_of_top_traders_gain floor
      minSmTraders: 10             # SM trader_count floor
      requireDirectionMatch: true  # SM direction must match the whale's direction
      # ── entry + sizing (config.entry / config.leverage) ──
      minScore: 6                  # additive-score floor to emit
      marginPctBase: 0.25          # margin = account_value * 0.25
      marginPctHighConv: 0.35      # ... or 0.35 when score >= 10
      defaultLeverage: 7           # leverage fallback (tiers: >=10 -> 10x, >=8 -> 8x, >=6 -> 7x)
      # ── dedup (config.dedupe) ──
      eventDedupeHours: 4          # per-(trader, asset) event dedup window (ctx.state)
    signal_data_schema:
      score: { type: number }
      tcs: { type: string, required: false }
      traderId: { type: string, required: false }
      traderDeltaPnl: { type: number, required: false }
      positionDeltaPnl: { type: number, required: false }
      concentration: { type: number, required: false }
      smPct: { type: number, required: false }
      smTraders: { type: number, required: false }
      priceChg4h: { type: number, required: false }
      priceChg1h: { type: number, required: false }
      whaleEntryPx: { type: number, required: false }
      currentPx: { type: number, required: false }
      reasons: { type: array, required: false }
      heldAssets: { type: array, required: false }

actions:
  - name: position_tracker_action   # rule-based lifecycle → DSL
    action_type: POSITION_TRACKER
    decision_mode: rule
    scanners: [position_tracker]

  - name: raptor_entry              # OPEN_POSITION, rule mode (source LLM gate was pure pass-through)
    action_type: OPEN_POSITION
    decision_mode: rule
    scanners: [raptor_signals]
    params:
      order_type: FEE_OPTIMIZED_LIMIT
      fee_optimized_limit_options:
        ensure_execution_as_taker: true    # source entry.ensureExecutionAsTaker true
        execution_timeout_seconds: 60
    context:
      - type: signal
        scanner: raptor_signals

# ── EXIT (DSL — conviction copy-follow; preset preserved from source v3.3) ──
exit:
  engine: dsl
  interval_seconds: 30              # source exit interval_seconds 30
  order_type: FEE_OPTIMIZED_LIMIT
  fee_optimized_limit_options:
    ensure_execution_as_taker: true
    execution_timeout_seconds: 60
  dsl_preset:
    hard_timeout:
      enabled: true
      interval_in_minutes: 360      # source hard_timeout 360min (6h absolute cap)
    weak_peak_cut:
      enabled: true
      interval_in_minutes: 60       # source weak_peak 60min
      min_value: 2.5                # source weak_peak min 2.5%
    dead_weight_cut:
      enabled: true
      interval_in_minutes: 40       # source dead_weight 40min
    phase1:
      enabled: true
      max_loss_pct: 25.0            # source phase1 max_loss 25
      retrace_threshold: 10         # source phase1 retrace 10
      consecutive_breaches_required: 1
    phase2:
      enabled: true
      tiers:                        # source T0..T4 — carried verbatim
        - { trigger_pct: 8,  lock_hw_pct: 25 }
        - { trigger_pct: 15, lock_hw_pct: 50 }
        - { trigger_pct: 25, lock_hw_pct: 65 }
        - { trigger_pct: 40, lock_hw_pct: 80 }
        - { trigger_pct: 60, lock_hw_pct: 88 }

# ── RISK guard rails (from source runtime.yaml; minutes/hours → seconds) ──
risk:
  data_retention_seconds: 259200    # 72h (was data_retention_hours 72)
  guard_rails:
    daily_loss_limit_pct: 15
    max_entries_per_day: 6
    bypass_max_entries_per_day_on_profit: false
    max_consecutive_losses: 3
    cooldown_seconds: 1800          # was cooldown_minutes 30
    drawdown_halt_pct: 25
    drawdown_reset_on_day_rollover: false
    per_asset_cooldown_seconds: 7200   # was per_asset_cooldown_minutes 120 (2h)

notifications:
  telegram_chat_id: "${TELEGRAM_CHAT_ID}"
  dsl_lifecycle: true
  dsl_notify_sl_updates: false
  action_lifecycle: true
