Appearance
Personalize your experience
Mode
Accent Color
Layout
Direction
9 EMA Breakout
Admin's ChoiceFreeHigh-momentum breakout strategy using 9 & 21 EMA crossover with volume filter
4.7(145)
3.4k installs 780 2 commentsQ
42 listings12400 followers
Official QuaTick team — building advanced charting & trading tools for the Indian market.
View Profileemabreakoutmomentumintraday
Free
Open in QuaTick IDE Edit in IDE Version1.2.0
Updated2025-10-05
Compatiblecandlestick
Rating Distribution
5
1
4
0
3
0
2
0
1
0
Preview
1 / 2
Chart preview
About
Enters long when 9 EMA crosses above 21 EMA with volume confirmation (>1.5× 20-bar average). Exits on reverse cross or RSI > 75.
Rules
1. **Entry**: 9 EMA > 21 EMA + Volume > 1.5× avg
2. **Exit**: 9 EMA < 21 EMA or trailing stop
3. **Risk**: 1-2% per trade
Strategy Rules
Entry Conditions
- ▸ 9 EMA crosses above 21 EMA
- ▸ Volume > 1.5× 20-bar average
Exit Conditions
- ▸ RSI > 75
- ▸ 9 EMA crosses below 21 EMA
- ▸ Trailing stop hit
Backtest Results
42.3%
Return
1.82
Sharpe
-12.4%
Max DD
58.2%
Win Rate
234
Trades
Source Code
Edit in IDEtypescript
| 1 | // EMA Crossover Strategy — Quatick IDE |
| 2 | // SDK math globals available: sma, ema, atr, rsi, macd, bollingerBands, vwap, etc. |
| 3 | |
| 4 | const metadata = { id: 'ema-crossover', name: 'EMA Crossover Strategy', version: '1.0.0', category: 'strategy' }; |
| 5 | |
| 6 | interface BarData { |
| 7 | time: number; |
| 8 | open: number; |
| 9 | high: number; |
| 10 | low: number; |
| 11 | close: number; |
| 12 | volume?: number; |
| 13 | } |
| 14 | |
| 15 | const defaultParams = { |
| 16 | fastPeriod: 9, |
| 17 | slowPeriod: 21, |
| 18 | volumeMultiplier: 1.5, |
| 19 | }; |
| 20 | |
| 21 | function run(data: BarData[], config = defaultParams) { |
| 22 | const closes = data.map(d => d.close); |
| 23 | |
| 24 | // ema() is an SDK global: ema(data[], period) -> number[] |
| 25 | const fastEMA = ema(closes, config.fastPeriod); |
| 26 | const slowEMA = ema(closes, config.slowPeriod); |
| 27 | |
| 28 | const volSMA = sma(data.map(d => d.volume ?? 0), 20); |
| 29 | |
| 30 | const trades: { entry: number; exit: number; type: string; pnl: number }[] = []; |
| 31 | let position: string | null = null; |
| 32 | let entryIdx = 0; |
| 33 | |
| 34 | for (let i = 1; i < data.length; i++) { |
| 35 | if (isNaN(fastEMA[i]) || isNaN(slowEMA[i])) continue; |
| 36 | const crossedUp = fastEMA[i - 1] <= slowEMA[i - 1] && fastEMA[i] > slowEMA[i]; |
| 37 | const crossedDown = fastEMA[i - 1] >= slowEMA[i - 1] && fastEMA[i] < slowEMA[i]; |
| 38 | const volOk = !isNaN(volSMA[i]) && (data[i].volume ?? 0) > config.volumeMultiplier * volSMA[i]; |
| 39 | |
| 40 | if (!position && crossedUp && volOk) { |
| 41 | position = 'long'; |
| 42 | entryIdx = i; |
| 43 | } else if (position === 'long' && crossedDown) { |
| 44 | trades.push({ entry: entryIdx, exit: i, type: 'long', pnl: data[i].close - data[entryIdx].close }); |
| 45 | position = null; |
| 46 | } |
| 47 | } |
| 48 | |
| 49 | return { |
| 50 | trades, |
| 51 | totalTrades: trades.length, |
| 52 | winRate: trades.length > 0 ? (trades.filter(t => t.pnl > 0).length / trades.length) * 100 : 0, |
| 53 | totalPnl: trades.reduce((sum, t) => sum + t.pnl, 0), |
| 54 | }; |
| 55 | } |
Read-only preview. Open in the QuaTick IDE to edit and deploy.
Reviews
No reviews yet. Be the first to review this listing.
Discussion
Sign in to join the discussion. Your posts and replies show up on your profile.