Navigation

    Backtrader Community

    • Register
    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    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

    General Code/Help
    1
    2
    248
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • mics
      mics last edited by

      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
      
      
      1 Reply Last reply Reply Quote 0
      • mics
        mics last edited by

        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?

        1 Reply Last reply Reply Quote 0
        • 1 / 1
        • First post
          Last post
        Copyright © 2016, 2017, 2018, 2019, 2020, 2021 NodeBB Forums | Contributors