Kalshi perpetual - LIMIT and LIMIT_MAKER close orders can open a position instead of reducing one
Author: rapcmiaCreated Sep 17, 2026Updated Sep 17, 2026
Labelsbug
Describe the bug
A take-profit order meant only to reduce an open position was accepted by Kalshi as an ordinary opening order. Hummingbot marks it CLOSE internally, but the request carries no reduce-only flag, so Kalshi treats it like any other order.
026-09-17 21:42:00,019 - 352472 - hummingbot.connector.derivative.kalshi_perpetual.kalshi_perpetual_derivative.KalshiPerpetualDerivative - NETWORK - Error submitting buy LIMIT_MAKER order to Kalshi_perpetual for 0.000100 BTC-USD 76100.
Traceback (most recent call last):
File "/home/eddga/hummingbot/hummingbot/8454/hummingbot/connector/exchange_py_base.py", line 462, in _create_order
await self._place_order_and_process_update(order=order, **kwargs,)
File "/home/eddga/hummingbot/hummingbot/8454/hummingbot/connector/derivative/kalshi_perpetual/kalshi_perpetual_derivative.py", line 328, in _place_order_and_process_update
exchange_order_id, update_timestamp = await self._place_order(
^^^^^^^^^^^^^^^^^^^^^^^^
...<7 lines>...
)
^
File "/home/eddga/hummingbot/hummingbot/8454/hummingbot/connector/derivative/kalshi_perpetual/kalshi_perpetual_derivative.py", line 313, in _place_order
response = await self._api_post(
^^^^^^^^^^^^^^^^^^^^^
...<3 lines>...
limit_id=CONSTANTS.CREATE_ORDER_LIMIT_ID)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/eddga/hummingbot/hummingbot/8454/hummingbot/connector/exchange_py_base.py", line 907, in _api_post
return await self._api_request(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/eddga/hummingbot/hummingbot/8454/hummingbot/connector/exchange_py_base.py", line 946, in _api_request
request_result = await rest_assistant.execute_request(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...<8 lines>...
)
^
File "/home/eddga/hummingbot/hummingbot/8454/hummingbot/core/web_assistant/rest_assistant.py", line 48, in execute_request
response = await self.execute_request_and_get_response(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...<9 lines>...
)
^
File "/home/eddga/hummingbot/hummingbot/8454/hummingbot/core/web_assistant/rest_assistant.py", line 101, in execute_request_and_get_response
raise IOError(f"Error executing request {method.name} {url}. HTTP status is {response.status}. "
f"Error: {error_text}")
OSError: Error executing request POST https://external-api.kalshi.com/trade-api/v2/margin/orders. HTTP status is 400. Error: {"error":{"code":"invalid_order","message":"invalid order","details":"post only cross"}}
2026-09-17 21:42:00,020 - 352472 - hummingbot.connector.derivative.kalshi_perpetual.kalshi_perpetual_derivative.KalshiPerpetualDerivative - WARNING - Failed to submit BUY order to Kalshi_perpetual. Check API key and network connection.The connector only sets reduce_only on immediate-or-cancel orders, because Kalshi rejects it on resting ones. Market closes go out as IOC and are fine. Every other close order — LIMIT, LIMIT_MAKER, and the limit-chaser that maps to LIMIT_MAKER — is sent as GTC, skips the flag, and rests on the book able to open exposure.
Steps to reproduce
- Setup a generic.grid_strike on kalshi_perpetual
- Set take-profit close order as LIMIT or LIMIT_MAKER.
- Start the v2 controller strategy and observe behavior
Release version
dev-2.17
Type of installation
Source
Attach required files
na
Source: hummingbot/hummingbot