senpi-trading-runtime

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Senpi Trading Runtime — OpenClaw Plugin

Senpi Trading Runtime — OpenClaw Plugin

On-chain position tracker with automated DSL (Dynamic Stop-Loss) exit engine. Monitors a wallet's positions on Hyperliquid for lifecycle events (open, close, edit, flip) and applies two-phase trailing stop-loss protection to all positions. It links to an existing strategy wallet address and does not create wallets.
链上仓位跟踪器,搭载自动化DSL(动态止损)退出引擎。监控Hyperliquid上钱包的仓位生命周期事件(开仓、平仓、编辑、方向翻转),为所有仓位应用两阶段移动止损保护。它会关联已有的策略钱包地址,不会自行创建钱包。

Core Concepts

核心概念

Flow: Position Tracker scanner → detects position changes → DSL exit engine manages trailing stops
  1. Position Tracker (
    position_tracker
    scanner) polls the wallet on-chain, detecting opens, closes, increases, decreases, and flips.
  2. DSL exit engine monitors tracked positions on a timer, computing trailing stop-loss floors across two phases.
  3. Strategy (in runtime) = link to an existing wallet address. The wallet address is the strategy identifier everywhere, but wallet creation happens via Senpi MCP (not the runtime).
Key insight: The position tracker enables DSL protection for ALL positions of a strategy address — including those opened manually on the exchange or by other tools.
流程: Position Tracker扫描器 → 检测仓位变化 → DSL退出引擎管理移动止损
  1. Position Tracker
    position_tracker
    扫描器)轮询链上钱包,检测开仓、平仓、仓位增加、仓位减少和方向翻转。
  2. DSL退出引擎定时监控被跟踪的仓位,跨两个阶段计算移动止损底线。
  3. 运行时内的策略 = 关联已有钱包地址。钱包地址是全平台通用的策略标识,但钱包创建需要通过Senpi MCP完成,而非运行时本身。
核心要点: 仓位跟踪器可为策略地址的所有仓位提供DSL保护——包括在交易所手动开仓或通过其他工具开仓的仓位。

Wallet lifecycle (required order)

钱包生命周期(必须遵循顺序)

  1. Create strategy wallet address via Senpi MCP calls (or confirm it already exists).
  2. Put that wallet address into runtime YAML (
    strategies.<name>.wallet
    /
    ${WALLET_ADDRESS}
    ).
  3. Install/create runtime. This links the runtime to the existing wallet for monitoring and exits.
Never treat
openclaw senpi runtime create
as wallet creation.
  1. 通过Senpi MCP调用创建策略钱包地址(或确认该地址已存在)。
  2. 将该钱包地址填入运行时YAML的
    strategies.<name>.wallet
    /
    ${WALLET_ADDRESS}
    字段。
  3. 安装/创建运行时。这一步会将运行时与已有钱包关联,用于监控和退出操作。
绝对不要将
openclaw senpi runtime create
命令当作钱包创建操作。

Strategy wallet validation (mandatory before runtime create/install)

策略钱包校验(创建/安装运行前必须执行)

Use this exact MCP-first guardrail to avoid using embedded wallets by mistake:
  1. Call
    strategy_list
    and collect
    strategies[].strategyWalletAddress
    .
  2. A runtime wallet is valid only if it appears in that list (case-insensitive match).
  3. If list is empty OR provided wallet is not in list: call
    strategy_create_custom_strategy
    to create a strategy wallet first.
  4. Use the newly created strategy wallet address directly as
    WALLET_ADDRESS
    in runtime YAML, then install runtime.
Hard rules:
  • Never use embedded wallet/injected wallet for runtime linking.
  • Never treat a wallet as a strategy wallet unless it exists in
    strategy_list
    .
  • Runtime install is blocked until strategy wallet validation passes.
  • Always confirm with the user before creating a new strategy wallet address, and explicitly confirm the budget (
    initialBudget
    ) that will be used.
Example MCP flow (tool names from Senpi MCP):
text
strategy_list({})
if provided_wallet not in strategies[].strategyWalletAddress:
  # confirm with user first: create new strategy wallet + initialBudget
  strategy_create_custom_strategy({
    initialBudget: <budget_usdc>,
    positions: [],
    skillName: <strategy_or_runtime_name>,
    skillVersion: "1.0.0"
  })
Notes:
  • initialBudget
    is required when creating the strategy wallet.
  • Use
    positions: []
    when you only need the strategy wallet created now and will trade later.
请严格遵循以下MCP优先的校验规则,避免误绑定内嵌钱包:
  1. 调用
    strategy_list
    接口,收集
    strategies[].strategyWalletAddress
    列表。
  2. 只有当待绑定的钱包出现在上述列表中时才视为有效(不区分大小写匹配)。
  3. 如果列表为空,或者待绑定钱包不在列表中:请先调用
    strategy_create_custom_strategy
    创建策略钱包。
  4. 将新创建的策略钱包地址直接作为运行时YAML中的
    WALLET_ADDRESS
    使用,再安装运行时。
硬性规则:
  • 绝对不要使用内嵌钱包/注入钱包进行运行时绑定。
  • 除非钱包存在于
    strategy_list
    返回结果中,否则不要将其视为策略钱包。
  • 策略钱包校验通过前,禁止安装运行时。
  • 创建新策略钱包地址前必须与用户确认,且明确确认将使用的预算(
    initialBudget
    )。
MCP流程示例(工具名来自Senpi MCP):
text
strategy_list({})
if provided_wallet not in strategies[].strategyWalletAddress:
  # 先和用户确认:创建新策略钱包 + 初始预算
  strategy_create_custom_strategy({
    initialBudget: <budget_usdc>,
    positions: [],
    skillName: <strategy_or_runtime_name>,
    skillVersion: "1.0.0"
  })
注意事项:
  • 创建策略钱包时
    initialBudget
    为必填项。
  • 如果你只需要创建策略钱包后续再交易,可传入
    positions: []

CLI Commands

CLI命令

All commands require the OpenClaw gateway running (
openclaw gateway run
).
Use
openclaw senpi --cheatsheet
to print the full plugin command cheatsheet to stdout.
所有命令都需要先启动OpenClaw网关(
openclaw gateway run
)。
使用
openclaw senpi --cheatsheet
可在标准输出打印完整的插件命令速查表。

Runtime management

运行时管理

Prerequisite: strategy wallet address already exists (created/fetched via Senpi MCP).
bash
undefined
前置条件:策略钱包地址已存在(通过Senpi MCP创建/获取)。
bash
undefined

Create a runtime from YAML file

从YAML文件创建运行时

openclaw senpi runtime create --path ./my-strategy.yaml openclaw senpi runtime create -p ./my-strategy.yaml # short form
openclaw senpi runtime create --path ./my-strategy.yaml openclaw senpi runtime create -p ./my-strategy.yaml # 简写形式

Create with inline YAML content

用内联YAML内容创建

openclaw senpi runtime create --content "<yaml>" openclaw senpi runtime create -c "<yaml>" # short form
openclaw senpi runtime create --content "<yaml>" openclaw senpi runtime create -c "<yaml>" # 简写形式

Create with custom ID

创建时指定自定义ID

openclaw senpi runtime create --path ./my-strategy.yaml --runtime-id my-name
openclaw senpi runtime create --path ./my-strategy.yaml --runtime-id my-name

List installed runtimes (id, wallet, source, status)

列出已安装的运行时(ID、钱包、来源、状态)

openclaw senpi runtime list
openclaw senpi runtime list

Delete a runtime

删除运行时

openclaw senpi runtime delete <runtime_id> # positional id openclaw senpi runtime delete --id <runtime_id> # named flag
undefined
openclaw senpi runtime delete <runtime_id> # 位置参数传ID openclaw senpi runtime delete --id <runtime_id> # 命名参数传ID
undefined

DSL position inspection

DSL仓位查看

bash
undefined
bash
undefined

All active DSL-tracked positions

所有被DSL跟踪的活跃仓位

openclaw senpi dsl positions openclaw senpi dsl positions -r <id> # filter by runtime id openclaw senpi dsl positions -a <addr> # filter by wallet address openclaw senpi dsl positions --json
openclaw senpi dsl positions openclaw senpi dsl positions -r <id> # 按运行时ID过滤 openclaw senpi dsl positions -a <addr> # 按钱包地址过滤 openclaw senpi dsl positions --json

Inspect one position (full DslState)

查看单个仓位的完整DslState

openclaw senpi dsl inspect <ASSET> openclaw senpi dsl inspect SOL -r <id> openclaw senpi dsl inspect SOL -a <addr> openclaw senpi dsl inspect BTC --json
openclaw senpi dsl inspect <ASSET> openclaw senpi dsl inspect SOL -r <id> openclaw senpi dsl inspect SOL -a <addr> openclaw senpi dsl inspect BTC --json

Archived (closed) positions — reason, ROE, phase, tier

已归档(已平仓)仓位:平仓原因、ROE、阶段、层级

openclaw senpi dsl closes openclaw senpi dsl closes -r <id> openclaw senpi dsl closes -a <addr> openclaw senpi dsl closes -l <n> openclaw senpi dsl closes --json
undefined
openclaw senpi dsl closes openclaw senpi dsl closes -r <id> openclaw senpi dsl closes -a <addr> openclaw senpi dsl closes -l <n> openclaw senpi dsl closes --json
undefined

Runtime diagnostics

运行时诊断

bash
openclaw senpi status                    # lightweight health summary (all runtimes)
openclaw senpi status -r <id>
openclaw senpi status --json

openclaw senpi state                     # full operational state (all runtimes)
openclaw senpi state -r <id>
openclaw senpi state --json
bash
openclaw senpi status                    # 轻量级健康摘要(所有运行时)
openclaw senpi status -r <id>
openclaw senpi status --json

openclaw senpi state                     # 完整运行状态(所有运行时)
openclaw senpi state -r <id>
openclaw senpi state --json

In-shell reference (
senpi guide
)

内置参考(
senpi guide

bash
openclaw senpi guide                 # overview + quick command list
openclaw senpi guide scanners        # scanner types and config fields
openclaw senpi guide actions         # action types and decision modes
openclaw senpi guide dsl             # DSL exit engine: phases, tiers, time cuts
openclaw senpi guide examples        # print minimal strategy YAML to stdout
openclaw senpi guide schema          # full YAML schema field reference
openclaw senpi guide version         # plugin version and changelog URL
bash
openclaw senpi guide                 # 概览 + 快速命令列表
openclaw senpi guide scanners        # 扫描器类型和配置字段
openclaw senpi guide actions         # 动作类型和决策模式
openclaw senpi guide dsl             # DSL退出引擎:阶段、层级、定时减仓
openclaw senpi guide examples        # 在标准输出打印最简策略YAML示例
openclaw senpi guide schema          # 完整YAML Schema字段参考
openclaw senpi guide version         # 插件版本和更新日志URL

CLI preferences (
senpi config
)

CLI偏好设置(
senpi config

Persists to
~/.openclaw/senpi-cli.json
. Restart gateway to apply.
bash
openclaw senpi config set-chat-id <chatId>
openclaw senpi config set-senpi-jwt-token <token>
openclaw senpi config set-state-dir <dir>
openclaw senpi config get <key>      # telegram-chat-id | senpi-jwt-token | state-dir
openclaw senpi config list           # secrets masked
openclaw senpi config unset <key>
openclaw senpi config reset
配置持久化存储在
~/.openclaw/senpi-cli.json
,重启网关后生效。
bash
openclaw senpi config set-chat-id <chatId>
openclaw senpi config set-senpi-jwt-token <token>
openclaw senpi config set-state-dir <dir>
openclaw senpi config get <key>      # 可查询字段:telegram-chat-id | senpi-jwt-token | state-dir
openclaw senpi config list           # 密钥会被脱敏
openclaw senpi config unset <key>
openclaw senpi config reset

Gateway RPC (advanced)

网关RPC(高级功能)

Common calls:
bash
openclaw gateway call senpi.installRuntime --params '{"runtimeYamlContent":"..."}'
openclaw gateway call senpi.listRuntimes --json --params '{}'
openclaw gateway call senpi.deleteRuntime --params '{"id":"my-runtime"}'
openclaw gateway call senpi.listDslPositions --json --params '{}'
openclaw gateway call senpi.getDslPositionState --json --params '{"asset":"SOL"}'
openclaw gateway call senpi.listDslArchives --json --params '{"limit":20}'
openclaw gateway call senpi.getHealthStatus --json --params '{}'
openclaw gateway call senpi.getSystemState --json --params '{}'
Methods summary
MethodParamsSuccess response
senpi.installRuntime
runtimeYamlContent
or
runtimeYamlPath
Runtime installed
senpi.listRuntimes
List of runtimes
senpi.deleteRuntime
id
or address
Deleted
senpi.listDslPositions
runtimeId?
Active positions
senpi.getDslPositionState
asset
,
runtimeId?
Single position state
senpi.listDslArchives
runtimeId?
,
address?
,
limit?
closes[]
(asset, direction, entryPrice, lastPrice, currentROE, closeReason, closedAt, phase, …)
senpi.getHealthStatus
runtimeId?
(string)
status
or
statuses[]
(health, components.scanners, components.dsl)
senpi.getSystemState
runtimeId?
(string)
state
or
states[]
(health, stateDir, scanner/DSL components)
Close reasons for
listDslArchives
:
dsl_breach
,
hard_timeout
,
weak_peak_cut
,
dead_weight_cut
,
exchange_sl_hit
,
manual
.
常用调用:
bash
openclaw gateway call senpi.installRuntime --params '{"runtimeYamlContent":"..."}'
openclaw gateway call senpi.listRuntimes --json --params '{}'
openclaw gateway call senpi.deleteRuntime --params '{"id":"my-runtime"}'
openclaw gateway call senpi.listDslPositions --json --params '{}'
openclaw gateway call senpi.getDslPositionState --json --params '{"asset":"SOL"}'
openclaw gateway call senpi.listDslArchives --json --params '{"limit":20}'
openclaw gateway call senpi.getHealthStatus --json --params '{}'
openclaw gateway call senpi.getSystemState --json --params '{}'
方法汇总
方法参数成功响应
senpi.installRuntime
runtimeYamlContent
runtimeYamlPath
运行时已安装
senpi.listRuntimes
运行时列表
senpi.deleteRuntime
id
或地址
已删除
senpi.listDslPositions
runtimeId?
活跃仓位列表
senpi.getDslPositionState
asset
,
runtimeId?
单个仓位状态
senpi.listDslArchives
runtimeId?
,
address?
,
limit?
closes[]
(包含资产、方向、入场价、最新价、当前ROE、平仓原因、平仓时间、阶段等字段)
senpi.getHealthStatus
runtimeId?
(字符串)
status
statuses[]
(健康状态、scanners组件状态、dsl组件状态)
senpi.getSystemState
runtimeId?
(字符串)
state
states[]
(健康状态、状态目录、扫描器/DSL组件状态)
listDslArchives
的平仓原因枚举:
dsl_breach
(触发DSL止损)、
hard_timeout
(硬超时)、
weak_peak_cut
(弱峰值减仓)、
dead_weight_cut
(无效仓位减仓)、
exchange_sl_hit
(触发交易所止损)、
manual
(手动平仓)。

Runtime YAML

运行时YAML

The runtime YAML drives all behavior. Top-level keys:
name
,
strategies
,
scanners
,
actions
,
exit
,
notifications
.
yaml
name: my-tracker
version: 1.0.0
description: >
  On-chain position tracker with DSL trailing stop-loss.

strategies:
  main:
    wallet: "${WALLET_ADDRESS}"
    budget: 500
    slots: 2
    margin_per_slot: 200
    trading_risk: conservative    # conservative | moderate | aggressive
    enabled: true

scanners:
  - name: position_tracker
    type: position_tracker
    interval: 10s

actions:
  - name: position_tracker_action
    action_type: POSITION_TRACKER
    decision_mode: rule
    scanners: [position_tracker]

exit:
  engine: dsl
  interval_seconds: 30            # how often the price monitor runs (5-3600)
  dsl_preset:                     # single preset (no named map needed)
    hard_timeout:
      enabled: true
      interval_in_minutes: 360
    weak_peak_cut:
      enabled: true
      interval_in_minutes: 120
      min_value: 5
    dead_weight_cut:
      enabled: true
      interval_in_minutes: 60
    phase1:
      enabled: true
      max_loss_pct: 4.0
      retrace_threshold: 7
      consecutive_breaches_required: 1
    phase2:
      enabled: true
      tiers:
        - { trigger_pct: 7,  lock_hw_pct: 40 }
        - { trigger_pct: 12, lock_hw_pct: 55 }
        - { trigger_pct: 15, lock_hw_pct: 75 }
        - { trigger_pct: 20, lock_hw_pct: 85 }

notifications:
  telegram_chat_id: "${TELEGRAM_CHAT_ID}"
Environment variable substitution:
${VAR}
and
${VAR:-default}
resolved at load time.
For full field details: YAML Schema Reference
运行时YAML定义所有运行逻辑。顶层字段包括:
name
strategies
scanners
actions
exit
notifications
yaml
name: my-tracker
version: 1.0.0
description: >
  On-chain position tracker with DSL trailing stop-loss.

strategies:
  main:
    wallet: "${WALLET_ADDRESS}"
    budget: 500
    slots: 2
    margin_per_slot: 200
    trading_risk: conservative    # conservative | moderate | aggressive
    enabled: true

scanners:
  - name: position_tracker
    type: position_tracker
    interval: 10s

actions:
  - name: position_tracker_action
    action_type: POSITION_TRACKER
    decision_mode: rule
    scanners: [position_tracker]

exit:
  engine: dsl
  interval_seconds: 30            # 价格监控运行频率(单位秒,范围5-3600)
  dsl_preset:                     # 单个预设,无需命名映射
    hard_timeout:
      enabled: true
      interval_in_minutes: 360
    weak_peak_cut:
      enabled: true
      interval_in_minutes: 120
      min_value: 5
    dead_weight_cut:
      enabled: true
      interval_in_minutes: 60
    phase1:
      enabled: true
      max_loss_pct: 4.0
      retrace_threshold: 7
      consecutive_breaches_required: 1
    phase2:
      enabled: true
      tiers:
        - { trigger_pct: 7,  lock_hw_pct: 40 }
        - { trigger_pct: 12, lock_hw_pct: 55 }
        - { trigger_pct: 15, lock_hw_pct: 75 }
        - { trigger_pct: 20, lock_hw_pct: 85 }

notifications:
  telegram_chat_id: "${TELEGRAM_CHAT_ID}"
环境变量替换:加载时会解析
${VAR}
${VAR:-default}
格式的变量。
完整字段说明请参考:YAML Schema Reference

DSL Exit Engine — Key Concepts

DSL退出引擎——核心概念

Two-phase trailing stop-loss protecting open positions:
Phase 1 (from entry until the first tier is reached):
  • Absolute floor from
    max_loss_pct
    (cap on loss from entry, scaled by leverage)
  • Trailing floor from
    retrace_threshold
    (ROE % pullback from high-water mark)
  • Effective floor = stricter of both (LONG: higher price; SHORT: lower)
  • Optional time-based cuts at preset level:
    hard_timeout
    ,
    weak_peak_cut
    ,
    dead_weight_cut
  • Exchange SL stays at the absolute floor only; tighter exits enforced by runtime
Phase 2 (after the first tier is reached — Phase 2 always starts at tier 0):
  • Tier floor =
    lock_hw_pct
    % of current high-water ROE (trails as HW advances, never loosens)
  • Exchange SL tracks the full effective floor and updates as it moves
Tiers are profit milestones (by ROE % from entry). Each tier has two fields:
trigger_pct
(ROE % that activates it) and
lock_hw_pct
(% of high-water ROE to lock as floor). Tiers must have strictly increasing
trigger_pct
.
Consecutive breaches are tick-based (not time-based). Each monitor tick (every
interval_seconds
), if price violates the floor, the breach counter increments. Recovery resets it.
Retrace convention:
retrace_threshold
is ROE %. Engine converts to price:
retrace_ROE% / 100 / leverage
. At 10x leverage, 7% ROE retrace = 0.7% price below high-water.
For full DSL configuration with all fields, time-based cuts, close reasons, and events: DSL Configuration Reference
保护开仓仓位的两阶段移动止损机制:
阶段1(从入场到触发第一个层级前):
  • max_loss_pct
    定义绝对止损底线(入场价的最大亏损比例,按杠杆缩放)
  • retrace_threshold
    定义移动止损底线(从最高水位回撤的ROE百分比)
  • 实际生效底线为两者中更严格的那个(多头取更高价格,空头取更低价格)
  • 可选预设触发的定时减仓规则:
    hard_timeout
    weak_peak_cut
    dead_weight_cut
  • 交易所侧止损仅设置为绝对底线,更严格的退出由运行时强制执行
阶段2(触发第一个层级后,阶段2始终从0级开始):
  • 层级底线 = 当前最高水位ROE的
    lock_hw_pct
    %(随最高水位上升而上移,永远不会放宽)
  • 交易所侧止损会跟踪完整的生效底线,随底线变动同步更新
层级是盈利里程碑(按入场以来的ROE百分比计算)。每个层级包含两个字段:
trigger_pct
(激活该层级的ROE百分比)和
lock_hw_pct
(作为止损底线锁定的最高水位ROE比例)。层级的
trigger_pct
必须严格递增。
连续触发次数按tick计数(而非时间)。每个监控tick(每
interval_seconds
执行一次)如果价格跌破底线,触发计数器就会加1,价格恢复后计数器重置。
回撤计算规则:
retrace_threshold
为ROE百分比。引擎会转换为价格:
回撤ROE% / 100 / 杠杆
。10倍杠杆下,7%的ROE回撤对应价格比最高水位低0.7%。
包含所有字段、定时减仓、平仓原因和事件的完整DSL配置说明请参考:DSL Configuration Reference

Environment Variables

环境变量

VariableRequiredPurpose
WALLET_ADDRESS
YesExisting strategy wallet address from Senpi MCP (used in YAML via
${WALLET_ADDRESS}
).
SENPI_API_KEY
For live MCPSenpi MCP authentication.
TELEGRAM_CHAT_ID
NoTelegram chat ID for notifications.
DSL_STATE_DIR
NoOverride DSL state file directory.
变量名必填用途
WALLET_ADDRESS
从Senpi MCP获取的已有策略钱包地址(在YAML中通过
${WALLET_ADDRESS}
引用)。
SENPI_API_KEY
对接正式MCP时需要Senpi MCP鉴权凭证。
TELEGRAM_CHAT_ID
接收通知的Telegram聊天ID。
DSL_STATE_DIR
覆盖DSL状态文件的存储目录。

References

参考文档

  • Runtime Concepts — Conceptual explanation of scanners, actions, DSL phases, and what every field controls in trading terms
  • YAML Schema Reference — All runtime YAML fields and DSL preset options
  • DSL Configuration Reference — Full DSL exit engine: phases, tiers, time cuts, close reasons, events
  • Strategy Examples — Ready-to-use YAML examples with different DSL tuning profiles
  • Migration from DSL Cron — Upgrade from old
    dsl-v5.py
    cron to plugin runtime
  • Runtime Template — Starter runtime.yaml with field mapping comments
  • Runtime Concepts — 扫描器、动作、DSL阶段的概念说明,以及所有字段在交易层面的控制逻辑
  • YAML Schema Reference — 所有运行时YAML字段和DSL预设选项说明
  • DSL Configuration Reference — 完整DSL退出引擎说明:阶段、层级、定时减仓、平仓原因、事件
  • Strategy Examples — 可直接使用的YAML示例,包含不同的DSL调优配置
  • Migration from DSL Cron — 从旧版
    dsl-v5.py
    定时任务升级到插件运行时的迁移指南
  • Runtime Template — 入门级runtime.yaml模板,附带字段映射注释