About dsl-tight
dsl-tight is an opinionated stop-loss preset for the dsl-dynamic-stop-loss skill, aimed at strategies that need tighter profit protection. It uses ROE-based tiers, per-tier breach counts, automatically calculated floors, and stagnation exits with the DSL v5 script.
Key features
- 01ROE-based stop and profit thresholds
- 02Four tiered profit-lock levels
- 03Breach counts tighten at higher tiers
- 04Entry- and leverage-based floor calculation
- 05Stagnation-based take-profit exit
Use cases
- 01Applying tighter stop-loss rules to a strategy
- 02Locking increasing shares of high-water gains
- 03Closing positions when profitable movement stalls
MCP support
The skill uses MCP clearinghouse to discover positions. The DSL v5 script reconciles position state with the clearinghouse.
Install
Copy the command and run it in a terminal.
npx skills add https:/ / github.com/ senpi-ai/ senpi-skills --skill dsl-tightAfter installing, type/dsl-tightin Claude Code to confirm it loaded.
Bundled filesdsl-profile.json
Details
From the project READMEDSL-Tight — Opinionated Stop-Loss Preset (v5)
A tighter, more opinionated variant of DSL for aggressive profit protection. Uses the same script and architecture as DSL v5 (dsl-v5.py) — strategy-scoped cron, MCP clearinghouse, state under {DSL_STATE_DIR}/{strategyId}/{asset}.json. All tier triggers are ROE-based (PnL / margin × 100); leverage is accounted for automatically.
Key difference from default DSL v5: DSL v5 is the configurable engine with maximum flexibility. DSL-Tight is the "just works" preset — fewer knobs, tighter defaults, per-tier breach counts, stagnation exits, and auto-calculated floors.
Core Concept
All thresholds defined in ROE. The script auto-converts to price levels:
price_floor = entry × (1 ± lockPct / 100 / leverage)
How It Works
Phase 1 — Absolute Floor (Stop-Loss)
- 5% ROE trailing floor
- 3 consecutive breaches required
- Auto-calculated absolute floor from entry/leverage/retrace
Phase 2 — Tiered Profit Lock
4 tiers that lock an increasing percentage of the high-water move:
| Tier | Trigger ROE | Lock % of HW Move | Breaches to Close |
|---|---|---|---|
| 1 | 10% | 50% | 3 |
| 2 | 20% | 65% | 2 |
| 3 | 40% | 75% | 2 |
| 4 | 75% | 85% | 1 |
Per-tier breach counts tighten as profit grows — at Tier 4 (75% ROE), a single breach closes immediately.
Stagnation Take-Profit
Auto-closes if:
- ROE ≥ 8% AND
- High-water mark hasn't improved for 1 hour
Catches winners that stall — takes the profit rather than waiting for a reversal.
Breach Mechanics
- Hard decay only (breach count resets to 0 on recovery)
- Per-tier breach requirements (3→2→2→1) replace the global Phase 1/Phase 2 split
- Floor is always:
max(tier_floor, trailing_floor)for LONG,min()for SHORT
State File Schema
State files live in the DSL v5 strategy directory: {DSL_STATE_DIR}/{strategyId}/{asset}.json (main dex) or {DSL_STATE_DIR}/{strategyId}/xyz--SYMBOL.json (xyz dex). See dsl-dynamic-stop-loss references/state-schema.md for path conventions.
{
"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.05,
"consecutiveBreachesRequired": 3
},
"phase2TriggerTier": 0,
"phase2": {
"retraceThreshold": 0.015,
"consecutiveBreachesRequired": 2
},
"tiers": [
{"triggerPct": 10, "lockPct": 50, "retrace": 0.015},
{"triggerPct": 20, "lockPct": 65, "retrace": 0.012},
{"triggerPct": 40, "lockPct": 75, "retrace": 0.010},
{"triggerPct": 75, "lockPct": 85, "retrace": 0.006}
],
"breachDecay": "hard",
"currentTierIndex": -1,
"tierFloorPrice": null,
"highWaterPrice": 28.87,
"floorPrice": 28.78,
"currentBreachCount": 0,
"createdAt": "2026-02-23T10:00:00.000Z"
}
Omit phase1.absoluteFloor — dsl-v5 fills it from entry and leverage. Set highWaterPrice to entry price, floorPrice to entry (or the computed absolute floor) for Phase 1 start.
Field Reference
| Field | Purpose |
|---|---|
phase1.absoluteFloor | Not needed — auto-calculated from entry, leverage, retrace |
tiers[].breachesRequired | Per-tier breach count (replaces global phase2 setting) |
tiers[].retrace | Per-tier trailing stop tightness |
stagnation.enabled | Enable stagnation take-profit |
stagnation.minRoePct | Minimum ROE to trigger stagnation check |
stagnation.maxStaleSec | Max seconds HW can be stale before auto-close |
Cron Setup
Same as DSL v5: one cron per strategy (not per position), every 3–5 minutes. The agent creates it when setting up DSL for a strategy.
Resolving the script path: When setting up the cron, locate the dsl-dynamic-stop-loss skill on disk (e.g. search the workspace, skills directory, or ClawHub install path for a folder named dsl-dynamic-stop-loss containing scripts/dsl-v5.py). Use that resolved path in the cron command — do not assume a fixed relative path. Example once resolved:
DSL_STATE_DIR=/data/workspace/dsl DSL_STRATEGY_ID=strategy-uuid python3 /path/to/dsl-dynamic-stop-loss/scripts/dsl-v5.py
No DSL_ASSET — the script discovers positions from MCP clearinghouse and state files in the strategy dir.
Clock-aligned schedule (OpenClaw): For runs at fixed 3-minute boundaries (e.g. :00, :03, :06…), create the job with a cron expression: "schedule": { "kind": "cron", "expr": "*/3 * * * *", "tz": "UTC" }. See dsl-dynamic-stop-loss SKILL.md Cron Setup and references/explained.md §0.
Agent responsibilities (same as DSL v5): on strategy_inactive remove cron and run strategy cleanup; on closed=true alert user; on pending_close=true alert and retry next tick.
Key Safety Features
- Same as DSL v5: strategy active check, reconcile state vs clearinghouse, delete state on close
- Auto-calculated floors eliminate manual math errors
- Per-tier breach tightening means large profits get maximum protection
- Stagnation TP prevents stalled winners from reversing
Example Walkthrough
10x LONG entry at $28.87:
- Phase 1: Floor auto-calculated ~$28.73. Price rises, HW tracks.
- Tier 1 at 10% ROE ($29.16): Floor locks at ~$29.01, 3 breaches to close.
- Tier 2 at 20% ROE ($29.45): Floor locks at ~$29.24, now only 2 breaches.
- Stagnation: Price stalls at 12% ROE for 65 min → auto-closed with profit.
- Tier 4 at 75% ROE ($31.04): Floor at ~$30.71. Single breach = instant close.
Script and Dependencies
Uses dsl-v5.py and dsl-cli.py from the dsl-dynamic-stop-loss skill. Install that skill first. Preferred setup: call dsl-cli.py add-dsl with --configuration @dsl-tight/dsl-profile.json (see "Setup via DSL CLI" above). When setting up cron or running the script, locate the dsl-dynamic-stop-loss skill on disk (search workspace/skills/install path for the folder containing scripts/dsl-v5.py and scripts/dsl-cli.py) and use that path. State files go in {DSL_STATE_DIR}/{strategyId}/{asset}.json (main) or xyz--SYMBOL.json (xyz). For cron setup, path conventions, cleanup on strategy inactive, and output schema, follow the dsl-dynamic-stop-loss skill.