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
52 changes: 42 additions & 10 deletions application/execution_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

from __future__ import annotations

import math
import hashlib
import json
import tempfile
Expand All @@ -12,6 +11,35 @@
from typing import Any

import pandas as pd
try:
from quant_platform_kit.common.cash_sweep import should_sell_cash_sweep_to_fund_whole_share_buy
except ImportError: # pragma: no cover - compatibility with older pinned shared wheels
def should_sell_cash_sweep_to_fund_whole_share_buy(
max_quantity,
cash_sweep_price,
base_buying_power,
funding_needs,
):
if max_quantity <= 0:
return False
sweep_price = float(cash_sweep_price or 0.0)
if sweep_price <= 0.0:
return False
current_buying_power = max(0.0, float(base_buying_power or 0.0))
sweep_capacity = float(max_quantity) * sweep_price
if sweep_capacity <= 0.0:
return False

for underweight_value, ask_price in funding_needs:
_ = underweight_value
quote_price = float(ask_price or 0.0)
Comment on lines +33 to +35
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Honor underweight size in fallback cash-sweep decision

In the ImportError fallback path (older shared-wheel environments), the new helper ignores underweight_value (_ = underweight_value) and can return True solely because one share is affordable after selling BOXX. This regresses the previous behavior that skipped sweep sales when the target deficit was less than one share (max_buy_quantity <= 0), so the system can now sell BOXX even though the subsequent buy computes qty == 0 and no risk asset order is placed. That produces unnecessary safe-haven liquidation and portfolio drift whenever a candidate’s underweight notional is above minimum_order_notional but below its share price.

Useful? React with 👍 / 👎.

if quote_price <= 0.0:
continue
if current_buying_power >= quote_price:
return False
if current_buying_power + sweep_capacity >= quote_price:
return True
return False
from quant_platform_kit.common.quantity import (
floor_to_quantity_step,
format_quantity,
Expand Down Expand Up @@ -663,23 +691,27 @@ def cash_sweep_sale_quantity_to_fund_buy(max_quantity: int, candidate_symbols: t
if max_quantity <= 0 or not safe_haven_symbol or cash_sweep_price <= 0.0:
return 0
base_buying_power = max(0.0, float(anticipated_buying_power))
funding_needs = []
for symbol in candidate_symbols:
underweight_value = target_mv[symbol] - current_mv.get(symbol, 0.0)
if underweight_value <= threshold:
continue
ask = prices.get(symbol)
if not ask or ask <= 0.0:
continue
max_buy_quantity = int(underweight_value // ask)
if max_buy_quantity <= 0:
continue
required_buying_power = max_buy_quantity * ask * 1.0
if base_buying_power >= required_buying_power:
return 0
return min(
max_quantity,
max(1, math.ceil((required_buying_power - base_buying_power) / cash_sweep_price)),
funding_needs.append(
(
underweight_value,
round(ask * limit_buy_premium, 2),
)
)
if should_sell_cash_sweep_to_fund_whole_share_buy(
float(max_quantity),
cash_sweep_price,
base_buying_power,
funding_needs,
):
return int(max_quantity)
return 0

has_sell_plan = False
Expand Down
13 changes: 10 additions & 3 deletions tests/test_execution_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -482,8 +482,15 @@ def fills(self):

def accountValues(self):
self._account_values_calls += 1
buying_power = "124" if self._account_values_calls == 1 else "324"
return [SimpleNamespace(tag="AvailableFunds", currency="USD", value=buying_power)]
buying_power = "24" if self._account_values_calls == 1 else "224"
return [
SimpleNamespace(
account="DU123",
tag="AvailableFunds",
currency="USD",
value=buying_power,
)
]

submitted = []

Expand All @@ -497,7 +504,7 @@ def fake_submit_order_intent(_ib, intent):
FakeIB(),
{"VOO": 0.8, "BOXX": 0.2},
{"VOO": {"quantity": 0}, "BOXX": {"quantity": 2}},
{"equity": 1000.0, "buying_power": 124.0},
{"equity": 1000.0, "buying_power": 24.0},
fetch_quote_snapshots=lambda *_args, **_kwargs: {
"VOO": SimpleNamespace(last_price=100.0),
"BOXX": SimpleNamespace(last_price=100.0),
Expand Down