mindesbunister 71c856c720 docs: add master optimization roadmap
Created unified roadmap consolidating all three optimization initiatives
to reduce fragmentation and provide single source of truth.

Three parallel data-driven optimizations:
1. Signal Quality (0/20 blocked signals) - 2-3 weeks
2. Position Scaling (160 trades, need v6 data) - 3-4 weeks
3. ATR-based TP (1/50 trades) - 6-8 weeks

All follow same pattern: collect data → analyze → implement → A/B test

Expected combined impact: 35-40% P&L improvement over 3 months
 4-5 months to reach $2,500

Includes:
- Unified timeline & priorities
- Progress tracking framework
- Weekly/monthly check-in questions
- Risk management (no premature optimization)
- Cross-references to all three roadmaps

Single dashboard for all optimization efforts.
2025-11-12 12:35:44 +01:00
2025-11-12 12:28:06 +01:00

Trading Bot v4 🚀

Fully Autonomous Trading Bot with Dual-Layer Redundancy for TradingView → n8n → Drift Protocol (Solana)

Status

Phase Status Description
Phase 1 COMPLETE Trade execution from TradingView signals
Phase 2 COMPLETE Real-time monitoring & automatic exits
Phase 3 COMPLETE Web UI, settings management, Docker deployment
Phase 4 COMPLETE Database integration, analytics, race condition fixes

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.

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

# 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

npm install

2. Configure Environment

# 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

# 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:

# 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:

# 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:

# 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

# 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

# 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:

# 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:

// 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:

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

# 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


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.

Description
No description provided
Readme 114 MiB
Languages
Python 91.9%
Cython 3.6%
C 2.2%
TypeScript 1.8%
C++ 0.2%
Other 0.1%