Commit Graph

22 Commits

Author SHA1 Message Date
mindesbunister
7c4adff4e4 Implement risk checks: cooldown, hourly limit, and daily drawdown
Implemented 3 critical risk checks in /api/trading/check-risk:

1. Daily Drawdown Check
   - Blocks trades if today's P&L < maxDailyDrawdown
   - Prevents catastrophic daily losses
   - Currently: -0 limit (configurable via MAX_DAILY_DRAWDOWN)

2. Hourly Trade Limit
   - Blocks trades if tradesInLastHour >= maxTradesPerHour
   - Prevents overtrading / algorithm malfunction
   - Currently: 20 trades/hour (configurable via MAX_TRADES_PER_HOUR)

3. Cooldown Period
   - Blocks trades if timeSinceLastTrade < minTimeBetweenTrades
   - Enforces breathing room between trades
   - Uses minutes (not seconds) thanks to previous commit
   - Currently: 0 min = disabled (configurable via MIN_TIME_BETWEEN_TRADES)

Added database helper functions:
- getLastTradeTime() - Returns timestamp of most recent trade
- getTradesInLastHour() - Counts trades in last 60 minutes
- getTodayPnL() - Sums realized P&L since midnight

All checks include detailed logging with values and thresholds.
Risk check called by n8n workflow before every trade execution.
2025-10-30 10:50:08 +01:00
mindesbunister
da72b5de04 Phase 3: TP/SL Optimization Analytics API
- Created /api/analytics/tp-sl-optimization endpoint
- Analyzes historical trades using MAE/MFE data
- Calculates optimal TP1/TP2/SL levels based on percentiles
- Provides win rate, profit factor, and hit rate analysis
- Shows money left on table (MFE - realized P&L)
- Projects impact of optimal levels on future performance

Analytics calculated:
- MAE analysis: avg, median, percentiles, worst
- MFE analysis: avg, median, percentiles, best
- Current level performance: TP1/TP2/SL hit rates
- Optimal recommendations: TP1=50% of avg MFE, TP2=80%, SL=70% of avg MAE
- Projected improvements: win rate change, profit factor, total P&L

Requires 10+ closed trades with MAE/MFE data to generate recommendations
Test script: scripts/test-analytics.sh

Next: Phase 4 (visual dashboard) or wait for trades with MAE/MFE data
2025-10-29 21:11:23 +01:00
mindesbunister
e068c5f2e6 Phase 2: Market context capture at entry
- Added getFundingRate() method to DriftService
- Capture expectedEntryPrice from oracle before order execution
- Capture fundingRateAtEntry from Drift Protocol
- Save market context fields to database (expectedEntryPrice, fundingRateAtEntry)
- Calculate entry slippage percentage in createTrade()
- Fixed template literal syntax errors in execute endpoint

Database fields populated:
- expectedEntryPrice: Oracle price before order
- entrySlippagePct: Calculated from entrySlippage
- fundingRateAtEntry: Current funding rate from Drift

Next: Phase 3 (analytics API) or test market context on next trade
2025-10-29 20:51:46 +01:00
mindesbunister
65e6a8efed Phase 1: Add MAE/MFE tracking and analytics schema
- Added 20+ analytics fields to Trade model (MAE/MFE, fill tracking, timing, market context, slippage)
- Implemented real-time MAE/MFE tracking in Position Manager (updates every 5s)
- Enhanced database schema with comprehensive trade analytics
- Updated all API endpoints to initialize MAE/MFE fields
- Modified updateTradeState() to persist MAE/MFE in configSnapshot

Database changes:
- maxFavorableExcursion/maxAdverseExcursion track best/worst profit %
- maxFavorablePrice/maxAdversePrice track exact price levels
- Fill tracking: tp1Filled, tp2Filled, softSlFilled, hardSlFilled
- Timing metrics: timeToTp1, timeToTp2, timeToSl
- Market context: atrAtEntry, adxAtEntry, volumeAtEntry, fundingRateAtEntry, basisAtEntry
- Slippage tracking: expectedEntryPrice, entrySlippagePct, expectedExitPrice, exitSlippagePct

Position Manager changes:
- Track MAE/MFE on every price check (2s interval)
- Throttled database updates (5s interval) via updateTradeMetrics()
- Persist MAE/MFE in trade state snapshots for recovery

Next: Phase 2 (market context capture) or Phase 3 (analytics API)
2025-10-29 20:34:03 +01:00
mindesbunister
797e80b56a CRITICAL FIX: TP/SL orders using wrong size calculation
**ROOT CAUSE:** placeExitOrders() calculated position size using TP/SL prices instead of entry price

**Problem:**
- TP1 order size: 85 / TP1_price (00.746) = 2.914 SOL
- Actual position: 80 / entry_price (99.946) = 3.901 SOL
- TP1 should close: 3.901 * 75% = 2.926 SOL
- But it only closed: 2.914 SOL = 74.7%  WRONG!

**Result:** TP1 closed ~25% instead of 75%, no runner left

**Fix:**
- Changed usdToBase() to use entryPrice for ALL size calculations
- Added entryPrice param to PlaceExitOrdersOptions interface
- Updated all API routes to pass entryPrice

**Testing:** Next trade will have correctly sized TP/SL orders
2025-10-29 17:34:10 +01:00
mindesbunister
e8a9b68fa7 Fix: Critical bugs - TP2 runner calculation + race condition + order cleanup
**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
2025-10-28 10:12:04 +01:00
mindesbunister
a72ddd8f0e Fix: Position Manager initialization race condition in API endpoints
- Changed /api/trading/positions to use getInitializedPositionManager()
- Changed /api/trading/test to use getInitializedPositionManager()
- Changed /api/trading/test-db to use getInitializedPositionManager()
- These endpoints were accessing Position Manager before DB restore completed
- Now properly wait for async initialization before accessing trade data
- Fixes /status Telegram command showing empty despite active positions
2025-10-27 23:38:24 +01:00
mindesbunister
9bf83260c4 Add /close command and auto-flip logic with order cleanup
- Added /close Telegram command for full position closure
- Updated /reduce to accept 10-100% (was 10-90%)
- Implemented auto-flip logic: automatically closes opposite position when signal reverses
- Fixed risk check to allow opposite direction trades (signal flips)
- Enhanced Position Manager to cancel orders when removing trades
- Added startup initialization for Position Manager (restores trades on restart)
- Fixed analytics to show stopped-out trades (manual DB update for orphaned trade)
- Updated reduce endpoint to route 100% closes through closePosition for proper cleanup
- All position closures now guarantee TP/SL order cancellation on Drift
2025-10-27 23:27:48 +01:00
mindesbunister
a07bf9f4b2 Add position reduction feature via Telegram
- New endpoint: /api/trading/reduce-position to take partial profits
- Closes specified percentage at market price
- Recalculates and places new TP/SL orders for remaining size
- Entry price stays the same, only size is reduced
- Telegram command: /reduce [percent] (default 50%, range 10-90%)
- Shows realized P&L from the closed portion
- Example: /reduce 25 closes 25% and updates orders for remaining 75%
2025-10-27 20:34:47 +01:00
mindesbunister
1acb5e7210 Add position scaling feature via Telegram
- New endpoint: /api/trading/scale-position to add to existing positions
- Calculates new average entry price after adding more size
- Cancels old TP/SL orders and places new ones at updated levels
- Telegram command: /scale [percent] (default 50%)
- Example: /scale 100 doubles your position
- Automatically adjusts Position Manager tracking with new values
- Cleaned up stale duplicate trade from database
2025-10-27 20:24:06 +01:00
mindesbunister
6a04d3469f Add remove-position endpoint and clean up stale position
- New endpoint: /api/trading/remove-position for manually removing stale positions
- Removed duplicate position from tracking (second SOL-PERP position)
- System now correctly shows 1 active position matching Drift
- Validation and analytics will now show accurate position count
2025-10-27 19:58:57 +01:00
mindesbunister
dde25ad2c1 Add position validation endpoint and Telegram /validate command
- New API endpoint: /api/trading/validate-positions
- Validates TP1, TP2, SL, leverage, and position size against current settings
- Fixed position size calculation: config stores collateral, positions store total value
- Added /validate command to Telegram bot for remote checking
- Returns detailed report of any mismatches with expected vs actual values
2025-10-27 19:20:36 +01:00
mindesbunister
8f90339d8d Add duplicate position prevention to risk check
- Updated risk check API to verify no existing positions on same symbol
- Use getInitializedPositionManager() to wait for trade restoration
- Updated .dockerignore to exclude test files and archive/
- Moved test-*.ts files to archive directory
- Prevents multiple positions from being opened on same symbol even if signals are valid
2025-10-27 19:08:07 +01:00
mindesbunister
4ae9c38ad8 Add trailing stop feature for runner position + fix settings persistence
- Implemented trailing stop logic in Position Manager for remaining position after TP2
- Added new ActiveTrade fields: tp2Hit, trailingStopActive, peakPrice
- New config settings: useTrailingStop, trailingStopPercent, trailingStopActivation
- Added trailing stop UI section in settings page with explanations
- Fixed env file parsing regex to support numbers in variable names (A-Z0-9_)
- Settings now persist correctly across container restarts
- Added back arrow navigation on settings page
- Updated all API endpoints and test files with new fields
- Trailing stop activates when runner reaches configured profit level
- SL trails below peak price by configurable percentage
2025-10-27 12:11:10 +01:00
mindesbunister
d3c04ea9c9 feat: Position Manager persistence + order cleanup + improved stop loss
- Add Position Manager state persistence to survive restarts
  - Auto-restore open trades from database on startup
  - Save state after TP1, SL adjustments, profit locks
  - Persist to configSnapshot JSON field

- Add automatic order cancellation
  - Cancel all TP/SL orders when position fully closed
  - New cancelAllOrders() function in drift/orders.ts
  - Prevents orphaned orders after manual closes

- Improve stop loss management
  - Move SL to +0.35% after TP1 (was +0.15%)
  - Gives more breathing room for retracements
  - Still locks in half of TP1 profit

- Add database sync when Position Manager closes trades
  - Auto-update Trade record with exit data
  - Save P&L, exit reason, hold time
  - Fix analytics showing stale data

- Add trade state management functions
  - updateTradeState() for Position Manager persistence
  - getOpenTrades() for startup restoration
  - getInitializedPositionManager() for async init

- Create n8n database analytics workflows
  - Daily report workflow (automated at midnight)
  - Pattern analysis (hourly/daily performance)
  - Stop loss effectiveness analysis
  - Database analytics query workflow
  - Complete setup guide (N8N_DATABASE_SETUP.md)
2025-10-27 10:39:05 +01:00
mindesbunister
8e5c592cac Fix database persistence and add analytics
- Fixed Prisma client not being available in Docker container
- Added isTestTrade flag to exclude test trades from analytics
- Created analytics views for net positions (matches Drift UI netting)
- Added API endpoints: /api/analytics/positions and /api/analytics/stats
- Added test trade endpoint: /api/trading/test-db
- Updated Dockerfile to properly copy Prisma client from builder stage
- Database now successfully stores all trades with full details
- Supports position netting calculations to match Drift perpetuals behavior
2025-10-27 09:35:01 +01:00
mindesbunister
b82ceb49a4 feat: add position size and leverage to Telegram confirmation message 2025-10-27 01:06:51 +01:00
mindesbunister
d64f6d84c4 feat: implement dual stop system and database tracking
- Add PostgreSQL database with Prisma ORM
  - Trade model: tracks entry/exit, P&L, order signatures, config snapshots
  - PriceUpdate model: tracks price movements for drawdown analysis
  - SystemEvent model: logs errors and system events
  - DailyStats model: aggregated performance metrics

- Implement dual stop loss system (enabled by default)
  - Soft stop (TRIGGER_LIMIT) at -1.5% to avoid wicks
  - Hard stop (TRIGGER_MARKET) at -2.5% to guarantee exit
  - Configurable via USE_DUAL_STOPS, SOFT_STOP_PERCENT, HARD_STOP_PERCENT
  - Backward compatible with single stop modes

- Add database service layer (lib/database/trades.ts)
  - createTrade(): save new trades with all details
  - updateTradeExit(): close trades with P&L calculations
  - addPriceUpdate(): track price movements during trade
  - getTradeStats(): calculate win rate, profit factor, avg win/loss
  - logSystemEvent(): log errors and system events

- Update execute endpoint to use dual stops and save to database
  - Calculate dual stop prices when enabled
  - Pass dual stop parameters to placeExitOrders
  - Save complete trade record to database after execution

- Add test trade button to settings page
  - New /api/trading/test endpoint for executing test trades
  - Displays detailed results including dual stop prices
  - Confirmation dialog before execution
  - Shows entry price, position size, stops, and TX signature

- Generate Prisma client in Docker build
- Update DATABASE_URL for container networking
2025-10-26 21:29:27 +01:00
mindesbunister
4cc294baef feat: Add on-chain TP/SL order placement
- Add placeExitOrders() to create reduce-only LIMIT orders for TP1, TP2, and SL
- Orders now visible in Drift UI
- Tested with real tiny position (0 base x 5x = 0)
- All 3 exit orders placed successfully on-chain
- Position manager continues monitoring as backup
- Added test script and results documentation
2025-10-26 13:30:07 +01:00
mindesbunister
1c4cc5d1fb feat: Add customizable TP size percentages and fix settings save
**New Features:**
- Added TAKE_PROFIT_1_SIZE_PERCENT (default: 50%)
- Added TAKE_PROFIT_2_SIZE_PERCENT (default: 50%)
- Users can now control WHAT % to close at each TP level
- Risk calculator now shows actual TP sizes dynamically

**Bug Fixes:**
- Fixed settings save failure by mounting .env file to container
- Added .env volume mount in docker-compose.yml
- Fixed permission issues (.env must be chmod 666)

**UI Changes:**
- Split TP controls into Price % and Size %
- TP1 Price: When to exit first partial
- TP1 Size: What % of position to close (1-100%)
- TP2 Price: When to exit second partial
- TP2 Size: What % of remaining to close (1-100%)
- Risk calculator displays dynamic percentages

**Example:**
- TP1 at +1% price, close 60% of position
- TP2 at +2% price, close 40% of remaining (24% of original)
- Total exit: 84% of position at TP levels
2025-10-24 15:35:36 +02:00
mindesbunister
26864c10f2 feat: Add container restart functionality from web UI
- Added restart button to settings page
- Created /api/restart endpoint (file-flag based)
- Implemented watch-restart.sh daemon
- Added systemd service for restart watcher
- Updated README with restart setup instructions
- Container automatically restarts when settings changed

Settings flow:
1. User edits settings in web UI
2. Click 'Save Settings' to persist to .env
3. Click 'Restart Bot' to apply changes
4. Watcher detects flag and restarts container
5. New settings loaded automatically
2025-10-24 15:06:26 +02:00
mindesbunister
2405bff68a feat: Complete Trading Bot v4 with Drift Protocol integration
Features:
- Autonomous trading system with Drift Protocol on Solana
- Real-time position monitoring with Pyth price feeds
- Dynamic stop-loss and take-profit management
- n8n workflow integration for TradingView signals
- Beautiful web UI for settings management
- REST API for trade execution and monitoring

- Next.js 15 with standalone output mode
- TypeScript with strict typing
- Docker containerization with multi-stage builds
- PostgreSQL database for trade history
- Singleton pattern for Drift client connection pooling
- BN.js for BigNumber handling (Drift SDK requirement)

- Configurable stop-loss and take-profit levels
- Breakeven trigger and profit locking
- Daily loss limits and trade cooldowns
- Slippage tolerance controls
- DRY_RUN mode for safe testing

- Real-time risk calculator
- Interactive sliders for all parameters
- Live preview of trade outcomes
- Position sizing and leverage controls
- Beautiful gradient design with Tailwind CSS

- POST /api/trading/execute - Execute trades
- POST /api/trading/close - Close positions
- GET /api/trading/positions - Monitor active trades
- GET /api/trading/check-risk - Validate trade signals
- GET /api/settings - View configuration
- POST /api/settings - Update configuration

- Fixed Borsh serialization errors (simplified order params)
- Resolved RPC rate limiting with singleton pattern
- Fixed BigInt vs BN type mismatches
- Corrected order execution flow
- Improved position state management

- Complete setup guides
- Docker deployment instructions
- n8n workflow configuration
- API reference documentation
- Risk management guidelines

- Runs on port 3001 (external), 3000 (internal)
- Uses Helius RPC for optimal performance
- Production-ready with error handling
- Health monitoring and logging
2025-10-24 14:24:36 +02:00