DocsExamples

Minimal Strategy

The smallest complete strategy that compiles and runs.

Code

/** * Minimal RSI Strategy * Buys when RSI oversold, sells when overbought */ function define(ctx) { ctx.param('rsiPeriod', { type: 'int', label: 'RSI Period', default: 14, min: 2, max: 50 }); ctx.param('oversold', { type: 'int', label: 'Oversold Level', default: 30, min: 10, max: 40 }); ctx.param('overbought', { type: 'int', label: 'Overbought Level', default: 70, min: 60, max: 90 }); } function init(ctx) { ctx.indicator('rsi', 'RSI', { period: ctx.p.rsiPeriod }); } function onBar(ctx, i) { const rsi = ctx.ind.rsi[i]; // Skip if indicator not ready if (q.isNaN(rsi)) return; const pos = ctx.position('ASSET'); // Buy when RSI oversold if (rsi < ctx.p.oversold && pos.qty === 0) { ctx.order.market('ASSET', 1, { signal: 'buy', reason: 'rsi_oversold' }); } // Sell when RSI overbought if (rsi > ctx.p.overbought && pos.qty > 0) { ctx.order.close('ASSET', { signal: 'sell', reason: 'rsi_overbought' }); } }

What This Strategy Does

  1. Declares RSI indicator in init()
  2. Checks RSI value each bar in onBar()
  3. Buys when RSI drops below oversold level
  4. Sells when RSI rises above overbought level

Key Concepts Demonstrated

  • Three functions: define(), init(), onBar()
  • Parameters: ctx.param() with type, bounds, labels
  • Indicators: Declared in init(), pre-computed by engine
  • Position check: ctx.position('ASSET').qty
  • Orders: ctx.order.market(), ctx.order.close()
  • Helpers: q.isNaN() for indicator warm-up

Anatomy of a QSL Strategy

// 1. DEFINE: Declare parameters function define(ctx) { ctx.param('name', { type: 'int', default: 14 }); } // 2. INIT: Declare indicators and state function init(ctx) { ctx.indicator('myIndicator', 'EMA', { period: ctx.p.name }); ctx.state.tradeCount = 0; } // 3. ONBAR: Trading logic function onBar(ctx, i) { // Your logic here }

Related

exampleminimalbasicstartertemplateqsl