Skip to content

Commit

Permalink
Merge pull request #32 from EtWnn/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
EtWnn authored Jun 6, 2021
2 parents a8a9062 + ca5048b commit 64b5db5
Show file tree
Hide file tree
Showing 10 changed files with 151 additions and 21 deletions.
8 changes: 5 additions & 3 deletions CryptoPrice/__init__.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
__version__ = "0.1.1"
__version__ = "0.1.2"
__author__ = "EtWnn"

from CryptoPrice.retrievers.BinanceRetriever import BinanceRetriever
from CryptoPrice.retrievers.KucoinRetriever import KucoinRetriever
from CryptoPrice.retrievers.CoinbaseRetriever import CoinbaseRetriever
from CryptoPrice.retrievers.MetaRetriever import MetaRetriever


def get_default_retriever() -> MetaRetriever:
"""
Provides a hands on price retriever made from the default BinanceRetriever and the default KucoinRetriever
Provides a hands on price retriever made from the default BinanceRetriever, the default KucoinRetriever
and the default CoinbaseRetriever
:return: the meta retriever constructed
:rtype: MetaRetriever
"""
return MetaRetriever([BinanceRetriever(), KucoinRetriever()])
return MetaRetriever([BinanceRetriever(), KucoinRetriever(), CoinbaseRetriever()])
87 changes: 87 additions & 0 deletions CryptoPrice/retrievers/CoinbaseRetriever.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
from datetime import datetime, timedelta, timezone
import traceback
from typing import List

import cbpro

from CryptoPrice.common.trade import TradingPair
from CryptoPrice.exceptions import RateAPIException
from CryptoPrice.retrievers.KlineRetriever import KlineRetriever
from CryptoPrice.common.prices import Kline
from CryptoPrice.utils.time import TIMEFRAME


class CoinbaseRetriever(KlineRetriever):
"""
This class is in charge of fetching klines from the Coinbase Pro API
docs: https://github.com/teleprint-me/coinbasepro-python
"""

def __init__(self, kline_timeframe: TIMEFRAME = TIMEFRAME.m1, closest_window: int = 310):
self.client = cbpro.public_client()
super(CoinbaseRetriever, self).__init__('coinbase', kline_timeframe, closest_window)

def get_supported_pairs(self) -> List[TradingPair]:
"""
Return the list of trading pair supported by this retriever
:return: list of trading pairs
:rtype: List[TradingPair]
"""
coinbase_symbols = list(self.client.products.list())
trading_pairs = [TradingPair(s['base_currency'] + s['quote_currency'],
s['base_currency'],
s['quote_currency'],
source=self.name) for s in coinbase_symbols]
return trading_pairs

def _get_klines_online(self, asset: str, ref_asset: str, timeframe: TIMEFRAME,
start_time: int, end_time: int) -> List[Kline]:
"""
Fetch klines online by asking the CoinbasePro API
:param asset: asset of the trading pair
:type asset: str
:param ref_asset: reference asset of the trading pair
:type ref_asset: str
:param timeframe: timeframe for the kline
:type timeframe: TIMEFRAME
:param start_time: fetch only klines with an open time greater or equal than start_time
:type start_time: Optional[int]
:param end_time: fetch only klines with an open time lower than end_time
:type end_time: Optional[int]
:return: list of klines
:rtype: List[Kline]
"""
klines = []
pair_name = f"{asset}-{ref_asset}"
granularity = 60 * timeframe.value
batch_size = 300
start_datetime = datetime.fromtimestamp(start_time, tz=timezone.utc)
end_datetime = datetime.fromtimestamp(end_time, tz=timezone.utc)
while start_datetime < end_datetime:
batch_end_datetime = start_datetime + timedelta(seconds=granularity*batch_size)
params = {
'start': start_datetime.isoformat(),
'end': batch_end_datetime.isoformat(),
'granularity': granularity
}
result = self.client.products.history(pair_name, params)

for row in result:
open_timestamp = int(row[0])
open = float(row[3])
high = float(row[2])
low = float(row[1])
close = float(row[4])

klines.append(Kline(open_timestamp, open, high, low, close,
asset, ref_asset, timeframe, source=self.name))

if len(result):
start_datetime = datetime.fromtimestamp(result[0][0], tz=timezone.utc) + timedelta(seconds=granularity)
else:
start_datetime = start_datetime + timedelta(seconds=granularity * batch_size)

return klines
13 changes: 11 additions & 2 deletions CryptoPrice/retrievers/MetaRetriever.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,16 @@ def get_mean_price(self, asset: str, ref_asset: str, timestamp: int, preferred_a
:rtype: Optional[MetaPrice]
"""
meta_prices = []
min_depth = max_depth + 1
for meta_price in self.get_path_prices(asset, ref_asset, timestamp, preferred_assets,
max_depth, max_depth_range):
max_depth, -1):
if meta_price is not None:
meta_prices.append(meta_price)
if min_depth > max_depth:
min_depth = len(meta_price.prices)
if len(meta_price.prices) - min_depth > max_depth_range:
break
else:
meta_prices.append(meta_price)
if len(meta_prices):
return MetaPrice.mean_from_meta_price(meta_prices)

Expand Down Expand Up @@ -103,6 +109,9 @@ def get_path_prices(self, asset: str, ref_asset: str, timestamp: int,
:return: Metaprice reflecting the value calculated through a trading path
:rtype: Optional[MetaPrice]
"""
if asset == ref_asset:
yield MetaPrice(1, asset, ref_asset, [], source=set('',))
return
if preferred_assets is None:
preferred_assets = ['BTC', 'ETH']

Expand Down
32 changes: 21 additions & 11 deletions CryptoPrice/storage/DataBase.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,11 +140,23 @@ def drop_table(self, table: Union[Table, str]):
:return: None
:rtype: None
"""
if isinstance(table, Table):
table = table.name
execution_order = f"DROP TABLE IF EXISTS {table}"
self.db_cursor.execute(execution_order)
self.db_conn.commit()
self.drop_tables([table])

def drop_tables(self, tables: List[Union[Table, str]]):
"""
Delete a list of tables if they exist
:param tables: list of tables to delete
:type tables: List[Union[Table, str]]
:return: None
:rtype: None
"""
for table in tables:
if isinstance(table, Table):
table = table.name
execution_order = f"DROP TABLE IF EXISTS {table}"
self.db_cursor.execute(execution_order)
self.commit()

def drop_all_tables(self):
"""
Expand All @@ -153,14 +165,12 @@ def drop_all_tables(self):
:return: None
:rtype: None
"""
tables_desc = self.get_all_tables()
for table_desc in tables_desc:
self.drop_table(table_desc[1])
self.commit()
tables = [t[1] for t in self.get_tables_descriptions()]
self.drop_tables(tables)

def get_all_tables(self) -> List[Tuple]:
def get_tables_descriptions(self) -> List[Tuple]:
"""
return all the tables existing in the database
return the descriptions of all the tables existing in the database
:return: tables descriptions
:rtype: List[Tuple]
Expand Down
11 changes: 11 additions & 0 deletions CryptoPrice/storage/KlineDataBase.py
Original file line number Diff line number Diff line change
Expand Up @@ -187,3 +187,14 @@ def add_cache_closest(self, asset: str, ref_asset: str, timeframe: TIMEFRAME, ti
row = (timestamp, closest_timestamp, window)
self.add_row(table, row, update_if_exists=True)

def drop_cache_tables(self):
"""
Delete all the cache tables stored in the database
:return: None
:rtype: None
"""
tables = [t[1] for t in self.get_tables_descriptions()]
tables = [table for table in tables if table.endswith('_cache')]
self.drop_tables(tables)

7 changes: 4 additions & 3 deletions README.rst
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
===============================
Welcome to CryptoPrice 0.1.1
Welcome to CryptoPrice 0.1.2
===============================


Expand All @@ -26,6 +26,7 @@ amount of different tokens or to compare the price difference between exchanges.
It currently includes:
- Binance API
- Kucoin API
- Coinbase API
- Cross-API logic

Quick Tour
Expand Down Expand Up @@ -71,7 +72,7 @@ A price retriever is already provided by the library, but feel free to check the
You can also fetch a price even if the trading pair does not exist: The retriever (MetaRetriever) will find a path with
several trading pairs to estimate the price between the asset and the ref asset. This method takes much more time
than the one above as several API calls (or database requests) have to be made.
than the one above as several API calls (or database requests) may be needed.

.. code-block:: python
Expand All @@ -91,7 +92,7 @@ than the one above as several API calls (or database requests) have to be made.
.. code-block:: bash
>>LTC = 420.80573 XRP, source: {'kucoin', 'binance'}
>>LTC = 420.76841 XRP, source: {'binance', 'kucoin', 'coinbase'}
Donation
Expand Down
2 changes: 1 addition & 1 deletion docs/source/overview.rst
Original file line number Diff line number Diff line change
Expand Up @@ -82,4 +82,4 @@ than the one above as several API calls (or database requests) have to be made.
.. code-block:: bash
>>LTC = 420.80573 XRP, source: {'kucoin', 'binance'}
>>LTC = 420.76841 XRP, source: {'binance', 'kucoin', 'coinbase'}
5 changes: 5 additions & 0 deletions docs/source/retrievers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ Implemented Retrievers

Below are the retrievers implemented in this library.

.. automodule:: CryptoPrice.retrievers.CoinbaseRetriever
:special-members: __init__
:members:
:undoc-members:

.. automodule:: CryptoPrice.retrievers.BinanceRetriever
:special-members: __init__
:members:
Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ sphinx
sphinx_rtd_theme
python-binance
kucoin-python
git+https://github.com/teleprint-me/[email protected]#egg=cbpro
6 changes: 5 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,11 @@
description='Library to retrieve price or candle history of crypto assets using multiple sources',
long_description=long_description,
long_description_content_type='text/x-rst',
install_requires=['requests', 'appdirs', 'python-binance', 'kucoin-python'],
install_requires=['requests',
'appdirs',
'python-binance',
'kucoin-python',
'cbpro@git+https://github.com/teleprint-me/[email protected]'],
keywords='eth bsc price ohlc candle history API Binance Kucoin',
classifiers=[
'Intended Audience :: Developers',
Expand Down

0 comments on commit 64b5db5

Please sign in to comment.