mcpField
O
owl-strategy

owl-strategy

github.com/senpi-aiOther14056 installsUpdated today
Repository

About owl-strategy

owl-strategy is a Senpi skill that scans crypto perpetuals for crowded trades showing exhaustion, then signals a contrarian entry. The producer daemon submits signals; the runtime owns execution and position management.

Key features

  1. 01Crowding and exhaustion scoring
  2. 02Persistence and macro trend gates
  3. 03Crypto perpetuals universe with OI filter
  4. 04Contrarian signal submission
  5. 05Runtime-enforced risk limits

Use cases

  1. 01Finding crowded trades with signs of exhaustion
  2. 02Filtering fade signals during strong BTC moves
  3. 03Submitting contrarian candidates to the runtime

MCP support

The producer uses SenpiClient.mcp_call() to fetch market data and positioning, then SenpiClient.push_signal() to send a contrarian signal. The runtime validates and processes signals.

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/senpi-ai/senpi-skills --skill owl-strategy

After installing, type/owl-strategyin Claude Code to confirm it loaded.

Bundled files

References and scripts installed along with SKILL.md.

README.md
runtime.yaml
config/
owl-config.json
references/
skill-attribution.md
scripts/
owl_config.py
owl-producer.py

Details

From the project README

🦉 OWL v8.0 — Pure Contrarian. Helpers-Native. Maker Exits.

Wait for the crowd to overcommit. Wait for them to exhaust. Then eat their liquidations.

One thesis: the crowd is wrong. Every other skill in the fleet enters WITH momentum, WITH the trend, WITH smart money. OWL is the only skill that enters AGAINST the crowd. The edge: crowded trades unwind violently and predictably.


What changed in v8.0.0

Plumbing-only migration. NO thesis change. v7.1's crowding/exhaustion scoring, persistence gates, MACRO_TREND_GATE, conviction leverage, DSL preset are all preserved verbatim.

Six-layer plumbing flip on @senpi-ai/runtime 1.1.0 (same pattern as Wolverine/Lemon/Cheetah v3.0+ migrations):

Layerv7.1v8.0
MCP callsmcporter subprocessSenpiClient.mcp_call() direct HTTPS
Signal emitopenclaw senpi external-scanner ingest subprocessSenpiClient.push_signal() direct HTTP POST
Reentrancyhand-rolled fcntl flock on producer.lockproducer_daemon.scanner_lock (stale-PID auto-recovery)
Tick schedulingopenclaw cron + agentTurnlong-lived producer_daemon process
/state alive_checknonewallet=/scanner= kwargs → daemon self-terminates if runtime/scanner removed
Signal type tagginginferred from payloadsignal_type="OWL_CONTRARIAN_FADE" passed explicitly

Why v8.0: keeps Owl on the same plumbing as the rest of the fleet. Eliminates per-tick subprocess overhead (~30-60s → ~1-3s ticks). No thesis change — v7.1 was the most recent thesis-level work.


Thesis (preserved from v7.1 / v6.2)

  • Crowding score: funding extremity (0-4) + SM tilt (0-3, +1 if confirms funding) + OI concentration (0-2). Floor 6.
  • Persistence: 1+ hour above floor, with 2-tick tolerance for noise (v5.3)
  • Exhaustion score: volume declining + price stalling + volume spike no follow-through + RSI divergence. ≥ 2 distinct signals, score ≥ 5.
  • Combined score ≥ 12 to fire.
  • Macro trend gate: block crypto fades when |BTC 4h move| > 3% (v7.1).
  • 6h post-loss per-asset cooldown.
  • Universe: ALL crypto perps with OI > $3M (v6.1 expansion, no top-30 truncation).
  • XYZ banned (different unwind dynamics; needs separate calibration).

Files

FilePurpose
runtime.yamlRuntime spec (scanners, actions, exit DSL, guard_rails) — schema version 1.8.0
scripts/owl-producer.pyLong-lived helpers-native producer daemon (15-min cadence)
scripts/owl_config.pyShared MCP helper + _wrapper_client proxy + atomic state I/O
config/owl-config.jsonOperator-tunable defaults (informational; producer constants WIN)

Producer behavior

Runs every 15 minutes (long-lived daemon, NOT openclaw cron). On each tick:

  1. Resolve wallet (OWL_WALLET env var, falls back to config.wallet); fail loud if both empty.
  2. Read account value via strategy_get_clearinghouse_state for sizing + dynamic cap.
  3. Apply dynamic daily cap (defense-in-depth alongside runtime guard_rails).
  4. Fetch universe: market_list_instruments (~80-100 crypto perps with OI > $3M).
  5. Fetch SM positioning map (one MCP call shared across all assets).
  6. MACRO_TREND_GATE: if |BTC 4h move| > 3%, skip tick.
  7. Score crowding per asset + update persistence history.
  8. Filter to persisted candidates (≥ 1h above crowding floor).
  9. Detect exhaustion for persisted candidates only (saves MCP calls).
  10. Filter combined score ≥ 12 + per-asset cooldown.
  11. Emit top contrarian candidate via cfg._wrapper_client.push_signal(..., signal_type="OWL_CONTRARIAN_FADE", ...) with conviction-scaled leverage (7/8/10 by score).
  12. Persist crowding history + cooldown state under state/<wallet-hash>/.

NO execution code. NO position-tracking. NO DSL state. The runtime owns all of that.

Direction is OPPOSITE of crowd direction. This is the entire edge — Owl is the only fleet agent that fades crowding.


Entry flow

Producer daemon tick (every 900s)
  ↓ Crowding score >= 6, persisted >= 1h
  ↓ Exhaustion score >= 5 with >= 2 signals
  ↓ Combined score >= 12
  ↓ SenpiClient.push_signal(scanner="owl_signals", signal_type="OWL_CONTRARIAN_FADE", ...)
Runtime (127.0.0.1:8787)
  ↓ Schema-validates fields against runtime.yaml
  ↓ LLM gate (decision_model = ${OWL_DECISION_MODEL})
  ↓ Pass-through unless malformed; rejects if direction == crowdDirection
  ↓ OPEN_POSITION via FEE_OPTIMIZED_LIMIT (maker-only, 60s, NO taker fallback)
DSL (runtime-managed)
  ↓ Phase 1 max_loss 35% / single-breach (wide for contrarian retrace)
  ↓ Phase 2 6-tier ladder starting at 5% trigger (Lemon-pattern first leg)
  ↓ hard_timeout 480m, weak_peak 120m@2%, dead_weight 30m
  ↓ Exit via FEE_OPTIMIZED_LIMIT (maker-first, 60s, taker fallback)

Required env vars

The runtime YAML uses these substitutions:

VarPurpose
${WALLET_ADDRESS}Strategy wallet address
${TELEGRAM_CHAT_ID}Telegram chat ID for notifications
${OWL_DECISION_MODEL}Bare model name for LLM gate. NO provider prefix.

The producer reads:

VarPurposeDefault
SENPI_AUTH_TOKENRequired for MCP calls + signal POST— (required; producer fails loud)
OWL_WALLETWallet (must match runtime YAML's wallet). Agent-specific by design. Per Turbine v2.0.9 contamination fix.falls back to config.wallet
OWL_MARGIN_PCTFraction of account value per slot0.25
OWL_MIN_OI_USDOverride OI floor3000000

Risk envelope (declarative, runtime-enforced)

SettingValue
Slots2
Margin per slot25% of account value (default ~$250 on $1k)
Default leverage8x (conviction tiers: 7x at 12-13, 8x at 14-15, 10x at 16+)
Daily loss halt10%
Drawdown halt25% (also producer-side circuit breaker)
Max entries per day4 (runtime ceiling); producer dynamic cap by PnL
Max consecutive losses4
Per-asset cooldown360 min (6h post-loss)
Asset universeAll crypto perps with OI > $3M (XYZ banned)

Dynamic daily cap (producer-side, v6 carryover):

Account stateMax entries / day
PnL < -25%0 (HARD STOP — runtime also halts)
PnL < -15%1
PnL < -5%2
Day realized PnL < +$1502 (base)
Day realized PnL ≥ +$1503
Day realized PnL ≥ +$4004

Expected behavior

MetricExpected
Crowded assets per scan5-15 above floor
Persisted ≥ 1h1-3 typically
Exhaustion confluence0-1 per scan
Trades per day0-2
Avg hold1-8h
Win rate target60-70% (contrarian unwinds, when timed right, are reliable)

Silence is correct. Owl waits for both the crowd state AND the exhaustion trigger. Most days, one or both is missing. Don't improvise.


v8.0.0 changelog

  • Plumbing-only. Six-layer flip per Wolverine v5.0 / Lemon v2.0 template. Thesis preserved verbatim from v7.1.
  • owl_config.py: mcporter_call() now routes through SenpiClient.mcp_call() (direct HTTPS). Exposes _wrapper_client proxy for push_signal().
  • owl-producer.py: drops fcntl lockfile + subprocess.run([...ingest]). Uses producer_daemon(fn=main, interval_seconds=900, ...) and cfg._wrapper_client.push_signal(signal_type="OWL_CONTRARIAN_FADE", ...).
  • runtime.yaml: schema version bump 1.7.1 → 1.8.0. Description rewritten. DSL preset, scanner owl_signals, action owl_entry, consecutive_breaches_required: 1 unchanged.
  • State files unchanged. crowding-history.json / asset-cooldowns.json / trade-counter.json continue to live under state/<wallet-hash>/.

License

Apache-2.0 — Built by Senpi (https://senpi.ai). Attribution required for derivative works. Source: https://github.com/Senpi-ai/senpi-skills


Skill Attribution

When creating a strategy, include skill_name and skill_version in the call. See references/skill-attribution.md for details.

Comments

Markdown supported