mirror of
https://github.com/aljazceru/bitfinex-api-py.git
synced 2025-12-19 06:44:22 +01:00
Merge pull request #25 from JacobPlaster/support-derivatives
Support derivatives
This commit is contained in:
@@ -1,3 +1,11 @@
|
||||
1.0.1
|
||||
|
||||
- Added ws event `status_update`
|
||||
- Added rest function `get_derivative_status`
|
||||
- Added rest function `get_derivative_statuses`
|
||||
- Added rest function `set_derivative_collateral`
|
||||
- Added channel support `status`
|
||||
|
||||
1.0.0
|
||||
|
||||
- Removal of camel-casing file naming and git duplicates
|
||||
|
||||
13
README.md
13
README.md
@@ -114,6 +114,7 @@ The websocket exposes a collection of events that are triggered when certain dat
|
||||
- `order_snapshot` (array[Order]): Initial open orders (Fired once)
|
||||
- `positions_snapshot` (array): Initial open positions (Fired once)
|
||||
- `wallet_update` (Wallet): changes to the balance of wallets
|
||||
- `status_update` (json): new platform status info
|
||||
- `seed_candle` (json): initial past candle to prime strategy
|
||||
- `seed_trade` (json): initial past trade to prime strategy
|
||||
- `funding_offer_snapshot` (array): opening funding offer balances
|
||||
@@ -227,6 +228,14 @@ Get the public orderbook of a given symbol
|
||||
Get tickers for the given symbols. Tickers shows you the current best bid and ask,
|
||||
as well as the last trade price.
|
||||
|
||||
### `get_derivative_status(symbol)`
|
||||
|
||||
Get derivative platform information for the given symbol.
|
||||
|
||||
### `get_derivative_statuses(symbols)`
|
||||
|
||||
Get derivative platform information for the given collection of symbols.
|
||||
|
||||
### `get_wallets()`
|
||||
|
||||
Get all wallets on account associated with API_KEY - Requires authentication.
|
||||
@@ -277,6 +286,10 @@ Get the public orderbook of a given symbol
|
||||
|
||||
Get all of the funding credits between the start and end period associated with API_KEY - Requires authentication.
|
||||
|
||||
### `set_derivative_collateral(symbol, collateral)`
|
||||
|
||||
Set the amount of collateral used to back a derivative position.
|
||||
|
||||
# Examples
|
||||
|
||||
For more info on how to use this library please see the example scripts in the `bfxapi/examples` directory. Here you will find usage of all interface exposed functions for both the rest and websocket.
|
||||
|
||||
@@ -12,8 +12,7 @@ API_SECRET=os.getenv("BFX_SECRET")
|
||||
bfx = Client(
|
||||
API_KEY=API_KEY,
|
||||
API_SECRET=API_SECRET,
|
||||
logLevel='DEBUG',
|
||||
rest_host='https://test.bitfinex.com/v2'
|
||||
logLevel='DEBUG'
|
||||
)
|
||||
|
||||
now = int(round(time.time() * 1000))
|
||||
|
||||
@@ -38,12 +38,18 @@ async def log_mul_tickers():
|
||||
print ("Tickers:")
|
||||
print (tickers)
|
||||
|
||||
async def log_derivative_status():
|
||||
status = await bfx.rest.get_derivative_status('tBTCF0:USTF0')
|
||||
print ("Deriv status:")
|
||||
print (status)
|
||||
|
||||
async def run():
|
||||
await log_historical_candles()
|
||||
await log_historical_trades()
|
||||
await log_books()
|
||||
await log_ticker()
|
||||
await log_mul_tickers()
|
||||
await log_derivative_status()
|
||||
|
||||
t = asyncio.ensure_future(run())
|
||||
asyncio.get_event_loop().run_until_complete(t)
|
||||
|
||||
23
bfxapi/examples/ws/subscribe_derivative_status.py
Normal file
23
bfxapi/examples/ws/subscribe_derivative_status.py
Normal file
@@ -0,0 +1,23 @@
|
||||
import os
|
||||
import sys
|
||||
sys.path.append('../')
|
||||
|
||||
from bfxapi import Client
|
||||
|
||||
bfx = Client(
|
||||
logLevel='INFO'
|
||||
)
|
||||
|
||||
@bfx.ws.on('error')
|
||||
def log_error(err):
|
||||
print ("Error: {}".format(err))
|
||||
|
||||
@bfx.ws.on('status_update')
|
||||
def log_msg(msg):
|
||||
print (msg)
|
||||
|
||||
async def start():
|
||||
await bfx.ws.subscribe_derivative_status('tBTCF0:USTF0')
|
||||
|
||||
bfx.ws.on('connected', start)
|
||||
bfx.ws.run()
|
||||
@@ -21,13 +21,13 @@ class Subscription:
|
||||
such as unsibscribe and subscribe.
|
||||
"""
|
||||
|
||||
def __init__(self, socket, channel_name, symbol, timeframe=None, **kwargs):
|
||||
def __init__(self, socket, channel_name, symbol, key=None, timeframe=None, **kwargs):
|
||||
self.socket = socket
|
||||
self.channel_name = channel_name
|
||||
self.symbol = symbol
|
||||
self.timeframe = timeframe
|
||||
self.is_subscribed_bool = False
|
||||
self.key = None
|
||||
self.key = key
|
||||
self.chan_id = None
|
||||
if timeframe:
|
||||
self.key = 'trade:{}:{}'.format(self.timeframe, self.symbol)
|
||||
@@ -79,7 +79,7 @@ class Subscription:
|
||||
def _generate_payload(self, **kwargs):
|
||||
payload = {'event': 'subscribe',
|
||||
'channel': self.channel_name, 'symbol': self.symbol}
|
||||
if self.timeframe:
|
||||
if self.timeframe or self.key:
|
||||
payload['key'] = self.key
|
||||
payload.update(**kwargs)
|
||||
return payload
|
||||
|
||||
1
bfxapi/rest/__init__.py
Normal file
1
bfxapi/rest/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
NAME = 'rest'
|
||||
@@ -33,7 +33,7 @@ class BfxRest:
|
||||
|
||||
async def fetch(self, endpoint, params=""):
|
||||
"""
|
||||
Fetch a GET request from the bitfinex host
|
||||
Send a GET request to the bitfinex api
|
||||
|
||||
@return reponse
|
||||
"""
|
||||
@@ -49,7 +49,7 @@ class BfxRest:
|
||||
|
||||
async def post(self, endpoint, data={}, params=""):
|
||||
"""
|
||||
Request a POST to the bitfinex host
|
||||
Send a pre-signed POST request to the bitfinex api
|
||||
|
||||
@return response
|
||||
"""
|
||||
@@ -151,7 +151,7 @@ class BfxRest:
|
||||
Get tickers for the given symbol. Tickers shows you the current best bid and ask,
|
||||
as well as the last trade price.
|
||||
|
||||
@parms symbols symbol string: pair symbol i.e tBTCUSD
|
||||
@param symbols symbol string: pair symbol i.e tBTCUSD
|
||||
@return Array [ SYMBOL, BID, BID_SIZE, ASK, ASK_SIZE, DAILY_CHANGE,
|
||||
DAILY_CHANGE_PERC, LAST_PRICE, VOLUME, HIGH, LOW ]
|
||||
"""
|
||||
@@ -164,7 +164,7 @@ class BfxRest:
|
||||
Get tickers for the given symbols. Tickers shows you the current best bid and ask,
|
||||
as well as the last trade price.
|
||||
|
||||
@parms symbols Array<string>: array of symbols i.e [tBTCUSD, tETHUSD]
|
||||
@param symbols Array<string>: array of symbols i.e [tBTCUSD, tETHUSD]
|
||||
@return Array [ SYMBOL, BID, BID_SIZE, ASK, ASK_SIZE, DAILY_CHANGE, DAILY_CHANGE_PERC,
|
||||
LAST_PRICE, VOLUME, HIGH, LOW ]
|
||||
"""
|
||||
@@ -172,6 +172,31 @@ class BfxRest:
|
||||
ticker = await self.fetch(endpoint)
|
||||
return ticker
|
||||
|
||||
async def get_derivative_status(self, symbol):
|
||||
"""
|
||||
Gets platform information for derivative symbol.
|
||||
|
||||
@param derivativeSymbol string: i.e tBTCF0:USTF0
|
||||
@return [KEY/SYMBOL, MTS, PLACEHOLDER, DERIV_PRICE, SPOT_PRICE, PLACEHOLDER, INSURANCE_FUND_BALANCE4,
|
||||
PLACEHOLDER, PLACEHOLDER, FUNDING_ACCRUED, FUNDING_STEP, PLACEHOLDER]
|
||||
"""
|
||||
statuses = await self.get_derivative_statuses([symbol])
|
||||
if len(statuses) > 0:
|
||||
return statuses[0]
|
||||
return []
|
||||
|
||||
async def get_derivative_statuses(self, symbols):
|
||||
"""
|
||||
Gets platform information for a collection of derivative symbols.
|
||||
|
||||
@param derivativeSymbols Array<string>: array of symbols i.e [tBTCF0:USTF0 ...] or ["ALL"]
|
||||
@return [KEY/SYMBOL, MTS, PLACEHOLDER, DERIV_PRICE, SPOT_PRICE, PLACEHOLDER, INSURANCE_FUND_BALANCE4,
|
||||
PLACEHOLDER, PLACEHOLDER, FUNDING_ACCRUED, FUNDING_STEP, PLACEHOLDER]
|
||||
"""
|
||||
endpoint = "status/deriv?keys={}".format(','.join(symbols))
|
||||
status = await self.fetch(endpoint)
|
||||
return status
|
||||
|
||||
##################################################
|
||||
# Authenticated Data #
|
||||
##################################################
|
||||
@@ -327,7 +352,7 @@ class BfxRest:
|
||||
return [FundingCredit.from_raw_credit(c) for c in credits]
|
||||
|
||||
##################################################
|
||||
# Orders #
|
||||
# Orders #
|
||||
##################################################
|
||||
|
||||
async def __submit_order(self, symbol, amount, price, oType=Order.Type.LIMIT,
|
||||
@@ -368,3 +393,20 @@ class BfxRest:
|
||||
payload['sell_price_oco'] = stop_sell_price
|
||||
endpoint = 'order/new'
|
||||
return await self.post(endpoint, data=payload)
|
||||
|
||||
##################################################
|
||||
# Derivatives #
|
||||
##################################################
|
||||
|
||||
async def set_derivative_collateral(self, symbol, collateral):
|
||||
"""
|
||||
Update the amount of callateral used to back a derivative position.
|
||||
|
||||
@param symbol of the derivative i.e 'tBTCF0:USTF0'
|
||||
@param collateral: amount of collateral/value to apply to the open position
|
||||
"""
|
||||
endpoint = 'auth/w/deriv/collateral/set'
|
||||
payload = {}
|
||||
payload['symbol'] = symbol
|
||||
payload['collateral'] = collateral
|
||||
return await self.post(endpoint, data=payload)
|
||||
|
||||
1
bfxapi/utils/__init__.py
Normal file
1
bfxapi/utils/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
NAME = 'utils'
|
||||
@@ -2,4 +2,4 @@
|
||||
This module contains the current version of the bfxapi lib
|
||||
"""
|
||||
|
||||
__version__ = '1.0.0'
|
||||
__version__ = '1.0.1'
|
||||
|
||||
1
bfxapi/websockets/__init__.py
Normal file
1
bfxapi/websockets/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
NAME = 'websockets'
|
||||
@@ -65,6 +65,23 @@ def _parse_trade(tData, symbol):
|
||||
'symbol': symbol
|
||||
}
|
||||
|
||||
def _parse_deriv_status_update(sData, symbol):
|
||||
return {
|
||||
'symbol': symbol,
|
||||
'status_type': 'deriv',
|
||||
'mts': sData[0],
|
||||
# placeholder
|
||||
'deriv_price': sData[2],
|
||||
'spot_price': sData[3],
|
||||
# placeholder
|
||||
'insurance_fund_balance': sData[5],
|
||||
# placeholder
|
||||
# placeholder
|
||||
'funding_accrued': sData[8],
|
||||
'funding_step': sData[9],
|
||||
# placeholder
|
||||
}
|
||||
|
||||
|
||||
class BfxWebsocket(GenericWebsocket):
|
||||
"""
|
||||
@@ -167,6 +184,8 @@ class BfxWebsocket(GenericWebsocket):
|
||||
await self._order_book_handler(data, raw_message_str)
|
||||
if subscription.channel_name == 'trades':
|
||||
await self._trade_handler(data)
|
||||
if subscription.channel_name == 'status':
|
||||
await self._status_handler(data)
|
||||
else:
|
||||
self.logger.warn(
|
||||
"Unknown data event: '{}' {}".format(dataEvent, data))
|
||||
@@ -293,6 +312,18 @@ class BfxWebsocket(GenericWebsocket):
|
||||
self._emit('funding_credit_snapshot', data[2])
|
||||
self.logger.info("Funding credit snapshot: {}".format(data))
|
||||
|
||||
async def _status_handler(self, data):
|
||||
sub = self.subscriptionManager.get(data[0])
|
||||
symbol = sub.symbol
|
||||
status_type = sub.key.split(":")[0]
|
||||
rstatus = data[1]
|
||||
if status_type == "deriv":
|
||||
status = _parse_deriv_status_update(rstatus, symbol)
|
||||
if status:
|
||||
self._emit('status_update', status)
|
||||
else:
|
||||
self.logger.warn('Unknown status data type: {}'.format(data))
|
||||
|
||||
async def _trade_handler(self, data):
|
||||
symbol = self.subscriptionManager.get(data[0]).symbol
|
||||
if type(data[1]) is list:
|
||||
@@ -439,6 +470,22 @@ class BfxWebsocket(GenericWebsocket):
|
||||
if socket.isConnected:
|
||||
await socket.ws.send(json.dumps(payload))
|
||||
|
||||
async def subscribe_order_book(self, symbol):
|
||||
return await self.subscribe('book', symbol)
|
||||
|
||||
async def subscribe_candles(self, symbol, timeframe):
|
||||
return await self.subscribe('candles', symbol, timeframe=timeframe)
|
||||
|
||||
async def subscribe_trades(self, symbol):
|
||||
return await self.subscribe('trades', symbol)
|
||||
|
||||
async def subscribe_ticker(self, symbol):
|
||||
return await self.subscribe('ticker', symbol)
|
||||
|
||||
async def subscribe_derivative_status(self, symbol):
|
||||
key = 'deriv:{}'.format(symbol)
|
||||
return await self.subscribe('status', symbol, key=key)
|
||||
|
||||
async def subscribe(self, *args, **kwargs):
|
||||
return await self.subscriptionManager.subscribe(*args, **kwargs)
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ class SubscriptionManager:
|
||||
count += 1
|
||||
return count
|
||||
|
||||
async def subscribe(self, channel_name, symbol, timeframe=None, **kwargs):
|
||||
async def subscribe(self, channel_name, symbol, key=None, timeframe=None, **kwargs):
|
||||
"""
|
||||
Subscribe to a new channel
|
||||
|
||||
@@ -51,7 +51,7 @@ class SubscriptionManager:
|
||||
socket = self.bfxapi.get_most_available_socket()
|
||||
# create a new subscription
|
||||
subscription = Subscription(
|
||||
socket, channel_name, symbol, timeframe, **kwargs)
|
||||
socket, channel_name, symbol, key, timeframe, **kwargs)
|
||||
self.logger.info("Subscribing to channel {}".format(channel_name))
|
||||
self.pending_subscriptions[subscription.get_key()] = subscription
|
||||
|
||||
|
||||
@@ -10,4 +10,4 @@ disable=too-few-public-methods,
|
||||
too-many-instance-attributes,
|
||||
invalid-name
|
||||
|
||||
ignore=tests
|
||||
ignore=tests,websockets,rest,utils
|
||||
|
||||
76
setup.py
Normal file
76
setup.py
Normal file
@@ -0,0 +1,76 @@
|
||||
"""A setuptools based setup module.
|
||||
See:
|
||||
https://packaging.python.org/guides/distributing-packages-using-setuptools/
|
||||
https://github.com/pypa/sampleproject
|
||||
"""
|
||||
|
||||
# Always prefer setuptools over distutils
|
||||
from setuptools import setup, find_packages
|
||||
from os import path
|
||||
# io.open is needed for projects that support Python 2.7
|
||||
# It ensures open() defaults to text mode with universal newlines,
|
||||
# and accepts an argument to specify the text encoding
|
||||
# Python 3 only projects can skip this import
|
||||
from io import open
|
||||
|
||||
here = path.abspath(path.dirname(__file__))
|
||||
|
||||
# Arguments marked as "Required" below must be included for upload to PyPI.
|
||||
# Fields marked as "Optional" may be commented out.
|
||||
|
||||
setup(
|
||||
name='bitfinex-api-py',
|
||||
version='1.0.1', # Required
|
||||
description='Official Bitfinex API', # Optional
|
||||
long_description='This is an official python library that is used to connect interact with the Bitfinex api.', # Optional
|
||||
long_description_content_type='text/markdown', # Optional
|
||||
url='https://github.com/bitfinexcom/bitfinex-api-py', # Optional
|
||||
author='Bitfinex', # Optional
|
||||
author_email='support@bitfinex.com', # Optional
|
||||
classifiers=[ # Optional
|
||||
# How mature is this project? Common values are
|
||||
# 3 - Alpha
|
||||
# 4 - Beta
|
||||
# 5 - Production/Stable
|
||||
'Development Status :: 4 - Beta',
|
||||
|
||||
# Indicate who your project is intended for
|
||||
'Intended Audience :: Developers',
|
||||
'Topic :: Software Development :: Build Tools',
|
||||
|
||||
# Pick your license as you wish
|
||||
'License :: OSI Approved :: Apache 2.0',
|
||||
|
||||
# Specify the Python versions you support here. In particular, ensure
|
||||
# that you indicate whether you support Python 2, Python 3 or both.
|
||||
# These classifiers are *not* checked by 'pip install'. See instead
|
||||
# 'python_requires' below.
|
||||
'Programming Language :: Python :: 2.7',
|
||||
'Programming Language :: Python :: 3.6',
|
||||
'Programming Language :: Python :: 3.7',
|
||||
],
|
||||
|
||||
keywords='bitfinex', # Optional
|
||||
|
||||
packages=find_packages(exclude=['examples', 'tests']), # Required
|
||||
|
||||
# Specify which Python versions you support. In contrast to the
|
||||
# 'Programming Language' classifiers above, 'pip install' will check this
|
||||
# and refuse to install the project if the version does not match. If you
|
||||
# do not support Python 2, you can simplify this to '>=3.5' or similar, see
|
||||
# https://packaging.python.org/guides/distributing-packages-using-setuptools/#python-requires
|
||||
python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, <4',
|
||||
|
||||
# This field lists other packages that your project depends on to run.
|
||||
# Any package you put here will be installed by pip when your project is
|
||||
# installed, so they must be valid existing projects.
|
||||
#
|
||||
# For an analysis of "install_requires" vs pip's requirements files see:
|
||||
# https://packaging.python.org/en/latest/requirements.html
|
||||
install_requires=['eventemitter', 'asyncio', 'websockets', 'pylint', 'six', 'pyee', 'aiohttp'], # Optional
|
||||
|
||||
project_urls={ # Optional
|
||||
'Bug Reports': 'https://github.com/bitfinexcom/bitfinex-api-py/issues',
|
||||
'Source': 'https://github.com/bitfinexcom/bitfinex-api-py',
|
||||
},
|
||||
)
|
||||
Reference in New Issue
Block a user