使用变量计算进行限价和止损输入时,括号订单策略.exit 不起作用

问题描述 投票:0回答:1

我正在尝试在 pine 脚本策略中复制括号订单(入市、限价止盈和限价止损),以通过 pine 脚本启用回溯测试和策略执行。止盈 (Long1_Take_Profit) 和止损 (Long1SL) 的输出变量都成功输出了 TP 和 SL 退出价格,这些价格通过 webhook 传输到我的 IB_Insync 机器人并提交到 TWS 括号订单中。然而,当在strategy.exit中使用这些相同的变量输出来复制括号顺序时,它们不起作用。止盈和止损根本不在 Tradingview 上执行。

只有当我在strategy.exit函数中输入手动限价和止损价格,或者诸如[close * 1.05]之类的计算时,我才能使strategy.exit发挥作用,并且如果我手动输入这些限制,它就会发挥作用价格转换为变量(例如下面的 TP 变量(TP = 17585 + 7)。但是如果我使用strategy.position_avg_price 甚至strategy.position_avg_price + 7(如 2 个示例,它们都在图表上的测试标签中打印正确的输出价格)限价和止损不起作用。

我的策略将止损设置为前 3 个柱线的最低点 [ta.lowest(3)],止盈是止损的比率(例如 1 比 1)。因此 - 止盈价格是根据止损价格计算的 - 并且两个变量计算输出都非常适合在 TWS IB API 机器人中使用。

我花了两天时间阅读并尝试了很多不同的方法来让它发挥作用。我尝试过strategy.order,确保变量对应于它们所需的输出类型(float/int等),甚至四舍五入到mintick。变量计算正确打印到标签并输出到 webhook/TWS - 所以我知道变量计算正在工作,并且我已经尝试了止盈和止损的刻度计算和百分比计算 = 所有这些都不起作用,除非直接输入到策略.退出函数。

我已经一遍又一遍地阅读tradingcode.net、电视文档和Stack Overflow,我似乎完全按照规定进行操作......所以我不明白为什么当我使用时它在V5中不起作用能够在 V3 和 V4 中获得类似的括号排序功能。 Tradingview Strategy.exit 是否无法从变量输出中获取“限制”和“停止”输入? (但是 - 我在 Stackoverflow 上看到其他代码使用此类变量输出作为限制和停止退出参数)。

工作代码在下面 - 我知道那里有很多不必要的代码行 - 这是因为我尝试了所有不同的尝试来解决问题(例如尝试刻度和百分比计算等),并且我将其留在那里。

这很可能是我做错的一件令人尴尬的简单事情——但我现在对此视而不见。 请有人帮助指导我解决这个问题所需的方向。 非常感谢你:-)

//@version=5
strategy("PPO Strat Entry Test",  overlay=true, default_qty_value=1, calc_on_order_fills=false, calc_on_every_tick=true, pyramiding=0)

//==============================================DATE FILTER===========================================================================================================================================

useDateFilter = input.bool(true, title='Filter Date Range of Backtest', group='Backtest Time Period')
backtestStartDate = input.time(title='Date', defval=timestamp('1 Apr 2024'), title='Start Date', group='Backtest Time Period', tooltip='This start date is in the time zone of the exchange ' + 'where the chart\'s instrument trades. It doesn\'t use the time ' + 'zone of the chart or of your computer.')
backtestEndDate = input.time(title='Date', defval=timestamp('30 Apr 2024'), title='End Date', group='Backtest Time Period', tooltip='This end date is in the time zone of the exchange ' + 'where the chart\'s instrument trades. It doesn\'t use the time ' + 'zone of the chart or of your computer.')

inDateRange = not useDateFilter or time >= backtestStartDate and time < backtestEndDate

//________________________________________________________________________________________________________________________________________________________________________
//              EXPONENTIAL MOVING AVERAGE

EMAlength = input.int(20, minval=1)
EMAexp = input(true, 'exponential')

esma(realClose, EMAlength)=>
    s = ta.sma(realClose, EMAlength)
    e = ta.ema(realClose, EMAlength)
    EMAexp ? e : s


//________________________________________________________________________________________________________________________________________________________________________
//              PPO

//PPO Chart Time
fast_length1 = input(title='Fast Length', defval=7, group = 'PPO')
slow_length1 = input(title='Slow Length', defval=21, group = 'PPO')

signal_length = input.int(title='Signal Smoothing', minval=1, maxval=50, defval=5, group = 'PPO')
sma_source = input(title='Simple MA(Oscillator)', defval=true, group = 'PPO')
sma_signal = input(title='Simple MA(Signal Line)', defval=true, group = 'PPO')
PPOsrc = close

// Calculating
fast_ma = sma_source ? ta.sma(PPOsrc, fast_length1) : ta.ema(PPOsrc, fast_length1)
slow_ma = sma_source ? ta.sma(PPOsrc, slow_length1) : ta.ema(PPOsrc, slow_length1)
PPO = ( ((fast_ma - slow_ma) / slow_ma) * 100 )
PPOsig = (sma_signal ? ta.sma(PPO, signal_length) : ta.ema(PPO, signal_length))

//Price Oscillator Chart Time
OSC_shortlen=input.int(7, "Short Length", minval=1, group = 'Price Osc')
OSC_longlen=input.int(21, "Long Length", minval=1, group = 'Price Osc')
OSC_exp = input(true, "exponential", group = 'Price Osc')

OSCshort = esma(PPOsrc, OSC_shortlen)
OSClong = esma(PPOsrc, OSC_longlen)
PPOosc = ( ((OSCshort - OSClong)/OSClong*100) )


Lowest3 = ta.lowest(3)

long1 = ta.crossunder(PPOsig, PPO)

//BRACKET ORDER PRICE CALCULATIONS
var float Long1_Entry_Price = 0.0
Long1_Entry_Price           := strategy.opentrades.entry_price(strategy.opentrades - 1) // strategy.position_avg_price

//Stop Loss
var float Long1SL           = 0.0
Long1SL                     := if strategy.position_size[1] <= 0 and strategy.position_size >= 1
    math.round_to_mintick(Lowest3)

Long1SLticks                = ((Long1_Entry_Price - Long1SL)/syminfo.mintick) //Attempted the use of ticks to see if that would work
var int Long1SL_Ticks       = 0
Long1SL_Ticks               := int(Long1SLticks)

// TAKE PROFIT
var float Long1_Take_Profit = 0.0
Long1_Take_Profit           := (Long1_Entry_Price - Long1SL) + Long1_Entry_Price           //  math.round_to_mintick(strategy.position_avg_price - Long1SL) + strategy.position_avg_price  // ProfitFactor //math.round_to_mintick(Long1_Entry_Price + (syminfo.mintick * 100))
Long1TP_Ticks               = ((Long1_Take_Profit - Long1_Entry_Price)/syminfo.mintick)
Long1TP_pc                  = 1+ (math.round(((Long1_Take_Profit - Long1_Entry_Price)/Long1_Entry_Price)*100, 2)) // Attempted the use of Percentent Take Profit to see if that would work


//TP =  (17585 + 7)
//SL = (17585 - 6)
TP = math.round_to_mintick(strategy.position_avg_price + 7)
SL = math.round_to_mintick(strategy.position_avg_price - 6)

//TEST LABEL showing variable output prices to check calculations are working properly
var label _l_SL = na
var label _l_TP = na

if strategy.position_size[1] <= 0 and strategy.position_size >= 1
    _l_TP := label.new(bar_index, high, str.tostring(Long1_Take_Profit), yloc=yloc.abovebar)
    label.set_textcolor(id=_l_TP, textcolor=color.white)
    label.set_size(_l_TP, size.large)
    label.set_style(_l_TP, label.style_label_left)

    _l_SL := label.new(bar_index, low, str.tostring(Long1SL), yloc=yloc.belowbar)
    label.set_textcolor(id=_l_SL, textcolor=color.white)
    label.set_size(_l_SL, size.large)
    label.set_style(_l_SL, label.style_label_left)


//ORDER EXECUTION
if inDateRange and long1 and barstate.isconfirmed// and strategy.position_size == 0
    strategy.entry('Long', strategy.long, qty = 1, comment = "Long1\nBrkt Entry", oca_name = "Long1") // oca_type = strategy.oca.cancel,
    strategy.exit('Exit Long', from_entry = 'Long',  qty = strategy.position_size, limit = Long1_Take_Profit, stop = Long1SL, oca_name = "Long1_Exit", comment_profit = "Profit Bkt\nClose Long1", comment_loss = "SL Bkt\nClose Long1") 

    //strategy.exit('Exit Long', from_entry = 'Long',  qty = strategy.position_size, limit = 17900, stop = 17700, comment = "Bkt Close\nLong1")
    //strategy.exit('Exit Long', from_entry = 'Long',  qty = strategy.position_size, profit = Long1TP_Ticks, loss = Long1SLticks, comment = "Bkt Close\nLong1")  
    //strategy.exit('Exit Long', from_entry = 'Long',  qty = strategy.position_size, profit = 10, loss = 10, comment = "Bkt Close\nLong1")
pine-script
1个回答
0
投票

经过大量研究并尝试不同的方法 - 我解决了。鉴于没有人回答,我本可以删除这个问题 - 但我决定发布答案,因为我在 Tradercode.net、Pine 脚本手册、堆栈溢出或网络上找不到清晰简洁的答案。

止损变量输出的计算需要在交易条目的相关“If”条件语句中进行,我之前尝试过,但没有成功。然而,变量声明需要位于这些 If 语句之外,而我之前的尝试将它们放在其中。然后,在执行每个“IF”条件语句时,为止损变量声明分配一个新值,因此分配了止损价格根据进入条件并与之相关。

我仍然无法让strategy.exit在Tradingcode.net和Tradingview文档记录的一个strategy.entry“if”语句下工作......它只能作为全局范围的一部分工作。

我的解决方案可能有点黑客,因为我仍然是这一切的菜鸟 - 但至少它现在可以按我的需要工作。我确信有更好的方法 - 但我当然找不到任何地方记录它。

清理后的工作代码如下

//@version=5
strategy("PPO Strat Entry Test",  overlay=true, default_qty_value=1, calc_on_order_fills=false, calc_on_every_tick=true, pyramiding=0)

//==============================================DATE FILTER===========================================================================================================================================

useDateFilter = input.bool(true, title='Filter Date Range of Backtest', group='Backtest Time Period')
backtestStartDate = input.time(title='Date', defval=timestamp('1 Apr 2024'), title='Start Date', group='Backtest Time Period', tooltip='This start date is in the time zone of the exchange ' + 'where the chart\'s instrument trades. It doesn\'t use the time ' + 'zone of the chart or of your computer.')
backtestEndDate = input.time(title='Date', defval=timestamp('30 Apr 2024'), title='End Date', group='Backtest Time Period', tooltip='This end date is in the time zone of the exchange ' + 'where the chart\'s instrument trades. It doesn\'t use the time ' + 'zone of the chart or of your computer.')

inDateRange = not useDateFilter or time >= backtestStartDate and time < backtestEndDate

//________________________________________________________________________________________________________________________________________________________________________
//              EXPONENTIAL MOVING AVERAGE

EMAlength = input.int(20, minval=1)
EMAexp = input(true, 'exponential')

esma(realClose, EMAlength)=>
    s = ta.sma(realClose, EMAlength)
    e = ta.ema(realClose, EMAlength)
    EMAexp ? e : s


//________________________________________________________________________________________________________________________________________________________________________
//              PPO

//PPO Chart Time
fast_length1 = input(title='Fast Length', defval=7, group = 'PPO')
slow_length1 = input(title='Slow Length', defval=21, group = 'PPO')

signal_length = input.int(title='Signal Smoothing', minval=1, maxval=50, defval=5, group = 'PPO')
sma_source = input(title='Simple MA(Oscillator)', defval=true, group = 'PPO')
sma_signal = input(title='Simple MA(Signal Line)', defval=true, group = 'PPO')
PPOsrc = close

// Calculating
fast_ma = sma_source ? ta.sma(PPOsrc, fast_length1) : ta.ema(PPOsrc, fast_length1)
slow_ma = sma_source ? ta.sma(PPOsrc, slow_length1) : ta.ema(PPOsrc, slow_length1)
PPO = ( ((fast_ma - slow_ma) / slow_ma) * 100 )
PPOsig = (sma_signal ? ta.sma(PPO, signal_length) : ta.ema(PPO, signal_length))

//Price Oscillator Chart Time
OSC_shortlen=input.int(7, "Short Length", minval=1, group = 'Price Osc')
OSC_longlen=input.int(21, "Long Length", minval=1, group = 'Price Osc')
OSC_exp = input(true, "exponential", group = 'Price Osc')

OSCshort = esma(PPOsrc, OSC_shortlen)
OSClong = esma(PPOsrc, OSC_longlen)
PPOosc = ( ((OSCshort - OSClong)/OSClong*100) )


Lowest3 = ta.lowest(low, 3)

long1 = ta.crossunder(PPOsig, PPO)

//BRACKET ORDER PRICE CALCULATIONS
var float Long1_Entry_Price = 0.0
var float Long1SL           = 0.0
var float Long1_Take_Profit = 0.0
Long1_Entry_Price   := strategy.position_avg_price
Long1_Take_Profit   := (strategy.position_avg_price - Long1SL) + strategy.position_avg_price

//ORDER EXECUTION
if inDateRange and long1 and barstate.isconfirmed and strategy.position_size == 0
    strategy.entry('Long', strategy.long, qty = 1, comment = "Long1\nBrkt Entry", oca_name = "Long1") // oca_type = strategy.oca.cancel,
    Long1SL             := Lowest3

strategy.exit('Take Profit Long', from_entry = 'Long',  qty = strategy.position_size, limit = Long1_Take_Profit, stop = Long1SL, oca_name = "Long1_Exit", comment_profit = "Profit Bkt\nClose Long1", comment_loss = "SL Bkt\nClose Long1") 

© www.soinside.com 2019 - 2024. All rights reserved.