这是一个基于RSI指标和EMA均线的动量对冲交易策略。该策略采用了双重RSI时间周期(RSI-14和RSI-2)结合三重EMA均线(50、100、200)来捕捉市场趋势反转机会,并通过动态仓位管理实现对冲效果。策略的核心特点是在满足入场条件时逐步增加仓位,同时设置了基于RSI超买超卖的止盈条件。
策略使用RSI-14和RSI-2两个不同周期的相对强弱指数,配合EMA-50、EMA-100和EMA-200三条均线来确定交易信号。做多条件需要RSI-14低于31且RSI-2向上突破10,同时要求三条均线呈现空头排列(EMA-50 < EMA-100 < EMA-200)。做空条件则相反,要求RSI-14高于69且RSI-2向下突破90,同时三条均线呈现多头排列(EMA-50 > EMA-100 > EMA-200)。策略采用20倍杠杆,并在每次交易时基于当前权益动态计算交易数量。当现有仓位满足条件时,新开仓位会以两倍于当前仓位的数量进行交易。止盈条件基于RSI指标的反向突破设置。
这是一个结合了动量和趋势的综合性策略,通过多重技术指标的配合来提高交易的准确性。策略的创新点在于采用了动态的仓位管理方式和对冲机制,但同时也带来了较高的风险。通过优化风险控制机制和引入更多的过滤条件,该策略有望在实际交易中取得更好的表现。建议在实盘使用前进行充分的回测和参数优化。
/*backtest
start: 2024-11-26 00:00:00
end: 2024-12-03 00:00:00
period: 10m
basePeriod: 10m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/
//@version=5
strategy("Custom RSI EMA Strategy Hedge", overlay=true, default_qty_type=strategy.fixed, default_qty_value=1)
// Definování vstupních podmínek
rsi_14 = ta.rsi(close, 14)
rsi_2 = ta.rsi(close, 2)
ema_50 = ta.ema(close, 50)
ema_100 = ta.ema(close, 100)
ema_200 = ta.ema(close, 200)
// Pákový efekt
leverage = 20
// Podmínky pro long pozici
longCondition = (rsi_14[1] < 31) and ta.crossover(rsi_2, 10) and (ema_50 < ema_100) and (ema_100 < ema_200)
// Podmínky pro short pozici
shortCondition = (rsi_14[1] > 69) and ta.crossunder(rsi_2, 90) and (ema_50 > ema_100) and (ema_100 > ema_200)
// Identifikátory pozic
long_id = "Long"
short_id = "Short"
// Definování průměrné ceny pozice pro long a short
var float long_avg_price = na
var float short_avg_price = na
// Sledujeme, zda se velikost pozice změnila
var float last_long_position_size = na
var float last_short_position_size = na
// Přerušení průměrné ceny pozice při změně pozice
if (last_long_position_size != strategy.position_size and strategy.position_size > 0)
long_avg_price := na
if (last_short_position_size != strategy.position_size and strategy.position_size < 0)
short_avg_price := na
// Aktualizace průměrné ceny pozice
if (strategy.position_size > 0)
long_avg_price := strategy.position_avg_price
else
long_avg_price := na
if (strategy.position_size < 0)
short_avg_price := strategy.position_avg_price
else
short_avg_price := na
// Uložení aktuální velikosti pozice pro příští bar
if (strategy.position_size > 0)
last_long_position_size := strategy.position_size
else if (strategy.position_size < 0)
last_short_position_size := strategy.position_size
// Podmínky pro take profit
takeProfitLongCondition = (rsi_14 > 69) and (rsi_2 > 90) and (long_avg_price < close)
takeProfitShortCondition = (rsi_14 < 31) and (rsi_2 < 10) and (short_avg_price > close)
// Velikost pozice
new_long_position_size = strategy.position_size == 0 ? na : math.abs(strategy.position_size) * 2
new_short_position_size = strategy.position_size == 0 ? na : math.abs(strategy.position_size) * 2
// Úprava velikosti pozice s ohledem na pákový efekt
position_value = strategy.equity * leverage
trade_qty_long = position_value / close
trade_qty_short = position_value / close
// Vstup do long pozice s dvojnásobkem aktuální pozice nebo standardní velikostí při první pozici
if (longCondition)
strategy.entry(long_id, strategy.long, qty=new_long_position_size == na ? trade_qty_long : new_long_position_size)
// Vstup do short pozice s dvojnásobkem aktuální pozice nebo standardní velikostí při první pozici
if (shortCondition)
strategy.entry(short_id, strategy.short, qty=new_short_position_size == na ? trade_qty_short : new_short_position_size)
// Výstup z long pozice při splnění podmínek pro take profit
if (takeProfitLongCondition)
strategy.close(long_id)
// Výstup z short pozice při splnění podmínek pro take profit
if (takeProfitShortCondition)
strategy.close(short_id)
// Zvýraznění části grafu, kde platí podmínky pro long
highlightLongCondition = (ema_50 < ema_100) and (ema_100 < ema_200)
bgcolor(highlightLongCondition ? color.new(color.green, 90) : na)
// Zvýraznění části grafu, kde platí podmínky pro short
highlightShortCondition = (ema_50 > ema_100) and (ema_100 > ema_200)
bgcolor(highlightShortCondition ? color.new(color.red, 90) : na)
// Přidání bodů pozic do grafu
plotshape(series=longCondition, location=location.belowbar, color=color.green, style=shape.labelup, text="L")
plotshape(series=shortCondition, location=location.abovebar, color=color.red, style=shape.labeldown, text="S")
// Vykreslení průměrné ceny pozice pro long a short pouze pokud pozice existuje
plot(strategy.position_size > 0 ? long_avg_price : na, title="Long Avg Price", color=color.blue, linewidth=2)
plot(strategy.position_size < 0 ? short_avg_price : na, title="Short Avg Price", color=color.orange, linewidth=2)
// Zvýraznění čtverců pro RSI14 > 70 (červeně) a RSI14 < 30 (zeleně)
var int rsi_above_70_start = na
var int rsi_below_30_start = na
var float top_value_above_70 = na
var float bottom_value_above_70 = na
var float top_value_below_30 = na
var float bottom_value_below_30 = na
// Identifikace začátku a konce období pro RSI14 > 70
if (rsi_14[1] > 70 and rsi_14[2] > 70)
if na(rsi_above_70_start)
rsi_above_70_start := bar_index
top_value_above_70 := high
bottom_value_above_70 := low
else
top_value_above_70 := math.max(top_value_above_70, high)
bottom_value_above_70 := math.min(bottom_value_above_70, low)
else
if not na(rsi_above_70_start)
// box.new(left = rsi_above_70_start, right = bar_index - 1, top = top_value_above_70, bottom = bottom_value_above_70, border_color = color.red, border_width = 2, bgcolor=color.new(color.red, 90))
rsi_above_70_start := na
top_value_above_70 := na
bottom_value_above_70 := na
// Identifikace začátku a konce období pro RSI14 < 30
if (rsi_14[1] < 30 and rsi_14[2] < 30)
if na(rsi_below_30_start)
rsi_below_30_start := bar_index
top_value_below_30 := high
bottom_value_below_30 := low
else
top_value_below_30 := math.max(top_value_below_30, high)
bottom_value_below_30 := math.min(bottom_value_below_30, low)
else
if not na(rsi_below_30_start)
// box.new(left = rsi_below_30_start, right = bar_index - 1, top = top_value_below_30, bottom = bottom_value_below_30, border_color = color.green, border_width = 2, bgcolor=color.new(color.green, 90))
rsi_below_30_start := na
top_value_below_30 := na
bottom_value_below_30 := na