Strategi Kuantitatif MACD Super Trend


Tanggal Pembuatan: 2023-12-26 11:13:24 Akhirnya memodifikasi: 2023-12-26 11:13:24
menyalin: 0 Jumlah klik: 792
1
fokus pada
1621
Pengikut

Strategi Kuantitatif MACD Super Trend

Ringkasan

Strategi ini menggunakan sinyal reversal tren potensial dari indikator overtrend dan MACD, yang bekerja dengan sinyal overbought dan oversold dari indikator RSI, untuk membentuk sistem sinyal open dan close yang lebih stabil dan efisien. Strategi ini disebut strategi kuantitatif MACD overtrend.

Prinsip Strategi

Logika inti dari strategi ini adalah menggunakan indikator supertrend dan indikator MACD secara komprehensif sebagai kriteria untuk sinyal buka posisi.

Bagian supertrend, strategi menggunakan perubahan arah indikator supertrend sebagai sinyal pembalikan potensial. Ketika arah indikator supertrend berputar dari atas ke bawah menghasilkan sinyal beli; Ketika arah indikator supertrend berputar dari bawah ke atas menghasilkan sinyal jual.

Pada bagian MACD, strategi menggunakan slope dan zero-axis intersection pada MACD indikator pada frame waktu yang lebih rendah (di bawah garis matahari) untuk menilai peluang terbalik potensial. Sinyal dihasilkan ketika slope MACD lebih besar dari nilai mutlak (di atas nilai terendah) dan slope tetap sama naik; Sinyal tambahan juga dihasilkan jika MACD indikator melintasi sumbu nol.

Pada sinyal pembukaan posisi, strategi memerlukan sinyal supertrend dan sinyal MACD untuk tetap sejalan dengan arah perintah pembukaan posisi.

Selain itu, strategi pada bagian posisi terendah juga memperkenalkan sinyal overbought dan oversold dari indikator RSI. Ketika indikator RSI lebih besar dari 80 menghasilkan sinyal jual, dan lebih kecil dari 20 menghasilkan sinyal beli, untuk membantu menentukan waktu berbalik.

Analisis Keunggulan

Keuntungan terbesar dari strategi ini adalah keberagaman sinyal indikator. Antara indikator yang berbeda dapat dibentuk saling melengkapi, membuat sinyal keseluruhan lebih stabil dan dapat diandalkan.

Indikator supertrend dapat menangkap tren jangka pendek yang lebih kuat. Skala MACD dapat menentukan kekuatan tren jangka menengah dan panjang, sehingga tidak tertipu oleh pembalikan palsu. RSI dapat memberi tahu waktu terbaik untuk membuka posisi dan posisi yang lebih baik untuk overbought dan oversold dalam situasi yang bergejolak.

Selain itu, pengaturan kerangka waktu strategi juga cukup masuk akal. Supertrend menggunakan kerangka waktu jam, indikator MACD menggunakan garis matahari, sehingga menjamin frekuensi perdagangan dan juga mempertimbangkan stabilitas penilaian tren.

Analisis risiko

Risiko utama dari strategi ini adalah bahwa ada kemungkinan besar untuk menghasilkan sinyal yang bercampur antara indikator. Misalnya, supertrend menghasilkan pembalikan palsu, sementara sinyal MACD tidak dihasilkan secara sinkron. Ini dapat menyebabkan kerugian yang tidak perlu.

Selain itu, RSI juga dapat digunakan untuk menentukan kapan posisi kosong terlalu dini atau terlalu terlambat, sehingga tidak dapat memaksimalkan waktu memegang strategi.

Terakhir, terlalu besarnya setelan terobosan pada MACD juga menyebabkan terlewatnya kesempatan untuk membalikkan posisi.

Arah optimasi

Strategi ini dapat dioptimalkan lebih lanjut dalam beberapa hal:

  1. Memperkenalkan mekanisme stop loss. Stop loss jika kerugian melebihi persentase tertentu.

  2. Penghakiman terhadap kemiringan MACD menambahkan penurunan nilai dinamis. Meningkatkan nilai kemiringan ketika pasar bergejolak dan menurunkan nilai ketika pasar stabil.

  3. Untuk menentukan posisi terdepan pada RSI, ada persyaratan untuk melakukan retrospeksi. Jika RSI melampaui 80, maka harus ada retrospeksi yang jelas untuk mempertimbangkan posisi terdepan.

  4. Testing MACD with volume and see if it improves signal reliability

  5. Trying automated parameter tuning to find optimal settings

Meringkaskan

Strategi kuantitatif MACD yang melampaui tren memberikan sinyal posisi terbuka dan posisi yang aman dengan kombinasi beberapa indikator. Keunggulan dari strategi ini adalah stabilitas sinyal, tingkat kemenangan yang tinggi, dan dapat ditingkatkan lebih lanjut melalui pengoptimalan parameter.

Kode Sumber Strategi
/*backtest
start: 2022-12-19 00:00:00
end: 2023-12-25 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

//@version=5

strategy("SuperTrend.MACD Strategy", overlay=false, default_qty_type=strategy.percent_of_equity, default_qty_value=100, initial_capital=100000, pyramiding=5, process_orders_on_close=true)

// ---------------- Utility Functions ----------------
getArrayValue(float[] arr, int ago) =>
    if ago >= 0
        array.get(arr, ago >= array.size(arr) ? na: array.size(arr) + -1 * ago -1)
    else
        na

filterNA(float[] a, s, int y) =>
    int x = 0
    if not na(s[0])
        array.push(a, s[0])
        if array.size(a) > y
            array.shift(a)
    a

pine_rsi(float[] x, int y) =>
    x0 = getArrayValue(x, 0)
    x1 = getArrayValue(x, 1)

    u = math.max(x0 - x1, 0) // upward ta.change
    d = math.max(x1 - x0, 0) // downward ta.change
    rs = ta.rma(u, y) / ta.rma(d, y)
    res = 100 - 100 / (1 + rs)
    res

turnAround(float[] arr) =>
    int isTurnAround = 0
    
    now = getArrayValue(arr, 0)
    p1 = getArrayValue(arr, 1)
    p2 = getArrayValue(arr, 2)

    if p1 > now and p1 > p2
        isTurnAround := -1
    else if p1 < now and p1 < p2
        isTurnAround := 1

intergerizeSignal(i) =>
    i>0 ? 1 : i<0 ? -1 : 0

linreg(float[] y, int n, int offset=0) => 
    float slope = na
    float intercept = na

    int endcursor = offset + n - 1

    if array.size(y) > endcursor
        float sumX = 0
        float sumX2 = 0
        float sumY = 0
        float sumY2 = 0
        float sumXY = 0

        for i=offset to endcursor
            yv = array.get(y, i)
            sumY += yv
            sumY2 += math.pow(yv, 2)
            sumX += i
            sumX2 += math.pow(i, 2)
            sumXY += i*yv

        // Pearson correlation coefficient
        r = (n * sumXY - sumX * sumY) / math.sqrt((n * sumY2 - math.pow(sumY, 2)) * (n * sumX2 - math.pow(sumX, 2)))

        // Coefficient of determination
        r2 = math.pow(r, 2)

        meanX = sumX / n
        meanY = sumY / n

        slope := (n * sumXY - sumX * sumY) / (n * sumX2 - math.pow(sumX, 2))
        intercept := meanY - slope * meanX

    [slope, intercept]

isStartOfDay() => dayofweek != dayofweek[1]

// ---------------- Variables ----------------

varip float st_signal = 0
varip float macd_signal = 0
varip float macd_close_signal = 0
varip float histo_signal = 0

var int openSignal = 0
var int closeSignal = 0

// -------------------------------- Supertrend Signal (Open) --------------------------------

// ST calculation
atrPeriod = input(10, "Supertrend ATR Length")
factor = input.float(2.0, "Supertrend Factor", step = 0.01)

[_, direction] = ta.supertrend(factor, atrPeriod)

st_direction_change = ta.change(direction)
if st_direction_change < 0
    st_signal := 4
if st_direction_change > 0
    st_signal := -4

// -------------------------------- MACD Signal (Open + Close) --------------------------------

// MACD Calculation
fastLength = input(12, title="MACD Fast Length")
slowLength = input(26, title="MACD Slow Length")
signalLength = input(9, title="MACD Signal Length")
macdSlowTimeframe = input.timeframe("D", "MACD Timeframe")
macdSlopeLookbackOpen = input(7, title="MACD Slope Lookback - Open")
macdSlopeLookbackClose = input(3, title="MACD Slope Lookback - Close")

dailyClose = request.security(syminfo.tickerid, macdSlowTimeframe, close, barmerge.gaps_on)
[macdLine, signalLine, _] = ta.macd(dailyClose, fastLength, slowLength, signalLength)

// MACD Slope calculation

varip macdHistory = array.new<float>(0)
varip macdSlowSlopeArr = array.new<float>(0)
varip float macdSlowSlope = na
varip float macdCloseSlope = na

if not na(macdLine[0])
    array.push(macdHistory, macdLine[0])
    if array.size(macdHistory) > macdSlopeLookbackOpen
        array.shift(macdHistory)
    [s1, _] = linreg(macdHistory, macdSlopeLookbackOpen)
    macdSlowSlope := s1

    array.push(macdSlowSlopeArr, macdSlowSlope)
    if array.size(macdSlowSlopeArr) > macdSlopeLookbackClose
        array.shift(macdSlowSlopeArr)
    [s2, _] = linreg(macdSlowSlopeArr, macdSlopeLookbackClose)
    macdCloseSlope := s2

// MACD Signal Calculation
// > open signal
threshold_macdSlowSlope = input.float(0.75, "MACD Slope Open Threshold", step = 0.05)

macdSlowSlopeOverThreshold = math.abs(macdSlowSlope) >= threshold_macdSlowSlope
macdSlowSlopeTrend = macdSlowSlope - getArrayValue(macdSlowSlopeArr, 1)
macdSlowSlopeTrendConfirm = macdSlowSlope*macdSlowSlopeTrend >0

if (macdSlowSlopeOverThreshold and macdSlowSlopeTrendConfirm)
    macd_signal := 3*macdSlowSlope/math.abs(macdSlowSlope)
else
    macd_signal := 0

// > close signal
int macdCloseSignal = 0
macdCloseSignal := intergerizeSignal(macdCloseSlope)

// Histogram signal Calculation
histSlow = macdLine - signalLine

if (ta.crossover(histSlow, 0))
	histo_signal := 2
if (ta.crossunder(histSlow, 0))
	histo_signal := -2

// -------------------------------- RSI Signal (Close) --------------------------------
int rsiCloseSignal = 0
varip float rsiSlow = na

rsiPeriod = input(14, title="RSI Period")

varip dailyCloseRSIFilter = array.new_float()

// rewrite pine_rsi to remove NaN value from series at calculation
dailyCloseRSIFilter := filterNA(dailyCloseRSIFilter, dailyClose, rsiPeriod)

if not na(dailyClose[0])
    rsiSlow := pine_rsi(dailyCloseRSIFilter, rsiPeriod)

if rsiSlow > 80
    rsiCloseSignal := -1
else if rsiSlow < 20
    rsiCloseSignal := 1
else
    rsiCloseSignal := 0

// -------------------------------- Overall Signal --------------------------------

// Close signal
closeSignals = array.from(macdCloseSignal, rsiCloseSignal)
closeSignal := array.includes(closeSignals, 1) ? 1 : array.includes(closeSignals, -1) ? -1 : 0
closeSignal := closeSignal * 5

// Open signal
if (macd_signal * st_signal > 0) and (macd_signal * macd_close_signal >= 0)
    openSignal := intergerizeSignal(st_signal)
    openSignal := openSignal * 6
else
    openSignal := 0

// -------------------------------- Order --------------------------------
// if strategy.position_size == 0
if openSignal * closeSignal >=0
    if openSignal > 0
        strategy.entry("Long Entry", strategy.long)
    else if openSignal < 0
        strategy.entry("Short Entry", strategy.short)

if strategy.position_size != 0
    if closeSignal < 0
        strategy.close("Long Entry")
    if closeSignal > 0
        strategy.close("Short Entry")


// -------------------------------- Plot --------------------------------

plot(closeSignal, title="Close Signal", color=color.red, linewidth = 1, style=plot.style_area)
plot(openSignal, title="Open Signal", color=color.green, linewidth = 1, style=plot.style_area)
plot(st_signal, title="ST Signal", color=color.black, linewidth = 1, style=plot.style_circles)
plot(macd_signal, title="MACD Signal", color=color.blue, linewidth = 1, style=plot.style_circles)
// plot(macdSlowSlope, title="macd slow slope", color=color.purple, linewidth = 1, style=plot.style_line)
// plot(macdCloseSlope, title="macd slow slope", color=color.lime, linewidth = 1, style=plot.style_line)

hline(0, "Zero Line", color=color.gray)