ibapi 进行交易时遇到问题

问题描述 投票:0回答:2

我正在尝试制作我的第一个算法机器人,并决定与 IB 合作并使用他们的 API。我关注了 Jacob Aramral 的关于制作机器人的 YouTube 系列,并且基本上遵循并添加了一些调整,以使逻辑按照我想要的方式执行。尝试运行代码后,我不断收到有关无法连接的错误。所以,我只是复制了他的代码并尝试运行它(https://github.com/Jake0303/InteractiveBrokersPythonBot/blob/main/InteractiveBrokersPythonBot.py)。它连接到 TWS(我假设是 IB 服务器),我可以输入股票代码并获取实时数据,但它不会进行交易。然后,我调整了雅各布的代码,基本上在每根蜡烛上进行交易(只是因为它正在读取我的纸质账户,并且我想看到进行任何交易),但是当满足标准时(最后收盘价高于之前蜡烛的收盘价)没有进行任何交易。我开始有点沮丧,所以希望有人能帮助我。我也尝试复制这里的介绍指南来尝试让 TWS 进行交易,但仍然没有成功。如果有人能看到我做错了什么并可以帮助我解决它,我将不胜感激。

我的 IBpro 账户由游戏资金提供资金,并订阅了“美国股票和期权附加流媒体捆绑包”和“美国证券快照和期货价值捆绑包”订阅。对于纸质账户,我使用 7497 作为套接字端口,检查了 Active X 和套接字客户端,并禁用了只读 API。我相信这就是我需要启用的所有功能,以允许 API 为我进行交易(除了有功能代码,哈哈)。这是应该可以工作的代码。我很好奇它是否适用于其他和地方交易。另外,代码运行后我还添加了监视器的片段。如有任何帮助,我们将不胜感激!

#Imports
import ibapi
from ibapi.client import EClient
from ibapi.wrapper import EWrapper
from ibapi.contract import Contract
from ibapi.order import *
import ta
import numpy as np
import pandas as pd
import pytz
import math
from datetime import datetime, timedelta
import threading
import time
#Vars
orderId = 1
#Class for Interactive Brokers Connection
class IBApi(EWrapper,EClient):
    def __init__(self):
        EClient.__init__(self, self)
    # Historical Backtest Data
    def historicalData(self, reqId, bar):
        try:
            bot.on_bar_update(reqId,bar,False)
        except Exception as e:
            print(e)
    # On Realtime Bar after historical data finishes
    def historicalDataUpdate(self, reqId, bar):
        try:
            bot.on_bar_update(reqId,bar,True)
        except Exception as e:
            print(e)
    # On Historical Data End
    def historicalDataEnd(self, reqId, start, end):
        print(reqId)
    # Get next order id we can use
    def nextValidId(self, nextorderId):
        global orderId
        orderId = nextorderId
    # Listen for realtime 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(errorCode)
        print(errorMsg)
#Bar Object
class Bar:
    open = 0
    low = 0
    high = 0
    close = 0
    volume = 0
    date = datetime.now()
    def __init__(self):
        self.open = 0
        self.low = 0
        self.high = 0
        self.close = 0
        self.volume = 0
        self.date = datetime.now()
#Bot Logic
class Bot:
    ib = None
    barsize = 1
    currentBar = Bar()
    bars = []
    reqId = 1
    global orderId
    smaPeriod = 50
    symbol = ""
    initialbartime = datetime.now().astimezone(pytz.timezone("America/New_York"))
    def __init__(self):
        #Connect to IB on init
        self.ib = IBApi()
        self.ib.connect("127.0.0.1", 7497,221)
        ib_thread = threading.Thread(target=self.run_loop, daemon=True)
        ib_thread.start()
        time.sleep(1)
        currentBar = Bar()
        #Get symbol info
        self.symbol = input("Enter the symbol you want to trade : ")
        #Get bar size
        self.barsize = int(input("Enter the barsize you want to trade in minutes : "))
        mintext = " min"
        if (int(self.barsize) > 1):
            mintext = " mins"
        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")
        #Create our IB Contract Object
        contract = Contract()
        contract.symbol = self.symbol.upper()
        contract.secType = "STK"
        contract.exchange = "SMART"
        contract.currency = "USD"
        self.ib.reqIds(-1)
        # Request Market Data
        #self.ib.reqRealTimeBars(0, contract, 5, "TRADES", 1, [])
        self.ib.reqHistoricalData(self.reqId,contract,"","2 D",str(self.barsize)+mintext,"TRADES",1,1,True,[])
    #Listen to socket in seperate thread
    def run_loop(self):
        self.ib.run()
    #Bracet Order Setup
    def bracketOrder(self, parentOrderId, action, quantity, profitTarget, stopLoss):
        #Initial Entry
        #Create our IB Contract Object
        contract = Contract()
        contract.symbol = self.symbol.upper()
        contract.secType = "STK"
        contract.exchange = "SMART"
        contract.currency = "USD"
        # Create Parent Order / Initial Entry
        parent = Order()
        parent.orderId = parentOrderId
        parent.orderType = "MKT"
        parent.action = action
        parent.totalQuantity = quantity
        parent.transmit = False
        # Profit Target
        profitTargetOrder = Order()
        profitTargetOrder.orderId = parent.orderId+1
        profitTargetOrder.orderType = "LMT"
        profitTargetOrder.action = "SELL"
        profitTargetOrder.totalQuantity = quantity
        profitTargetOrder.lmtPrice = round(profitTarget,2)
        profitTargetOrder.parentId = parentOrderId
        profitTargetOrder.transmit = False
        # Stop Loss
        stopLossOrder = Order()
        stopLossOrder.orderId = parent.orderId+2
        stopLossOrder.orderType = "STP"
        stopLossOrder.action = "SELL"
        stopLossOrder.totalQuantity = quantity
        stopLossOrder.parentId = parentOrderId
        stopLossOrder.auxPrice = round(stopLoss,2)
        stopLossOrder.transmit = True

        bracketOrders = [parent, profitTargetOrder, stopLossOrder]
        return bracketOrders
    #Pass realtime bar data back to our bot object
    def on_bar_update(self, reqId, bar,realtime):
        global orderId
        #Historical Data to catch up
        if (realtime == False):
            self.bars.append(bar)
        else:
            bartime = datetime.strptime(bar.date,"%Y%m%d %H:%M:%S").astimezone(pytz.timezone("America/New_York"))
            minutes_diff = (bartime-self.initialbartime).total_seconds() / 60.0
            self.currentBar.date = bartime
            lastBar = self.bars[len(self.bars)-1]
            #On Bar Close
            if (minutes_diff > 0 and math.floor(minutes_diff) % self.barsize == 0):
                self.initialbartime = bartime
                #Entry - If we have a higher high, a higher low and we cross the 50 SMA Buy
                #1.) SMA
                closes = []
                for bar in self.bars:
                    closes.append(bar.close)
                self.close_array = pd.Series(np.asarray(closes))
                self.sma = ta.trend.sma(self.close_array,self.smaPeriod,True)
                print("SMA : " + str(self.sma[len(self.sma)-1]))
                #2.) Calculate Higher Highs and Lows
                lastLow = self.bars[len(self.bars)-1].low
                lastHigh = self.bars[len(self.bars)-1].high
                lastClose = self.bars[len(self.bars)-1].close

                # Check Criteria
                if (bar.close > lastHigh
                    and self.currentBar.low > lastLow
                    and bar.close > str(self.sma[len(self.sma)-1])
                    and lastClose < str(self.sma[len(self.sma)-2])):
                    #Bracket Order 2% Profit Target 1% Stop Loss
                    profitTarget = bar.close*1.02
                    stopLoss = bar.close*0.99
                    quantity = 1
                    bracket = self.bracketOrder(orderId,"BUY",quantity, profitTarget, stopLoss)
                    contract = Contract()
                    contract.symbol = self.symbol.upper()
                    contract.secType = "STK"
                    contract.exchange = "SMART"
                    contract.currency = "USD"
                    #Place Bracket Order
                    for o in bracket:
                        o.ocaGroup = "OCA_"+str(orderId)
                        self.ib.placeOrder(o.orderId,contract,o)
                    orderId += 3
                #Bar closed append
                self.currentBar.close = bar.close
                print("New bar!")
                self.bars.append(self.currentBar)
                self.currentBar = Bar()
                self.currentBar.open = bar.open
        #Build  realtime bar
        if (self.currentBar.open == 0):
            self.currentBar.open = bar.open
        if (self.currentBar.high == 0 or bar.high > self.currentBar.high):
            self.currentBar.high = bar.high
        if (self.currentBar.low == 0 or bar.low < self.currentBar.low):
            self.currentBar.low = bar.low

#Start Bot
bot = Bot()
python bots trading algorithmic-trading ib-api
2个回答
0
投票

进行了一些调整,包括不满足标准时显示消息。 应该让你开始

#Imports
import ibapi
from ibapi.client import EClient
from ibapi.wrapper import EWrapper
from ibapi.contract import Contract
from ibapi.order import *

import pandas as pd
import pytz
import math
from datetime import datetime, timedelta
import threading
import time
#Vars
orderId = 1

#Class for Interactive Brokers Connection
class IBApi(EWrapper,EClient):
    def __init__(self):
        EClient.__init__(self, self)
    # Historical Backtest Data
    def historicalData(self, reqId, bar):
        try:
            myBar = Bar()
            myBar.open = bar.open
            myBar.low = bar.low
            myBar.high = bar.high
            myBar.close = bar.close
            myBar.volume = bar.volume
            myBar.date = pytz.timezone("America/New_York").localize(datetime.strptime(bar.date[:17], "%Y%m%d %H:%M:%S"))
            bot.on_bar_update(reqId,myBar,False)
        except Exception as e:
            print("historicalData Ex: ",e)

    # On Historical Data End
    def historicalDataEnd(self, reqId, start, end):
        try:
            print("\nHistorical data recieved: ",start," to ",end)
            print("Waiting for next bar close....")
            contract = Contract()
            contract.symbol = bot.symbol.upper()
            contract.secType = "STK"
            contract.exchange = "SMART"
            contract.currency = "USD"
            bot.ib.reqRealTimeBars(2, contract, 5, "TRADES", False, []) 
        except Exception as e:
            print("historicalDataEnd Ex: ",e)
    # Get next order id we can use
    def nextValidId(self, nextorderId):
        global orderId
        orderId = nextorderId
    # Listen for realtime bars
    def realtimeBar(self, reqId, time, open_, high, low, close,volume, wap, count):
        super().realtimeBar(reqId, time, open_, high, low, close, volume, wap, count)
        
        bar = Bar()
        bar.open = open_
        bar.low = low
        bar.high = high
        bar.close = close
        bar.volume = volume
        bar.date = datetime.fromtimestamp(time, pytz.timezone("America/New_York"))
        bot.on_bar_update(reqId, bar, True)

    def error(self, id, errorCode, errorMsg, advOrdRej):  # Depending on API version advOrdRej may not be required
        print(errorCode,": ",errorMsg)


#Bar Object
class Bar:
    open = 0
    low = 0
    high = 0
    close = 0
    volume = 0
    date = datetime.now()
    def __init__(self):
        self.open = 0
        self.low = 0
        self.high = 0
        self.close = 0
        self.volume = 0
        self.date = datetime.now()
#Bot Logic
class Bot:
    ib = None
    barsize = 1
    currentBar = Bar()
    bars = []
    reqId = 1
    global orderId
    smaPeriod = 50
    symbol = ""
    nextBarTime = 0
    
    def __init__(self):
        #Connect to IB on init
        self.ib = IBApi()
        self.ib.connect("127.0.0.1", 7497,221)
        ib_thread = threading.Thread(target=self.run_loop, daemon=True)
        ib_thread.start()
        time.sleep(1)
        currentBar = Bar()
        #Get symbol info
        self.symbol = input("Enter the symbol you want to trade : ")
        #Get bar size
        self.barsize = int(input("Enter the barsize you want to trade in minutes : "))
        mintext = " min"
        if (int(self.barsize) > 1):
            mintext = " mins"
            
        secs = 60 * self.barsize * 200 # barcount to retrieve
        queryTime = (datetime.now().astimezone(pytz.timezone("America/New_York"))-timedelta(seconds=secs)).strftime("%Y%m%d %H:%M:%S")
        
        #Create our IB Contract Object
        contract = Contract()
        contract.symbol = self.symbol.upper()
        contract.secType = "STK"
        contract.exchange = "SMART"
        contract.currency = "USD"
        self.ib.reqIds(-1)
        # Request History
        self.ib.reqHistoricalData(1,contract,"",str(secs)+" S",str(self.barsize)+mintext,"TRADES",0,1,False,[])
        
    #Listen to socket in seperate thread
    def run_loop(self):
        self.ib.run()
    #Bracet Order Setup
    def bracketOrder(self, parentOrderId, action, quantity, profitTarget, stopLoss):
        #Initial Entry
        #Create our IB Contract Object
        contract = Contract()
        contract.symbol = self.symbol.upper()
        contract.secType = "STK"
        contract.exchange = "SMART"
        contract.currency = "USD"
        # Create Parent Order / Initial Entry
        parent = Order()
        parent.orderId = parentOrderId
        parent.orderType = "MKT"
        parent.action = action
        parent.totalQuantity = quantity
        parent.transmit = False
        # Profit Target
        profitTargetOrder = Order()
        profitTargetOrder.orderId = parent.orderId+1
        profitTargetOrder.orderType = "LMT"
        profitTargetOrder.action = "SELL"
        profitTargetOrder.totalQuantity = quantity
        profitTargetOrder.lmtPrice = round(profitTarget,2)
        profitTargetOrder.parentId = parentOrderId
        profitTargetOrder.transmit = False
        # Stop Loss
        stopLossOrder = Order()
        stopLossOrder.orderId = parent.orderId+2
        stopLossOrder.orderType = "STP"
        stopLossOrder.action = "SELL"
        stopLossOrder.totalQuantity = quantity
        stopLossOrder.parentId = parentOrderId
        stopLossOrder.auxPrice = round(stopLoss,2)
        stopLossOrder.transmit = True

        bracketOrders = [parent, profitTargetOrder, stopLossOrder]
        return bracketOrders
    

    #Pass realtime bar data back to our bot object
    def on_bar_update(self, reqId, bar, realtime):
        global orderId,nextBarTime,currentBar
        
        try:
            #Historical Data to catch up
            if (realtime == False):
                self.bars.append(bar)
                self.nextBarTime = bar.date+timedelta(seconds=60 * self.barsize)
            else:
                if (bar.date >= self.nextBarTime):
                    #On Bar Close
                    self.bars.append(self.currentBar)
                    print("Bar Closed ",self.currentBar.date.strftime('%H:%M'),"   o:",self.currentBar.open," h:",self.currentBar.high," l:",self.currentBar.low," c:",self.currentBar.close)
                    
                    # Calc SMA
                    closes = []
                    for bar in self.bars:
                        closes.append(bar.close)
                        
                    numbers_series = pd.Series(closes)
                    windows = numbers_series.rolling(self.smaPeriod)
                    moving_averages = windows.mean()
                    sma = moving_averages.tolist()

                    # Calculate Higher Highs and Lows
                    lastLow = self.bars[len(self.bars)-1].low
                    lastHigh = self.bars[len(self.bars)-1].high
                    lastClose = self.bars[len(self.bars)-1].close
                    
                    # Check Criteria
                    if (self.currentBar.close > lastHigh
                        and self.currentBar.low > lastLow
                        and self.currentBar.close > sma[len(sma)-1]
                        and lastClose < sma[len(sma)-2]):
                        
                        print("Placing Order")
                        
                        #Bracket Order 2% Profit Target 1% Stop Loss
                        profitTarget = bar.close*1.02
                        stopLoss = bar.close*0.99
                        quantity = 1
                        bracket = self.bracketOrder(orderId,"BUY",quantity, profitTarget, stopLoss)
                        contract = Contract()
                        contract.symbol = self.symbol.upper()
                        contract.secType = "STK"
                        contract.exchange = "SMART"
                        contract.currency = "USD"
                        #Place Bracket Order
                        for o in bracket:
                            o.ocaGroup = "OCA_"+str(orderId)
                            self.ib.placeOrder(o.orderId,contract,o)
                        orderId += 3
                        
                    else:
                        if(self.currentBar.close <= lastHigh):
                            print("-- Criteria not met: 'self.currentBar.close > lastHigh'    Close:",self.currentBar.close,"   lastHigh:",lastHigh)
                        if(self.currentBar.low <= lastLow):
                            print("-- Criteria not met: 'self.currentBar.low > lastLow'    Low:",self.currentBar.close,"   lastLow:",lastLow)
                        if(self.currentBar.close <= sma[len(sma)-1]):
                            print("-- Criteria not met: 'self.currentBar.close > sma[len(sma)-1]'     Close:",self.currentBar.close,"   sma:",sma[len(sma)-1])
                        if(lastClose >= sma[len(sma)-2]):
                            print("-- Criteria not met: 'lastClose < sma[len(sma)-2]'    lastClose:",lastClose,"   sma:",sma[len(sma)-2])
                    
                    
                    # Create new bar 
                    self.currentBar = Bar()    
                    self.currentBar.open = bar.open
                    self.currentBar.high = bar.high
                    self.currentBar.low = bar.low
                    self.currentBar.close = bar.close              
                    self.currentBar.date = self.nextBarTime #bar.date
                    
                    self.nextBarTime += timedelta(seconds=60 * self.barsize)  
           
                else:
                    #Build realtime bar
                    if (self.currentBar.open == 0):
                        self.currentBar.open = bar.open
                    if (self.currentBar.high == 0 or bar.high > self.currentBar.high):
                        self.currentBar.high = bar.high
                    if (self.currentBar.low == 0 or bar.low < self.currentBar.low):
                        self.currentBar.low = bar.low
                    self.currentBar.close = bar.close
                    
        except Exception as e:
            print("on_bar_update Ex: ",e)

#Start Bot
bot = Bot()

0
投票

首先,感谢您找到这个讨论。附加的代码对我也有帮助。然而,我发现,在原始 GitHub 文件和此处的代码中,“最后”值以某种方式立即更新为当前值,这意味着以下打印将始终相同:

检查标准

print("self.currentBar.Close:",self.currentBar.close) 打印(“最后关闭:”,最后关闭) if (self.currentBar.close > LastClose):

我还测试了:“if (self.currentBar.close == lastClose):”并且它确实进行了交易..

如果有人可以帮助让lastClose真正成为最后一次关闭而不是currentBar.Close?

© www.soinside.com 2019 - 2024. All rights reserved.