وسائل لوڈ ہو رہے ہیں... لوڈنگ...

آرکیٹیکچر کی پیشرفت بیک ٹیسٹنگ کی حکمت عملی

مصنف:چاؤ ژانگ، تاریخ: 2023-10-17 17:26:03
ٹیگز:

img

جائزہ

اس حکمت عملی میں کچھ اہم حالات کے تحت طویل یا مختصر جانے کے لئے سطح کی پیشرفت کا نقطہ نظر اپنایا گیا ہے ، اور اس میں بہترین پیرامیٹر مجموعہ تلاش کرنے کے لئے آٹو بیک ٹیسٹنگ کی صلاحیتیں ہیں۔

اصول

  1. ان پٹ پیرامیٹرز میں بیک بیک دن ، منافع کی فیصد ، اسٹاپ نقصان کی فیصد ، اور آٹو بیک ٹیسٹنگ پیرامیٹرز جیسے بیک بیک رینج ، منافع / اسٹاپ نقصان کی حد وغیرہ شامل ہیں۔

  2. بیک ٹسٹنگ کے دوران ، بیک بیک کے مختلف مجموعوں کو عبور کریں ، منافع لیں اور نقصان کو روکیں ، اور ہر مجموعہ کے لئے پی این ایل ریکارڈ کریں۔

  3. بریک آؤٹ سگنل منطق: لمبا جب قریب سے اوپر کی بینڈ اور داخلہ بار نہیں ، مختصر جب قریب سے نیچے کی بینڈ اور داخلہ بار سے نیچے ہوتا ہے۔

  4. سٹاپ نقصان کی شرط: اگر منافع نہیں لیا اور سٹاپ نقصان کو متحرک کیا جاتا ہے، تو تجارت سے باہر نکلیں.

  5. لے منافع کی شرط: اگر روک نہیں ہے اور لے منافع چالو کیا جاتا ہے، تجارت سے باہر نکلیں.

  6. تفصیلی بیک ٹسٹ کے نتائج کی میز دکھائیں، جو صارف کی ترتیبات پر مبنی جیت کی شرح، خالص منافع یا تجارت کی تعداد کے مطابق ترتیب دی جاسکتی ہے۔

فوائد

  1. آٹو بیک ٹیسٹ دستی ٹیسٹنگ کے بغیر زیادہ سے زیادہ پیرامیٹر سیٹ کو تیزی سے تلاش کرسکتا ہے.

  2. ضرورت کے مطابق جیت کی شرح، خالص منافع، تجارت کی تعداد وغیرہ کی طرف سے backtest کے نتائج لچکدار ترتیب دیں.

  3. ہر تجارت کے لئے PnL کو تصور کریں.

  4. اپنی مرضی کے مطابق backtest پیرامیٹرز عالمی زیادہ سے زیادہ تلاش کرنے کے لئے وسیع پیرامیٹر کی جگہ کی جانچ کے لئے.

  5. سادہ اور واضح تجارتی قوانین کو سمجھنے اور لاگو کرنے میں آسان.

خطرات اور حل

  1. مختصر بیک ٹیسٹ کی مدت غیر مستحکم نتائج کا باعث بن سکتی ہے۔ حل: طویل بیک ٹیسٹ کی مدت کا استعمال کریں۔

  2. منافع کو متاثر کرنے والے سلائڈ کے لئے موزوں کثرت سے تجارت۔ حل: مناسب طریقے سے منافع / اسٹاپ نقصان کی سطح کو کم کریں۔

  3. ایک آلہ بیک ٹسٹ نمائندہ نہیں ہوسکتا ہے۔ حل: مضبوط پیرامیٹر سیٹ تلاش کرنے کے لئے مختلف مصنوعات پر ٹیسٹ کریں۔

  4. زیادہ سے زیادہ اصلاح شدہ پیرامیٹرز زیادہ فٹنگ کا سبب بنتے ہیں۔ حل: مصنوعات اور ٹائم فریموں میں پیرامیٹرز کی استحکام کا تجربہ کریں۔

  5. لین دین کے اخراجات کو نظر انداز کرنے سے نتائج میں تعصب پیدا ہوتا ہے۔ حل: معقول کمیشن کی ترتیبات کا استعمال کریں۔

بہتری کی ہدایات

  1. اصلاح کے طول و عرض میں اضافہ کریں جیسے ٹریلنگ اسٹاپ یا تجارتی حدود شامل کرنا۔

  2. رجحان فلٹرز کے ساتھ داخلہ کے حالات کو بہتر بنائیں.

  3. متحرک لے منافع یا پیچھے سٹاپ نقصان کی طرح منافع / سٹاپ نقصان کو بہتر بنائیں.

  4. پیرامیٹر کی اصلاح کے لئے مشین لرننگ متعارف کروائیں۔

  5. تیز بیک ٹیسٹنگ کے لئے کوڈ کی ساخت کو بہتر بنائیں.

  6. مصنوعات اور ٹائم فریموں میں پیرامیٹر کی مضبوطی کی جانچ کریں۔

  7. آٹو ٹریڈنگ کی صلاحیتوں کو ضم کرنے پر غور کریں.

نتیجہ

اس حکمت عملی میں واضح اور آسان منطق ہے ، آٹو بیک ٹیسٹنگ پیرامیٹرز کی تیز رفتار موافقت کو قابل بناتی ہے ، پی این ایل ڈسپلے مزید بہتری کی سہولت فراہم کرتی ہے۔ خطرات موجود ہیں لیکن کثیر جہتی اصلاحات کے ذریعہ ان کو کم کیا جاسکتا ہے ، جس میں عملی قدر ہے۔ خلاصہ یہ ہے کہ آٹو بیک ٹیسٹنگ ٹولز سے لیس یہ حکمت عملی تاجروں کو آسان بریک آؤٹ تصورات کی بنیاد پر مستحکم تجارتی نظام تیار کرنے میں مدد دے سکتی ہے۔


/*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)





مزید