BG MVC Model View Controller eğitim serisi yayında...

Ana sayfa > Borsa > Pine Script Programlama > Pine Script strateji örnekleri > pine_script_strateji_rsi_001

Pine Script stratejileri

EMA 200 ile birlikte işlem yapan RSI stratejisi

Bu strateji ile, long ve short işlemlerin her biri için 4 farklı seçenekle işlem yapabilir, backtest zaman aralığı seçebilir, long işlemden çıkış yöntemi için gösterge short koşulu ile iz süren stop arasından birini tercih edebilirsiniz.

Stratejide, alım işlemi koşulu için, RSI göstergesi, isteğe bağlı olarak, EMA 200 ile birlikte kullanılır.

Stratejinin en avantajlı tarafı, long ve short işlemler için, RSI çizgisinin üst bant, alt bant, orta çizgi ve RSI hareketli ortalama değerlerinden birini kesmesinin kullanılabilmesidir. Böylece, kullanıcı hangi değerin karlı yüzde ve net kar yüzdelerini artıracağını görebilmektedir.

  • calc_on_every_tick=true: Bar içinde gerçek zamanlı hesaplama
  • commission_value=0.04: Komisyon yüzdesi: 0.0004 (Onbinde dört)
  • initial_capital=10000: İlk sermaye: 10000
  • default_qty_type=strategy.cash: Sermaye türü: Peşin
  • default_qty_value=10000: İşlem yapılacak sermaye: 10000

Bu ayarlar, stratejinin "Ayarlar/Özellikler" sekmesinde değiştirilebilir.

Strateji dahilinde, RSI göstergesi ile stratejiye ait ön tanımlı değerler değiştirilebilir:

  • RSI uzunluğu (Ön tanımlı değer 14)
  • RSI hareketli ortalama uzunluk değeri (Ön tanımlı değer 50)
  • RSI üst bant değeri (Ön tanımlı değer 30)
  • RSI alt bant değeri (Ön tanımlı değer 70)
  • Long koşulu için 4 farklı yöntemden birisi
  • Short koşulu için 4 farklı yöntemden birisi
  • Long işlemden çıkış yöntemi (RSI short koşulu veya iz süren stop)
  • Zarar durdur ATR periyot ve çarpan değerleri (Ön tanımlı değerleri sırasıyla 14 ve 3)
  • Backtest periyodu

// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © Niteya
//@version=5
// Bu strateji şablonu sadece eğitim amaçlı olarak verilmiştir. Yatırım kararlarınızda kullanmayınız.
strategy("Niteya Strategy RSI", shorttitle='Niteya RSI', overlay=true, calc_on_every_tick=true, commission_value=0.04, initial_capital=10000, default_qty_type=strategy.cash, default_qty_value=10000)

// RSI inputs
rsi_length = input.int(14, minval=1, title="RSI Length")
rsi_maLength = input.int(50, title="RSI MA Length")

rsi_band_lower_level = input.int(30, title="RSI Lower Band")
rsi_band_upper_level = input.int(70, title="RSI Upper Band")

rsi_value_base_long = input.string(title="RSI Long yöntemi", defval="RSI ↘ alt bant", options=['RSI ↘ alt bant', 'RSI ↗ alt bant', 'RSI ↗ MA', 'RSI ↗ 50'])
rsi_value_base_short = input.string(title="RSI Short yöntemi", defval="RSI ↗ üst bant", options=['RSI ↗ üst bant', 'RSI ↘ üst bant', 'RSI ↘ MA', 'RSI ↘ 50'])

// RSI calculations
rsi_calc(close_g) =>
    rsi_up = ta.rma(math.max(ta.change(close_g), 0), rsi_length)
    rsi_down = ta.rma(-math.min(ta.change(close_g), 0), rsi_length)
    rsi = rsi_down == 0 ? 100 : rsi_up == 0 ? 0 : 100 - (100 / (1 + rsi_up / rsi_down))
    rsi_MA = ta.sma(rsi, rsi_maLength)

    rsi_cross_band_upper_index = ta.barssince(ta.cross(rsi, rsi_band_upper_level))
    rsi_cross_MA_index = ta.barssince(ta.cross(rsi, rsi_MA))
    rsi_cross_center_index = ta.barssince(ta.cross(rsi, 50))
    rsi_cross_band_lower_index = ta.barssince(ta.cross(rsi, rsi_band_lower_level))

    last_cross = math.min(rsi_cross_band_upper_index, rsi_cross_MA_index, rsi_cross_center_index, rsi_cross_band_lower_index)

    rsi_band_upper=0, rsi_MA_val=0, rsi_center=0, rsi_band_lower=0

    switch last_cross
        rsi_cross_band_upper_index => // RSI çizgisi en son üst bant çizgisini kesmişse
            // rsi üst bant çizgisini yukarı doğru kesmişşe -1, aşağı doğru kesmişşe -2, değilse 0  
            rsi_band_upper := not(rsi_band_upper_level[last_cross]-rsi[last_cross]>0) ? -2 : (rsi_band_upper_level[last_cross]-rsi[last_cross]>0) ? -1 : 0 
        rsi_cross_MA_index => // RSI çizgisi en son MA50 çizgisini kesmişse
            // rsi MA çizgisini yukarı doğru kesmişşe 1, aşağı doğru kesmişşe -1, değilse 0 
            rsi_MA_val := not(rsi_MA[last_cross]-rsi[last_cross]>0) ? 1 : (rsi_MA[last_cross]-rsi[last_cross]>0) ? -1 : 0 
        rsi_cross_center_index => // RSI çizgisi merkez çizgisini (50) kesmişse
            // rsi merkez çizgisini yukarı doğru kesmişşe, aşağı doğru kesmişse -1, değilse 0 
            rsi_center := not(50-rsi[last_cross]>0)  ? 1 : (50-rsi[last_cross]>0) ? -1 : 0  
        rsi_cross_band_lower_index => // RSI çizgisi en son alt bant çizgisini kesmişse
            // rsi alt bant çizgisini yukarı doğru kesmişşe 1, aşağı doğru kesmişşe 2, değilse 0  
            rsi_band_lower := not(rsi_band_lower_level[last_cross]-rsi[last_cross]>0) ? 1 : (rsi_band_lower_level[last_cross]-rsi[last_cross]>0) ? 2 : 0 

    rsi_long = switch rsi_value_base_long
        'RSI ↘ alt bant' => rsi_band_lower==2 ? 1 : 0 // RSI alt bant çizgisini (30) aşağı doğru kestiğinde alım yap. 
        'RSI ↗ alt bant' => rsi_band_lower==1 ? 1 : 0 // RSI alt bant çizgisini (30) yukarı doğru kestiğinde alım yap.  
        'RSI ↗ MA' => rsi_MA_val==1 ? 1 : 0 // RSI MA çizgisini yukarı doğru kestiğinde alım yap.
        'RSI ↗ 50' => rsi_center==1 ? 1 : 0 // RSI merkez çizgisini (50) yukarı doğru kestiğinde alım yap.
        => 0

    rsi_short = switch rsi_value_base_short
        'RSI ↗ üst bant' => rsi_band_upper==-2 ? -1 : 0 // RSI üst bant çizgisini yukarı doğru kestiğinde satış yap.
        'RSI ↘ üst bant' => rsi_band_upper==-1 ? -1 : 0 // RSI üst bant çizgisini aşağı doğru kestiğinde satış yap.
        'RSI ↘ MA' => rsi_MA_val==-1 ? -1 : 0 // RSI MA çizgisini aşağı doğru kestiğinde satış yap. 
        'RSI ↘ 50' => rsi_center==-1 ? -1 : 0 // RSI merkez çizgisini aşağı doğru kestiğinde satış yap.
        => 0

    rsi_value = rsi_long==1 ? 1 : rsi_short==-1 ? -1 : 0 

rsi_value = rsi_calc(close)

// MA
is_ema200 = input.bool(true, title="EMA 200 üstünde Long işlem aç")

ma_length1 = input(20, 'MA length1')
ma_length2 = input(50, 'MA length2')
ma_length3 = input(200, 'MA length3')

is_ma_lines = input.bool(true, title="MA çizgileri")

ma_11 = ta.ema(close, ma_length1)
ma_12 = ta.ema(close, ma_length2)
ma_13 = ta.ema(close, ma_length3)

plot(is_ma_lines ? ma_11 : na, title="MA src1", color=color.blue, linewidth=1)
plot(is_ma_lines ? ma_12 : na, title="MA src2", color=color.orange, linewidth=2)
plot(is_ma_lines ? ma_13 : na, title="MA src3", color=color.black, linewidth=3)

var long_exit_vals = "Long işlem çıkış değerleri"
sl_method = input.string('Short', title="Long işlem çıkış yöntemi", options=['Stop loss', 'Short', 'Both'], group=long_exit_vals)

// Zarar durdur için ATR giriş değerleri
atr_period = input.int(14, 'Zarar durdur ATR periyodu', minval=7, step=1, group=long_exit_vals)
atr_multiplier = input.float(3, 'Zarar durdur ATR çarpanı', minval=1.5, step=0.1, group=long_exit_vals)

// Backtest periyodu
var backtest = "Backtest periyodu"
StartDay = input(1, 'Başlangıç günü', group=backtest)
StartMonth = input(1, 'Başlangıç ayı', group=backtest)
StartYear = input(2021, 'Başlangıç yılı', group=backtest)
PeriodStart = timestamp(StartYear, StartMonth, StartDay, 0, 0)

StopDay = input(31, 'Bitiş günü', group=backtest)
StopMonth = input(12, 'Bitiş ayı', group=backtest)
StopYear = input(9999, 'Bitiş yılı', group=backtest)
PeriodStop = timestamp(StopYear, StopMonth, StopDay, 0, 0)

var int long_no = 0
var int close_no = 0

// ATR hesaplama
atr_long = ta.atr(atr_period)

// İz süren stop hesaplama
stop_loss_atr = atr_multiplier * atr_long
Trail = 0.0
iff_1 = close > nz(Trail[1], 0) ? close - stop_loss_atr : close + stop_loss_atr
iff_2 = close < nz(Trail[1], 0) and close[1] < nz(Trail[1], 0) ? math.min(nz(Trail[1], 0), close + stop_loss_atr) : iff_1
Trail := close > nz(Trail[1], 0) and close[1] > nz(Trail[1], 0) ? math.max(nz(Trail[1], 0), close - stop_loss_atr) : iff_2

ema_200 = ta.ema(close, 200)

rsi_long = rsi_value==1 and (is_ema200 and not na(ema_200) ? (close>ema_200 ? true : false) : true)
entry_long =  rsi_long

rsi_short = rsi_value==-1
entry_short =  rsi_short
		 
stop_loss_long = Trail

exit_long = close<stop_loss_long		 
			
var int PeriodS1 = 0 // Strateji backtest başlangıç tarihini gösteren değişken
var int PeriodS2 = 0 // Strateji backtest bitiş tarihini gösteren değişken
var float close_s = na // Strateji backtest başlangıç tarihindeki hisse fiyatını gösteren değişken 
var float close_e = na // Strateji backtest bitiş tarihindeki hisse fiyatını gösteren değişken
var bool cs=false, ce=false

// İlk barda değerleri atama
if barstate.isfirst
    close_s := close
    PeriodS1 := timestamp(year(time), month(time), dayofmonth(time), 0, 0)

// Başlangıç ve bitiş kapanış değerlerini strateji backtest işlem tarihi başlangıç ve bitiş tarihlerine göre ayarlama
if time >= PeriodStart and not cs
    close_s := close
    PeriodS1 := timestamp(year(time), month(time), dayofmonth(time), 0, 0)
    cs := true

if time <= PeriodStop and not ce
    PeriodS2 := timestamp(year(time), month(time), dayofmonth(time), 0, 0)
    close_e := close
    ce := true

// Aktif bar tarihinin strateji backtest işlemi başlangıç ve bitiş tarihinin içinde olup olmadığını gösteren fonksiyon
In_Period() =>
    time >= PeriodStart and time <= PeriodStop ? true : false

if In_Period()

	if entry_long and strategy.opentrades==0 // Long koşul gerçekleşmisse ve açılmış bir işlem yoksa long işlem aç
		strategy.entry('long', strategy.long, comment='BUY')
		long_no += 1

    // Seçeneğe bağlı olarak, short koşul gerçekleşmisse veya iz süren stop seviyesinin altına geçilmişse ve 
	// açılmış bir işlem varsa long işlemi kapat
	if strategy.opentrades>0 and (sl_method=='Both' ? exit_long or entry_short : (sl_method=='Stop loss' ? exit_long : entry_short))
        strategy.close_all(comment='SELL')        
        close_no += 1		

// İz süren stop çizimi
plot_con = In_Period() and strategy.position_size > 0
plot(plot_con and not exit_long ? stop_loss_long : na, style=plot.style_linebr, color=color.new(color.red, 0), linewidth=1, title='Stop loss seviyesi')		
		
// Stratejinin kârlı yüzde oranını hesaplayan fonksiyon 
GetWinRate(includeEvens = false) =>
	winTradeCount = strategy.wintrades + 
         (includeEvens ? strategy.eventrades : 0)
	(winTradeCount / strategy.closedtrades) * 100

if(barstate.islast)
    if time <= PeriodStop
        PeriodS2 := timestamp(year(time), month(time), dayofmonth(time), 0, 0)
        close_e := close
		
    string time_str = ''
    period = timeframe.period
    gwr = GetWinRate()       
    text_color_wr = gwr > 0 ? color.green : gwr < 0 ? color.red : color.gray 
    text_color_np = strategy.netprofit > 0 ? color.green : strategy.netprofit < 0 ? color.red : color.gray 
    text_color_single = close_e-close_s > 0 ? color.green : close_e-close_s < 0 ? color.red : color.gray 

    // Zaman aralığını metein olarak alma
    switch 
        period=="1" => time_str := '1 dakika'
        period=="3" => time_str := '3 dakika'
        period=="5" => time_str := '5 dakika'
        period=="15" => time_str := '15 dakika'
        period=="30" => time_str := '30 dakika'
        period=="45" => time_str := '45 dakika'
        period=="60" => time_str := '1 saat'
        period=="120" => time_str := '2 saat'
        period=="180" => time_str := '3 saat'
        period=="240" => time_str := '4 saat'
        str.pos(period, "D")>=0 => time_str := '1 gün'
        str.pos(period, "W")>=0 => time_str := '1 hafta'
        str.pos(period, "M")>=0 => time_str := '1 ay'

    var table m_table = table.new(position.middle_left, columns=2, rows=14, bgcolor=color.rgb(212, 212, 212), border_width=1, border_color=color.white)
    
    table.merge_cells(m_table, 0, 0, 1, 0)
    
    table.cell(m_table, 0, 0, "Niteya RSI (" + str.tostring(dayofmonth(PeriodS1), "00") + '.' + str.tostring(month(PeriodS1), "00") + '.' + str.tostring(year(PeriodS1)) + "-" +
     str.tostring(dayofmonth(time), "00") + '.' + str.tostring(month(time), "00") + '.' + str.tostring(year(time)) + ")", text_color=color.white, text_halign=text.align_center, text_size=size.normal, bgcolor=color.new(#31153a, 0))
    
    table.cell(m_table, 0, 1, 'Periyot', text_color=color.rgb(244, 244, 244), text_halign=text.align_left, text_size=size.large, bgcolor=color.orange)
    table.cell(m_table, 0, 2, 'İlk sermaye', text_color=color.rgb(244, 244, 244), text_halign=text.align_left, text_size=size.large, bgcolor=color.orange)
    table.cell(m_table, 0, 3, 'Karlı yüzde (%)', text_color=color.rgb(244, 244, 244), text_halign=text.align_left, text_size=size.large, bgcolor=color.orange)
    table.cell(m_table, 0, 4, 'Net kar (%)', text_color=color.rgb(244, 244, 244), text_halign=text.align_left, text_size=size.large, bgcolor=color.orange)
    table.cell(m_table, 0, 5, 'Net kar', text_color=color.rgb(244, 244, 244), text_halign=text.align_left, text_size=size.large, bgcolor=color.orange)
    table.cell(m_table, 0, 6, 'Açılan işlemler', text_color=color.rgb(244, 244, 244), text_halign=text.align_left, text_size=size.large, bgcolor=color.orange)
    table.cell(m_table, 0, 7, 'Kapanan işlemler', text_color=color.rgb(244, 244, 244), text_halign=text.align_left, text_size=size.large, bgcolor=color.orange)
    table.cell(m_table, 0, 8, 'Başlangıç tarihi', text_color=color.rgb(244, 244, 244), text_halign=text.align_left, text_size=size.large, bgcolor=color.orange)
    table.cell(m_table, 0, 9, 'Bitiş tarihi', text_color=color.rgb(244, 244, 244), text_halign=text.align_left, text_size=size.large, bgcolor=color.orange)

    table.cell(m_table, 0, 10, 'İlk fiyat', text_color=color.rgb(244, 244, 244), text_halign=text.align_left, text_size=size.large, bgcolor=color.rgb(103, 74, 31))
    table.cell(m_table, 0, 11, 'Son fiyat', text_color=color.rgb(244, 244, 244), text_halign=text.align_left, text_size=size.large, bgcolor=color.rgb(103, 74, 31))
    table.cell(m_table, 0, 12, 'Net kar (%)', text_color=color.rgb(244, 244, 244), text_halign=text.align_left, text_size=size.large, bgcolor=color.rgb(103, 74, 31))
    table.cell(m_table, 0, 13, 'Net kar', text_color=color.rgb(244, 244, 244), text_halign=text.align_left, text_size=size.large, bgcolor=color.rgb(103, 74, 31))

    table.cell(m_table, 1, 1, str.tostring(time_str), text_color=#505050, text_halign=text.align_right, text_size=size.large, bgcolor=color.rgb(212, 212, 212))
    table.cell(m_table, 1, 2, str.tostring(strategy.initial_capital), text_color=#505050, text_halign=text.align_right, text_size=size.large, bgcolor=color.rgb(212, 212, 212))
    
    if not na(gwr)
        table.cell(m_table, 1, 3, str.tostring(gwr, '0.00'), text_color=text_color_wr, text_halign=text.align_right, text_size=size.large, bgcolor=color.rgb(212, 212, 212))
        table.cell(m_table, 1, 4, str.tostring((100*strategy.netprofit)/strategy.initial_capital, '0.00'), text_color=text_color_np, text_halign=text.align_right, text_size=size.large, bgcolor=color.rgb(212, 212, 212))
        table.cell(m_table, 1, 5, str.tostring(strategy.netprofit, '0.00'), text_color=text_color_np, text_halign=text.align_right, text_size=size.large, bgcolor=color.rgb(212, 212, 212))
        table.cell(m_table, 1, 6, str.tostring(long_no), text_color=#505050, text_halign=text.align_right, text_size=size.large, bgcolor=color.rgb(212, 212, 212))
        table.cell(m_table, 1, 7, str.tostring(strategy.closedtrades), text_color=#505050, text_halign=text.align_right, text_size=size.large, bgcolor=color.rgb(212, 212, 212))
    
    table.cell(m_table, 1, 8, str.tostring(dayofmonth(PeriodS1), "00") + '.' + str.tostring(month(PeriodS1), "00") + '.' + str.tostring(year(PeriodS1)), text_color=#505050, text_halign=text.align_right, text_size=size.large, bgcolor=color.rgb(212, 212, 212))
    table.cell(m_table, 1, 9, str.tostring(dayofmonth(PeriodS2), "00") + '.' + str.tostring(month(PeriodS2), "00") + '.' + str.tostring(year(PeriodS2)), text_color=#505050, text_halign=text.align_right, text_size=size.large, bgcolor=color.rgb(212, 212, 212))

    np = (close_e-close_s)*(strategy.initial_capital/close_s)
    
    table.cell(m_table, 1, 10, str.tostring(close_s, '0.000'), text_color=#505050, text_halign=text.align_right, text_size=size.large, bgcolor=color.rgb(212, 212, 212))
    table.cell(m_table, 1, 11, str.tostring(close_e, '0.000'), text_color=#505050, text_halign=text.align_right, text_size=size.large, bgcolor=color.rgb(212, 212, 212))
    table.cell(m_table, 1, 12, str.tostring((100*np)/strategy.initial_capital, '0.00'), text_color=text_color_single, text_halign=text.align_right, text_size=size.large, bgcolor=color.rgb(212, 212, 212))
    table.cell(m_table, 1, 13, str.tostring(np, '0.00'), text_color=text_color_single, text_halign=text.align_right, text_size=size.large, bgcolor=color.rgb(212, 212, 212))

Yukarıdaki strateji ile ilgili bir uygulama aşağıdaki grafikte gösterilmektedir. Long işlem için, RSI değerinin hareketli ortalama değerini yukarı doğru kesmesi, short işlem RSI değerinin üst bant değerini (70) yukarı doğru kesmesi esas alınmıştır.