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

notify_store : Create Events when Connection Failed



  • WORKING
    I have setup notify_store to clear stop orders when I manually close a position using the brokers platform. This works.

    NOT WORKING
    I want to send close positions and open orders when a connection has failed. I often found that the system continues to send orders after a time out even through BT has stopped. This can result in accumulated positions.

    When either a 'Connection Failed' or 'Timed Out' is received by notify_store, I'd like to run through the process shown below:

    • read my *.ini file to find position size prior to connection issue
    • send a close order
    • send a cancel stop loss
    • write to *.ini file to signal connection failed
    • runstop

    I've test the sequence above by placing it under if 'external transaction MARKET_ORDER' in msg: and it works. It reads ini file, closes positions, writes ini file and then reloads cerebro as a subprocess in the parent program. However, when it is placed in if 'V20ConnectionError' in msg: or if 'timed out' in msg: I receive the following error:

    if 'external transaction MARKET_ORDER' in msg:
    TypeError: argument of type 'V20ConnectionError' is not iterable
    

    Is this not possible, or does it need to be used as a callback (which I'm not familiar using)?

    Appreciate any thoughts you have.

    NOTIFY_STORE CODE:

    def notify_store(self, msg, *args, **kwargs):
    
        print('*' * 5, 'STORE NOTIF:', msg)
    
        ### IF MANUAL CLOSE TRADE VIA PLATFORM, THEN CANCEL STOP LOSS --- THIS WORKS
        
        if 'external transaction MARKET_ORDER' in msg:
            print('msg = external transaction')
    
            try:
                cancel = self.cancel(self.stop_ord) #CANCEL STOP LOSS
                print('CANCEL STOP LOSS')
                return
                
            except AttributeError:
                print('NO STOP LOSS TO CANCEL')
                return
                
            else:
                print('NOT SURE IF STOP LOSS CURRENTLY OPEN')
                return
    
    
        ### CONNECTION FAILED --- THIS DOES NOT WORK
        
        if 'V20ConnectionError' in msg:
        
            print('CONNECTION FAILED')
            
            #READ INI FILE TO GET POSTION SIZE
            bt_file.read_trade_ini(self)
            
            print('TRY TO CLOSE POSITION')
            self.close(size=self.position_size)
            print('POSITION CLOSED. TRY TO CANCEL STOP LOSS')
            self.cancel(self.stop_ord)
            print('CANCEL STOP LOSS')
    
            bt_file.reload_write(self)    #CREATE SHUTDOWN & RELOAD TRIGGER IN INI FILE
            
            print('STOPPING BACKTRADER')
            self.env.runstop()
            press('enter')
            return
            
            
            
        if 'timed out' in msg: ### TIMED OUT --- THIS DOES NOT WORK
        
            print('TIMED OUT')
            
            #READ INI FILE TO GET POSTION SIZE
            bt_file.read_trade_ini(self)
            
            print('TRY TO CLOSE POSITION')
            self.close(size=self.position_size)
            print('POSITION CLOSED. TRY TO CANCEL STOP LOSS')
            self.cancel(self.stop_ord)
            print('CANCEL STOP LOSS')
        
            bt_file.reload_write(self)    #CREATE SHUTDOWN & RELOAD TRIGGER IN INI FILE
            print('STOPPING BACKTRADER')
            self.env.runstop()
            press('enter')
            return
    
    


  • SOLVED

    Never underestimate the power of perseverance.


    The following is my modified notify_store(). This is tested with OANDA.

    What it does:

    • If a manual trade occurs via the broker platform with 'external transaction MARKET_ORDER' then try to cancel stop_loss if one exists.

    • All other notify_store errors:

      • Try to send sms alert (using Twillio account) with error to my mobile
      • Get position size from my *ini file (Note: on each cycle through next() I store critical system/trade data in an *.ini file). Position is queried from *.ini instead of broker because connection may not allow getting position from broker
      • Try close order with position size
      • Try cancel stop loss
      • Write SHUTDOWN signal to *ini file to let parent program know BT has failed
      • Stop BT
    • The parent program will see that BT (as a subprocess) has failed and shut down. It will kill the BT subprocess and reload it.

    • BT reloads and during __init__ looks to see if there is already existing system/trade data in the *.ini file. If True then the old system/trade data is reloaded, otherwise a fresh start is required.

    import backtrader as bt
    import signal
    from keyboard import press
    from actions.sms_send import SendSMS
    from ini.ini_reader import bt_file
    
    def notify_store(self, msg, *args, **kwargs):
    
        print('*' * 5, 'STORE NOTIF:', msg)
    
        
        if 'external transaction MARKET_ORDER' in msg:
            print('msg = external transaction')
    
            try:
                cancel = self.cancel(self.stop_ord) #CANCEL STOP LOSS
                print('CANCEL STOP LOSS')
                return
                
            except AttributeError:
                print('NO STOP LOSS TO CANCEL')
            returnsdg
                
            else:
            
                print('NOT SURE IF STOP LOSS CURRENTLY OPEN')
                message = SendSMS.client.messages.create(
                    from_='+xxxxxxxxxx',
                    to='+xxxxxxxxxx',
                    body=('FAILED TO CANCEL STOP LOSS: CHECK ON PLATFORM'))
                return
                
        else:
            print('CONNECTION FAILED')
            
            print('SEND SMS')
            try:
                message = SendSMS.client.messages.create(
                    from_='+xxxxxxxxxx',
                    to='+xxxxxxxxxx',
                    body=('SHUT DOWN: CLOSING POSITIONS & RELOADING: {}'.format(msg)))
            except:
                pass
            print('SMS SENT')
            
            print('GET POSITION SIZE FROM INI FILE')
            time.sleep(2)
            #READ INI TO GET POSTION SIZE. CANNOT GET POSITION SIZE FROM BROKER IF CONNECTION INTERUPTED
            bt_file.read_trade_ini(self)
            time.sleep(2)
            print('INI FILE READ')
            print('POSITION SIZE: ' + str(self.position_size)) #self.position_size IS READ FROM THE INI FILE AND GETS UPDATED ON EACH next()
           
    
            print('TRY TO CLOSE POSITION')
            time.sleep(2)
            try:
               self.close(size=self.position_size) #SEND A CLOSE ORDER. THIS WILL WORK IF API CONNECTION RE-ESTABLISHED, EVEN IF BT HAS STALLED
            except:
                pass
            time.sleep(2)
            print('POSITION CLOSED. TRY TO CANCEL STOP LOSS')
            try:
                self.cancel(self.stop_ord) #SEND A CANCEL STOP LOSS ORDER. THIS WILL WORK IF API CONNECTION RE-ESTABLISHED, EVEN IF BT HAS STALLED
            except:
                pass
            print('CANCEL STOP LOSS')
    
        
            time.sleep(2)
            bt_file.reload_write(self)    #CREATE SHUTDOWN/RELOAD TRIGGER IN INI FILE FOR PARRENT PROGRAM TO RECEIVE
            time.sleep(2)
            print('STOPPING BACKTRADER')
            self.env.runstop()  #SHUT DOWN BACKTRADER
            press('enter')
            return #EXIT BACKTRADER
    
    

    What other ideas have people used to deal with connection failures?


Log in to reply
 

});