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:
190
config/trading.ts
Normal file
190
config/trading.ts
Normal 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
|
||||
}
|
||||
Reference in New Issue
Block a user