mcpField
R
roach-strategy

roach-strategy

github.com/senpi-aiOther14051 installsUpdated today
Repository

About roach-strategy

roach-strategy is a Striker-only trading skill for Senpi's runtime. Its producer detects filtered market signals and hands them to the runtime, which handles position execution and risk controls.

Key features

  1. 0190-second market-signal producer
  2. 02Striker signal filters and cooldowns
  3. 03Runtime-managed execution and risk limits
  4. 04Maker-first exits with taker fallback
  5. 05Daemon health and activity monitoring

Use cases

  1. 01Sending qualifying market signals to Senpi runtime
  2. 02Running a strategy with runtime-enforced risk limits
  3. 03Monitoring producer daemon health and signal activity

Install

Copy the command and run it in a terminal.

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

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

Bundled files

References and scripts installed along with SKILL.md.

README.md
runtime.yaml
config/
roach-config.json
references/
skill-attribution.md
scripts/
roach_config.py
roach-producer.py

Details

From the project README

🪳 ROACH v3.0.0 — Striker Only. senpi_runtime_helpers.

Cockroaches survive anything. ROACH survives by not trading when there's no explosion.


What changed in v2.0

Architecture (not thesis):

Layerv1.xv2.0
Trading loopAgent runs scanner, agent calls create_positionProducer pushes signals via SenpiClient.push_signal(); runtime owns execution
Entry gateAgent decidesLLM pass-through gate (producer already filtered)
ExitDSL via runtime.yaml (good)Same DSL preset, but with FEE_OPTIMIZED_LIMIT order type — maker-first with 60s window, taker fallback
Risk gatesAgent enforces in scanner codeDeclarative via runtime.risk.guard_rails
Per-asset cooldownProducer state fileRuntime + producer (defense in depth)

Why v2: v1 used MARKET orders for every exit, paying ~3 bp/exit in HL taker fees. Recent 25-trade sample: $46 in HL fees, 100% taker. v2's FEE_OPTIMIZED_LIMIT with ensure_execution_as_taker: true and 60s timeout prefers maker fill but accepts taker fallback when the position must close. Expected recovery: 50-70% of HL exit fees.

Thesis preserved from v1.2: Stalker disabled. Striker only. FIRST_JUMP from #25+, rank jump >= 15 OR contribVelocity >= 15, score >= 10 with 4+ reasons, 1.5x volume, 1h price aligned, 4h trend aligned, XYZ banned.


Files

FilePurpose
runtime.yamlsenpi-trading-runtime spec (scanners, actions, exit DSL, guard_rails)
scripts/roach-producer.pyCron-driven producer — emits Striker signals to runtime
scripts/roach_config.pyShared MCP helper + atomic state I/O
config/roach-config.jsonOperator-tunable defaults (informational; producer constants WIN)

Producer behavior

Runs every 90s as a long-lived daemon (via producer_daemon; scanner_lock with stale-PID auto-recovery is owned by the daemon). On each tick:

  1. Reentrancy guard: acquires state/<wallet-hash>/producer.lock. If a prior run hasn't released it (cron faster than MCP latency), this run skips cleanly.
  2. Fetch markets: leaderboard_get_markets (top 50, XYZ filtered out at parse time).
  3. Detect striker signals: rank jumps, contribVelocity, contribution explosions vs scan history.
  4. Apply hard gates: 4h trend aligned, cc_15m >= 0.5, 1h price aligned >= 0.1%, volume >= 1.5x, score >= 10, 4+ reasons, asset not in 120min cooldown.
  5. Emit signals via client.push_signal() (direct HTTP POST to the runtime API).
  6. Persist scan history + cooldown state under state/<wallet-hash>/.

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


Entry flow

Producer daemon (90s tick)
  ↓ Striker signal detected
  ↓ client.push_signal(scanner="roach_signals", ...)
Runtime
  ↓ Schema-validates fields against runtime.yaml
  ↓ LLM gate (decision_model = ${ROACH_DECISION_MODEL})
  ↓ Pass-through unless malformed (producer already filtered everything else)
  ↓ OPEN_POSITION via FEE_OPTIMIZED_LIMIT (maker-first, 60s, taker fallback)
DSL (runtime-managed)
  ↓ Phase 1 max_loss 18% / 3-breach
  ↓ Phase 2 tiers (7/40, 12/55, 15/75, 20/85)
  ↓ hard_timeout 120min, weak_peak 45min, dead_weight 25min
  ↓ 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
${ROACH_DECISION_MODEL}Bare model name for LLM gate. NO provider prefix (e.g. google/..., anthropic/..., openai/...) — OpenClaw double-prefixes and rejects with 500 Unknown model. Pick any model your OpenClaw host's runtime registry supports.

The producer reads:

VarPurposeDefault
ROACH_WALLETWallet (must match runtime YAML's wallet). Agent-specific by design — do NOT use generic STRATEGY_ADDRESS. Per Turbine v2.0.9 contamination fix: a shared env var is a fleet-wide vector if multiple agents share an install.— (required; producer fails loud)
OPENCLAW_BINCLI binary nameopenclaw
EXTERNAL_SCANNER_NAMEScanner IDroach_signals
ROACH_LEVERAGELeverage to assert in signal payload7
ROACH_MARGIN_USDMargin per slot to assert in signal payload250

Producer install (on OpenClaw host)

Source path in the senpi-skills repo: roach/. Install destination on the OpenClaw host: /data/workspace/skills/roach-strategy/. The two names differ — repo uses roach, install dir uses the SKILL.md name field (roach-strategy).

Full operator-facing install runbook lives in README.md — five-step flow (openclaw.json plugin registration → install senpi-trading-runtime skill → pull Roach files → env vars → recreate runtime + launch daemon → smoke test).

After install, manage the daemon via the senpi-helpers CLI:

senpi-helpers list                                  # daemons visible with recent LAST_TICK
senpi-helpers health roach-<wallet-suffix>          # exit 0 = healthy
senpi-helpers stats roach-<wallet-suffix> --hours 1 # signals posted + error histogram
senpi-helpers restart roach-<wallet-suffix>         # stop + re-exec from boot.json

Inspect producer state (per-wallet scan history):

ls -la /data/workspace/skills/roach-strategy/state/<wallet-hash>/
# Expect: scan-history.json with mtime in last few minutes.
# A fresh scan-history.json (mtime < 5 min) confirms the daemon is ticking.

Risk envelope (declarative, runtime-enforced)

SettingValue
Slots (max concurrent positions)2
Margin per slot$250
Default leverage7x
Daily loss halt10%
Drawdown halt25%
Max entries per day6
Max consecutive losses3
Post-loss cooldown30 min
Per-asset cooldown120 min
XYZ equitiesBanned at producer scan level

Expected behavior

MetricExpected
Trades/day (chop)0-1
Trades/day (trending)1-3
Days with zero tradesCommon and correct
Win rate50-70% target (Striker quality)
Avg fee per closeMaterially lower than v1 (maker fills)
Total fees / volume~50-70% reduction vs v1 baseline

SILENCE IS CORRECT. If Roach goes 24-48 hours without a trade, that means there were no FIRST_JUMP explosions worth taking. That's the experiment working, not a bug.


What was removed in v2

Removed (responsibilities moved to runtime):

  • roach-scanner.py (replaced by roach-producer.py)
  • Trade counter / daily-loss tracking (runtime guard_rails)
  • Bootstrap gate / config/bootstrap-complete.json (runtime install handles state)
  • Asset cooldown bookkeeping in scanner (still in producer as defense-in-depth, but runtime is the authority)
  • Dynamic slots based on PnL (runtime owns slots)
  • All create_position calls (runtime owns execution)

Permanently disabled (decided in v1.0):

  • Stalker mode and all accumulation detection
  • XYZ equities (banned at scan level)

License

MIT — Built by Senpi (https://senpi.ai). 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