Skip to main content
Glama

calculate_trailing_stop

Calculate trailing stop loss levels with breakeven and profit protection for Bybit cryptocurrency positions to manage risk and lock in gains.

Instructions

Calculate trailing stop loss with breakeven and profit protection

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
categoryYesCategory (linear, inverse)
symbolYesSymbol (e.g., ETHUSDT)
entryPriceYesEntry price of the position
currentPriceYesCurrent market price
sideYesPosition side (Buy for long, Sell for short)
initialStopLossYesInitial stop loss price
trailingDistanceYesTrailing distance in price units
breakevenTriggerNoPrice distance from entry to activate breakeven protection (optional)
profitProtectionTriggerNoPrice distance from entry to activate profit protection (optional)

Implementation Reference

  • The core handler function that executes the calculate_trailing_stop tool logic, computing new stop loss levels with trailing, breakeven, and profit protection features.
    async calculateTrailingStop( category: string, symbol: string, entryPrice: number, currentPrice: number, side: 'Buy' | 'Sell', initialStopLoss: number, trailingDistance: number, breakevenTrigger?: number, profitProtectionTrigger?: number ): Promise<{ newStopLoss: number; trailingActivated: boolean; breakevenProtection: boolean; profitProtected: number; unrealizedPnL: number; unrealizedPnLPercentage: number; recommendations: { shouldUpdateStop: boolean; newStopPrice: number; protectionLevel: 'none' | 'breakeven' | 'profit'; reasoning: string; }; calculations: { priceMovement: number; priceMovementPercentage: number; stopLossMovement: number; maxDrawdownProtection: number; profitLocked: number; }; warnings: string[]; error?: string; }> { try { const warnings: string[] = []; const isLong = side === 'Buy'; // Validate inputs if (trailingDistance <= 0) { return { newStopLoss: initialStopLoss, trailingActivated: false, breakevenProtection: false, profitProtected: 0, unrealizedPnL: 0, unrealizedPnLPercentage: 0, recommendations: { shouldUpdateStop: false, newStopPrice: initialStopLoss, protectionLevel: 'none', reasoning: 'Invalid trailing distance' }, calculations: { priceMovement: 0, priceMovementPercentage: 0, stopLossMovement: 0, maxDrawdownProtection: 0, profitLocked: 0 }, warnings: ['Trailing distance must be greater than 0'], error: 'Invalid trailing distance' }; } // Calculate price movements const priceMovement = isLong ? currentPrice - entryPrice : entryPrice - currentPrice; const priceMovementPercentage = (priceMovement / entryPrice) * 100; // Calculate unrealized PnL const unrealizedPnL = priceMovement; const unrealizedPnLPercentage = priceMovementPercentage; // Set default triggers if not provided const breakevenTriggerDistance = breakevenTrigger || (Math.abs(entryPrice - initialStopLoss) * 1.5); const profitProtectionTriggerDistance = profitProtectionTrigger || (Math.abs(entryPrice - initialStopLoss) * 2.0); let newStopLoss = initialStopLoss; let trailingActivated = false; let breakevenProtection = false; let profitProtected = 0; let protectionLevel: 'none' | 'breakeven' | 'profit' = 'none'; let reasoning = 'No trailing conditions met'; // Check if price has moved favorably enough to activate trailing const favorableMovement = isLong ? currentPrice > entryPrice : currentPrice < entryPrice; if (favorableMovement) { // Calculate potential new stop loss based on trailing distance const potentialNewStop = isLong ? currentPrice - trailingDistance : currentPrice + trailingDistance; // Only move stop loss if it's better than current stop const shouldMoveStop = isLong ? potentialNewStop > initialStopLoss : potentialNewStop < initialStopLoss; if (shouldMoveStop) { newStopLoss = potentialNewStop; trailingActivated = true; // Check for breakeven protection const breakevenReached = isLong ? currentPrice >= entryPrice + breakevenTriggerDistance : currentPrice <= entryPrice - breakevenTriggerDistance; if (breakevenReached) { const breakevenStop = entryPrice; // Move stop to breakeven if (isLong ? breakevenStop > newStopLoss : breakevenStop < newStopLoss) { newStopLoss = breakevenStop; breakevenProtection = true; protectionLevel = 'breakeven'; reasoning = 'Breakeven protection activated - stop moved to entry price'; } } // Check for profit protection const profitProtectionReached = isLong ? currentPrice >= entryPrice + profitProtectionTriggerDistance : currentPrice <= entryPrice - profitProtectionTriggerDistance; if (profitProtectionReached) { const profitProtectionStop = isLong ? entryPrice + (profitProtectionTriggerDistance * 0.5) // Lock in 50% of the trigger distance as profit : entryPrice - (profitProtectionTriggerDistance * 0.5); if (isLong ? profitProtectionStop > newStopLoss : profitProtectionStop < newStopLoss) { newStopLoss = profitProtectionStop; profitProtected = Math.abs(profitProtectionStop - entryPrice); protectionLevel = 'profit'; reasoning = `Profit protection activated - locking in ${profitProtected.toFixed(2)} profit`; } } if (protectionLevel === 'none') { reasoning = `Trailing stop activated - following price with ${trailingDistance} distance`; } } else { reasoning = 'Price moved favorably but not enough to improve stop loss'; } } else { reasoning = 'Price has not moved favorably - maintaining original stop loss'; } // Calculate additional metrics const stopLossMovement = Math.abs(newStopLoss - initialStopLoss); const maxDrawdownProtection = Math.abs(currentPrice - newStopLoss); const profitLocked = Math.max(0, isLong ? newStopLoss - entryPrice : entryPrice - newStopLoss); // Add warnings for risk management if (unrealizedPnLPercentage < -5) { warnings.push('Position is down more than 5% - consider reviewing strategy'); } if (trailingDistance > Math.abs(entryPrice - initialStopLoss) * 2) { warnings.push('Trailing distance is very large compared to initial risk - may give back too much profit'); } if (Math.abs(unrealizedPnLPercentage) > 20) { warnings.push('Large unrealized PnL - consider taking partial profits'); } // Get instrument info for price formatting const instrumentInfo = await this.getInstrumentsInfo(category, symbol); if ('result' in instrumentInfo) { const priceFilter = instrumentInfo.result.list[0].priceFilter; const tickSize = parseFloat(priceFilter.tickSize); const decimalPlaces = tickSize.toString().split('.')[1]?.length || 0; // Round new stop loss to valid tick size newStopLoss = Math.round(newStopLoss / tickSize) * tickSize; newStopLoss = parseFloat(newStopLoss.toFixed(decimalPlaces)); } return { newStopLoss, trailingActivated, breakevenProtection, profitProtected, unrealizedPnL, unrealizedPnLPercentage, recommendations: { shouldUpdateStop: newStopLoss !== initialStopLoss, newStopPrice: newStopLoss, protectionLevel, reasoning }, calculations: { priceMovement, priceMovementPercentage, stopLossMovement, maxDrawdownProtection, profitLocked }, warnings }; } catch (error: any) { return { newStopLoss: initialStopLoss, trailingActivated: false, breakevenProtection: false, profitProtected: 0, unrealizedPnL: 0, unrealizedPnLPercentage: 0, recommendations: { shouldUpdateStop: false, newStopPrice: initialStopLoss, protectionLevel: 'none', reasoning: 'Error calculating trailing stop' }, calculations: { priceMovement: 0, priceMovementPercentage: 0, stopLossMovement: 0, maxDrawdownProtection: 0, profitLocked: 0 }, warnings: [], error: error.message }; } }
  • Input schema definition for the calculate_trailing_stop tool, specifying parameters and validation.
    { name: 'calculate_trailing_stop', description: 'Calculate trailing stop loss with breakeven and profit protection', inputSchema: { type: 'object', properties: { category: { type: 'string', description: 'Category (linear, inverse)', }, symbol: { type: 'string', description: 'Symbol (e.g., ETHUSDT)', }, entryPrice: { type: 'number', description: 'Entry price of the position', }, currentPrice: { type: 'number', description: 'Current market price', }, side: { type: 'string', description: 'Position side (Buy for long, Sell for short)', }, initialStopLoss: { type: 'number', description: 'Initial stop loss price', }, trailingDistance: { type: 'number', description: 'Trailing distance in price units', }, breakevenTrigger: { type: 'number', description: 'Price distance from entry to activate breakeven protection (optional)', }, profitProtectionTrigger: { type: 'number', description: 'Price distance from entry to activate profit protection (optional)', }, }, required: ['category', 'symbol', 'entryPrice', 'currentPrice', 'side', 'initialStopLoss', 'trailingDistance'], }, },
  • src/index.ts:1024-1044 (registration)
    Tool handler registration in the MCP CallToolRequest switch statement, dispatching arguments to BybitService.calculateTrailingStop and returning the result.
    case 'calculate_trailing_stop': { const result = await this.bybitService.calculateTrailingStop( typedArgs.category, typedArgs.symbol, typedArgs.entryPrice, typedArgs.currentPrice, typedArgs.side, typedArgs.initialStopLoss, typedArgs.trailingDistance, typedArgs.breakevenTrigger, typedArgs.profitProtectionTrigger ); return { content: [ { type: 'text', text: JSON.stringify(result, null, 2), }, ], }; }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/kondisettyravi/mcp-bybit-node'

If you have feedback or need assistance with the MCP directory API, please join our Discord server