Tutorial: Trading on Bitfinex using Golang

Jacob Plaster
Bitfinex
Published in
4 min readApr 9, 2019

Our Golang client is one of our most popular open source projects with over 350 forks/stars on Github. Why Go? Well, it’s a seriously quick compiled programming language with great support for concurrency, making it perfect for trading.

The Bitfinex Golang client

The Bitfinex Golang client is a library created by the Bitfinex team to help programmers interact with our WebSocket and REST interfaces.

The library offers a wide array of functionality, including the ability to create new trades, manage existing orders, retrieve historical data and a lot more. You can find the client on GitHub here.

In the following tutorial we are going to pull the bitfinex-api-go library, subscribe to new price updates and then begin making trades on the BTC/USD trading pair using the client WebSocket. We will also explore historical data using the rest interface.

If you have any questions along the way, stop by our Telegram channel to discuss the process with our developers.

Installing the client

Firstly, before we do anything, we need to pull the client from the Bitfinex repo.

To do this, simply run:

go get github.com/bitfinexcom/bitfinex-api-go

Subscribing to BTC/USD price updates

In order to access the Golang library, we first need to import the package. Once we have done this we can create a new client object and tell it to connect to the Bitfinex WebSocket.

package mainimport (
"context"
"log"
"github.com/bitfinexcom/bitfinex-api-go/v2"
"github.com/bitfinexcom/bitfinex-api-go/v2/websocket"
)
func main() {
client := websocket.New()
err := client.Connect()
if err != nil {
log.Printf("could not connect: %s", err.Error())
return
}
}

Now that we have an open connection to the Bitfinex API, we can submit a request to begin receiving new trade updates on the BTCUSD pair. Once this request is received, it will start streaming every single newly executed trade on the given pair to our client.

_, err = c.SubscribeTrades(context.Background(), bitfinex.TradingPrefix+bitfinex.XRPBTC)
if err != nil {
log.Fatal(err)
}

The client exposes a “Listener” channel which takes in all of the data received via the WebSocket. We can use this to log all incoming trades to the console.

for obj := range c.Listen() {
switch obj.(type) {
case error:
log.Printf("EROR RECV: %s", obj)
default:
log.Printf("MSG RECV: %#v", obj)
}
}

Creating a limit order

Again, let’s create and connect the Client. This time we need to specify our API_KEY and API_SECRET since are going to be creating new orders.

In order to set up an API key please go to bitfinex.com/api, log into your Bitfinex account and select “Create New Key”. For this tutorial we need both ‘Read’ and ‘Write’ permissions for ‘Orders’.

package mainimport (
"context"
"log"
"github.com/bitfinexcom/bitfinex-api-go/v2"
"github.com/bitfinexcom/bitfinex-api-go/v2/websocket"
)
func main() {
client := websocket.New().Credentials("BFX_KEY", "BFX_SECRET")
err := client.Connect()
if err != nil {
log.Printf("could not connect: %s", err.Error())
return
}
}

Now we can create a new function that takes in the WebSocket client and submits a new order for 0.02 Bitcoin at a price of 5000. Since we don’t want to use margin, we will specify that the order should be executed on the exchange market.

func SubmitNewOrder(c *websocket.Client) {
or := &bitfinex.OrderNewRequest{
Symbol: "tBTCUSD",
CID: 123,
Amount: 0.02,
Type: "EXCHANGE LIMIT",
Price: 5000,
}
err := c.SubmitOrder(context.Background(), or)
if err != nil {
log.Fatal(err)
}
}

When we call this function, we need to be sure that our client has already passed the authentication process. To do this, we will listen for an authentication success response before submitting our new order.

for obj := range client.Listen() {
switch obj.(type) {
case error:
log.Printf("channel closed: %s", obj)
break
case *websocket.AuthEvent:
// on authorize create new order
SubmitNewOrder(client)
default:
log.Printf("MSG RECV: %#v", obj)
}
}

Accessing historical candles

We don’t want to make blind trades so we can use the client rest interface to get all of the latest candles.

To do this, we need to create a new instance of the REST client and then call the History function which will provide us with a set of candles at the given interval for the given trading pair.

package mainimport (
"log"
bfx "github.com/bitfinexcom/bitfinex-api-go/v2"
"github.com/bitfinexcom/bitfinex-api-go/v2/rest"
"time"
)
func main() {
client := rest.NewClient()
candles, err := c.Candles.History(bfx.TradingPrefix+bfx.BTCUSD, bfx.FiveMinutes)
if err != nil {
log.Fatalf("Failed getting candles: %s", err)
}
log.Printf("length of candles is: %v", len(candles.Snapshot))
log.Printf("first candle is: %#v\n", candles.Snapshot[0])
log.Printf("last candle is: %#v\n", candles.Snapshot[len(candles.Snapshot)-1])
}

The above code takes the most recent batch of candles on the five minute interval and logs them to the console.

Thanks for reading

Now you have what it takes to ingest real-time/historical data and submit new orders using our Golang client!

As always, if you would like to contribute to the repo then simply open a pull request to github.com/bitfinexcom/bitfinex-api-go.

If you would like to see more examples or see the full code snippets of this tutorial then please head to github.com/bitfinexcom/bitfinex-api-go/tree/master/examples/v2.

We’ve removed our equity requirements to open our platform to everyone. Visit Bitfinex today to get started.

Join us on our mission to create the most innovative & industry-leading cryptocurrency exchange.

Stay up to date with Bitfinex on Twitter, Telegram, LinkedIn & YouTube.

--

--