RSI-VWAP 볼륨 가격 전략


생성 날짜: 2023-10-08 13:52:09 마지막으로 수정됨: 2023-10-08 13:52:09
복사: 0 클릭수: 1135
avatar of ChaoZhang ChaoZhang
1
집중하다
1617
수행원

개요

RSI-VWAP 계량 전략은 추세에 따라가는 전략이다. 그것은 상대적으로 강한 지수 ((RSI) 와 거래량 가중 평균 가격 ((VWAP) 두 가지 지표를 결합하여, 추세에서 여러 번 가중점과 손실을 실현한다. 이 전략은 중장선 추세 거래에 적합하다.

원칙

RSI 지표선이 초과구역에서 다시 초과구역으로 내려오면, 트렌드가 반전되었다고 생각하며, 더 많은 것을 한다. RSI 지표선이 초과구역에서 올라와서 초과구역으로 들어갔을 때, 트렌드가 반전되었다고 생각하며, 더 많은 것을 한다.

다중 포지션의 스톱 라인은 최신 포지션 개시 가격의 ((1-스톱 손실 비율), 스톱 라인은 포지션 보유 평균 가격의 ((1+스톱 비율); 빈 포지션은 비슷하다.

매번 포지션 개설 후, 다시 신호를 유발하면, 포지션을 추가할 수 있으며, 최대 5번의 포지션이 추가되며, 매번의 포지션이 증가하여 트렌드 추적을 구현한다.

장점

  1. RSI와 VWAP를 결합하면 트렌드 반전 지점을 더 잘 판단할 수 있다.

  2. 여러 번 상장하면 트렌드 상황을 최대한 활용할 수 있다. 상장 횟수가 증가함에 따라 상장량이 점차 확대되어 트렌드 추적이 가능하다.

  3. 스톱로스 라인을 설정하여 위험을 효과적으로 제어할 수 있다. 지분을 보유한 경우 손실이 발생하면 스톱로스 출구, 손실이 더 확대되는 것을 방지한다.

  4. 트래킹 스톱을 설정하고, 수익을 잠금하고, 수익의 회귀를 방지한다.

위험

  1. RSI 지표에는 리파인트 현상이 존재하며, 실제 신호 트리거 포인트에서 오차가 발생할 수 있다.

  2. VWAP에도 리파인트가 있을 수 있다. 실제 최적의 입구점은 나중에 결정될 것이다.

  3. 스톱포인트 설정이 잘못되면 불필요한 손실이 발생할 수 있습니다.

  4. 이 경우, 수익을 달성하지 못할 수도 있습니다.

  5. 트렌드를 잘못 판단하고 계속 더 많이 하는 것은 손실을 확대시킬 수 있다.

최적화

  1. RSI 파라미터를 최적화하여 최적의 길이주기를 찾습니다.

  2. 오버 바이 오버 셀 영역을 최적화하여 트렌드 반전을 더 정확하게 판단할 수 있습니다.

  3. 다양한 포장 전략을 테스트하여 최적의 포장을 찾아보세요.

  4. 손해 막을 최적화하여 최적의 변수를 찾습니다.

  5. 트렌드를 판단하는 다른 지표와 결합하여 트렌드 반전의 가능성을 높이는 시도.

요약하다

RSI-VWAP 계량 전략, RSI 지표와 VWAP 지표를 결합하여 트렌드 반전점을 판단하고, 여러 번 상장하여 트렌드 상황을 추적하고, 수익이 기본 기준에 도달하면 중지하고, 손실이 발생하면 중지하고, 위험 제어 및 수익 보호를 종합적으로 고려합니다. 매개 변수를 최적화하면 더 나은 전략 효과를 얻을 수 있습니다. 이 전략은 경험이있는 거래자에게 적합합니다.

전략 소스 코드
/*backtest
start: 2023-09-07 00:00:00
end: 2023-10-07 00:00:00
period: 2h
basePeriod: 15m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © Xaviz

//#####©ÉÉÉɶN###############################################
//####*..´´´´´´,,,»ëN########################################
//###ë..´´´´´´,,,,,,''%©#####################################
//###'´´´´´´,,,,,,,'''''?¶###################################
//##o´´´´´´,,,,,,,''''''''*©#################################
//##'´´´´´,,,,,,,'''''''^^^~±################################
//#±´´´´´,,,,,,,''''''''^í/;~*©####æ%;í»~~~~;==I±N###########
//#»´´´´,,,,,,'''''''''^;////;»¶X/í~~/~~~;=~~~~~~~~*¶########
//#'´´´,,,,,,''''''''^^;////;%I^~/~~/~~~=~~~;=?;~~~~;?ë######
//©´´,,,,,,,''''''''^^~/////X~/~~/~~/~~»í~~=~~~~~~~~~~^;É####
//¶´,,,,,,,''''''''^^^;///;%;~/~~;í~~»~í?~?~~~?I/~~~~?*=íÑ###
//N,,,,,,,'''''''^^^^^///;;o/~~;;~~;£=»í»;IX/=~~~~~~^^^^'*æ##
//#í,,,,,''''''''^^^^^;;;;;o~»~~~~íX//~/»~;í?IíI»~~^/*?'''=N#
//#%,,,'''''''''^^^^^^í;;;;£;~~~//»I»/£X/X/»í*&~~~^^^^'^*~'É#
//#©,,''''''''^^^^^^^^~;;;;&/~/////*X;í;o*í»~=*?*===^'''''*£#
//##&''''''''^^^^^^^^^^~;;;;X=í~~~»;;;/~;í»~»±;^^^^^';=''''É#
//##N^''''''^^^^^^^^^^~~~;;;;/£;~~/»~~»~~///o~~^^^^''''?^',æ#
//###Ñ''''^^^^^^^^^^^~~~~~;;;;;í*X*í»;~~IX?~~^^^^/?'''''=,=##
//####X'''^^^^^^^^^^~~~~~~~~;;íííííí~~í*=~~~~Ií^'''=''''^»©##
//#####£^^^^^^^^^^^~~~~~~~~~~~íííííí~~~~~*~^^^;/''''='',,N###
//######æ~^^^^^^^^~~~~~~~~~~~~~~íííí~~~~~^*^^^'=''''?',,§####
//########&^^^^^^~~~~~~~~~~~~~~~~~~~~~~~^^=^^''=''''?,íN#####
//#########N?^^~~~~~~~~~~~~~~~~~~~~~~~~^^^=^''^?''';í@#######
//###########N*~~~~~~~~~~~~~~~~~~~~~~~^^^*'''^='''/É#########
//##############@;~~~~~~~~~~~~~~~~~~~^^~='''~?'';É###########
//#################É=~~~~~~~~~~~~~~^^^*~'''*~?§##############
//#####################N§£I/~~~~~~»*?~»o§æN##################

//@version=4
// strategy("RSI-VWAP", overlay=true, initial_capital = 1000, currency = "USD", pyramiding = 5, default_qty_type = strategy.cash, default_qty_value = 1000, commission_value = 0.04)

//Uncomment for alerts
//study("RSI-VWAP INDICATOR", overlay=true)

// ================================================================================================================================================================================
// VARIABLES
// ================================================================================================================================================================================

var bool longCondition = na, var bool shortCondition = na, var bool Xlong = na,
var int CondIni_Xlong = 0, var bool XlongCondition = na
var float last_open_longCondition = na, var float last_open_shortCondition = na
var int last_longCondition = 0, var int last_shortCondition = 0
var int last_long_sl = na, var int last_short_sl = na
var bool CondIni_long_sl = 0, var bool CondIni_short_sl = 0
var int nLongs = na, var int nShorts = na, var int pyr = na
var float sum_long = 0.0, var float sum_short = 0.0
var float Position_Price = 0.0, Position_Price := nz(Position_Price[1])
var bool Final_Long_sl = na, var bool Final_Short_sl = na, var bool Act_sl = na, var float sl = na
var int last_long_tp = na, var int last_short_tp = na
var bool CondIni_long_tp = 0, var bool CondIni_short_tp = 0
var float Quantity = na, var float Increase = na
var float sum_qty_l = na, var float sum_qty_s = na

// ================================================================================================================================================================================
// RSI VWAP INDICATOR
// ================================================================================================================================================================================

// Initial inputs
Positions = input("LONG ONLY", "LONG / SHORT", options = ["LONG & SHORT","LONG ONLY"])
Long_only = Positions == "LONG ONLY" ? true : na
Act_RSI_VWAP = input(true, "RSI VOLUME WEIGHTED AVERAGE PRICE")
RSI_VWAP_length = input(17, "RSI-VWAP LENGTH")
RSI_VWAP_overSold = input(19, "RSI-VWAP OVERSOLD", type=input.float)
RSI_VWAP_overBought = input(80, "RSI-VWAP OVERBOUGHT", type=input.float)

// RSI with VWAP as source
RSI_VWAP = rsi(vwap(close), RSI_VWAP_length)

// Plotting, overlay=false
//r=plot(RSI_VWAP, color = RSI_VWAP > RSI_VWAP_overBought ? color.red : RSI_VWAP < RSI_VWAP_overSold ? color.lime : color.teal, title="rsi", linewidth=2, style=plot.style_line)
//h1=plot(RSI_VWAP_overBought, color = color.gray, style=plot.style_stepline)
//h2=plot(RSI_VWAP_overSold, color = color.gray, style=plot.style_stepline)
//fill(r,h1, color = RSI_VWAP > RSI_VWAP_overBought ? color.red : na, transp = 75)
//fill(r,h2, color = RSI_VWAP < RSI_VWAP_overSold ? color.lime : na, transp = 75)

// ================================================================================================================================================================================
// STRATEGY
// ================================================================================================================================================================================

// Long/Short/Xlong Conditions
longCondition := (crossover(RSI_VWAP, RSI_VWAP_overSold)) and (nz(nLongs[1]) < pyr)
shortCondition := (crossunder(RSI_VWAP, RSI_VWAP_overBought)) and (nz(nShorts[1]) < pyr) and not Long_only
Xlong := (crossunder(RSI_VWAP, RSI_VWAP_overBought)) and Long_only
CondIni_Xlong := longCondition ? 1 : Xlong ? -1 : nz(CondIni_Xlong[1])
XlongCondition := Xlong and nz(CondIni_Xlong[1]) == 1

// Get the price of the last opened long or short
last_open_longCondition := longCondition ? close : nz(last_open_longCondition[1])
last_open_shortCondition := shortCondition ? close : nz(last_open_shortCondition[1])

// Get the bar time of the last opened long or short
last_longCondition := longCondition ? time : nz(last_longCondition[1])
last_shortCondition := shortCondition ? time : nz(last_shortCondition[1])

// In long/short conditions
in_longCondition = last_longCondition > last_shortCondition
in_shortCondition = last_shortCondition > last_longCondition

// ================================================================================================================================================================================
// PRICE AVERAGE / PYRAMIDING
// ================================================================================================================================================================================

// Pyramiding
pyr := input(5, "PYRAMIDING 🎢")

// Counting long & short iterations
nLongs := nz(nLongs[1])
nShorts := nz(nShorts[1])

// Longs Counter
if longCondition or (Final_Long_sl and not Act_sl)
    nLongs := nLongs + 1
    nShorts := na
    
// Shorts Counter
if shortCondition or (Final_Short_sl and not Act_sl)
    nLongs := na
    nShorts := nShorts + 1

// Quantity Factor
QF_l = Quantity+(Increase*(nLongs-1))
QF_s = Quantity+(Increase*(nShorts-1))

// Price average of your position according to the quantities
if longCondition
    sum_long := nz(last_open_longCondition)*QF_l + nz(sum_long[1])
    sum_short := 0.0
    sum_qty_l := QF_l + nz(sum_qty_l[1])
    sum_qty_s := na
    
if Final_Long_sl and not Act_sl
    sum_long := ((1-(sl/100))*last_open_longCondition)*QF_l + nz(sum_long[1])
    sum_short := 0.0
    sum_qty_l := QF_l + nz(sum_qty_l[1])
    sum_qty_s := na
    
if shortCondition
    sum_short := nz(last_open_shortCondition)*QF_s + nz(sum_short[1])
    sum_long := 0.0
    sum_qty_s := QF_s + nz(sum_qty_s[1])
    sum_qty_l := na
    
if Final_Short_sl and not Act_sl
    sum_long := 0.0
    sum_short := ((1+(sl/100))*last_open_shortCondition)*QF_s + nz(sum_short[1])
    sum_qty_s := QF_s + nz(sum_qty_s[1])
    sum_qty_l := na
    
// Calculating and Plotting the price average
Position_Price := nz(Position_Price[1])
Position_Price := longCondition or (Final_Long_sl and not Act_sl) ? sum_long/(sum_qty_l) : shortCondition or (Final_Short_sl and not Act_sl) ? sum_short/(sum_qty_s) : na
plot(Position_Price[1], title = "Average Price", color = in_longCondition ? color.blue : color.red, linewidth = 2, style = plot.style_cross, transp = 0)

// ================================================================================================================================================================================
// STOP LOSS / RE-ENTRY
// ================================================================================================================================================================================

// SL initial inputs
Act_sl := input(true, "ACTIVATE SL / DEACTIVATE RE-ENTRY")
sl := input(7.5, "STOP LOSS / RE-ENTRY %", type = input.float, minval = 0, step = 0.5)

// Initial SL conditions
long_sl = crossunder(low, (1-(sl/100))*last_open_longCondition) and in_longCondition and not longCondition
short_sl = crossover(high, (1+(sl/100))*last_open_shortCondition) and in_shortCondition and not shortCondition

// Get the time of the last sl
last_long_sl := long_sl ? time : nz(last_long_sl[1])
last_short_sl := short_sl ? time : nz(last_short_sl[1])

// Sl counter
CondIni_long_sl := long_sl ? 1 : longCondition ? -1 : nz(CondIni_long_sl[1])
CondIni_short_sl := short_sl ? 1 : shortCondition ? -1 : nz(CondIni_short_sl[1])

// Final SL conditions
Final_Long_sl := long_sl and nz(CondIni_long_sl[1]) == -1 and in_longCondition and not longCondition
Final_Short_sl := short_sl and nz(CondIni_short_sl[1]) == -1 and in_shortCondition and not shortCondition

// ================================================================================================================================================================================
// TAKE PROFIT
// ================================================================================================================================================================================

// Take Profit input
Act_tp = input(false, "ACTIVATE TAKE PROFIT")
tp = input(10.0, "TAKE PROFIT %", type = input.float, minval = 0, step = 0.5)

// Initial TP conditions
long_tp = crossover(high, (1+(tp/100))*fixnan(Position_Price)) and in_longCondition and not longCondition and not Final_Long_sl and Act_tp
short_tp = crossunder(low, (1-(tp/100))*fixnan(Position_Price)) and in_shortCondition and not shortCondition and not Final_Short_sl and Act_tp

// Get the time of the last tp
last_long_tp := long_tp ? time : nz(last_long_tp[1])
last_short_tp := short_tp ? time : nz(last_short_tp[1])

// Tp signal ordering
CondIni_long_tp := (Final_Long_sl and Act_sl) or XlongCondition ? 1 : longCondition ? -1 : nz(CondIni_long_tp[1])
CondIni_short_tp := Final_Short_sl and Act_sl ? 1 : shortCondition ? -1 : nz(CondIni_short_tp[1])

// Final tp condition
Final_Long_tp = long_tp and last_longCondition > nz(last_long_tp[1]) and nz(CondIni_long_tp[1]) == -1
Final_Short_tp = short_tp and last_shortCondition > nz(last_short_tp[1]) and nz(CondIni_short_tp[1]) == -1

if Final_Long_tp or (Final_Long_sl and Act_sl) or XlongCondition
    sum_long := 0.0
    nLongs := na
    CondIni_long_sl := 1
    sum_qty_l := na
    
if Final_Short_tp or (Final_Short_sl and Act_sl)
    sum_short := 0.0
    nShorts := na
    CondIni_short_sl := 1
    sum_qty_s := na
    
// ================================================================================================================================================================================
// SIGNALS
// ================================================================================================================================================================================

// Longs
// label.new(
//    x = longCondition[1] ? time : na, 
//    y = na, 
//    text = 'LONG '+tostring(nLongs), 
//    color = color.blue, 
//    textcolor = color.black,  
//    style = label.style_labelup, 
//    xloc = xloc.bar_time, 
//    yloc = yloc.belowbar,
//    size = size.tiny
//    )

// // Shorts
// label.new(
//    x = shortCondition[1] ? time : na, 
//    y = na, 
//    text = 'SHORT '+tostring(nShorts), 
//    color = color.red, 
//    textcolor = color.black,  
//    style = label.style_labeldown, 
//    xloc = xloc.bar_time, 
//    yloc = yloc.abovebar,
//    size = size.tiny
//    )

// // XLongs
// label.new(
//    x = XlongCondition[1] ? time : na, 
//    y = na, 
//    text = 'XLONG', 
//    color = color.yellow, 
//    textcolor = color.black,  
//    style = label.style_labeldown, 
//    xloc = xloc.bar_time, 
//    yloc = yloc.abovebar,
//    size = size.tiny
//    )
   
// // Tp on longs
// label.new(
//    x = Final_Long_tp ? time : na, 
//    y = na, 
//    text = 'TP '+tostring(tp)+'%', 
//    color = color.orange, 
//    textcolor = color.black,  
//    style = label.style_labeldown, 
//    xloc = xloc.bar_time, 
//    yloc = yloc.abovebar,
//    size = size.tiny
//    ) 

ltp = iff(Final_Long_tp, (fixnan(Position_Price)*(1+(tp/100))), na), plot(ltp, style=plot.style_cross, linewidth=3, color = color.white, editable = false)

// Tp on shorts
// label.new(
//    x = Final_Short_tp ? time : na, 
//    y = na, 
//    text = 'TP '+tostring(tp)+'%', 
//    color = color.orange, 
//    textcolor = color.black,  
//    style = label.style_labelup, 
//    xloc = xloc.bar_time, 
//    yloc = yloc.belowbar,
//    size = size.tiny
//    )
   
stp = iff(Final_Short_tp, (fixnan(Position_Price)*(1-(tp/100))), na), plot(stp, style=plot.style_cross, linewidth=3, color = color.white, editable = false)

// Sl on Longs
// label.new(
//    x = Final_Long_sl ? time : na, 
//    y = na, 
//    text = Act_sl ? ('SL '+tostring(sl)+'%') : ('RE '+tostring(sl)+'%'), 
//    color = color.green, 
//    textcolor = color.black,  
//    style = label.style_labelup, 
//    xloc = xloc.bar_time, 
//    yloc = yloc.belowbar,
//    size = size.tiny
//    )
   
// Sl on Longs dot   
lsl = iff(Final_Long_sl, (last_open_longCondition*(1-(sl/100))), na), plot(lsl, style=plot.style_cross, linewidth=3, color = color.white, editable = false)

// Sl on Shorts
// label.new(
//    x = Final_Short_sl ? time : na, 
//    y = na, 
//    text = Act_sl ? ('SL '+tostring(sl)+'%') : ('RE '+tostring(sl)+'%'), 
//    color = color.maroon, 
//    textcolor = color.black,  
//    style = label.style_labeldown, 
//    xloc = xloc.bar_time, 
//    yloc = yloc.abovebar,
//    size = size.tiny
//    ) 

// Sl on Shorts dot
ssl = iff(Final_Short_sl, (last_open_shortCondition*(1+(sl/100))), na), plot(ssl, style=plot.style_cross, linewidth=3, color = color.white, editable = false)

// ================================================================================================================================================================================
// BACKTEST
// ================================================================================================================================================================================

// Backtest inputs
Act_BT = input(true, "BACKTEST 💹")
Quantity := input(1000, "$ QUANTITY 1ST ENTRY")/close
Increase := input(500, "$ INCREASE NEXT ENTRY")/close

// Backtest Period inputs
testStartYear = input(2019, "BACKTEST START YEAR ⏲️", minval = 1980, maxval = 2222) 
testStartMonth = input(01, "BACKTEST START MONTH", minval = 1, maxval = 12)
testStartDay = input(01, "BACKTEST START DAY", minval = 1, maxval = 31)
testPeriodStart = timestamp(testStartYear,testStartMonth,testStartDay,0,0)
testStopYear = input(2222, "BACKTEST STOP YEAR", minval=1980, maxval = 2222)
testStopMonth = input(12, "BACKTEST STOP MONTH", minval=1, maxval=12)
testStopDay = input(31, "BACKTEST STOP DAY", minval=1, maxval=31)
testPeriodStop = timestamp(testStopYear, testStopMonth, testStopDay, 0, 0)

// Backtest Condition
testPeriod = true

// Backtest entries
if (Act_BT and not na(RSI_VWAP) and testPeriod)
    strategy.entry("Long", strategy.long, qty = QF_l, when = longCondition or (Final_Long_sl and not Act_sl))
    strategy.close("Long", when = XlongCondition)
    strategy.entry("Short", strategy.short, qty = QF_s, when = (shortCondition or (Final_Short_sl and not Act_sl)))
    strategy.exit("XL", "Long", limit = Act_tp ? (fixnan(Position_Price)*(1+(tp/100))) : na, stop = (Act_sl ? (1-(sl/100))*last_open_longCondition : na))
    strategy.exit("XS", "Short", limit = Act_tp ? (fixnan(Position_Price)*(1-(tp/100))) : na, stop = (Act_sl ? (1+(sl/100))*last_open_shortCondition : na))

// ================================================================================================================================================================================
// ALERTS
// ================================================================================================================================================================================

alertcondition((longCondition[1] or (Final_Long_sl and not Act_sl)) and nLongs == 1, title="Long 1 Alert", 
   message = "LONG1")
alertcondition((longCondition[1] or (Final_Long_sl and not Act_sl)) and nLongs == 2, title="Long 2 Alert", 
   message = "LONG2")
alertcondition((longCondition[1] or (Final_Long_sl and not Act_sl)) and nLongs == 3, title="Long 3 Alert", 
   message = "LONG3")
alertcondition((longCondition[1] or (Final_Long_sl and not Act_sl)) and nLongs == 4, title="Long 4 Alert", 
   message = "LONG4")
alertcondition((longCondition[1] or (Final_Long_sl and not Act_sl)) and nLongs == 5, title="Long 5 Alert", 
   message = "LONG5")

alertcondition(Final_Long_tp or (Final_Long_sl and Act_sl), title="TPL/SLL Alert", 
   message = "TPL/SLL")

alertcondition((shortCondition[1] or (Final_Short_sl and not Act_sl)) and nShorts == 1, title="Short 1 Alert", 
   message = "SHORT1")
alertcondition((shortCondition[1] or (Final_Short_sl and not Act_sl)) and nShorts == 2, title="Short 2 Alert", 
   message = "SHORT2")
alertcondition((shortCondition[1] or (Final_Short_sl and not Act_sl)) and nShorts == 3, title="Short 3 Alert", 
   message = "SHORT3")
alertcondition((shortCondition[1] or (Final_Short_sl and not Act_sl)) and nShorts == 4, title="Short 4 Alert", 
   message = "SHORT4")
alertcondition((shortCondition[1] or (Final_Short_sl and not Act_sl)) and nShorts == 5, title="Short 5 Alert", 
   message = "SHORT5")

alertcondition(Final_Short_tp or (Final_Short_sl and Act_sl), title="TPS/SLS Alert", 
   message = "TPS/SLS")

// by Xaviz