Files
trading_bot_v4/docs/history/PER_SYMBOL_SETTINGS.md
mindesbunister 881a99242d feat: Add per-symbol trading controls for SOL and ETH
- Add SymbolSettings interface with enabled/positionSize/leverage fields
- Implement per-symbol ENV variables (SOLANA_*, ETHEREUM_*)
- Add SOL and ETH sections to settings UI with enable/disable toggles
- Add symbol-specific test buttons (SOL LONG/SHORT, ETH LONG/SHORT)
- Update execute and test endpoints to check symbol enabled status
- Add real-time risk/reward calculator per symbol
- Rename 'Position Sizing' to 'Global Fallback' for clarity
- Fix position manager P&L calculation for externally closed positions
- Fix zero P&L bug affecting 12 historical trades
- Add SQL scripts for recalculating historical P&L data
- Move archive TypeScript files to .archive to fix build

Defaults:
- SOL: 10 base × 10x leverage = 100 notional (profit trading)
- ETH:  base × 1x leverage =  notional (data collection)
- Global: 10 × 10x for BTC and other symbols

Configuration priority: Per-symbol ENV > Market config > Global ENV > Defaults
2025-11-03 10:28:48 +01:00

10 KiB
Raw Blame History

Per-Symbol Settings Implementation

Overview

Implemented individual enable/disable toggles and position sizing controls for Solana (SOL-PERP) and Ethereum (ETH-PERP) in the settings UI, allowing independent configuration of each trading pair.

Date

November 3, 2024

Changes Made

1. Configuration System (config/trading.ts)

Added:

  • SymbolSettings interface with enabled, positionSize, and leverage fields
  • solana and ethereum optional fields to TradingConfig interface
  • Per-symbol environment variable support:
    • SOLANA_ENABLED (default: true)
    • SOLANA_POSITION_SIZE (default: 210)
    • SOLANA_LEVERAGE (default: 10)
    • ETHEREUM_ENABLED (default: true)
    • ETHEREUM_POSITION_SIZE (default: 4)
    • ETHEREUM_LEVERAGE (default: 1)

Modified:

  • getPositionSizeForSymbol() now returns { size, leverage, enabled }
  • Symbol-specific settings take priority over global fallback settings
  • Default SOL config: $210 base × 10x = $2100 notional
  • Default ETH config: $4 base × 1x = $4 notional (close to Drift's $38-40 minimum)

2. Settings UI (app/settings/page.tsx)

Added:

  • New TradingSettings interface fields:
    • SOLANA_ENABLED, SOLANA_POSITION_SIZE, SOLANA_LEVERAGE
    • ETHEREUM_ENABLED, ETHEREUM_POSITION_SIZE, ETHEREUM_LEVERAGE

New UI Sections:

  1. "Solana (SOL-PERP)" section:

    • Enable/disable toggle
    • Position size input (1-10000 USD)
    • Leverage input (1-20x)
    • Real-time risk/reward calculator showing max loss, full win, and R:R ratio
  2. "Ethereum (ETH-PERP)" section:

    • Enable/disable toggle
    • Position size input (1-10000 USD)
    • Leverage input (1-20x)
    • Real-time risk/reward calculator
    • Note: Drift minimum is ~$38-40 (0.01 ETH)
  3. "Global Position Sizing (Fallback)" section:

    • Renamed from "Position Sizing"
    • Clarifies these are defaults for symbols without specific config (e.g., BTC-PERP)
    • Yellow warning banner explaining fallback behavior

Test Buttons:

  • Replaced single LONG/SHORT buttons with symbol-specific tests:
    • 💎 Test SOL LONG / 💎 Test SOL SHORT (purple gradient)
    • Test ETH LONG / Test ETH SHORT (blue gradient)
    • Buttons disabled when respective symbol trading is disabled
    • testTrade() function now accepts symbol parameter

3. Settings API (app/api/settings/route.ts)

GET endpoint:

  • Returns all 6 new per-symbol fields with defaults from ENV

POST endpoint:

  • Saves per-symbol settings to .env file (implementation via existing updateEnvFile())

4. Execute Endpoint (app/api/trading/execute/route.ts)

Added:

  • Symbol enabled check before execution
  • Returns 400 error if trading is disabled for the symbol
  • Logs enabled status along with position size and leverage

Example flow:

const { size, leverage, enabled } = getPositionSizeForSymbol(driftSymbol, config)
if (!enabled) {
  return NextResponse.json({
    success: false,
    error: 'Symbol trading disabled',
    message: `Trading is currently disabled for ${driftSymbol}...`
  }, { status: 400 })
}

5. Test Endpoint (app/api/trading/test/route.ts)

Added:

  • Symbol enabled check (same as execute endpoint)
  • Test trades rejected if symbol is disabled

6. Archive Cleanup

Fixed:

  • Moved .ts files from archive/ to .archive/ to exclude from TypeScript compilation
  • Fixed import paths in archived test files

Configuration Priority

Order of precedence:

  1. Per-symbol ENV vars (highest priority)
    • SOLANA_POSITION_SIZE, SOLANA_LEVERAGE, SOLANA_ENABLED
    • ETHEREUM_POSITION_SIZE, ETHEREUM_LEVERAGE, ETHEREUM_ENABLED
  2. Market-specific config (from MARKET_CONFIGS in config/trading.ts)
  3. Global ENV vars (fallback)
    • MAX_POSITION_SIZE_USD, LEVERAGE
  4. Default config (lowest priority)

Use Cases

Use Case 1: Data Collection on ETH

  • Set ETHEREUM_POSITION_SIZE=4 and ETHEREUM_LEVERAGE=1
  • Results in $4 notional (minimal risk)
  • Collects trade data for strategy optimization
  • Note: Actual Drift minimum is ~$38-40, so this will be adjusted up

Use Case 2: Profit Generation on SOL

  • Set SOLANA_POSITION_SIZE=210 and SOLANA_LEVERAGE=10
  • Results in $2100 notional position
  • Full-scale trading with normal risk

Use Case 3: Disable ETH Temporarily

  • Set ETHEREUM_ENABLED=false in settings UI
  • All ETH signals from TradingView will be rejected
  • SOL trading continues normally

Use Case 4: Different Risk Profiles

  • SOL: High conviction, larger size ($210 × 10x = $2100)
  • ETH: Testing strategy, minimal size ($4 × 1x = $4)
  • BTC: Falls back to global settings ($54 × 10x = $540)

Testing Performed

  1. Built successfully with npm run build
  2. Docker image built successfully
  3. Container started and restored existing position
  4. No TypeScript errors
  5. Settings UI loads with new sections
  6. Per-symbol test buttons functional

Next Steps

  1. Test symbol enable/disable in production
  2. Verify ETH trades use $4 sizing (or Drift's minimum)
  3. Confirm SOL trades continue at $210 sizing
  4. Monitor that disabled symbols correctly reject signals
  5. Update .env with desired per-symbol settings

Breaking Changes

None - Fully backward compatible:

  • If per-symbol ENV vars not set, falls back to global settings
  • All symbols default to enabled: true
  • Existing ENV vars (MAX_POSITION_SIZE_USD, LEVERAGE) still work as fallback

Files Modified

  1. config/trading.ts - Added SymbolSettings interface and per-symbol ENV support
  2. app/settings/page.tsx - Added SOL/ETH sections with toggles and test buttons
  3. app/api/settings/route.ts - Added per-symbol fields to GET/POST
  4. app/api/trading/execute/route.ts - Added enabled check
  5. app/api/trading/test/route.ts - Added enabled check
  6. archive/test-drift-v4.ts - Fixed imports (moved to .archive)
  7. archive/test-position-manager.ts - Fixed imports (moved to .archive)

Configuration Reference

Default Values

# Solana (SOL-PERP)
SOLANA_ENABLED=true
SOLANA_POSITION_SIZE=210
SOLANA_LEVERAGE=10

# Ethereum (ETH-PERP)
ETHEREUM_ENABLED=true
ETHEREUM_POSITION_SIZE=4
ETHEREUM_LEVERAGE=1

# Global Fallback (BTC, others)
MAX_POSITION_SIZE_USD=54
LEVERAGE=10

Example: Disable ETH, Keep SOL at $2100

SOLANA_ENABLED=true
SOLANA_POSITION_SIZE=210
SOLANA_LEVERAGE=10
ETHEREUM_ENABLED=false

Example: Both Minimal Sizing

SOLANA_ENABLED=true
SOLANA_POSITION_SIZE=4
SOLANA_LEVERAGE=1
ETHEREUM_ENABLED=true
ETHEREUM_POSITION_SIZE=4
ETHEREUM_LEVERAGE=1

UI Screenshots

Settings Page Structure

┌─────────────────────────────────────────┐
│ ⚙️ Trading Bot Settings                 │
├─────────────────────────────────────────┤
│ 📊 Risk Calculator (Global)             │
├─────────────────────────────────────────┤
│ 💎 Solana (SOL-PERP)                    │
│   🟢 Enable Solana Trading [Toggle]     │
│   SOL Position Size: [210] USD          │
│   SOL Leverage: [10]x                   │
│   Risk/Reward: Max Loss $31.50 ...      │
├─────────────────────────────────────────┤
│ ⚡ Ethereum (ETH-PERP)                   │
│   🟢 Enable Ethereum Trading [Toggle]   │
│   ETH Position Size: [4] USD            │
│   ETH Leverage: [1]x                    │
│   Risk/Reward: Max Loss $0.06 ...       │
├─────────────────────────────────────────┤
│ 💰 Global Position Sizing (Fallback)    │
│   ⚠️ Fallback for BTC and others        │
│   Position Size: [54] USD               │
│   Leverage: [10]x                       │
├─────────────────────────────────────────┤
│ ... (other sections) ...                │
├─────────────────────────────────────────┤
│ [💾 Save Settings] [🔄 Restart Bot]     │
├─────────────────────────────────────────┤
│ 🧪 Test Trades (REAL MONEY)             │
│ [💎 Test SOL LONG] [💎 Test SOL SHORT]  │
│ [⚡ Test ETH LONG] [⚡ Test ETH SHORT]   │
└─────────────────────────────────────────┘

Implementation Notes

Why Per-Symbol Settings?

  1. ETH for Data Only: User wants minimal risk on ETH ($4 positions) purely for collecting trade data
  2. SOL for Profits: User wants normal-sized positions on SOL ($2100) for actual profit generation
  3. Cooldown Independence: Each symbol has independent cooldown timer (already implemented in previous phase)
  4. Strategy Testing: Can test different strategies on different symbols simultaneously

Drift Minimum Constraints

  • SOL: 0.1 SOL minimum (~$5-15) Our $210 base exceeds this
  • ETH: 0.01 ETH minimum (~$38-40) ⚠️ Our $4 target is below this
  • BTC: 0.0001 BTC minimum (~$10-12) Our $54 base exceeds this

Solution for ETH: The execute endpoint will attempt to open with specified size, and Drift SDK will adjust up to meet minimum. Monitor actual executed sizes in logs.

Risk/Reward Display

Each symbol section shows real-time risk metrics:

  • Max Loss: Position size × leverage × |SL%|
  • Full Win: TP1 gain + TP2 gain
  • R:R Ratio: Full Win / Max Loss

Example for SOL ($210 × 10x = $2100 notional, -1.5% SL, +0.7% TP1, +1.5% TP2):

  • Max Loss: $31.50
  • TP1 Gain: $7.35 (50% position)
  • TP2 Gain: $15.75 (50% position)
  • Full Win: $23.10
  • R:R: 1:0.73

Future Enhancements

  1. Add BTC-PERP section (currently uses global fallback)
  2. Per-symbol stop loss percentages (currently global)
  3. Per-symbol take profit levels (currently global)
  4. Import/export symbol configurations
  5. Symbol-specific quality score thresholds
  6. Historical performance by symbol in analytics dashboard