Skip to content

Commit 46816b7

Browse files
author
Pedro Pablo Bustamante Barrera
committed
Merge branch 'develop'
2 parents 402d925 + b86e756 commit 46816b7

14 files changed

+317
-78
lines changed

cryptomarket/args.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -201,10 +201,10 @@ def clean_nones(a_dict: Dict[Any, Optional[Any]]) -> Dict[Any, Any]:
201201

202202
class DictBuilder:
203203
def __init__(self):
204-
self.the_dict = dict()
204+
self.the_dict = {}
205205

206206
def build(self):
207-
orderedDict = dict()
207+
orderedDict = {}
208208
for parameter in sorted(self.the_dict):
209209
orderedDict[parameter] = self.the_dict[parameter]
210210
return orderedDict

cryptomarket/client.py

Lines changed: 121 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
Price, PriceHistory, SubAccount, Symbol,
1212
Ticker, Trade, Transaction, Fee)
1313
from cryptomarket.dataclasses.aclSettings import ACLSettings
14+
from cryptomarket.dataclasses.convertedCandles import ConvertedCandles
15+
from cryptomarket.dataclasses.convertedCandlesOfSymbol import ConvertedCandlesOfSymbol
1416
from cryptomarket.dataclasses.publicTrade import PublicTrade
1517
from cryptomarket.http_client import HttpClient
1618

@@ -30,10 +32,11 @@ def __init__(self, api_key: Optional[str] = None, secret_key: Optional[str] = No
3032
self.get_trades_by_symbol = self.get_trades_of_symbol
3133
# aliases of orders
3234
self.create_new_order = self.create_spot_order
33-
self.create_spot_order = self.create_spot_order
3435
self.create_new_spot_order = self.create_spot_order
3536

3637
def close(self):
38+
"""Closes the underlying http connection
39+
"""
3740
self.httpClient.close_session()
3841

3942
def _get(self, endpoint: str, params=None):
@@ -449,7 +452,7 @@ def get_candles_of_symbol(
449452
:param limit: Optional. Prices per currency pair. Defaul is 100. Min is 1. Max is 1000
450453
:param offset: Optional. Default is 0. Min is 0. Max is 100000
451454
452-
:returns: A list of candles of a symbol
455+
:returns: A class with the target_currency and data with a dict with a list of candles for each symbol of the query. indexed by symbol
453456
"""
454457
params = args.DictBuilder().period(period).sort(sort).since(
455458
since).till(till).limit(limit).offset(offset).build()
@@ -458,6 +461,92 @@ def get_candles_of_symbol(
458461
return [from_dict(data_class=Candle, data=candle_data)
459462
for candle_data in response]
460463

464+
def get_converted_candles(
465+
self,
466+
target_currency: str,
467+
symbols: Optional[List[str]] = None,
468+
period: Optional[Union[
469+
args.Period, Literal[
470+
'M1', 'M3', 'M15', 'M30', 'H1', 'H4', 'D1', 'D7', '1M'
471+
]
472+
]] = None,
473+
sort: Optional[Union[args.Sort, Literal['ASC', 'DESC']]] = None,
474+
since: str = None,
475+
till: str = None,
476+
limit: int = None
477+
) -> ConvertedCandles:
478+
"""Gets candles regarding the last price converted to the target currency for all symbols or for the specified symbols
479+
480+
Candles are used for OHLC representation
481+
482+
The result contains candles with non-zero volume only (no trades = no candles).
483+
484+
Conversion from the symbol quote currency to the target currency is the mean of "best" bid price and "best" ask price in the order book. If there is no "best" bid of ask price, the last price is returned.
485+
486+
Requires no API key Access Rights.
487+
488+
https://api.exchange.cryptomkt.com/#candles
489+
490+
:param target_currency: Target currency for conversion
491+
:param symbols: Optional. A list of symbol ids. If empty then gets for all symbols
492+
:param period: Optional. A valid tick interval. 'M1' (one minute), 'M3', 'M5', 'M15', 'M30', 'H1' (one hour), 'H4', 'D1' (one day), 'D7', '1M' (one month). Default is 'M30'
493+
:param sort: Optional. Sort direction. 'ASC' or 'DESC'. Default is 'DESC'
494+
:param from: Optional. Initial value of the queried interval. As DateTime
495+
:param till: Optional. Last value of the queried interval. As DateTime
496+
:param limit: Optional. Prices per currency pair. Defaul is 100. Min is 1. Max is 1000
497+
498+
:returns: A class with the target_currency and data with a list of candles for the symbol of the query.
499+
"""
500+
params = args.DictBuilder().target_currency(target_currency).symbols(symbols).period(period).sort(sort).since(
501+
since).till(till).limit(limit).build()
502+
response = self._get(
503+
endpoint="public/converted/candles", params=params)
504+
return from_dict(ConvertedCandles, response)
505+
506+
def get_converted_candles_of_symbol(
507+
self,
508+
target_currency: str,
509+
symbol: str,
510+
period: Optional[Union[
511+
args.Period, Literal[
512+
'M1', 'M3', 'M15', 'M30', 'H1', 'H4', 'D1', 'D7', '1M'
513+
]
514+
]] = None,
515+
sort: Optional[Union[args.Sort, Literal['ASC', 'DESC']]] = None,
516+
since: str = None,
517+
till: str = None,
518+
limit: int = None,
519+
offset: int = None
520+
) -> ConvertedCandlesOfSymbol:
521+
"""Gets candles regarding the last price converted to the target currency for the specified symbols
522+
523+
Candles are used for OHLC representation
524+
525+
The result contains candles with non-zero volume only (no trades = no candles).
526+
527+
Conversion from the symbol quote currency to the target currency is the mean of "best" bid price and "best" ask price in the order book. If there is no "best" bid of ask price, the last price is returned.
528+
529+
Requires no API key Access Rights.
530+
531+
https://api.exchange.cryptomkt.com/#candles
532+
533+
:param target_currency: Target currency for conversion
534+
:param symbol: A symbol id
535+
:param period: Optional. A valid tick interval. 'M1' (one minute), 'M3', 'M5', 'M15', 'M30', 'H1' (one hour), 'H4', 'D1' (one day), 'D7', '1M' (one month). Default is 'M30'
536+
:param sort: Optional. Sort direction. 'ASC' or 'DESC'. Default is 'DESC'
537+
:param from: Optional. Initial value of the queried interval. As DateTime
538+
:param till: Optional. Last value of the queried interval. As DateTime
539+
:param limit: Optional. Prices per currency pair. Defaul is 100. Min is 1. Max is 1000
540+
:param offset: Optional. Default is 0. Min is 0. Max is 100000
541+
542+
:returns: A list of candles of a symbol
543+
"""
544+
params = args.DictBuilder().target_currency(target_currency).period(period).sort(sort).since(
545+
since).till(till).limit(limit).offset(offset).build()
546+
response = self._get(
547+
endpoint=f"public/converted/candles/{symbol}", params=params)
548+
return from_dict(ConvertedCandlesOfSymbol, response)
549+
461550
#################
462551
# AUTHENTICATED #
463552
#################
@@ -1357,3 +1446,33 @@ def get_sub_account_crypto_address(self, sub_account_id: str, currency: str) ->
13571446
response = self._get(
13581447
endpoint=f'sub-account/crypto/address/{sub_account_id}/{currency}')
13591448
return from_dict(data_class=Address, data=response["result"]["address"])
1449+
1450+
###########
1451+
# ALIASES #
1452+
###########
1453+
1454+
# market data
1455+
get_ticker_by_symbol = get_ticker
1456+
get_ticker_of_symbol = get_ticker
1457+
get_ticker_last_price = get_ticker_last_price_of_symbol
1458+
get_ticker_last_price_by_symbol = get_ticker_last_price_of_symbol
1459+
get_trades_by_symbol = get_trades_of_symbol
1460+
get_order_book_by_symbol = get_order_book_of_symbol
1461+
get_order_book = get_order_book_of_symbol
1462+
get_order_book_volume_by_symbol = get_order_book_volume_of_symbol
1463+
get_order_book_volume = get_order_book_volume_of_symbol
1464+
get_candles_by_symbol = get_order_book_volume_of_symbol
1465+
get_converted_candles_by_symbol = get_converted_candles_of_symbol
1466+
1467+
# spot trading
1468+
get_spot_trading_balance_by_currency = get_spot_trading_balance_of_currency
1469+
get_spot_trading_balance = get_spot_trading_balance_of_currency
1470+
get_trading_commissions = get_all_trading_commissions
1471+
get_trading_commission_by_symbol = get_trading_commission
1472+
get_trading_commission_of_symbol = get_trading_commission
1473+
1474+
# wallet management
1475+
get_wallet_balance = get_wallet_balance_of_currency
1476+
get_wallet_balance_by_currency = get_wallet_balance_of_currency
1477+
get_deposit_crypto_address = get_deposit_crypto_address_of_currency
1478+
get_deposit_crypto_address_by_currency = get_deposit_crypto_address_of_currency
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
from dataclasses import dataclass
2+
from typing import Dict, List
3+
from cryptomarket.dataclasses.candle import Candle
4+
5+
6+
@dataclass
7+
class ConvertedCandles:
8+
target_currency: str
9+
data: Dict[str, List[Candle]]
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
from dataclasses import dataclass
2+
from typing import List
3+
4+
from cryptomarket.dataclasses.candle import Candle
5+
6+
7+
@dataclass
8+
class ConvertedCandlesOfSymbol:
9+
target_currency: str
10+
data: List[Candle]

cryptomarket/websockets/callback_cache.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
class CallbackCache:
66
def __init__(self):
7-
self.callbacks: Dict[str, ReusableCallback] = dict()
7+
self.callbacks: Dict[str, ReusableCallback] = {}
88
self._id = 1
99

1010
def next_id(self):

cryptomarket/websockets/interceptors.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,6 @@ def intercept_report(callback):
99

1010

1111
def intercept_report_(err, response, callback):
12-
print('interceptor')
13-
print('err:', err)
14-
print('response:', response)
1512
if err:
1613
callback(err, None)
1714
return

cryptomarket/websockets/market_data_client.py

Lines changed: 89 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ def subscribe_to_trades(
102102
params = args.DictBuilder().symbols_as_list(symbols).limit(limit).build()
103103

104104
def intercept_feed(feed, feed_type):
105-
result = dict()
105+
result = {}
106106
for key in feed:
107107
result[key] = [from_dict(data_class=WSTrade, data=data)
108108
for data in feed[key]]
@@ -129,7 +129,7 @@ def subscribe_to_candles(
129129
):
130130
"""subscribe to a feed of candles
131131
132-
subscription is for the specified symbols
132+
subscription is only for the specified symbols
133133
134134
normal subscriptions have one update message per symbol
135135
@@ -140,12 +140,12 @@ def subscribe_to_candles(
140140
141141
:param callback: callable that recieves a dict of candles, indexed by symbol.
142142
:param symbols: A list of symbol ids to subscribe to
143-
:param period: Optional. A valid tick interval. 'M1' (one minute), 'M3', 'M5', 'M15', 'M30', 'H1' (one hour), 'H4', 'D1' (one day), 'D7', '1M' (one month). Default is 'M30'
143+
:param period: Optional. A valid tick interval. 'M1' (one minute), 'M3', 'M5', 'M15', 'M30', 'H1' (one hour), 'H4', 'D1' (one day), 'D7', '1M' (one month).
144144
:param limit: Number of historical entries returned in the first feed. Min is 0. Max is 1000. Default is 0
145145
:param result_callback: A callable of two arguments, takes either a CryptomarketAPIException, or the list of correctly subscribed symbols
146146
"""
147147
def intercept_feed(feed, feed_type):
148-
result = dict()
148+
result = {}
149149
for key in feed:
150150
result[key] = [
151151
from_dict(data_class=WSCandle, data=data) for data in feed[key]]
@@ -158,6 +158,51 @@ def intercept_feed(feed, feed_type):
158158
result_callback=result_callback,
159159
)
160160

161+
def subscribe_to_converted_candles(
162+
self,
163+
callback: Callable[[Dict[str, List[WSCandle]], Literal['snapshot', 'update']], None],
164+
target_currency: str,
165+
symbols: List[str],
166+
period: Union[args.Period,
167+
Literal['M1', 'M3', 'M15', 'M30', 'H1', 'H4', 'D1', 'D7', '1M']] = None,
168+
limit: Optional[int] = None,
169+
result_callback: Optional[Callable[[
170+
Union[CryptomarketAPIException, None], Union[List[str], None]], None]] = None,
171+
):
172+
"""subscribes to a feed of candles regarding the last price converted to the target currency for the specified symbols
173+
174+
subscription is only for the specified symbols
175+
176+
normal subscriptions have one update message per symbol
177+
178+
Conversion from the symbol quote currency to the target currency is the mean of "best" bid price and "best" ask price in the order book. If there is no "best" bid or ask price, the last price is returned.
179+
180+
Requires no API key Access Rights
181+
182+
https://api.exchange.cryptomkt.com/#subscribe-to-converted-candles
183+
184+
185+
:param callback: callable that recieves a dict of candles, indexed by symbol.
186+
:param symbols: A list of symbol ids to subscribe to
187+
:param period: A valid tick interval. 'M1' (one minute), 'M3', 'M5', 'M15', 'M30', 'H1' (one hour), 'H4', 'D1' (one day), 'D7', '1M' (one month).
188+
:param limit: Limit of returned entries. Min is 0. Max is 1000. Default is 0
189+
:param result_callback: A callable of two arguments, takes either a CryptomarketAPIException, or the list of correctly subscribed symbols
190+
"""
191+
def intercept_feed(feed, feed_type):
192+
result = {}
193+
for key in feed:
194+
result[key] = [
195+
from_dict(data_class=WSCandle, data=data) for data in feed[key]]
196+
callback(result, feed_type)
197+
params = args.DictBuilder().target_currency(
198+
target_currency).symbols_as_list(symbols).limit(limit).build()
199+
self._send_channeled_subscription(
200+
channel=f'converted/candles/{period}',
201+
callback=intercept_feed,
202+
params=params,
203+
result_callback=result_callback,
204+
)
205+
161206
def subscribe_to_mini_ticker(
162207
self,
163208
callback: Callable[[Dict[str, WSMiniTicker]], None],
@@ -510,7 +555,8 @@ def subscribe_to_price_rates(
510555
"""
511556
if currencies is None:
512557
currencies = ['*']
513-
params = args.DictBuilder().currencies_as_list(currencies).speed(speed).target_currency(target_currency).build()
558+
params = args.DictBuilder().currencies_as_list(currencies).speed(
559+
speed).target_currency(target_currency).build()
514560

515561
def intercept_feed(feed, feed_type):
516562
callback({key: from_dict(data_class=WSPriceRate, data=feed[key])
@@ -521,3 +567,41 @@ def intercept_feed(feed, feed_type):
521567
params=params,
522568
result_callback=result_callback
523569
)
570+
571+
def subscribe_to_price_rates_in_batches(
572+
self,
573+
callback: Callable[[Dict[str, WSPriceRate]], None],
574+
speed: Union[args.PriceRateSpeed, Literal['1s', '3s']],
575+
target_currency: Optional[str],
576+
currencies: Optional[List[str]] = None,
577+
result_callback: Optional[Callable[[
578+
Union[CryptomarketAPIException, None], Union[List[str], None]], None]] = None,
579+
):
580+
"""subscribe to a feed of price rates
581+
582+
subscription is for all currencies or specified currencies (bases), against a target currency (quote). indexed by currency id (bases)
583+
584+
batch subscriptions have a joined update for all symbols
585+
586+
https://api.exchange.cryptomkt.com/#subscribe-to-price-rates
587+
588+
:param callback: callable that recieves a dict of mini tickers, indexed by symbol.
589+
:param speed: The speed of the feed. '1s' or '3s'
590+
:param target_currency: quote currency for the price rates
591+
:param currencies: Optional. A list of currencies ids (as bases) to subscribe to. If not provided it subscribes to all currencies
592+
:param result_callback: A callable of two arguments, takes either a CryptomarketAPIException, or the list of correctly subscribed currencies
593+
"""
594+
if currencies is None:
595+
currencies = ['*']
596+
params = args.DictBuilder().currencies_as_list(currencies).speed(
597+
speed).target_currency(target_currency).build()
598+
599+
def intercept_feed(feed, feed_type):
600+
callback({key: from_dict(data_class=WSPriceRate, data=feed[key])
601+
for key in feed})
602+
self._send_channeled_subscription(
603+
channel=f'price/rate/{speed}/batch',
604+
callback=intercept_feed,
605+
params=params,
606+
result_callback=result_callback
607+
)

cryptomarket/websockets/orderbook_cache.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ class SideOrder(Enum):
1616

1717
class OrderbookCache:
1818
def __init__(self):
19-
self.orderbooks = dict()
20-
self.ob_states = dict()
19+
self.orderbooks = {}
20+
self.ob_states = {}
2121

2222
def update(self, method: str, key:str, new_data: dict):
2323
if method == methodSnapshotOrderbook:

cryptomarket/websockets/trading_client.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -463,3 +463,12 @@ def intercept_result(err, response):
463463
callback(None, result)
464464
params = args.DictBuilder().symbol(symbol).build()
465465
self._send_by_id('spot_fee', callback=intercept_result, params=params)
466+
467+
###########
468+
# ALIASES #
469+
###########
470+
471+
get_spot_trading_balance = get_spot_trading_balance_of_currency
472+
get_spot_trading_balance_by_currency = get_spot_trading_balance_of_currency
473+
get_spot_commision = get_spot_commision_of_symbol
474+
get_spot_commision_by_symbol = get_spot_commision_of_symbol

cryptomarket/websockets/wallet_client.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,3 +243,10 @@ def intercept_response(err, response):
243243
callback=intercept_response,
244244
params=params
245245
)
246+
247+
###########
248+
# ALIASES #
249+
###########
250+
251+
get_wallet_balance_by_currency = get_wallet_balance_of_currency
252+
get_wallet_balance = get_wallet_balance_of_currency

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
setuptools.setup(
1919
name="cryptomarket",
20-
version="3.0.0",
20+
version="3.1.0",
2121
packages=['cryptomarket', 'cryptomarket.websockets'],
2222
include_package_data=True,
2323
description="Cryptomarket API client library",

0 commit comments

Comments
 (0)