Skip to content

Commit

Permalink
updating (#3)
Browse files Browse the repository at this point in the history
  • Loading branch information
hftcryptobot authored Apr 17, 2024
1 parent a7aacfd commit 945a8a2
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 57 deletions.
38 changes: 21 additions & 17 deletions example.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from datetime import datetime, timedelta
from time import sleep

from hftcryptoapi.bitmart import Bitmart
from hftcryptoapi.bitmart.data.constants import *
Expand All @@ -23,24 +24,27 @@
contracts_details = client.get_futures_contracts_details()
symbol_details = client.get_spot_ticker_details(symbol_spot)
kline_steps = client.get_kline_steps() # Not used
print(
client.get_symbol_kline(
symbol="BTC_USDT",
tf=TimeFrame.tf_1h,
market=Market.SPOT,
from_time=from_time,
to_time=to_time
)

btc_usdt_klines = client.get_symbol_kline(
symbol="BTC_USDT",
tf=TimeFrame.tf_1h,
market=Market.SPOT,
from_time=from_time,
to_time=to_time
)
print(
client.get_symbol_kline(
symbol=symbol,
tf=TimeFrame.tf_1h,
market=Market.FUTURES,
from_time=from_time,
to_time=to_time
)
for kline in btc_usdt_klines:
print(str(kline))

symbol_klines = client.get_symbol_kline(
symbol=symbol,
tf=TimeFrame.tf_1h,
market=Market.FUTURES,
from_time=from_time,
to_time=to_time
)
for kline in symbol_klines:
print(str(kline))

bt_trades = client.get_symbol_recent_trades(symbol_spot, N=100)
depth_futures = client.get_symbol_depth(symbol=symbol_spot, precision=6, size=50, market=Market.SPOT)
depth_spot = client.get_symbol_depth(symbol=symbol, precision=6, size=50, market=Market.FUTURES)
Expand All @@ -59,7 +63,7 @@
client.subscribe_public(Market.FUTURES, [BtFuturesSocketKlineChannels.K_LINE_CHANNEL_1HOUR,
BtFuturesSocketDepthChannels.DEPTH_CHANNEL_5LEVEL], [symbol])

client.start_websockets(Market.FUTURES, on_message=lambda message: print(f' {message}'))
client.start_websockets(Market.FUTURES, on_message=lambda message: print(f'Message: {message}'))
client.subscribe_public(Market.SPOT, [BtSpotSocketKlineChannels.K_LINE_CHANNEL_1HOUR,
BtSpotSocketDepthChannels.DEPTH_CHANNEL_5LEVEL,
BtSpotTradeChannel,
Expand Down
107 changes: 70 additions & 37 deletions hftcryptoapi/bitmart/Bitmart.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,23 @@

class BitmartClient(PyClient):

def __init__(self, api_key: Optional[str] = None, secret_key: Optional[str] = None, memo: Optional[str] = None,
url: str = API_URL, timeout: tuple = TIMEOUT):
def __init__(
self,
api_key: Optional[str] = None,
secret_key: Optional[str] = None,
memo: Optional[str] = None,
url: str = API_URL,
timeout: tuple = TIMEOUT
):
PyClient.__init__(self, api_key, secret_key, memo, url, timeout)
self.ws_public: Dict[Union[Market], BitmartWs] = {Market.SPOT: BitmartWs(WS_URL, Market.SPOT),
Market.FUTURES: BitmartWs(CONTRACT_WS_URL, Market.FUTURES)}
self.ws_public: Dict[Union[Market], BitmartWs] = {
Market.SPOT: BitmartWs(WS_URL, Market.SPOT),
Market.FUTURES: BitmartWs(CONTRACT_WS_URL, Market.FUTURES)
}
self.ws_private: Dict[Union[Market], BitmartWs] = {
Market.SPOT: BitmartWs(WS_URL_USER, Market.SPOT, api_key, memo, secret_key),
Market.FUTURES: BitmartWs(CONTRACT_WS_URL_USER, Market.FUTURES, api_key, memo, secret_key)}
Market.FUTURES: BitmartWs(CONTRACT_WS_URL_USER, Market.FUTURES, api_key, memo, secret_key)
}

def subscribe_private(self, market: Market, channels: List[str], symbols: Optional[List[str]] = None):
self.ws_private[market].subscribe(channels, symbols)
Expand All @@ -38,8 +47,8 @@ def stop_websockets(self, market: Market):
self.ws_private[market].stop()

def wait_for_socket_connection(self, market: Market, is_public: bool = True):
ws = self.ws_public[market] if is_public else self.ws_private[market]
while not ws.is_connected:
socket = self.ws_public[market] if is_public else self.ws_private[market]
while not socket.is_connected:
sleep(1)

def get_system_time(self) -> datetime:
Expand Down Expand Up @@ -127,10 +136,12 @@ def get_ticker_of_all_pairs(self):
best_bid_size = ticker['best_bid_size']
fluctuation = ticker['fluctuation']
timestamp = ticker['timestamp']
currency_details = SpotTickerDetails(symbol, last_price, quote_volume_24h, base_volume_24h, high_24h,
low_24h, open_24h, close_24h, best_ask, best_ask_size, best_bid,
best_bid_size,
fluctuation, timestamp)
currency_details = SpotTickerDetails(
symbol, last_price, quote_volume_24h, base_volume_24h, high_24h,
low_24h, open_24h, close_24h, best_ask, best_ask_size, best_bid,
best_bid_size,
fluctuation, timestamp
)
list_currency_details.append(currency_details)

return list_currency_details
Expand All @@ -139,8 +150,14 @@ def get_kline_steps(self):
response = self._request_without_params(GET, SPOT_K_LIE_STEP)
return json.loads(response.content)['data']['steps']

def get_symbol_kline(self, symbol: str, from_time: datetime, to_time: datetime, tf: TimeFrame = TimeFrame.tf_1d,
market=Market.SPOT) -> List[Kline]:
def get_symbol_kline(
self,
symbol: str,
from_time: datetime,
to_time: datetime,
tf: TimeFrame = TimeFrame.tf_1d,
market=Market.SPOT
) -> List[Kline]:
klines_data = []

if market == Market.SPOT:
Expand Down Expand Up @@ -340,9 +357,11 @@ def get_order_details(self, symbol: str, order_id: str, market=Market.SPOT) -> B
return self.update_order_details(o)

# GET https://api-cloud.bitmart.com/spot/v3/orders
def get_order_history(self, symbol: str, market=Market.SPOT,
start_time: Optional[datetime] = None,
end_time: Optional[datetime] = None) -> List[BitmartOrder]:
def get_order_history(
self, symbol: str, market=Market.SPOT,
start_time: Optional[datetime] = None,
end_time: Optional[datetime] = None
) -> List[BitmartOrder]:

orders = []
if market == Market.SPOT:
Expand Down Expand Up @@ -390,11 +409,13 @@ def get_order_history(self, symbol: str, market=Market.SPOT,
return orders

# Unified methods for trading
def submit_order(self, symbol: str, side: Union[FuturesSide, SpotSide],
price: Optional[float] = None, size: Optional[float] = 0, order_type: OrderType = OrderType.LIMIT,
market: Market = Market.SPOT, leverage: Optional[int] = 1,
open_type: OrderOpenType = OrderOpenType.ISOLATED,
client_order_id: Optional[str] = None):
def submit_order(
self, symbol: str, side: Union[FuturesSide, SpotSide],
price: Optional[float] = None, size: Optional[float] = 0, order_type: OrderType = OrderType.LIMIT,
market: Market = Market.SPOT, leverage: Optional[int] = 1,
open_type: OrderOpenType = OrderOpenType.ISOLATED,
client_order_id: Optional[str] = None
):

bm_order = BitmartOrder(symbol, side, size, price, market, order_type, leverage, open_type, client_order_id)
if market == Market.SPOT:
Expand Down Expand Up @@ -470,8 +491,10 @@ def get_account_balance(self, market=Market.SPOT) -> BitmartWallet:

return bitmart_wallet

def close_futures_position(self, symbol: str, position_side: Position,
open_type: OrderOpenType = OrderOpenType.CROSS) -> bool:
def close_futures_position(
self, symbol: str, position_side: Position,
open_type: OrderOpenType = OrderOpenType.CROSS
) -> bool:
is_cross = open_type == OrderOpenType.CROSS
order_side = FuturesSide.SELL_CLOSE_LONG if position_side == Position.LONG else FuturesSide.BUY_CLOSE_SHORT
positions = self.get_futures_position_details(symbol)
Expand All @@ -486,33 +509,43 @@ def close_futures_position(self, symbol: str, position_side: Position,

order_open_type = OrderOpenType.CROSS if is_cross and p.position_cross else OrderOpenType.ISOLATED

self.submit_order(market=Market.FUTURES, symbol=symbol, order_type=OrderType.MARKET,
side=order_side,
size=size, open_type=order_open_type)
self.submit_order(
market=Market.FUTURES, symbol=symbol, order_type=OrderType.MARKET,
side=order_side,
size=size, open_type=order_open_type
)
result = True

return result

def spot_margin_borrow(self, symbol: str, currency: str, amount: float) -> str:
response = self._request_with_params(POST, MARGIN_BORROW,
params=dict(symbol=symbol, currency=currency, amount=amount),
auth=Auth.SIGNED)
response = self._request_with_params(
POST, MARGIN_BORROW,
params=dict(symbol=symbol, currency=currency, amount=amount),
auth=Auth.SIGNED
)
borrow_id = json.loads(response.content)['data']['borrow_id']

return borrow_id

def spot_margin_repay(self, symbol: str, currency: str, amount: float) -> str:
response = self._request_with_params(POST, MARING_REPAY,
params=dict(symbol=symbol, currency=currency, amount=amount),
auth=Auth.SIGNED)
def spot_margin_repay(
self, symbol: str, currency: str, amount: float
) -> str:
response = self._request_with_params(
POST, MARING_REPAY,
params=dict(symbol=symbol, currency=currency, amount=amount),
auth=Auth.SIGNED
)
repay_id = json.loads(response.content)['data']['repay_id']

return repay_id

def spot_margin_get_borrow_record(self, symbol: str, borrow_id: Optional[str] = None,
start_time: Optional[datetime] = None,
end_time: Optional[datetime] = None,
records_count: Optional[int] = None) -> List[BorrowRecord]:
def spot_margin_get_borrow_record(
self, symbol: str, borrow_id: Optional[str] = None,
start_time: Optional[datetime] = None,
end_time: Optional[datetime] = None,
records_count: Optional[int] = None
) -> List[BorrowRecord]:

params = dict(symbol=symbol)
if borrow_id is not None:
Expand Down
23 changes: 21 additions & 2 deletions hftcryptoapi/bitmart/data/rest.py
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,7 @@ def __init__(self, symbol, last_price, quote_volume_24h, base_volume_24h, high_2
self.date_time = datetime.fromtimestamp(timestamp / 1000)
self.funding_rate = None
self.funding_rate_datetime = None
self.url = url

def __str__(self):
return f"{self.symbol}: {self.last_price} ({self.base_volume_24h})"
Expand All @@ -270,10 +271,23 @@ def __init__(self, timestamp, symbol, open_interest, open_interest_value):


class FuturesFundingRate(object):
def __init__(self, timestamp, symbol, rate_value):
def __init__(
self,
timestamp,
symbol,
rate_value,
expected_rate,
funding_time,
funding_upper_limit,
funding_lower_limit
):
self.symbol = symbol
self.timestamp = datetime.fromtimestamp(timestamp / 1000)
self.rate_value = float(rate_value)
self.expected_rate = expected_rate
self.funding_time = funding_time
self.funding_upper_limit = funding_upper_limit
self.funding_lower_limit = funding_lower_limit


class TickerFuturesWebSocket(object):
Expand Down Expand Up @@ -362,7 +376,8 @@ def __init__(self, symbol, product_type, base_currency, quote_currency, vol_prec
max_volume, min_volume,
contract_size, index_price, index_name, min_leverage, max_leverage, turnover_24h,
volume_24h, last_price,
open_timestamp, expire_timestamp, settle_timestamp):
open_timestamp, expire_timestamp, settle_timestamp,
funding_rate, expected_funding_rate, open_interest, open_interest_value):
self.symbol = symbol
self.product_type = FuturesContractType.PERPETUAL if int(product_type) == 1 else FuturesContractType.FUTURES
self.base_currency = base_currency
Expand All @@ -382,6 +397,10 @@ def __init__(self, symbol, product_type, base_currency, quote_currency, vol_prec
self.open_date_time = datetime.fromtimestamp(open_timestamp / 1000)
self.expire_date_time = datetime.fromtimestamp(expire_timestamp / 1000)
self.settle_date_time = datetime.fromtimestamp(settle_timestamp / 1000)
self.funding_rate = funding_rate
self.expected_funding_rate = expected_funding_rate
self.open_interest = open_interest
self.open_interest_value = open_interest_value


class BitmartSpotSymbolDetails(object):
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ license = { file = "LICENSE" }
classifiers = ["Programming Language :: Python :: 3"]
dependencies = [
"requests==2.23.0",
"urllib3==1.21.1",
"urllib3==1.26",
"utils==1.0.1",
"websockets>=9.1",
"pytest==6.2.1",
Expand Down

0 comments on commit 945a8a2

Please sign in to comment.