Update README with comprehensive architecture, dual-layer redundancy, and current features

- Add dual-layer redundancy explanation (on-chain + Position Manager)
- Document dual stop-loss system (soft TRIGGER_LIMIT + hard TRIGGER_MARKET)
- Add complete trade flow documentation (signal → execution → monitoring → exit)
- Update supported timeframes (5min and 15min)
- Document database integration (PostgreSQL + Prisma)
- Add configuration system details (three-layer merge)
- Document recent bug fixes (TP2 calculation, race condition, order cancellation)
- Add comprehensive file structure
- Update API endpoints with all current routes
- Add real-world trade examples with P&L calculations
- Document singleton patterns and critical coding practices
- Add troubleshooting section with common issues
- Update testing commands and safety guidelines
This commit is contained in:
mindesbunister
2025-10-28 12:08:18 +01:00
parent e8a9b68fa7
commit 715fa8bd11

821
README.md
View File

@@ -1,6 +1,6 @@
# Trading Bot v4 🚀 # Trading Bot v4 🚀
**Fully Autonomous Trading Bot** for TradingView → n8n → Drift Protocol (Solana) **Fully Autonomous Trading Bot** with Dual-Layer Redundancy for TradingView → n8n → Drift Protocol (Solana)
## Status ## Status
@@ -9,23 +9,54 @@
| Phase 1 | ✅ **COMPLETE** | Trade execution from TradingView signals | | Phase 1 | ✅ **COMPLETE** | Trade execution from TradingView signals |
| Phase 2 | ✅ **COMPLETE** | Real-time monitoring & automatic exits | | Phase 2 | ✅ **COMPLETE** | Real-time monitoring & automatic exits |
| Phase 3 | ✅ **COMPLETE** | Web UI, settings management, Docker deployment | | Phase 3 | ✅ **COMPLETE** | Web UI, settings management, Docker deployment |
| Phase 4 | ✅ **COMPLETE** | Database integration, analytics, race condition fixes |
## What It Does ## What It Does
1. **Receives signals** from TradingView (5-minute chart) 1. **Receives signals** from TradingView (5-minute OR 15-minute charts)
2. **Executes trades** on Drift Protocol (Solana DEX) 2. **Executes trades** on Drift Protocol (Solana DEX) with dual stop-loss system
3. **Monitors prices** in real-time via Pyth Network 3. **Monitors positions** every 2 seconds via Pyth Network WebSocket + HTTP fallback
4. **Closes positions** automatically at TP1/TP2/SL 4. **Closes positions** automatically at TP1 (partial) / TP2 (80%) / SL (100%)
5. **Adjusts stops** dynamically (breakeven, profit lock) 5. **Adjusts stops** dynamically (breakeven at +0.5%, profit lock at +1.2%)
6. **Provides web UI** for configuration and monitoring 6. **Tracks everything** in PostgreSQL (trades, prices, P&L, win rate)
7. **Provides web UI** for configuration, monitoring, and analytics
**100% autonomous. No manual intervention required!** **100% autonomous. Dual-layer safety. No manual intervention required!**
## Architecture: Dual-Layer Redundancy
**Key Design Principle:** Every trade has **TWO independent exit mechanisms**:
1. **On-Chain Orders (Drift Protocol)** - Primary layer
- TP1/TP2 as LIMIT orders
- Soft SL as TRIGGER_LIMIT (-1.5%, avoids wicks)
- Hard SL as TRIGGER_MARKET (-2.5%, guarantees exit)
2. **Software Monitoring (Position Manager)** - Backup layer
- Checks prices every 2 seconds
- Closes via MARKET orders if on-chain orders fail
- Dynamic SL adjustments
- Emergency stop functionality
**Why?** If Drift orders don't fill (low liquidity, network issues), Position Manager acts as backup. Both write to the same PostgreSQL database for complete trade history.
## Quick Start (Docker) ## Quick Start (Docker)
### 1. Deploy with Docker Compose ### 1. Prerequisites
- Docker & Docker Compose installed
- Solana wallet with Drift Protocol account
- Helius RPC API key (mainnet)
- TradingView alerts → n8n webhook setup
### 2. Deploy with Docker Compose
```bash ```bash
# Build and start # Clone and setup
cd /home/icke/traderv4
# Configure .env file (copy from .env.example)
nano .env
# Build and start all services
docker compose up -d docker compose up -d
# View logs # View logs
@@ -35,20 +66,27 @@ docker compose logs -f trading-bot
docker compose down docker compose down
``` ```
### 2. Access Web Interface ### 3. Access Web Interface
- **Settings UI:** `http://YOUR_HOST:3001/settings` - **Settings UI:** `http://YOUR_HOST:3001/settings`
- **Analytics:** `http://YOUR_HOST:3001/analytics`
- **API Endpoints:** `http://YOUR_HOST:3001/api/` - **API Endpoints:** `http://YOUR_HOST:3001/api/`
### 3. Configure Settings ### 4. Configure Settings
Open `http://YOUR_HOST:3001/settings` in your browser to: Open `http://YOUR_HOST:3001/settings` in your browser to:
- Adjust position size and leverage - Adjust position size ($10-$10,000) and leverage (1x-20x)
- Set stop-loss and take-profit levels - Set stop-loss (-1.5% soft, -2.5% hard) and take-profit levels
- Configure dynamic stop-loss triggers - Configure dynamic stop-loss (breakeven +0.5%, profit lock +1.2%)
- Set daily loss limits - Set daily loss limits and max trades per hour
- Toggle DRY_RUN mode - Toggle DRY_RUN mode for paper trading
### 4. Setup n8n Workflow After saving, click **"Restart Bot"** to apply changes.
Import `n8n-complete-workflow.json` into your n8n instance and configure TradingView alerts.
### 5. Setup n8n Workflow
Import `workflows/trading/Money_Machine.json` into your n8n instance:
- Configure TradingView webhook URL
- Set timeframe filters (5min and/or 15min)
- Add API authentication header
- Test with manual execution
## Alternative: Manual Setup ## Alternative: Manual Setup
@@ -81,31 +119,159 @@ npm start
--- ---
## Features ## Core Features
### Phase 1: Trade Execution ✅ ### Dual Stop-Loss System
- Drift Protocol integration - **Soft Stop** (TRIGGER_LIMIT): -1.5% from entry, avoids wick-outs
- Market order execution - **Hard Stop** (TRIGGER_MARKET): -2.5% from entry, guarantees exit
- TradingView signal normalization - Both placed on-chain as reduce-only orders
- n8n webhook endpoint - Position Manager monitors as backup (closes via MARKET if needed)
- Risk validation API
### Phase 2: Autonomous Trading ✅ ### Dynamic Stop-Loss Adjustments
- **Pyth price monitoring** (WebSocket + polling) - **Breakeven**: Moves SL to +0.01% when price hits +0.5%
- **Position manager** (tracks all trades) - **Profit Lock**: Locks in profit when price hits +1.2%
- **Automatic exits** (TP1/TP2/SL/Emergency) - **Reduces risk** while letting winners run
- **Dynamic SL** (breakeven + profit lock)
- **Multi-position** support
- **Real-time P&L** tracking
### Phase 3: Production Ready ✅ ### Take-Profit Strategy
- **Web UI** for settings management - **TP1** (default +0.7%): Closes 50% of position, moves SL to breakeven
- **Docker deployment** with multi-stage builds - **TP2** (default +1.5%): Closes 80% of remaining position
- **REST API** for all operations - **Runner**: 20% remains open if takeProfit2SizePercent < 100%
- **Risk calculator** with live preview
- **Settings persistence** to .env file
- **PostgreSQL** integration ready
### Position Manager (Singleton)
- Monitors all positions every 2 seconds
- Singleton pattern: Use `getPositionManager()` - never instantiate directly
- Tracks price updates in database
- Closes positions when targets hit
- Cancels orphaned orders automatically
- Acts as backup if on-chain orders don't fill
### Database Integration (PostgreSQL + Prisma)
**Models:**
- `Trade`: Complete trade history with entry/exit data
- `PriceUpdate`: Price movements every 2 seconds during monitoring
- `SystemEvent`: Errors, restarts, important events
- `DailyStats`: Win rate, profit factor, avg win/loss
**Analytics:**
- Real-time P&L tracking
- Win rate and profit factor
- Best/worst trades
- Drawdown monitoring
### Configuration System (Three-Layer Merge)
1. **Defaults** (`config/trading.ts` - DEFAULT_TRADING_CONFIG)
2. **Environment** (`.env` file via `getConfigFromEnv()`)
3. **Runtime** (API overrides via `getMergedConfig(overrides)`)
Always use `getMergedConfig()` in business logic - never read env vars directly.
### Safety Features
- **Reduce-only orders**: All TP/SL orders can only close, not open positions
- **Account health checks**: Validates margin before every trade
- **Risk validation**: `/api/trading/check-risk` endpoint
- **Daily loss limits**: Stops trading after max loss reached
- **Cooldown periods**: Prevents over-trading
- **DRY_RUN mode**: Paper trading for testing
---
## How It Works: Complete Trade Flow
### 1. Signal Reception (TradingView → n8n)
```
TradingView Alert: "LONG SOLUSDT .P 15"
n8n Webhook receives signal
Parse Signal node extracts:
- Symbol: SOLUSDT → SOL-PERP (normalized)
- Direction: long
- Timeframe: 15 (from .P 15)
Timeframe Filter: Allow 5 or 15 minutes only
Check Risk: Validate position limits, daily loss, etc.
```
### 2. Trade Execution (n8n → Next.js API → Drift)
```
POST /api/trading/execute
getMergedConfig() - Get current settings
initializeDriftService() - Connect to Drift SDK
Check account health (margin requirements)
openPosition() - Execute MARKET order
Calculate dual stop prices (soft -1.5%, hard -2.5%)
placeExitOrders() - Place on-chain TP/SL orders
├─ TP1: LIMIT reduce-only at +0.7%
├─ TP2: LIMIT reduce-only at +1.5%
├─ Soft SL: TRIGGER_LIMIT reduce-only at -1.5%
└─ Hard SL: TRIGGER_MARKET reduce-only at -2.5%
createTrade() - Save to PostgreSQL database
positionManager.addTrade() - Start monitoring loop
```
### 3. Position Monitoring (Every 2 Seconds)
```
Position Manager Loop:
getPythPriceMonitor().getLatestPrice()
Calculate current P&L and percentage gain/loss
Check TP1 hit? → closePosition(75%) + move SL to breakeven
Check TP2 hit? → closePosition(80% of remaining)
Check SL hit? → closePosition(100%)
Check dynamic adjustments:
├─ Price > +0.5%? → Move SL to breakeven (+0.01%)
└─ Price > +1.2%? → Lock profit (move SL to +X%)
addPriceUpdate() - Save price to database
Repeat every 2 seconds until position closed
```
### 4. Position Exit (Automatic)
```
Exit Triggered (TP/SL hit):
If closed by on-chain order:
├─ Position Manager detects position.size === 0
├─ Determines exit reason (TP1/TP2/SL from price)
├─ updateTradeExit() - Save exit data to database
└─ removeTrade() - Stop monitoring + cancel orphaned orders
If closed by Position Manager:
├─ closePosition() - Execute MARKET order
├─ cancelAllOrders() - Cancel remaining on-chain orders
├─ updateTradeExit() - Save exit data to database
└─ removeTrade() - Stop monitoring
```
### 5. Order Cleanup (Automatic)
```
When position closes (100%):
cancelAllOrders(symbol) - Query all open orders
Filter by marketIndex and status === 0 (Open)
driftClient.cancelOrders() - Cancel on Drift
Logs: "Cancelled X orders" or "Cancelled X orphaned orders"
```
**Result:** Clean exit with no orphaned orders, complete trade history in database, ready for next signal.
--- ---
## Web Interface ## Web Interface
@@ -118,13 +284,13 @@ Beautiful web interface for managing all trading parameters:
- Set leverage (1x-20x) - Set leverage (1x-20x)
**Risk Management:** **Risk Management:**
- Stop-loss percentage - Stop-loss percentage (soft -1.5%, hard -2.5%)
- Take-profit 1 & 2 levels - Take-profit 1 & 2 levels
- Emergency stop level - Emergency stop level
**Dynamic Stop-Loss:** **Dynamic Stop-Loss:**
- Breakeven trigger - Breakeven trigger (+0.5%)
- Profit lock trigger and amount - Profit lock trigger and amount (+1.2%)
**Safety Limits:** **Safety Limits:**
- Max daily loss - Max daily loss
@@ -140,30 +306,48 @@ Beautiful web interface for managing all trading parameters:
- TP1 and TP2 gains - TP1 and TP2 gains
- Risk/Reward ratio - Risk/Reward ratio
### Analytics Page (`/analytics`)
Real-time trading performance dashboard:
- Current open positions with live P&L
- Trade history with detailed entry/exit data
- Win rate and profit factor
- Total P&L (daily, weekly, monthly)
- Best and worst trades
- Drawdown tracking
### API Endpoints ### API Endpoints
All endpoints require `Authorization: Bearer YOUR_API_SECRET_KEY` All endpoints require `Authorization: Bearer YOUR_API_SECRET_KEY` (except `/api/trading/test`)
**Trade Execution:** **Trade Execution:**
```bash ```bash
# Execute a trade # Execute a trade (production - from n8n)
POST /api/trading/execute POST /api/trading/execute
{ {
"symbol": "SOL-PERP", "symbol": "SOL-PERP",
"direction": "long", "direction": "long",
"timeframe": "5", "timeframe": "15",
"signalStrength": "strong" "signalStrength": "strong"
} }
# Close a position # Test trade (no auth required - from settings UI)
POST /api/trading/test
{
"symbol": "SOL-PERP",
"direction": "long",
"timeframe": "15"
}
# Close a position (partial or full)
POST /api/trading/close POST /api/trading/close
{ {
"symbol": "SOL-PERP", "symbol": "SOL-PERP",
"percentToClose": 100 "percentToClose": 100 // or 50, 75, etc.
} }
# Get active positions # Get active positions
GET /api/trading/positions GET /api/trading/positions
# Returns: { positions: [...], monitoring: [...] }
# Validate trade (risk check) # Validate trade (risk check)
POST /api/trading/check-risk POST /api/trading/check-risk
@@ -178,69 +362,118 @@ POST /api/trading/check-risk
# Get current settings # Get current settings
GET /api/settings GET /api/settings
# Update settings # Update settings (writes to .env file)
POST /api/settings POST /api/settings
{ {
"MAX_POSITION_SIZE_USD": 100, "MAX_POSITION_SIZE_USD": 100,
"LEVERAGE": 10, "LEVERAGE": 10,
"STOP_LOSS_PERCENT": -1.5, "STOP_LOSS_PERCENT": -1.5,
... "SOFT_STOP_LOSS_PERCENT": -1.5,
"HARD_STOP_LOSS_PERCENT": -2.5,
"TAKE_PROFIT_1_PERCENT": 0.7,
"TAKE_PROFIT_2_PERCENT": 1.5,
"TAKE_PROFIT_2_SIZE_PERCENT": 80,
"BREAKEVEN_TRIGGER_PERCENT": 0.5,
"PROFIT_LOCK_TRIGGER_PERCENT": 1.2,
"DRY_RUN": false
} }
# Restart bot container (apply settings) # Restart bot container (apply settings)
POST /api/restart POST /api/restart
# Creates /tmp/trading-bot-restart.flag
# watch-restart.sh detects flag and runs: docker restart trading-bot-v4
``` ```
**Notes:** **Analytics:**
- Settings changes require container restart to take effect ```bash
- Use the web UI's "Restart Bot" button or call `/api/restart` # Get trade statistics
- Restart watcher must be running (see setup below) GET /api/analytics/stats
# Returns: { winRate, profitFactor, totalTrades, totalPnL, ... }
# Update settings # Get recent trades
POST /api/settings GET /api/analytics/positions
{ # Returns: { openPositions: [...], recentTrades: [...] }
"MAX_POSITION_SIZE_USD": 100,
"LEVERAGE": 5,
"STOP_LOSS_PERCENT": -1.5,
...
}
``` ```
**Symbol Normalization:**
- TradingView sends: `SOLUSDT`, `BTCUSDT`, `ETHUSDT`
- Bot converts to: `SOL-PERP`, `BTC-PERP`, `ETH-PERP`
- Always use Drift format in API calls
---
--- ---
## Docker Deployment ## Docker Deployment
### Architecture ### Architecture
- **Multi-stage build** for optimized image size - **Multi-stage build**: deps → builder → runner (Node 20 Alpine)
- **Next.js standalone** output for production - **Next.js standalone** output for production (~400MB image)
- **PostgreSQL** for trade history - **PostgreSQL 16-alpine** for trade history
- **Isolated network** (172.28.0.0/16) - **Isolated network** (172.28.0.0/16)
- **Health monitoring** and logging - **Health monitoring** and logging
### Container Details ### Container Details
- **Port:** 3001 (external) → 3000 (internal) - **trading-bot-v4**: Main application
- **Image:** Node 20 Alpine - Port: 3001 (external) → 3000 (internal)
- **Size:** ~400MB (optimized) - Restart: unless-stopped
- **Restart:** unless-stopped - Volumes: .env file mounted
- **trading-bot-postgres**: Database
- Port: 5432 (internal only)
- Persistent volume: trading-bot-postgres-data
- Auto-backup recommended
### Critical Build Steps
1. Install deps: `npm install --production`
2. Copy source and generate Prisma client: `npx prisma generate`
3. Build Next.js: `npm run build` (standalone mode)
4. Runner stage: Copy standalone + static + node_modules + Prisma client
**Why Prisma generate before build?** The Trade type from Prisma must exist before Next.js compiles TypeScript.
### Commands ### Commands
```bash ```bash
# Build image # Build and deploy
docker compose build trading-bot docker compose build trading-bot
# Start services
docker compose up -d docker compose up -d
# View logs # View logs (real-time)
docker compose logs -f trading-bot docker compose logs -f trading-bot
# View logs (last 100 lines)
docker compose logs --tail=100 trading-bot
# Restart after config changes # Restart after config changes
docker compose restart trading-bot docker compose restart trading-bot
# Rebuild and restart (force recreate)
docker compose up -d --force-recreate trading-bot
# Stop everything # Stop everything
docker compose down docker compose down
# Stop and remove volumes (WARNING: deletes database)
docker compose down -v
``` ```
### Database Operations
```bash
# Connect to database
docker exec -it trading-bot-postgres psql -U postgres -d trading_bot_v4
# Run migrations from host
DATABASE_URL="postgresql://postgres:postgres@localhost:5432/trading_bot_v4" npx prisma migrate dev
# Generate Prisma client
npx prisma generate
# View tables
docker exec trading-bot-postgres psql -U postgres -d trading_bot_v4 -c "\dt"
```
**DATABASE_URL caveat:** Use `trading-bot-postgres` (container name) in .env for runtime, but `localhost:5432` for Prisma CLI migrations from host.
### Restart Watcher (Required for Web UI Restart Button) ### Restart Watcher (Required for Web UI Restart Button)
The restart watcher monitors for restart requests from the web UI: The restart watcher monitors for restart requests from the web UI:
@@ -262,15 +495,54 @@ sudo systemctl status trading-bot-restart-watcher
The watcher enables the "Restart Bot" button in the web UI to automatically restart the container when settings are changed. The watcher enables the "Restart Bot" button in the web UI to automatically restart the container when settings are changed.
### Environment Variables ### Environment Variables
All settings are configured via `.env` file: All settings configured via `.env` file:
- Drift wallet credentials
- Solana RPC endpoint (Helius recommended) **Required:**
- Trading parameters (size, leverage, SL, TP) - `DRIFT_WALLET_PRIVATE_KEY`: Solana wallet (JSON array or base58 string)
- Risk limits and safety controls - `SOLANA_RPC_URL`: Helius RPC endpoint (mainnet recommended)
- API authentication key - `API_SECRET_KEY`: Random secret for API authentication
- `DATABASE_URL`: PostgreSQL connection string
**Trading Parameters:**
- `MAX_POSITION_SIZE_USD`: Position size in USD
- `LEVERAGE`: Leverage multiplier (1-20x)
- `STOP_LOSS_PERCENT`: Soft stop percentage (e.g., -1.5)
- `HARD_STOP_LOSS_PERCENT`: Hard stop percentage (e.g., -2.5)
- `TAKE_PROFIT_1_PERCENT`: TP1 target (e.g., 0.7)
- `TAKE_PROFIT_2_PERCENT`: TP2 target (e.g., 1.5)
- `TAKE_PROFIT_2_SIZE_PERCENT`: How much to close at TP2 (e.g., 80)
**Dynamic Stop-Loss:**
- `BREAKEVEN_TRIGGER_PERCENT`: Move to breakeven at (e.g., 0.5)
- `PROFIT_LOCK_TRIGGER_PERCENT`: Lock profit at (e.g., 1.2)
- `PROFIT_LOCK_AMOUNT_PERCENT`: Profit to lock (e.g., 0.5)
**Safety:**
- `MAX_DAILY_LOSS`: Max loss per day in USD
- `MAX_TRADES_PER_HOUR`: Rate limiting
- `TRADE_COOLDOWN_MINUTES`: Cooldown between trades
- `DRY_RUN`: Enable paper trading (true/false)
- `USE_DUAL_STOPS`: Enable dual stop system (true/false)
Changes to `.env` require container restart to take effect. Changes to `.env` require container restart to take effect.
### Singleton Services (Critical Pattern)
**Never create multiple instances** - always use getter functions:
```typescript
// Drift Client
const driftService = await initializeDriftService() // NOT: new DriftService()
const driftService = getDriftService() // After init
// Position Manager
const positionManager = getPositionManager() // NOT: new PositionManager()
// Database
const prisma = getPrismaClient() // NOT: new PrismaClient()
```
Creating multiple instances causes connection issues and state inconsistencies.
--- ---
## File Structure ## File Structure
@@ -280,66 +552,93 @@ traderv4/
├── README.md ← You are here ├── README.md ← You are here
├── docker-compose.yml ← Docker orchestration ├── docker-compose.yml ← Docker orchestration
├── Dockerfile ← Multi-stage build ├── Dockerfile ← Multi-stage build
├── .env ← Configuration (template) ├── .env ← Configuration (create from .env.example)
├── package.json ← Dependencies ├── package.json ← Dependencies (Next.js 15, Drift SDK, Prisma)
├── next.config.js ← Next.js config (standalone output)
├── tsconfig.json ← TypeScript config
├── docs/Documentation ├── app/ Next.js 15 App Router
│ ├── setup/ │ ├── layout.tsx ← Root layout with Tailwind
│ ├── DOCKER.mdDocker deployment guide │ ├── page.tsx Home page
│ ├── SETUP.mdSetup instructions │ ├── globals.css Global styles
│ │ ├── SETTINGS_SETUP.md ← Settings guide
│ │ ├── TELEGRAM_BOT_README.md ← Telegram bot guide
│ │ ├── N8N_WORKFLOW_SETUP.md ← n8n workflow setup
│ │ └── N8N_DATABASE_SETUP.md ← n8n database setup
│ ├── guides/
│ │ ├── TESTING.md ← Testing guide
│ │ ├── N8N_WORKFLOW_GUIDE.md ← n8n usage guide
│ │ └── WORKFLOW_VERIFICATION.md ← Workflow testing
│ └── history/
│ ├── PHASE_1_COMPLETE.md ← Phase 1 completion
│ ├── PHASE_2_COMPLETE.md ← Phase 2 completion
│ └── ... ← Development history
├── workflows/ ← n8n workflow files
│ ├── trading/ ← Main trading workflows
│ ├── analytics/ ← Analytics workflows
│ └── telegram/ ← Telegram bot workflows
├── scripts/ ← Utility scripts
│ ├── docker/ ← Docker helpers
│ ├── setup/ ← Setup scripts
│ └── testing/ ← Test scripts
├── tests/ ← Test files
├── app/
│ ├── layout.tsx ← Root layout
│ ├── globals.css ← Tailwind styles
│ ├── settings/ │ ├── settings/
│ │ └── page.tsx ← Settings UI │ │ └── page.tsx ← Settings UI
│ ├── analytics/
│ │ └── page.tsx ← Analytics dashboard
│ └── api/ │ └── api/
│ ├── settings/ │ ├── settings/
│ │ └── route.ts ← Settings API │ │ └── route.ts ← GET/POST settings, writes to .env
│ ├── restart/
│ │ └── route.ts ← Creates restart flag file
│ ├── analytics/
│ │ ├── stats/route.ts ← Trade statistics
│ │ └── positions/route.ts ← Open/recent positions
│ └── trading/ │ └── trading/
│ ├── execute/route.ts ← Execute trades │ ├── execute/route.ts ← Main execution (production)
│ ├── test/route.ts ← Test execution (UI)
│ ├── close/route.ts ← Close positions │ ├── close/route.ts ← Close positions
│ ├── positions/route.ts ← Query positions │ ├── positions/route.ts ← Query positions
── check-risk/route.ts ← Risk validation ── check-risk/route.ts ← Risk validation
│ └── remove-position/route.ts ← Remove from monitoring
├── lib/ ├── lib/ ← Business logic
│ ├── drift/ │ ├── drift/
│ │ ├── client.ts ← Drift SDK wrapper │ │ ├── client.ts ← Drift SDK wrapper (singleton)
│ │ └── orders.ts ← Order execution │ │ └── orders.ts ← Order execution & cancellation
│ ├── pyth/ │ ├── pyth/
│ │ └── price-monitor.ts ← Real-time prices │ │ └── price-monitor.ts ← WebSocket + HTTP fallback
── trading/ ── trading/
└── position-manager.ts ← Auto-exit logic └── position-manager.ts ← Monitoring loop (singleton)
│ ├── database/
│ │ ├── trades.ts ← Trade CRUD operations
│ │ └── views.ts ← Analytics queries
│ └── notifications/
│ └── telegram.ts ← Telegram alerts (optional)
├── config/ ├── config/
│ └── trading.ts ← Market configurations │ └── trading.ts ← Market configs & defaults
├── prisma/ ├── prisma/
── schema.prisma ← Database schema ── schema.prisma ← Database models
│ └── migrations/ ← Migration history
│ ├── 20251026200052_init/
│ └── 20251027080947_add_test_trade_flag/
├── workflows/ ← n8n workflow JSON files
│ ├── trading/
│ │ └── Money_Machine.json ← Main trading workflow
│ ├── analytics/
│ │ ├── n8n-daily-report.json
│ │ ├── n8n-database-analytics.json
│ │ └── n8n-stop-loss-analysis.json
│ └── telegram/
│ └── telegram-webhook-FINAL.json
├── scripts/ ← Utility scripts
│ ├── docker-build.sh
│ ├── docker-start.sh
│ ├── docker-stop.sh
│ ├── docker-logs.sh
│ ├── watch-restart.sh ← Restart watcher daemon
│ ├── send_trade.sh ← Test trade execution
│ └── test-exit-orders.sh ← Test exit order placement
├── tests/ ← Test files
│ ├── test-drift-v4.ts
│ ├── test-full-flow.ts
│ ├── test-position-manager.ts
│ └── test-price-monitor.ts
├── docs/ ← Documentation
│ ├── SETUP.md ← Detailed setup guide
│ ├── DOCKER.md ← Docker deployment
│ ├── TESTING.md ← Testing guide
│ ├── TELEGRAM_BOT_README.md ← Telegram setup
│ ├── N8N_WORKFLOW_SETUP.md ← n8n configuration
│ ├── PHASE_2_COMPLETE.md ← Phase 2 features
│ └── QUICKREF_PHASE2.md ← Quick reference
└── logs/ ← Log files (created at runtime)
``` ```
--- ---
@@ -359,42 +658,239 @@ traderv4/
--- ---
## Trade Example ## Trade Example (Real-World Flow)
### Entry Signal ### Entry Signal from TradingView
``` ```
TradingView: LONG SOL @ $140.00 Alert Message: "LONG SOLUSDT .P 15"
Position: $1,000 (10x = $10,000)
SL: $137.90 (-1.5%) n8n receives webhook
TP1: $140.98 (+0.7%)
TP2: $142.10 (+1.5%) Parse: symbol=SOL-PERP, direction=long, timeframe=15
Timeframe check: 15 minutes ✅ (allowed)
Risk check: Daily loss OK, no existing position ✅
Execute trade via API
``` ```
### TP1 Hit ### Position Opened
``` ```
✅ Price reaches $140.98 Symbol: SOL-PERP
→ Auto-close 50% (+$70) Direction: LONG
→ Move SL to $140.21 (breakeven) Entry: $200.00
→ Trade is now RISK-FREE Position Size: $100 (10x leverage = $1,000 notional)
On-Chain Orders Placed:
├─ TP1: LIMIT at $201.40 (+0.7%) - Close 50%
├─ TP2: LIMIT at $203.00 (+1.5%) - Close 80% of remaining
├─ Soft SL: TRIGGER_LIMIT at $197.00 (-1.5%)
└─ Hard SL: TRIGGER_MARKET at $195.00 (-2.5%)
Position Manager: ✅ Monitoring started (every 2s)
Database: ✅ Trade #601 saved
``` ```
### TP2 Hit ### TP1 Hit (First Target)
``` ```
Price reaches $142.10 Price reaches $201.40
→ Auto-close remaining 50% (+$150)
→ Total P&L: +$220 (+22% account) On-chain TP1 order fills → 50% closed
→ Trade complete!
Position Manager detects partial close:
├─ Profit: +$7.00 (+7% account)
├─ Remaining: 50% ($500 notional)
├─ Move SL to breakeven: $200.02 (+0.01%)
└─ Trade is now RISK-FREE ✅
Database updated: exitReason=TP1_PARTIAL
```
### Price Continues Higher
```
Price reaches $202.44 (+1.22%)
Position Manager dynamic adjustment:
├─ Trigger: +1.2% profit lock activated
├─ Move SL to: $201.00 (+0.5% profit locked)
└─ Letting winner run with locked profit ✅
```
### TP2 Hit (Second Target)
```
Price reaches $203.00
On-chain TP2 order fills → 80% of remaining closed (40% of original)
Position Manager detects:
├─ Profit from TP2: +$6.00
├─ Remaining: 10% runner ($100 notional)
└─ Runner continues with locked profit SL
Database updated: exitReason=TP2_PARTIAL
```
### Final Exit (Runner)
```
Option 1: Runner hits new high → Manual/trailing stop
Option 2: Price pulls back → Locked profit SL hits at $201.00
Option 3: Emergency stop or manual close
Total P&L:
├─ TP1: +$7.00 (50% at +0.7%)
├─ TP2: +$6.00 (40% at +1.5%)
└─ Runner: +$3.00 (10% at +3.0%, closed at pullback)
═══════════════════
Total: +$16.00 (+16% account growth)
Database: ✅ Trade #601 complete
```
### If Stop-Loss Hit Instead
```
Price drops to $197.00
Soft SL (TRIGGER_LIMIT) activates:
├─ Triggers at $197.00
├─ Limit order at $196.95 (avoid wick)
└─ If fills → Position closed ✅
If soft SL doesn't fill (low liquidity):
├─ Price drops to $195.00
├─ Hard SL (TRIGGER_MARKET) activates
└─ Market order guarantees exit ✅
Position Manager backup:
├─ Detects position still open at -2.5%
└─ Closes via MARKET order if needed
Loss: -$25.00 (-2.5% account)
Database: ✅ exitReason=STOP_LOSS
```
**Key Points:**
- Dual stop system ensures exit even in volatile markets
- Position Manager acts as backup to on-chain orders
- Dynamic SL makes trades risk-free after +0.5%
- Profit lock captures gains before reversals
- Complete audit trail in database
---
## Common Issues & Solutions
### "Drift service not initialized"
**Cause:** Drift client not connected before trade execution
**Solution:** Ensure `initializeDriftService()` called before operations
### "Position not found in monitoring"
**Cause:** Race condition - orders placed after Position Manager started
**Solution:** ✅ FIXED - Orders now placed before monitoring starts
### "Orphaned orders after exit"
**Cause:** Old bug - Position Manager detected closure before orders existed
**Solution:** ✅ FIXED - Order placement sequencing corrected
**Cleanup:** Cancel manually on Drift UI or wait for next trade's auto-cleanup
### "TP2 closes entire position instead of 80%"
**Cause:** Old bug - TP2 calculated from original position instead of remaining
**Solution:** ✅ FIXED - TP2 now calculates from remaining after TP1
### "Database save failed but trade executed"
**Cause:** PostgreSQL connection issue or schema mismatch
**Solution:** Trade still executes successfully, check database logs and fix connection
### "Prisma Client not generated" (Docker build)
**Cause:** `npx prisma generate` not run before `npm run build`
**Solution:** Ensure Dockerfile runs Prisma generate in builder stage
### "Wrong DATABASE_URL" (localhost vs container)
**Container runtime:** Use `trading-bot-postgres:5432` in .env
**Prisma CLI (host):** Use `localhost:5432` for migrations
**Solution:** Maintain two DATABASE_URL values for different contexts
### Container won't restart after settings change
**Cause:** Restart watcher not running
**Solution:**
```bash
sudo systemctl status trading-bot-restart-watcher
sudo systemctl start trading-bot-restart-watcher
``` ```
--- ---
## Safety Guidelines ## Safety Guidelines
1. **Start Small**: Use $10-50 positions first 1. **Start Small**: Use $10-50 positions for first 20 trades
2. **Test Thoroughly**: Run all test scripts 2. **Test Thoroughly**:
3. **Monitor Closely**: Watch first 10 auto-exits - Run with DRY_RUN=true first
4. **Verify Fills**: Check Drift UI after exits - Execute test trades from settings UI
5. **Scale Gradually**: Increase size weekly - Verify all exits work correctly
3. **Monitor Closely**: Watch first 10 auto-exits in real-time
4. **Verify Database**: Check that all trades are being saved correctly
5. **Check Drift UI**: Confirm positions and orders match expectations
6. **Scale Gradually**: Increase position size 2x per week maximum
7. **Daily Review**: Check analytics page every day
8. **Backup Database**: Export PostgreSQL data weekly
**Risk Warning:** Cryptocurrency trading involves substantial risk. This bot executes trades automatically. Start small and never risk more than you can afford to lose.
---
## Testing Commands
```bash
# Local development
npm run dev
# Build production
npm run build && npm start
# Docker build and restart
docker compose build trading-bot
docker compose up -d --force-recreate trading-bot
docker logs -f trading-bot-v4
# Test trade from UI
# Go to http://localhost:3001/settings
# Click "Test LONG" or "Test SHORT"
# Test trade from terminal
./send_trade.sh LONG SOL-PERP 15
# Check current positions
curl -s -X GET http://localhost:3001/api/trading/positions \
-H "Authorization: Bearer YOUR_API_SECRET_KEY" | jq
# Test exit order placement
./test-exit-orders.sh
# Database operations
npx prisma generate
DATABASE_URL="postgresql://postgres:postgres@localhost:5432/trading_bot_v4" npx prisma migrate dev
docker exec trading-bot-postgres psql -U postgres -d trading_bot_v4 -c "SELECT * FROM \"Trade\" ORDER BY \"createdAt\" DESC LIMIT 5;"
# Check logs
docker compose logs --tail=100 trading-bot
docker compose logs -f trading-bot | grep "Position Manager"
```
---
## Documentation
| Document | Purpose |
|----------|---------|
| `README.md` | Complete system overview (this file) |
| `docs/SETUP.md` | Detailed setup instructions |
| `docs/DOCKER.md` | Docker deployment guide |
| `docs/TESTING.md` | Comprehensive testing guide |
| `docs/TELEGRAM_BOT_README.md` | Telegram bot setup |
| `docs/N8N_WORKFLOW_SETUP.md` | n8n workflow configuration |
| `docs/PHASE_2_COMPLETE.md` | Phase 2 features and architecture |
| `docs/QUICKREF_PHASE2.md` | Quick reference guide |
| `.github/copilot-instructions.md` | AI agent instructions (architecture) |
--- ---
@@ -402,11 +898,38 @@ TP2: $142.10 (+1.5%)
- **Drift Protocol**: https://drift.trade - **Drift Protocol**: https://drift.trade
- **Drift Docs**: https://docs.drift.trade - **Drift Docs**: https://docs.drift.trade
- **Drift SDK**: https://github.com/drift-labs/protocol-v2
- **Pyth Network**: https://pyth.network - **Pyth Network**: https://pyth.network
- **Solana RPC**: https://helius.dev - **Solana RPC**: https://helius.dev (recommended)
- **Next.js**: https://nextjs.org
- **Prisma ORM**: https://prisma.io
--- ---
**Ready to trade autonomously? Read `QUICKREF_PHASE2.md` to get started! 🚀** ## Development Notes
*Start small, monitor closely, scale gradually!* ### Key Patterns to Follow
1. **Singleton Services**: Always use getter functions, never instantiate directly
2. **Configuration**: Always use `getMergedConfig()`, never read env vars directly
3. **Database Errors**: Wrap in try/catch, don't fail trades on DB errors
4. **Price Calculations**: Direction matters - long vs short use opposite math
5. **Reduce-Only Orders**: All TP/SL orders MUST have `reduceOnly: true`
6. **Symbol Normalization**: Always use `normalizeTradingViewSymbol()`
### Adding New Features
1. **New Config**: Update DEFAULT_TRADING_CONFIG + getConfigFromEnv() + .env
2. **New Database Fields**: Update schema.prisma → migrate → regenerate → rebuild Docker
3. **New API Endpoint**: Follow auth pattern, use getMergedConfig(), init services
4. **Order Logic Changes**: Test with DRY_RUN=true first, use small positions
### Recent Bug Fixes (Oct 2024)
- ✅ TP2 runner calculation: Now uses remaining position after TP1
- ✅ Race condition: Exit orders now placed BEFORE monitoring starts
- ✅ Order cancellation: removeTrade() properly cancels orphaned orders
- ✅ Dynamic SL: Breakeven at +0.5%, profit lock at +1.2%
---
**Ready to trade autonomously? Start with `docs/SETUP.md` and test with DRY_RUN=true! 🚀**
*Dual-layer safety. Complete audit trail. Built for reliability.*