docs: Add Bug #89 to copilot-instructions.md Critical Pitfalls

- Entry+Exit Price Extraction fix documented
- Uses getActualFillPriceFromTx() helper with Drift SDK LogParser
- Oracle price vs actual fill difference caused P&L errors
- Git commits: c1bff0d, b4bcde9
- Updated pitfall count reference to 89+
This commit is contained in:
mindesbunister
2026-01-12 08:37:32 +01:00
parent b4bcde942a
commit 3c76c9cd69

View File

@@ -3462,7 +3462,7 @@ ORDER BY MIN(adx) DESC;
## Common Pitfalls
**⚠️ CRITICAL REFERENCE: See `docs/COMMON_PITFALLS.md` for complete list (73 documented issues)**
**⚠️ CRITICAL REFERENCE: See `docs/COMMON_PITFALLS.md` for complete list (89+ documented issues)**
This section contains the **TOP 10 MOST CRITICAL** pitfalls that every AI agent must know. For full details, category breakdowns, code examples, and historical context, see the complete documentation.
@@ -3931,6 +3931,88 @@ This section contains the **TOP 10 MOST CRITICAL** pitfalls that every AI agent
- **Next Validation:** Monitor next trade with container restart to confirm state persists correctly
- **Lesson Learned:** Nested database queries in updates cause race conditions. State persistence needs verification step to catch silent failures. Container restart testing is MANDATORY for state recovery systems. TypeScript compilation validates syntax but not full integration - test suite execution critical.
**14. Entry+Exit Price Extraction - Using Oracle Price Instead of Actual Fill (#89 - CRITICAL - Jan 9, 2026)**
- **Symptom:** P&L showing wrong values (e.g., -$7.18 displayed vs -$13.33 actual), entry/exit prices in database don't match Drift trade history
- **User Report:** "we lost -13.33 on drift for that last trade but the bot shows -7.18 - where is the difference coming from?"
- **Financial Impact:** All historical P&L calculations incorrect, position tracking unreliable, total P&L potentially off by hundreds of dollars
- **Real Incident (Jan 9, 2026):**
* SOL-PERP SHORT opened, expected entry $188.xx
* Bot recorded entry: $188.70 (oracle price at moment of order)
* Actual Drift fill: $188.16 (real execution price)
* Same issue on exit: recorded oracle price instead of fill price
* P&L discrepancy: $6.15 difference on single trade
- **Root Cause:**
* File: `lib/drift/orders.ts` - `openPosition()` and `closePosition()` functions
* Code used `pythClient.getPrice(symbol)` for entry/exit prices
* Oracle price ≠ actual fill price (slippage, market depth, timing)
* Drift executes at VAMM price, not oracle price
* P&L calculated from wrong prices → wrong totals
- **THE FIX (Jan 9, 2026):**
```typescript
// NEW HELPER: Extract actual fill price from transaction logs
export async function getActualFillPriceFromTx(
connection: Connection,
txSignature: string,
driftClient: DriftClient
): Promise<number | null> {
const tx = await connection.getTransaction(txSignature, {
maxSupportedTransactionVersion: 0,
commitment: 'confirmed'
})
if (!tx?.meta?.logMessages) return null
// Use Drift SDK's LogParser to extract OrderActionRecord events
const events = new LogParser(driftClient.program).parseEventsFromLogs(tx)
for (const event of events) {
if (event.eventType === 'OrderActionRecord') {
const record = event as OrderActionRecord
if (record.baseAssetAmountFilled && record.quoteAssetAmountFilled) {
const baseAmount = record.baseAssetAmountFilled.toNumber() / 1e9
const quoteAmount = record.quoteAssetAmountFilled.toNumber() / 1e6
if (baseAmount > 0) {
return quoteAmount / baseAmount // Actual fill price
}
}
}
}
return null
}
// In openPosition(): Use actual fill instead of oracle
const actualEntryPrice = await getActualFillPriceFromTx(connection, txSig, driftClient)
const entryPrice = actualEntryPrice || oraclePrice // Fallback if parsing fails
// In closePosition(): Use actual fill for P&L calculation
const actualExitPrice = await getActualFillPriceFromTx(connection, txSig, driftClient)
const exitPrice = actualExitPrice || oraclePrice
```
- **Why Oracle Price Was Wrong:**
* Oracle = Pyth network aggregate price (external reference)
* Fill = Drift VAMM execution price (actual trade)
* Difference: Slippage, market impact, timing latency
* Example: Oracle $188.70, Fill $188.16 = $0.54 difference × leverage = significant P&L error
- **Prevention Rules:**
1. NEVER use oracle price for P&L calculations
2. ALWAYS extract actual fill from transaction logs
3. Use Drift SDK LogParser for OrderActionRecord events
4. Fallback to oracle only if parsing fails (with warning log)
5. Verify P&L matches Drift UI after every trade
- **Red Flags Indicating This Bug:**
* Bot P&L doesn't match Drift trade history
* Entry/exit prices slightly off from expected
* Cumulative P&L drift over many trades
* User says "Drift shows different number"
- **Files Changed:**
* lib/drift/orders.ts: Added `getActualFillPriceFromTx()` helper (lines 58-95)
* lib/drift/orders.ts: `openPosition()` uses actual fill for entry (line 180)
* lib/drift/orders.ts: `closePosition()` uses actual fill for exit P&L (line 285)
- **Git commits:** c1bff0d (exit fix), b4bcde9 (entry+exit combined)
- **Deployment:** Jan 9, 2026 ~22:00 UTC (container trading-bot-v4)
- **Status:** ✅ FIXED AND DEPLOYED - Both entry and exit now use actual Drift fill prices
- **Lesson Learned:** Oracle prices are reference prices, not execution prices. In leveraged trading, even small price differences compound into significant P&L errors. Always use actual transaction data for financial calculations.
---
**REMOVED FROM TOP 10 (Still documented in full section):**