Skip to content
Merged
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
3 changes: 0 additions & 3 deletions blueprints/brlogin.py
Original file line number Diff line number Diff line change
Expand Up @@ -750,9 +750,6 @@ def broker_callback(broker, para=None):
auth_token = f"{auth_token}"

# For brokers that have user_id and feed_token from authenticate_broker
if broker in ["angel", "aliceblue", "compositedge", "pocketful", "definedge", "dhan"]:
# For Compositedge, handle missing session user
if broker == "compositedge" and "user" not in session:
if broker in ["angel", "compositedge", "pocketful", "definedge", "dhan", "rmoney"]:
# For OAuth brokers, handle missing session user
if broker in ("compositedge", "rmoney") and "user" not in session:
Expand Down
41 changes: 35 additions & 6 deletions broker/deltaexchange/api/order_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -526,7 +526,25 @@ def cancel_order(orderid, auth):


def cancel_all_orders_api(data, auth):
"""Cancel all currently open orders (regardless of creation date)."""
"""
Cancel all currently open orders via DELETE /v2/orders/all.
Uses the bulk cancel endpoint instead of cancelling orders one by one.
Falls back to individual cancellation if bulk endpoint fails.
"""
# Try bulk cancel first (single API call)
body = {
"cancel_limit_orders": True,
"cancel_stop_orders": True,
"cancel_reduce_only_orders": True,
}
result = get_api_response("/v2/orders/all", auth, method="DELETE", payload=json.dumps(body))
if result.get("success"):
logger.info("[DeltaExchange] All open orders cancelled via /v2/orders/all")
return ["all"], []

# Fallback: cancel individually
logger.warning("[DeltaExchange] Bulk cancel failed, falling back to individual cancellation")
order_book = _get_all_open_orders(auth)
if not order_book:
return [], []
Expand Down Expand Up @@ -573,15 +591,21 @@ def modify_order(data, auth):
# ---------------------------------------------------------------------------

def close_all_positions(current_api_key, auth):
"""Square off all open positions using market orders."""
"""Square off all open positions (derivatives + spot) using market orders."""
positions = get_positions(auth)
if not positions:
return {"message": "No Open Positions Found"}, 200

for pos in positions:
if not isinstance(pos, dict):
continue
size = int(pos.get("size", 0))
is_spot = pos.get("_is_spot", False)

# Use float() to handle fractional spot sizes (e.g. 0.0001 BTC)
try:
size = float(pos.get("size", 0))
except (ValueError, TypeError):
size = 0
if size == 0:
continue

Expand All @@ -590,8 +614,13 @@ def close_all_positions(current_api_key, auth):
action = "SELL" if size > 0 else "BUY"
quantity = abs(size)

# Resolve OpenAlgo symbol from DB; fall back to product_symbol
symbol = get_symbol(str(product_id), "CRYPTO") or product_symbol
# Resolve OpenAlgo symbol from DB.
# For spot wallet entries, product_id is asset_id (not product token),
# so look up by brsymbol instead.
if is_spot:
symbol = get_oa_symbol(product_symbol, "CRYPTO") or product_symbol
else:
symbol = get_symbol(str(product_id), "CRYPTO") or product_symbol
logger.info(f"[DeltaExchange] Close: {action} {quantity} {symbol}")

order_payload = {
Expand All @@ -601,7 +630,7 @@ def close_all_positions(current_api_key, auth):
"action": action,
"exchange": "CRYPTO",
"pricetype": "MARKET",
"product": "NRML",
"product": "CNC" if is_spot else "NRML",
"quantity": str(quantity),
}
_, api_response, _ = place_order_api(order_payload, auth)
Expand Down
4 changes: 2 additions & 2 deletions services/orderbook_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ def format_order_data(order_data):
formatted_item = {}
for key, value in item.items():
if isinstance(value, (int, float)):
# Keep quantity fields as integers
# Keep quantity fields as integers when whole, preserve float for fractional (crypto spot)
if key.lower() in quantity_fields:
formatted_item[key] = int(value)
formatted_item[key] = int(value) if value == int(value) else value
else:
formatted_item[key] = format_decimal(value)
else:
Expand Down
2 changes: 1 addition & 1 deletion services/tradebook_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def format_trade_data(trade_data):
if isinstance(trade_data, list):
return [
{
key: int(value)
key: (int(value) if value == int(value) else value)
if (key.lower() in quantity_fields and isinstance(value, (int, float)))
else (format_decimal(value) if isinstance(value, (int, float)) else value)
for key, value in item.items()
Expand Down
Loading