GithubHelp home page GithubHelp logo

bitfinex-api-py's Introduction

bitfinex-api-py

PyPI - Python Version Code style: black GitHub Action

Official implementation of the Bitfinex APIs (V2) for Python 3.8+.

Features

  • Support for 75+ REST endpoints (a list of available endpoints can be found here)
  • New WebSocket client to ensure fast, secure and persistent connections
  • Full support for Bitfinex notifications (including custom notifications)
  • Native support for type hinting and type checking with mypy

Installation

python3 -m pip install bitfinex-api-py

Quickstart

from bfxapi import Client, REST_HOST

from bfxapi.types import Notification, Order

bfx = Client(
    rest_host=REST_HOST,
    api_key="<YOUR BFX API-KEY>",
    api_secret="<YOUR BFX API-SECRET>"
)

notification: Notification[Order] = bfx.rest.auth.submit_order(
    type="EXCHANGE LIMIT", symbol="tBTCUSD", amount=0.165212, price=30264.0)

order: Order = notification.data

if notification.status == "SUCCESS":
    print(f"Successful new order for {order.symbol} at {order.price}$.")

if notification.status == "ERROR":
    raise Exception(f"Something went wrong: {notification.text}")

Authenticating in your account

To authenticate in your account, you must provide a valid API-KEY and API-SECRET:

bfx = Client(
    [...],
    api_key=os.getenv("BFX_API_KEY"),
    api_secret=os.getenv("BFX_API_SECRET")
)

Warning

Remember to not share your API-KEYs and API-SECRETs with anyone.
Everyone who owns one of your API-KEYs and API-SECRETs will have full access to your account.
We suggest saving your credentials in a local .env file and accessing them as environment variables.

Revoke your API-KEYs and API-SECRETs immediately if you think they might have been stolen.

NOTE: A guide on how to create, edit and revoke API-KEYs and API-SECRETs can be found here.

Next


WebSocket client documentation

  1. Instantiating the client
  2. Running the client
  3. Subscribing to public channels
  4. Listening to events

Advanced features

Examples

Instantiating the client

bfx = Client(wss_host=PUB_WSS_HOST)

Client::wss contains an instance of BfxWebSocketClient (core implementation of the WebSocket client).
The wss_host argument is used to indicate the URL to which the WebSocket client should connect.
The bfxapi package exports 2 constants to quickly set this URL:

Constant URL When to use
WSS_HOST wss://api.bitfinex.com/ws/2 Suitable for all situations, supports authentication.
PUB_WSS_HOST wss://api-pub.bitfinex.com/ws/2 For public uses only, doesn't support authentication.

PUB_WSS_HOST is recommended over WSS_HOST for applications that don't require authentication.

NOTE: The wss_host parameter is optional, and the default value is WSS_HOST.

Authentication

To learn how to authenticate in your account, have a look at Authenticating in your account.

If authentication is successful, the client will emit the authenticated event.
All operations that require authentication will fail if run before the emission of this event.
The data argument contains information about the authentication, such as the userId, the auth_id, etc...

@bfx.wss.on("authenticated")
def on_authenticated(data: Dict[str, Any]):
    print(f"Successful login for user <{data['userId']}>.")

data can also be useful for checking if an API-KEY has certain permissions:

@bfx.wss.on("authenticated")
def on_authenticated(data: Dict[str, Any]):
    if not data["caps"]["orders"]["read"]:
        raise Exception("This application requires read permissions on orders.")

    if not data["caps"]["positions"]["write"]:
        raise Exception("This application requires write permissions on positions.")

Running the client

The client can be run using BfxWebSocketClient::run:

bfx.wss.run()

If an event loop is already running, users can start the client with BfxWebSocketClient::start:

await bfx.wss.start()

If the client succeeds in connecting to the server, it will emit the open event.
This is the right place for all bootstrap activities, such as subscribing to public channels.
To learn more about events and public channels, see Listening to events and Subscribing to public channels.

@bfx.wss.on("open")
async def on_open():
    await bfx.wss.subscribe("ticker", symbol="tBTCUSD")

Closing the connection

Users can close the connection with the WebSocket server using BfxWebSocketClient::close:

await bfx.wss.close()

A custom close code number, along with a verbose reason, can be given as parameters:

await bfx.wss.close(code=1001, reason="Going Away")

After closing the connection, the client will emit the disconnected event:

@bfx.wss.on("disconnected")
def on_disconnected(code: int, reason: str):
    if code == 1000 or code == 1001:
        print("Closing the connection without errors!")

Subscribing to public channels

Users can subscribe to public channels using BfxWebSocketClient::subscribe:

await bfx.wss.subscribe("ticker", symbol="tBTCUSD")

On each successful subscription, the client will emit the subscribed event:

@bfx.wss.on("subscribed")
def on_subscribed(subscription: subscriptions.Subscription):
    if subscription["channel"] == "ticker":
        print(f"{subscription['symbol']}: {subscription['sub_id']}") # tBTCUSD: f2757df2-7e11-4244-9bb7-a53b7343bef8

Unsubscribing from a public channel

It is possible to unsubscribe from a public channel at any time.
Unsubscribing from a public channel prevents the client from receiving any more data from it.
This can be done using BfxWebSocketClient::unsubscribe, and passing the sub_id of the public channel you want to unsubscribe from:

await bfx.wss.unsubscribe(sub_id="f2757df2-7e11-4244-9bb7-a53b7343bef8")

Setting a custom sub_id

The client generates a random sub_id for each subscription.
These values must be unique, as the client uses them to identify subscriptions.
However, it is possible to force this value by passing a custom sub_id to BfxWebSocketClient::subscribe:

await bfx.wss.subscribe("candles", key="trade:1m:tBTCUSD", sub_id="507f1f77bcf86cd799439011")

Listening to events

Whenever the WebSocket client receives data, it will emit a specific event.
Users can either ignore those events or listen for them by registering callback functions.
These callback functions can also be asynchronous; in fact the client fully supports coroutines (asyncio).

To add a listener for a specific event, users can use the decorator BfxWebSocketClient::on:

@bfx.wss.on("candles_update")
def on_candles_update(sub: subscriptions.Candles, candle: Candle):
    print(f"Candle update for key <{sub['key']}>: {candle}")

The same can be done without using decorators:

bfx.wss.on("candles_update", callback=on_candles_update)

Advanced features

Using custom notifications

Using custom notifications requires user authentication.

Users can send custom notifications using BfxWebSocketClient::notify:

await bfx.wss.notify({ "foo": 1 })

Any data can be sent along with a custom notification.

Custom notifications are broadcast by the server on all user's open connections.
So, each custom notification will be sent to every online client of the current user.
Whenever a client receives a custom notification, it will emit the notification event:

@bfx.wss.on("notification")
def on_notification(notification: Notification[Any]):
    print(notification.data) # { "foo": 1 }

Examples

Creating a new order

import os

from bfxapi import Client, WSS_HOST

from bfxapi.types import Notification, Order

bfx = Client(
    wss_host=WSS_HOST,
    api_key=os.getenv("BFX_API_KEY"),
    api_secret=os.getenv("BFX_API_SECRET")
)

@bfx.wss.on("authenticated")
async def on_authenticated(_):
    await bfx.wss.inputs.submit_order(
        type="EXCHANGE LIMIT", symbol="tBTCUSD", amount=0.165212, price=30264.0)

@bfx.wss.on("order_new")
def on_order_new(order: Order):
    print(f"Successful new order for {order.symbol} at {order.price}$.")

@bfx.wss.on("on-req-notification")
def on_notification(notification: Notification[Order]):
    if notification.status == "ERROR":
        raise Exception(f"Something went wrong: {notification.text}")

bfx.wss.run()

How to contribute

All contributions are welcome! :D

A guide on how to install and set up bitfinex-api-py's source code can be found here.
Before opening any pull requests, please have a look at Before Opening a PR.
Contributors must uphold the Contributor Covenant code of conduct.

Index

  1. Installation and setup
  2. Before opening a PR
  3. License

Installation and setup

A brief guide on how to install and set up the project in your Python 3.8+ environment.

Cloning the repository

git clone https://github.com/bitfinexcom/bitfinex-api-py.git

Installing the dependencies

python3 -m pip install -r dev-requirements.txt

Make sure to install dev-requirements.txt (and not requirements.txt!).
dev-requirements.txt will install all dependencies in requirements.txt plus any development dependency.
dev-requirements includes mypy, black, isort, flake8, and pre-commit (more on these tools in later chapters).

All done, your Python 3.8+ environment should now be able to run bitfinex-api-py's source code.

Set up the pre-commit hooks (optional)

Do not skip this paragraph if you intend to contribute to the project.

This repository includes a pre-commit configuration file that defines the following hooks:

  1. isort
  2. black
  3. flake8

To set up pre-commit use:

python3 -m pre-commit install

These will ensure that isort, black and flake8 are run on each git commit.

Visit this page to learn more about git hooks and pre-commit.

Manually triggering the pre-commit hooks

You can also manually trigger the execution of all hooks with:

python3 -m pre-commit run --all-files

Before opening a PR

We won't accept your PR or we'll request changes if the following requirements aren't met.

Wheter you're submitting a bug fix, a new feature or a documentation change, you should first discuss it in an issue.

You must be able to check off all tasks listed in PULL_REQUEST_TEMPLATE before opening a pull request.

Tip

Setting up the project's pre-commit hooks will help automate this process (more).

License

Copyright 2023 Bitfinex

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

bitfinex-api-py's People

Contributors

davi0k avatar davi0kprogramsthings avatar fintzd avatar hajdbo avatar itsdeka avatar jacobplaster avatar jsphon avatar matthewli1409 avatar nkasimova avatar ph4z avatar prdn avatar richardhoekstra avatar robertkowalski avatar songaal avatar straussmaximilian avatar sturgelose avatar vigan-abd avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

bitfinex-api-py's Issues

How do I close a client.ws conection?

I don't know how to close my websocket connection, so in case of an exception the program shuts down for being able to run again.

Here is a simplified version of code

I just want to open the connection, wait a few seconds and then close it

bfx = Client(API_KEY, API_SECRET)

@bfx.ws.on('all')
async def log_updates(notification):
      print(notification)

bfx.ws.run()
time.sleep(5)
bfx.ws.stop()

Can somebody tell me how to do this? I'm new to programming and have tried lots of stuff unsuccessfully

maintain available balance

Since release of ws v2 I'm trying to maintain real time availabe balance, since bitfinex is the only exchange worldwide that does not provide this in real time websocket. (Calling every av. balance via websocket takes over 1 minute, so maintaining it myself is the only way to go).
Beside being very very hard and complex, I still did not find any solution that works for all possible events.
Unfortunately neither the support, nor paolo itself were able or had the time to really answer the problems I showed them. I hope with releasing this libary, they finally solve this.

I think, that my current solution (that works nearly perfect) is already too complicated and there must be an easier way. So I ask you to provide code to maintain av. balance in all cases. If you can't, I can provide you my code and show you in which cases it still fails, so you can fix your websocket API.

ws.submit_order returning none

Issue type

  • bug
  • missing functionality
  • performance
  • [ x] feature request

Brief description

Suppose I want to market buy BTC and then set stops depending on the amount I was filled at. If we consider the code from the example

await bfx.ws.submit_order('tBTCUSD', 0, 1, 'EXCHANGE MARKET')

Then since submit_order is returning None, the only way I see to get this information is to use a callback with the 'order_confirmed' decorator as follows:

@bfx.ws.on('order_confirmed')
async def trade_completed(order):
   # use order info

async def submit_order(auth_message):
    x = await bfx.ws.submit_order('tBTCUSD', 0, 0.0008, 'EXCHANGE MARKET')
   # How to use information from trade_completed

Now the issue I am having with this is, how can we pass the information received by trade_completed to submit_order? IIRC global variables do not work with asyncio. The only way would be to wrap all these co routines in a class but then one cannot use the decorators.

Am I missing something here?

Steps to reproduce

Additional Notes:

How to know if an order is successfully submitted?

Issue type

  • bug
  • missing functionality
  • performance
  • feature request

Brief description

In websocket, the submit_order function doesn't have return value. For example, if I submit a buy order where the price times amount exceeds the wallet balance, the submission will fail, and it will not trigger order_confirmed call back. What is the best way to know whether the order is successfully submitted?

Missing ws.*_funding_offer

Issue type

  • bug
  • missing functionality
  • performance
  • feature request

Brief description

Apparently, there are no functions for creating/updating funding offers via WS? Thanks!

Can't close small position

Issue type

  • bug
  • missing functionality
  • performance
  • feature request

Brief description

I can no more close a position if amount is < min order size.
Even if the close flag is activated.
It seems like API server ignore the flag or flag computation is wrong.

Steps to reproduce

Open a position, reduce it until it is < min order size.
Send an order with close=True
Receive the exception message: order < min order size

Additional Notes:

As far as I remember I did not had this issue in the past.

How to know the available balance of a wallet?

Issue type

  • bug
  • missing functionality
  • performance
  • feature request

Brief description

In both REST and WebSocket, get_wallets returns the total balance of each wallet. In case I have a pending buy order, how to know the available balance of a wallet?

can't register atexit after shutdown thrown in Python 3.9

Issue type

  • bug
  • missing functionality
  • performance
  • feature request

Brief description

Example code doesn't run since Python 3.9.

Steps to reproduce

  • Run any example code with Python 3.9 installed
Additional Notes:
  • Error "can't register atexit after shutdown" is thrown.

Dependency versions not specified in setup.py

When installing bitfinex-api-py from PyPI via pip, it fetches the wrong versions of dependencies. E.g. pyee-8.0.1 (wrong), which has a different API than pyee-5.0.0 (specified in requirements.txt).

If you want the package to work when installed from PyPI, you need to also specify dependency versions in setup.py. This page recommends specifying loose version bounds, but apparently you can also use ==.

Execute trade on candle close

Issue type

  • bug
  • missing functionality
  • performance
  • feature request

Brief description

I am studying the provided examples and have some trouble understanding what the best practices are with asyncio.

Specifically, I would like to be able to get the information on a candle close (no intermediary data required) and be able to execute a trade as soon as the candle is completed.

Right now the subscription seems to be returning the last (completed) candle as well as partial updates on the currently running candle.

Given that there is no current timestamp data, I don't see a way that is either non-hacky or sacrifices latency to achieve the desired goal.

Can anybody show an example how this could be effectively done with the ws api? I.e an event that can get executed as soon as one has complete information on the current candle?

Steps to reproduce

Additional Notes:

incompatible with latest version of pyee 8.X.X

Since pyee version 8.X.X EventEmitter for asyncio has now been replaced with AsyncIOEventEmitter

Current bitfinex-api-py has not been updated thus returns error

 File "/home/user/.pyenv/versions/3.8.6/lib/python3.8/site-packages/bitfinex_api_py-1.1.8-py3.8.egg/bfxapi/websockets/generic_websocket.py", line 60, in _start_event_worker
    return EventEmitter(scheduler=asyncio.ensure_future)
TypeError: __init__() got an unexpected keyword argument 'scheduler'

from pyee

           'pyee.EventEmitter is deprecated and will be removed in a future '
            'major version; you should instead use either '
            'pyee.AsyncIOEventEmitter, pyee.TwistedEventEmitter, '
            'pyee.ExecutorEventEmitter, pyee.TrioEventEmitter, '
            'or pyee.BaseEventEmitter.'

https://github.com/jfhbrook/pyee/blob/358fb04d76ac5857a6685bc0b34a2ccfa6d9fb43/pyee/_compat.py#L35

Generate Table of contents in docs

Issue type

  • feature request

Brief description

The nodejs docs have a nice TOC generated via JSdocs, unfortunately python does not have this so we may need to create a script to do this automatically

Steps to reproduce

Additional Notes:

Problem with Example

Issue type

  • [x ] bug
  • missing functionality
  • performance
  • feature request

Brief description

Hi @ all,

i tried to get the example to work:

import os
import sys
sys.path.append('../../../')

from bfxapi import Client

bfx = Client(
  logLevel='DEBUG',
  # Verifies that the local orderbook is up to date
  # with the bitfinex servers
  manageOrderBooks=True
)

@bfx.ws.on('error')
def log_error(err):
  print ("Error: {}".format(err))

@bfx.ws.on('order_book_update')
def log_update(data):
  print ("Book update: {}".format(data))

@bfx.ws.on('order_book_snapshot')
def log_snapshot(data):
  print ("Initial book: {}".format(data))

async def start():
  await bfx.ws.subscribe('book', 'tBTCUSD')
  # bfx.ws.subscribe('book', 'tETHUSD')

bfx.ws.on('connected', start)
bfx.ws.run()

i got the error:

Traceback (most recent call last):
  File "C:/........../btx.py", line 11, in <module>
    manageOrderBooks=True
  File "C:\............\Python\Python37-32\lib\site-packages\bfxapi\client.py", line 26, in __init__
    ws_capacity=ws_capacity, create_event_emitter=create_event_emitter, *args, **kwargs)
  File "C:\..............\Python\Python37-32\lib\site-packages\bfxapi\websockets\bfx_websocket.py", line 168, in __init__
    super(BfxWebsocket, self).__init__(host, logLevel=logLevel, *args, **kwargs)
  File "C:\..............\Python\Python37-32\lib\site-packages\bfxapi\websockets\generic_websocket.py", line 80, in __init__
    self.events = create_ee()
  File "C:\...............\Python\Python37-32\lib\site-packages\bfxapi\websockets\generic_websocket.py", line 60, in _start_event_worker
    return EventEmitter(scheduler=asyncio.ensure_future)
TypeError: __init__() got an unexpected keyword argument 'scheduler'

Can someone help me? I am using python 3.7

How to post a SELL order via ws?

Issue type

Missing functionality

Brief description

I am trying to place a "SELL" order, but it's not working

Steps to reproduce

  • Using the Order model, via WS, create an order like: await bfx.ws.submit_order('tBTCUSD', 10944, 0.01, Order.Side.SELL)
  • Log out the order in async def trade_completed(order):
  • It's placed a buy order

[BfxWebsocket] [ERROR] Notification ERROR: price_aux_limit: invalid

Issue type

  • bug
  • missing functionality
  • performance
  • feature request

Brief description

I am attempting to use the bfx.ws.submit_order function to place an order.
It appears that it is impossible to place an exchange stop limit buy order. No matter what value is provided for the price_aux_limit parameter the API returns the error:

[BfxWebsocket] [ERROR] Notification ERROR: price_aux_limit: invalid

I tried a decimal value greater than the price, equal to the price, less than the price, a very small value (assuming it might be a delta to the price) and even None as well as a negative value.

Please add a possibility to submit exchange stop limit buy order via the python api.

Steps to reproduce

call:

bfx.ws.submit_order(symbol='tBTCUSD', price=8500.5, price_aux_limit=8501.5, amount=0.001, market_type=Order.Type.EXCHANGE_STOP_LIMIT))

from a successfully authenticated websocket client.

Additional Notes:
  • I am having great difficulty infering the correct call signatures for any type of order from the provided API documentation. Example code for each type of allowed order would be extremely helpful.

Issue when using is_subscribed()

Issue type

  • [x ] bug
  • missing functionality
  • performance
  • feature request

here is the code:

@bfx_ws.on('all')
def bfxws_data_handler(data):
    if type(data) is list:
        dataEvent = data[1]
        chan_id = data[0]

        if type(dataEvent) is not str and bfx_ws.subscriptionManager.is_subscribed(chan_id):
            sub = bfx_ws.subscriptionManager.get(chan_id)
            if sub.channel_name == 'ticker':
                payload = {
                    'symbol': sub.symbol[1:],
                    'data': dataEvent[4:],
                }
                logger.debug(f'{sub.symbol} - ticker event')
                logger.info(f'{payload}')
    else:
        self.logger.info(f'bfx-info: {data}')

Brief description

This is the error I'm getting from terminal:
UnboundLocalError: local variable 'p_sub' referenced before assignment

Steps to reproduce

Additional Notes:

I tried and look at the source code, I see that p_sub is called and declare in confirm_subscription and is_subscibed() doesnt call that function or have anything related to it so why am I getting the error. I'm I missing something?
Sorry if this is not an issue and just my fault. If it is my fault please kindly show me how it should be done. Thank you!

wallet API returning complete data

Issue type

  • bug
  • missing functionality
  • performance
  • [ x] feature request

Brief description

From the wallet ws example (https://github.com/bitfinexcom/bitfinex-api-py/blob/master/bfxapi/examples/ws/wallet_balance.py) it seems that it is only possible to see the balance/unsettled amount in each wallet.

Is there any chance the API could be changed so that one also gets the remaining fields, most yimportantly the available balance?

Steps to reproduce

Additional Notes:

from_raw_order not found error

Issue type

  • bug
  • missing functionality
  • performance
  • feature request

Brief description

I'm have installed the latest package version bitfinex-api-py (1.1.3). Run the rest example in: bitfinex-api-py/bfxapi/examples/rest/create_order.py /
Get error: from_raw_order not found error

Steps to reproduce

-run the example: bitfinex-api-py/bfxapi/examples/rest/create_order.py /

Additional Notes:
  • seemed to have been fixed in code modification #43, not still not working

rest, submit_order, error "Notification' has no attribute 'from_raw_order"

Trying to put new order , get an error below:
...bfxapi\rest\bfx_rest.py", line 546, in submit_order
AttributeError: type object 'Notification' has no attribute 'from_raw_order'

Unfortunately, I'm not enough experience to understand what the problem is.
I will be grateful for the help.

My code:
async def bf_rest_stream():
bfx_rest = Client(
API_KEY='',
API_SECRET=''
)
time.sleep(2)

while True:
        for key in copy_start_orders:

            up_order = copy_start_orders[key]
            
            if up_order.eid is False:
                print('Sending new order from BF WS: ' + str(up_order))
                response = await bfx_rest.rest.submit_order(pair, up_order.price, up_order.quantity,
                                                       up_order.order_type, up_order.hidden,
                                                       gid=up_order.gid)
                for o in response.notify_info:
                    print("Order: ", o)
            
        start_orders.clear()
    time.sleep(1)

Automatically reconnects to unsubscribed channels

Issue type

  • bug
  • missing functionality
  • performance
  • feature request

Brief description

After a WS disconnection (code 1006), BfxWebsocket automatically resubscribes to all channels, but the problem is it will also resubscribe to channels that were previously unsubscribed explicitly.

Steps to reproduce

  1. Subscribe to an orderbook, and then unsubscribe with await client.ws.unsubscribe(self.channel).
  2. Wait for a disconnection. Due to high volumes these days, disconnections are happening many times a day.
  3. Whatever function is set to run on client.ws.on('order_book_update') will start processing messages from the unsubscribed channel again.
Additional Notes:

I thought removing the channel_id manually from the subscription manager might work, but it gives me a KeyError:

await self.ws.unsubscribe(self.channel)
del(self.ws.subscriptionManager.subscriptions_chanid[self.channel])

Support pip installation

The best way to package and distribute a python package is through pip. Currently, the API does not support that as it doesn't provide a setup.py
Packaging projects in python: https://packaging.python.org/tutorials/packaging-projects/

There are also other minor warnings like:

warning: the following paths have collided (e.g. case-sensitive paths on 
a case-insensitive filesystem) and only one from the same colliding group 
is in the working tree:

  'bfxapi/Client.py'
  'bfxapi/client.py'
  'bfxapi/models/Order.py'
  'bfxapi/models/order.py'
  'bfxapi/models/Position.py'
  'bfxapi/models/position.py'
  'bfxapi/models/Subscription.py'
  'bfxapi/models/subscription.py'
  'bfxapi/models/Trade.py'
  'bfxapi/models/trade.py'
  'bfxapi/models/Wallet.py'
  'bfxapi/models/wallet.py'

Repro:

  • Execute pip install git+https://github.com/bitfinexcom/bitfinex-api-py.git

Balances are slow receiving information

Issue type

  • bug
  • missing functionality
  • [ x] performance
  • feature request

Brief description

When a change occurs in my wallet, it takes me about 5 seconds to receive the information using websocket. Why? The order book for example is fast but the balance of the wallet is slow. Is it api or server problem?

Thank you.

Failed to reauth and resub after reconnection

Issue type

  • bug
  • missing functionality
  • performance
  • feature request

Brief description

When running an authenticated websocket client, in case of deconnection, client is able to reconnect but not to re-authenticate and resubscribe to preivously subscribed channels.

Steps to reproduce

python bfxapi/examples/ws/wallet_balance.py &
netstat -lataupen | grep 443 # Look for the remote api ip address
ip route add blackhole ipaddress/32 # Add a blakhole route to api
After few seconds client will connect to a new ip address but not reauthenticate and resubscribe

Additional Notes:

Missing LedgerID

Hello!
I try use get_legers method but in current release i can't receive ID field.
Can you help me?
I have fix for this:
ledger.zip

Wallet available balances are always returning "None"

with the endpoint:
v2/auth/r/wallets

['funding', 'BTC', 2.71e-06, 0, None, None, None]
['funding', 'DSH', 1.94321047, 0, None, None, None]
['funding', 'JPY', 5510.94389166, 0, None, None, None]
['funding', 'TRX', 54, 0, None, None, None]
['funding', 'UST', 91.08264069, 0, None, None, None]
['exchange', 'BTC', 5.7e-07, 0, None, None, None]
['exchange', 'BTG', 0.006, 0, None, None, None]
['exchange', 'BTT', 0.89512506, 0, None, None, None]
['exchange', 'JPY', -1e-08, 0, None, None, None]
['exchange', 'USD', 5.714e-05, 0, None, None, None]
['exchange', 'UST', 0.00472941, 0, None, None, None]

Checksum Error for order_book for Funding

I change subscribe_orderbook.py to track BTC interest by changing line 27 with:
await bfx.ws.subscribe('book', 'fBTC')
but get got such an error:

...
...
...
[BfxWebsocket] [DEBUG] [10614,[0.00008744,2,18,55.61031005]]
Book update: {'symbol': 'fBTC', 'data': [8.744e-05, 2, 18, 55.61031005]}
[BfxWebsocket] [DEBUG] [10614,"cs",-809501394]
[BfxWebsocket] [WARNING] Checksum orderbook invalid for 'fBTC'. Resetting subscription.
[BfxWebsocket] [DEBUG] {"event":"unsubscribed","status":"OK","chanId":10614}
[BfxWebsocket] [DEBUG] {"event":"subscribed","channel":"book","chanId":10615,"symbol":"fBTC","prec":"P0","freq":"F0","len":"25","currency":"BTC"}
Traceback (most recent call last):
  File "Fundbot.py", line 40, in <module>
    bfx.ws.run()
  File "/home/death/Desktop/BotTerest/bitfinex-api-py/bfxapi/websockets/GenericWebsocket.py", line 51, in run
    self.loop.run_until_complete(self._main(self.host))
  File "/usr/lib/python3.7/asyncio/base_events.py", line 584, in run_until_complete
    return future.result()
  File "/home/death/Desktop/BotTerest/bitfinex-api-py/bfxapi/websockets/GenericWebsocket.py", line 75, in _main
    await self._connect(host)
  File "/home/death/Desktop/BotTerest/bitfinex-api-py/bfxapi/websockets/GenericWebsocket.py", line 66, in _connect
    await self.on_message(message)
  File "/home/death/Desktop/BotTerest/bitfinex-api-py/bfxapi/websockets/BfxWebsocket.py", line 369, in on_message
    await self._ws_system_handler(msg)
  File "/home/death/Desktop/BotTerest/bitfinex-api-py/bfxapi/websockets/BfxWebsocket.py", line 151, in _ws_system_handler
    await self._WS_SYSTEM_HANDLERS[eType](msg)
  File "/home/death/Desktop/BotTerest/bitfinex-api-py/bfxapi/websockets/BfxWebsocket.py", line 195, in _system_subscribed_handler
    await self.subscriptionManager.confirm_subscription(data)
  File "/home/death/Desktop/BotTerest/bitfinex-api-py/bfxapi/websockets/SubscriptionManager.py", line 59, in confirm_subscription
    p_sub = self.pending_subscriptions[get_key]
KeyError: 'book_fBTC'

order not working properly

Issue type

  • bug
  • missing functionality
  • performance
  • feature request

Brief description

I submitted an order to test, I put an order for 12 XPR at 0.22, but somehow it executed at 0.25462 (see first and last line of attached).

Any idea on how to fix it?

Also, how do I sell? I can't find an example how how to place a sell order

Additional Notes:

image

Example doesn't run in Python 3.8

Issue type

  • bug
  • missing functionality
  • performance
  • feature request

Brief description

I ran on python 3.8 the following example code (authenticate):

import os
import sys
from bfxapi import Client, Order


bfx = Client(
  API_KEY='<YOUR_API_KEY>',
  API_SECRET='<YOUR_API_SECRET>'
)

@bfx.ws.on('authenticated')
async def do_something():
  print ("Success!")

bfx.ws.run()

I got this error

Traceback (most recent call last):
  File "crypto_trader.py", line 3, in <module>
    from bfxapi import Client, Order
  File "/home/rht/github/repos/bitfinex-api-py/bfxapi/__init__.py", line 6, in <module>
    from .client import Client
  File "/home/rht/github/repos/bitfinex-api-py/bfxapi/client.py", line 8, in <module>
    import asyncio
  File "/home/rht/code/venv/lib/python3.8/site-packages/asyncio/__init__.py", line 21, in <module>
    from .base_events import *
  File "/home/rht/code/venv/lib/python3.8/site-packages/asyncio/base_events.py", line 296
    future = tasks.async(future, loop=self)
                   ^
SyntaxError: invalid syntax

The fix is to not install asyncio on Python 3.8. There is a syntax for requirements.txt / setup.py as described in https://pip.pypa.io/en/stable/reference/pip_install/#requirement-specifiers, namely
asyncio==3.4.3;python_version<'3.8'

Cannot place trailing-stop orders via REST API v2

Issue type

  • missing functionality
  • feature request

Brief description

It appears to be impossible to place a trailing-stop order via the REST API v2 in Python
We have a full-fledged application implementing your REST API v2 and we could not figure out a way to place trailing-stop orders.
Please let us know at your earliest convenience if there is a way to place a trailing-stop order from this context.

Steps to reproduce

  • Place a trailing-stop order via the Bitfinex REST API v2 in Python
Additional Notes:
  • if there is no possibility to place a trailing-stop please provide an ETA for this functionality. Would love to keep using Bitfinex but need this functionality.

Thank you very much! I look forward to hearing from you soon.

Failed authentication after reconnect

Hello,

Some times i get error "asyncio:Fatal error on SSL transport", after that reconnection is initialized. But, if I trying put new order I get authentication error.

Error: (socketId=0) Failed authentication - auth: invalid

SSL transport error:

[BfxOrderManager] [INFO] Update Order order_id=37344025432 dispatched
ERROR:asyncio:Fatal error on SSL transport
protocol: <asyncio.sslproto.SSLProtocol object at 0x0548CD18>
transport: <_ProactorSocketTransport fd=1160 read=<_OverlappedFuture pending overlapped=<pending, 0x7182de8> cb=[_ProactorReadPipeTransport._loop_reading()]> write=<_OverlappedFuture finished result=31> write_bufsize=117>
Traceback (most recent call last):
File "C:\Program Files (x86)\Python38-32\lib\asyncio\sslproto.py", line 698, in _process_write_backlog
del self._write_backlog[0]
IndexError: deque index out of range
ERROR:websockets.protocol:Error in data transfer
Traceback (most recent call last):
File "C:\Program Files (x86)\Python38-32\lib\site-packages\websockets\protocol.py", line 674, in transfer_data
message = yield from self.read_message()
File "C:\Program Files (x86)\Python38-32\lib\site-packages\websockets\protocol.py", line 742, in read_message
frame = yield from self.read_data_frame(max_size=self.max_size)
File "C:\Program Files (x86)\Python38-32\lib\site-packages\websockets\protocol.py", line 815, in read_data_frame
frame = yield from self.read_frame(max_size)
File "C:\Program Files (x86)\Python38-32\lib\site-packages\websockets\protocol.py", line 880, in read_frame
frame = yield from Frame.read(
File "C:\Program Files (x86)\Python38-32\lib\site-packages\websockets\framing.py", line 99, in read
data = yield from reader(2)
File "C:\Program Files (x86)\Python38-32\lib\asyncio\streams.py", line 723, in readexactly
await self._wait_for_data('readexactly')
File "C:\Program Files (x86)\Python38-32\lib\asyncio\streams.py", line 517, in _wait_for_data
await self._waiter
File "C:\Program Files (x86)\Python38-32\lib\asyncio\sslproto.py", line 698, in _process_write_backlog
del self._write_backlog[0]
IndexError: deque index out of range
[BfxWebsocket] [ERROR] WebSocket connection is closed: code = 1006 (connection closed abnormally [internal]), no reason
[BfxWebsocket] [INFO] Waiting 5 seconds before retrying...

My code for new order:
bfx = Client(
API_KEY=API_KEY,
API_SECRET=API_SECRET,
logLevel='INFO'
)
@bfx.ws.on('authenticated')
async def handle_events(self):
while True:

                if up_order.eid is False:
                    
                    response = await bfx.ws.submit_order(pair, up_order.price, up_order.quantity,
                                                         up_order.order_type, up_order.hidden,
                                                         gid=up_order.gid)
                else:
                    
                    response = await bfx.ws.update_order(up_order.eid, price=up_order.price,
                                                         amount=up_order.quantity, hidden=up_order.hidden)

Collisions on case sensitive systems

warning: the following paths have collided (e.g. case-sensitive paths on 
a case-insensitive filesystem) and only one from the same colliding group 
is in the working tree:

  'bfxapi/Client.py'
  'bfxapi/client.py'
  'bfxapi/models/Order.py'
  'bfxapi/models/order.py'
  'bfxapi/models/Position.py'
  'bfxapi/models/position.py'
  'bfxapi/models/Subscription.py'
  'bfxapi/models/subscription.py'
  'bfxapi/models/Trade.py'
  'bfxapi/models/trade.py'
  'bfxapi/models/Wallet.py'
  'bfxapi/models/wallet.py'

Tickers events and snapshots

Hi,

I have seen that it is possible to subscribe to tickers, but I cannot see in the documentation the event names for new tickers and to get a initial snapshot. Are these events already implemented?

Thanks

Client disconnect after few seconds when subscribing to order book channels

Issue type

  • bug
  • missing functionality
  • performance
  • feature request

Brief description

Client disconnect after few seconds when subscribing to order book channels

Steps to reproduce

Just subscribe to an order book channel and wait for a socket disconnection message like:
"[BfxWebsocket] [ERROR] code = 1006 (connection closed abnormally [internal]), no reason"

Additional Notes

It happens only to this particular public channel, other channels like ticker, candles and trades are apparently OK.

Withdrawal endpoint

Hi.

I can not find the implementation of withdrawal rest endpoint for v1 or equivalent for v2.
Will these methods be implemented in the future?
If the method exists, show the sample code please.

example get authenticated endpoints does not work

Issue type

  • bug
  • missing functionality
  • performance
  • feature request

Brief description

the example get rest authenticated endpoints produces an error

Steps to reproduce

Traceback (most recent call last):
File "trade/bitfinex_api_py/get_authenticated_data.py", line 63, in
asyncio.get_event_loop().run_until_complete(t)
File "/usr/lib/python3.5/asyncio/base_events.py", line 466, in run_until_complete
return future.result()
File "/usr/lib/python3.5/asyncio/futures.py", line 293, in result
raise self._exception
File "/usr/lib/python3.5/asyncio/tasks.py", line 239, in _step
result = coro.send(None)
File "trade/bitfinex_api_py/get_authenticated_data.py", line 57, in run
await log_active_positions()
File "trade/bitfinex_api_py/get_authenticated_data.py", line 38, in log_active_positions
positions = await bfx.rest.get_active_position()
File "/home/jklock/crypto/env/lib/python3.5/site-packages/bfxapi/rest/bfx_rest.py", line 259, in get_active_position
return [Position.from_raw_rest_position(rp) for rp in raw_positions]
File "/home/jklock/crypto/env/lib/python3.5/site-packages/bfxapi/rest/bfx_rest.py", line 259, in
return [Position.from_raw_rest_position(rp) for rp in raw_positions]
File "/home/jklock/crypto/env/lib/python3.5/site-packages/bfxapi/models/position.py", line 41, in from_raw_rest_position
return Position(*raw_position)
TypeError: init() takes 11 positional arguments but 21 were given

Additional Notes:
  • I use the bitfinex-api-py (1.1.4)

REST v2 missing symbol_details (not this library)

Issue type

  • bug
  • missing functionality
  • performance
  • feature request

Brief description

The REST API v2 of bitfinex currently lacks a way to receive all relevant pair informations. Every single other exchange has such a call, but not bitfinex. I know the "Configs" (https://docs.bitfinex.com/reference#rest-public-conf), but the only promissing call, which is "pub:info:pair" is WIP and lacks alot of information.
Please take my feedback and transform "pub:info:pair" into the perfect call to get all the information I'm looking for.

What I want to get from such a call (now only talking about exchange/spot trading):

  • All pairs traded on the exchange with status (if they are trading or halted/post_only/cancel_only or whatever. If bitfinex does not have those stati, you should implement them, since a serious exchange needs them).
  • Assigned to each of these pairs, I need the base and the quote currency of each pair. Bitfinex does not use a seperator like "BTC_EUR", instead the pairs look like "tBTCEUR". In addition it is not guranteed that a pair always has 6 characters after this "t". That means it is impossible for the user to automatically identify the currencies involved in a pair. So you need to return this in an API call.
  • In addition, I need all the trading details, like: min/max ordersize/quotesize/price and precision of price and also of amounts. (I think currently bitfinex has no "min/max quotesize". But I think it should implement it in exchange for min/max order sizes. minquotes fit much better for volatile cryptos.)

Steps to reproduce

Additional Notes:
  • Feel free to contact me for more detailed feedback. I'm trading at over 15 other crypto exchanges since years and implemented their API. I think I know very well what a daytrader using REST needs. Bitfinex was one of the first exchanges I traded manually, but is one of the last I trade via API, because all my feedback was ignored and the API was(/is?) quite bad compared to other exchanges.

Channel id collision

Issue type

  • [x ] bug
  • missing functionality
  • performance
  • feature request

Brief description

Hi, I am using WS client to collect Trades data via Public Channels (wss://api-pub.bitfinex.com/ws/2). I use 61 symbols and use one instance of the client. WS capacity is 7 to be in connection limits, therefore I have 9 connections.

Problem. When socket send "subscribe" message sometimes I receive "subscribed" messages with channel id, which I already have for the different symbol. It may occur in initial subscribe or after disconnect and subsequent "subscribe" message.
After that, I receive different data in one channel and only for one symbol because SubscriptionManager has dict indexed by chan_id.
What the logic of channel id? Is it unique for one connection?

Steps to reproduce

Additional Notes:

Some logs
websockets.protocol 2020-11-10 19:45:32,213 DEBUG 140165410432768: client > Frame(fin=True, opcode=1, data=b'{"event": "subscribe", "channel": "trades", "symbol": "tXTZBTC"}', rsv1=False, rsv2=False, rsv3=False)
websockets.protocol 2020-11-10 19:45:32,362 DEBUG 140170267449088: client < Frame(fin=True, opcode=1, data=b'{"event":"subscribed","channel":"trades","chanId":83819,"symbol":"tXTZBTC","pair":"XTZBTC"}', rsv1=False, rsv2=False, rsv3=False)
...
websockets.protocol 2020-11-10 19:45:32,789 DEBUG 140165410432768: client > Frame(fin=True, opcode=1, data=b'{"event": "subscribe", "channel": "trades", "symbol": "tTRXBTC"}', rsv1=False, rsv2=False, rsv3=False)
websockets.protocol 2020-11-10 19:45:32,871 DEBUG 140167591487232: client < Frame(fin=True, opcode=1, data=b'{"event":"subscribed","channel":"trades","chanId":83819,"symbol":"tTRXBTC","pair":"TRXBTC"}', rsv1=False, rsv2=False, rsv3=False)
...
websockets.protocol 2020-11-10 19:45:36,391 DEBUG 140167591487232: client < Frame(fin=True, opcode=1, data=b'[83819,"te",[521283606,1605026736336,-83.67221784,0.00000163]]', rsv1=False, rsv2=False, rsv3=False)
...
websockets.protocol 2020-11-10 19:51:28,294 DEBUG 140170267449088: client < Frame(fin=True, opcode=1, data=b'[83819,"te",[521383524,1605027088238,-1.03423172,0.0001397]]', rsv1=False, rsv2=False, rsv3=False)

Get_active_position isn't working

await bfx.rest.get_active_position() causes:
Error: init() takes 11 positional arguments but 21 were given

Also, does someone know how to handle Unknown data event: 'pu' outside the @bfx.ws.on('all') handler??

Handle 'pu' messages on websocket API

Issue type

  • bug
  • missing functionality
  • performance
  • feature request

Brief description

You receive Unknown data event: 'pu' on each 'pu' message

Steps to reproduce

Additional Notes:

How to get current bitfinex datetime?

Hi!
I'm getting tickers like this:

async def work():

    while True:

        ticker = await bfx.rest.get_public_ticker('tBTCUSD')

        print("Ticker:")

        print(ticker)

        await asyncio.sleep(1)

loop = asyncio.get_event_loop()

try:

    asyncio.ensure_future(work())

    loop.run_forever()

except KeyboardInterrupt:

    pass

finally:

    print("Closing Loop")

    loop.close()

How can I get a ticker's datetime?

No event omited for ticker channel ws

Issue type

  • bug
  • missing functionality
  • performance
  • feature request

Brief description

There is no event omited to get the result of ws ticker channel

Steps to reproduce

Additional Notes:

100% CPU consumption on simply subscribing to trades/candles etc

Issue type

  • [1 ] performance

Brief description

Running a simple WS connection subscribing to a single tickers trades feed consumes 100% of CPU resources

Steps to reproduce

git clone repo
install
cd examples/ws
python subscribe_trades_candles.py
Additional Notes:

top [shift+m] to see cpu usage
pgrep -fa python to see pid
ps -o %cpu,%mem,cmd -p [pid] to see singe line cpu output

show term link:
http://showterm.io/69795ac847f5c37f599bb

Looks to be..

           await asyncio.sleep(0)

Personally I just changed this locally to sleep(0.01) and now my computer and breathe again and I dont have t o go to bed wondering if my computer will still be alive when i wake up

Candle snapshot event

Issue type

  • bug
  • missing functionality
  • performance
  • feature request

Brief description

I see that snapshot events are available for other types such as Orders, Wallets, etc. but there is no such event for Candles. Is there any plan to add that as an event, or am I missing something obvious?

Steps to reproduce

  • NA
Additional Notes:
  • NA

Websocket fails to connect

Issue type

  • bug
  • missing functionality
  • [ X] performance
  • feature request

Brief description

When trying to subscribe to the web-socket that gets the trade candles, the code occasionally crashes. Sometimes it failes to connect after 5 attempts, sometimes it manages to connect. More often than not it fails. Also this sometimes occur after running the code successfully for a short while.

Is the code somehow dependent on me be logged into the actual bitfinex website to connect the websocket?

Steps to reproduce

  • By running the subscribe_trades_candles.py example
Additional Notes:
[BfxWebsocket] [INFO] Websocket connected to wss://api-pub.bitfinex.com/ws/2
[BfxWebsocket] [INFO] {'event': 'info', 'version': 2, 'serverId': '412b8f9c-86a9-4c08-b5e9-beb797a79d3a', 'platform': {'status': 1}}
[BfxWebsocket] [INFO] Websocket opened.
[BfxSubscriptionManager] [INFO] Subscribing to channel candles
Fatal error on SSL transport
protocol: <asyncio.sslproto.SSLProtocol object at 0x7f8220c577d0>
transport: <_SelectorSocketTransport fd=16 read=polling write=<idle, bufsize=0>>
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/sslproto.py", line 668, in _process_write_backlog
    data, offset = self._write_backlog[0]
IndexError: deque index out of range
Unexpected exception in keepalive ping task
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/websockets/protocol.py", line 984, in keepalive_ping
    ping_waiter = yield from self.ping()
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/websockets/protocol.py", line 583, in ping
    yield from self.ensure_open()
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/websockets/protocol.py", line 646, in ensure_open
    ) from self.transfer_data_exc
websockets.exceptions.ConnectionClosed: WebSocket connection is closed: code = 1006 (connection closed abnormally [internal]), no reason
Error in data transfer
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/websockets/protocol.py", line 674, in transfer_data
    message = yield from self.read_message()
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/websockets/protocol.py", line 742, in read_message
    frame = yield from self.read_data_frame(max_size=self.max_size)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/websockets/protocol.py", line 815, in read_data_frame
    frame = yield from self.read_frame(max_size)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/websockets/protocol.py", line 884, in read_frame
    extensions=self.extensions,
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/websockets/framing.py", line 99, in read
    data = yield from reader(2)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/streams.py", line 679, in readexactly
    await self._wait_for_data('readexactly')
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/streams.py", line 473, in _wait_for_data
    await self._waiter
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/sslproto.py", line 668, in _process_write_backlog
    data, offset = self._write_backlog[0]
IndexError: deque index out of range

new_trade will be duplicated

Both trade_update and trade_executed will hit the following code:

@bfx.ws.on('new_trade')
def log_trade(trade):
    trade_queue.put(trade)

Therefore you will always get the trade duplicated. Update should be emitted on the update_trade events instead.

    async def _trade_update_handler(self, data):
        tData = data[2]
        # [209, 'tu', [312372989, 1542303108930, 0.35, 5688.61834032]]
        if self.subscriptionManager.is_subscribed(data[0]):
            symbol = self.subscriptionManager.get(data[0]).symbol
            tradeObj = _parse_trade(tData, symbol)
            ***self._emit('new_trade', tradeObj)***

    async def _trade_executed_handler(self, data):
        tData = data[2]
        # [209, 'te', [312372989, 1542303108930, 0.35, 5688.61834032]]
        if self.subscriptionManager.is_subscribed(data[0]):
            symbol = self.subscriptionManager.get(data[0]).symbol
            tradeObj = _parse_trade(tData, symbol)
            self._emit('new_trade', tradeObj)

Over time event emitter not labelling trades correctly.

Issue type

  • [ x] bug
  • missing functionality
  • performance
  • feature request

Brief description

When subscribing to multiple trades feeds all is working fine, but over time, the event emitter can end up putting the symbols / prices

Steps to reproduce


bfx = Client(
  logLevel='WARNING'
)
@bfx.ws.on('error')
def log_error(err):
  error("Error: {}".format(err))


@bfx.ws.on('new_trade')
def log_trade(trade):
  topic = trade['symbol']+'_trades'
  log_detail = "{}, {} - {} {} {}".format( DateUtils.miliseconds_to_datetime(trade['mts']).replace(microsecond=0), 
      topic,
      trade['symbol'], 
      trade['price'],
      trade['amount'] )

  print(log_detail)




async def start():
    for t in tickers:
        await bfx.ws.subscribe('trades', t['ticker_api_request'])

bfx.ws.on('connected', start)
bfx.ws.run()
Additional Notes:

Example output during disconnect outage

2020-06-25 16:55:07.328736  2020-06-25 15:55:07, tETHBTC_trades - tETHBTC 0.025294 -0.029 
2020-06-25 16:55:07.329235  2020-06-25 15:55:07, tETHBTC_trades - tETHBTC 0.025292 -0.03585639 
2020-06-25 16:55:23.332983  2020-06-25 15:55:23, tETHUSD_trades - tETHUSD 233.74 -2.8e-07 
2020-06-25 16:56:03.611476  2020-06-25 15:56:03, tEOSUSD_trades - tEOSUSD 9236.5686871 0.005 
^ EOS with a BTCUSD Price

2020-06-25 16:56:12.196299  2020-06-25 15:56:12, tETHUSD_trades - tETHUSD 233.76 2 
2020-06-25 16:56:12.196807  2020-06-25 15:56:12, tETHUSD_trades - tETHUSD 233.82 0.427799 
2020-06-25 16:56:12.197279  2020-06-25 15:56:12, tETHUSD_trades - tETHUSD 233.82 2.28567699 
2020-06-25 16:56:15.594217  2020-06-25 15:56:15, tEOSUSD_trades - tEOSUSD 9237.77438995 0.2 
^ EOS with a BTCUSD Price

2020-06-25 16:56:54.762407  2020-06-25 15:56:54, tXRPUSD_trades - tXRPUSD 0.18239 -50 
2020-06-25 16:57:34.358662  2020-06-25 15:57:34, tEOSUSD_trades - tEOSUSD 9237.77438995 0.005 
^ EOS with a BTCUSD Price

2020-06-25 16:57:35.401819  2020-06-25 15:57:35, tETHUSD_trades - tETHUSD 233.81725776 -0.02341478 
2020-06-25 16:57:37.010144  2020-06-25 15:57:36, tEOSUSD_trades - tEOSUSD 9237.72421007 -0.005 
2020-06-25 16:57:46.517429  2020-06-25 15:57:46, tETHUSD_trades - tETHUSD 233.81725776 -1.002946 
2020-06-25 16:57:47.279341  2020-06-25 15:57:47, tEOSUSD_trades - tEOSUSD 9237.77438995 0.005 
2020-06-25 16:57:56.695126  2020-06-25 15:57:56, tEOSUSD_trades - tEOSUSD 9237.77438995 0.025399 
2020-06-25 16:57:58.255911  2020-06-25 15:57:58, tEOSUSD_trades - tEOSUSD 9237.77438995 0.005 
2020-06-25 16:57:59.438746  2020-06-25 15:57:59, tEOSUSD_trades - tEOSUSD 9237.77438995 0.005 
2020-06-25 16:58:00.460332  2020-06-25 15:58:00, tLTCUSD_trades - tLTCUSD 42.586 -0.1 
2020-06-25 16:58:00.553624  2020-06-25 15:58:00, tXRPUSD_trades - tXRPUSD 0.18242 1245.3593 
2020-06-25 16:58:00.988011  2020-06-25 15:58:00, tXRPUSD_trades - tXRPUSD 0.18242 100.96765575 
2020-06-25 16:58:01.636211  2020-06-25 15:58:01, tXRPUSD_trades - tXRPUSD 0.18244 2203.44437108 
2020-06-25 16:58:12.873277  2020-06-25 15:58:12, tEOSUSD_trades - tEOSUSD 9237.72421007 -0.087 
2020-06-25 16:58:14.390358  2020-06-25 15:58:14, tEOSUSD_trades - tEOSUSD 9237.72421007 -0.25 
2020-06-25 16:58:18.367355  2020-06-25 15:58:18, tEOSUSD_trades - tEOSUSD 9237.72421007 -0.005 
2020-06-25 16:58:27.712325  2020-06-25 15:58:27, tEOSUSD_trades - tEOSUSD 9237.77438995 0.1 
2020-06-25 16:58:51.302180  2020-06-25 15:58:51, tEOSUSD_trades - tEOSUSD 9237.77438995 0.00406 
2020-06-25 16:58:56.483467  2020-06-25 15:58:56, tEOSUSD_trades - tEOSUSD 9237.77438995 0.00758921 
2020-06-25 16:59:20.655391  2020-06-25 15:59:20, tEOSUSD_trades - tEOSUSD 9238.50964496 -0.0006003 
[BfxWebsocket] [ERROR] WebSocket connection is closed: code = 1001 (going away), reason = CloudFlare WebSocket proxy restarting
2020-06-25 16:59:42.253479  Error: (socketId=0) Already Subscribed - subscribe: dup 
2020-06-25 16:59:42.253685  Error: (socketId=0) Already Subscribed - subscribe: dup 
2020-06-25 16:59:42.253760  Error: (socketId=0) Already Subscribed - subscribe: dup 
2020-06-25 16:59:42.253822  Error: (socketId=0) Already Subscribed - subscribe: dup 
2020-06-25 16:59:42.253879  Error: (socketId=0) Already Subscribed - subscribe: dup 
2020-06-25 16:59:42.253938  Error: (socketId=0) Already Subscribed - subscribe: dup 
..
2020-06-25 16:59:42.299748  Error: (socketId=0) Already Subscribed - subscribe: dup 
2020-06-25 16:59:42.299788  Error: (socketId=0) Already Subscribed - subscribe: dup 
2020-06-25 16:59:42.299828  Error: (socketId=0) Already Subscribed - subscribe: dup 
2020-06-25 16:59:42.299868  Error: (socketId=0) Already Subscribed - subscribe: dup 
2020-06-25 16:59:53.105075  2020-06-25 15:59:53, tEOSUSD_trades - tEOSUSD 2.4841 125.72123908 
2020-06-25 17:00:02.238756  2020-06-25 16:00:02, tETHUSD_trades - tETHUSD 9238.50964496 -0.013316 
^ ETH with a BTCUSD Price

2020-06-25 17:00:03.650980  2020-06-25 16:00:03, tXMRUSD_trades - tXMRUSD 64.811 0.96 
2020-06-25 17:00:08.076672  2020-06-25 16:00:08, tETHUSD_trades - tETHUSD 9238.6 0.0013 
2020-06-25 17:00:08.077088  2020-06-25 16:00:08, tETHUSD_trades - tETHUSD 9238.6 0.0013 
2020-06-25 17:00:08.085816  2020-06-25 16:00:08, tETHUSD_trades - tETHUSD 9238.6 0.0013 
^ ETH with a BTCUSD Price

2020-06-25 17:00:08.086223  2020-06-25 16:00:08, tETHUSD_trades - tETHUSD 9238.6 0.0011 
2020-06-25 17:00:10.240429  2020-06-25 16:00:10, tETHUSD_trades - tETHUSD 9238.6 0.0002 
2020-06-25 17:00:10.240850  2020-06-25 16:00:10, tETHUSD_trades - tETHUSD 9238.6 0.0048 
2020-06-25 17:00:10.585936  2020-06-25 16:00:10, tETHUSD_trades - tETHUSD 9238.6 0.0066 

get_public_trades stalls forever

Issue type

  • bug
  • missing functionality
  • performance
  • feature request

Brief description

I think I might be having a misunderstanding of how asyncio is supposed to work and/or how this API is designed. Consider the following (striped down) example from the codebase

import os, sys, asyncio, time
sys.path.append('../')

from bfxapi import Client

bfx = Client(logLevel='DEBUG')

now = int(round(time.time() * 1000))
then = now - 10000 

async def log_historical_trades():
  trades = await bfx.rest.get_public_trades('tBTCUSD', start=then, end=now, limit=10000)
  [ print (t) for t in trades ]

async def run():
   await log_historical_trades()
t = asyncio.ensure_future(run())
asyncio.get_event_loop().run_until_complete(t)


Steps to reproduce

The above program is supposed to print the trades happening in the last 10k millisecond. Indeed, it does that, but then blocks forever.

What exactly am I missing here? How can one stop the execution and continue fetching new trades?

Additional Notes:

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.