Strategi ini menggabungkan tiga penunjuk teknikal: CCI, RSI, dan Saluran Keltner (KC), bersama-sama dengan penapis trend untuk mencapai perdagangan dua arah pada pasangan mata wang AUDNZD dan GBPNZD. Ia menggunakan CCI dan RSI untuk menentukan keadaan overbought dan oversold, KC sebagai rujukan untuk stop-loss dan mengambil keuntungan, dan purata bergerak sebagai penapis trend untuk membuka kedudukan selaras dengan trend. Strategi ini telah diuji semula pada data sejarah selama 5 tahun yang lalu, mencapai pulangan yang stabil.
Strategi ini menggunakan beberapa penunjuk klasik dan agak mudah untuk kod dan backtest di TradingView. Walaupun hasil backtesting baik, kawalan risiko dan penyesuaian parameter masih diperlukan untuk perdagangan langsung. Adalah disyorkan untuk memulakan dengan dana kecil untuk ujian dan secara beransur-ansur meningkatkan pelaburan apabila pengalaman terkumpul. Dengan tahap automasi yang tinggi, ia sesuai untuk digunakan oleh pelabur konservatif dalam jangka panjang.
/*backtest start: 2024-04-01 00:00:00 end: 2024-04-30 23:59:59 period: 2h basePeriod: 15m exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}] */ //@version=5 strategy('CCI Strategy with Trend Filter AUDNZD, GBPNZD', overlay=true, default_qty_type=strategy.cash, default_qty_value=50000, commission_value=0.0005, slippage=2, initial_capital=10000) // State variables to ensure one entry per signal var bool isLongOpen = false var bool isShortOpen = false // Input Parameters for allowing long and short trades allowLong = input(true, title='Allow Long Trades') allowShort = input(true, title='Allow Short Trades') // Trend Filter Inputs maType = input.string(title='MA Type', options=['OFF', 'SMA', 'EMA', 'SMMA', 'CMA', 'TMA'], defval='OFF') trendFilterMethod = input.string(title='Trend Filter Method', options=['OFF', 'Normal', 'Reversed'], defval='OFF') maLength = input(14, title='MA Length') // Other Input Parameters lengthKC = input(30, title='Keltner Channels Length') multKC = input(0.7, title='Keltner Channels Multiplier') lengthCCI = input(5, title='CCI Length') overboughtCCI = input(75, title='CCI Overbought Level') oversoldCCI = input(-75, title='CCI Oversold Level') rsiPeriod = input(30, title='RSI Period') rsiOverbought = input(60, title='RSI Overbought Level') rsiOversold = input(60, title='RSI Oversold Level') volumeMultiplier = input.float(0, title='Volume Multiplier', step=0.1, minval=0) // Define Moving Averages var float maValue = na if maType == 'SMA' maValue := ta.sma(close, maLength) else if maType == 'EMA' maValue := ta.ema(close, maLength) else if maType == 'SMMA' float initialSMMA = ta.sma(close, maLength) maValue := na(maValue[1]) ? initialSMMA : (maValue[1] * (maLength - 1) + close) / maLength else if maType == 'CMA' float firstSMA = ta.sma(close, maLength) float secondSMA = ta.sma(close, maLength) maValue := na(maValue[1]) ? firstSMA : (firstSMA + secondSMA - maValue[1]) / 2 else if maType == 'TMA' maValue := ta.sma(ta.sma(close, math.round(maLength / 2)), math.round(maLength / 2) + 1) // Entry Conditions with Trend Filter longCondition = allowLong and (trendFilterMethod == 'OFF' or trendFilterMethod == 'Normal' and close > maValue or trendFilterMethod == 'Reversed' and close < maValue) shortCondition = allowShort and (trendFilterMethod == 'OFF' or trendFilterMethod == 'Normal' and close < maValue or trendFilterMethod == 'Reversed' and close > maValue) // Keltner Channels typicalPrice = hlc3 middleLine = ta.sma(typicalPrice, lengthKC) range_1 = multKC * ta.atr(lengthKC) upperChannel = middleLine + range_1 lowerChannel = middleLine - range_1 // CCI cci = ta.cci(close, lengthCCI) // RSI rsi = ta.rsi(close, rsiPeriod) // Volume volCondition = volume > ta.sma(volume, 50) * volumeMultiplier // Combined Entry Conditions with Trend Filter and state check longCondition := longCondition and cci < oversoldCCI and low < lowerChannel and rsi < rsiOversold and volCondition and not isLongOpen shortCondition := shortCondition and cci > overboughtCCI and high > upperChannel and rsi > rsiOverbought and volCondition and not isShortOpen // Execute orders at the open of the new bar after conditions are met if longCondition strategy.entry('Long', strategy.long) alert('LicenseID,buy,AUDNZD,risk=1') isLongOpen := true if shortCondition strategy.entry('Short', strategy.short) alert('LicenseID,sell,AUDNZD,risk=1') isShortOpen := true // Exit Conditions and Alerts longExitCondition = cci > 0 shortExitCondition = cci < 0 if (longExitCondition and isLongOpen) strategy.close('Long') alert('LiceneseID,closelong,AUDNZD') isLongOpen := false if (shortExitCondition and isShortOpen) strategy.close('Short') alert('LicenseID,closeshort,AUDNZD') isShortOpen := false // Plotting plot(upperChannel, color=color.new(color.red, 0), linewidth=1) plot(lowerChannel, color=color.new(color.green, 0), linewidth=1) hline(overboughtCCI, 'Overbought', color=color.red) hline(oversoldCCI, 'Oversold', color=color.green)