【问题标题】:Strategy not opening any trades策略不开启任何交易
【发布时间】:2022-08-17 23:27:38
【问题描述】:

我的策略有问题,特别是它根本没有打开任何交易。我尝试尽可能多地对此进行调试,并且我的调试标签准确地显示了应该在哪里进行交易。但是,根本没有交易。

该策略用于 Capital.com 上的 US500 指数,设置为 1H 时间框架和 HTF 确认蜡烛上的 3 个 SFP 和 LFT 确认蜡烛上的 2 个 SFP。没有使用有时间限制的回测——但即使我使用它并将其设置为仅上个月,也没有任何变化。

这是我正在尝试的策略:

//@version=5
strategy(title = \"Candle Squeeze Strategy\", shorttitle=\"Squeeze Strategy\", overlay=true, process_orders_on_close = true, calc_on_order_fills = true, pyramiding = 0, default_qty_type = strategy.percent_of_equity, default_qty_value = 75, commission_type = strategy.commission.percent, commission_value = 0.04, initial_capital = 100, max_bars_back = 5000, max_boxes_count = 500, max_lines_count = 500, max_labels_count = 500)

GROUP_PA_OPTIONS             = \"Price Action Options\"
GROUP_TIME_LIMITED_BACKTESTS = \"Time-Limit BackTests (0 = disable)\"

i_tf = input.timeframe( \"60\", \"TF to look for Squeeze in\", group = GROUP_PA_OPTIONS )
i_squeeze_num_prev_candles_confirmation = input.int(3, \"Confirm Squeeze on HTF by this many candles\", minval = 0, tooltip = \"We will check this many candles in the same direction as was the trend before HTF Squeeze to see if there was a continuous rise / fall in that trend right before the Squeeze. For example, in a downtrend followed by a Squeeze, we will check X red continuous candles right before Squeeze was found. If we cannot find this many continuous candles in that downtrend, we will not open any trades for that Squeeze.\", group = GROUP_PA_OPTIONS)
i_ltf_squeeze_num_prev_candles_confirmation = input.int(2, \"Confirm Squeeze on LFT by this many candles\", minval = 0, tooltip = \"We will check this many candles in the same direction as was the trend before LFT Squeeze to see if there was a continuous rise / fall in that trend right before the Squeeze. For example, in a downtrend followed by a Squeeze, we will check X red continuous candles right before Squeeze was found. If we cannot find this many continuous candles in that downtrend, we will not open any trades for that Squeeze.\", group = GROUP_PA_OPTIONS)
TPPerc = input.float( 2, title=\"Take Profit (%)\", minval=0.1, step=0.1, group = GROUP_PA_OPTIONS)
SLPerc = input.float( 1, title=\"Stop Loss (%)\", minval=0.1, step=0.1, group = GROUP_PA_OPTIONS)

i_use_time_limited_backtesting = input.bool( false, \"Use Time-Limited Backtesting\", group = GROUP_TIME_LIMITED_BACKTESTS )
i_startDay = input.int(0, \"Start Day\", minval = 0, maxval = 31, group = GROUP_TIME_LIMITED_BACKTESTS)
i_startMonth = input.int(0, \"Start Month\", minval = 0, maxval = 12, group = GROUP_TIME_LIMITED_BACKTESTS)
i_startYear = input.int(0, \"Start Year\", minval = 0, maxval = 2100, group = GROUP_TIME_LIMITED_BACKTESTS)

i_endDay = input.int(0, \"End Day\", minval = 0, maxval = 31, group = GROUP_TIME_LIMITED_BACKTESTS)
i_endMonth = input.int(0, \"End Month\", minval = 0, maxval = 12, group = GROUP_TIME_LIMITED_BACKTESTS)
i_endYear = input.int(0, \"End Year\", minval = 0, maxval = 2100, group = GROUP_TIME_LIMITED_BACKTESTS)

inDateRange = true

var tf_last_bar_index = -1
var last_candle_type = \"\"
var last_candle_close = -1.0
var prev_candle_type = \"\"
var prev_candle_close = -1.0
var first_candle_type = \"\"
var first_candle_close = -1.0
var squeeze_plotted = false
var htf_squeeze_found = false
var recorded_squeeze_type          = \"\"  // squeeze type
var recorded_squeeze_price_level   = 0.0 // squeeze price to get back to, break below/above and then return through it
var recorded_squeeze_bar_index     = 0   // squeeze bar index, so we don\'t check agains the same bar we found the squeeze on
var price_crossed_recorded_squeeze = false // once true, we\'ll wait for the price to cross the recorded squeeze again and then we\'ll start checking for the next printed FVG
var price_squeeze_cross_bar_index  = 0   // bar index where our price crossed the recorded squeeze

var last_trade_ts = time
var min_trade_gap_minutes = 2

var order_types = array.new_string( 1, \"\" ) // order type
var our_active_orders_count = array.new_int( 1, 0 )
var order_prices = array.new_float( 2 ) // 0 = exit price, 1 = stop price

if array.size( order_prices ) == 0
    array.fill( order_prices, 0.0, 0, 1 )

// Look if the close time of the current bar falls inside the date range
if i_use_time_limited_backtesting and i_startDay != 0 and i_startMonth != 0 and i_startYear != 0 and i_endDay != 0 and i_endMonth != 0 and i_endYear != 0
    inDateRange := ( time >= timestamp( syminfo.timezone, i_startYear, i_startMonth, i_startDay, 0, 0 ) ) and ( time < timestamp( syminfo.timezone, i_endYear, i_endMonth, i_endDay, 0, 0 ) )

//Convert a given string resolution into seconds
ResolutionToSec(res)=>
    mins = res == \"1\" ? 1 :
           res == \"3\" ? 3 :
           res == \"5\" ? 5 :
           res == \"10\" ? 10 :
           res == \"15\" ? 15 :
           res == \"30\" ? 30 :
           res == \"45\" ? 45 :
           res == \"60\" ? 60 :
           res == \"120\" ? 120 :
           res == \"180\" ? 180 :
           res == \"240\" ? 240 :
           res == \"1D\" ? 1440 :
           res == \"1W\" ? 10080 :
           res == \"1M\" ? 43200 : 0
    ms = mins * 60

// }

if ResolutionToSec( i_tf ) < ResolutionToSec( timeframe.period )
    runtime.error(\"Strategy timeframe must be higher or equal than current timeframe.\")

// searches for the Xth value in the prices_array, since we may have multiple same values in that array for the same HTF candle
// and we need for example the 1st, 2nd and 3rd value from that HTF
findHistoryCandle( prices_array, bar_index_array, current_bar_index, candle_num_to_return ) =>
    last_b_index = current_bar_index
    candles_counter = 0
    ret = 0.0

    for i = 0 to array.size( bar_index_array ) - 1
        if array.get( bar_index_array, i ) < current_bar_index and array.get( bar_index_array, i ) != last_b_index
            last_b_index := array.get( bar_index_array, i )
            candles_counter := candles_counter + 1
            if candles_counter == candle_num_to_return
                ret := array.get( prices_array, i )
                break

    [ ret, last_b_index ]

// squeeze detection
string squeeze_type = na
history_array_length = 75
[ candle_open, candle_close, tf_bar_index ] = request.security( syminfo.tickerid, i_tf, [ open, close, bar_index ], barmerge.gaps_off, barmerge.lookahead_off )

tf_bar_index_array = array.new_int()
for i = 0 to history_array_length
    array.push( tf_bar_index_array, tf_bar_index[ i ] )

candle_open_array = array.new_float()
for i = 0 to history_array_length
    array.push( candle_open_array, candle_open[ i ] )

candle_close_array = array.new_float()
for i = 0 to history_array_length
    array.push( candle_close_array, candle_close[ i ] )

// bar index has changed, update candle values
if tf_last_bar_index == -1 or tf_last_bar_index != tf_bar_index
    last_candle_type := candle_close > candle_open ? \"up\" : candle_close < candle_open ? \"down\" : \"\"
    last_candle_close := candle_close
    [ prev_close_price, prev_bar_id ] = findHistoryCandle( candle_close_array, tf_bar_index_array, tf_bar_index[0], 1 )
    [ prev_open_price, prev_bar_id2 ] = findHistoryCandle( candle_open_array, tf_bar_index_array, tf_bar_index[0], 1 )
    prev_candle_type := prev_close_price > prev_open_price ? \"up\" : prev_close_price < prev_open_price ? \"down\" : \"\"
    prev_candle_close := prev_close_price
    //prev_candle_index := prev_bar_id
    [ first_close_price, first_bar_id ] = findHistoryCandle( candle_close_array, tf_bar_index_array, tf_bar_index[0], 2 )
    [ first_open_price, first_bar_id2 ] = findHistoryCandle( candle_open_array, tf_bar_index_array, tf_bar_index[0], 2 )
    first_candle_type := first_close_price > first_open_price ? \"up\" : first_close_price < first_open_price ? \"down\" : \"\"
    first_candle_close := first_close_price

    squeeze_plotted := false

    // only update last bar index here from the higher TF if we\'re initializing
    if tf_last_bar_index == -1
        tf_last_bar_index := tf_bar_index

// squeeze in swing low
if prev_candle_type == \"up\" and last_candle_type == \"down\" and first_candle_type == \"down\" and last_candle_close < prev_candle_close and first_candle_close < prev_candle_close
    squeeze_type := \"down\"
    
    // check previous X candles for trend confirmation?
    if i_squeeze_num_prev_candles_confirmation > 0
        for i = 2 to 2 + i_squeeze_num_prev_candles_confirmation
str.tostring( findHistoryCandle( candle_open_array, tf_bar_index_array, tf_bar_index[0], i ) ) + \" / \" + str.tostring( findHistoryCandle( candle_close_array, tf_bar_index_array, tf_bar_index[0], i ) > findHistoryCandle( candle_open_array, tf_bar_index_array, tf_bar_index[0], i ) ) )
            [ candle_close_price, candle_bar_id ] = findHistoryCandle( candle_close_array, tf_bar_index_array, tf_bar_index[0], i )
            [ candle_open_price, candle_bar_id2 ] = findHistoryCandle( candle_open_array, tf_bar_index_array, tf_bar_index[0], i )
            if candle_close_price > candle_open_price
                squeeze_type := na
                //squeeze_candle_index := 0
                break

// squeeze in swing high
if prev_candle_type == \"down\" and last_candle_type == \"up\" and first_candle_type == \"up\" and last_candle_close > prev_candle_close and first_candle_close > prev_candle_close
    squeeze_type := \"up\"

    // check previous X candles for trend confirmation?
    if i_squeeze_num_prev_candles_confirmation > 0
        for i = 2 to 2 + i_squeeze_num_prev_candles_confirmation
tf_bar_index_array, tf_bar_index[0], i ) ) + \" / \" + str.tostring( findHistoryCandle( candle_close, tf_bar_index_array, tf_bar_index[0], i ) < findHistoryCandle( candle_open, tf_bar_index_array, tf_bar_index[0], i ) ) )
            [ candle_close_price, candle_bar_id ] = findHistoryCandle( candle_close_array, tf_bar_index_array, tf_bar_index[0], i )
            [ candle_open_price, candle_bar_id2 ] = findHistoryCandle( candle_open_array, tf_bar_index_array, tf_bar_index[0], i )
            if candle_close_price < candle_open_price
                squeeze_type := na
                break

plots_offset = math.floor( ResolutionToSec( i_tf ) / ResolutionToSec( timeframe.period ) )

plotshape(not squeeze_plotted and not na(squeeze_type) and squeeze_type == \"down\", color=color.green, title=\"Squeeze Down\", text=\"Squeeze\", style=shape.labelup, size=size.small, textcolor=color.white, offset = -plots_offset, location=location.belowbar)
plotshape(not squeeze_plotted and not na(squeeze_type) and squeeze_type == \"up\", color=color.red, title=\"Squeeze Up\", text=\"Squeeze\", style=shape.labeldown, size=size.small, textcolor=color.white, offset = -plots_offset)

// we only want the first squeeze candle marked
if not na(squeeze_type)
    squeeze_plotted := true

// squeeze detection on current TF when HTF squeeze was found
string squeeze_type_ltf = na
last_candle_type_ltf = close > open ? \"up\" : close < open ? \"down\" : \"\"
last_candle_close_ltf = close
prev_candle_type_ltf = close[1] > open[1] ? \"up\" : close[1] < open[1] ? \"down\" : \"\"
prev_candle_close_ltf = close[1]
first_candle_type_ltf = close[2] > open[2] ? \"up\" : close[2] < open[2] ? \"down\" : \"\"
first_candle_close_ltf = close[2]

if squeeze_plotted or htf_squeeze_found
    htf_squeeze_found := true
    // squeeze in swing low
    if prev_candle_type_ltf == \"up\" and last_candle_type_ltf == \"down\" and first_candle_type_ltf == \"down\" and last_candle_close_ltf < prev_candle_close_ltf and first_candle_close_ltf < prev_candle_close_ltf
        squeeze_type_ltf := \"down\"
    
        // check previous X candles for trend confirmation?
        if i_ltf_squeeze_num_prev_candles_confirmation > 0
            for i = 2 to 2 + i_ltf_squeeze_num_prev_candles_confirmation
                if close[i] > open[i]
                    squeeze_type_ltf := na
    
    // squeeze in swing high
    if prev_candle_type_ltf == \"down\" and last_candle_type_ltf == \"up\" and first_candle_type_ltf == \"up\" and last_candle_close_ltf > prev_candle_close_ltf and first_candle_close_ltf > prev_candle_close_ltf
        squeeze_type_ltf := \"up\"
    
        // check previous X candles for trend confirmation?
        if i_ltf_squeeze_num_prev_candles_confirmation > 0
            for i = 2 to 2 + i_ltf_squeeze_num_prev_candles_confirmation
                if close[i] < open[i]
                    squeeze_type_ltf := na

    // reset this variable, as we\'ll show our LFT squeeze now
    if not na(squeeze_type_ltf)
        htf_squeeze_found := false

plotshape(i_tf != timeframe.period and not na(squeeze_type_ltf) and squeeze_type_ltf == \"down\", color=color.blue, title=\"LTF Squeeze\", text=\"LTF Squeeze Down\", style=shape.labelup, size=size.small, textcolor=color.white, offset = -1, location=location.belowbar)
plotshape(i_tf != timeframe.period and not na(squeeze_type_ltf) and squeeze_type_ltf == \"up\", color=color.maroon, title=\"LTF Squeeze\", text=\"LTF Squeeze Up\", style=shape.labeldown, size=size.small, textcolor=color.white, offset = -1)

// reset if we plotted LTF squeeze and store the squeeze candle properties
if not na(squeeze_type_ltf)
    recorded_squeeze_type := squeeze_type_ltf
    recorded_squeeze_price_level := squeeze_type_ltf == \"down\" ? high[1] : low[1]
    recorded_squeeze_bar_index := tf_bar_index[0]
    squeeze_type_ltf := na
    // reset these 2 if we crossed a recorded squeeze but failed to act on it
    if price_crossed_recorded_squeeze
        price_crossed_recorded_squeeze := false
        price_squeeze_cross_bar_index  := 0

// broker section
trade_type = array.get(order_types, 0)
exit_price = array.get(order_prices, 0)
stop_price = array.get(order_prices, 1)

// close trades when price reaches our target
exit_bool = array.get( our_active_orders_count, 0 ) > 0 and (trade_type == \"Buy\" ? close >= exit_price : close <= exit_price )
if exit_price > 0 and strategy.opentrades > 0 and exit_bool
    strategy.close( trade_type, comment = trade_type + \" TP reached\" )
    array.set(order_prices, 0, 0.0)
    array.set(order_prices, 1, 0.0)
    array.set(order_types, 0, \"\")
    array.set( our_active_orders_count, 0, 0 )
    recorded_squeeze_type          := \"\"
    recorded_squeeze_price_level   := 0.0
    recorded_squeeze_bar_index     := 0
    price_crossed_recorded_squeeze := false
    price_squeeze_cross_bar_index  := 0

// remove trades from internal cache when they reach SL
sl_bool = array.get( our_active_orders_count, 0 ) > 0 and (trade_type == \"Buy\" ? close <= stop_price : close >= stop_price )
if stop_price > 0 and strategy.opentrades > 0 and sl_bool
    array.set(order_prices, 0, 0.0)
    array.set(order_prices, 1, 0.0)
    array.set(order_types, 0, \"\")
    array.set( our_active_orders_count, 0, 0 )
    recorded_squeeze_type          := \"\"
    recorded_squeeze_price_level   := 0.0
    recorded_squeeze_bar_index     := 0
    price_crossed_recorded_squeeze := false
    price_squeeze_cross_bar_index  := 0

// check whether the current price crossed our squeeze price yet
if recorded_squeeze_type != \"\" and price_crossed_recorded_squeeze == false and tf_bar_index[0] != recorded_squeeze_bar_index and ( ( recorded_squeeze_type == \"up\" and close < recorded_squeeze_price_level ) or ( recorded_squeeze_type == \"down\" and close > recorded_squeeze_price_level ) )
    price_crossed_recorded_squeeze := true
    price_squeeze_cross_bar_index := tf_bar_index[0]

label.new(bar_index, high, str.tostring( price_squeeze_cross_bar_index ) )

var debug = table.new(position = position.bottom_right, columns = 1, rows = 1, border_width = 1)

// check whether we\'re not crossing the recorded squeeze price back again
table.cell(table_id = debug, column = 0, row = 0 , text = \"trades: \" + str.tostring( strategy.opentrades ) + \" / rec_sq_t: \" + recorded_squeeze_type + \" / crossed: \" + str.tostring( price_crossed_recorded_squeeze ) + \" / idx: \" + str.tostring( price_squeeze_cross_bar_index ) + \" != \" + str.tostring( tf_bar_index[0] ) + \" / lvl:  \" + str.tostring( recorded_squeeze_price_level ), bgcolor=color.black, text_color=color.white)
if strategy.opentrades == 0 and recorded_squeeze_type != \"\" and price_crossed_recorded_squeeze == true and tf_bar_index[0] != price_squeeze_cross_bar_index and ( ( recorded_squeeze_type == \"up\" and close >= recorded_squeeze_price_level ) or ( recorded_squeeze_type == \"down\" and close <= recorded_squeeze_price_level ) ) and inDateRange and ( ( time - last_trade_ts ) / 1000 >= ( 60 * min_trade_gap_minutes ) )
    // open a trade here
    type = recorded_squeeze_type == \"down\" ? \"Buy\" : \"Sell\"
    strategy.entry( type, type == \"Buy\" ? strategy.long : strategy.short )

    // calculate TP
    TP = 0.0
    if ( type == \"Buy\" )
        TP := close + ( ( TPPerc / 100 ) * close )
    else
        TP := close - ( ( TPPerc / 100 ) * close )

    label.new(bar_index, low - 20, \"trade - \" + type + \" at \" + str.tostring( close ) + \", tp \" + str.tostring( TP ) )

    // calculate SL
    SL = 0.0
    if ( type == \"Buy\" )
        SL := close - ( ( SLPerc / 100 ) * close )
    else
        SL := close + ( ( SLPerc / 100 ) * close )

    label.new(bar_index, low - 40, \"exit - \" + str.tostring( SL ) )
    strategy.exit( type, stop = SL, comment = \"closed by SL\" )

    array.set( order_types, 0, type )
    array.set( our_active_orders_count, 0, 1 )
    array.set( order_prices, 0, TP )
    array.set( order_prices, 1, SL )
    last_trade_ts := time

// update last bar index
tf_last_bar_index := tf_bar_index

// Exit open market position when date range ends
if (not inDateRange)
    strategy.close_all()

    标签: pine-script pinescript-v5


    【解决方案1】:

    首先,为了进行测试,我忽略了 2 个错误行:137,152,只需删除它们即可。 然后nz(low[1]) 忽略/更正了第 222 行,以解决策略定义中的真正问题:default_qty_type = strategy.percent_of_equity。如果您将其保留为默认固定,或增加您的 initial_capital,您的策略将被执行。

    【讨论】:

      猜你喜欢
      • 2021-03-12
      • 1970-01-01
      • 1970-01-01
      • 2011-01-18
      • 2020-08-18
      • 1970-01-01
      • 2023-02-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多