
Strategi ini menggunakan cara level breakout, melakukan lebih banyak blanko dalam kondisi breakout tertentu, dan memiliki fungsi feedback otomatis untuk menemukan kombinasi parameter optimal.
Parameter input termasuk jumlah hari, persentase stop, persentase stop, dan parameter pengembalian otomatis seperti jumlah hari, rentang stop loss, dan sebagainya.
Pada saat melakukan retrospeksi, periksa berbagai kombinasi dari jumlah hari, persentase stop loss, dan persentase stop loss, dan catat keuntungan dan kerugian dalam setiap kombinasi.
Penilaian sinyal terobosan: harga penutupan melewati band atas dan bukan waktu masuk ke pasar, melakukan lebih banyak; harga penutupan melewati band bawah dan bukan waktu masuk ke pasar, melakukan kosong.
Penghakiman kondisi stop loss: Jika tidak berhenti dan memicu garis stop loss, maka stop loss akan dimulai.
Kondisi penutupan: Jika tidak ada kerusakan dan memicu penutupan, penutupan akan dihentikan.
Tampilan tabel yang jelas dari hasil pengujian, dapat disortir berdasarkan tingkat keuntungan atau keuntungan bersih atau jumlah transaksi yang disetel oleh pengguna.
Fungsi feedback otomatis dapat dengan cepat menemukan kombinasi parameter yang optimal, tanpa perlu pengujian manual.
Anda dapat memilah-milah hasil pengembalian berdasarkan tingkat keuntungan, laba bersih, jumlah transaksi, dan sebagainya. Anda dapat secara fleksibel memilih parameter optimal yang sesuai dengan kebutuhan Anda.
Untuk melihat keuntungan dan kerugian dari setiap transaksi.
Parameter pengukuran dapat disesuaikan, sehingga dapat menguji ruang parameter yang lebih luas untuk menemukan yang terbaik secara keseluruhan.
Strategi trading yang sederhana, jelas, dan mudah dipahami.
Siklus pengembalian yang pendek dapat menyebabkan hasil yang tidak stabil. Solusi: atur siklus pengembalian yang lebih panjang.
Perdagangan yang sering dapat menyebabkan terjadinya slippage yang mempengaruhi keuntungan. Solusi: Melegakan stop loss dengan tepat.
Hasil pengujian terhadap satu produk mungkin tidak representatif. Solusi: pengujian terhadap varietas yang berbeda untuk menemukan kombinasi parameter yang stabil.
Parameter yang terlalu dioptimalkan dapat menyebabkan over-fit. Solusi: Verifikasi parameter stabilitas pada varietas yang berbeda dan periode waktu.
Mengabaikan biaya transaksi dapat menyebabkan hasil pengukuran yang menyimpang. Solusi: Tetapkan parameter biaya yang wajar.
Menambahkan dimensi optimasi parameter, seperti menambahkan stop loss bergerak atau pembatasan jumlah transaksi.
Optimalkan kondisi masuk ke pasar dengan menggunakan filter indikator tren.
Optimalkan strategi stop loss, seperti stop loss dinamis atau tracking stop loss.
Optimasi parameter tambahan untuk algoritma seperti pembelajaran mesin.
Pengoptimalan struktur kode untuk meningkatkan kecepatan pengetesan.
Stabilitas parameter verifikasi multi-siklus pada beberapa varietas.
Pertimbangkan untuk mengintegrasikan fungsi perdagangan otomatis.
Strategi ini memiliki konsep yang jelas dan mudah dimengerti, fitur pengembalian otomatis dapat mengoptimalkan parameter dengan cepat, menunjukkan bahwa keuntungan dan kerugian menguntungkan untuk perbaikan strategi. Ada risiko tertentu yang perlu diperhatikan, tetapi dapat dioptimalkan melalui perbaikan terus menerus dalam banyak hal, dan memiliki nilai praktis yang kuat. Secara keseluruhan, strategi ini menggunakan pemikiran yang sederhana dan dilengkapi dengan alat pengembalian otomatis, yang dapat membantu pedagang membangun sistem perdagangan yang stabil dengan cepat.
/*backtest
start: 2023-09-16 00:00:00
end: 2023-10-16 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/
// © -_-
//@version=5
// strategy("[-_-] LBAB", process_orders_on_close=true, overlay=true, max_labels_count=500, max_lines_count=500, max_boxes_count=500, default_qty_type=strategy.cash, default_qty_value=100, initial_capital=10000, commission_type=strategy.commission.percent, commission_value=0.075)
// Inputs
lookback = input.int(2, title="Lookback", minval=2, maxval=15)
tp = input.float(5, title="TP (%)", minval=1, maxval=10000)
sl = input.float(5, title="SL (% from Low)", minval=1, maxval=100)
com = input.float(0.075, title="Commission (%)", minval=0, maxval=50)
min_lookback_tr = input.float(2, title="Min Lookback", minval=1, maxval=500, inline="tr_lookback", group="Optimisation")
max_lookback_tr = input.float(5, title="Max Lookback", minval=1, maxval=500, inline="tr_lookback", group="Optimisation")
min_tp_tr = input.float(5, title="Min TP (%)", minval=1, maxval=10000, inline="tr_tp", group="Optimisation")
max_tp_tr = input.float(10, title="Max TP (%)", minval=1, maxval=10000, inline="tr_tp", group="Optimisation")
min_sl_tr = input.float(1, title="Min SL (%)", minval=1, maxval=100, inline="tr_sl", group="Optimisation")
max_sl_tr = input.float(5, title="Max SL (%)", minval=1, maxval=100, inline="tr_sl", group="Optimisation")
imp_perc_profit = input.bool(true, title="Percentage profitable", group="Optimisation")
imp_netprofit = input.bool(false, title="Net profit", group="Optimisation")
imp_numtrades = input.bool(false, title="Number of trades", group="Optimisation")
table_pos = input.string("Bottom Right", title="Position", options=["Top Left", "Top Center", "Top Right", "Middle Left", "Middle Center", "Middle Right", "Bottom Left", "Bottom Center", "Bottom Right"], group="Table")
table_font_size = input.string("Normal", title="Font size", options=["Auto", "Tiny", "Small", "Normal", "Large"], group="Table")
// Table parameters
table_pos_ = switch table_pos
"Top Left" => position.top_left
"Top Center" => position.top_center
"Top Right" => position.top_right
"Middle Left" => position.middle_left
"Middle Center" => position.middle_center
"Middle Right" => position.middle_right
"Bottom Left" => position.bottom_left
"Bottom Center" => position.bottom_center
"Bottom Right" => position.bottom_right
table_font_size_ = switch table_font_size
"Auto" => size.auto
"Tiny" => size.tiny
"Small" => size.small
"Normal" => size.normal
"Large" => size.large
// Sorting function (first element will be largest)
sortArr(arr, arr_index) =>
n = array.size(arr) - 1
for i = 0 to n - 1
for j = 0 to n - i - 1
if array.get(arr, j) < array.get(arr, j + 1)
temp = array.get(arr, j)
temp_index = array.get(arr_index, j)
array.set(arr, j, array.get(arr, j + 1))
array.set(arr, j + 1, temp)
array.set(arr_index, j, array.get(arr_index, j + 1))
array.set(arr_index, j + 1, temp_index)
// Safe checks
if min_lookback_tr > max_lookback_tr
runtime.error("Min Lookback must be less than Max Lookback")
if min_tp_tr > max_tp_tr
runtime.error("Min Take Profit must be less than Max Take Profit")
if min_sl_tr > max_sl_tr
runtime.error("Min Stop Loss must be less than Max Stop Loss")
//
tp_min_ = int(min_tp_tr / 1)
tp_max_ = int(max_tp_tr / 1)
sl_min_ = int(min_sl_tr / 1)
sl_max_ = int(max_sl_tr / 1)
// Size for arrays
arr_size = int((max_lookback_tr - min_lookback_tr + 1) * (tp_max_ - tp_min_ + 1) * (sl_max_ - sl_min_ + 1))
// Arrays
var arr_bi = array.new_int(arr_size, na) // bar_index of Smash Day
var arr_in_pos = array.new_bool(arr_size, false) // are we in a position?
var arr_params = array.new_string(arr_size, "")
var arr_wonlost = array.new_string(arr_size, "")
var arr_profit = array.new_float(arr_size, 0)
// Testing what parameters are best
index = 0
// Lookback
for lookback_i = min_lookback_tr to max_lookback_tr
// Take profit
for tp_i = tp_min_ to tp_max_
// Stop loss
for sl_i = sl_min_ to sl_max_
// Parameters of current iteration
lookback_ = lookback_i
tp_ = tp_i
sl_ = sl_i
//
if array.get(arr_params, index) == ""
array.set(arr_params, index, str.tostring(lookback_) + " " + str.tostring(tp_) + " " + str.tostring(sl_))
// Was there an entry?
was_edone = false
// If entry price reached
if not array.get(arr_in_pos, index) and not na(array.get(arr_bi, index))
if high >= high[bar_index - array.get(arr_bi, index)] and bar_index != array.get(arr_bi, index)
array.set(arr_in_pos, index, true)
was_edone := true
// If we're in a position
if array.get(arr_in_pos, index) and bar_index != array.get(arr_bi, index) and not was_edone
low_sl = low[bar_index - array.get(arr_bi, index)] * (1 - sl_ / 100)
high_ep = high[bar_index - array.get(arr_bi, index)]
high_tp = high_ep * (1 + tp_ / 100)
amount = 100
// Stop loss
if low <= low_sl
array.set(arr_in_pos, index, false)
array.set(arr_wonlost, index, array.get(arr_wonlost, index) + "0")
array.set(arr_profit, index, array.get(arr_profit, index) - math.abs(amount / high_ep * low_sl - amount) - com / 100 * amount * 2)
array.set(arr_bi, index, na)
// Take profit
if high >= high_tp
array.set(arr_in_pos, index, false)
array.set(arr_wonlost, index, array.get(arr_wonlost, index) + "1")
array.set(arr_profit, index, array.get(arr_profit, index) + math.abs(amount / high_ep * high_tp - amount) - com / 100 * amount * 2)
array.set(arr_bi, index, na)
// Entry condition
cond = barstate.isconfirmed and close < low[1] and high[1] < high[lookback_ + 1] //and not array.get(arr_in_pos, index)
// New entry price
if cond and not array.get(arr_in_pos, index)
array.set(arr_bi, index, bar_index)
// Update index
index := index + 1
// Checking the results
var table t = na
var result_index = array.new_int(0, na)
var result_arr_winrate = array.new_float(0, na)
var result_arr_tradenum = array.new_int(0, na)
var sort_array = array.new_float(0, na)
if (barstate.islast or barstate.islastconfirmedhistory) and na(t)
for i = 0 to array.size(arr_params) - 1
wins = 0
losses = 0
arr = array.get(arr_wonlost, i)
for j = 0 to str.length(arr) - 1
str_ = str.substring(arr, j, j + 1)
if str_ == "0"
losses := losses + 1
if str_ == "1"
wins := wins + 1
// Push percentage profitable trades
perc_profit = math.round(wins / (wins + losses) * 100, 2)
array.push(result_arr_winrate, perc_profit)
// Push number of trades
trade_num = str.length(array.get(arr_wonlost, i))
array.push(result_arr_tradenum, trade_num)
// Push index
array.push(result_index, i)
// For combined sorting
array.push(sort_array, (imp_netprofit ? array.get(arr_profit, i) : 1) * (imp_perc_profit ? perc_profit : 1) * (imp_numtrades ? trade_num : 1))
// Sort
sortArr(array.copy(sort_array), result_index)
t := table.new(columns=6, rows=13, bgcolor=color.white, border_color=color.new(color.blue, 0), border_width=1, frame_color=color.new(color.blue, 0), frame_width=1, position=table_pos_)
table.cell(t, 0, 0, "% Profitable" + (imp_perc_profit ? " ↓" : ""), bgcolor=imp_perc_profit ? color.rgb(23, 18, 25) : color.white, text_color=imp_perc_profit ? color.white : color.black, text_size=table_font_size_)
table.cell(t, 1, 0, "Net Profit" + (imp_netprofit ? " ↓" : ""), bgcolor=imp_netprofit ? color.rgb(23, 18, 25) : color.white, text_color=imp_netprofit ? color.white : color.black, text_size=table_font_size_)
table.cell(t, 2, 0, "# of trades" + (imp_numtrades ? " ↓" : ""), bgcolor=imp_numtrades ? color.rgb(23, 18, 25) : color.white, text_color=imp_numtrades ? color.white : color.black, text_size=table_font_size_)
table.cell(t, 3, 0, "Lookback", text_size=table_font_size_)
table.cell(t, 4, 0, "Take Profit %", text_size=table_font_size_)
table.cell(t, 5, 0, "Stop Loss %", text_size=table_font_size_)
counter = 0
forloop_counter = math.min(array.size(result_index) - 1, 10)
for i = 0 to forloop_counter
i_ = array.get(result_index, i)
params_ = str.split(array.get(arr_params, i_), " ")
col_ = color.new(color.blue, 75)
table.cell(t, 0, i + 1, str.tostring(array.get(result_arr_winrate, i_)) + "%", bgcolor=col_, text_size=table_font_size_)
table.cell(t, 1, i + 1, str.tostring(math.round(array.get(arr_profit, i_), 2)) + "$", bgcolor=col_, text_size=table_font_size_)
table.cell(t, 2, i + 1, str.tostring(array.get(result_arr_tradenum, i_)), bgcolor=col_, text_size=table_font_size_)
table.cell(t, 3, i + 1, array.get(params_, 0), bgcolor=col_, text_size=table_font_size_)
table.cell(t, 4, i + 1, array.get(params_, 1), bgcolor=col_, text_size=table_font_size_)
table.cell(t, 5, i + 1, array.get(params_, 2), bgcolor=col_, text_size=table_font_size_)
counter := counter + 1
// Warn if timeframe is <= 10 minutes
if timeframe.in_seconds(timeframe.period) <= 600
table.cell(t, 0, forloop_counter + 2, "Timeframe might be too low", bgcolor=color.orange, text_size=table_font_size_, tooltip="Selected timeframe might be too low and cause an error")
table.merge_cells(t, 0, forloop_counter + 2, 5, forloop_counter + 2)
// Strategy
var int bi = na
var int pos_bi = na
// Buy condition
cond = barstate.isconfirmed and close < low[1] and high[1] < high[lookback + 1] and strategy.position_size == 0
// Stop loss, Take profit
if strategy.position_size[1] == 0 and strategy.position_size > 0 and bar_index != bi
strategy.exit("TP/SL", "Long", stop=low[bar_index - bi] * (1 - sl / 100), limit=high[bar_index - bi] * (1 + tp / 100))
pos_bi := bar_index
// Buy
if cond
strategy.order("Long", strategy.long, stop=high)
bi := bar_index
// Box
if strategy.position_size[1] != 0 and strategy.position_size == 0
tn = strategy.closedtrades - 1
penp = strategy.closedtrades.entry_price(tn)
pexp = strategy.closedtrades.exit_price(tn)