Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 68 additions & 1 deletion src/blofin/api/trading.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,26 @@
from ..constants import (
FUTURES_ACCOUNT_BALANCE_ENDPOINT,
ACCOUNT_POSITIONS_ENDPOINT,
ACCOUNT_POSITIONS_ENDPOINT_CT,
ACCOUNT_MARGIN_MODE_ENDPOINT,
ACCOUNT_SET_MARGIN_MODE_ENDPOINT,
ACCOUNT_POSITION_MODE_ENDPOINT,
ACCOUNT_SET_POSITION_MODE_ENDPOINT,
ACCOUNT_BATCH_LEVERAGE_INFO_ENDPOINT,
ACCOUNT_SET_LEVERAGE_ENDPOINT,
ACCOUNT_SET_LEVERAGE_ENDPOINT_CT,
TRADE_ORDER_ENDPOINT,
TRADE_ORDER_ENDPOINT_CT,
TRADE_BATCH_ORDERS_ENDPOINT,
TRADE_ORDER_TPSL_ENDPOINT,
TRADE_CANCEL_ORDER_ENDPOINT,
TRADE_CANCEL_BATCH_ORDERS_ENDPOINT,
TRADE_CANCEL_TPSL_ENDPOINT,
TRADE_ORDERS_PENDING_ENDPOINT,
TRADE_ORDERS_PENDING_ENDPOINT_CT,
TRADE_ORDERS_TPSL_PENDING_ENDPOINT,
TRADE_CLOSE_POSITION_ENDPOINT,
TRADE_CLOSE_POSITION_ENDPOINT_CT,
TRADE_ORDERS_HISTORY_ENDPOINT,
TRADE_ORDERS_TPSL_HISTORY_ENDPOINT,
TRADE_FILLS_HISTORY_ENDPOINT,
Expand Down Expand Up @@ -50,6 +55,10 @@ def get_positions(self, inst_id: Optional[str] = None):
params = {'instId': inst_id} if inst_id else {}
return send_request('GET', ACCOUNT_POSITIONS_ENDPOINT, self.client.auth, params=params, authenticate=True)

def get_positions_ct(self, inst_id: Optional[str] = None):
params = {'instId': inst_id} if inst_id else {}
return send_request('GET', ACCOUNT_POSITIONS_ENDPOINT_CT, self.client.auth, params=params, authenticate=True)

def get_margin_mode(self):
return send_request('GET', ACCOUNT_MARGIN_MODE_ENDPOINT, self.client.auth, authenticate=True)

Expand Down Expand Up @@ -88,6 +97,18 @@ def set_leverage(self, inst_id: str, leverage: int, margin_mode: str, position_s
data['positionSide'] = position_side
return send_request('POST', ACCOUNT_SET_LEVERAGE_ENDPOINT, self.client.auth, data=data, authenticate=True)

def set_leverage_ct(self, inst_id: str, margin_mode: str, leverage: int, position_side: Optional[str] = None):
if margin_mode not in MARGIN_MODES:
raise BloFinParameterException(f"Invalid margin_mode. Must be one of: {', '.join(MARGIN_MODES)}")
data = {
'instId': inst_id,
'marginMode': margin_mode,
'leverage': leverage
}
if position_side:
data['positionSide'] = position_side
return send_request('POST', ACCOUNT_SET_LEVERAGE_ENDPOINT_CT, self.client.auth, data=data, authenticate=True)

def place_order(self, inst_id: str, margin_mode: str, position_side: str, side: str, order_type: str, price: float, size: float, **kwargs):
if margin_mode not in MARGIN_MODES:
raise BloFinParameterException(f"Invalid margin_mode. Must be one of: {', '.join(MARGIN_MODES)}")
Expand All @@ -110,6 +131,24 @@ def place_order(self, inst_id: str, margin_mode: str, position_side: str, side:
}
return send_request('POST', TRADE_ORDER_ENDPOINT, self.client.auth, data=data, authenticate=True)

def place_order_ct(self, inst_id: str, margin_mode: str, position_side: str, side: str, order_type: str, price: float, size: float, **kwargs):
if margin_mode not in MARGIN_MODES:
raise BloFinParameterException(f"Invalid margin_mode. Must be one of: {', '.join(MARGIN_MODES)}")
if position_side not in POSITION_SIDES:
raise BloFinParameterException(f"Invalid position_side. Must be one of: {', '.join(POSITION_SIDES)}")

data = {
'instId': inst_id,
'marginMode': margin_mode,
'positionSide': position_side,
'side': side,
'orderType': order_type,
'price': price,
'size': size,
**kwargs
}
return send_request('POST', TRADE_ORDER_ENDPOINT_CT, self.client.auth, data=data, authenticate=True)

def place_multiple_orders(self, orders: List[dict]):
return send_request('POST', TRADE_BATCH_ORDERS_ENDPOINT, self.client.auth, data=orders, authenticate=True)

Expand Down Expand Up @@ -159,6 +198,15 @@ def get_active_orders(self, inst_id: Optional[str] = None, order_type: Optional[
params = filter_none_params(instId=inst_id, orderType=order_type, state=state, after=after, before=before, limit=limit)
return send_request('GET', TRADE_ORDERS_PENDING_ENDPOINT, self.client.auth, params=params, authenticate=True)

def get_active_orders_ct(self, inst_id: Optional[str] = None, order_type: Optional[str] = None, state: Optional[str] = None, after: Optional[str] = None, before: Optional[str] = None, limit: Optional[int] = None):
if order_type and order_type not in ORDER_TYPES:
raise BloFinParameterException(f"Invalid order_type. Must be one of: {', '.join(ORDER_TYPES)}")
if state and state not in ORDER_STATES:
raise BloFinParameterException(f"Invalid state. Must be one of: {', '.join(ORDER_STATES)}")

params = filter_none_params(instId=inst_id, orderType=order_type, state=state, after=after, before=before, limit=limit)
return send_request('GET', TRADE_ORDERS_PENDING_ENDPOINT_CT, self.client.auth, params=params, authenticate=True)

def get_active_tpsl_orders(self, inst_id: Optional[str] = None, tpsl_id: Optional[str] = None, client_order_id: Optional[str] = None, after: Optional[str] = None, before: Optional[str] = None, limit: Optional[int] = None):
params = filter_none_params(instId=inst_id, tpslId=tpsl_id, clientOrderId=client_order_id, after=after, before=before, limit=limit)
return send_request('GET', TRADE_ORDERS_TPSL_PENDING_ENDPOINT, self.client.auth, params=params, authenticate=True)
Expand All @@ -178,6 +226,25 @@ def close_positions(self, inst_id: str, margin_mode: str, position_side: str, cl
data['clientOrderId'] = client_order_id
return send_request('POST', TRADE_CLOSE_POSITION_ENDPOINT, self.client.auth, data=data, authenticate=True)

def close_positions_ct(self, inst_id: str, margin_mode: str, position_side: str, client_order_id: Optional[str] = None, close_type: str = "pnl", size: Optional[float] = None):
if margin_mode not in MARGIN_MODES:
raise BloFinParameterException(f"Invalid margin_mode. Must be one of: {', '.join(MARGIN_MODES)}")
if position_side not in POSITION_SIDES:
raise BloFinParameterException(f"Invalid position_side. Must be one of: {', '.join(POSITION_SIDES)}")

data = {
'instId': inst_id,
'marginMode': margin_mode,
'positionSide': position_side,
'closeType': close_type
}
if client_order_id:
data['clientOrderId'] = client_order_id
if size:
data['size'] = size

return send_request('POST', TRADE_CLOSE_POSITION_ENDPOINT_CT, self.client.auth, data=data, authenticate=True)

def get_order_history(self, inst_id: Optional[str] = None, order_type: Optional[str] = None, state: Optional[str] = None, after: Optional[str] = None, before: Optional[str] = None, begin: Optional[str] = None, end: Optional[str] = None, limit: Optional[int] = None):
if order_type and order_type not in ORDER_TYPES:
raise BloFinParameterException(f"Invalid order_type. Must be one of: {', '.join(ORDER_TYPES)}")
Expand Down Expand Up @@ -431,4 +498,4 @@ def get_algo_order_history(self, inst_id: Optional[str] = None, algo_id: Optiona
limit=limit,
orderType=order_type
)
return send_request('GET', TRADE_ORDERS_ALGO_HISTORY_ENDPOINT, self.client.auth, params=params, authenticate=True)
return send_request('GET', TRADE_ORDERS_ALGO_HISTORY_ENDPOINT, self.client.auth, params=params, authenticate=True)
8 changes: 7 additions & 1 deletion src/blofin/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,27 +15,33 @@
# Trade endpoints
FUTURES_ACCOUNT_BALANCE_ENDPOINT = '/api/v1/account/balance'
ACCOUNT_POSITIONS_ENDPOINT = '/api/v1/account/positions'
ACCOUNT_POSITIONS_ENDPOINT_CT = '/api/v1/copytrading/account/positions-by-contract'
ACCOUNT_MARGIN_MODE_ENDPOINT = '/api/v1/account/margin-mode'
ACCOUNT_SET_MARGIN_MODE_ENDPOINT = '/api/v1/account/set-margin-mode'
ACCOUNT_POSITION_MODE_ENDPOINT = '/api/v1/account/position-mode'
ACCOUNT_SET_POSITION_MODE_ENDPOINT = '/api/v1/account/set-position-mode'
ACCOUNT_BATCH_LEVERAGE_INFO_ENDPOINT = '/api/v1/account/batch-leverage-info'
ACCOUNT_SET_LEVERAGE_ENDPOINT = '/api/v1/account/set-leverage'
ACCOUNT_SET_LEVERAGE_ENDPOINT_CT = '/api/v1/copytrading/account/set-leverage'
TRADE_ORDER_ENDPOINT = '/api/v1/trade/order'
TRADE_ORDER_ENDPOINT_CT = '/api/v1/copytrading/trade/place-order'
TRADE_BATCH_ORDERS_ENDPOINT = '/api/v1/trade/batch-orders'
TRADE_ORDER_TPSL_ENDPOINT = '/api/v1/trade/order-tpsl'
TRADE_CANCEL_ORDER_ENDPOINT = '/api/v1/trade/cancel-order'
TRADE_CANCEL_BATCH_ORDERS_ENDPOINT = '/api/v1/trade/cancel-batch-orders'
TRADE_CANCEL_TPSL_ENDPOINT = '/api/v1/trade/cancel-tpsl'
TRADE_ORDERS_PENDING_ENDPOINT = '/api/v1/trade/orders-pending'
TRADE_ORDERS_PENDING_ENDPOINT_CT = '/api/v1/copytrading/trade/orders-pending'
TRADE_ORDERS_TPSL_PENDING_ENDPOINT = '/api/v1/trade/orders-tpsl-pending'
TRADE_CLOSE_POSITION_ENDPOINT = '/api/v1/trade/close-position'
TRADE_CLOSE_POSITION_ENDPOINT_CT = '/api/v1/copytrading/trade/close-position-by-contract'
TRADE_ORDERS_HISTORY_ENDPOINT = '/api/v1/trade/orders-history'
TRADE_ORDERS_TPSL_HISTORY_ENDPOINT = '/api/v1/trade/orders-tpsl-history'
TRADE_FILLS_HISTORY_ENDPOINT = '/api/v1/trade/fills-history'

# Public API Endpoints
PUBLIC_INSTRUMENTS_ENDPOINT = '/api/v1/market/instruments'
#PUBLIC_INSTRUMENTS_ENDPOINT_CT = '/api/v1/copytrading/instruments' # useless
PUBLIC_TICKERS_ENDPOINT = '/api/v1/market/tickers'
PUBLIC_ORDER_BOOK_ENDPOINT = '/api/v1/market/books'
PUBLIC_TRADES_ENDPOINT = '/api/v1/market/trades'
Expand Down Expand Up @@ -218,4 +224,4 @@
TRADING_MAX_ORDER_SIZE = 1000

# Algo trading max order size
ALGO_MAX_LIMIT = 100
ALGO_MAX_LIMIT = 100