
この戦略は,レベル突破の方法をとり,一定の突破条件で多空をしており,最適なパラメータの組み合わせを見つけるための自動反射機能を持っています.
入力パラメータには,回顧日数,停止比率,停止比率,および回顧日数,停止停止範囲などの自動回測パラメータが含まれます.
回転時,回転日数,止損率,止損率の様々な組み合わせを回転して,それぞれの組み合わせの下での損益を記録する.
突破シグナル判断:閉盘価格上は上帯を突破し,入市時柱ではなく,多額の取引;閉盘価格下は下帯を突破し,入市時柱ではなく,空き.
止損条件判定:止損ラインを触発して止まらない場合は,止損出場する.
停止条件判定:止損がなく,停止線が触発された場合は,止止が出場する.
フィードバック結果の詳細な表が表示され,ユーザの設定により,収益率または純利益または取引回数で並べられます.
自動反射機能は,手作業のテストを必要とせずに,最適なパラメータの組み合わせを素早く見つけることができます.
率,純利益,取引回数などの順序付けで,自分の必要に応じて最適なパラメータを柔軟に選択できます.
取引の利益と損失を視覚化します.
回測パラメータはカスタマイズされ,より広いパラメータ空間をテストして,全局の最適値を見つけることができる.
戦略的取引のルールがシンプルでわかりやすく,理解しやすい.
返信周期が短く結果が不安定になる可能性があります. 解決策:より長い返信周期を設定してください.
取引の頻度が滑りやすいため,利益に影響する. 解決策:適切な緩解の止まりの止まりの幅.
単一の商品の反省結果は不代表である可能性があります. 解決策:異なる品種を反省し,安定したパラメータの組み合わせを見つけます.
パラメータを過度最適化すると過適合が起こりうる. 解決策:異なる品種と時間周期におけるパラメータの安定性を検証する.
トランザクションコストを無視すると,反測結果の偏差が生じます. 解決策:合理的な手数料パラメータを設定します.
移動ストップや取引回数制限など,パラメータ最適化の次元を追加する.
市場参入条件の最適化とトレンド指標のフィルタリング
ダイナミックストップやストップトラッキングなどのストップストップ戦略を最適化します.
機械学習などのアルゴリズム補助パラメータの最適化.
コード構造を最適化し,反省速度を上げます.
多種多周期検証パラメータの安定性
自動取引機能の統合を検討する.
この戦略の総合的な考え方は明確で分かりやすく,自動反測機能はパラメータを迅速に最適化することができ,損益状況が戦略改善に有利であることを示す.ある程度のリスクがあることに注意する必要があるが,多方面での最適化による継続的な改善が可能で,強力な実用価値を有している.全体的に言えば,この戦略は,単純な突破的な考え方を活用し,自動反測ツールで装備され,トレーダーが迅速に安定した取引システムを確立するのを支援できる.
/*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)