├── .vs └── InteractiveBrokersPythonBot │ └── v16 │ └── .suo ├── InteractiveBrokersPythonBot.py ├── InteractiveBrokersPythonBot.pyproj ├── InteractiveBrokersPythonBot.sln └── README.md /.vs/InteractiveBrokersPythonBot/v16/.suo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jake0303/InteractiveBrokersPythonBot/082f23f32c6d4564adfa8bd5c050a7737ceadde3/.vs/InteractiveBrokersPythonBot/v16/.suo -------------------------------------------------------------------------------- /InteractiveBrokersPythonBot.py: -------------------------------------------------------------------------------- 1 | #Imports 2 | import ibapi 3 | from ibapi.client import EClient 4 | from ibapi.wrapper import EWrapper 5 | from ibapi.contract import Contract 6 | from ibapi.order import * 7 | import ta 8 | import numpy as np 9 | import pandas as pd 10 | import pytz 11 | import math 12 | from datetime import datetime, timedelta 13 | import threading 14 | import time 15 | #Vars 16 | orderId = 1 17 | #Class for Interactive Brokers Connection 18 | class IBApi(EWrapper,EClient): 19 | def __init__(self): 20 | EClient.__init__(self, self) 21 | # Historical Backtest Data 22 | def historicalData(self, reqId, bar): 23 | try: 24 | bot.on_bar_update(reqId,bar,False) 25 | except Exception as e: 26 | print(e) 27 | # On Realtime Bar after historical data finishes 28 | def historicalDataUpdate(self, reqId, bar): 29 | try: 30 | bot.on_bar_update(reqId,bar,True) 31 | except Exception as e: 32 | print(e) 33 | # On Historical Data End 34 | def historicalDataEnd(self, reqId, start, end): 35 | print(reqId) 36 | # Get next order id we can use 37 | def nextValidId(self, nextorderId): 38 | global orderId 39 | orderId = nextorderId 40 | # Listen for realtime bars 41 | def realtimeBar(self, reqId, time, open_, high, low, close,volume, wap, count): 42 | super().realtimeBar(reqId, time, open_, high, low, close, volume, wap, count) 43 | try: 44 | bot.on_bar_update(reqId, time, open_, high, low, close, volume, wap, count) 45 | except Exception as e: 46 | print(e) 47 | def error(self, id, errorCode, errorMsg): 48 | print(errorCode) 49 | print(errorMsg) 50 | #Bar Object 51 | class Bar: 52 | open = 0 53 | low = 0 54 | high = 0 55 | close = 0 56 | volume = 0 57 | date = datetime.now() 58 | def __init__(self): 59 | self.open = 0 60 | self.low = 0 61 | self.high = 0 62 | self.close = 0 63 | self.volume = 0 64 | self.date = datetime.now() 65 | #Bot Logic 66 | class Bot: 67 | ib = None 68 | barsize = 1 69 | currentBar = Bar() 70 | bars = [] 71 | reqId = 1 72 | global orderId 73 | smaPeriod = 50 74 | symbol = "" 75 | initialbartime = datetime.now().astimezone(pytz.timezone("America/New_York")) 76 | def __init__(self): 77 | #Connect to IB on init 78 | self.ib = IBApi() 79 | self.ib.connect("127.0.0.1", 7496,1) 80 | ib_thread = threading.Thread(target=self.run_loop, daemon=True) 81 | ib_thread.start() 82 | time.sleep(1) 83 | currentBar = Bar() 84 | #Get symbol info 85 | self.symbol = input("Enter the symbol you want to trade : ") 86 | #Get bar size 87 | self.barsize = int(input("Enter the barsize you want to trade in minutes : ")) 88 | mintext = " min" 89 | if (int(self.barsize) > 1): 90 | mintext = " mins" 91 | queryTime = (datetime.now().astimezone(pytz.timezone("America/New_York"))-timedelta(days=1)).replace(hour=16,minute=0,second=0,microsecond=0).strftime("%Y%m%d %H:%M:%S") 92 | #Create our IB Contract Object 93 | contract = Contract() 94 | contract.symbol = self.symbol.upper() 95 | contract.secType = "STK" 96 | contract.exchange = "SMART" 97 | contract.currency = "USD" 98 | self.ib.reqIds(-1) 99 | # Request Market Data 100 | #self.ib.reqRealTimeBars(0, contract, 5, "TRADES", 1, []) 101 | self.ib.reqHistoricalData(self.reqId,contract,"","2 D",str(self.barsize)+mintext,"TRADES",1,1,True,[]) 102 | #Listen to socket in seperate thread 103 | def run_loop(self): 104 | self.ib.run() 105 | #Bracet Order Setup 106 | def bracketOrder(self, parentOrderId, action, quantity, profitTarget, stopLoss): 107 | #Initial Entry 108 | #Create our IB Contract Object 109 | contract = Contract() 110 | contract.symbol = self.symbol.upper() 111 | contract.secType = "STK" 112 | contract.exchange = "SMART" 113 | contract.currency = "USD" 114 | # Create Parent Order / Initial Entry 115 | parent = Order() 116 | parent.orderId = parentOrderId 117 | parent.orderType = "MKT" 118 | parent.action = action 119 | parent.totalQuantity = quantity 120 | parent.transmit = False 121 | # Profit Target 122 | profitTargetOrder = Order() 123 | profitTargetOrder.orderId = parent.orderId+1 124 | profitTargetOrder.orderType = "LMT" 125 | profitTargetOrder.action = "SELL" 126 | profitTargetOrder.totalQuantity = quantity 127 | profitTargetOrder.lmtPrice = round(profitTarget,2) 128 | profitTargetOrder.parentId = parentOrderId 129 | profitTargetOrder.transmit = False 130 | # Stop Loss 131 | stopLossOrder = Order() 132 | stopLossOrder.orderId = parent.orderId+2 133 | stopLossOrder.orderType = "STP" 134 | stopLossOrder.action = "SELL" 135 | stopLossOrder.totalQuantity = quantity 136 | stopLossOrder.parentId = parentOrderId 137 | stopLossOrder.auxPrice = round(stopLoss,2) 138 | stopLossOrder.transmit = True 139 | 140 | bracketOrders = [parent, profitTargetOrder, stopLossOrder] 141 | return bracketOrders 142 | #Pass realtime bar data back to our bot object 143 | def on_bar_update(self, reqId, bar,realtime): 144 | global orderId 145 | #Historical Data to catch up 146 | if (realtime == False): 147 | self.bars.append(bar) 148 | else: 149 | bartime = datetime.strptime(bar.date,"%Y%m%d %H:%M:%S").astimezone(pytz.timezone("America/New_York")) 150 | minutes_diff = (bartime-self.initialbartime).total_seconds() / 60.0 151 | self.currentBar.date = bartime 152 | lastBar = self.bars[len(self.bars)-1] 153 | #On Bar Close 154 | if (minutes_diff > 0 and math.floor(minutes_diff) % self.barsize == 0): 155 | self.initialbartime = bartime 156 | #Entry - If we have a higher high, a higher low and we cross the 50 SMA Buy 157 | #1.) SMA 158 | closes = [] 159 | for bar in self.bars: 160 | closes.append(bar.close) 161 | self.close_array = pd.Series(np.asarray(closes)) 162 | self.sma = ta.trend.sma(self.close_array,self.smaPeriod,True) 163 | print("SMA : " + str(self.sma[len(self.sma)-1])) 164 | #2.) Calculate Higher Highs and Lows 165 | lastLow = self.bars[len(self.bars)-1].low 166 | lastHigh = self.bars[len(self.bars)-1].high 167 | lastClose = self.bars[len(self.bars)-1].close 168 | 169 | # Check Criteria 170 | if (bar.close > lastHigh 171 | and self.currentBar.low > lastLow 172 | and bar.close > str(self.sma[len(self.sma)-1]) 173 | and lastClose < str(self.sma[len(self.sma)-2])): 174 | #Bracket Order 2% Profit Target 1% Stop Loss 175 | profitTarget = bar.close*1.02 176 | stopLoss = bar.close*0.99 177 | quantity = 1 178 | bracket = self.bracketOrder(orderId,"BUY",quantity, profitTarget, stopLoss) 179 | contract = Contract() 180 | contract.symbol = self.symbol.upper() 181 | contract.secType = "STK" 182 | contract.exchange = "SMART" 183 | contract.currency = "USD" 184 | #Place Bracket Order 185 | for o in bracket: 186 | o.ocaGroup = "OCA_"+str(orderId) 187 | self.ib.placeOrder(o.orderId,contract,o) 188 | orderId += 3 189 | #Bar closed append 190 | self.currentBar.close = bar.close 191 | print("New bar!") 192 | self.bars.append(self.currentBar) 193 | self.currentBar = Bar() 194 | self.currentBar.open = bar.open 195 | #Build realtime bar 196 | if (self.currentBar.open == 0): 197 | self.currentBar.open = bar.open 198 | if (self.currentBar.high == 0 or bar.high > self.currentBar.high): 199 | self.currentBar.high = bar.high 200 | if (self.currentBar.low == 0 or bar.low < self.currentBar.low): 201 | self.currentBar.low = bar.low 202 | 203 | #Start Bot 204 | bot = Bot() -------------------------------------------------------------------------------- /InteractiveBrokersPythonBot.pyproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | Debug 4 | 2.0 5 | 4786e9ef-3047-46a2-bae7-943ad2f0cba0 6 | . 7 | InteractiveBrokersPythonBot.py 8 | 9 | 10 | . 11 | . 12 | InteractiveBrokersPythonBot 13 | InteractiveBrokersPythonBot 14 | 15 | 16 | true 17 | false 18 | 19 | 20 | true 21 | false 22 | 23 | 24 | 25 | 26 | 27 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /InteractiveBrokersPythonBot.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30711.63 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{888888A0-9F3D-457C-B088-3A5042F75D52}") = "InteractiveBrokersPythonBot", "InteractiveBrokersPythonBot.pyproj", "{4786E9EF-3047-46A2-BAE7-943AD2F0CBA0}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {4786E9EF-3047-46A2-BAE7-943AD2F0CBA0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {4786E9EF-3047-46A2-BAE7-943AD2F0CBA0}.Release|Any CPU.ActiveCfg = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | GlobalSection(ExtensibilityGlobals) = postSolution 21 | SolutionGuid = {1EAC8935-1C45-4D2F-A399-208530FA083B} 22 | EndGlobalSection 23 | EndGlobal 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # A Simple Interactive Brokers Python Bot Youtube : https://www.youtube.com/watch?v=XKbk8SY9LD0 2 | --------------------------------------------------------------------------------