ibsync
is a Go package designed to simplify interaction with the Interactive Brokers API. It is inspired by the great ib_insync Python library and based on ibapi. It provides a synchronous, easy-to-use interface for account management, trade execution, real-time and historical market data within the IB ecosystem.
Caution
This package is in the beta phase. While functional, it may still have bugs or incomplete features. Please test extensively in non-production environments.
- Go version 1.23 or higher (recommended)
- An Interactive Brokers account with TWS or IB Gateway installed and running
Install the package via go get
:
go get -u github.com/scmhub/ibsync
Here’s a basic example to connect and get the managed accounts list:
package main
import "github.com/scmhub/ibsync"
func main() {
// Get the logger (zerolog)
log := ibapi.Logger()
ibsync.SetConsoleWriter() // pretty logs to console, for dev and test.
// New IB client & Connect
ib := ibsync.NewIB()
err := ib.Connect()
if err != nil {
log.Error().Err(err).Msg("Connect")
return
}
defer ib.Disconnect()
managedAccounts := ib.ManagedAccounts()
log.Info().Strs("accounts", managedAccounts).Msg("Managed accounts list")
}
Connect with a different configuration.
// New IB client & Connect
ib := ibsync.NewIB()
err := ib.Connect(
ibsync.NewConfig(
ibsync.WithHost("10.74.0.9"), // Default: "127.0.0.1".
ibsync.WithPort(4002), // Default: 7497.
ibsync.WithClientID(5), // Default: a random number. If set to 0 it will also retreive manual orders.
ibsync.WithTimeout(1*time.Second), // Default is 30 seconds.
),
)
if err != nil {
log.Error().Err(err).Msg("Connect")
return
}
defer ib.Disconnect()
Account value, summary, positions, trades...
// Account Values
accountValues := ib.AccountValues()
// Account Summary
accountSummary := ib.AccountSummary()
// Portfolio
portfolio := ib.Portfolio()
// Positions
// Subscribe to Postion
ib.ReqPositions()
// Position Channel
posChan := ib.PositionChan()
// Trades
trades := ib.Trades()
openTrades := ib.OpenTrades()
Request contract details from symbol, exchange
// NewStock("AMD", "", "")
amd := ibsync.NewStock("AMD", "", "")
cd, err := ib.ReqContractDetails(amd)
if err != nil {
log.Error().Err(err).Msg("request contract details")
return
}
fmt.Println("number of contract found for request NewStock(\"AMD\", \"\", \"\") :", len(cd))
Subscribe to the pnl stream
// Request PnL subscription for the account.
ib.ReqPnL(account, modelCode)
// Get a PnL channel to receive updates...
pnlChan := ib.PnlChan(account, modelCode)
go func() {
for pnl := range pnlChan {
fmt.Println("Received PnL from channel:", pnl)
}
}()
//... Or read the last PnL on the client state
pnl := ib.Pnl(account, modelCode)
fmt.Println("Current PnL:", pnl)
Place an order and create a new trade. Modify or cancel the trade. Cancel all trades
// Create the contract
eurusd := ibsync.NewForex("EUR", "IDEALPRO", "USD")
// Create the order
order := ibsync.LimitOrder("BUY", ibsync.StringToDecimal("20000"), 1.05)
// Place the order
trade := ib.PlaceOrder(eurusd, order)
go func() {
<-trade.Done()
fmt.Println("The trade is done!!!")
}()
// Cancel the order
ib.CancelOrder(Order, ibsync.NewOrderCancel())
// Cancel all orders
ib.ReqGlobalCancel()
Real time and historical bar data.
// Historical data
barChan, _ := ib.ReqHistoricalData(eurusd, endDateTime, duration, barSize, whatToShow, useRTH, formatDate)
var bars []ibsync.Bar
for bar := range barChan {
bars = append(bars, bar)
}
// Historical data up to date
barChan, cancel := ib.ReqHistoricalDataUpToDate(eurusd, duration, barSize, whatToShow, useRTH, formatDate)
go func() {
for bar := range barChan {
bars = append(bars, bar)
}
}()
time.Sleep(10 * time.Second)
cancel()
// Real time bars
rtBarChan, cancel := ib.ReqRealTimeBars(eurusd, 5, "MIDPOINT", useRTH)
<-rtBarChan
cancel()
Real time and historical tick data.
// Snapshot - Market price
snapshot, err := ib.Snapshot(eurusd)
if err != nil {
panic(fmt.Errorf("snapshot eurusd: %v", err))
}
fmt.Println("Snapshot market price", snapshot.MarketPrice())
// Tick by tick data
tickByTick := ib.ReqTickByTickData(eurusd, "BidAsk", 100, true)
time.Sleep(5 * time.Second)
ib.CancelTickByTickData(eurusd, "BidAsk")
// HistoricalTicks
historicalTicks, err, done := ib.ReqHistoricalTicks(aapl, startDateTime, time.Time{}, 100, true, true)
Request scanner parameters and scanner subscritpion
// Scanner Parameters
xml, err := ib.ReqScannerParameters()
// Scanner subscription
scanSubscription := ibsync.NewScannerSubscription()
scanSubscription.Instrument = "STK"
scanSubscription.LocationCode = "STK.US.MAJOR"
scanSubscription.ScanCode = "TOP_PERC_GAIN"
scanData, err := ib.ReqScannerSubscription(scanSubscription)
// Scanner subcscription with filter option
opts := ibsync.ScannerSubscriptionOptions{
FilterOptions: []ibsync.TagValue{
{Tag: "changePercAbove", Value: "20"},
{Tag: "priceAbove", Value: "5"},
{Tag: "priceBelow", Value: "50"},
},
}
filterScanData, err := ib.ReqScannerSubscription(scanSubscription, opts)
For more information on how to use this package, please refer to the GoDoc documentation and check the examples directory. You can also have a look at the ib_test.go
file
Caution
This project is in the beta phase and is still undergoing testing and development. Users are advised to thoroughly test the software in non-production environments before relying on it for live trading. Features may be incomplete, and bugs may exist. Use at your own risk.
Important
This project is not affiliated with Interactive Brokers Group, Inc. All references to Interactive Brokers, including trademarks, logos, and brand names, belong to their respective owners. The use of these names is purely for informational purposes and does not imply endorsement by Interactive Brokers.
Important
The authors of this package make no guarantees regarding the software's reliability, accuracy, or suitability for any particular purpose, including trading or financial decisions. No liability will be accepted for any financial losses, damages, or misinterpretations arising from the use of this software.
Distributed under the MIT License. See LICENSE for more information.
Philippe Chavanne - contact