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

Live Trading / Ibbroker / Load Trades at start



  • Hi,

    I use Backtrader in live mode with IB.

    Each time cerebro start, the trades are not initialized. So when the strategy place an order a new trade will be open.

    Is there a way to initialized the trades with the position already open ?

    Thanks for the help.

    Alexandre



  • By default bt works only with positions open by itself. You can search for discussions on this topic on the forum, maybe somebody already implemented this.



  • My goal is to load the positions open by backtrader in a previous run/session.
    The previous positions are also opened by bt.
    But the previous trades are not recognized by bt as "bt position".

    Thanks for the help,



  • @Alexandre-Durand

    I have a system that provides some functionality that you are after by storing all critical variables, trade data, account data in an *.ini file which is updated on each loop of next(). While this is not exactly what you might be after, it may overcome your problem until a better solution can be found.

    How my system works on initial start:

    • Parent program
      • Creates *.ini file
      • Runs BT as subprocess
      • BT starts normally

    When connection fails

    • notify_store receives error
    • wait for connection to be restored (but BT does not resume)
      • send sms alerting me of restart
      • try send close position and try cancel stop loss (if any are open). API still receives these commands even when BT cannot resume.
      • runstop BT
    • write variable to ini file signalling shutdown (this is for the parent program to read and action)

    When shutdown recognised by parent program

    • kill BT
      -reload BT

    When BT reloads

    • check if fresh start or reload.
      • If reload, then init with variables from last loop of next() prior to shutdown
      • If fresh start, init with normal defaults
      • [Option here to recreate the positions that had to been closed when BT failed so that the strategy can continue depending on how much time and price has moved]

    Here is some sample code:

    NOTIFY_STORE

    def notify_store(self, msg, *args, **kwargs):
    
        print('*' * 5, 'STORE NOTIF:', msg)
        
        try:
            if 'external transaction MARKET_ORDER' in msg:
                print('msg = external transaction')
                
                self.hitstoploss = 0
                
                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')
                    try:
                        message = SendSMS.client.messages.create(
                            from_='+xxxxxxxxxx',
                            to='+xxxxxxxxxx',
                            body=(self.productcode + ' FAILED TO CANCEL STOP LOSS: CHECK ON PLATFORM'))
                    except:
                        pass
                    return
    
        except:
                
            print('CONNECTION FAILED')
            
            print('SEND SMS')
                        
            x = 1
            while True: #IF INTERNET CONNECTION DOWN. WAIT UNTIL ABLE TO SEND SMS BEFORE COMMENCING RELOAD
                try:
                    
                    message = SendSMS.client.messages.create(
                        from_='+xxxxxxxxxx',
                        to='+xxxxxxxxxx',
                        body=('SHUT DOWN: CLOSING POSITIONS & RELOADING'))
    #                        body=(self.productcode + ' SHUT DOWN: CLOSING POSITIONS & RELOADING: {}'.format(msg)))
    
                    print('SMS SENT')
                    break
                except:
                    print('!!! CONNECTION BROKEN !!! - FAILED TO SEND SMS. RETRYING #' + str(x))
                    time.sleep(2)
                    x = x + 1
                    pass
            
            print('GET POSITION SIZE FROM INI FILE')
            #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(10)
            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 TRIGGER IN INI FILE FOR PARENT PROGRAM TO RECEIVE
            time.sleep(2)
            print('STOPPING BACKTRADER')
            self.env.runstop()  #SHUT DOWN BACKTRADER
            time.sleep(1)
            press('enter')  #MUST KEEP CURSOR ACTIVE ON THE TERMINAL FOR THIS TO WORK
            return
    

    PARENT PROGRAM

    
    ***FRESH START***
    
        #----- ESTABLISH INI FILE -----#
    
        config = configparser.ConfigParser()
        home = os.path.expanduser('~') #USER DIRECTORY
        filename = pc + '.ini'
        
        if not os.path.exists(home + '/00_config/' + filename):
            print('CREATING NEW INI FILE')
            f = open(home + '/00_config/' + filename, 'w')
        else:
            print('EXISTING INI FILE')
            pass
        
        myfile = Path(home + '/00_config/' + filename)
        
        config.read(myfile)
        section_00 = pc
        section_01 = pc + '-01'
        section_02 = pc + '-02'
        
        time.sleep(1)
        
        #----- CLEAR INI FILE -----#
        print('PREPARING INI FILE')
        with open(myfile,'r+') as s:
            config.read_file(s)
            config.remove_section(section_00)
            config.remove_section(section_01)
            config.remove_section(section_02)
            s.seek(0)
            config.write(s)
            s.truncate()
            
        time.sleep(1)
        #----- CREATE RELOAD SECTIONS IF THEY DO NOT EXIST -----#
        try:
            config.get(section_01, 'override')
        except:
    #    except configparser.NoSectionError:
            config.add_section(section_01)   #ADD NEW SECTION
        
        #CREATE ACCOUNT SECTION IF IT DOES NOT EXIST
        try:
            config.get(section_02, 'account')
        except:
    #    except configparser.NoSectionError:
            config.add_section(section_02)
            
        #CREATE TRADE DATA SECTION IF IT DOES NOT EXIST
        try:
            config.get(pc, 'tradeid')
        except:
    #    except configparser.NoSectionError:
            config.add_section(pc)
        
        #----- RELOAD DEFAULT VALUES -----#
        config.set(section_01, 'override','0')
        config.set(section_01, 'reload','0')
        config.set(section_02, 'account','0')
        config.write(myfile.open('w'))
    
      
        #----- LOAD CEREBRO -----#
        cerebro(pc) #LOADS BT ('pc' refers to product code that is passed to BT from the parent)
    
    ***LOOP CHECKS ON INI FILE***
    
        while True:
    
    #----- CONNECTION FAILURE - RELOAD -----#
    
            config.read(myfile)
            reload_sc = config.get(section_01,'reload')
    
            if reload_sc == 'SHUTDOWN': #IF INI FILE SAYS 'SHUTDOWN' (WHICH IS SET BY NOTIFY_STORE), THEN...
            
                print('KILL CEREBRO')
                #use to have a kill.subprocess command in here but it seemed redundant but might be useful if running multiple instances on one machine
                time.sleep(1)
                print('RELOAD CEREBRO')
                time.sleep(2)
                cerebro(pc)
    
            else:
                pass
    
    

    BT

    ***FRESH START***
    
    def __init__():
    
            ini_transfer.reload_read(self) #Loads ini file
    
            if self.reload_sc == 'SHUTDOWN': #If reloaded set as'SHUTDOWN' then init with last values, not default
                ini_transfer.read_restart_data(self) 
            else:
                vars(self) #This is just a method contain a group of variables
    
    

    SAMPLE CODE FROM INI_TRANSFER

        def read_restart_data(self):
            args = parse_args()
            config = configparser.ConfigParser()
            home = os.path.expanduser('~')
            myfile = Path(home + '/00_config/' + args.data0 + '.ini')
            config.read(myfile) #path of your .ini file
            
            self.tradeid = config.get(args.data0,'tradeid')
            self.position_size = float(config.get(args.data0,'position_size'))
            self.freezebar = float(config.get(args.data0,'freezebar'))
            self.enter_price = float(config.get(args.data0,'enter_price'))
            self.retracement = float(config.get(args.data0,'retracement'))
            self.hitstoploss = int(config.get(args.data0,'hitstoploss'))
            self.high_2 = float(config.get(args.data0,'high_2'))
            self.low_2 = float(config.get(args.data0,'low_2'))
            self.high_3 = float(config.get(args.data0,'high_3'))
            self.pos_long = int(config.get(args.data0,'pos_long'))
            self.pos_short = int(config.get(args.data0,'pos_short'))
            self.stop_position = float(config.get(args.data0,'stop_position'))
            self.trend_backflip = float(config.get(args.data0,'trend_backflip'))
            self.trend_exit_trigger = float(config.get(args.data0,'trend_exit_trigger'))
            self.false_signal = float(config.get(args.data0,'false_signal'))
            self.RTH = int(config.get(args.data0,'RTH'))
            self.trend_exit_price = float(config.get(args.data0,'trend_exit_price'))
            self.break_out_long = float(config.get(args.data0,'break_out_long'))
            self.break_out_short = float(config.get(args.data0,'break_out_short'))
    
    

    Perhaps some of this might assist you with new ideas to tackle your problem.

    Also appreciate if anyone has ideas on how to improve or simplify this?

    Not being from a coding background, I am making this up as I go. No doubt there are more efficient ways of achieving some of the things I am doing.


Log in to reply
 

});