Skip to content
Back to skills

1914 Track Position 25f91a38

ASecurity

Track crypto positions with entry prices, current values, and PnL calculations

  • 9 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 11, 2026
databasesjavascriptjavasqlapidatabase

Works with

  • api

Security analysis

A100/100

Scanned October 11, 2026

npx -y skills add tools-only/X-Skills --skill 1914-track-position_25f91a38 --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of 1914 Track Position 25f91a38?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for 1914 Track Position 25f91a38
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/tools-only-1914-track-position-25f91a38/badge)](https://www.skillsdirectory.com/skills/tools-only-1914-track-position-25f91a38)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

SKILL.md
---
name: track-position
description: >
  Track crypto positions with entry prices, current values, and PnL
  calculations
shortcut: tp
---
# Track Crypto Position

Comprehensive position tracking for cryptocurrency investments with real-time price updates and advanced analytics.

## Usage

When the user wants to track a crypto position, gather the following information and implement a complete tracking system:

### Required Information
- **Symbol**: The cryptocurrency ticker (BTC, ETH, SOL, etc.)
- **Entry Price**: Purchase price per unit
- **Quantity**: Amount purchased
- **Entry Date**: When the position was opened
- **Exchange**: Where the trade was executed (optional)
- **Target Price**: Profit target (optional)
- **Stop Loss**: Risk management level (optional)

## Implementation

### 1. Database Schema

Create a structured database to track positions:

```sql
CREATE TABLE IF NOT EXISTS crypto_positions (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    symbol VARCHAR(10) NOT NULL,
    entry_price DECIMAL(20,8) NOT NULL,
    quantity DECIMAL(20,8) NOT NULL,
    entry_date TIMESTAMP NOT NULL,
    current_price DECIMAL(20,8),
    last_updated TIMESTAMP,
    exchange VARCHAR(50),
    target_price DECIMAL(20,8),
    stop_loss DECIMAL(20,8),
    status VARCHAR(20) DEFAULT 'open',
    notes TEXT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE IF NOT EXISTS position_history (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    position_id UUID REFERENCES crypto_positions(id),
    price DECIMAL(20,8) NOT NULL,
    value DECIMAL(20,8) NOT NULL,
    pnl DECIMAL(20,8) NOT NULL,
    pnl_percentage DECIMAL(10,4) NOT NULL,
    recorded_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX idx_positions_symbol ON crypto_positions(symbol);
CREATE INDEX idx_positions_status ON crypto_positions(status);
CREATE INDEX idx_history_position ON position_history(position_id);
```

### 2. Position Tracking Class

```javascript
class CryptoPositionTracker {
    constructor() {
        this.priceFeeds = {
            coingecko: 'https://api.coingecko.com/api/v3',
            binance: 'https://api.binance.com/api/v3',
            coinbase: 'https://api.coinbase.com/v2'
        };
    }

    async trackPosition(positionData) {
        const {
            symbol,
            entryPrice,
            quantity,
            entryDate,
            exchange = 'Unknown',
            targetPrice = null,
            stopLoss = null,
            notes = ''
        } = positionData;

        // Validate input
        this.validatePositionData(positionData);

        // Get current price
        const currentPrice = await this.getCurrentPrice(symbol);

        // Calculate metrics
        const metrics = this.calculateMetrics({
            entryPrice,
            quantity,
            currentPrice
        });

        // Store position
        const position = await this.storePosition({
            symbol: symbol.toUpperCase(),
            entry_price: entryPrice,
            quantity,
            entry_date: entryDate,
            current_price: currentPrice,
            exchange,
            target_price: targetPrice,
            stop_loss: stopLoss,
            notes
        });

        // Record initial history
        await this.recordHistory(position.id, currentPrice, metrics);

        return {
            position,
            metrics,
            analysis: this.analyzePosition(position, metrics)
        };
    }

    calculateMetrics({ entryPrice, quantity, currentPrice }) {
        const entryValue = entryPrice * quantity;
        const currentValue = currentPrice * quantity;
        const unrealizedPnL = currentValue - entryValue;
        const pnlPercentage = ((currentValue - entryValue) / entryValue) * 100;

        return {
            entryValue: parseFloat(entryValue.toFixed(2)),
            currentValue: parseFloat(currentValue.toFixed(2)),
            unrealizedPnL: parseFloat(unrealizedPnL.toFixed(2)),
            pnlPercentage: parseFloat(pnlPercentage.toFixed(2)),
            roi: pnlPercentage,
            riskRewardRatio: this.calculateRiskReward({
                entryPrice,
                currentPrice,
                targetPrice: position.target_price,
                stopLoss: position.stop_loss
            })
        };
    }

    calculateRiskReward({ entryPrice, currentPrice, targetPrice, stopLoss }) {
        if (!targetPrice || !stopLoss) return null;

        const potentialReward = targetPrice - entryPrice;
        const potentialRisk = entryPrice - stopLoss;

        if (potentialRisk === 0) return null;

        return parseFloat((potentialReward / potentialRisk).toFixed(2));
    }

    analyzePosition(position, metrics) {
        const analysis = {
            status: this.determineStatus(metrics),
            recommendation: this.getRecommendation(position, metrics),
            risks: this.identifyRisks(position, metrics),
            opportunities: this.identifyOpportunities(position, metrics)
        };

        return analysis;
    }

    determineStatus(metrics) {
        if (metrics.pnlPercentage > 20) return 'STRONG_PROFIT';
        if (metrics.pnlPercentage > 5) return 'PROFIT';
        if (metrics.pnlPercentage > -5) return 'NEUTRAL';
        if (metrics.pnlPercentage > -20) return 'LOSS';
        return 'SIGNIFICANT_LOSS';
    }

    getRecommendation(position, metrics) {
        const recommendations = [];

        // Check stop loss
        if (position.stop_loss && position.current_price <= position.stop_loss) {
            recommendations.push({
                action: 'EXIT',
                reason: 'Stop loss hit',
                urgency: 'HIGH'
            });
        }

        // Check target
        if (position.target_price && position.current_price >= position.target_price) {
            recommendations.push({
                action: 'TAKE_PROFIT',
                reason: 'Target price reached',
                urgency: 'MEDIUM'
            });
        }

        // Check significant profit
        if (metrics.pnlPercentage > 50) {
            recommendations.push({
                action: 'PARTIAL_PROFIT',
                reason: 'Consider taking partial profits (50%+ gain)',
                urgency: 'LOW'
            });
        }

        // Check significant loss
        if (metrics.pnlPercentage < -30 && !position.stop_loss) {
            recommendations.push({
                action: 'SET_STOP_LOSS',
                reason: 'Significant loss without stop loss protection',
                urgency: 'HIGH'
            });
        }

        return recommendations;
    }

    async getCurrentPrice(symbol) {
        // Implementation would fetch from multiple sources
        // and return average or most reliable price
        try {
            const prices = await Promise.all([
                this.fetchCoingeckoPrice(symbol),
                this.fetchBinancePrice(symbol)
            ]);

            return prices.reduce((sum, price) => sum + price, 0) / prices.length;
        } catch (error) {
            throw new Error(`Failed to fetch price for ${symbol}: ${error.message}`);
        }
    }

    async updateAllPositions() {
        const openPositions = await this.getOpenPositions();
        const updates = [];

        for (const position of openPositions) {
            try {
                const currentPrice = await this.getCurrentPrice(position.symbol);
                const metrics = this.calculateMetrics({
                    entryPrice: position.entry_price,
                    quantity: position.quantity,
                    currentPrice
                });

                await this.updatePosition(position.id, {
                    current_price: currentPrice,
                    last_updated: new Date()
                });

                await this.recordHistory(position.id, currentPrice, metrics);

                updates.push({
                    symbol: position.symbol,
                    currentPrice,
                    metrics,
                    status: 'UPDATED'
                });
            } catch (error) {
                updates.push({
                    symbol: position.symbol,
                    status: 'ERROR',
                    error: error.message
                });
            }
        }

        return updates;
    }
}
```

### 3. Display Format

When displaying position information, format it clearly:

```javascript
function displayPosition(position, metrics) {
    const output = `
╔════════════════════════════════════════════════════════════════╗
║                    CRYPTO POSITION TRACKER                     ║
╠════════════════════════════════════════════════════════════════╣
║ Symbol:        ${position.symbol.padEnd(48)} ║
║ Entry Price:   $${position.entry_price.toFixed(2).padEnd(47)} ║
║ Current Price: $${position.current_price.toFixed(2).padEnd(47)} ║
║ Quantity:      ${position.quantity.toString().padEnd(48)} ║
╠════════════════════════════════════════════════════════════════╣
║                          METRICS                               ║
╠════════════════════════════════════════════════════════════════╣
║ Entry Value:   $${metrics.entryValue.toFixed(2).padEnd(47)} ║
║ Current Value: $${metrics.currentValue.toFixed(2).padEnd(47)} ║
║ Unrealized P&L: ${formatPnL(metrics.unrealizedPnL).padEnd(47)} ║
║ P&L %:         ${formatPnLPercentage(metrics.pnlPercentage).padEnd(48)} ║
╠════════════════════════════════════════════════════════════════╣
║ Status:        ${determineStatusEmoji(metrics.pnlPercentage)} ${metrics.status.padEnd(43)} ║
╚════════════════════════════════════════════════════════════════╝
    `;

    return output;
}

function formatPnL(value) {
    const formatted = `$${Math.abs(value).toFixed(2)}`;
    if (value >= 0) {
        return `+${formatted} `;
    } else {
        return `-${formatted} `;
    }
}

function formatPnLPercentage(percentage) {
    const formatted = `${Math.abs(percentage).toFixed(2)}%`;
    if (percentage >= 0) {
        return `+${formatted} `;
    } else {
        return `-${formatted} `;
    }
}

function determineStatusEmoji(percentage) {
    if (percentage > 20) return '';
    if (percentage > 5) return '';
    if (percentage > -5) return '';
    if (percentage > -20) return '️';
    return '';
}
```

### 4. Alert System

Set up automatic alerts for significant events:

```javascript
class PositionAlertSystem {
    constructor() {
        this.alertThresholds = {
            profitTarget: 0.20,      // 20% profit
            lossWarning: -0.10,      // 10% loss
            criticalLoss: -0.25,     // 25% loss
            volatilitySpike: 0.15    // 15% daily move
        };
    }

    async checkAlerts(position, previousPrice, currentPrice) {
        const alerts = [];
        const priceChange = ((currentPrice - previousPrice) / previousPrice) * 100;

        // Check profit targets
        if (metrics.pnlPercentage >= this.alertThresholds.profitTarget * 100) {
            alerts.push({
                type: 'PROFIT_TARGET',
                message: ` ${position.symbol} hit profit target: +${metrics.pnlPercentage.toFixed(2)}%`,
                severity: 'INFO',
                action: 'Consider taking profits'
            });
        }

        // Check loss warnings
        if (metrics.pnlPercentage <= this.alertThresholds.lossWarning * 100 &&
            metrics.pnlPercentage > this.alertThresholds.criticalLoss * 100) {
            alerts.push({
                type: 'LOSS_WARNING',
                message: `️ ${position.symbol} loss warning: ${metrics.pnlPercentage.toFixed(2)}%`,
                severity: 'WARNING',
                action: 'Review position and consider stop loss'
            });
        }

        // Check critical loss
        if (metrics.pnlPercentage <= this.alertThresholds.criticalLoss * 100) {
            alerts.push({
                type: 'CRITICAL_LOSS',
                message: ` ${position.symbol} critical loss: ${metrics.pnlPercentage.toFixed(2)}%`,
                severity: 'CRITICAL',
                action: 'Immediate review required'
            });
        }

        // Check volatility
        if (Math.abs(priceChange) >= this.alertThresholds.volatilitySpike * 100) {
            alerts.push({
                type: 'VOLATILITY_SPIKE',
                message: ` ${position.symbol} volatility spike: ${priceChange > 0 ? '+' : ''}${priceChange.toFixed(2)}% in 24h`,
                severity: 'INFO',
                action: 'Monitor closely for opportunities or risks'
            });
        }

        return alerts;
    }
}
```

## Error Handling

Always implement comprehensive error handling:

```javascript
try {
    const position = await tracker.trackPosition({
        symbol: 'BTC',
        entryPrice: 45000,
        quantity: 0.5,
        entryDate: new Date('2024-01-01'),
        targetPrice: 60000,
        stopLoss: 40000
    });

    displayPosition(position.position, position.metrics);
} catch (error) {
    if (error.code === 'INVALID_SYMBOL') {
        console.error(`Invalid cryptocurrency symbol: ${error.symbol}`);
    } else if (error.code === 'API_ERROR') {
        console.error(`Failed to fetch price data: ${error.message}`);
    } else {
        console.error(`Unexpected error: ${error.message}`);
    }
}
```

This command provides comprehensive position tracking with real-time updates, PnL calculations, risk analysis, and actionable recommendations for crypto investments.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.