Description

Custom levels Rough Draft

Comments (0)

0/2000

Loading comments…

Source code

function calculate(bars, ctx) {
  // Scalping strategy for ES/NQ on 1-minute chart
  // Level color teams: green 35, red 80, yellow 26 42 58 94, blue 00 10 20 50, black 47 72 86
  
  // Strategy inputs
  const qty = ctx.input('Quantity', 1, { min: 1, max: 10 });
  const slTicks = ctx.input('Stop Loss (ticks)', 8, { min: 1, max: 20 });
  const tpTicks = ctx.input('Take Profit (ticks)', 4, { min: 1, max: 10 });
  const useTrailing = ctx.input('Use Trailing Stop', false);
  const trailOffset = ctx.input('Trail Offset (ticks)', 6, { min: 1, max: 15 });
  const maxTradesPerDay = ctx.input('Max Trades Per Day', 10, { min: 1, max: 50 });
  const startHour = ctx.input('Start Hour (ET)', 9, { min: 0, max: 23 });
  const endHour = ctx.input('End Hour (ET)', 16, { min: 0, max: 23 });
  
  // Get current price and tick info
  const price = ctx.price.last;
  const tickSize = ctx.syminfo.tickSize;
  const last = bars.length - 1;
  
  // Check trading window
  if (!ctx.time.inSession(last, startHour, endHour)) {
    ctx.log('Outside trading window');
    return;
  }
  
  // Check daily trade limit
  if (ctx.strategy.account.todayTrades >= maxTradesPerDay) {
    ctx.log('Daily trade limit reached');
    return;
  }
  
  // Calculate key levels based on your color teams
  // These repeat every 100 points
  const baseLevel = Math.floor(price / 100) * 100;
  
  // Define level values
  const greenLevels = [35];
  const redLevels = [80];
  const yellowLevels = [26, 42, 58, 94];
  const blueLevels = [0, 10, 20, 50];
  const blackLevels = [47, 72, 86];
  
  // Combine all levels
  const allLevels = [
    ...greenLevels.map(l => baseLevel + l),
    ...redLevels.map(l => baseLevel + l),
    ...yellowLevels.map(l => baseLevel + l),
    ...blueLevels.map(l => baseLevel + l),
    ...blackLevels.map(l => baseLevel + l),
    ...greenLevels.map(l => baseLevel + 100 + l),
    ...redLevels.map(l => baseLevel + 100 + l),
    ...yellowLevels.map(l => baseLevel + 100 + l),
    ...blueLevels.map(l => baseLevel + 100 + l),
    ...blackLevels.map(l => baseLevel + 100 + l),
    ...greenLevels.map(l => baseLevel - 100 + l),
    ...redLevels.map(l => baseLevel - 100 + l),
    ...yellowLevels.map(l => baseLevel - 100 + l),
    ...blueLevels.map(l => baseLevel - 100 + l),
    ...blackLevels.map(l => baseLevel - 100 + l)
  ].sort((a, b) => a - b);
  
  // Find nearest levels above and below current price
  let nearestBelow = -Infinity;
  let nearestAbove = Infinity;
  
  for (const level of allLevels) {
    if (level < price && level > nearestBelow) {
      nearestBelow = level;
    }
    if (level > price && level < nearestAbove) {
      nearestAbove = level;
    }
  }
  
  // Calculate distance to nearest levels
  const distanceToBelow = price - nearestBelow;
  const distanceToAbove = nearestAbove - price;
  
  // Draw level lines for visualization
  for (const level of allLevels) {
    // Determine color based on level type
    let color = '#787b86'; // default gray
    
    const remainder = level % 100;
    if (greenLevels.includes(remainder)) color = '#00e676'; // green
    else if (redLevels.includes(remainder)) color = '#ef5350'; // red
    else if (yellowLevels.includes(remainder)) color = '#ffeb3b'; // yellow
    else if (blueLevels.includes(remainder)) color = '#2196f3'; // blue
    else if (blackLevels.includes(remainder)) color = '#212121'; // black
    
    ctx.hline(level, {
      color: color,
      lineStyle: 'dashed',
      lineWidth: 1,
      label: remainder.toString()
    });
  }
  
  // Get current position
  const pos = ctx.strategy.position;
  
  // Phase 1: FLAT - look for entry signals near key levels
  if (pos.side === 'flat') {
    // Check if we're near a key level (within 2 points)
    const levelThreshold = 2.0;
    
    // Entry logic: bounce off support (buy) or resistance (sell)
    if (distanceToBelow <= levelThreshold) {
      // Near support level - look for bullish reversal
      const ema9 = ctx.ta.ema(ctx.price.close, 9);
      const ema21 = ctx.ta.ema(ctx.price.close, 21);
      
      // Bullish signal: price above EMA9, EMA9 above EMA21, recent bullish candle
      if (bars[last].close > ema9[last] && 
          ema9[last] > ema21[last] && 
          bars[last].close > bars[last].open) {
        
        const entryPrice = price;
        const stopLoss = entryPrice - slTicks * tickSize;
        const takeProfit = entryPrice + tpTicks * tickSize;
        
        ctx.strategy.entry('long_scalp', 'long', {
          qty: qty,
          bracket: {
            stopLoss: { price: stopLoss },
            takeProfit: [{ price: takeProfit }]
          }
        });
        
        if (useTrailing) {
          ctx.strategy.setTrail('long_scalp', {
            trailOffset: trailOffset,
            unit: 'ticks'
          });
        }
        
        ctx.log('Long entry at support: ' + entryPrice.toFixed(2));
      }
    }
    
    if (distanceToAbove <= levelThreshold) {
      // Near resistance level - look for bearish reversal
      const ema9 = ctx.ta.ema(ctx.price.close, 9);
      const ema21 = ctx.ta.ema(ctx.price.close, 21);
      
      // Bearish signal: price below EMA9, EMA9 below EMA21, recent bearish candle
      if (bars[last].close < ema9[last] && 
          ema9[last] < ema21[last] && 
          bars[last].close < bars[last].open) {
        
        const entryPrice = price;
        const stopLoss = entryPrice + slTicks * tickSize;
        const takeProfit = entryPrice - tpTicks * tickSize;
        
        ctx.strategy.entry('short_scalp', 'short', {
          qty: qty,
          bracket: {
            stopLoss: { price: stopLoss },
            takeProfit: [{ price: takeProfit }]
          }
        });
        
        if (useTrailing) {
          ctx.strategy.setTrail('short_scalp', {
            trailOffset: trailOffset,
            unit: 'ticks'
          });
        }
        
        ctx.log('Short entry at resistance: ' + entryPrice.toFixed(2));
      }
    }
    
    // Breakout entry: price breaks through key level with momentum
    const atr = ctx.ta.atr(ctx.price.high, ctx.price.low, ctx.price.close, 14);
    const atrValue = atr[last] || 5;
    
    // Check for breakout above resistance
    if (bars[last].close > nearestAbove && bars[last-1].close <= nearestAbove) {
      // Breakout long
      const entryPrice = price;
      const stopLoss = entryPrice - Math.min(slTicks * tickSize, atrValue * 0.5);
      const takeProfit = entryPrice + tpTicks * tickSize;
      
      ctx.strategy.entry('breakout_long', 'long', {
        qty: qty,
        bracket: {
          stopLoss: { price: stopLoss },
          takeProfit: [{ price: takeProfit }]
        }
      });
      
      ctx.log('Breakout long above resistance: ' + entryPrice.toFixed(2));
    }
    
    // Check for breakdown below support
    if (bars[last].close < nearestBelow && bars[last-1].close >= nearestBelow) {
      // Breakdown short
      const entryPrice = price;
      const stopLoss = entryPrice + Math.min(slTicks * tickSize, atrValue * 0.5);
      const takeProfit = entryPrice - tpTicks * tickSize;
      
      ctx.strategy.entry('breakout_short', 'short', {
        qty: qty,
        bracket: {
          stopLoss: { price: stopLoss },
          takeProfit: [{ price: takeProfit }]
        }
      });
      
      ctx.log('Breakdown short below support: ' + entryPrice.toFixed(2));
    }
  }
  
  // Phase 2: IN POSITION - manage existing trades
  if (pos.side !== 'flat') {
    // Check if price has reached next key level (potential exit)
    const isLong = pos.side === 'long';
    const nextLevel = isLong ? nearestAbove : nearestBelow;
    const distanceToNextLevel = isLong ? nextLevel - price : price - nextLevel;
    
    // Consider early exit if near next key level and showing reversal signs
    if (distanceToNextLevel <= 1.0) {
      const rsi = ctx.ta.rsi(ctx.price.close, 14);
      const rsiValue = rsi[last] || 50;
      
      // Overbought/oversold at key level - consider exiting
      if ((isLong && rsiValue > 70) || (!isLong && rsiValue < 30)) {
        ctx.strategy.close();
        ctx.log('Early exit at key level with RSI extreme');
      }
    }
    
    // Check for daily loss limit
    if (ctx.strategy.account.dayPnl < -500) {
      ctx.strategy.flattenAll();
      ctx.log('Daily loss limit reached - flattening all');
    }
  }
  
  // End of day flattening
  if (ctx.time.hour(last) >= 15 && ctx.time.minute(last) >= 45) { // 3:45 PM ET
    if (pos.side !== 'flat') {
      ctx.strategy.flattenAll();
      ctx.log('End of day flattening');
    }
  }
}