Breakout Band Fixed Stop Loss Strategi

Penulis:ChaoZhang, Tanggal: 2023-11-03 14:31:21
Tag:

img

Gambaran umum

Ide utama dari strategi ini adalah untuk menggunakan band breakout untuk mengidentifikasi arah tren dan menggabungkan stop loss tetap untuk manajemen risiko. Strategi pertama menghitung harga tertinggi dan terendah selama periode tertentu untuk membentuk band breakout. Ketika harga menembus band breakout, sinyal perdagangan dihasilkan. Selain itu, strategi ini memungkinkan pedagang untuk menetapkan jumlah stop loss tetap. Setiap kali perdagangan dilakukan, sistem akan menghitung ukuran posisi berdasarkan jumlah stop loss tetap, sehingga setiap kerugian tetap.

Prinsip Strategi

Strategi ini terdiri dari empat bagian utama: manajemen posisi, identifikasi band breakout, pengaturan stop loss dan ukuran posisi.

Pertama, strategi memeriksa apakah ada posisi terbuka.

Kedua, strategi menghitung harga tertinggi dan terendah selama periode untuk membentuk band breakout. Ketika harga keluar dari band, sinyal perdagangan dihasilkan. Secara khusus, jika harga pecah di atas band atas, sinyal panjang dihasilkan. Jika harga pecah di bawah band bawah, sinyal pendek dihasilkan.

Selain itu, ketika sinyal panjang dihasilkan, strategi menetapkan titik tengah dari band breakout sebagai stop loss. Hal yang sama berlaku untuk sinyal pendek. Untuk melacak stop loss, strategi juga menyesuaikan stop loss secara real-time saat berada di posisi.

Akhirnya, strategi memungkinkan untuk menetapkan jumlah stop loss tetap. Ketika sinyal dihasilkan, strategi menghitung jumlah pips dari stop loss ke harga saat ini, dan menggabungkan faktor seperti ukuran tik dan nilai tukar, untuk menentukan perubahan harga antara stop loss dan harga saat ini dalam hal moneter. Ukuran posisi kemudian dihitung berdasarkan jumlah stop loss tetap.

Di atas adalah prinsip-prinsip utama dari strategi. mengidentifikasi arah tren dengan break-out band dan mengendalikan risiko dengan stop loss tetap adalah konsep inti.

Keuntungan

Strategi stop loss yang tetap ini memiliki keuntungan berikut:

  1. Konsep stop loss lanjutan. Strategi ini menggunakan jumlah stop loss tetap bukan jarak stop loss tetap. Hal ini menghindari masalah tidak dapat memperbaiki risiko di seluruh produk dengan nilai tick yang berbeda. Dari perspektif manajemen risiko, stop loss moneter tetap lebih maju.

  2. Ukuran posisi yang wajar. Strategi dapat secara cerdas menghitung ukuran posisi berdasarkan jumlah stop loss tetap, sehingga kerugian per perdagangan dikendalikan, sehingga mengelola eksposur risiko secara wajar.

  3. Identifikasi breakout yang sederhana dan efektif. Mengidentifikasi breakout dengan band adalah sederhana dan langsung, dan dapat secara efektif mengidentifikasi arah tren. Dibandingkan dengan breakout dari satu tingkat harga, identifikasi band breakout ini dapat menghindari lebih banyak sinyal palsu dari tren.

  4. Kemampuan strategi untuk menyesuaikan stop loss secara real-time untuk trailing stop loss membantu mengunci lebih banyak keuntungan.

  5. Aplikasi yang luas. Strategi ini dapat diterapkan pada produk apa pun. Selama parameter ditetapkan dengan benar, pengendalian risiko stop loss dengan jumlah tetap dapat dicapai, membuat strategi ini sangat serbaguna.

  6. Struktur kode yang jelas dan modular, membuatnya mudah dipahami dan dioptimalkan.

Risiko

Meskipun ada keuntungan, ada beberapa risiko yang harus diperhatikan untuk strategi:

  1. Kualitas pola pecah tidak diuji. Strategi ini tidak menilai kualitas pola pecah dan dapat menghasilkan beberapa sinyal berkualitas rendah. Indikator lain diperlukan untuk menyaring sinyal.

  2. Stop loss tetap mungkin terlalu mekanis. harga pasar sering selisih. stop loss tetap mungkin terlalu bergantung pada aturan dan kurang fleksibel dalam penyesuaian.

  3. Tidak ada batasan pada frekuensi perdagangan. Strategi tidak membatasi frekuensi perdagangan dan mungkin perdagangan terlalu sering. Aturan lain diperlukan untuk membatasi frekuensi.

  4. Stop loss tetap tergantung pada pengaturan parameter. Menetapkan jumlah stop loss tetap sangat penting untuk pengendalian risiko secara keseluruhan dan perlu mempertimbangkan ukuran modal, nafsu risiko dll.

  5. Arah breakout dapat memberikan sinyal yang salah. Sinyal breakout yang salah dapat terjadi selama osilasi harga atau pullback. Lebih banyak kondisi diperlukan untuk mengoptimalkan strategi.

  6. Tidak ada mekanisme pengambilan keuntungan. Strategi saat ini tidak memiliki kemampuan pengambilan keuntungan untuk secara aktif mengunci keuntungan. Ini dapat menyebabkan keuntungan yang tidak memuaskan.

Untuk mengatasi risiko ini, beberapa cara untuk mengoptimalkan strategi meliputi:

  1. Menambahkan indikator untuk menyaring kualitas sinyal, misalnya MACD, KD dll.

  2. Mengintegrasikan indikator kekuatan pecah untuk mengevaluasi kualitas.

  3. Menambahkan batas frekuensi perdagangan terbuka, misalnya satu perdagangan per hari.

  4. Mengoptimalkan logika stop loss tetap, misalnya stop loss berbasis persentase di atas ambang batas.

  5. Menambahkan filter lain, misalnya volatilitas, meningkatkan stop loss, dll.

  6. Menggabungkan strategi mengambil keuntungan, misalnya mengambil keuntungan di dekat resistensi.

Arahan Optimasi

Berdasarkan analisis, strategi dapat dioptimalkan dalam aspek berikut:

  1. Menambahkan filter untuk meningkatkan kualitas sinyal menggunakan beberapa indikator teknis dan menilai kualitas tren.

  2. Mengoptimalkan stop loss untuk fleksibilitas yang lebih besar. Dapat beralih ke stop trailing berdasarkan persentase setelah retracement tertentu. Juga dapat mengoptimalkan secara dinamis berdasarkan volatilitas.

  3. Mengontrol frekuensi perdagangan untuk menghindari perdagangan berlebihan dengan menambahkan filter pada periode waktu atau frekuensi.

  4. Memasukkan indikator tren untuk meningkatkan waktu, misalnya menunggu konfirmasi tren.

  5. Mengoptimalkan strategi pengambilan keuntungan untuk meningkatkan profitabilitas melalui target keuntungan, penundaan keuntungan, penundaan volatilitas, dll.

  6. Mengoptimalkan parameter risiko berdasarkan backtest, seperti jumlah stop tetap, periode breakout dll.

  7. Refactoring kode untuk ekstensibilitas yang lebih baik dengan lebih memisahkan sinyal, filter, risiko, modul keuntungan.

  8. Uji lebih banyak produk untuk peluang arbitrase. Evaluasi keuntungan di berbagai kombinasi produk.

Melalui dimensi optimasi ini, strategi stop loss breakout dapat menjadi lebih kuat dan menguntungkan.

Kesimpulan

Secara keseluruhan, strategi ini masuk akal dalam menggunakan band istirahat untuk mengidentifikasi tren dan berhenti jumlah tetap untuk pengendalian risiko. Konsepnya progresif untuk manajemen risiko. Logika ukuran posisi juga bagus untuk mengendalikan kerugian per perdagangan. Tetapi strategi dapat ditingkatkan melalui berbagai optimasi untuk meningkatkan kualitas sinyal, fleksibilitas dalam stop loss, profitabilitas, dll. Dengan menggabungkan filter tren, meningkatkan pengambilan keuntungan, dan mengontrol frekuensi perdagangan secara ketat, perbaikan yang signifikan dapat dicapai.


/*backtest
start: 2023-10-26 00:00:00
end: 2023-10-28 03:00:00
period: 10m
basePeriod: 1m
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/
//@version=4
//@author=Takazudo

strategy("Fixed price SL",
  overlay=true,
  default_qty_type=strategy.fixed,
  initial_capital=0,
  currency=currency.USD)

var COLOR_TRANSPARENT = color.new(#000000, 100)
var COLOR_ENTRY_BAND = color.new(#43A6F5, 30)

//============================================================================
// config
//============================================================================

// Money management
_g1 = 'Money management'
var config_riskPrice = input(100, minval=1, title="Risk price for each entry", group=_g1)
var config_depositCurrency = input(title="Deposit currency", type=input.string, defval="USD", options=["USD"], group=_g1)

// Entry strategy
_g2 = 'Entry strategy'
var config_entryBandBars = input(defval = 100, title = "Entry band bar count",  minval=1, group=_g2)

// Backtesting range
_g3 = 'Backtesting range'
fromYear  = input(defval = 2018, title = "From Year",  minval = 1970, group=_g3)
fromMonth = input(defval = 1,    title = "From Month", minval = 1, maxval = 12, group=_g3)
fromDay   = input(defval = 1,    title = "From Day",   minval = 1, maxval = 31, group=_g3)
toYear  = input(defval = 2020, title = "To Year",  minval = 1970, group=_g3)
toMonth = input(defval = 12,    title = "To Month", minval = 1, maxval = 12, group=_g3)
toDay   = input(defval = 31,    title = "To Day",   minval = 1, maxval = 31, group=_g3)

//============================================================================
// exchange caliculations
//============================================================================

// mico pip size caliculation
// ex1: AUDCAD -> 0.0001
// ex2: USDJPY -> 0.01
f_calcMicroPipSize() =>
    _base = syminfo.basecurrency
    _quote = syminfo.currency
    _result = 0.0001
    if _quote == 'JPY'
        _result := _result * 100
    if _base == 'BTC'
        _result := _result * 100
    _result

// convert price to pips
f_convertPriceToPips(_price) =>
    _microPipSize = f_calcMicroPipSize()
    _price / _microPipSize

// caliculate exchange rate between deposit and quote currency
f_calcDepositExchangeSymbolId() =>
    _result = ''
    _deposit = config_depositCurrency
    _quote = syminfo.currency
    if (_deposit == 'USD') and (_quote == 'USD')
        _result := na
    if (_deposit == 'USD') and (_quote == 'AUD')
        _result := 'OANDA:AUDUSD'
    if (_deposit == 'EUR') and (_quote == 'USD')
        _result := 'OANDA:EURUSD'
    if (_deposit == 'USD') and (_quote == 'GBP')
        _result := 'OANDA:GBPUSD'
    if (_deposit == 'USD') and (_quote == 'NZD')
        _result := 'OANDA:NZDUSD'
    if (_deposit == 'USD') and (_quote == 'CAD')
        _result := 'OANDA:USDCAD'
    if (_deposit == 'USD') and (_quote == 'CHF')
        _result := 'OANDA:USDCHF'
    if (_deposit == 'USD') and (_quote == 'JPY')
        _result := 'OANDA:USDJPY'
    _result

// Let's say we need CAD to USD exchange
// However there's only "OANDA:USDCAD" symbol.
// Then we need to invert the exhchange rate.
// this function tells us whether we should invert the rate or not
f_calcShouldInvert() =>
    _result = false
    _deposit = config_depositCurrency
    _quote = syminfo.currency
    if (_deposit == 'USD') and (_quote == 'CAD')
        _result := true
    if (_deposit == 'USD') and (_quote == 'CHF')
        _result := true
    if (_deposit == 'USD') and (_quote == 'JPY')
        _result := true
    _result

// caliculate how much quantity should I buy or sell
f_calcQuantitiesForEntry(_depositExchangeRate, _slPips) =>
    _microPipSize = f_calcMicroPipSize()
    _priceForEachPipAsDeposit = _microPipSize * _depositExchangeRate
    _losePriceOnSl = _priceForEachPipAsDeposit * _slPips
    floor(config_riskPrice / _losePriceOnSl)

//============================================================================
// Quantity caliculation
//============================================================================

depositExchangeSymbolId = f_calcDepositExchangeSymbolId()

// caliculate deposit exchange rate
rate = security(depositExchangeSymbolId, timeframe.period, hl2)
shouldInvert = f_calcShouldInvert()
depositExchangeRate = if config_depositCurrency == syminfo.currency
    // if USDUSD, no exchange of course
    1
else
    // else, USDCAD to CADUSD invert if we need
    shouldInvert ? (1 / rate) : rate

//============================================================================
// Range Edge caliculation
//============================================================================

f_calcEntryBand_high() =>
    _highest = max(open[3], close[3])
    for i = 4 to (config_entryBandBars - 1)
        _highest := max(_highest, open[i], close[i])
    _highest

f_calcEntryBand_low() =>
    _lowest = min(open[3], close[3])
    for i = 4 to (config_entryBandBars - 1)
        _lowest := min(_lowest, open[i], close[i])
    _lowest

entryBand_high = f_calcEntryBand_high()
entryBand_low = f_calcEntryBand_low()
entryBand_height = entryBand_high - entryBand_low

plot(entryBand_high, color=COLOR_ENTRY_BAND, linewidth=1)
plot(entryBand_low, color=COLOR_ENTRY_BAND, linewidth=1)

rangeBreakDetected_long = entryBand_high < close
rangeBreakDetected_short = entryBand_low > close

shouldMakeEntryLong = (strategy.position_size == 0) and rangeBreakDetected_long
shouldMakeEntryShort = (strategy.position_size == 0) and rangeBreakDetected_short

//============================================================================
// SL & Quantity
//============================================================================

var sl_long = hl2
var sl_short = hl2

entryQty = 0
slPips = 0.0

// just show info bubble
f_showEntryInfo(_isLong) =>
    _str =
      'SL pips: ' + tostring(slPips) + '\n' +
      'Qty: ' + tostring(entryQty)
    _bandHeight = entryBand_high - entryBand_low
    _y = _isLong ? (entryBand_low + _bandHeight * 1/4) : (entryBand_high - _bandHeight * 1/4)
    _style = _isLong ? label.style_label_up : label.style_label_down
    label.new(bar_index, _y, _str, size=size.large, style=_style)

if shouldMakeEntryLong
    sl_long := (entryBand_high + entryBand_low) / 2
    slPips := f_convertPriceToPips(close - sl_long)
    entryQty := f_calcQuantitiesForEntry(depositExchangeRate, slPips)
if shouldMakeEntryShort
    sl_short := (entryBand_high + entryBand_low) / 2
    slPips := f_convertPriceToPips(sl_short - close)
    entryQty := f_calcQuantitiesForEntry(depositExchangeRate, slPips)

// trailing SL
if strategy.position_size > 0
    sl_long := max(sl_long, entryBand_low)
if strategy.position_size < 0
    sl_short := min(sl_short, entryBand_high)

//============================================================================
// backtest duration
//============================================================================

// Calculate start/end date and time condition
startDate  = timestamp(fromYear, fromMonth, fromDay, 00, 00)
finishDate = timestamp(toYear,   toMonth,   toDay,   00, 00)

//============================================================================
// make entries
//============================================================================

if (true)
    if shouldMakeEntryLong
        strategy.entry(id="Long", long=true, stop=close, qty=entryQty)
        f_showEntryInfo(true)
    if shouldMakeEntryShort
        strategy.entry(id="Short", long=false, stop=close, qty=entryQty)
        f_showEntryInfo(false)

strategy.exit('Long-SL/TP', 'Long', stop=sl_long)
strategy.exit('Short-SL/TP', 'Short', stop=sl_short)

//============================================================================
// plot misc
//============================================================================

sl = strategy.position_size > 0 ? sl_long :
  strategy.position_size < 0 ? sl_short : na

plot(sl, color=color.red, style=plot.style_cross, linewidth=2, title="SL")

value_bgcolor = rangeBreakDetected_long ? color.green :
  rangeBreakDetected_short ? color.red : COLOR_TRANSPARENT

bgcolor(value_bgcolor, transp=95)


Lebih banyak