Code Monkey home page Code Monkey logo

ibkit's Introduction

IBKit - Interactive Brokers API swiftified

License Swift Xcode 13.0+ macOS 12+ SPM

IBKit is open source Interactive Brokers API library written in Swift. It allows you to automate trades, retrieve market data and monitor positions and orders. Offering both live and paper trading capabilities, it can be used as an algo trading platform or as an backtesting datasource. In latter case you need to write your own portfolio accounting and performance measurement methods.

The software is not an official API and is not affiliated or related with Interactive Brokers.

Conformance

The current version should conform with IB API version 10.24. It is the aim to update the software with to MacOS major releases and include also better bites from TWS API.

Current status

  • Common features seems to work fine but complex orders may generate errors.
  • FA Accounts are not currently supported

Requirements

Setting up IB Gateway

  • Launch IB Gateway, select IB Api as interface and use your live or paper trading credentials to log in.
  • To prevent IB Gateway/TWS to close application on your specified time, you need to select “Restart” option instead of “Auto logoff” under Configuration>Lock and Exit menu. IB maintains its servers on Saturday early mornings (GMT) and the service is disrupted for a few hours. They also restart their servers on each morning so your gateway or workstation will be disconnected for a minute or two.
  • Pay attention to your Master Client ID, host and port as you will need them when initiating new client. You find these values under Configuration>Settings>API>Settings menu.
  • Select UTC format for sending instrument-specific attributes
  • If you want to submit orders, you shall also uncheck Read Only API from Configuration>Settings>API>Settings menu.

Getting Started

Create a new Xcode project and navigate to File > Swift Packages > Add Package Dependency. Enter the url https://github.com/stensoosaar/IBKit and tap Next. Choose the main branch, and on the next screen, check off the packages as needed.

How to use?

While the api calls closely resemble IB's own API, the responses are provided by using dedicated data publishers for market, account and system events.

	var subscriptions: [AnyCancellable] = []

	client.marketEventFeed
		.sink { event in 
			handle event
		}
		.store(in: &subscriptions)

	do {
		let requestID = client.getNextID()
		let interval = DateInterval.lookback(10, unit: .minute, until: .distantFuture)
		try client.requestPriceHistory(requestID, contract: contract, barSize: IBBarSize.day, barSource: IBBarSource.bidAsk, lookback: interval)
	} catch {
		print(error.localizedDescription)
	}

Most response messages are stripped down from request context (e.g., bar size or source), and you need to pair requests and responses using a unique requestID. One way to achieve that is to create your own custom publisher and map the data against your own data model.

class SimulatedBroker{

   var api: IBClient

   func priceHistoryPublisher(_ interval: DateInterval, size: IBBarSize, contract: IBContract, extendedSession: Bool = false) throws -> AnyPublisher<AnyPriceUpdate, CustomAPIError>{
   		
   	let requestID = api.nextRequestID
   	let source: IBBarSource = [.cfd, .forex, .crypto].contains{$0 == contract.securitiesType} ? .midpoint : .trades
   	let request = IBPriceHistoryRequest(requestID: requestID, contract: contract, size: size, source: source, lookback: interval, extendedTrading: extendedSession)
   	try api.send(request: request)
   	
   	return AnyPublisher(self.api.eventFeed
   		.setFailureType(to: CustomAPIError.self)
   		.compactMap { $0 as? IBIndexedEvent }
   		.filter { $0.requestID == requestID }
   		.tryMap{ response -> (any AnyPriceUpdate) in
   			switch response {
   			   // handle response / error here 
   			}
   		.mapError { $0 as! CustomAPIError }
   		.eraseToAnyPublisher()
   	)
   		
   }
}


let broker = SimulatedBroker(id: 0)
var subscriptions: [AnyCancellable] = []
broker.api.connect()

do{
   let contract = IBContract.future(localSymbol: "MESM4", currency: "USD")
   let interval = DateInterval.lookback(10, unit: .minute, until: .distantFuture)
   try broker.priceHistoryPublisher(interval, size: .minute, contract: contract)
   	.sink { completion in
   		print(completion)
   	} receiveValue: { response in
   		print(respinse)
   	}
   	.store(in: &subscriptions)
} catch{
   print(error.localizedDescription)
}

See also included playground pages.

ibkit's People

Contributors

stensoosaar avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

ibkit's Issues

How to use the API

I am tryin to use IBKit. It looks great.

However, I don't even know how to initialize the API and start to use it.

Is there any document or could you provide more details about how to init the API and how to request historical price for a stock, for example?

IBPriceBar failed to decode double

I've tried to subscribe to ETH, using below method and utilising raw initialiser for your enums from values
marketData("ETH", interval: 5, secType: "CRYPTO", exchange: "PAXOS")

private func historicBarPublisher(
        for contract: IBContract,
        barSize size: IBBarSize = .minute,
        duration: IBDuration = IBDuration.continuousUpdates(60, unit: .second)
    ) throws -> Int {
        let requestID = client.nextRequestID
        try client.requestPriceHistory(
            requestID,
            contract: contract,
            barSize: size, // from raw time interval == 5
            barSource: IBBarSource.trades,
            lookback: duration // IBDuration.continuousUpdates(60, unit: .second)
        )
        return requestID
    }

IBPriceBar fails to decode double

Decoding error: cant unwrap double from , cursor: 5  ["90", "1", "-1", "20240425-06:50:40", "", "", "", "", "0", "-1"]

Outgoing message race between user requests and handshaking process

the connection locking logic, as there seems to be outgoing message race between user requests and handshaking process...

connecting: 127.0.0.1:4002
connected

1714051808.505105.    ("API\0\0\0\0\tv142..175")
1714051808.5111098.   ("\0\0\0G20\00\00\0ETH\0CRYPTO\0\00.00\0\00.00\0PAXOS\0\0USD\0\0\00\0\01 min\060 S\00\0TRADES\01\01\0\0")
connected to API
1714051808.526440.   ("\0\0\0\n71\02\0999\0\0")

_Originally posted by @stensoosaar in https://github.com/stensoosaar/IBKit/pull/5#issuecomment-2077194162_

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.