dsl-dynamic-stop-loss

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Dynamic Stop Loss (DSL) v4

动态止损(DSL)v4

Automated trailing stop loss for leveraged perp positions on Hyperliquid. Monitors price via cron, ratchets profit floors upward through configurable tiers, and auto-closes positions on breach — no agent intervention required for the critical path.
面向Hyperliquid上杠杆永续合约仓位的自动追踪止损工具。通过cron监控价格,通过可配置的层级逐步上调利润下限,触发止损线时自动平仓——核心路径无需Agent介入。

Self-Contained Design

独立设计

Script handles:              Agent handles:
✅ Price monitoring           📢 Telegram alerts
✅ High water tracking        🧹 Cron cleanup (disable after close)
✅ Tier upgrades              📊 Portfolio reporting
✅ Breach detection           🔄 Retry awareness (pendingClose alerts)
✅ Position closing (via mcporter, with retry)
✅ State deactivation
✅ Error handling (fetch failures)
The script closes positions directly via
mcporter
. If the agent is slow, busy, or restarting, the position still gets closed on the next cron tick.
Script handles:              Agent handles:
✅ Price monitoring           📢 Telegram alerts
✅ High water tracking        🧹 Cron cleanup (disable after close)
✅ Tier upgrades              📊 Portfolio reporting
✅ Breach detection           🔄 Retry awareness (pendingClose alerts)
✅ Position closing (via mcporter, with retry)
✅ State deactivation
✅ Error handling (fetch failures)
脚本直接通过
mcporter
平仓。如果Agent响应慢、繁忙或重启,仓位仍会在下一个cron执行周期完成平仓。

How It Works

工作原理

Phase 1: "Let It Breathe" (uPnL < first tier)

阶段1:“预留波动空间”(uPnL < 第一层级阈值)

  • Wide retrace: 3% from high water mark
  • Patient: requires 3 consecutive breach checks below floor
  • Absolute floor: hard price floor to cap max loss
  • Goal: Don't get shaken out before the trade develops
  • 宽幅回撤容忍: 距离最高水位价3%
  • 延迟判定: 需要连续3次检测到价格低于止损线才会触发平仓
  • 绝对止损线: 硬价格下限,限制最大亏损
  • 目标: 交易走势成型前避免被小幅震荡洗出

Phase 2: "Lock the Bag" (uPnL ≥ first tier)

阶段2:“锁定收益”(uPnL ≥ 第一层级阈值)

  • Tight retrace: 1.5% from high water mark (or per-tier retrace)
  • Quick exit: 1–2 consecutive breaches to close
  • Tier floors: ratchet up as profit grows — never go back down
  • Effective floor: best of tier floor and trailing floor
  • 窄幅回撤容忍: 距离最高水位价1.5%(或各层级自定义回撤阈值)
  • 快速平仓: 连续1-2次触发止损即平仓
  • 层级止损线: 随利润增长逐步上调——永不下调
  • 有效止损线: 取层级止损线和追踪止损线的最优值

ROE-Based Tier Ratcheting

基于ROE的层级递进机制

All tier triggers use ROE (Return on Equity):
PnL / margin × 100
. This means a
triggerPct: 10
fires at 10% return on margin, not 10% price move. Leverage is accounted for automatically.
Tiers are defined as
{triggerPct, lockPct}
pairs. Each tier can optionally specify its own
retrace
value to tighten stops as profit grows:
json
"tiers": [
  {"triggerPct": 10, "lockPct": 5},
  {"triggerPct": 20, "lockPct": 14},
  {"triggerPct": 30, "lockPct": 22, "retrace": 0.012},
  {"triggerPct": 50, "lockPct": 40, "retrace": 0.010},
  {"triggerPct": 75, "lockPct": 60, "retrace": 0.008},
  {"triggerPct": 100, "lockPct": 80, "retrace": 0.006}
]
The gap between trigger and lock (e.g., 10% trigger → 5% lock) gives breathing room so a minor pullback after hitting a tier doesn't immediately close. Ratchets never go down — once you hit Tier 2, Tier 1's floor is permanently superseded.
See references/tier-examples.md for LONG and SHORT worked examples with exact price calculations.
所有层级触发条件都使用ROE(净资产收益率)计算:
PnL / margin × 100
。这意味着
triggerPct: 10
会在保证金回报率达到10%时触发,而非价格波动10%,杠杆倍数会被自动纳入计算。
层级通过
{triggerPct, lockPct}
键值对定义。每个层级可选择性指定专属的
retrace
值,随利润增长收紧止损阈值:
json
"tiers": [
  {"triggerPct": 10, "lockPct": 5},
  {"triggerPct": 20, "lockPct": 14},
  {"triggerPct": 30, "lockPct": 22, "retrace": 0.012},
  {"triggerPct": 50, "lockPct": 40, "retrace": 0.010},
  {"triggerPct": 75, "lockPct": 60, "retrace": 0.008},
  {"triggerPct": 100, "lockPct": 80, "retrace": 0.006}
]
触发阈值和锁定阈值的差值(例如10%触发→5%锁定)预留了波动空间,避免触达层级后的小幅回调立即触发平仓。层级永不回退——一旦达到第2层级,第1层级的止损线将永久失效。
查看 references/tier-examples.md 可获取LONG和SHORT仓位的完整示例,包含精确的价格计算逻辑。

Direction Matters

方向敏感逻辑

⚠️ CRITICAL — Getting direction backwards causes immediate false breaches or no protection at all. The script handles this automatically via the
direction
field, but double-check when initializing state files manually.
LONGSHORT
Tier floor
entry × (1 + lockPct / 100 / leverage)
entry × (1 - lockPct / 100 / leverage)
Absolute floorBelow entry (e.g., entry × 0.97)Above entry (e.g., entry × 1.03)
High waterHighest price seenLowest price seen
Trailing floor
hw × (1 - retrace)
hw × (1 + retrace)
Breach
price ≤ floor
price ≥ floor
uPnL
(price - entry) × size
(entry - price) × size
⚠️ 重要提示——方向设置错误会导致立即误触发平仓或完全失去保护。脚本会通过
direction
字段自动处理方向逻辑,但手动初始化状态文件时请务必双重校验。
LONGSHORT
层级止损线
entry × (1 + lockPct / 100 / leverage)
entry × (1 - lockPct / 100 / leverage)
绝对止损线低于入场价(例如入场价 × 0.97)高于入场价(例如入场价 × 1.03)
最高水位价观测到的最高价格观测到的最低价格
追踪止损线
hw × (1 - retrace)
hw × (1 + retrace)
触发止损
price ≤ floor
price ≥ floor
未实现盈利
(price - entry) × size
(entry - price) × size

Breach Decay

止损触发计数衰减机制

When price recovers above the floor:
  • "hard"
    (default): breach count resets to 0
  • "soft"
    : breach count decays by 1 per check
Soft mode is useful for volatile assets where price rapidly oscillates around the floor.
当价格回升到止损线以上时:
  • "hard"
    (默认模式): 触发计数重置为0
  • "soft"
    : 每次检测触发计数减1
软模式适合价格在止损线附近快速震荡的高波动资产。

Floor Resolution

止损线判定逻辑

At each check, the effective floor is the best of:
  1. Tier floor — locked profit level (Phase 2 only)
  2. Trailing floor — from high water mark and retrace %
  3. Absolute floor — hard minimum (Phase 1 only)
For LONGs, "best" = maximum. For SHORTs, "best" = minimum.
每次检测时,有效止损线取以下三者的最优值
  1. 层级止损线 —— 锁定的利润水平(仅阶段2生效)
  2. 追踪止损线 —— 基于最高水位价和回撤比例计算
  3. 绝对止损线 —— 硬下限(仅阶段1生效)
对于LONG仓位,“最优值”=最大值。对于SHORT仓位,“最优值”=最小值。

Architecture

架构

┌──────────────────────────────────────────┐
│ Cron: every 3-5 min (per position)       │
├──────────────────────────────────────────┤
│ scripts/dsl-v4.py                        │
│ • Reads state from JSON file             │
│ • Fetches price from allMids API         │
│ • Direction-aware (LONG + SHORT)         │
│ • Updates high water mark                │
│ • Checks tier upgrades (ROE-based)       │
│ • Per-tier retrace override              │
│ • Calculates effective floor             │
│ • Detects breaches (with decay modes)    │
│ • ON BREACH: closes via mcporter w/retry │
│ • pendingClose if close fails            │
│ • Outputs enriched JSON status           │
├──────────────────────────────────────────┤
│ Agent reads JSON output:                 │
│ • closed=true → alert user, disable cron │
│ • pending_close=true → alert, will retry │
│ • tier_changed=true → notify user        │
│ • status=error → log, check failures     │
│ • Otherwise → silent                     │
└──────────────────────────────────────────┘
┌──────────────────────────────────────────┐
│ Cron: every 3-5 min (per position)       │
├──────────────────────────────────────────┤
│ scripts/dsl-v4.py                        │
│ • Reads state from JSON file             │
│ • Fetches price from allMids API         │
│ • Direction-aware (LONG + SHORT)         │
│ • Updates high water mark                │
│ • Checks tier upgrades (ROE-based)       │
│ • Per-tier retrace override              │
│ • Calculates effective floor             │
│ • Detects breaches (with decay modes)    │
│ • ON BREACH: closes via mcporter w/retry │
│ • pendingClose if close fails            │
│ • Outputs enriched JSON status           │
├──────────────────────────────────────────┤
│ Agent reads JSON output:                 │
│ • closed=true → alert user, disable cron │
│ • pending_close=true → alert, will retry │
│ • tier_changed=true → notify user        │
│ • status=error → log, check failures     │
│ • Otherwise → silent                     │
└──────────────────────────────────────────┘

Files

文件说明

FilePurpose
scripts/dsl-v4.py
Core DSL engine — monitors, closes, outputs JSON
State file (JSON)Per-position config + runtime state
Multiple positions: Set
DSL_STATE_FILE=/path/to/state.json
to run separate instances per position. Each gets its own state file and cron job.
文件用途
scripts/dsl-v4.py
DSL核心引擎——监控、平仓、输出JSON
状态文件(JSON)每个仓位独立的配置+运行时状态
多仓位支持:设置
DSL_STATE_FILE=/path/to/state.json
即可为每个仓位运行独立实例,每个实例对应独立的状态文件和cron任务。

State File Schema

状态文件 Schema

See references/state-schema.md for the complete schema with all fields documented.
Minimal required fields to create a new state file:
json
{
  "active": true,
  "asset": "HYPE",
  "direction": "LONG",
  "leverage": 10,
  "entryPrice": 28.87,
  "size": 1890.28,
  "wallet": "0xYourStrategyWalletAddress",
  "strategyId": "uuid-of-strategy",
  "phase": 1,
  "phase1": {
    "retraceThreshold": 0.03,
    "consecutiveBreachesRequired": 3,
    "absoluteFloor": 28.00
  },
  "phase2TriggerTier": 1,
  "phase2": {
    "retraceThreshold": 0.015,
    "consecutiveBreachesRequired": 2
  },
  "tiers": [
    {"triggerPct": 10, "lockPct": 5},
    {"triggerPct": 20, "lockPct": 14},
    {"triggerPct": 30, "lockPct": 22, "retrace": 0.012},
    {"triggerPct": 50, "lockPct": 40, "retrace": 0.010},
    {"triggerPct": 75, "lockPct": 60, "retrace": 0.008},
    {"triggerPct": 100, "lockPct": 80, "retrace": 0.006}
  ],
  "currentTierIndex": -1,
  "tierFloorPrice": null,
  "highWaterPrice": 28.87,
  "floorPrice": 28.00,
  "currentBreachCount": 0,
  "createdAt": "2026-02-20T15:22:00.000Z"
}
wallet
is required
— the script uses it to call
close_position
on breach.
查看 references/state-schema.md 获取完整的字段说明Schema。
创建新状态文件所需的最少必填字段:
json
{
  "active": true,
  "asset": "HYPE",
  "direction": "LONG",
  "leverage": 10,
  "entryPrice": 28.87,
  "size": 1890.28,
  "wallet": "0xYourStrategyWalletAddress",
  "strategyId": "uuid-of-strategy",
  "phase": 1,
  "phase1": {
    "retraceThreshold": 0.03,
    "consecutiveBreachesRequired": 3,
    "absoluteFloor": 28.00
  },
  "phase2TriggerTier": 1,
  "phase2": {
    "retraceThreshold": 0.015,
    "consecutiveBreachesRequired": 2
  },
  "tiers": [
    {"triggerPct": 10, "lockPct": 5},
    {"triggerPct": 20, "lockPct": 14},
    {"triggerPct": 30, "lockPct": 22, "retrace": 0.012},
    {"triggerPct": 50, "lockPct": 40, "retrace": 0.010},
    {"triggerPct": 75, "lockPct": 60, "retrace": 0.008},
    {"triggerPct": 100, "lockPct": 80, "retrace": 0.006}
  ],
  "currentTierIndex": -1,
  "tierFloorPrice": null,
  "highWaterPrice": 28.87,
  "floorPrice": 28.00,
  "currentBreachCount": 0,
  "createdAt": "2026-02-20T15:22:00.000Z"
}
wallet
为必填字段
——脚本触发止损时会使用该字段调用
close_position
接口。

Absolute Floor Calculation

绝对止损线计算

  • LONG:
    entry × (1 - maxLoss% / leverage)
    — e.g., 10x with 3% →
    28.87 × (1 - 0.03/10)
    = $28.78
  • SHORT:
    entry × (1 + maxLoss% / leverage)
    — e.g., 7x with 3% →
    1955 × (1 + 0.03/7)
    = $1,963.38
  • LONG仓位
    入场价 × (1 - 最大亏损% / 杠杆倍数)
    —— 例如10倍杠杆、3%最大亏损 →
    28.87 × (1 - 0.03/10)
    = $28.78
  • SHORT仓位
    入场价 × (1 + 最大亏损% / 杠杆倍数)
    —— 例如7倍杠杆、3%最大亏损 →
    1955 × (1 + 0.03/7)
    = $1,963.38

Output JSON

输出JSON

The script prints a single JSON line per run. See references/output-schema.md for the complete schema.
Key fields for agent decision-making:
FieldAgent action
closed: true
Alert user, disable cron
pending_close: true
Alert — close failed, retrying next tick
tier_changed: true
Notify user with tier details
status: "error"
Log; alert if
consecutive_failures >= 3
breached: true
Alert "⚠️ BREACH X/X"
distance_to_next_tier_pct < 2
Optionally notify approaching next tier
脚本每次运行会打印一行JSON。查看 references/output-schema.md 获取完整Schema。
Agent决策所需的关键字段:
字段Agent执行动作
closed: true
通知用户,禁用cron
pending_close: true
告警——平仓失败,下一个执行周期重试
tier_changed: true
告知用户层级升级详情
status: "error"
日志记录;如果
consecutive_failures >= 3
则告警
breached: true
告警 "⚠️ 已触发X/X次止损校验"
distance_to_next_tier_pct < 2
可选通知用户即将触达下一层级

Cron Setup

Cron 配置

Per-position cron (every 3-5 min):
DSL_STATE_FILE=/data/workspace/dsl-state-BTC.json python3 scripts/dsl-v4.py
Stagger multiple positions by offsetting start times (:00, :01, :02).
每个仓位独立配置cron(每3-5分钟执行一次):
DSL_STATE_FILE=/data/workspace/dsl-state-BTC.json python3 scripts/dsl-v4.py
多个仓位可错开启动时间(:00, :01, :02)避免并发压力。

How to Set Up a New Position

新仓位设置流程

  1. Open position via Senpi API (
    create_position
    )
  2. Create a state file with position details (see schema above)
    • Double-check
      direction
      — controls all LONG/SHORT math
    • Calculate
      absoluteFloor
      correctly
      for the direction
  3. Create a cron job (every 3-5 min)
  4. DSL handles everything from there
  1. 通过Senpi API开仓(
    create_position
  2. 创建包含仓位详情的状态文件(参考上述Schema)
    • 双重校验
      direction
      字段
      ——控制所有LONG/SHORT计算逻辑
    • 根据持仓方向正确计算
      absoluteFloor
  3. 创建cron任务(每3-5分钟执行一次)
  4. 后续流程全部由DSL自动处理

When a Position Closes

仓位平仓流程

  1. ✅ Script closes position via
    mcporter call senpi close_position
    (with retry)
  2. ✅ Script sets
    active: false
    (or
    pendingClose: true
    if close fails)
  3. 🤖 Agent disables the cron (reads
    closed=true
    )
  4. 🤖 Agent sends alert to user
If close fails, script sets
pendingClose: true
and retries next cron tick.
  1. ✅ 脚本通过
    mcporter call senpi close_position
    平仓(支持重试)
  2. ✅ 脚本设置
    active: false
    (如果平仓失败则设置
    pendingClose: true
  3. 🤖 Agent禁用cron(读取到
    closed=true
  4. 🤖 Agent向用户发送告警
如果平仓失败,脚本会设置
pendingClose: true
,并在下一个cron周期重试。

Customization

自定义配置

See references/customization.md for conservative/moderate/aggressive presets and per-tier retrace tuning guidelines.
查看 references/customization.md 获取保守/适中/激进配置预设,以及各层级回撤阈值调优指南。

API Dependencies

API 依赖

  • Price: Hyperliquid
    allMids
    API (direct HTTP, no auth)
  • Close position: Senpi
    close_position
    via mcporter
⚠️ Do NOT use
strategy_close_strategy
to close individual positions. That closes the entire strategy (irreversible). Use
close_position
.
  • 价格数据: Hyperliquid
    allMids
    API(直接HTTP请求,无需鉴权)
  • 平仓接口: 通过mcporter调用Senpi
    close_position
    接口
⚠️ 不要使用
strategy_close_strategy
关闭单个仓位
。该接口会关闭整个策略(不可逆)。请使用
close_position

Setup Checklist

配置检查清单

  1. Extract
    scripts/dsl-v4.py
    and
    chmod +x
  2. Ensure
    mcporter
    is configured with Senpi auth
  3. Create state file(s) per position
  4. Set up cron:
    DSL_STATE_FILE=/path/to/state.json python3 scripts/dsl-v4.py
  5. Agent reads output for alerts and cron cleanup
  6. If
    pending_close=true
    , script auto-retries on next tick
  1. 提取
    scripts/dsl-v4.py
    并执行
    chmod +x
    赋予执行权限
  2. 确保
    mcporter
    已配置Senpi鉴权信息
  3. 为每个仓位创建独立的状态文件
  4. 配置cron:
    DSL_STATE_FILE=/path/to/state.json python3 scripts/dsl-v4.py
  5. Agent读取输出用于告警和cron清理
  6. 如果
    pending_close=true
    ,脚本会在下一个执行周期自动重试