- 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
10 KiB
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:
SymbolSettingsinterface withenabled,positionSize, andleveragefieldssolanaandethereumoptional fields toTradingConfiginterface- 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
TradingSettingsinterface fields:SOLANA_ENABLED,SOLANA_POSITION_SIZE,SOLANA_LEVERAGEETHEREUM_ENABLED,ETHEREUM_POSITION_SIZE,ETHEREUM_LEVERAGE
New UI Sections:
-
"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
-
"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)
-
"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 acceptssymbolparameter
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
.tsfiles fromarchive/to.archive/to exclude from TypeScript compilation - Fixed import paths in archived test files
Configuration Priority
Order of precedence:
- Per-symbol ENV vars (highest priority)
SOLANA_POSITION_SIZE,SOLANA_LEVERAGE,SOLANA_ENABLEDETHEREUM_POSITION_SIZE,ETHEREUM_LEVERAGE,ETHEREUM_ENABLED
- Market-specific config (from
MARKET_CONFIGSin config/trading.ts) - Global ENV vars (fallback)
MAX_POSITION_SIZE_USD,LEVERAGE
- Default config (lowest priority)
Use Cases
Use Case 1: Data Collection on ETH
- Set
ETHEREUM_POSITION_SIZE=4andETHEREUM_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=210andSOLANA_LEVERAGE=10 - Results in $2100 notional position
- Full-scale trading with normal risk
Use Case 3: Disable ETH Temporarily
- Set
ETHEREUM_ENABLED=falsein 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
- ✅ Built successfully with
npm run build - ✅ Docker image built successfully
- ✅ Container started and restored existing position
- ✅ No TypeScript errors
- ✅ Settings UI loads with new sections
- ✅ Per-symbol test buttons functional
Next Steps
- Test symbol enable/disable in production
- Verify ETH trades use $4 sizing (or Drift's minimum)
- Confirm SOL trades continue at $210 sizing
- Monitor that disabled symbols correctly reject signals
- Update
.envwith 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
config/trading.ts- Added SymbolSettings interface and per-symbol ENV supportapp/settings/page.tsx- Added SOL/ETH sections with toggles and test buttonsapp/api/settings/route.ts- Added per-symbol fields to GET/POSTapp/api/trading/execute/route.ts- Added enabled checkapp/api/trading/test/route.ts- Added enabled checkarchive/test-drift-v4.ts- Fixed imports (moved to .archive)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?
- ETH for Data Only: User wants minimal risk on ETH ($4 positions) purely for collecting trade data
- SOL for Profits: User wants normal-sized positions on SOL ($2100) for actual profit generation
- Cooldown Independence: Each symbol has independent cooldown timer (already implemented in previous phase)
- 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
- Add BTC-PERP section (currently uses global fallback)
- Per-symbol stop loss percentages (currently global)
- Per-symbol take profit levels (currently global)
- Import/export symbol configurations
- Symbol-specific quality score thresholds
- Historical performance by symbol in analytics dashboard