
Positions
- 15 installs
- 610 repo stars
- Updated June 26, 2026
- alsk1992/cloddsbot
Positions (in cloddsbot) is a skill that manages open trading positions with automated stop-loss, take-profit, and trailing-stop orders.
About
This skill manages open trading positions with automated stop-loss, take-profit, and trailing-stop orders. A developer uses it to set exits by absolute price, percent from entry or current, or in partial and multi-level tranches, then have the manager monitor prices and execute exits automatically. It emits events when stops trigger or price approaches a level.
- Manages open positions with stop-loss, take-profit, and trailing stops
- Absolute, percent-from-entry, and partial/multi-level exits
- Monitors prices and fires events when stops trigger or price approaches
Positions by the numbers
- 15 all-time installs (skills.sh)
- Ranked #745 of 1,106 Finance & Trading skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
positions capabilities & compatibility
Requires trading credentials for the underlying platform; trades incur platform fees.
- Capabilities
- agent tooling
- Use cases
- trading
- Pricing
- Bring your own API key
What positions says it does
Manage open positions with automated stop-loss, take-profit, and trailing stop orders.
Position management with stop-loss, take-profit, and trailing stops
npx skills add https://github.com/alsk1992/cloddsbot --skill positionsAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 15 |
|---|---|
| repo stars | ★ 610 |
| Last updated | June 26, 2026 |
| Repository | alsk1992/cloddsbot ↗ |
What it does
Protect open positions with automated stop-loss, take-profit, and trailing stops.
When should I use this skill?
You want to protect open positions with automatic stops and profit targets.
What you get
Positions guarded by automated stop-loss, take-profit, and trailing stops.
By the numbers
- 4 stop types (stop-loss, take-profit, trailing, break-even)
- 5s monitor interval default
Files
Positions - Complete API Reference
Manage open positions with automated stop-loss, take-profit, and trailing stop orders.
---
Chat Commands
View Positions
/positions List all positions
/positions poly Polymarket positions only
/positions futures Futures positions only
/position <id> Position detailsStop-Loss
/sl <position-id> at 0.35 Set stop-loss price
/sl <position-id> -10% Stop-loss 10% below entry
/sl poly "Trump" at 0.35 Set by market nameTake-Profit
/tp <position-id> at 0.65 Set take-profit price
/tp <position-id> +20% Take-profit 20% above entry
/tp poly "Trump" at 0.65 Set by market nameTrailing Stop
/trailing <position-id> 5% Trail 5% from high
/trailing <position-id> $0.05 Trail $0.05 from highPartial Exits
/tp <position-id> at 0.55 size 50% Take profit on half
/sl <position-id> at 0.40 size 25% Stop-loss on quarter---
TypeScript API Reference
Create Position Manager
import { createPositionManager } from 'clodds/positions';
const positions = createPositionManager({
// Monitoring
checkIntervalMs: 5000,
// Execution
orderType: 'market', // 'market' | 'limit'
limitBuffer: 0.01, // Buffer for limit orders
// Storage
storage: 'sqlite',
dbPath: './positions.db',
});
// Start monitoring
await positions.start();List Positions
const all = await positions.list();
for (const pos of all) {
console.log(`${pos.id}: ${pos.platform} ${pos.market}`);
console.log(` Side: ${pos.side}`);
console.log(` Size: ${pos.size}`);
console.log(` Entry: ${pos.entryPrice}`);
console.log(` Current: ${pos.currentPrice}`);
console.log(` P&L: ${pos.pnl} (${pos.pnlPercent}%)`);
console.log(` Stop-loss: ${pos.stopLoss || 'none'}`);
console.log(` Take-profit: ${pos.takeProfit || 'none'}`);
}Set Stop-Loss
// Absolute price
await positions.setStopLoss({
positionId: 'pos-123',
price: 0.35,
});
// Percentage from entry
await positions.setStopLoss({
positionId: 'pos-123',
percentFromEntry: 10, // 10% below entry
});
// Percentage from current
await positions.setStopLoss({
positionId: 'pos-123',
percentFromCurrent: 5, // 5% below current
});
// Partial stop-loss
await positions.setStopLoss({
positionId: 'pos-123',
price: 0.35,
sizePercent: 50, // Exit 50% of position
});Set Take-Profit
// Absolute price
await positions.setTakeProfit({
positionId: 'pos-123',
price: 0.65,
});
// Percentage from entry
await positions.setTakeProfit({
positionId: 'pos-123',
percentFromEntry: 20, // 20% above entry
});
// Multiple take-profit levels
await positions.setTakeProfit({
positionId: 'pos-123',
levels: [
{ price: 0.55, sizePercent: 25 }, // 25% at 0.55
{ price: 0.60, sizePercent: 25 }, // 25% at 0.60
{ price: 0.70, sizePercent: 50 }, // 50% at 0.70
],
});Set Trailing Stop
// Percentage trail
await positions.setTrailingStop({
positionId: 'pos-123',
trailPercent: 5, // Trail 5% below high
});
// Absolute trail
await positions.setTrailingStop({
positionId: 'pos-123',
trailAmount: 0.05, // Trail $0.05 below high
});
// Activate after target
await positions.setTrailingStop({
positionId: 'pos-123',
trailPercent: 5,
activateAt: 0.55, // Only start trailing after 0.55
});Remove Stops
// Remove stop-loss
await positions.removeStopLoss('pos-123');
// Remove take-profit
await positions.removeTakeProfit('pos-123');
// Remove trailing stop
await positions.removeTrailingStop('pos-123');
// Remove all
await positions.removeAllStops('pos-123');Event Handlers
// Stop-loss triggered
positions.on('stopLossTriggered', (position, result) => {
console.log(`🛑 Stop-loss hit: ${position.market}`);
console.log(` Entry: ${position.entryPrice}`);
console.log(` Exit: ${result.exitPrice}`);
console.log(` P&L: ${result.pnl}`);
});
// Take-profit triggered
positions.on('takeProfitTriggered', (position, result) => {
console.log(`✅ Take-profit hit: ${position.market}`);
console.log(` P&L: ${result.pnl}`);
});
// Trailing stop triggered
positions.on('trailingStopTriggered', (position, result) => {
console.log(`📉 Trailing stop hit: ${position.market}`);
console.log(` High: ${position.highWaterMark}`);
console.log(` Exit: ${result.exitPrice}`);
});
// Price approaching stop
positions.on('approaching', (position, type, distance) => {
console.log(`⚠️ ${position.market} ${distance}% from ${type}`);
});Position Summary
const summary = await positions.getSummary();
console.log(`Total positions: ${summary.count}`);
console.log(`Total value: $${summary.totalValue}`);
console.log(`Unrealized P&L: $${summary.unrealizedPnl}`);
console.log(`With stop-loss: ${summary.withStopLoss}`);
console.log(`With take-profit: ${summary.withTakeProfit}`);---
Stop Types
| Type | Description |
|---|---|
| Stop-Loss | Exit when price drops to limit losses |
| Take-Profit | Exit when price rises to lock in gains |
| Trailing Stop | Dynamic stop that follows price up |
| Break-Even | Move stop to entry after profit target |
---
Order Execution
| Option | Description |
|---|---|
market | Immediate execution at current price |
limit | Execute at specified price or better |
buffer | Add buffer to limit price for fills |
---
Best Practices
1. Always set stops — Don't leave positions unprotected 2. Use trailing stops — Lock in gains as price moves 3. Partial exits — Scale out at multiple levels 4. Monitor approaching — Get alerts before triggers 5. Review filled stops — Check execution quality
/**
* Positions CLI Skill
*
* Commands:
* /positions - View all open positions
* /positions <id> - View position details
* /positions stop-loss <id> <price> - Set stop-loss
* /positions take-profit <id> <price> - Set take-profit
* /positions close <id> - Close position
*/
async function execute(args: string): Promise<string> {
const parts = args.trim().split(/\s+/);
const cmd = parts[0]?.toLowerCase() || 'list';
try {
const { getGlobalPositionManager } = await import('../../../execution/position-manager');
const manager = getGlobalPositionManager();
switch (cmd) {
case 'list':
case '': {
const positions = manager.getPositions();
if (positions.length === 0) return 'No open positions.';
const stats = manager.getStats();
let output = `**Open Positions** (${stats.openPositions})\n\n`;
for (const p of positions) {
if (p.status !== 'open') continue;
const pnlSign = p.unrealizedPnL >= 0 ? '+' : '';
output += `**${p.id}** ${p.platform} ${p.side} ${p.outcomeName}\n`;
output += ` ${p.size} shares @ $${p.entryPrice.toFixed(2)} → $${p.currentPrice.toFixed(2)}`;
output += ` (${pnlSign}${p.unrealizedPnLPct.toFixed(1)}%)`;
if (p.stopLoss) output += ` SL:$${p.stopLoss.toFixed(2)}`;
if (p.takeProfit) output += ` TP:$${p.takeProfit.toFixed(2)}`;
output += '\n';
}
output += `\nTotal unrealized PnL: $${stats.totalUnrealizedPnL.toFixed(2)}`;
return output;
}
case 'stop-loss':
case 'sl': {
if (!parts[1] || !parts[2]) return 'Usage: /positions stop-loss <position-id> <price>';
const price = parseFloat(parts[2]);
if (isNaN(price)) return 'Invalid price.';
manager.setStopLoss(parts[1], { price });
return `Stop-loss set for position ${parts[1]} at $${price.toFixed(2)}.`;
}
case 'take-profit':
case 'tp': {
if (!parts[1] || !parts[2]) return 'Usage: /positions take-profit <position-id> <price>';
const price = parseFloat(parts[2]);
if (isNaN(price)) return 'Invalid price.';
manager.setTakeProfit(parts[1], { price });
return `Take-profit set for position ${parts[1]} at $${price.toFixed(2)}.`;
}
case 'trailing':
case 'trail': {
if (!parts[1] || !parts[2]) return 'Usage: /positions trailing <position-id> <distance%>';
const pct = parseFloat(parts[2]);
if (isNaN(pct)) return 'Invalid percentage.';
manager.setStopLoss(parts[1], { trailingPercent: pct });
return `Trailing stop set for position ${parts[1]} at ${pct}% distance.`;
}
case 'close': {
if (!parts[1]) return 'Usage: /positions close <position-id>';
const pos = manager.getPosition(parts[1]);
if (!pos) return `Position ${parts[1]} not found.`;
manager.closePosition(parts[1], pos.currentPrice, 'manual');
return `Closed position ${parts[1]} at $${pos.currentPrice.toFixed(2)}.`;
}
case 'close-all': {
const positions = manager.getPositions().filter(p => p.status === 'open');
if (positions.length === 0) return 'No open positions to close.';
for (const p of positions) {
manager.closePosition(p.id, p.currentPrice, 'manual');
}
return `Closed ${positions.length} positions.`;
}
default: {
// Treat as position ID lookup
const pos = manager.getPosition(cmd);
if (!pos) return `Position "${cmd}" not found. Use \`/positions list\` to see all.`;
const pnlSign = pos.unrealizedPnL >= 0 ? '+' : '';
let output = `**Position ${pos.id}**\n\n`;
output += `Platform: ${pos.platform}\n`;
output += `Market: ${pos.marketId}\n`;
output += `Outcome: ${pos.outcomeName}\n`;
output += `Side: ${pos.side}\n`;
output += `Size: ${pos.size} shares\n`;
output += `Entry: $${pos.entryPrice.toFixed(2)}\n`;
output += `Current: $${pos.currentPrice.toFixed(2)}\n`;
output += `PnL: ${pnlSign}$${pos.unrealizedPnL.toFixed(2)} (${pnlSign}${pos.unrealizedPnLPct.toFixed(1)}%)\n`;
output += `Opened: ${pos.openedAt.toLocaleString()}\n`;
if (pos.stopLoss) output += `Stop-loss: $${pos.stopLoss.toFixed(2)}\n`;
if (pos.takeProfit) output += `Take-profit: $${pos.takeProfit.toFixed(2)}\n`;
if (pos.trailingStop) output += `Trailing stop: ${pos.trailingStop}%\n`;
output += `Status: ${pos.status}`;
return output;
}
}
} catch (error) {
return `Position manager error: ${error instanceof Error ? error.message : String(error)}`;
}
}
export default {
name: 'positions',
description: 'Position management with stop-loss, take-profit, and trailing stops',
commands: ['/positions', '/pos'],
handle: execute,
};
Related skills
FAQ
What stop types are supported?
Stop-loss, take-profit, trailing stop, and break-even.
Can it exit part of a position?
Yes, it supports partial exits and multi-level take-profit tranches.