Files
trading_bot_v4/README.md
mindesbunister 17071fe7ec docs: Update minimum quality score from 60 to 81 across documentation
- Updated .github/copilot-instructions.md key constraints and signal quality system description
- Updated config/trading.ts minimum score from 60 to 81 with v8 performance rationale
- Updated SIGNAL_QUALITY_SETUP_GUIDE.md intro to reflect 81 threshold
- Updated SIGNAL_QUALITY_OPTIMIZATION_ROADMAP.md current system section
- Updated BLOCKED_SIGNALS_TRACKING.md quality score requirements

Context: After v8 Money Line indicator deployed with 0.6% flip threshold,
system achieving 66.7% win rate with average quality score 94.2. Raised
minimum threshold from 60 to 81 to maintain exceptional selectivity.

Current v8 stats: 6 trades, 4 wins, $649.32 profit, 94.2 avg quality
Account growth: $540 → $1,134.92 (110% gain in 2-3 days)
2025-11-21 15:49:26 +01:00

1035 lines
33 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Trading Bot v4 🚀
**Fully Autonomous Trading Bot** with Dual-Layer Redundancy for TradingView → n8n → Drift Protocol (Solana)
## 📊 Live Status
**Capital:** $97.55 USDC | **Target:** $2,500 (Phase 1) | **Leverage:** 15x (SOL)
**Win Rate:** 60%+ target | **Trades Executed:** 161 | **System:** ✅ Operational
### Development Status
| Phase | Status | Description |
|-------|--------|-------------|
| Phase 1-4 | ✅ **COMPLETE** | Core system: Execution, monitoring, UI, database |
| Phase 5 | 🔄 **IN PROGRESS** | Data collection & optimization (see below) |
## 🎯 Active Optimization Initiatives
Three parallel data-driven improvements targeting **35-40% P&L increase** over 3 months:
### 1. Signal Quality Optimization (🔜 2-3 weeks)
Filter bad trades BEFORE entry by optimizing quality thresholds
```
Progress: [▓░░░░░░░░░] 0/20 blocked signals collected (0%)
Status: Phase 1 - Data Collection
Impact: +5% win rate expected (60% → 65%)
```
### 2. Position Scaling & Exit Strategy (🔜 3-4 weeks)
Optimize HOW MUCH to close at each target based on signal quality
```
Progress: [▓▓▓▓▓▓▓▓▓▓] 161/50 trades (322%) ✅ - Need v6 indicator data
Status: Phase 5 complete (TP2-as-runner), Phase 2-4 pending analysis
Impact: +15% average win size expected
```
### 3. ATR-Based Take Profit Levels (🔜 6-8 weeks)
Replace fixed % targets with volatility-adaptive ATR multipliers
```
Progress: [▓░░░░░░░░░] 1/50 trades with ATR (2%)
Status: Phase 1 - Data Collection
Impact: +10% total P&L expected (better hit rates in all conditions)
```
**📈 Combined Expected Impact:** 35-40% improvement → Phase 1 goal acceleration from 6-7 months to 4-5 months
📋 [**View Master Roadmap**](./OPTIMIZATION_MASTER_ROADMAP.md) for detailed timeline and implementation plan
## What It Does
1. **Receives signals** from TradingView (5-minute OR 15-minute charts)
2. **Executes trades** on Drift Protocol (Solana DEX) with dual stop-loss system
3. **Monitors positions** every 2 seconds via Pyth Network WebSocket + HTTP fallback
4. **Closes positions** automatically at TP1 (partial) / TP2 (80%) / SL (100%)
5. **Adjusts stops** dynamically (breakeven at +0.5%, profit lock at +1.2%)
6. **Tracks everything** in PostgreSQL (trades, prices, P&L, win rate)
7. **Provides web UI** for configuration, monitoring, and analytics
**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.
## 📈 The Money Line v8 Indicator
### How It Works (Simple Explanation)
The **Money Line** is a dynamic support/resistance indicator that adapts to market volatility. Think of it as a "safety zone" - price above = bullish, price below = bearish.
**The Core Concept:**
- **Green line** = Bulls in control, momentum up → Go LONG
- **Red line** = Bears in control, momentum down → Go SHORT
- **Line flip** = Power shift detected → Enter trade
### What Creates the Line
**1. ATR (Average True Range)**
- Measures how much the market moves on average
- Volatile markets → wider bands, calm markets → tighter bands
- Think: "How much wiggle room does price need?"
**2. The Multiplier**
- ATR × Multiplier = Distance from price to line
- v8 uses 3.8x for 5min charts (stickier than previous versions)
- Higher multiplier = line changes color less often
**3. HalfTrend Algorithm**
- Calculates upper band (resistance) and lower band (support)
- Price crosses above upper band → line turns GREEN (bullish)
- Price crosses below lower band → line turns RED (bearish)
- Line "sticks" to its color until price STRONGLY breaks the opposite band
### v8 Improvements (Anti-Whipsaw Protection)
**Flip Threshold (0.6%)**
- Price must move 0.6% beyond the line before it changes color
- Filters tiny bounces that don't mean anything
- Example: Line at $100 → price must hit $100.60 to flip bullish
**Entry Buffer (0.2 ATR)**
- Confirms the breakout is real, not just a wick
- Waits for price to close beyond line + buffer zone
- Prevents fake signals from sudden spikes
**Stickier Bands**
- Increased multipliers make the line "lazier" to flip
- Follows major trends, ignores minor corrections
### In Simple Terms
*"It's like a traffic light for trading:*
- *Green = Go long (buy)*
- *Red = Go short (sell)*
- *The line doesn't change until there's a REAL trend shift, filtering out fake moves.*
*It adapts to volatility automatically - in crazy markets it needs bigger moves to flip, in calm markets it's more sensitive. This keeps you trading WITH the flow, not against it."*
**Technical Name:** Modified HalfTrend Supertrend with ATR-based adaptive bands and flip threshold confirmation
**Street Name:** The Money Line 💰
### Indicator Versions
- **v6:** Filtered mode with ADX/volume/RSI confirmations (conservative)
- **v7:** Pure line flips (too noisy, deprecated)
- **v8:** Sticky trend with flip threshold + momentum confirmation (current)
All versions available in `workflows/trading/` directory.
## Quick Start (Docker)
### 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
# 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
# View logs
docker compose logs -f trading-bot
# Stop
docker compose down
```
### 3. Access Web Interface
- **Settings UI:** `http://YOUR_HOST:3001/settings`
- **Analytics:** `http://YOUR_HOST:3001/analytics`
- **API Endpoints:** `http://YOUR_HOST:3001/api/`
### 4. Configure Settings
Open `http://YOUR_HOST:3001/settings` in your browser to:
- Adjust position size ($10-$10,000) and leverage (1x-20x)
- Set stop-loss (-1.5% soft, -2.5% hard) and take-profit levels
- Configure dynamic stop-loss (breakeven +0.5%, profit lock +1.2%)
- Set daily loss limits and max trades per hour
- Toggle DRY_RUN mode for paper trading
After saving, click **"Restart Bot"** to apply changes.
### 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
### 1. Install Dependencies
```bash
npm install
```
### 2. Configure Environment
```bash
# Copy and edit .env
cp .env.example .env
# Required variables:
DRIFT_WALLET_PRIVATE_KEY=[your_wallet_array]
SOLANA_RPC_URL=https://mainnet.helius-rpc.com/?api-key=YOUR_KEY
API_SECRET_KEY=your_random_secret_key
DRY_RUN=false
```
### 3. Run
```bash
# Development
npm run dev
# Production
npm run build
npm start
```
---
## Core Features
### Dual Stop-Loss System
- **Soft Stop** (TRIGGER_LIMIT): -1.5% from entry, avoids wick-outs
- **Hard Stop** (TRIGGER_MARKET): -2.5% from entry, guarantees exit
- Both placed on-chain as reduce-only orders
- Position Manager monitors as backup (closes via MARKET if needed)
### Dynamic Stop-Loss Adjustments
- **Breakeven**: Moves SL to +0.01% when price hits +0.5%
- **Profit Lock**: Locks in profit when price hits +1.2%
- **Reduces risk** while letting winners run
### Take-Profit Strategy
- **TP1** (default +0.7%): Closes 50% of position, moves SL to breakeven
- **TP2** (default +1.5%): Closes 80% of remaining position
- **Runner**: 20% remains open if takeProfit2SizePercent < 100%
### 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
### Settings Page (`/settings`)
Beautiful web interface for managing all trading parameters:
**Position Sizing:**
- Adjust position size ($10-$10,000 USD)
- Set leverage (1x-20x)
**Risk Management:**
- Stop-loss percentage (soft -1.5%, hard -2.5%)
- Take-profit 1 & 2 levels
- Emergency stop level
**Dynamic Stop-Loss:**
- Breakeven trigger (+0.5%)
- Profit lock trigger and amount (+1.2%)
**Safety Limits:**
- Max daily loss
- Max trades per hour
- Cooldown between trades
**Execution:**
- Slippage tolerance
- DRY_RUN toggle for testing
**Live Risk Calculator:**
- Shows max loss in USD
- TP1 and TP2 gains
- 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
All endpoints require `Authorization: Bearer YOUR_API_SECRET_KEY` (except `/api/trading/test`)
**Trade Execution:**
```bash
# Execute a trade (production - from n8n)
POST /api/trading/execute
{
"symbol": "SOL-PERP",
"direction": "long",
"timeframe": "15",
"signalStrength": "strong"
}
# 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
{
"symbol": "SOL-PERP",
"percentToClose": 100 // or 50, 75, etc.
}
# Get active positions
GET /api/trading/positions
# Returns: { positions: [...], monitoring: [...] }
# Validate trade (risk check)
POST /api/trading/check-risk
{
"symbol": "SOL-PERP",
"direction": "long"
}
```
**Settings Management:**
```bash
# Get current settings
GET /api/settings
# Update settings (writes to .env file)
POST /api/settings
{
"MAX_POSITION_SIZE_USD": 100,
"LEVERAGE": 10,
"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)
POST /api/restart
# Creates /tmp/trading-bot-restart.flag
# watch-restart.sh detects flag and runs: docker restart trading-bot-v4
```
**Analytics:**
```bash
# Get trade statistics
GET /api/analytics/stats
# Returns: { winRate, profitFactor, totalTrades, totalPnL, ... }
# Get recent trades
GET /api/analytics/positions
# Returns: { openPositions: [...], recentTrades: [...] }
```
**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
### Architecture
- **Multi-stage build**: deps → builder → runner (Node 20 Alpine)
- **Next.js standalone** output for production (~400MB image)
- **PostgreSQL 16-alpine** for trade history
- **Isolated network** (172.28.0.0/16)
- **Health monitoring** and logging
### Container Details
- **trading-bot-v4**: Main application
- Port: 3001 (external) → 3000 (internal)
- 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
```bash
# Build and deploy
docker compose build trading-bot
docker compose up -d
# View logs (real-time)
docker compose logs -f trading-bot
# View logs (last 100 lines)
docker compose logs --tail=100 trading-bot
# Restart after config changes
docker compose restart trading-bot
# Rebuild and restart (force recreate)
docker compose up -d --force-recreate trading-bot
# Stop everything
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)
The restart watcher monitors for restart requests from the web UI:
```bash
# Start watcher manually
cd /home/icke/traderv4
nohup ./watch-restart.sh > logs/restart-watcher.log 2>&1 &
# OR install as systemd service (recommended)
sudo cp trading-bot-restart-watcher.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable trading-bot-restart-watcher
sudo systemctl start trading-bot-restart-watcher
# Check watcher status
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.
### Environment Variables
All settings configured via `.env` file:
**Required:**
- `DRIFT_WALLET_PRIVATE_KEY`: Solana wallet (JSON array or base58 string)
- `SOLANA_RPC_URL`: Helius RPC endpoint (mainnet recommended)
- `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.
### 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
```
traderv4/
├── README.md ← You are here
├── docker-compose.yml ← Docker orchestration
├── Dockerfile ← Multi-stage build
├── .env ← Configuration (create from .env.example)
├── package.json ← Dependencies (Next.js 15, Drift SDK, Prisma)
├── next.config.js ← Next.js config (standalone output)
├── tsconfig.json ← TypeScript config
├── app/ ← Next.js 15 App Router
│ ├── layout.tsx ← Root layout with Tailwind
│ ├── page.tsx ← Home page
│ ├── globals.css ← Global styles
│ ├── settings/
│ │ └── page.tsx ← Settings UI
│ ├── analytics/
│ │ └── page.tsx ← Analytics dashboard
│ └── api/
│ ├── settings/
│ │ └── 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/
│ ├── execute/route.ts ← Main execution (production)
│ ├── test/route.ts ← Test execution (UI)
│ ├── close/route.ts ← Close positions
│ ├── positions/route.ts ← Query positions
│ ├── check-risk/route.ts ← Risk validation
│ └── remove-position/route.ts ← Remove from monitoring
├── lib/ ← Business logic
│ ├── drift/
│ │ ├── client.ts ← Drift SDK wrapper (singleton)
│ │ └── orders.ts ← Order execution & cancellation
│ ├── pyth/
│ │ └── price-monitor.ts ← WebSocket + HTTP fallback
│ ├── trading/
│ │ └── position-manager.ts ← Monitoring loop (singleton)
│ ├── database/
│ │ ├── trades.ts ← Trade CRUD operations
│ │ └── views.ts ← Analytics queries
│ └── notifications/
│ └── telegram.ts ← Telegram alerts (optional)
├── config/
│ └── trading.ts ← Market configs & defaults
├── prisma/
│ ├── 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)
```
---
## Documentation
| Document | Purpose |
|----------|---------|
| `README.md` | This overview |
| `docs/setup/SETUP.md` | Detailed setup instructions |
| `docs/setup/DOCKER.md` | Docker deployment guide |
| `docs/setup/TELEGRAM_BOT_README.md` | Telegram bot setup |
| `docs/guides/TESTING.md` | Comprehensive testing guide |
| `docs/history/PHASE_2_COMPLETE.md` | Phase 2 feature overview |
| `workflows/trading/` | n8n workflow files |
- `../N8N_SETUP_GUIDE.md` - n8n configuration
---
## Trade Example (Real-World Flow)
### Entry Signal from TradingView
```
Alert Message: "LONG SOLUSDT .P 15"
n8n receives webhook
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
```
### Position Opened
```
Symbol: SOL-PERP
Direction: LONG
Entry: $200.00
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
```
### TP1 Hit (First Target)
```
Price reaches $201.40
On-chain TP1 order fills → 50% closed
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
1. **Start Small**: Use $10-50 positions for first 20 trades
2. **Test Thoroughly**:
- Run with DRY_RUN=true first
- Execute test trades from settings UI
- 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) |
---
## Resources
- **Drift Protocol**: https://drift.trade
- **Drift Docs**: https://docs.drift.trade
- **Drift SDK**: https://github.com/drift-labs/protocol-v2
- **Pyth Network**: https://pyth.network
- **Solana RPC**: https://helius.dev (recommended)
- **Next.js**: https://nextjs.org
- **Prisma ORM**: https://prisma.io
---
## Development Notes
### 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.*