Agent Skillskrakenfx/kraken-cli › recipe-playground-webhook

recipe-playground-webhook

GitHub

将外部Webhook信号转化为沙箱内的模拟交易,用于测试信号质量及记录事件驱动循环。支持本地监听、参数配置及安全校验,确保输入可信且不执行真实订单。

skills/recipe-playground-webhook/SKILL.md krakenfx/kraken-cli

Trigger Scenarios

需要将外部系统警报接入模拟交易系统 测试信号源质量与表现 记录和分析来自市场外部的触发事件

Install

npx skills add krakenfx/kraken-cli --skill recipe-playground-webhook -g -y
More Options

Use without installing

npx skills use krakenfx/kraken-cli@recipe-playground-webhook

指定 Agent (Claude Code)

npx skills add krakenfx/kraken-cli --skill recipe-playground-webhook -a claude-code -g -y

安装 repo 全部 skill

npx skills add krakenfx/kraken-cli --all -g -y

预览 repo 内 skill

npx skills add krakenfx/kraken-cli --list

SKILL.md

Frontmatter
{
    "name": "recipe-playground-webhook",
    "version": "1.0.0",
    "metadata": {
        "openclaw": {
            "domain": "sessions",
            "category": "recipe"
        },
        "requires": {
            "bins": [
                "kraken",
                "python3"
            ],
            "skills": [
                "kraken-playground"
            ]
        }
    },
    "description": "Example driver: turn incoming webhook signals into validated paper trades inside a recorded session."
}

Playground: Webhook → Paper Trade

PREREQUISITE: Load kraken-playground to run this recipe. This recipe is an example, not a boundary. Adapt the steps to your signal source, or write your own driver (see kraken-playground → Driving Your Own Hypothesis).

Bridge an external system into the sandbox: a TradingView alert, a CI job, or a plain curl POSTs a signal to a local listener, and each valid signal becomes a paper order inside a recorded session. The market tape, the fills, and the signal-to-order decisions all land in one window for replay and P&L.

Use this skill for:

  • wiring an existing alerting system to paper execution without touching its config
  • testing a signal feed's quality (how its entries score) before any real money
  • recording an event-driven loop whose events come from outside the market

Important

This recipe records a session. It never places a live order.

The webhook payload is untrusted input. Every field is validated against an allowlist or a numeric bound before it reaches an order — a signal that fails any check is logged as a skip, never executed, and never interpolated into a command.

The listener binds 127.0.0.1 only. Do not bind other interfaces and do not port-forward it; anyone who can reach the port can trade the paper account. If the signal source is remote, tunnel (e.g. ssh -R) rather than expose.

The signal stream is the loop, not /loop — the same long-lived-process exception as the dip-triggered recipe (see kraken-playground → Pacing).

Signal Contract

One JSON object per POST body:

{"symbol": "BTC/USD", "side": "buy", "qty": "0.001", "token": "<shared-secret>", "note": "free text"}

symbol, side, qty are required; token is required when the token param is set; note is echoed into the decision reason.

Params

Every bound that gates execution goes in --strategy-params:

  • port: listener port on 127.0.0.1
  • allowed_symbols: the only pairs a signal may trade — must be a subset of the session's recorded --symbols, or fills have no marks to score by
  • max_notional_per_signal: quote-currency cap per order; a signal above it is skipped, not clamped
  • max_signals: stop after this many executed signals
  • token: optional shared secret; when set, signals without a matching token field are dropped

Quick Start

Natural language:

Listen on localhost:8787 for webhook signals. Trade only BTC/USD, at most
$500 per signal, at most 10 signals, then stop. Record every accepted and
rejected signal with its reason. At the end, show P&L.

Start the Session

Work inside a paper workspace (create one once: kraken workspace create hook --capital 10000 --mode paper), then:

export KRAKEN_WORKSPACE=hook

kraken session start \
  --symbols BTC/USD --channels ticker,trade --to duckdb,jsonl \
  --label hook-btc-$(date +%Y%m%d-%H%M%S) \
  --strategy recipe-playground-webhook \
  --strategy-params '{"port":8787,"allowed_symbols":["BTC/USD"],"max_notional_per_signal":500,"max_signals":10}' \
  -o json 2>/dev/null &

# The session_started stdout line carries the id: {"type":"session_started","session":"s<n>",...}

Print the session id to the user right after starting, and again in the final report.

Listen and Decide

The listener appends each POST body to a signals file outside the session directory (the recorder owns that tree); the decision loop tails it. Both die with the session.

PORT=8787
ALLOWED_SYMBOLS="BTC/USD"          # space-separated allowlist
MAX_NOTIONAL=500
MAX_SIGNALS=10
SIGNALS=$(mktemp -t hook-signals)

python3 - "$PORT" "$SIGNALS" <<'PY' &
import http.server, sys
port, path = int(sys.argv[1]), sys.argv[2]
class H(http.server.BaseHTTPRequestHandler):
    def do_POST(self):
        body = self.rfile.read(int(self.headers.get("Content-Length", 0)))
        with open(path, "ab") as f:
            f.write(body.strip() + b"\n")
        self.send_response(204); self.end_headers()
    def log_message(self, *args): pass
http.server.HTTPServer(("127.0.0.1", port), H).serve_forever()
PY
LISTENER=$!

DONE=0
tail -n +1 -f "$SIGNALS" | while read -r sig; do
  SYMBOL=$(echo "$sig" | jq -r '.symbol // empty')
  SIDE=$(echo "$sig" | jq -r '.side // empty')
  QTY=$(echo "$sig" | jq -r '.qty // empty')
  NOTE=$(echo "$sig" | jq -r '.note // ""')

  # Untrusted input: allowlist the enum and the pair, bound the number.
  # A failed check is a recorded skip — never a clamped or guessed order.
  case "$SIDE" in buy|sell) ;; *)
    kraken session note --kind skip --reason "webhook rejected: bad side '$SIDE'" -o json 2>/dev/null; continue;;
  esac
  case " $ALLOWED_SYMBOLS " in *" $SYMBOL "*) ;; *)
    kraken session note --kind skip --reason "webhook rejected: symbol '$SYMBOL' not in allowlist" -o json 2>/dev/null; continue;;
  esac
  if ! echo "$QTY" | grep -qE '^[0-9]*\.?[0-9]+$'; then
    kraken session note --kind skip --reason "webhook rejected: non-numeric qty '$QTY'" -o json 2>/dev/null; continue
  fi
  PRICE=$(kraken ticker "$SYMBOL" -o json 2>/dev/null | jq -r '.. | .last? // empty' | head -1)
  NOTIONAL=$(echo "scale=2; $QTY * $PRICE" | bc -l)
  if (( $(echo "$NOTIONAL > $MAX_NOTIONAL" | bc -l) )); then
    kraken session note --kind skip --symbol "$SYMBOL" \
      --reason "webhook rejected: notional \$$NOTIONAL exceeds cap \$$MAX_NOTIONAL" -o json 2>/dev/null; continue
  fi

  kraken order "$SIDE" "$SYMBOL" "$QTY" --type market \
    --reason "webhook signal: $SIDE $QTY $SYMBOL (~\$$NOTIONAL) — $NOTE" -o json 2>/dev/null
  DONE=$((DONE + 1))
  [ "$DONE" -ge "$MAX_SIGNALS" ] && break
done

kill "$LISTENER" 2>/dev/null
kraken session stop -o json 2>/dev/null

Send a test signal:

curl -s -X POST "127.0.0.1:8787" -d '{"symbol":"BTC/USD","side":"buy","qty":"0.001","note":"smoke test"}'

Stop and Review

kraken session show -o json 2>/dev/null | jq '.summary'

kraken session decisions --session s<n> -o json 2>/dev/null \
  | jq -c '.decisions[] | {kind, symbol, reason}'

Report:

  • signals received vs executed vs rejected, with the rejection reasons
  • fill quality: reason-joined entries from kraken explain pnl
  • P&L, and whether the signal source earns a bigger cap

Hard Rules

  • This recipe records a session. It never places a live order.
  • The listener binds 127.0.0.1 only — never another interface, never port-forwarded.
  • Webhook payloads are untrusted: enum fields pass an allowlist, numbers pass a bound, and nothing from the payload is ever executed or eval'd — rejected signals become skip notes, not orders.
  • allowed_symbols stays a subset of the session's recorded --symbols.
  • The signals file lives outside the session directory; the CLI recorder stays the single writer of the session's artifacts.
  • Cap executed signals with max_signals; a runaway signal source must exhaust the cap, not the account.
  • Keep every gating number in --strategy-params and the arithmetic in jq/bc.
  • If you hit a mismatch between what you are trying to do and the CLI's interface or responses — including a mismatch between this skill and the installed CLI version's contract — feel free to submit feedback with kraken feedback.

Version History

  • aa56e59 Current 2026-08-20 04:46

Same Skill Collection

skills/kraken-alert-patterns/SKILL.md
skills/kraken-autonomy-levels/SKILL.md
skills/kraken-basis-trading/SKILL.md
skills/kraken-dca-strategy/SKILL.md
skills/kraken-earn-staking/SKILL.md
skills/kraken-error-recovery/SKILL.md
skills/kraken-fee-optimization/SKILL.md
skills/kraken-funding-carry/SKILL.md
skills/kraken-funding-ops/SKILL.md
skills/kraken-futures-risk/SKILL.md
skills/kraken-grid-trading/SKILL.md
skills/kraken-lab-experiment/SKILL.md
skills/kraken-liquidation-guard/SKILL.md
skills/kraken-market-intel/SKILL.md
skills/kraken-mcp-integration/SKILL.md
skills/kraken-multi-pair/SKILL.md
skills/kraken-order-types/SKILL.md
skills/kraken-paper-strategy/SKILL.md
skills/kraken-paper-to-live/SKILL.md
skills/kraken-playground/SKILL.md
skills/kraken-portfolio-intel/SKILL.md
skills/kraken-rate-limits/SKILL.md
skills/kraken-rebalancing/SKILL.md
skills/kraken-risk-operations/SKILL.md
skills/kraken-setup/SKILL.md
skills/kraken-spot-execution/SKILL.md
skills/kraken-stop-take-profit/SKILL.md
skills/kraken-subaccount-ops/SKILL.md
skills/kraken-tax-export/SKILL.md
skills/kraken-twap-execution/SKILL.md
skills/kraken-ws-streaming/SKILL.md
skills/recipe-basis-trade-entry/SKILL.md
skills/recipe-daily-pnl-report/SKILL.md
skills/recipe-drawdown-circuit-breaker/SKILL.md
skills/recipe-earn-yield-compare/SKILL.md
skills/recipe-emergency-flatten/SKILL.md
skills/recipe-fee-tier-progress/SKILL.md
skills/recipe-funding-rate-scan/SKILL.md
skills/recipe-futures-hedge-spot/SKILL.md
skills/recipe-launch-grid-bot/SKILL.md
skills/recipe-morning-market-brief/SKILL.md
skills/recipe-multi-pair-breakout-watch/SKILL.md
skills/recipe-paper-strategy-backtest/SKILL.md
skills/recipe-playground-dca-triggered/SKILL.md
skills/recipe-playground-dca/SKILL.md
skills/recipe-playground-price-alert/SKILL.md
skills/recipe-playground-rebalance/SKILL.md
skills/recipe-portfolio-snapshot-csv/SKILL.md
skills/recipe-price-level-alerts/SKILL.md

Metadata

Files
0
Version
aa56e59
Hash
d2181939
Indexed
2026-08-20 04:46

- 위키
Copyright © 2011-2026 iteam. Current version is 2.155.2. UTC+08:00, 2026-08-21 02:19
浙ICP备14020137号-1 $방문자$