Skip to content

Commit

Permalink
Merge pull request #21 from olned/cex.io
Browse files Browse the repository at this point in the history
v0.14.0
  • Loading branch information
olned authored Jun 23, 2020
2 parents fd486bb + 00da31a commit 2cf5764
Show file tree
Hide file tree
Showing 60 changed files with 1,109 additions and 220 deletions.
22 changes: 14 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
# ssc2ce
A Set of Simple Connectors for access To Cryptocurrency Exchanges via websocket based on
[aiohttp](https://aiohttp.readthedocs.io) .
A set of simple connectors for access to few cryptocurrency Exchanges via websocket based on
[aiohttp](https://aiohttp.readthedocs.io).

This is more of a pilot project, if you have any wishes for adding exchanges or expanding functionality, please register issues
Supported Exchanges:
- Bitfinex - only public API,
- CEX.io,
- Coinbase Pro
- Deribit

This is more of a pilot project, if you have any wishes for adding exchanges or expanding functionality, please register issues.

## Installation
Install ssc2ce with:
Expand All @@ -23,7 +29,7 @@ from ssc2ce import Bitfinex
conn = Bitfinex()


async def handle_subscription(data, connector: Bitfinex):
def handle_subscription(data, connector: Bitfinex):
print(data, f"received:{connector.receipt_time}")


Expand Down Expand Up @@ -93,17 +99,17 @@ except KeyboardInterrupt:
If you clone repository you can run examples from the root directory.

```bash
$ PYTHONPATH=.:$PYTHONPATH python examples/bitfinex_basic_example.py
PYTHONPATH=.:$PYTHONPATH python examples/bitfinex/bitfinex_basic_example.py
```

To run some examples, you may need additional modules, you can install them from the `requirements.txt` file.

```bash
$ pip install -r requirements.txt
pip install -r requirements.txt
```

To run the private.py example, you must either fill in the .env file or set the environment variables DERIBIT_CLIENT_ID and DERIBIT_CLIENT_SECRET. Look at .env_default.
To run the private.py example, you must either fill in the .env file, look at .env.example, or set the environment variables DERIBIT_CLIENT_ID and DERIBIT_CLIENT_SECRET.

```bash
$ PYTHONPATH=.:$PYTHONPATH DERIBIT_CLIENT_ID=YOU_ACCESS_KEY DERIBIT_CLIENT_SECRET=YOU_ACCESS_SECRET python examples/deribit_private.py
PYTHONPATH=.:$PYTHONPATH DERIBIT_CLIENT_ID=YOU_ACCESS_KEY DERIBIT_CLIENT_SECRET=YOU_ACCESS_SECRET python examples/deribit/deribit_private.py
```
8 changes: 8 additions & 0 deletions examples/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
CEX_API_KEY=
CEX_SECRET=
CEX_UID=
COINBASE_PRO_KEY=
COINBASE_PRO_SECRET=
COINBASE_PRO_PASSPHRASE=
DERIBIT_CLIENT_ID=
DERIBIT_CLIENT_SECRET=
Empty file added examples/__init__.py
Empty file.
Empty file added examples/bitfinex/__init__.py
Empty file.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ def __init__(self, instrument):
self.top_bid = 0.
self.top_ask = 0.

def handle_book(self, message, connector):
def handle_book(self, message, _):
if type(message[1]) is str:
if message[1] == "cs":
pass
Expand Down
3 changes: 3 additions & 0 deletions examples/cex/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
CEX_API_KEY=YOUR_KEY
CEX_SECRET=YOUR_SECRET
CEX_UID=YOUR_PASSPHRASE
Empty file added examples/cex/__init__.py
Empty file.
72 changes: 72 additions & 0 deletions examples/cex/cex_io_private_example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#!/usr/bin/env python
import asyncio
import logging
import os

import aiohttp
from ssc2ce import Cex
from dotenv import load_dotenv

logging.basicConfig(format='%(asctime)s %(name)s %(funcName)s %(levelname)s %(message)s', level=logging.INFO)
logger = logging.getLogger("bitfinex-basic-example")

env_path = os.path.join(os.path.dirname(__file__), '.env')
load_dotenv(env_path)

auth_param = dict(apiKey=os.environ.get('CEX_API_KEY'),
secret=os.environ.get('CEX_SECRET'),
uid=os.environ.get('CEX_UID'))

conn = Cex(auth_param)

archive_orders = []


async def get_archive_orders(symbol1, symbol2):
global archive_orders
res = await conn.private_get(f"archived_orders/{symbol1}/{symbol2}")
archive_orders += res


async def start():
request = {'e': "get-balance", 'oid': '1'}

await conn.ws.send_json(request)

my_balance = {}
data = await conn.ws.receive()
if data.type == aiohttp.WSMsgType.TEXT:
data = data.json()
if data.get('ok') == 'ok':
balance = data['data']['balance']
for key, value in balance.items():
if float(value) != 0.00:
my_balance[key] = value

print(my_balance)

coroutines = []
data = await conn.public_get("currency_limits")

if data.get('ok') == 'ok':
for pair in data['data']['pairs']:
if pair['symbol1'] in my_balance and pair['symbol2'] in my_balance:
print(pair)
coroutines.append(get_archive_orders(pair['symbol1'], pair['symbol2']))
break

if coroutines:
await asyncio.gather(*coroutines)
for order in archive_orders:
print(order)

await conn.stop()


conn.on_connect_ws = start
loop = asyncio.get_event_loop()

try:
loop.run_until_complete(conn.run_receiver())
except KeyboardInterrupt:
logger.info("Application closed by KeyboardInterrupt.")
41 changes: 41 additions & 0 deletions examples/cex/cex_io_public_example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#!/usr/bin/env python
import asyncio
import logging

from ssc2ce import Cex

logging.basicConfig(format='%(asctime)s %(name)s %(funcName)s %(levelname)s %(message)s', level=logging.INFO)
logger = logging.getLogger("bitfinex-basic-example")

conn = Cex()


async def subscribe():
data = await conn.public_get("currency_limits")
if data.get('ok') == 'ok':
for pair in data['data']['pairs']:
if pair['symbol1'] == 'BTC' and pair['symbol2'] == 'EUR':
print(pair)

data = await conn.public_get("ticker/BTC/EUR")
print(data)

request = {'e': "subscribe", 'rooms': ["ticker"]}

await conn.ws.send_json(request)


def print_ticker(msg):
print(msg)
return True


conn.on_connect_ws = subscribe
conn.on_message = print_ticker

loop = asyncio.get_event_loop()

try:
loop.run_until_complete(conn.run_receiver())
except KeyboardInterrupt:
print("Application closed by KeyboardInterrupt.")
60 changes: 60 additions & 0 deletions examples/cex/cex_io_subscribe_book.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#!/usr/bin/env python
import asyncio
import logging
import os

from examples.common.book_watcher import BookWatcher
from ssc2ce import Cex, CexParser
from dotenv import load_dotenv

logging.basicConfig(format='%(asctime)s %(name)s %(funcName)s %(levelname)s %(message)s', level=logging.INFO)
logger = logging.getLogger("bitfinex-basic-example")

env_path = os.path.join(os.path.dirname(__file__), '.env')
load_dotenv(env_path)

auth_param = dict(apiKey=os.environ.get('CEX_API_KEY'),
secret=os.environ.get('CEX_SECRET'),
uid=os.environ.get('CEX_UID'))

print(auth_param)

conn = Cex(auth_param)
parser = CexParser()
watcher = BookWatcher(parser)
conn.on_message = parser.parse


async def subscribe():
for market in ["BTC-EUR", 'ETH-EUR', "ETH-BTC"]:
pair = list(market.split('-'))
request = {'e': "order-book-subscribe",
'oid': 'book-1',
'data': {'pair': [pair[0], pair[1]], 'subscribe': True, 'depth': 0}
}

await conn.ws.send_json(request)


output = open("cex_dump_1h.jsonl", "w")


def dump(msg: str):
output.write(msg)
output.write('\n')


conn.on_connect_ws = subscribe
conn.on_before_handling = dump
loop = asyncio.get_event_loop()


def stop():
asyncio.ensure_future(conn.ws.close())


loop.call_later(3600, stop)
try:
loop.run_until_complete(conn.run_receiver())
except KeyboardInterrupt:
print("Application closed by KeyboardInterrupt.")
3 changes: 3 additions & 0 deletions examples/coinbase/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
COINBASE_PRO_KEY=YOUR_KEY
COINBASE_PRO_SECRET=YOUR_SECRET
COINBASE_PRO_PASSPHRASE=YOUR_PASSPHRASE
Empty file added examples/coinbase/__init__.py
Empty file.
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@ async def subscribe():


def handle_heartbeat(data: dict) -> bool:
global last_time
last_time = data["time"]
logger.info(f"{repr(data)}")
return True

Expand Down
65 changes: 65 additions & 0 deletions examples/coinbase/coinbase_pro_private.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#!/usr/bin/env python
import asyncio
import logging
import os

from dotenv import load_dotenv
from ssc2ce import Coinbase

logging.basicConfig(format='%(asctime)s %(name)s %(funcName)s %(levelname)s %(message)s', level=logging.INFO)
logger = logging.getLogger("bitfinex-basic-example")

env_path = os.path.join(os.path.dirname(__file__), '.env')
load_dotenv(env_path)

auth_param = dict(api_key=os.environ.get('COINBASE_PRO_KEY'),
secret_key=os.environ.get('COINBASE_PRO_SECRET'),
passphrase=os.environ.get('COINBASE_PRO_PASSPHRASE'))

print(auth_param)


def handle_message(message: str):
logger.info(message)


conn = Coinbase(auth_param=auth_param)
conn.on_message = handle_message


async def start():
res = await conn.private_get('/accounts')
print(res)
await conn.stop()
# await conn.ws.send_json({
# "type": "subscribe",
# "product_ids": [
# "BTC-USD",
# "ETH-BTC"
# ],
# "channels": [
# "level2",
# "heartbeat"
# ]
# })


def handle_heartbeat(data: dict) -> bool:
logger.info(f"{repr(data)}")
return True


conn.on_connect_ws = start


def stop():
asyncio.ensure_future(conn.stop())


loop = asyncio.get_event_loop()
loop.call_later(3600, stop)

try:
loop.run_until_complete(conn.run_receiver())
except KeyboardInterrupt:
logger.info("Application closed by KeyboardInterrupt.")
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
#!/usr/bin/env python
import asyncio
import json
import logging
from ssc2ce import Coinbase

conn = Coinbase(False)
conn = Coinbase(sandbox=False)

pending = {}

Expand All @@ -25,7 +24,7 @@ async def subscribe_books():
})


output = open("coinbase_dump.txt", "w")
output = open("coinbase_dump.jsonl", "w")


def dump(msg: str):
Expand All @@ -38,9 +37,7 @@ def stop():


async def run():
# from pprint import pprint
all_products = [x for x in await conn.get_products()]
# pprint(all_products)

my_products = {x['id']: x for x in all_products if x['quote_currency'] == 'EUR'}
base_currencies = [x['base_currency'] for x in my_products.values()]
Expand All @@ -56,6 +53,7 @@ async def run():
instruments += list(my_products.keys())
await conn.run_receiver()


conn.on_before_handling = dump
conn.on_connect_ws = subscribe_books

Expand Down
Loading

0 comments on commit 2cf5764

Please sign in to comment.