Chiến lược giao dịch dao động động động lực RSI Stochastic

Tác giả:ChaoZhang, Ngày: 2023-12-26 12:11:21
Tags:

img

Tổng quan

Bài viết này chủ yếu giải thích một chiến lược giao dịch dao động động dựa trên chỉ số Stochastic RSI. Chiến lược này áp dụng các chỉ số kỹ thuật chu kỳ ngắn hơn (như 30 phút) để đưa ra quyết định giao dịch dựa trên việc liệu Stochastic RSI có đi vào khu vực mua quá mức / bán quá mức hay không. So với các chiến lược động lực khác, chiến lược này kết hợp các lợi thế của cả chỉ số RSI và Stochastic để nắm bắt chính xác hơn các dao động thị trường ngắn hạn.

Nguyên tắc chiến lược

Chỉ số cốt lõi của chiến lược là Stochastic RSI. Công thức tính toán của Stochastic RSI là:

Chỉ số RSI ngẫu nhiên = (RSI - RSI thấp) / (RSI cao - RSI thấp) * 100

Trong đó RSI được tính bằng cách sử dụng tham số lengthRSI (bên mặc định 12), và Stochastic RSI được tính bằng cách sử dụng tham số lengthStoch (bên mặc định 12).

Khi Stochastic RSI cao hơn khu vực màu tím, đó là khu vực mua quá mức, sau đó mua ngắn; khi Stochastic RSI thấp hơn khu vực màu tím, đó là khu vực bán quá mức, sau đó mua dài.

Ngoài ra, chiến lược cũng thiết lập điều kiện lọc trung bình động. Chỉ khi EMA nhanh cao hơn EMA chậm bạn có thể mở một vị trí dài; chỉ khi EMA nhanh thấp hơn EMA chậm bạn có thể mở một vị trí ngắn. Điều này tránh giao dịch ngược xu hướng.

Ưu điểm của Chiến lược

So với một chiến lược RSI duy nhất, chiến lược này kết hợp chỉ số Stochastic để xác định rõ hơn các khu vực mua quá mức / bán quá mức, do đó cải thiện độ tin cậy của tín hiệu.

So với một chiến lược Stochastic duy nhất, chiến lược này sử dụng RSI làm nguồn dữ liệu đầu vào của Stochastic, có thể lọc ra một số tiếng ồn và làm cho tín hiệu đáng tin cậy hơn.

Điều kiện lọc trung bình động được thiết lập để tránh hiệu quả việc xây dựng các vị trí ngược xu hướng, do đó giảm thiểu tổn thất không cần thiết.

Thời gian trì hoãn vị trí được thiết lập để tránh bị dừng lại bởi các vụ phá vỡ sai.

Rủi ro của chiến lược

Chiến lược chủ yếu sử dụng các chỉ số chu kỳ ngắn, vì vậy nó chỉ phù hợp với các hoạt động ngắn hạn và có thể không hoạt động tốt trong dài hạn.

Chỉ số Stochastic RSI có một sự chậm trễ nhất định và có thể bỏ lỡ tín hiệu sau những thay đổi giá mạnh mẽ trong ngắn hạn.

Trong các thị trường dao động, Stochastic RSI có thể tạo ra nhiều lần thâm nhập vào các khu vực mua quá mức / bán quá mức, có thể dẫn đến giao dịch quá mức và tăng chi phí giao dịch.

Hướng dẫn tối ưu hóa

  1. Các kết hợp tham số khác nhau có thể được thử nghiệm để tối ưu hóa thêm giá trị chiều dài, K và D của Stochastic RSI.

  2. Các thông số độ dài RSI khác nhau có thể được thử nghiệm để tìm một chu kỳ RSI phù hợp hơn.

  3. Hãy thử kết hợp với các chỉ số khác để cải thiện thêm độ chính xác tín hiệu, chẳng hạn như MACD, Bollinger Bands, v.v.

  4. Kiểm tra các thông số trì hoãn giữ vị trí khác nhau để tìm thời gian thoát phù hợp hơn.

Kết luận

Bài viết này chi tiết các nguyên tắc xây dựng, lợi thế, rủi ro và ý tưởng tối ưu hóa của một chiến lược đà dựa trên chỉ số Stochastic RSI. So với các chiến lược chỉ số duy nhất, chiến lược này sử dụng điểm mạnh của cả RSI và Stochastic để xác định rõ ràng và đáng tin cậy hơn các hiện tượng mua/bán quá mức ngắn hạn trên thị trường cho giao dịch đảo ngược.


/*backtest
start: 2023-11-25 00:00:00
end: 2023-12-25 00:00:00
period: 1h
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/
// © Drun30 (Federico Magnani)

//@version=4
//STRATEGIA PRINCIPALE
capitaleIniziale=10000

var sizeordineInit= 50 // → % di capitale investita per ogni trade
var deltaSize = 25 // → delta% di capitale investito se trade precedente è stato in perdita
var sizeLimite = 100 //il trade non userà mai questa percentuale di capitale investito
var sizeordine = sizeordineInit

//Parametri ottimali 30 min
usiShort=false
usiLong=true
ipercomprato=85.29
ipervenduto=30.6
//

strategy("Momentum Strategy (V7.B.4)", initial_capital=capitaleIniziale, currency="USD", default_qty_type=strategy.percent_of_equity, commission_type=strategy.commission.percent, commission_value=0.1, slippage = 5, default_qty_value=sizeordineInit, overlay=false, pyramiding=0)

backtest = input(title="------------------------Backtest Period------------------------", defval = false)
start = timestamp(input(2020, "start year"), input(1, "start month"), input(1, "start day"), 00, 00)
end = timestamp(input(0, "end year"), input(0, "end month"), input(0, "end day"), 00, 00) 

siamoindata=time > start?true:false
if end > 0
    siamoindata:=time > start and time <= end?true:false

basicParameters = input(title="------------------------Basic Parameters------------------------", defval = false)
smoothK = input(3, minval=1)
smoothD = input(6, minval=1)
lengthRSI = input(12, minval=1) 
src = input(close, title="RSI Source")
rsi1 = rsi(src, lengthRSI)
lengthStoch = input(12, minval=1)
k = ema(stoch(rsi1, rsi1, rsi1, lengthStoch), smoothK)
d = ema(k, smoothD)
altezzaipercomprato= input(ipercomprato, title="Overbought Height", minval=1, type=input.float)
altezzaipervenduto= input(ipervenduto, title="Oversold Height", minval=1,type=input.float) 

BarsDelay = input(6,title="Bars delay",minval=0) 

GambleSizing = input(true, title = "Gamble Sizing?",type=input.bool)
gambleAdd = input(deltaSize,title="Gamble Add (%)",minval=0,type=input.integer)
gambleLimit = input(sizeLimite,title="Gamble MAX (%)",minval=0,type=input.integer)
if GambleSizing and strategy.closedtrades[0]>strategy.closedtrades[1]
    if strategy.losstrades[0]>strategy.losstrades[1] and sizeordine<gambleLimit
        sizeordine:=sizeordine+gambleAdd
    if strategy.wintrades[0]>strategy.wintrades[1]
        sizeordine:=sizeordineInit

periodomediamobile_fast = input(1, title="Fast EMA length",minval=1)
periodomediamobile_slow = input(60, title="Slow EMA length",minval=1)

plot(k, color=color.blue)
plot(d, color=color.orange)
h0 = hline(altezzaipercomprato)
h1 = hline(altezzaipervenduto)
fill(h0, h1, color=color.purple, transp=80)
// n=input(Vicinanzadalcentro,title="Vicinanza dal centro",minval=0) 
//sarebbe il livello di D in cui si acquista o si vende, maggiore è la vicinanza maggiore sarà la frequenza dei trades, SE 0 è DISABILITATO

//     siamoinipervenduto= d<=altezzaipervenduto and d<=d[n] and d>d[1]?true:false //and d<d[3] and d>d[1]
//     siamoinipercomprato= d>=altezzaipercomprato and d>=d[n] and d<d[1]?true:false //and d>d[3] and d<d[1]
goldencross = crossover(k,d)
deathcross = crossunder(k,d)
// METTI VARIABILE IN CUI AVVIENE CROSSOVER O CROSSUNDER
valoreoro = valuewhen(goldencross,d,0)
valoremorte = valuewhen(deathcross,d,0)

siamoinipervenduto = goldencross and valoreoro<=altezzaipervenduto?true:false//d<=altezzaipervenduto?true:false
siamoinipercomprato = deathcross and valoremorte>=altezzaipercomprato?true:false//d>=altezzaipercomprato?true:false

long_separator = input(title="------------------------LONG------------------------", defval = usiLong)

sl_long_inp = input(10, title="Stop Loss LONG %", type=input.float) 
tp_long_inp = input(8, title="Take Profit LONG %",type=input.float)
stop_level_long = strategy.position_avg_price * (1 - (sl_long_inp/100)) //strategy.position_avg_price corrisponde al prezzo con cui si è aperta la posizione
take_level_long = strategy.position_avg_price * (1 + (tp_long_inp/100))

//BINANCE
JSON_long = 'OPEN LONG: PUT THE JSON HERE FOR THE API CALL'
JSON_chiusura = 'CLOSE POSITION: PUT THE JSON HERE FOR THE API CALL' 

webhookLong = JSON_long
webhookClose= JSON_chiusura

trendFilterL = input(title="TREND FILTER LONG?", defval = true)

EMAfast=ema(close,periodomediamobile_fast)
EMAslow=ema(close,periodomediamobile_slow)

siamoinuptrend_ema=EMAfast>EMAslow?true:false //close>=EMAfast and EMAfast>EMAslow
siamoinuptrend = siamoinuptrend_ema

// CondizioneAperturaLong = siamoinipervenduto and siamoindata // and siamoinuptrend
CondizioneAperturaLong = siamoinipervenduto and siamoindata and long_separator
if trendFilterL
    CondizioneAperturaLong := siamoinipervenduto and siamoindata and long_separator and siamoinuptrend

CondizioneChiusuraLong = siamoinipercomprato and siamoindata 

possiamoAprireLong=0
if trendFilterL and siamoinuptrend
    possiamoAprireLong:=5
plot(possiamoAprireLong,color=color.green)

sonPassateLeBarreG = barssince(CondizioneAperturaLong) == BarsDelay?true:false
sonPassateLeBarreD = barssince(CondizioneChiusuraLong) == BarsDelay?true:false

haiUnLongAncoraAperto = false
haiUnLongAncoraAperto := strategy.position_size>0?true:false

// Se l'ultimo valore della serie "CondizioneAperturaLong" è TRUE, allora hai un long ancora aperto
// Se l'ultimo valore della serie "CondizioneAperturaLong" è FALSE, allora:
//       Se l'ultimo valore della serie "CondizioneChiusuraLong" è TRUE, allora NON hai un long ancora aperto 
//       Se l'ultimo valore della serie "CondizioneChiusuraLong" è FALSE, allora restituisce l'ultimo valore della serie "haiUnLongAncoraAperto"

haiUnLongAncoraAperto_float = if(haiUnLongAncoraAperto==true)
    10
else
    0

plot(haiUnLongAncoraAperto_float,color=color.red) //FInché la linea rossa si trova a livello "1" allora c'è un ordine long in corso

quantita = (sizeordine/100*(capitaleIniziale+strategy.netprofit))/valuewhen(haiUnLongAncoraAperto==false and CondizioneAperturaLong,close,0)

plot(sizeordine,color=color.purple, linewidth=3)

if  strategy.position_size<=0 and CondizioneAperturaLong //and sonPassateLeBarreG and haiUnLongAncoraAperto==false strategy.opentrades==0
    strategy.entry("Vamonos",strategy.long, alert_message=webhookLong, comment="OPEN LONG", qty=quantita)

if  strategy.position_size>0 //and sonPassateLeBarreD // and CondizioneChiusuraLong 
    if siamoinuptrend == true and sonPassateLeBarreD
        strategy.close("Vamonos", alert_message=webhookClose, comment="CLOSE LONG")
    else if siamoinuptrend == false and CondizioneChiusuraLong
        strategy.close("Vamonos", alert_message=webhookClose, comment="CLOSE LONG")

    
if strategy.position_size>0 and siamoindata
    strategy.exit("Vamonos", stop=stop_level_long, limit=take_level_long, comment="CLOSE LONG (LIMIT/STOP)")


short_separator = input(title="------------------------SHORT------------------------", defval = usiShort)    

sl_short_inp = input(20, title="Stop Loss SHORT %")
tp_short_inp = input(35, title="Take Profit SHORT %")
stop_level_short = strategy.position_avg_price * (1 + (sl_short_inp/100))
take_level_short= strategy.position_avg_price * (1 - (tp_short_inp/100))

// BINANCE 
JSON_short = 'OPEN SHORT: PUT THE JSON HERE FOR THE API CALL'

webhookShort = JSON_short

trendFilterS = input(title="TREND FILTER SHORT?", defval = true)

siamoindowntrend_ema=EMAfast<EMAslow?true:false //close<=EMAfast and EMAfast<EMAslow
siamoindowntrend=siamoindowntrend_ema

CondizioneAperturaShort = short_separator and siamoinipercomprato and siamoindata 
if trendFilterS
    CondizioneAperturaShort:=short_separator and siamoinipercomprato and siamoindata and siamoindowntrend

CondizioneChiusuraShort = siamoinipervenduto and siamoindata

sonPassateLeBarreGs = barssince(CondizioneAperturaShort) == BarsDelay?true:false
sonPassateLeBarreDs = barssince(CondizioneChiusuraShort) == BarsDelay?true:false

haiUnoShortAncoraAperto = false
haiUnoShortAncoraAperto := strategy.position_size<0?true:false

haiUnoShortAncoraAperto_float = if(haiUnoShortAncoraAperto==true)
    15
else
    0

plot(haiUnoShortAncoraAperto_float,color=color.purple) //FInché la linea viola si trova a livello "2" allora c'è un ordine short in corso

if CondizioneAperturaShort and strategy.position_size>=0 //and haiUnoShortAncoraAperto==false
    strategy.entry("Andale",strategy.short,alert_message=webhookShort, comment="OPEN SHORT")

if  strategy.position_size<0 //and sonPassateLeBarreD // and CondizioneChiusuraLong 
    if siamoindowntrend == true and sonPassateLeBarreDs
        strategy.close("Andale",alert_message=webhookClose, comment="CLOSE SHORT")
    else if siamoindowntrend == false and CondizioneChiusuraShort
        strategy.close("Andale",alert_message=webhookClose, comment="CLOSE SHORT")

if strategy.position_size<0 and siamoindata
    strategy.exit("Andale", stop=stop_level_short, limit=take_level_short, comment="CLOSE SHORT (LIMIT/STOP)")

Thêm nữa