资源加载中... loading...

CCI+RSI+KC趋势滤波多空双向交易策略

Author: ChaoZhang, Date: 2024-05-15 16:56:03
Tags: CCIRSIKCSMAEMASMMACMATMA

CCI+RSI+KC趋势滤波多空双向交易策略

概述

本策略采用CCI、RSI和肯特纳通道(KC)三种技术指标,结合趋势过滤器,实现在AUDNZD和GBPNZD货币对上的多空双向交易。策略通过CCI和RSI来判断超买超卖情况,KC作为止损止盈的参考依据,同时使用移动平均线作为趋势过滤,在顺势的情况下进行开仓操作。该策略已经在过去5年的历史数据上进行了回测,取得了稳定的收益。

策略原理

  1. 计算CCI、RSI和KC指标。KC上轨为中线加上ATR,下轨为中线减去ATR。
  2. 根据输入参数选择移动平均线类型(SMA、EMA、SMMA、CMA或TMA)和趋势过滤方法(关闭、正向或反向)。
  3. 多头开仓条件:允许做多、CCI<超卖线、收盘价50周期均量*倍数、当前无多头仓位。
  4. 空头开仓条件:允许做空、CCI>超买线、收盘价>KC上轨、RSI>超买线、成交量>50周期均量*倍数、当前无空头仓位。
  5. 多头平仓条件:CCI>0。空头平仓条件:CCI。
  6. 开仓时发出警报,平仓时也发出警报。

策略优势

  1. 结合多个指标进行综合判断,提高信号准确性。
  2. 采用趋势过滤方法,可以根据市场趋势灵活调整,顺势而为。
  3. 移动平均线类型可选,适应不同的市场特点。
  4. 已经过长时间的历史数据验证,稳定性好,适合长期使用。
  5. 双向交易,适应各种行情,获利机会多。
  6. 自动化程度高,不需要人工干预,省时省力。

策略风险

  1. 缺乏传统的止损止盈,遇到极端行情可能出现较大回撤。
  2. 在震荡市可能出现频繁开平仓,交易成本增加。
  3. 使用了相对较短的CCI周期,可能出现噪音信号。
  4. 在趋势不明朗或市场波动加大时,趋势过滤作用有限。
  5. 固定仓位,不能自适应市场波动率的变化。

策略优化方向

  1. 可以考虑增加移动止损或固定点数止损,控制单笔交易风险。
  2. RSI和CCI的参数可以进一步优化,以减少噪音信号。
  3. 可以考虑引入波动率指标如ATR,根据市场波动调整仓位和止损。
  4. 增加更多货币对,并根据每个品种特点单独优化参数。
  5. 尝试引入机器学习等人工智能技术,自适应优化参数。

总结

该策略采用了多个经典指标,trading view上编写和回测都比较方便。回测效果不错,但实盘中还需注意控制风险,调整参数。建议先小资金测试,积累经验后再逐步加大投入。机械化程度高,适合稳健型投资者长期使用。


/*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)


相关内容

更多内容