feat: Complete Trading Bot v4 with Drift Protocol integration

Features:
- Autonomous trading system with Drift Protocol on Solana
- Real-time position monitoring with Pyth price feeds
- Dynamic stop-loss and take-profit management
- n8n workflow integration for TradingView signals
- Beautiful web UI for settings management
- REST API for trade execution and monitoring

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

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

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

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

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

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

- Runs on port 3001 (external), 3000 (internal)
- Uses Helius RPC for optimal performance
- Production-ready with error handling
- Health monitoring and logging
This commit is contained in:
mindesbunister
2025-10-24 14:24:36 +02:00
commit 2405bff68a
45 changed files with 15683 additions and 0 deletions

190
config/trading.ts Normal file
View File

@@ -0,0 +1,190 @@
/**
* Trading Bot v4 - Configuration
*
* Optimized for 5-minute scalping with 10x leverage on Drift Protocol
*/
export interface TradingConfig {
// Position sizing
positionSize: number // USD amount to trade
leverage: number // Leverage multiplier
// Risk management (as percentages of entry price)
stopLossPercent: number // Negative number (e.g., -1.5)
takeProfit1Percent: number // Positive number (e.g., 0.7)
takeProfit2Percent: number // Positive number (e.g., 1.5)
emergencyStopPercent: number // Hard stop (e.g., -2.0)
// Dynamic adjustments
breakEvenTriggerPercent: number // When to move SL to breakeven
profitLockTriggerPercent: number // When to lock in profit
profitLockPercent: number // How much profit to lock
// DEX specific
priceCheckIntervalMs: number // How often to check prices
slippageTolerance: number // Max acceptable slippage (%)
// Risk limits
maxDailyDrawdown: number // USD stop trading threshold
maxTradesPerHour: number // Limit overtrading
minTimeBetweenTrades: number // Cooldown period (seconds)
// Execution
useMarketOrders: boolean // true = instant execution
confirmationTimeout: number // Max time to wait for confirmation
}
export interface MarketConfig {
symbol: string // e.g., 'SOL-PERP'
driftMarketIndex: number
pythPriceFeedId: string
minOrderSize: number
tickSize: number
}
// Default configuration for 5-minute scalping with $1000 capital and 10x leverage
export const DEFAULT_TRADING_CONFIG: TradingConfig = {
// Position sizing
positionSize: 50, // $50 base capital (SAFE FOR TESTING)
leverage: 10, // 10x leverage = $500 position size
// Risk parameters (wider for DEX slippage/wicks)
stopLossPercent: -1.5, // -1.5% price = -15% account loss (closes 100%)
takeProfit1Percent: 0.7, // +0.7% price = +7% account gain (closes 50%)
takeProfit2Percent: 1.5, // +1.5% price = +15% account gain (closes 50%)
emergencyStopPercent: -2.0, // -2% hard stop = -20% account loss
// Dynamic adjustments
breakEvenTriggerPercent: 0.4, // Move SL to breakeven at +0.4%
profitLockTriggerPercent: 1.0, // Lock profit at +1.0%
profitLockPercent: 0.4, // Lock +0.4% profit
// DEX settings
priceCheckIntervalMs: 2000, // Check every 2 seconds
slippageTolerance: 1.0, // 1% max slippage on market orders
// Risk limits
maxDailyDrawdown: -150, // Stop trading if daily loss exceeds $150 (-15%)
maxTradesPerHour: 6, // Max 6 trades per hour
minTimeBetweenTrades: 600, // 10 minutes cooldown
// Execution
useMarketOrders: true, // Use market orders for reliable fills
confirmationTimeout: 30000, // 30 seconds max wait
}
// Supported markets on Drift Protocol
export const SUPPORTED_MARKETS: Record<string, MarketConfig> = {
'SOL-PERP': {
symbol: 'SOL-PERP',
driftMarketIndex: 0,
pythPriceFeedId: '0xef0d8b6fda2ceba41da15d4095d1da392a0d2f8ed0c6c7bc0f4cfac8c280b56d',
minOrderSize: 0.1, // 0.1 SOL minimum
tickSize: 0.0001,
},
'BTC-PERP': {
symbol: 'BTC-PERP',
driftMarketIndex: 1,
pythPriceFeedId: '0xe62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43',
minOrderSize: 0.001, // 0.001 BTC minimum
tickSize: 0.01,
},
'ETH-PERP': {
symbol: 'ETH-PERP',
driftMarketIndex: 2,
pythPriceFeedId: '0xff61491a931112ddf1bd8147cd1b641375f79f5825126d665480874634fd0ace',
minOrderSize: 0.01, // 0.01 ETH minimum
tickSize: 0.01,
},
}
// Map TradingView symbols to Drift markets
export function normalizeTradingViewSymbol(tvSymbol: string): string {
const upper = tvSymbol.toUpperCase()
if (upper.includes('SOL')) return 'SOL-PERP'
if (upper.includes('BTC')) return 'BTC-PERP'
if (upper.includes('ETH')) return 'ETH-PERP'
// Default to SOL if unknown
console.warn(`Unknown symbol ${tvSymbol}, defaulting to SOL-PERP`)
return 'SOL-PERP'
}
// Get market configuration
export function getMarketConfig(symbol: string): MarketConfig {
const config = SUPPORTED_MARKETS[symbol]
if (!config) {
throw new Error(`Unsupported market: ${symbol}`)
}
return config
}
// Validate trading configuration
export function validateTradingConfig(config: TradingConfig): void {
if (config.positionSize <= 0) {
throw new Error('Position size must be positive')
}
if (config.leverage < 1 || config.leverage > 20) {
throw new Error('Leverage must be between 1 and 20')
}
if (config.stopLossPercent >= 0) {
throw new Error('Stop loss must be negative')
}
if (config.takeProfit1Percent <= 0 || config.takeProfit2Percent <= 0) {
throw new Error('Take profit values must be positive')
}
if (config.takeProfit1Percent >= config.takeProfit2Percent) {
throw new Error('TP2 must be greater than TP1')
}
if (config.slippageTolerance < 0 || config.slippageTolerance > 10) {
throw new Error('Slippage tolerance must be between 0 and 10%')
}
}
// Environment-based configuration
export function getConfigFromEnv(): Partial<TradingConfig> {
return {
positionSize: process.env.MAX_POSITION_SIZE_USD
? parseFloat(process.env.MAX_POSITION_SIZE_USD)
: undefined,
leverage: process.env.LEVERAGE
? parseInt(process.env.LEVERAGE)
: undefined,
stopLossPercent: process.env.STOP_LOSS_PERCENT
? parseFloat(process.env.STOP_LOSS_PERCENT)
: undefined,
takeProfit1Percent: process.env.TAKE_PROFIT_1_PERCENT
? parseFloat(process.env.TAKE_PROFIT_1_PERCENT)
: undefined,
takeProfit2Percent: process.env.TAKE_PROFIT_2_PERCENT
? parseFloat(process.env.TAKE_PROFIT_2_PERCENT)
: undefined,
maxDailyDrawdown: process.env.MAX_DAILY_DRAWDOWN
? parseFloat(process.env.MAX_DAILY_DRAWDOWN)
: undefined,
maxTradesPerHour: process.env.MAX_TRADES_PER_HOUR
? parseInt(process.env.MAX_TRADES_PER_HOUR)
: undefined,
}
}
// Merge configurations
export function getMergedConfig(
overrides?: Partial<TradingConfig>
): TradingConfig {
const envConfig = getConfigFromEnv()
const config = {
...DEFAULT_TRADING_CONFIG,
...envConfig,
...overrides,
}
validateTradingConfig(config)
return config
}