- Documented 5.7% P&L over-reporting bug (Drift $133.03 vs Database $140.56)
- Root cause: closePosition() used oracle price instead of actual fill price
- Fix: getActualFillPriceFromTx() helper extracts real fills from transaction logs
- WrappedEvent has properties directly on object, NOT nested under .data
- References commit c1bff0d (Jan 11, 2026)
- Added getActualFillPriceFromTx() helper using Drift SDK LogParser
- Extracts OrderActionRecord from transaction logs for real fill data
- P&L now calculated from exitPrice (actual fill) not oraclePrice
- Fixes ~5.7% P&L over-reporting issue ($7.53 on $133 trade)
Root cause: Oracle price at close time differs from actual fill price
Evidence: Drift showed $133.03, database showed $140.56
- Updated copilot-instructions.md: Changed status to DEPLOYED TO PRODUCTION
- Updated PYRAMIDING_IMPLEMENTATION_PLAN.md: Added Phase 8 deployment status
- Added deployment verification checklist with git commit references
- Both documentation files now reflect production deployment state
- Added comprehensive documentation for TP/SL size mismatch bug
- Root cause: usdToBase() recalculated tokens at each exit price
- Fix: Pass positionSizeTokens from position fill, use tokensToBase()
- Updated Quick Reference Table (now 74 pitfalls)
- Updated last modified date to January 6, 2026
BUG #92: Exit orders (TP1, TP2, SL) had different token sizes than position
- Position: 142.91 SOL but TP1=140.87 SOL, SL=147.03 SOL (WRONG)
- Root cause: usdToBase() calculated tokens as USD/price per order
- Each exit order price produced different token amounts
FIX: Pass actual token count via positionSizeTokens parameter
- Added positionSizeTokens to PlaceExitOrdersOptions interface
- Added tokensToBase() helper (tokens * 1e9 directly)
- All exit sections now use token-based calculation when available
Files updated to pass positionSizeTokens:
- app/api/trading/execute/route.ts: openResult.fillSize
- lib/trading/smart-entry-timer.ts: openResult.fillSize
- lib/trading/sync-helper.ts: Math.abs(driftPos.size)
- lib/trading/position-manager.ts: Math.abs(position.size) + fetch patterns
- lib/startup/init-position-manager.ts: Math.abs(position.size)
- lib/health/position-manager-health.ts: Drift position fetch + token size
Result: When position = X tokens, ALL exit orders close portions of X tokens
- TP1: X * tp1SizePercent / 100 tokens
- TP2: remaining * tp2SizePercent / 100 tokens
- SL: X tokens (full position)
Backward compatible: Falls back to USD calculation if positionSizeTokens not provided
- Status changed from PRODUCTION READY to DECOMMISSIONED
- Cost savings: ~$20-30/month (overkill for current $540 capital)
- Backup archived at /home/icke/backups/hostinger-ha/
- Contains: DB dump, n8n data, env, DNS scripts, docker-compose, nginx configs
- Restoration instructions added for when capital grows
- Historical reference preserved for future re-implementation
- Updated config/trading.ts defaults: takeProfit1Percent, minTp1Percent, maxTp1Percent all set to 1.45
- Updated .env: TAKE_PROFIT_1_PERCENT, MIN_TP1_PERCENT, MAX_TP1_PERCENT all set to 1.45
- Updated documentation: Exit strategy section reflects fixed 1.45% TP1 (no ATR variance)
- User requested fixed TP1 at 1.45% instead of ATR-based dynamic targets
- Container restarted to apply changes
- Changed Format Success from Set node (n8n-nodes-base.set) to Code node (n8n-nodes-base.code)
- Set nodes with complex inline JS expressions often fail to evaluate, returning raw template code
- Code node typeVersion 2 properly executes JavaScript with template literals
- Fixes Telegram receiving raw ${resp.symbol} instead of actual values
Affects:
- Smart Entry queue messages
- Trade opened messages
- Signal processed messages
IMPORTANT: User must import updated workflow to n8n via:
1. Open https://flow.egonetix.de
2. Money Machine workflow → Settings → Export
4. Import workflows/trading/Money_Machine.json
- Optimized indicator was missing Direction Mode feature (Long Only)
- Copied working moneyline_v11_2_indicator.pinescript over broken optimized version
- Direction Mode defaults to 'Long Only' (disables SHORT signals)
- Key feature: allowLong/allowShort gates final signals based on direction setting
- Green supertrend line now properly sticks to candles with plot.style_linebr
- Added Monte Carlo simulation notebook for v11.2 projections
Files changed:
- workflows/trading/moneyline_v11_2_optimized_indicator.pinescript (restored)
- docs/analysis/v11_compounding_simulation.ipynb (new)
- Updated CURRENT ACTIVE SYSTEM section with Direction Mode feature
- Default: 'Long Only' (84% win rate on LONGs, SHORTs disabled until optimized)
- Added allowLong/allowShort filter logic documentation
- Updated Last Updated date to Jan 2, 2026 with commit reference
- Added 'Trade Direction' dropdown (Both/Long Only/Short Only)
- Default set to 'Long Only' to disable SHORT signals
- Signals filtered by allowLong/allowShort before alerts fire
- Debug table shows current direction mode setting
- User discovered 84% win rate on LONGs - shorts need optimization
- Production ready for LONG-only live trading
CRITICAL BUG FIXED (Jan 2, 2026):
- Old backtest treated SHORT signal as 'exit LONG only' (reversal system)
- Live trading opens actual SHORT position = different outcome
- Backtest showed profit but live trading lost money due to mismatch
Changes:
- Added close_entries_rule='ANY' to strategy declaration
- Opposite signal now CLOSES current position first, then opens NEW
- Added 'Direction Mode' dropdown: Both / Long Only / Short Only
- Comments document the fix for future reference
This allows honest evaluation:
1. Run 'Both' mode to see true combined performance
2. Run 'Long Only' to see LONG-only results
3. Run 'Short Only' to see SHORT-only results (likely the problem area)
Root Cause: Math.floor(sizeToClose * 1e9) truncated position sizes, leaving tiny fractional remnants (e.g., 0.00000008 SOL) that prevented full position closure.
Discovery: Drift UI 'Close All Positions' failed with 'not enough collateral' but clicking 'Market' order worked - because Market uses exact position size.
Solution: SDK's driftClient.closePosition() uses exact BN arithmetic internally (baseAssetAmount.abs()), avoiding any floating point truncation.
Changes:
- lib/drift/orders.ts lines 647-690
- For 100% closes: Now uses driftClient.closePosition(marketIndex)
- For partial closes: Continues using placeAndTakePerpOrder
Expected Impact: Flip operations will now fully close positions without leaving fractional remnants that cause 'position still open' failures.
Financial Impact: Prevents flip failures that caused user 000+ losses from multiple bugs in position closing logic.
ROOT CAUSE: placePerpOrder() only places orders on Drift order book, doesn't fill.
SOLUTION: placeAndTakePerpOrder() places AND matches against makers atomically.
Real Incident (Dec 31, 2025):
- Dec 30 18:17: SHORT opened at $124.36
- Dec 31 00:30: LONG signal received - should flip position
- Transaction confirmed but Solscan showed 'Place' not 'Fill'
- Position remained open, eventually hit SL twice
- Total loss: ~$40.21
Files changed:
- lib/drift/orders.ts (line 662): placePerpOrder → placeAndTakePerpOrder
- docs/COMMON_PITFALLS.md: Added Bug #90 documentation
Deployment: Dec 31, 2025 11:38 CET (container trading-bot-v4)
- Q95 strategy section marked as ARCHIVED (superseded by v11.2)
- 5-Candle Time Exit marked as REMOVED (commit 9036252)
- Updated 'Filters Applied' to note 5-candle removal
- Added references to v11.2 as current production system
- v11.2 backtest (+53.80% return, PF 2.617) did NOT include 5-candle rule
- Removed TIME_EXIT_5_CANDLE logic from position-manager.ts
- v11.2 backtest (+53.80%) didn't include this exit rule
- Trades will now be allowed to reach TP1 (+1.1%) instead of early exit
- Previous behavior: Exit after 25min if MFE < $30 (force-exited -0.20% trade)
- New behavior: Let trades run to configured TP1/SL levels
Rationale: The 5-candle rule was from an older Q>=95 strategy optimization.
v11.2 indicator already filters to PF 2.617 profitable setups, additional
time-based filtering was counter-productive and introduced untested behavior.
- Corrected comment from +50%/2.507 to actual verified +53.80%/2.617
- 202 trades, 8.35% max drawdown confirmed via user screenshot
- At 5x leverage: ~269% monthly return potential, 00 → 00-,100
- Created comprehensive exit strategy analysis from 30-day backtest
- Key finding: Average loss -1.84 vs average win /bin/bash.76 (42 asymmetry)
- Root cause: Position management not working, not entry quality
- Dynamic thresholds tested: only +.21/month improvement (rejected)
- Backtesting infrastructure: 487-line Python script with regime analysis
- Database: PostgreSQL integration for 78 real trades Nov 23 - Dec 23
- Next steps: Fix exit strategy, not thresholds (exits are the problem)
- Insert 'Check Skip Notification' IF node between Format Risk and Telegram Risk
- Route TRUE branch (skipNotification === true) to workflow end (no notification)
- Route FALSE branch to Telegram Risk for notification
- Fixes unwanted FARTCOIN-PERP notifications while preserving SOL-PERP notifications
- API at /api/trading/check-risk returns skipNotification: true for disabled symbols
Key clarifications in ORDERBOOK_SHADOW_LOGGING.md:
1. Trade execution only (NOT periodic):
- Orderbook captured in /api/trading/execute (lines 1037-1053)
- NOT captured in /api/trading/market-data (1-minute feed)
- Frequency: 3-5 orderbook snapshots per day (when trades execute)
- vs. 1,440 market data updates per day (price/ATR/ADX/RSI)
2. Phase 1.5 declined (Dec 19, 2025):
- User asked about 1-minute periodic orderbook capture
- Agent explained tradeoffs: 1,440 API calls/day, more storage
- User confirmed trade-time capture sufficient for now
- Periodic monitoring not needed for Phase 1 validation
3. Scope clarity for resumption:
- Phase 1 complete and deployed
- Goal: Collect 50-100 trades with orderbook data
- Phase 2: Real orderbook API integration (Hyperliquid/Jupiter)
- Next agent: Monitor trade data collection, analyze patterns
Status: ✅ All Phase 1 tasks complete, awaiting first trade validation
User clarification: 'i thought it is the v11 v2'
- Updated to show v11.2 IMPROVED as active version
- Documented both available indicators (v11.2 improved and v11 all filters)
- Added parameters for both versions for comparison
- Note: Database shows 'v11' but user has v11.2 loaded in TradingView
MANDATORY section for all AI agents to check first:
- Current TradingView indicator: v11 All Filters (filters NOW working)
- Signal quality scoring: v9 with direction-specific thresholds
- Position management: TP2-as-runner with ATR-based dynamic targets
- Adaptive leverage: 10x/5x with LONG 95+, SHORT 90+ thresholds
- Verification commands to check what's actually deployed
This prevents confusion when multiple implementations exist.
User mandate: 'i want this to be a mandatory thing to document'