Skip to content

Commit

Permalink
Merge branch 'hummingbot:development' into development
Browse files Browse the repository at this point in the history
  • Loading branch information
geneuinely07 authored Sep 7, 2023
2 parents c3f1017 + 579912f commit 8cba8ad
Show file tree
Hide file tree
Showing 42 changed files with 3,637 additions and 202 deletions.
2 changes: 2 additions & 0 deletions hummingbot/connector/connector_status.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@
'injective_v2': 'bronze',
'injective_v2_perpetual': 'bronze',
'plenty': 'bronze',
'woo_x': 'bronze',
'woo_x_testnet': 'bronze',
}

warning_messages = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,20 +38,19 @@


class DydxPerpetualDerivative(PerpetualDerivativePyBase):

web_utils = web_utils

def __init__(
self,
client_config_map: "ClientConfigAdapter",
dydx_perpetual_api_key: str,
dydx_perpetual_api_secret: str,
dydx_perpetual_passphrase: str,
dydx_perpetual_ethereum_address: str,
dydx_perpetual_stark_private_key: str,
trading_pairs: Optional[List[str]] = None,
trading_required: bool = True,
domain: str = CONSTANTS.DEFAULT_DOMAIN,
self,
client_config_map: "ClientConfigAdapter",
dydx_perpetual_api_key: str,
dydx_perpetual_api_secret: str,
dydx_perpetual_passphrase: str,
dydx_perpetual_ethereum_address: str,
dydx_perpetual_stark_private_key: str,
trading_pairs: Optional[List[str]] = None,
trading_required: bool = True,
domain: str = CONSTANTS.DEFAULT_DOMAIN,
):
self._dydx_perpetual_api_key = dydx_perpetual_api_key
self._dydx_perpetual_api_secret = dydx_perpetual_api_secret
Expand Down Expand Up @@ -223,15 +222,15 @@ async def _place_cancel(self, order_id: str, tracked_order: InFlightOrder):
return True

async def _place_order(
self,
order_id: str,
trading_pair: str,
amount: Decimal,
trade_type: TradeType,
order_type: OrderType,
price: Decimal,
position_action: PositionAction = PositionAction.NIL,
**kwargs,
self,
order_id: str,
trading_pair: str,
amount: Decimal,
trade_type: TradeType,
order_type: OrderType,
price: Decimal,
position_action: PositionAction = PositionAction.NIL,
**kwargs,
) -> Tuple[str, float]:
if self._current_place_order_requests == 0:
# No requests are under way, the dictionary can be cleaned
Expand All @@ -240,12 +239,29 @@ async def _place_order(
# Increment number of currently undergoing requests
self._current_place_order_requests += 1

if order_type.is_limit_type():
time_in_force = CONSTANTS.TIF_GOOD_TIL_TIME
else:
time_in_force = CONSTANTS.TIF_IMMEDIATE_OR_CANCEL
if trade_type.name.lower() == 'buy':
# The price needs to be relatively high before the transaction, whether the test will be cancelled
price = Decimal("1.5") * self.get_price_for_volume(
trading_pair,
True,
amount
).result_price
else:
price = Decimal("0.75") * self.get_price_for_volume(
trading_pair,
False,
amount
).result_price

notional_amount = amount * price
if notional_amount not in self._order_notional_amounts.keys():
self._order_notional_amounts[notional_amount] = len(self._order_notional_amounts.keys())
# Set updated rate limits
self._throttler.set_rate_limits(self.rate_limits_rules)

size = str(amount)
price = str(price)
side = "BUY" if trade_type == TradeType.BUY else "SELL"
Expand All @@ -254,7 +270,6 @@ async def _place_order(
reduce_only = False

post_only = order_type is OrderType.LIMIT_MAKER
time_in_force = CONSTANTS.TIF_GOOD_TIL_TIME
market = await self.exchange_symbol_associated_to_pair(trading_pair)

signature = self._auth.get_order_signature(
Expand Down Expand Up @@ -307,15 +322,15 @@ async def _place_order(
return str(resp["order"]["id"]), iso_to_epoch_seconds(resp["order"]["createdAt"])

def _get_fee(
self,
base_currency: str,
quote_currency: str,
order_type: OrderType,
order_side: TradeType,
position_action: PositionAction,
amount: Decimal,
price: Decimal = s_decimal_NaN,
is_maker: Optional[bool] = None,
self,
base_currency: str,
quote_currency: str,
order_type: OrderType,
order_side: TradeType,
position_action: PositionAction,
amount: Decimal,
price: Decimal = s_decimal_NaN,
is_maker: Optional[bool] = None,
) -> TradeFeeBase:
is_maker = is_maker or False
if CONSTANTS.FEES_KEY not in self._trading_fees.keys():
Expand Down Expand Up @@ -541,8 +556,8 @@ async def _process_funding_payments(self, funding_payments: List):
if trading_pair not in prev_timestamps.keys():
prev_timestamps[trading_pair] = None
if (
prev_timestamps[trading_pair] is not None
and dateparse(funding_payment["effectiveAt"]).timestamp() <= prev_timestamps[trading_pair]
prev_timestamps[trading_pair] is not None
and dateparse(funding_payment["effectiveAt"]).timestamp() <= prev_timestamps[trading_pair]
):
continue
timestamp = dateparse(funding_payment["effectiveAt"]).timestamp()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -703,9 +703,14 @@ async def _update_positions(self):
hb_trading_pair = await self.trading_pair_associated_to_exchange_symbol(ex_trading_pair)

amount = Decimal(position.get("size"))
position_side = PositionSide.LONG if Decimal(position.get("size")) > 0 else PositionSide.SHORT

pos_key = self._perpetual_trading.position_key(hb_trading_pair, position_side)
ex_mode = position.get("mode")
if ex_mode == 'single':
mode = PositionMode.ONEWAY
position_side = PositionSide.LONG if Decimal(position.get("size")) > 0 else PositionSide.SHORT
else:
mode = PositionMode.HEDGE
position_side = PositionSide.LONG if ex_mode == "dual_long" else PositionSide.SHORT
pos_key = self._perpetual_trading.position_key(hb_trading_pair, position_side, mode)

if amount != 0:
trading_rule = self._trading_rules[hb_trading_pair]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@

TRANSACTIONS_CHECK_INTERVAL = CONSTANTS.TRANSACTIONS_CHECK_INTERVAL

RATE_LIMITS = CONSTANTS.RATE_LIMITS

ORDER_STATE_MAP = CONSTANTS.ORDER_STATE_MAP

ORDER_NOT_FOUND_ERROR_MESSAGE = CONSTANTS.ORDER_NOT_FOUND_ERROR_MESSAGE
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ def __init__(
self._trading_required = trading_required
self._trading_pairs = trading_pairs
self._data_source = connector_configuration.create_data_source()
self._rate_limits = connector_configuration.network.rate_limits()

super().__init__(client_config_map=client_config_map)
self._data_source.configure_throttler(throttler=self._throttler)
Expand All @@ -85,7 +86,7 @@ def authenticator(self) -> AuthBase:

@property
def rate_limits_rules(self) -> List[RateLimit]:
return CONSTANTS.RATE_LIMITS
return self._rate_limits

@property
def domain(self) -> str:
Expand Down Expand Up @@ -543,6 +544,7 @@ def _update_order_after_creation_success(
new_state=order.current_state,
misc_updates=misc_updates,
)
self.logger().debug(f"\nCreated order {order.client_order_id} ({exchange_order_id}) with TX {misc_updates}")
self._order_tracker.process_order_update(order_update)

def _on_order_creation_failure(
Expand Down Expand Up @@ -1010,7 +1012,10 @@ def _process_transaction_event(self, transaction_event: Dict[str, Any]):
async def _check_orders_transactions(self):
while True:
try:
await self._check_orders_creation_transactions()
# Executing the process shielded from this async task to isolate it from network disconnections
# (network disconnections cancel this task)
task = asyncio.create_task(self._check_orders_creation_transactions())
await asyncio.shield(task)
await self._sleep(CONSTANTS.TRANSACTIONS_CHECK_INTERVAL)
except NotImplementedError:
raise
Expand Down Expand Up @@ -1086,7 +1091,10 @@ async def _check_created_orders_status_for_transaction(self, transaction_hash: s
async def _process_queued_orders(self):
while True:
try:
await self._cancel_and_create_queued_orders()
# Executing the batch cancelation and creation process shielded from this async task to isolate the
# creation/cancelation process from network disconnections (network disconnections cancel this task)
task = asyncio.create_task(self._cancel_and_create_queued_orders())
await asyncio.shield(task)
sleep_time = (self.clock.tick_size * 0.5
if self.clock is not None
else self._orders_processing_delta_time)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,9 @@ def validate_account_type(cls, v: Union[(str, Dict) + tuple(ACCOUNT_MODES.values

def create_data_source(self):
return self.account_type.create_data_source(
network=self.network.network(), use_secure_connection=self.network.use_secure_connection()
network=self.network.network(),
use_secure_connection=self.network.use_secure_connection(),
rate_limits=self.network.rate_limits(),
)


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -475,7 +475,7 @@ cdef class BitfinexExchange(ExchangeBase):
http_method: str,
url,
headers,
data_str: Optional[str, list] = None) -> list:
data_str = None) -> list:
"""
A wrapper for submitting API requests to Bitfinex
:returns: json data from the endpoints
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,8 @@ async def create_orders(
except asyncio.CancelledError:
raise
except Exception as ex:
self.logger().debug(
f"Error broadcasting transaction to create orders (message: {order_creation_messages})")
results = self._place_order_results(
orders_to_create=spot_orders + perpetual_orders,
order_hashes=spot_order_hashes + derivative_order_hashes,
Expand Down Expand Up @@ -501,34 +503,36 @@ async def cancel_orders(
derivative_orders_data.append(order_data)
orders_with_hash.append(order)

delegated_message = self._order_cancel_message(
spot_orders_to_cancel=spot_orders_data,
derivative_orders_to_cancel=derivative_orders_data,
)
if len(orders_with_hash) > 0:
delegated_message = self._order_cancel_message(
spot_orders_to_cancel=spot_orders_data,
derivative_orders_to_cancel=derivative_orders_data,
)

try:
result = await self._send_in_transaction(messages=[delegated_message])
if result["rawLog"] != "[]":
raise ValueError(f"Error sending the order cancel transaction ({result['rawLog']})")
else:
cancel_transaction_hash = result.get("txhash", "")
try:
result = await self._send_in_transaction(messages=[delegated_message])
if result["rawLog"] != "[]":
raise ValueError(f"Error sending the order cancel transaction ({result['rawLog']})")
else:
cancel_transaction_hash = result.get("txhash", "")
results.extend([
CancelOrderResult(
client_order_id=order.client_order_id,
trading_pair=order.trading_pair,
misc_updates={"cancelation_transaction_hash": cancel_transaction_hash},
) for order in orders_with_hash
])
except asyncio.CancelledError:
raise
except Exception as ex:
self.logger().debug(f"Error broadcasting transaction to cancel orders (message: {delegated_message})")
results.extend([
CancelOrderResult(
client_order_id=order.client_order_id,
trading_pair=order.trading_pair,
misc_updates={"cancelation_transaction_hash": cancel_transaction_hash},
exception=ex,
) for order in orders_with_hash
])
except asyncio.CancelledError:
raise
except Exception as ex:
results.extend([
CancelOrderResult(
client_order_id=order.client_order_id,
trading_pair=order.trading_pair,
exception=ex,
) for order in orders_with_hash
])

return results

Expand Down Expand Up @@ -739,7 +743,7 @@ def _uses_default_portfolio_subaccount(self) -> bool:
raise NotImplementedError

@abstractmethod
def _calculate_order_hashes(
async def _calculate_order_hashes(
self,
spot_orders: List[GatewayInFlightOrder],
derivative_orders: [GatewayPerpetualInFlightOrder]
Expand Down Expand Up @@ -804,9 +808,10 @@ async def _last_traded_price(self, market_id: str) -> Decimal:
market_ids=[market_id],
limit=1,
)
if len(trades_response["trades"]) > 0:
trades = trades_response.get("trades", [])
if len(trades) > 0:
price = market.price_from_chain_format(
chain_price=Decimal(trades_response["trades"][0]["price"]["price"]))
chain_price=Decimal(trades[0]["price"]["price"]))

else:
market = await self.derivative_market_info_for_id(market_id=market_id)
Expand All @@ -815,7 +820,8 @@ async def _last_traded_price(self, market_id: str) -> Decimal:
market_ids=[market_id],
limit=1,
)
if len(trades_response["trades"]) > 0:
trades = trades_response.get("trades", [])
if len(trades) > 0:
price = market.price_from_chain_format(
chain_price=Decimal(trades_response["trades"][0]["positionDelta"]["executionPrice"]))

Expand All @@ -829,7 +835,7 @@ async def _transaction_from_chain(self, tx_hash: str, retries: int) -> int:
while executed_tries < retries and not found:
executed_tries += 1
try:
async with self.throttler.execute_task(limit_id=CONSTANTS.SPOT_ORDERS_HISTORY_LIMIT_ID):
async with self.throttler.execute_task(limit_id=CONSTANTS.GET_TRANSACTION_CHAIN_LIMIT_ID):
block_height = await self.query_executor.get_tx_block_height(tx_hash=tx_hash)
found = True
except ValueError:
Expand Down
Loading

0 comments on commit 8cba8ad

Please sign in to comment.