For code/output blocks: Use ``` (aka backtick or grave accent) in a single line before and after the block. See: http://commonmark.org/help/

Set minimum trade time / don't sell until certain amount of time has elapsed



  • I would like to set up a strategy that, after a Buy, will not consider a Sell signal until a certain amount of time has elapsed. A clear use-case for this is intraday strategies that might trigger PDT (Pattern Day Trader) regulations, so we need to hold a ticker at least overnight (if bought anytime on Tuesday, cannot sell until 9:30am EST on Wednesday).

    I'm thinking about keeping track of the trade open time in a custom object in next() then evaluating it during a future next(), but I imagine this could get funky in ways I can't imagine right now, especially if I was trying to use bracket orders as well.

    On that note, another ideal way to think about it would be, when setting up the bracket orders, to be able to se a "not valid before" on the stop loss and take profit, sort of like the opposite of valid_until.

    What would be the most backtrader-y approach to this problem?

    Thanks for your thoughts.


  • administrators

    (time_now - time_market_entry) >= time_delta ?



  • @backtrader said in Set minimum trade time / don't sell until certain amount of time has elapsed:

    (time_now - time_market_entry) >= time_delta ?

    Yeah, that's basically what I've done, but apparently incorrectly.

    Here's what i'm currently doing but it seems to be generating some odd results:

    def __init__(self):
        self.startcash = self.broker.getvalue()
        self.custom_orders = {}
        for i, d in enumerate(self.datas):
    
            # Instantiate order keeper for all your datas
            self.custom_orders[d] = dict()
    
    def next(self)
        '''
        ...
        '''
    
        for index, data in enumerate(self.datas):
            datetime, dataname = self.datetime.date(), data._name
    
            pos = self.getposition(data).size
    
            # If we're not in a position, and we have a long trade signal, place a buy
            if not pos and trade_signal == True:
                self.custom_orders[data]['entry'] = self.buy(
                                    data = data,
                                    exectype = bt.Order.Limit,
                                    price = data.close[0],
                                    transmit = True,
                                    info = {'ticker':dataname, 'price_range':(round(data.low[0], 2), round(data.high[0], 2)), 
                                        'direction':'LONG',  'type':'Limit Entry', 
                                        'SL': stop_loss, 'TP': take_profit, 'datetime': datetime},
                                    )
    
            # If we're already in a position, look for an exit
            if pos:
    
                # Retrieve order info
                entry_order_info = self.custom_orders[data]['entry'].info['info']
    
                # Check if the order was opened a day ago (to avoid PDT)
                if (entry_order_info['datetime'] + pd.Timedelta(days=1)) < datetime:
    
                    if np.any(np.array([data.open[0], data.high[0], data.low[0], data.close[0]]) < entry_order_info['SL']):
                        self.custom_orders[data]['stop_loss'] = self.close(
                                            data = data,
                                            info = {'ticker':dataname, 'price_range':(round(data.low[0], 2), round(data.high[0], 2)), 
                                                'direction':'LONG', 'type':'Stop Loss', 
                                                'setup': 'close long trade SL', 'datetime': datetime},
                                            )
    
                    elif np.any(np.array([data.open[0], data.high[0], data.low[0], data.close[0]]) > entry_order_info['TP']):
                        self.custom_orders[data]['take_profit'] = self.close(
                                            data = data,
                                            info = {'ticker':dataname, 'price_range':(round(data.low[0], 2), round(data.high[0], 2)), 
                                                'direction':'LONG', 'type':'Take Profit', 
                                                'setup': 'close long trade TP', 'datetime': datetime},
                                            )
    

    Weird things:

    1. Some trades are being closed after 1 bar, despite my logic seeming to point to this not being allowed

    2. There are short trades being opened?!

        trade_analyzer = strategy.analyzers.trade_analyzer.get_analysis()
        print("N short trades: {}".format(trade_analyzer.short.total))
        print("N long trades: {}".format(trade_analyzer.long.total))
        print("Average trade length: {}".format(trade_analyzer.len.average))
        print("Max trade length: {}".format(trade_analyzer.len.max))
        print("Min trade length: {}".format(trade_analyzer.len.min))
    
    N short trades: 2                                                                                                                                                                                           
    N long trades: 27                                                                                                                                                                                           
    Average trade length: 20.103448275862068                                                                                                                                                                    
    Max trade length: 33                                                                                                                                                                                        
    Min trade length: 1  
    

    (Timeframe is 1H, and is correctly configured)

    PS: I also tried market orders for the entry, thinking that might be the problem (i.e. limit orders not being executed for a while and then the close logic detecting when the order was placed not executed). Different results, but similar.

    PPS: I'm interested in hearing the correct use of data vs. dataname in my code here, when being used in placing orders, accessing my custom_orders dictionaries inside of next, etc.



  • @tw00000 Any thoughts @backtrader ?? I really appreciate your advice you can give it.

    In particular, I'm most concerned about the fact that it's opening short trades even though I'm not using sell anywhere in my code!


  • administrators

    Your code is a non-working snippet and there are no logs whatsoever. What can you really expect as a diagnostic?

    @tw00000 said in Set minimum trade time / don't sell until certain amount of time has elapsed:

    I'm not using sell anywhere in my code!

    But you use (apparently) close, and you are for sure calling it several times. But in order to find it out, you would like to log to the console or a file, what you are actually doing. But you don't and the presented code is also for sure not the code which is being executed.

    @tw00000 said in Set minimum trade time / don't sell until certain amount of time has elapsed:

    Some trades are being closed after 1 bar, despite my logic seeming to point to this not being allowed

    Which logic? You work with hours but check date (i.e. full days). You are bound to exit on the next day on some occasions. You may also want to actually log what your deadline is and see when you are expected to exit the market.

    I do understand your desire to achieve something very complex and present only something which you think is digestible and will show your problem. But the reality is you present something which has nothing to do with the reality.

    In order to test your "exit" logic, my personal suggestion:

    • Write a simple script with which you test that logic before testing it in a complex script.


  • @backtrader So, it is possible that close could issue a sell order, if there was not a buy order open?


  • administrators

    If you issue it several times in a row before the broker has had a chance to close a position, of course.


Log in to reply
 

});