|
@@ -448,76 +448,96 @@ class HyperliquidClient:
|
|
|
logger.error(f"❌ Error loading markets: {error_message} (Full exception: {e})")
|
|
|
return None
|
|
|
|
|
|
- def place_stop_loss_order(self, symbol: str, side: str, amount: float, price: float, params: Optional[Dict] = None) -> Tuple[Optional[Dict[str, Any]], Optional[str]]:
|
|
|
+ def place_stop_loss_order(self, symbol: str, side: str, amount: float, stop_price_arg: float, params: Optional[Dict] = None) -> Tuple[Optional[Dict[str, Any]], Optional[str]]:
|
|
|
"""
|
|
|
- Place a stop loss order (implemented as a limit order).
|
|
|
+ Place a stop loss order (as a stop-market order).
|
|
|
Returns a tuple: (order_object, error_message_string).
|
|
|
Error_message_string is None on success. Order_object is None on failure.
|
|
|
|
|
|
Args:
|
|
|
symbol: Trading symbol (e.g., 'BTC/USDC:USDC')
|
|
|
- side: 'buy' or 'sell'
|
|
|
+ side: 'buy' or 'sell' (side of the order to be placed when stop is triggered)
|
|
|
amount: Order amount
|
|
|
- price: Stop loss price
|
|
|
- params: Additional parameters for CCXT compatibility
|
|
|
+ stop_price_arg: The price at which the stop loss triggers
|
|
|
+ params: Additional parameters (mostly unused now, but kept for signature compatibility)
|
|
|
"""
|
|
|
try:
|
|
|
if not self.sync_client:
|
|
|
logger.error("❌ Client not initialized")
|
|
|
return None, "Client not initialized"
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ trigger_params = {
|
|
|
+ 'trigger': {
|
|
|
+ 'triggerPx': str(stop_price_arg),
|
|
|
+ 'isMarket': True,
|
|
|
+ 'tpsl': 'sl'
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
-
|
|
|
-
|
|
|
- order_params = params or {}
|
|
|
-
|
|
|
-
|
|
|
- logger.info(f"🛑 Placing stop loss order: {side} {amount} {symbol} @ ${price}")
|
|
|
-
|
|
|
- order = self.sync_client.create_limit_order(symbol, side, amount, price, params=order_params)
|
|
|
-
|
|
|
- logger.info(f"✅ Successfully placed stop loss order for {amount} {symbol} at ${price}")
|
|
|
- logger.debug(f"📄 Stop loss order details: {order}")
|
|
|
+
|
|
|
+ if params:
|
|
|
+ trigger_params.update(params)
|
|
|
+
|
|
|
+ logger.info(f"🛑 Placing STOP-MARKET order: {side} {amount} {symbol} with trigger @ ${stop_price_arg:.4f}")
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ order = self.sync_client.create_order(
|
|
|
+ symbol,
|
|
|
+ 'market',
|
|
|
+ side,
|
|
|
+ amount,
|
|
|
+ None,
|
|
|
+ params=trigger_params
|
|
|
+ )
|
|
|
+
|
|
|
+ logger.info(f"✅ Successfully placed stop-market order for {amount} {symbol}, trigger @ ${stop_price_arg:.4f}")
|
|
|
+ logger.debug(f"📄 Stop-market order details: {order}")
|
|
|
|
|
|
return order, None
|
|
|
except Exception as e:
|
|
|
error_message = self._extract_error_message(e)
|
|
|
- logger.error(f"❌ Error placing stop loss order: {error_message} (Full exception: {e})")
|
|
|
+ logger.error(f"❌ Error placing stop-market order: {error_message} (Full exception: {e})")
|
|
|
return None, error_message
|
|
|
|
|
|
- def place_take_profit_order(self, symbol: str, side: str, amount: float, price: float, params: Optional[Dict] = None) -> Tuple[Optional[Dict[str, Any]], Optional[str]]:
|
|
|
+ def place_take_profit_order(self, symbol: str, side: str, amount: float, take_profit_price_arg: float, params: Optional[Dict] = None) -> Tuple[Optional[Dict[str, Any]], Optional[str]]:
|
|
|
"""
|
|
|
- Place a take profit order (implemented as a limit order).
|
|
|
+ Place a take profit order (as a limit order, or can be adapted to trigger like SL).
|
|
|
+ Currently places a limit order. For true TP trigger, needs similar logic to SL.
|
|
|
Returns a tuple: (order_object, error_message_string).
|
|
|
- Error_message_string is None on success. Order_object is None on failure.
|
|
|
|
|
|
Args:
|
|
|
- symbol: Trading symbol (e.g., 'BTC/USDC:USDC')
|
|
|
+ symbol: Trading symbol
|
|
|
side: 'buy' or 'sell'
|
|
|
amount: Order amount
|
|
|
- price: Take profit price
|
|
|
- params: Additional parameters for CCXT compatibility
|
|
|
+ take_profit_price_arg: The price for the take profit order
|
|
|
+ params: Additional parameters
|
|
|
"""
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ logger.warning("⚠️ place_take_profit_order currently places a LIMIT order. For triggered TP, it needs updating similar to SL.")
|
|
|
try:
|
|
|
if not self.sync_client:
|
|
|
logger.error("❌ Client not initialized")
|
|
|
return None, "Client not initialized"
|
|
|
|
|
|
-
|
|
|
-
|
|
|
order_params = params or {}
|
|
|
|
|
|
-
|
|
|
- logger.info(f"🎯 Placing take profit order: {side} {amount} {symbol} @ ${price}")
|
|
|
+ logger.info(f"🎯 Placing take profit (LIMIT) order: {side} {amount} {symbol} @ ${take_profit_price_arg}")
|
|
|
|
|
|
- order = self.sync_client.create_limit_order(symbol, side, amount, price, params=order_params)
|
|
|
+ order = self.sync_client.create_limit_order(symbol, side, amount, take_profit_price_arg, params=order_params)
|
|
|
|
|
|
- logger.info(f"✅ Successfully placed take profit order for {amount} {symbol} at ${price}")
|
|
|
+ logger.info(f"✅ Successfully placed take profit (LIMIT) order for {amount} {symbol} at ${take_profit_price_arg}")
|
|
|
logger.debug(f"📄 Take profit order details: {order}")
|
|
|
|
|
|
return order, None
|
|
|
except Exception as e:
|
|
|
error_message = self._extract_error_message(e)
|
|
|
- logger.error(f"❌ Error placing take profit order: {error_message} (Full exception: {e})")
|
|
|
+ logger.error(f"❌ Error placing take profit (LIMIT) order: {error_message} (Full exception: {e})")
|
|
|
return None, error_message
|
|
|
|
|
|
def get_recent_fills(self, limit: int = 100) -> Optional[List[Dict[str, Any]]]:
|