I built a trading bot for Interactive Brokers using there API. However, I can neither get it to return “TOP-PER_GAIN” nor AvailableCash from my account.
Can any of you tell where I am going wrong? Here is the relevant piece of code.
from ib_insync import *
from ib_insync import IB, Stock, MarketOrder
import threading
import time
import datetime
import asyncio
from ibapi.wrapper import *
from ibapi.contract import Contract
class IBapi(Wrapper, Client):
def __init__(self):
EClient.__init__(self, self)
# Listen for real time bars
def realtimeBar(self, reqId, time, open_, high, low, close, volume, wap, count):
super().realtimeBar(reqId, time, open_, high, low, close, volume, wap, count)
try:
bot.on_bar_update(reqId, time, open_, high, low, close, volume, wap, count)
except Exception as e:
print(e)
def error(self, id, errorCode, errorMsg):
print(f"Error: {errorCode}, {errorMsg}")
class bot:
def __init__(self, account_id):
self.account_id = account_id
# Connect to IB on init
self.ib = IB()
self.ib_thread = threading.Thread(target=self.run_loop, daemon=True)
self.ib_thread.start()
time.sleep(1)
self.connect_ib()
# Request symbols from the scanner
self.symbols = self.search_stocks()
if not self.symbols:
print("No symbols found from scanner.")
return
# IB Contract Object
self.contract = Contract()
self.contract.secType = "STK"
self.contract.exchange = "SMART"
self.contract.currency = "USD"
self.contract.symbol = symbol
# Request Market Data
self.ib.reqRealTimeBars(0, self.contract, 5, "TRADES", 1, [])
print("Market data requested")
def connect_ib(self):
self.ib.connect('127.0.0.1', 7496, clientId=1) # Adjust the port if needed
print("Connection successful")
def run_loop(self):
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
self.ib.run()
# Pass real time bar data back to the bot object
def on_bar_update(self, reqId, time, open_, high, low, close, volume, wap, count):
print(f"Close price: {close}")
def filter_by_price_change(self, symbols):
filtered_symbols = []
for symbol in symbols:
contract = Stock(symbol, 'SMART', 'USD')
self.ib.qualifyContracts(contract)
ticker = self.ib.reqMktData(contract)
self.ib.sleep(1) # Wait for data to be fetched
if ticker.close and ticker.previousClose:
price_change = ((ticker.close - ticker.previousClose) / ticker.previousClose) * 100
if price_change >= 5:
filtered_symbols.append(symbol)
self.ib.cancelMktData(contract)
return filtered_symbols
def search_stocks(self):
# Define the scanner subscription criteria
scanner = ScannerSubscription(
instrument='STK',
locationCode='STK.US.MAJOR',
scanCode='TOP_PERC_GAIN',
abovePrice=1,
aboveVolume=50000
)
# Request the scanner data
scanDataList = self.ib.reqScannerSubscription(scanner)
time.sleep(20) # Wait a moment for the scanner to gather data
print("Stocks Scanned")
# Extract stock symbols from the scanner data
symbols = [scan.contractDetails.contract.symbol for scan in scanDataList]
print(symbols)
# Filter symbols by a 5% increase in price from the previous day
filtered_symbols = self.filter_by_price_change(symbols)
print(filtered_symbols)
return filtered_symbols
def get_available_cash(self):
try:
account_summary = self.ib.reqAccountSummary(9001, "All", AccountSummaryTags.AllTags)
if not account_summary:
print("No account summary data returned.")
return 0.0
for item in account_summary:
if item.tag == 'AvailableFunds' and item.currency == 'USD'and item.account == self.account_id:
return float(item.value)
print(item.value)
print("Account summary data does not contain available funds information.")
return 0.0
except Exception as e:
print(f"Error retrieving account summary: {e}")
return 0.0
def buy_stock(self, stock, initial_cash):
# Rule 3: Spend up to 1/4 of available money on a stock
max_investment = initial_cash / 4
# Get current price
data = self.ib.reqMktData(stock, '', False, False)
self.ib.sleep(2) # Let IB fetch the data
if data and data.last != 0:
current_price = data.last
quantity = max_investment // current_price
# Place market order to buy the stock
order = MarketOrder('BUY', quantity)
trade = self.ib.placeOrder(stock, order)
return trade, current_price
return None, None
def sell_stock(self, stock, quantity):
# Place market order to sell the stock
order = MarketOrder('SELL', quantity)
trade = self.ib.placeOrder(stock, order)
return trade`your text`
def trading_bot(account_id):
my_bot = bot(account_id)
# Get initial available cash
available_cash = my_bot.get_available_cash()
print(available_cash)
portfolio = []
while True:
current_time = datetime.datetime.now().time()
# Execute only within trading hours, adjust the time as per your need
if datetime.time(9, 30) <= current_time <= datetime.time(16, 0):
# Rule 1: Check for stocks to buy until 9:50 a.m.
if current_time <= datetime.time(10, 30):
candidates = my_bot.search_stocks()
Here is the current output:
Connection successful
Stocks Scanned
[]
[]
No symbols found from scanner.
Error retrieving account summary: name ‘AccountSummaryTags’ is not defined
0.0
Dev_99 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.