Files
gh-jeremylongshore-claude-c…/commands/track-position.md
2025-11-29 18:53:07 +08:00

418 lines
14 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
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.