Wednesday, 28 September 2016

IB TWS Trading Platform Python 6

In this tutorial we will request account updates and receive the position size and average price of our position. Create 2 labels and 2 text boxes (entry box)
        #create label for Average Price
        self.label22 = Label(f1, font=myFont, text='Avg Price', width=8 )
        self.label22.grid(row=6, column=3)

        #create label for Position
        self.label23 = Label(f1, font=myFont, text='Position', width=8)
        self.label23.grid(row=7, column=3)

 #create entrybox (textbox) for Average Price
        self.tbAvgPrice = Entry(f1, font=myFont, width=7, textvariable=varAvgPrice)
        self.tbAvgPrice.grid(row=6, column=4)

        #create entrybox (textbox) for Position size
        self.tbPosition = Entry(f1, font=myFont, width=7, textvariable=varPosition)
        self.tbPosition.grid(row=7, column=4)
  Add this to the server_handler function under "updatePortfolio"
            self.position = msg.position
            self.average_price = msg.averageCost
  Add this under the monitor_position function
        # '%.2f' = formats to 2 decimal places
        varAvgPrice.set('%.2f' % self.average_price) 
        varPosition.set(self.position)
add this to the bottom of the onEnter function
        varPosition.set('0')
        varAvgPrice.set('0.00')
  Add this near the bottom with the rest of the StringVar variables
varAvgPrice = StringVar(root, value='0.00') # variable for average price
varPosition = StringVar(root, value='0')  # variable for Position and set default to zero

All of the code up to tutorial 6


# Craig Hammond 2017 www.sharpertradingimage.com
from ib.ext.Contract import Contract
from ib.ext.Order import Order
from ib.opt import Connection, message
from tkinter import *
from tkinter import ttk
import time
from msvcrt import getch


class Application(Frame):

    def __init__(self, master):
        """Initialize the Frame"""
        ttk.Frame.__init__(self, master)

        self.port=7496
        self.client_id = 82 # this can be any number
        self.grid()
        self.create_widgets()
        self.account_code = None
        self.symbol_id, self.symbol = 0, 'AAPL'
        self.order_id = 555
        

    def create_widgets(self):  # Method or function
        """ create the window layout.  """

        myFont = ('Lucida Grande', 12)

        # create connect button widget
        self.btnConnect = ttk.Button(self, text='Connect', command=self.connect_to_tws)
        self.btnConnect.grid(row=0, column=0)
        self.btnDisconnect = ttk.Button(self, text = "Disconnect", command=self.disconnect_it).grid(row=0, column=1, sticky=W)

        #notebook
        n = ttk.Notebook(root, width=550, height=350)
        f1 = ttk.Frame(n)   # first page, which would get widgets gridded into it
        f2 = ttk.Frame(n)   # second page
        n.add(f1, text='One')
        n.add(f2, text='Two')
        n.grid(row=3, column=0, padx=5, pady=5, sticky=W)

        #create listbox
        self.listbox1 = Listbox(f1, font=('Lucida Grande',9), width=7)
        #self.listbox1.bind('', self.OnDoubleClick_listbox)
        self.listbox1.insert(1, 'NFLX')
        self.listbox1.insert(2, 'AAPL')
        self.listbox1.insert(3, 'FB')
        self.listbox1.grid(row=0, rowspan=5, column=0, padx=5)
        
         #create Label Symbol
        self.label4 = Label(f1, font=myFont, text="Symbol").grid(row=0, column =1)

        #create Label Quantity
        self.label5 = Label(f1, font=myFont, text="Quantity").grid(row=0, column =2)
        
        #create Label Limit Price
        self.label6 = Label(f1, font=myFont, text="Limit Price").grid(row=0, column =3)
        
        #create Label Market
        self.label7 = Label(f1, font=myFont, text="Market").grid(row=0, column =4)

        #create combo box for the Symbol 
        self.cbSymbol = ttk.Combobox(f1, font=myFont, width=6, textvariable = varSymbol)
        self.cbSymbol.bind("<Return>", self.cbSymbol_onEnter) #when the enter key is press an event happens
        self.cbSymbol.bind('<<ComboboxSelected>>',self.cbSymbol_onEnter)
        self.cbSymbol['values'] = ('AAPL','FB','NFLX')
        self.cbSymbol.grid(row=1, column =1,sticky = W)

        #create spinbox (numericUpDown) for Limit Price
        self.spinQuantity = Spinbox(f1, font=myFont, increment=100, from_=0, to=10000, width=7,
                                    textvariable=varQuantity).grid(row=1, column=2)

        #create spinbox (numericUpDown) for Limit Price
        self.spinLimitPrice = Spinbox(f1, font=myFont, format='%8.2f', increment=.01, from_=0.0, to=1000.0, width=7,
                                      textvariable=varLimitPrice)
        # when control and up or down arrow are pressed call spenLimitDime()
        #self.spinLimitPrice.bind('', self.spinLimitDime)
        # when Alt and up or down arrow are pressed call spenLimitPenny()
        #self.spinLimitPrice.bind('', self.spinLimitPenny) 
        self.spinLimitPrice.grid(row=1, column=3)
                                       
        #create textbox(Entry box) for the Market
        self.cbMarket = ttk.Combobox(f1, font=myFont, width=7, textvariable=varMarket).grid(row=1, column=4, sticky = W)

        #create Label OrderType ********-3-****
        self.label8 = Label(f1, font=myFont, text="OrderType").grid(row=2, column =1, sticky=W)

        #create Label Visible 
        self.label9 = Label(f1, font=myFont, text="Visible").grid(row=2, column =2)

        #create Label Primary Exchange
        self.labe20 = Label(f1, font=myFont, text="Primary Ex.").grid(row=2, column =3)

        #create Label Time in Force
        self.labe21 = Label(f1, font=myFont, text="TIF").grid(row=2, column =4)

        #create textbox(Entry box) for the Order Type ****4****
        self.cbOrderType = ttk.Combobox(f1, font=myFont, width=6, textvariable=varOrderType)
        self.cbOrderType['values'] = ('LMT','MKT','STP', 'STP LMT', 'TRAIL', 'MOC', 'LOC')
        self.cbOrderType.grid(row=3, column =1,sticky = W)

        #create textbox(Entry box) for the Primary Exchange
        self.tbPrimaryEx = Entry(f1, font=myFont, width=8, textvariable=varPrimaryEx).grid(row=3, column =3,sticky = W)

        #create textbox(Entry box) for the Time in Force
        self.cbTIF = ttk.Combobox(f1, font=myFont, width=7, textvariable=varTIF)
        self.cbTIF['values'] = ('DAY','GTC')
        self.cbTIF.grid(row=3, column =4,sticky = W)

        #create Bid Label
        self.label2 = Label(f1, font=myFont, text="Bid", width=7).grid(row=4, column=2)

        #create Ask Label
        self.label3 = Label(f1, font=myFont, text="Ask", width=7).grid(row=4, column=3)


        #create textbox(Entry box) for the Bid price  
        self.tbBid = Entry(f1, font=myFont, width=7, textvariable = varBid)
        self.tbBid.bind("<Button-1>", self.tbBid_Click)
        self.tbBid.grid(row=5, column =2, sticky=E)
        
        #create textbox(Entry box) for the Ask price  
        self.tbAsk = Entry(f1, font=myFont, width=7, textvariable = varAsk)
        self.tbAsk.bind("<Button-1>", self.tbAsk_Click)
        self.tbAsk.grid(row=5, column=3)

        #create a sell button 
        self.btnSell = Button(f1, font=('',10,'bold'), text="SELL", width=9, bg="red", fg="white", command=self.sell)
        self.btnSell.grid(row=5, column=1, sticky=W)

        #create a buy button 
        self.btnBuy = Button(f1, font=('',10,'bold'), text="BUY", width=9, bg="green", fg="white", command=self.buy)
        self.btnBuy.grid(row=5, column=4, sticky=E)

        #create Label
        self.label1 = Label(f1, font=myFont, width=8, text="Last").grid(row=6, column =1)

        #create textbox(Entry box) for the last price 
        self.tbLast = Entry(f1, font=myFont, width=8, textvariable = varLast)
        self.tbLast.bind("<Button-1>", self.tbLast_Click)
        self.tbLast.grid(row=6, column =2,sticky = W)

        # create button for cancel all
        self.btnCancelAll = Button(f1, font= ('', 10), text= 'Cancel All',
                                   width=8, bg="blue", fg="white", command=self.cancel_all)
        self.btnCancelAll.grid(row=7, column=2)

        
        #create label for Average Price
        self.label22 = Label(f1, font=myFont, text='Avg Price', width=8 )
        self.label22.grid(row=6, column=3)

        #create label for Position
        self.label23 = Label(f1, font=myFont, text='Position', width=8)
        self.label23.grid(row=7, column=3)

        #create entrybox (textbox) for Average Price
        self.tbAvgPrice = Entry(f1, font=myFont, width=7, textvariable=varAvgPrice)
        self.tbAvgPrice.grid(row=6, column=4)

        #create entrybox (textbox) for Position size
        self.tbPosition = Entry(f1, font=myFont, width=7, textvariable=varPosition)
        self.tbPosition.grid(row=7, column=4)

            

    def tbBid_Click(self, event):
        LimitPrice = varBid.get()
        varLimitPrice.set(LimitPrice)

    def tbAsk_Click(self, event):
        LimitPrice = varAsk.get()
        varLimitPrice.set(LimitPrice)    

    def tbLast_Click(self, event):
        LimitPrice = varLast.get()
        varLimitPrice.set(LimitPrice)
        
    def cancel_all(self):
            self.tws_conn.reqGlobalCancel()   

    def connect_to_tws(self):
        self.tws_conn = Connection.create(port=self.port,
                                          clientId=self.client_id)
        self.tws_conn.connect()
        self.register_callback_functions()
        
    def disconnect_it(self):
        self.tws_conn.disconnect()

    def buy(self):
        self.symbol = varSymbol.get()  # gets the symbol string from the symbol combo box
        self.quantity = varQuantity.get()  # gets the share size from the quantity spinbox
        self.order_type = varOrderType.get()  # gets the order type for the order type combobox
        self.limit_price = varLimitPrice.get()  # gets the limit price from the limit price spinbox
        # calls the function place_market order passes variables
        # symbol, quantity, order type, buy or sell represeted by true or false, and limit price
        self.place_market_order(self.symbol, self.quantity, self.order_type, True, self.limit_price)
    def sell(self):
        self.symbol = varSymbol.get()
        self.quantity = varQuantity.get()
        self.order_type = varOrderType.get()
        self.limit_price = varLimitPrice.get()
        self.place_market_order(self.symbol, self.quantity, self.order_type, False, self.limit_price)

    # Place order  ********************************************************************************place order
    def place_market_order(self, symbol, quantity, order_type, is_buy, limit_price):
        print (symbol, quantity, order_type, is_buy, limit_price)
        contract = self.create_contract(symbol,
                                        'STK',
                                        'SMART',
                                        'NASDAQ',
                                        'USD')
        # tests if is buy or sell
        buysell = 'BUY' if is_buy else 'SELL'
        order = self.create_order(order_type, quantity, buysell, limit_price)
        self.tws_conn.placeOrder(self.order_id, contract, order)
        # increses the order id by one
        self.order_id += 1
    
    def cbSymbol_onEnter(self, event):
        # cancels Account updates
        self.tws_conn.reqAccountUpdates(False, self.account_code)
        # changes characters to upper case
        varSymbol.set(varSymbol.get().upper())
        # gets the value of the text from the combobox. cbSymbol
        # and adds it to the variable mytext
        mytext = varSymbol.get()
        # gets list of values from dropdwn list of
        # cbSymbol combobox
        vals = self.cbSymbol.cget('values')
        # selects all in the combobox. cbSymbol
        self.cbSymbol.select_range(0, END)
        # checks of symbol exists in the combobox if not it adds it
        # to the dropdown list
        if not vals:
            self.cbSymbol.configure(values = (mytext, ))
        elif mytext not in vals: 
            self.cbSymbol.configure(values = vals + (mytext, ))
        mySymbol = varSymbol.get()
        self.symbol = mySymbol
       
        # calls the cancel_market_data() method   
        self.cancel_market_data()
        # calls the method to request streaming data
        self.request_market_data(self.symbol_id, self.symbol)
        # calls method to request account updates
        self.request_account_updates(self.account_code)
        # sets bid and ask price to zero
        varBid.set('0.00')
        varAsk.set('0.00')
        varPosition.set('0')
        varAvgPrice.set('0.00')
               
    def request_account_updates(self, account_code):  
        self.tws_conn.reqAccountUpdates(True, self.account_code)
    def cancel_market_data(self):
        self.tws_conn.cancelMktData(self.symbol_id)
    
    def request_market_data(self, symbol_id, symbol): 
        contract = self.create_contract(symbol,
                                        'STK',
                                        'SMART',
                                        'NASDAQ',
                                        'USD')
        self.tws_conn.reqMktData(symbol_id, contract, '', False)
           
 
    def tick_event(self, msg):
        if msg.tickerId == 0: 
            if msg.field == 1: # 1 is for the bid price
                self.bid_price = msg.price
            elif msg.field == 2:  # 2 is for the ask price
                self.ask_price = msg.price
            elif msg.field == 4:  # 4 represents the last price
                self.last_prices = msg.price
            self.monitor_position(msg)

    def create_contract(self, symbol, sec_type, exch, prim_exch, curr):
        contract = Contract()
        contract.m_symbol = symbol
        contract.m_secType = sec_type
        contract.m_exchange = exch
        contract.m_primaryExch = prim_exch
        contract.m_currency = curr
        return contract

    def create_order(self, order_type, quantity, action, limit_price):  
        order = Order()
        order.m_orderType = order_type
        order.m_totalQuantity = quantity
        order.m_action = action
        order.m_lmtPrice = limit_price
        return order

    def register_callback_functions(self):
        # Assign server messages handling function.
        self.tws_conn.registerAll(self.server_handler)

        # Assign error handling function.
        self.tws_conn.register(self.error_handler, 'Error')

        # Register market data events.
        self.tws_conn.register(self.tick_event,
                               message.tickPrice,
                               message.tickSize)

    def server_handler(self, msg):
        if msg.typeName == "nextValidId":
            self.order_id = msg.orderId  
        elif msg.typeName == "managedAccounts":
            self.account_code = msg.accountsList
        elif msg.typeName == "updatePortfolio" \
                and msg.contract.m_symbol == self.symbol \
                and msg.contract.m_secType == 'STK':
            self.unrealized_pnl = msg.unrealizedPNL
            self.realized_pnl = msg.realizedPNL
            self.position = msg.position
            self.average_price = msg.averageCost
        elif msg.typeName == "error" and msg.id != -1:
            return
        
    def error_handler(self, msg):
        if msg.typeName == 'error'and msg.id != -1:
            print ('Server Error:', msg)

    def monitor_position(self, msg): #*
        print ('Last Price = %s' % (self.last_prices))
        varLast.set(self.last_prices)
        varBid.set(self.bid_price)
        varAsk.set(self.ask_price)
        # '%.2f' = formats to 2 decimal places
        varAvgPrice.set('%.2f' % self.average_price) 
        varPosition.set(self.position)
        

root = Tk()
root.title("Connect to IB TWS with Python")
root.geometry('600x480')
root.attributes('-topmost', True)
varSymbol = StringVar(root, value='NFLX')
varQuantity = StringVar(root, value='100')
varLimitPrice = StringVar()
varMarket = StringVar(root, value='SMART')
varOrderType = StringVar(root, value='LMT')
varPrimaryEx = StringVar(root, value='NASDAQ')
varTIF = StringVar(root, value='DAY')
varLast = StringVar()
varBid = StringVar()
varAsk = StringVar()
varAvgPrice = StringVar(root, value='0.00') 
varPosition = StringVar(root, value='0')

app = Application(root)

root.mainloop()



Pages: 1 2 3 4 5 6 7 8 9


Save Save Save Save Save Save Save Save Save Save Save Save Save Save

No comments:

Post a Comment