RSI dan supertrend 2 (supertrend 5 menit 2 atas 3 bawah) rsi 4 atas dan 2 bawah (buy searah 2x)

//@version=6
strategy("MTF Supertrend 5M + RSI Primed 1M Strategy (Fix Timezone)", overlay=true, initial_capital=10000, default_qty_type=strategy.fixed, default_qty_value=0.1)

// ==========================================
// 1. INPUT FILTER TANGGAL & JAM (BACKTEST)
// ==========================================
var string G_TIME = "Filter Waktu & Tanggal Backtest"
startYear   = input.int(2025, "Tahun Mulai", group=G_TIME)
startMonth  = input.int(1, "Bulan Mulai", minval=1, maxval=12, group=G_TIME)
startDay    = input.int(1, "Tanggal Mulai", minval=1, maxval=31, group=G_TIME)

endYear     = input.int(2026, "Tahun Selesai", group=G_TIME)
endMonth    = input.int(12, "Bulan Selesai", minval=1, maxval=12, group=G_TIME)
endDay      = input.int(31, "Tanggal Selesai", minval=1, maxval=31, group=G_TIME)

// Pilihan Zona Waktu (Default: Asia/Jakarta untuk WIB)
tzInput     = input.string("Asia/Jakarta", "Zona Waktu Anda", options=["Asia/Jakarta", "Asia/Makassar", "Asia/Jayapura", "UTC"], group=G_TIME)

// Input Batasan Jam Harian (Pukul 05:00 Subuh s/d 23:59 Malam)
startHour   = input.int(5, "Jam Mulai (Sesi Harian)", minval=0, maxval=23, group=G_TIME)
startMinute = input.int(0, "Menit Mulai (Sesi Harian)", minval=0, maxval=59, group=G_TIME)
endHour     = input.int(23, "Jam Selesai (Sesi Harian)", minval=0, maxval=23, group=G_TIME)
endMinute   = input.int(59, "Menit Selesai (Sesi Harian)", minval=0, maxval=59, group=G_TIME)

// Fungsi mengecek validasi tanggal dan jam harian berdasarkan zona waktu pilihan
inWindow() => 
    // Mengonversi waktu bar saat ini ke zona waktu yang dipilih
    currentHour   = hour(time, tzInput)
    currentMinute = minute(time, tzInput)

    // Validasi Rentang Tanggal Besar
    startTime = timestamp(tzInput, startYear, startMonth, startDay, 0, 0, 0)
    endTime   = timestamp(tzInput, endYear, endMonth, endDay, 23, 59, 59)
    dateValid = time >= startTime and time <= endTime
    
    // Validasi Jam Trading Harian (05:00 - 23:59)
    currentHourMinute = currentHour * 100 + currentMinute
    targetStart = startHour * 100 + startMinute
    targetEnd = endHour * 100 + endMinute
    timeValid = currentHourMinute >= targetStart and currentHourMinute <= targetEnd
    
    dateValid and timeValid

// ==========================================
// KUSTOM FUNGSI MATEMATIKA HIPERBOLIK (FIX CE10271)
// ==========================================
f_cosh(float x) => (math.exp(x) + math.exp(-x)) / 2
f_acosh(float x) => x < 1 ? na : math.log(x + math.sqrt(x * x - 1))
f_sinh(float x) => (math.exp(x) - math.exp(-x)) / 2
f_asinh(float x) => math.log(x + math.sqrt(x * x + 1))

// ==========================================
// 2. TIMEFRAME 5 MENIT (SUPERTREND HEIKIN ASHI)
// ==========================================
var string G_ST = "Setting Supertrend (5 Menit)"
atrPeriod5M = input.int(2, "ATR Length", minval=1, group=G_ST)
factor5M    = input.float(3.0, "Factor", minval=0.01, step=0.01, group=G_ST)

f_ha_ohlc() =>
    haClose = (open + high + low + close) / 4
    var float haOpen = na
    haOpen := na(haOpen[1]) ? (open + close) / 2 : (nz(haOpen[1]) + nz(haClose[1])) / 2
    haHigh = math.max(high, math.max(haOpen, haClose))
    haLow  = math.min(low, math.min(haOpen, haClose))
    [haOpen, haHigh, haLow, haClose]

[haO_5m, haH_5m, haL_5m, haC_5m] = request.security(syminfo.tickerid, "5", f_ha_ohlc(), barmerge.gaps_off, barmerge.lookahead_off)

f_supertrend(f, p, h, l, c) =>
    atr = ta.atr(p)
    up = (h + l) / 2 - f * atr
    dn = (h + l) / 2 + f * atr
    var float up_line = na
    var float dn_line = na
    var int dir = 1
    up_line := c[1] > up_line[1] ? math.max(up, up_line[1]) : up
    dn_line := c[1] < dn_line[1] ? math.min(dn, dn_line[1]) : dn
    dir := c > dn_line[1] ? -1 : c < up_line[1] ? 1 : nz(dir[1], 1)
    [dir == -1 ? up_line : dn_line, dir]

[st_line_5m, st_dir_5m] = request.security(syminfo.tickerid, "5", f_supertrend(factor5M, atrPeriod5M, high, low, close), barmerge.gaps_off, barmerge.lookahead_off)

is_bullish_5m = (st_dir_5m == -1)
is_bearish_5m = (st_dir_5m == 1)

// ==========================================
// 3. TIMEFRAME 1 MENIT (RSI PRIMED ENTRYS)
// ==========================================
var string G_RSI = "Setting RSI Primed (1 Menit)"
rsiLength = input.float(4.0, "RSI Length", group=G_RSI)
rsiSmooth = input.float(2.0, "RSI Smoothing (Chebyshev)", group=G_RSI)

f_chebyshevI(src, len, ripple) =>
    var float chebyshev = na
    a = f_cosh(1 / len * f_acosh(1 / (1 - ripple)))
    b = f_sinh(1 / len * f_asinh(1 / ripple))
    g = (a - b) / (a + b)
    chebyshev := (1 - g) * src + g * nz(chebyshev[1], src)
    chebyshev

f_custom_rsi(src, len, smooth) =>
    close_filtered = f_chebyshevI(src, smooth, 0.5)
    up = math.max(ta.change(close_filtered), 0)
    down = -math.min(ta.change(close_filtered), 0)
    up_filtered = f_chebyshevI(up, len, 0.5)
    down_filtered = f_chebyshevI(down, len, 0.5)
    rsi_val = down_filtered == 0 ? 100 : 100 - (100 / (1 + up_filtered / down_filtered))
    rsi_val

rsi_open  = f_custom_rsi(open, rsiLength, rsiSmooth)
rsi_high  = f_custom_rsi(high, rsiLength, rsiSmooth)
rsi_low   = f_custom_rsi(low, rsiLength, rsiSmooth)
rsi_close = f_custom_rsi(close, rsiLength, rsiSmooth)

var float ha_rsi_open = na
ha_rsi_close = (rsi_open + rsi_high + rsi_low + rsi_close) / 4
ha_rsi_open  := na(ha_rsi_open[1]) ? (rsi_open + rsi_close) / 2 : (nz(ha_rsi_open[1]) + nz(ha_rsi_close[1])) / 2

rsi_main = ha_rsi_close
level_90 = 90.0
level_10 = 10.0

// ==========================================
// 4. LOGIKA ENTRY, LOT SIZE, DAN EXIT STRATEGY
// ==========================================
if inWindow()
    lot_buy  = is_bullish_5m ? 0.2 : 0.1
    lot_sell = is_bearish_5m ? 0.2 : 0.1

    // Entry SELL (Logika 1 & 3)
    if ta.crossover(rsi_main, level_90) or (rsi_main >= level_90 and not (strategy.position_size < 0))
        strategy.entry("SELL", strategy.short, qty=lot_sell)

    // Entry BUY (Logika 2 & 4)
    if ta.crossunder(rsi_main, level_10) or (rsi_main <= level_10 and not (strategy.position_size > 0))
        strategy.entry("BUY", strategy.long, qty=lot_buy)

    // Close BUY di Level 90
    if strategy.position_size > 0 and (ta.crossover(rsi_main, level_90) or rsi_main >= level_90)
        strategy.close("BUY", comment="Tutup BUY di Level 90")

    // Close SELL di Level 10
    if strategy.position_size < 0 and (ta.crossunder(rsi_main, level_10) or rsi_main <= level_10)
        strategy.close("SELL", comment="Tutup SELL di Level 10")

// Otomatis menutup semua posisi jika waktu sudah habis melewati jam 23:59 malam (Force Close)
if not inWindow() and strategy.position_size != 0
    strategy.close_all(comment="Sesi Selesai - Tutup Paksa Posisi")

Komentar