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
- Declares RSI indicator in
init() - Checks RSI value each bar in
onBar() - Buys when RSI drops below oversold level
- 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
- EMA Crossover — Trend-following example
- Strategy Lifecycle — Execution order
exampleminimalbasicstartertemplateqsl