# Symbol-Specific Position Sizing Guide ## Overview The bot now supports different position sizes and leverage for each trading symbol. This enables strategies like: - **High-risk symbols (SOL):** $50 @ 10x leverage = $500 exposure (profit generation) - **Low-risk symbols (ETH):** $1 @ 1x leverage = $1 exposure (data collection) ## Configuration ### 1. Market Configuration (`config/trading.ts`) ```typescript export const SUPPORTED_MARKETS: Record = { 'SOL-PERP': { driftMarketIndex: 0, pythFeedId: '0xef0d...', // Uses default config.positionSize and config.leverage }, 'ETH-PERP': { driftMarketIndex: 1, pythFeedId: '0xff61...', // OVERRIDE: Data collection mode with minimal risk positionSize: 1, // $1 base size leverage: 1, // 1x leverage = $1 total exposure }, 'BTC-PERP': { driftMarketIndex: 2, pythFeedId: '0xe62d...', // Uses default config.positionSize and config.leverage }, } ``` ### 2. Helper Function ```typescript export function getPositionSizeForSymbol( symbol: string, baseConfig: TradingConfig ): { size: number; leverage: number } { const marketConfig = SUPPORTED_MARKETS[symbol] if (!marketConfig) { throw new Error(`Unsupported symbol: ${symbol}`) } return { size: marketConfig.positionSize ?? baseConfig.positionSize, leverage: marketConfig.leverage ?? baseConfig.leverage, } } ``` ### 3. Execute Endpoint Integration The `app/api/trading/execute/route.ts` endpoint now: 1. Normalizes symbol (ETHUSDT β†’ ETH-PERP) 2. Gets merged config via `getMergedConfig()` 3. **Calls `getPositionSizeForSymbol(symbol, config)`** to get symbol-specific sizing 4. Uses returned `{ size, leverage }` for position calculation ## Example: ETH Data Collection Setup ### Goal Collect as many ETH signals as possible with minimal risk to improve signal quality analysis. ### Configuration ```typescript 'ETH-PERP': { driftMarketIndex: 1, pythFeedId: '0xff61491a931112ddf1bd8147cd1b641375f79f5825126d665480874634fd0ace', positionSize: 1, // $1 base size leverage: 1, // No leverage } ``` ### Expected Behavior - TradingView sends: `ETHUSDT LONG` or `ETHUSDT SHORT` - Bot normalizes to: `ETH-PERP` - Bot loads sizing: `positionSize: 1, leverage: 1` - Position size: `$1 Γ— 1 = $1 total exposure` - At ETH = $3,500: Opens ~0.00029 ETH position - Risk: Maximum loss = ~$1 (if emergency stop hits) ### Console Output ``` πŸ“Š Normalized symbol: ETHUSDT β†’ ETH-PERP πŸ“ Symbol-specific sizing for ETH-PERP: Position size: $1 Leverage: 1x πŸ’° Opening LONG position: Symbol: ETH-PERP Base size: $1 Leverage: 1x Total position: $1 ``` ## Testing ### 1. SOL Trade (Default Sizing) Send webhook: ```json { "symbol": "SOLUSDT", "direction": "LONG" } ``` Expected logs: ``` πŸ“ Symbol-specific sizing for SOL-PERP: Position size: $50 Leverage: 10x Total position: $500 ``` ### 2. ETH Trade (Override Sizing) Send webhook: ```json { "symbol": "ETHUSDT", "direction": "SHORT" } ``` Expected logs: ``` πŸ“ Symbol-specific sizing for ETH-PERP: Position size: $1 Leverage: 1x Total position: $1 ``` ### 3. Verify in Drift Check open positions - ETH position should show ~$1 notional value. ## Strategy Rationale ### Why $1 @ 1x for ETH? 1. **Data Collection Priority:** ETH shows 2-3x more signals than SOL 2. **Risk Management:** Cross margin means ETH position uses shared collateral 3. **No Profit Pressure:** Not trying to make money on ETH, just gather quality scores 4. **Statistical Significance:** Need 20-50 trades with quality scores before Phase 2 5. **Collateral Preservation:** Current SOL long uses most collateral, can't risk large ETH positions ### When to Increase ETH Sizing? Only after: - βœ… Phase 1 complete (20-50 trades with quality scores) - βœ… ETH signal quality proven β‰₯ SOL (win rate, profit factor) - βœ… Sufficient collateral available (not at risk of liquidation) - βœ… Phase 2 ATR-based targets implemented and validated ## Cross Margin Considerations **Critical:** All positions (SOL, ETH, BTC) share the same collateral pool on Drift. ### Collateral Math ``` Total Collateral: $500 Current SOL position: ~$450 used Free collateral: ~$50 Adding ETH @ $1: - Maintenance margin: ~$0.05 (5%) - Initial margin: ~$0.10 (10%) - Impact: Minimal βœ… Adding ETH @ $50: - Maintenance margin: ~$2.50 - Initial margin: ~$5 - Risk: Higher liquidation risk ⚠️ ``` ### Safety Buffer Keep at least 30% free collateral at all times: - Total: $500 - Max used: $350 (70%) - Reserve: $150 (30%) for margin calls and new positions ## Future Enhancements ### Phase 2: Reserve-Based Sizing Module Create `lib/trading/position-sizing.ts`: ```typescript export interface PositionSizingParams { symbol: string direction: 'long' | 'short' totalCollateral: number usedCollateral: number marketConfig: MarketConfig baseConfig: TradingConfig } export function calculatePositionSize(params: PositionSizingParams): number { const freeCollateral = params.totalCollateral - params.usedCollateral const reservePercent = 0.30 // Keep 30% reserve const availableForTrade = freeCollateral * (1 - reservePercent) // Get base size from market config or default const baseSize = params.marketConfig.positionSize ?? params.baseConfig.positionSize const leverage = params.marketConfig.leverage ?? params.baseConfig.leverage const requiredCollateral = baseSize * leverage * 0.10 // 10% initial margin // If not enough collateral, reduce position size if (requiredCollateral > availableForTrade) { return availableForTrade / leverage / 0.10 } return baseSize } ``` **Benefits:** - Prevents over-leveraging - Maintains safety buffer - Dynamic sizing based on account state - Supports multiple concurrent positions **When to implement:** After Phase 1 validation, before increasing ETH position sizes. ## Troubleshooting ### Issue: ETH still trading at $50 **Check:** 1. Restart bot after config changes: `docker restart trading-bot-v4` 2. Verify config loaded: Check console logs for "Symbol-specific sizing" 3. Ensure symbol normalization: ETHUSDT β†’ ETH-PERP (not ETH-USD) ### Issue: Position Manager using wrong size **Root cause:** Position Manager calculates position amounts from on-chain data, not config. **Behavior:** - Execute endpoint uses `positionSize` and `leverage` from config - Position Manager reads actual position size from Drift - They're independent systems (by design for safety) ### Issue: Database shows wrong positionSize **Root cause:** Database stores actual executed size, not config size. **Expected:** - Config: `ETH-PERP positionSize: 1` - Database: `positionSize: 1.0` (matches execution) - Drift on-chain: ~0.00029 ETH (~$1 notional) All three should align. If not, config didn't load properly. ## Summary Symbol-specific sizing enables: - βœ… Multi-asset trading with different risk profiles - βœ… Data collection strategies (ETH @ $1) - βœ… Profit generation strategies (SOL @ $50) - βœ… Cross-margin safety (minimal ETH exposure) - βœ… Faster signal quality validation (more trades) **Next steps:** 1. βœ… Config updated (DONE) 2. βœ… Execute endpoint integrated (DONE) 3. ⏸️ Create ETH alert in TradingView (USER ACTION) 4. ⏸️ Restart bot: `docker restart trading-bot-v4` 5. ⏸️ Monitor first ETH trade for correct sizing 6. ⏸️ Collect 20-50 trades with quality scores 7. ⏸️ Proceed to Phase 2 (ATR-based dynamic targets)