Implement your Trading Strategy with the Bitfinex Honey and Terminal Framework
in Dazaar, Trading
We recently learned how backlinking strategy can work with Bitfinex Terminal data streams. At its core, the data streams are free Dazaar feeders shared over BitTorrent-like P2P technology. But unlike BitTorrent, the data can be verified cryptographically and is easy to stream. We can request data set frames from the center or decide to follow a live stream with the latest additions. Of course, it is possible to download the entire dataset as well.
In this article, we will use data streamed on the Bitfinex Terminal to implement a live strategy. For demonstration purposes, the trading signals generated are sent to the Bitfinex Websocket API. In practice, however, we can do anything with them. Even if you wanted to power on a coffee machine with a Raspberry Pi every time your strategy traded, you could still do it!
For our tutorial, we use a popular strategy, Cross Strategy EMA. It emits a trading signal when two EMA indicators cross each other. The Trans EMA strategy is included as one of the examples in the bfx-hf strategy library.
Let’s start
First we need to set the required dependencies:
npm install dazaar hyperbee bitfinex-terminal-key-encoding bfx-hf-util bfx-hf-strategy bfx-hf-strategy-dazaar bitfinex-api-node bfx-api-node-models bitfinex-terminal-terms-of-use
We also need to create a file, which will contain the code we write, let’s call it exec-strategy.js
:
touch exec-strategy.js
Now we can load the required dependencies. Readers of our post-test tutorial will see some similarities:
const dazaar = require('dazaar') const swarm = require('dazaar/swarm') const Hyperbee = require('hyperbee') const keyEncoding = require('bitfinex-terminal-key-encoding') const terms = require('bitfinex-terminal-terms-of-use') const { SYMBOLS, TIME_FRAMES } = require('bfx-hf-util') const EMAStrategy = require('bfx-hf-strategy/examples/ema_cross') const execDazaar = require('bfx-hf-strategy-dazaar')
We also load and start a Bitfinex Websocket client. To make it work, you must replace the placeholders with your qualifications:
const { WSv2 } = require('bitfinex-api-node') const { Order } = require('bfx-api-node-models') const apiKey = 'SECRET' const apiSecret="SECRETSECRET" const ws = new WSv2({ apiKey, apiSecret })
Next we will start our strategy:
const market = { symbol: SYMBOLS.BTC_USD, tf: TIME_FRAMES.ONE_MINUTE } const strat = EMAStrategy(market)
And start Dazaar:
const dmarket = dazaar('dbs/terminal-live') // stores received data in `dbs/terminal-live`
With wget
we can extract the Dazaar Card for the data feed we want to consume. An overview of data feeds can be found here.
wget https://raw.githubusercontent.com/bitfinexcom/bitfinex-terminal/master/cards/bitfinex.terminal.btcusd.trades.json
That card is loaded into Dazaar and the Terms of Service are agreed upon by loading them into Dazaar after we have read them:
const card = require('./bitfinex.terminal.btcusd.candles.json') const buyer = dmarket.buy(card, { sparse: true, terms })
And if Dazaar emits a feed
event, we set up Hyperbee and call a function called runStrategy
:
buyer.on('feed', function () { console.log('got feed') const db = new Hyperbee(buyer.feed, { keyEncoding, valueEncoding: 'json' }) runStrategy(db) })
So far, most of our setup is similar to the setup we used for post-tests in the last article. Now we have to define the function runStrategy
, which allows us to do something with the trading signals from our strategy:
async function runStrategy (db) { }
The function runStrategy
establishes the logic that runs our strategy on each candle received. First, we open the Websocket to the Bitfinex API.
await ws.open() await ws.auth()
We also set up the data flow. We call execDazaar
with our strategy, defined market and Hyperbee database. As options, we pass in submitOrder
, a custom function that we will write in a bit. submitOrder
is called for every trading signal emitted from our strategy. The simulateFill
the option allows us not to wait for the order to be fully filled by the exchange, which is useful for our tutorial. The built-in submitOrder
-function in the Honey Framework also issues orders from WebSocket and waits for an order to be filled before continuing. When producing, you may want to use the built-in one, depending on your strategy and use case. We also seed the state of the strategy, we use a count of 120 candles.
const { exec, stream } = await execDazaar(strat, market, db, { submitOrder, simulateFill: true, includeTrades: false, seedCandleCount: 120 })
execDazaar
returns a stream and function called exec
. We call exec
on every record sent in the stream:
for await (const data of stream) { const { key, value } = data await exec(key, value) }
Our role runStrategy
now complete, the full function is:
async function runStrategy (db) { await ws.open() await ws.auth() const { exec, stream } = await execDazaar(strat, market, db, { submitOrder, simulateFill: true, includeTrades: false, seedCandleCount: 10 }) for await (const data of stream) { const { key, value } = data await exec(key, value) } }
We still have to define the function submitOrder
. For each signal emitted from our EMA Cross strategy, submitOrder
is called with the current state of the strategy and order data. In our case, we take the order data and send it to Bitfinex. We are writing a simplified version of the
async function submitOrder (strategyState = {}, order = {}) { const _o = { cid: Date.now(), ...order } console.log('submitting order', _o) const o = new Order(_o, ws) o.registerListeners() o.on('update', () => { console.log(`order updated: ${o.serialize()}`) }) const res = await o.submit() return res }
To get started, we have to connect to the network, which will trigger a feed
event:
swarm(buyer)
When we run the file now, it will take the last 120 candles and pre-seed our strategy algorithm with it. It will then follow the live stream of new candles coming in and running our strategy on it. In case a trading signal is generated, it is delivered to the Bitfinex API. You can find the full file we wrote in this article here.
And that’s it! In this article, we have learned how we can take a Honey Framework strategy, feed data from Bitfinex Terminal, and present the trading signals for trading. With the help of custom submitOrder
functions, we can build custom functionality on which our trading strategy operates. Hope you enjoyed the article.
PS: Bitfinex is hiring! š