Add documentation for duplicate position fix

This commit is contained in:
mindesbunister
2025-10-27 19:08:52 +01:00
parent 8f90339d8d
commit eeb90ad455

View File

@@ -0,0 +1,146 @@
# Duplicate Position Prevention - Fix Documentation
**Date:** 2025-01-27
**Issue:** Multiple positions opened on same symbol from different timeframe signals
**Status:** ✅ RESOLVED
## Problem Description
User received TradingView alerts on both 15-minute AND 30-minute charts for SOLUSDT. The bot:
1. ✅ Correctly extracted timeframe from both alerts (15 and 30)
2. ✅ Correctly filtered out the 30-minute signal (as intended)
3. ❌ BUT allowed the 15-minute signal even though a position already existed
4. ❌ Result: Two LONG positions on SOL-PERP opened 15 minutes apart
**Root Cause:** Risk check API (`/api/trading/check-risk`) had `TODO` comment for checking existing positions but was always returning `allowed: true`.
## Solution Implemented
### 1. Updated Risk Check API
**File:** `app/api/trading/check-risk/route.ts`
**Changes:**
- Import `getInitializedPositionManager()` instead of `getPositionManager()`
- Wait for Position Manager initialization (restores trades from database)
- Check if any active trade exists on the requested symbol
- Block trade if duplicate found
```typescript
// Check for existing positions on the same symbol
const positionManager = await getInitializedPositionManager()
const existingTrades = Array.from(positionManager.getActiveTrades().values())
const duplicatePosition = existingTrades.find(trade => trade.symbol === body.symbol)
if (duplicatePosition) {
return NextResponse.json({
allowed: false,
reason: 'Duplicate position',
details: `Already have ${duplicatePosition.direction} position on ${body.symbol} (entry: $${duplicatePosition.entryPrice})`,
})
}
```
### 2. Fixed Timing Issue
**Problem:** `getPositionManager()` creates instance immediately but trades are restored asynchronously in background.
**Solution:** Use `getInitializedPositionManager()` which waits for the initialization promise to complete before returning.
### 3. Updated .dockerignore
**Problem:** Test files in `tests/` and `archive/` directories were being included in Docker build, causing TypeScript compilation errors.
**Solution:** Added to `.dockerignore`:
```
tests/
archive/
*.test.ts
*.spec.ts
```
## Testing Results
### Test 1: Duplicate Position (BLOCKED ✅)
```bash
curl -X POST /api/trading/check-risk \
-d '{"symbol":"SOL-PERP","direction":"long"}'
Response:
{
"allowed": false,
"reason": "Duplicate position",
"details": "Already have long position on SOL-PERP (entry: $202.835871)"
}
```
**Logs:**
```
🔍 Risk check for: { symbol: 'SOL-PERP', direction: 'long' }
🚫 Risk check BLOCKED: Duplicate position exists {
symbol: 'SOL-PERP',
existingDirection: 'long',
requestedDirection: 'long',
existingEntry: 202.835871
}
```
### Test 2: Different Symbol (ALLOWED ✅)
```bash
curl -X POST /api/trading/check-risk \
-d '{"symbol":"BTC-PERP","direction":"long"}'
Response:
{
"allowed": true,
"details": "All risk checks passed"
}
```
## System Behavior Now
**n8n Workflow Flow:**
1. TradingView sends alert → n8n webhook
2. Extract timeframe from message (`\.P\s+(\d+)` regex)
3. **15min Chart Only?** IF node: Check `timeframe == "15"`
4. If passed → Call `/api/trading/check-risk`
5. **NEW:** Check if position exists on symbol
6. If no duplicate → Execute trade via `/api/trading/execute`
**Risk Check Matrix:**
| Scenario | Timeframe Filter | Risk Check | Result |
|----------|------------------|------------|---------|
| 15min signal, no position | ✅ PASS | ✅ PASS | Trade executes |
| 15min signal, position exists | ✅ PASS | 🚫 BLOCK | Trade blocked |
| 30min signal, no position | 🚫 BLOCK | N/A | Trade blocked |
| 30min signal, position exists | 🚫 BLOCK | N/A | Trade blocked |
## Future Enhancements
The risk check API still has TODO items:
- [ ] Check daily drawdown limit
- [ ] Check trades per hour limit
- [ ] Check cooldown period after loss
- [ ] Check Drift account health before trade
- [ ] Allow opposite direction trades (hedging)?
## Files Modified
1. `app/api/trading/check-risk/route.ts` - Added duplicate position check
2. `.dockerignore` - Excluded test files from Docker build
3. Moved `test-*.ts` files from `/` to `archive/`
## Git Commits
- **8f90339** - "Add duplicate position prevention to risk check"
- **17b0806** - "Add 15-minute chart filter to n8n workflow" (previous)
## Deployment
```bash
docker compose build trading-bot
docker compose up -d --force-recreate trading-bot
```
Bot automatically restores existing positions from database on startup via Position Manager persistence.
---
**Status:** System now prevents duplicate positions on same symbol. Multiple 15-minute signals will be blocked by risk check even if timeframe filter passes.