**Issue 1: TP2 Runner Position Bug** ✅ FIXED - TP2 was calculated as 80% of ORIGINAL position instead of REMAINING - With TP1=75%, TP2=80%: Was closing 75%+80%=155% (capped at 100%) - Now correctly: TP1 closes 75%, TP2 closes 80% of remaining 25% = 20% - Result: 5% runner now remains for trailing stop as intended! **Issue 2: Race Condition - Orphaned SL Orders** ✅ FIXED - Orders were placed AFTER Position Manager started monitoring - If TP hit fast, PM detected 'external closure' before orders finished - Orders completed after position gone → orphaned SL orders on Drift - Now: Exit orders placed BEFORE starting monitoring - PM can now properly cancel remaining orders when position closes **Issue 3: 5min vs 15min Timeframe** ⚠️ NEEDS VERIFICATION - n8n workflow correctly filters for timeframe === '15' - Extracts timeframe with regex: /\.P\s+(\d+)/ - User needs to verify TradingView alert includes '.P 15' in message - Format should be: 'SOL buy .P 15' not just 'SOL buy' **Technical Changes:** - lib/drift/orders.ts: Fixed TP2 calculation to use remaining size - Added logging: Shows TP1, TP2, remaining, and runner amounts - app/api/trading/execute/route.ts: Reordered to place orders before monitoring - Prevents race condition where orders complete after position closed **Testing:** - Next trade will show proper runner position (5% remains) - No more orphaned SL orders after wins - Logs will show: 'Runner (if any): $X.XX' **Documentation:** - Created CRITICAL_ISSUES_FOUND.md explaining all 3 issues - Created FIXES_APPLIED.md with testing instructions
4.7 KiB
4.7 KiB
Fixes Applied - Trading Bot v4
Summary of Changes
Fixed 3 critical bugs discovered in your trading bot:
- ✅ TP2 Runner Calculation Bug - Now correctly calculates TP2 as percentage of REMAINING position
- ✅ Race Condition Fix - Exit orders now placed BEFORE Position Manager starts monitoring
- ⚠️ TradingView Timeframe - Needs verification of alert format
Fix 1: TP2 Runner Position Bug
File: lib/drift/orders.ts
Problem:
// BEFORE (WRONG):
const tp1USD = (options.positionSizeUSD * options.tp1SizePercent) / 100 // 75% of $80 = $60
const tp2USD = (options.positionSizeUSD * options.tp2SizePercent) / 100 // 80% of $80 = $64 ❌
// Total: $124 (exceeds position!) → Drift closes 100%, no runner
Fixed:
// AFTER (CORRECT):
const tp1USD = (options.positionSizeUSD * options.tp1SizePercent) / 100 // 75% of $80 = $60
const remainingAfterTP1 = options.positionSizeUSD - tp1USD // $80 - $60 = $20
const tp2USD = (remainingAfterTP1 * options.tp2SizePercent) / 100 // 80% of $20 = $16 ✅
// Remaining: $20 - $16 = $4 (5% runner!) ✅
Result:
- With
TAKE_PROFIT_2_SIZE_PERCENT=80:- TP1 closes 75% ($60)
- TP2 closes 80% of remaining ($16)
- 5% runner remains ($4) for trailing stop!
Added logging to verify:
📊 Exit order sizes:
TP1: 75% of $80.00 = $60.00
Remaining after TP1: $20.00
TP2: 80% of remaining = $16.00
Runner (if any): $4.00
Fix 2: Race Condition - Orphaned SL Orders
File: app/api/trading/execute/route.ts
Problem:
Old Flow:
1. Open position
2. Add to Position Manager → starts monitoring immediately
3. Place exit orders (TP1, TP2, SL)
If TP hits fast (< 2-3 seconds):
- Position Manager detects "external closure"
- Tries to cancel orders (finds none yet)
- Orders finish placing AFTER position gone
- Result: Orphaned SL orders on Drift!
Fixed:
New Flow:
1. Open position
2. Place exit orders (TP1, TP2, SL) ← FIRST
3. Add to Position Manager → starts monitoring
Now:
- All orders exist before monitoring starts
- If TP hits fast, Position Manager can cancel remaining orders
- No orphaned orders!
Issue 3: TradingView Timeframe Filter
Status: Needs Your Action
The n8n workflow correctly filters for 15-minute timeframe:
{
"conditions": {
"string": [{
"value1": "={{ $json.timeframe }}",
"operation": "equals",
"value2": "15"
}]
}
}
The timeframe is extracted from your TradingView alert with regex:
/\.P\s+(\d+)/ // Looks for ".P 15" or ".P 5" in message
Action Required:
Check your TradingView alert message format.
It should look like:
{{ticker}} {{strategy.order.action}} .P 15
Examples:
- ✅ Correct:
SOL buy .P 15(will be accepted) - ❌ Wrong:
SOL buy .P 5(will be rejected) - ⚠️ Missing:
SOL buy(defaults to 15, but not explicit)
To verify:
- Open your TradingView chart
- Go to Alerts
- Check the alert message format
- Ensure it includes ".P 15" for 15-minute timeframe
Testing the Fixes
Test 1: Runner Position
- Place a test trade (or wait for next signal)
- Watch position in Drift
- TP1 should hit → 75% closes
- TP2 should hit → 80% of remaining closes
- 5% runner should remain for trailing stop
Expected in Drift:
- After TP1: 0.25 SOL remaining (from 1.0 SOL)
- After TP2: 0.05 SOL remaining (runner)
Test 2: No Orphaned Orders
- Place test trade
- If TP hits quickly, check Drift "Orders" tab
- Should show: No open orders after position fully closes
- Previously: 2 SL orders remained after win
Test 3: Timeframe Filter
- Send 5-minute alert from TradingView (with ".P 5")
- Check n8n execution → Should be rejected by filter
- Send 15-minute alert (with ".P 15")
- Should be accepted and execute trade
Build & Deploy
# Build (in progress)
docker compose build trading-bot
# Restart
docker compose up -d --force-recreate trading-bot
# Verify
docker logs -f trading-bot-v4
Look for new log message:
📊 Exit order sizes:
TP1: 75% of $XX.XX = $XX.XX
Remaining after TP1: $XX.XX
TP2: 80% of remaining = $XX.XX
Runner (if any): $XX.XX
Summary
| Issue | Status | Impact |
|---|---|---|
| TP2 Runner Calculation | ✅ Fixed | 5% runner will now remain as intended |
| Orphaned SL Orders | ✅ Fixed | Orders placed before monitoring starts |
| 5min vs 15min Filter | ⚠️ Verify | Check TradingView alert includes ".P 15" |
Next Steps:
- Deploy fixes (build running)
- Verify TradingView alert format
- Test with next trade signal
- Monitor for runner position and clean order cancellation