2

A simple strategy script sends alerts to open and exit trades, that need to switch between long and short when conditions are met.

Problem: Two alerts (e.g. exit short / enter long) are generated one after the other. Enter long fails, as the previous short deal didn't have time to close.

Question: How can I delay script execution by 5-10 seconds?

Have tried Utilities.sleep(10000), but it does not compile.

*I am a complete beginner, and looking for a simple answer. Hope there is one :]

Here the code:

'''
strategy("My Strategy", overlay=true, default_qty_type=strategy.percent_of_equity, default_qty_value=15)

////////////
// Inputs //

length = input(100)
mult   = input(2.0)

message_long_entry  = input("long entry message")
message_long_exit  = input("long exit message")
message_short_entry = input("short entry message")
message_short_exit = input("short exit message")

atrPeriod = input(10, "ATR Length")
factor = input.float(3.0, "Factor", step = 0.01)

[_, direction] = ta.supertrend(factor, atrPeriod)

if ta.change(direction) < 0
    strategy.entry("My Long Entry Id", strategy.long, when = barstate.isconfirmed)
    alert(message_short_exit)
 ///   Utilities.sleep(10000)    <--- Delay needed here
    alert(message_long_entry)

    
if ta.change(direction) > 0
    strategy.entry("My Short Entry Id", strategy.short, when = barstate.isconfirmed)
    alert(message_long_exit)
 ///   Utilities.sleep(10000)    <--- Delay needed here
    alert(message_short_entry)

'''
KarWil
  • 21
  • 2

2 Answers2

0

You can use this example from Pinecoders FAQ

//@version=5
strategy('Strat with time delay', overlay=true)

i_qtyTimeUnits = -input.int(20, 'Quantity', inline='Delay', minval=0, tooltip='Use 0 for no delay')
i_timeUnits = input.string('minutes', '', inline='Delay', options=['seconds', 'minutes', 'hours', 'days', 'months', 'years'])

// ————— Converts current chart timeframe into a float minutes value.
f_tfInMinutes() =>
    _tfInMinutes = timeframe.multiplier * (timeframe.isseconds ? 1. / 60 : timeframe.isminutes ? 1. : timeframe.isdaily ? 60. * 24 : timeframe.isweekly ? 60. * 24 * 7 : timeframe.ismonthly ? 60. * 24 * 30.4375 : na)
    _tfInMinutes

// ————— Calculates a +/- time offset in variable units from the current bar's time or from the current time.
// WARNING:
//      This functions does not solve the challenge of taking into account irregular gaps between bars when calculating time offsets.
//      Optimal behavior occurs when there are no missing bars at the chart resolution between the current bar and the calculated time for the offset.
//      Holidays, no-trade periods or other irregularities causing missing bars will produce unpredictable results.
f_timeFrom(_from, _qty, _units) =>
    // _from  : starting time from where the offset is calculated: "bar" to start from the bar's starting time, "close" to start from the bar's closing time, "now" to start from the current time.
    // _qty   : the +/- qty of _units of offset required. A "series float" can be used but it will be cast to a "series int".
    // _units : string containing one of the seven allowed time units: "chart" (chart's resolution), "seconds", "minutes", "hours", "days", "months", "years".
    // Dependency: f_resInMinutes().
    int _timeFrom = na
    // Remove any "s" letter in the _units argument, so we don't need to compare singular and plural unit names.
    _unit = str.replace_all(_units, 's', '')
    // Determine if we will calculate offset from the bar's time or from current time.
    _t = _from == 'bar' ? time : _from == 'close' ? time_close : timenow
    // Calculate time at offset.
    if _units == 'chart'
        // Offset in chart res multiples.
        _timeFrom := int(_t + f_tfInMinutes() * 60 * 1000 * _qty)
        _timeFrom
    else
        // Add the required _qty of time _units to the _from starting time.
        _year = year(_t) + (_unit == 'year' ? int(_qty) : 0)
        _month = month(_t) + (_unit == 'month' ? int(_qty) : 0)
        _day = dayofmonth(_t) + (_unit == 'day' ? int(_qty) : 0)
        _hour = hour(_t) + (_unit == 'hour' ? int(_qty) : 0)
        _minute = minute(_t) + (_unit == 'minute' ? int(_qty) : 0)
        _second = second(_t) + (_unit == 'econd' ? int(_qty) : 0)
        // Return the resulting time in ms Unix time format.
        _timeFrom := timestamp(_year, _month, _day, _hour, _minute, _second)
        _timeFrom

// Entry conditions.
ma = ta.sma(close, 100)
goLong = close > ma
goShort = close < ma

// Time delay filter
var float lastTradeTime = na
if nz(ta.change(strategy.position_size), time) != 0
    // An order has been executed; save the bar's time.
    lastTradeTime := time
    lastTradeTime
// If user has chosen to do so, wait `i_qtyTimeUnits` `i_timeUnits` between orders
delayElapsed = f_timeFrom('bar', i_qtyTimeUnits, i_timeUnits) >= lastTradeTime

if goLong and delayElapsed
    strategy.entry('Long', strategy.long, comment='Long')
if goShort and delayElapsed
    strategy.entry('Short', strategy.short, comment='Short')

plot(ma, 'MA', goLong ? color.lime : color.red)
plotchar(delayElapsed, 'delayElapsed', '•', location.top, size=size.tiny)


Starr Lucky
  • 1,578
  • 1
  • 7
  • 8
0

What worked for me was just adding a while loop in my webhook side code checking if there is in realtime an active trade. Im using binance so through postman i accessed to GET /fapi/v2/positionRisk which shows you your current positions information which shows like this:

[
    {
        "symbol": "BTCUSDT",
        "positionAmt": "0.000",
        "entryPrice": "0.0",
        "markPrice": "22615.15917559",
        "unRealizedProfit": "0.00000000",
        "liquidationPrice": "0",
        "leverage": "10",
        "maxNotionalValue": "20000000",
        "marginType": "isolated",
        "isolatedMargin": "0.00000000",
        "isAutoAddMargin": "false",
        "positionSide": "BOTH",
        "notional": "0",
        "isolatedWallet": "0",
        "updateTime": 165963
    } ]

so accessing your current positions amount:

check = float(client.futures_position_information(symbol="BTCUSDT")[0]["positionAmt"])

note if you have hedge mode activated you would have to check from both your long or short side positions changing through [0] or [1] depending on which side you need.

now you can just add the loop before any of your entries:

while check != 0:
                check = float(client.futures_position_information(symbol="BTCUSDT")[0]["positionAmt"])

order = client.futures_create_order(symbol=symbol, side=side, type=order_type, quantity=quantity) //this is your entry after loop breaks

this will delay any of your entries with the loop always updating and checking your current position amount until all of your positions are closed which will make it 0, breaking, and then allowing the code to keep going and start a new position in this case

Eralven
  • 11
  • 2
  • This is great, but we can not always control the receiving side if working with external party. – dorien Apr 18 '23 at 13:20