Example 3: Volatility-Based Position Sizing

This strategy adjusts position size based on recent price volatility.

class Strategy {
  constructor() {
    this.strategy = {
      data: {
        token: {
          address: "",
          creationTime: 0
        },
        priceTicks: []
      },
      steps: [
        {
          run: (entry, current) => this.buyWithVolatilityAdjustment(entry, current),
          label: "Buy with volatility-adjusted size"
        },
        {
          run: (entry, current) => this.exitAtTarget(entry, current),
          label: "Exit at 3x profit target"
        }
      ],
      context: {}
    }
  }

  /**
   * Calculate price volatility over recent ticks
   * Uses standard deviation of price changes
   */
  calculateVolatility(periods) {
    const ticks = this.strategy.data.priceTicks;

    if (ticks.length < periods + 1) {
      return null;
    }

    // Calculate price changes
    const changes = [];
    for (let i = 0; i < periods; i++) {
      const change = (ticks[i].usdPrice - ticks[i + 1].usdPrice) / ticks[i + 1].usdPrice;
      changes.push(change);
    }

    // Calculate mean
    const mean = changes.reduce((sum, val) => sum + val, 0) / changes.length;

    // Calculate standard deviation
    const squaredDiffs = changes.map(val => Math.pow(val - mean, 2));
    const variance = squaredDiffs.reduce((sum, val) => sum + val, 0) / changes.length;
    const stdDev = Math.sqrt(variance);

    return stdDev;
  }

  /**
   * Step 1: Buy with position size based on volatility
   * Higher volatility = smaller position size (risk management)
   */
  buyWithVolatilityAdjustment(signalPrice, currentPrice) {
    // Wait for 10% dip
    if (currentPrice > signalPrice * 0.9) {
      return null;
    }

    // Calculate volatility
    const volatility = this.calculateVolatility(20);

    // If not enough data, use conservative default
    let positionSize = 50; // Default 50%

    if (volatility !== null) {
      // Scale position size based on volatility
      // Low volatility (< 0.05 = 5%) → 100% position
      // Medium volatility (0.05-0.15) → 50-75% position
      // High volatility (> 0.15 = 15%) → 25-50% position

      if (volatility < 0.05) {
        positionSize = 100;
      } else if (volatility < 0.10) {
        positionSize = 75;
      } else if (volatility < 0.15) {
        positionSize = 50;
      } else {
        positionSize = 25;
      }

      // Store volatility for reference
      this.strategy.context.entryVolatility = volatility;
      this.strategy.context.positionSize = positionSize;
    }

    return {
      buy: true,
      partToBuyInPercentage: positionSize
    };
  }

  /**
   * Step 2: Simple exit at 3x target
   */
  exitAtTarget(entryPrice, currentPrice) {
    if (currentPrice >= entryPrice * 3) {
      return {
        sell: true,
        partToSellInPercentage: 100
      };
    }

    return null;
  }
}

Best Practices for Advanced Strategies

  1. Always Handle Missing Data: Check if priceTicks has enough data before calculations

  2. Use Context Wisely: Store important values (peaks, entry data) for later steps

  3. Avoid Complexity: More complex ≠ better; start simple and add logic incrementally

  4. Test Edge Cases: What happens with insufficient data? Extreme prices?

  5. Document Your Logic: Use comments to explain WHY, not just WHAT

  6. Consider Performance: Avoid nested loops over large arrays (O(n²) operations)

  7. Risk Management First: Always have a stop loss or exit plan

  8. Validate Calculations: Check for division by zero, null values, NaN results

Last updated