|
2 | 2 |
|
3 | 3 | from __future__ import annotations |
4 | 4 |
|
5 | | -import math |
6 | 5 | import hashlib |
7 | 6 | import json |
8 | 7 | import tempfile |
|
12 | 11 | from typing import Any |
13 | 12 |
|
14 | 13 | import pandas as pd |
| 14 | +try: |
| 15 | + from quant_platform_kit.common.cash_sweep import should_sell_cash_sweep_to_fund_whole_share_buy |
| 16 | +except ImportError: # pragma: no cover - compatibility with older pinned shared wheels |
| 17 | + def should_sell_cash_sweep_to_fund_whole_share_buy( |
| 18 | + max_quantity, |
| 19 | + cash_sweep_price, |
| 20 | + base_buying_power, |
| 21 | + funding_needs, |
| 22 | + ): |
| 23 | + if max_quantity <= 0: |
| 24 | + return False |
| 25 | + sweep_price = float(cash_sweep_price or 0.0) |
| 26 | + if sweep_price <= 0.0: |
| 27 | + return False |
| 28 | + current_buying_power = max(0.0, float(base_buying_power or 0.0)) |
| 29 | + sweep_capacity = float(max_quantity) * sweep_price |
| 30 | + if sweep_capacity <= 0.0: |
| 31 | + return False |
| 32 | + |
| 33 | + for underweight_value, ask_price in funding_needs: |
| 34 | + _ = underweight_value |
| 35 | + quote_price = float(ask_price or 0.0) |
| 36 | + if quote_price <= 0.0: |
| 37 | + continue |
| 38 | + if current_buying_power >= quote_price: |
| 39 | + return False |
| 40 | + if current_buying_power + sweep_capacity >= quote_price: |
| 41 | + return True |
| 42 | + return False |
15 | 43 | from quant_platform_kit.common.quantity import ( |
16 | 44 | floor_to_quantity_step, |
17 | 45 | format_quantity, |
@@ -663,23 +691,27 @@ def cash_sweep_sale_quantity_to_fund_buy(max_quantity: int, candidate_symbols: t |
663 | 691 | if max_quantity <= 0 or not safe_haven_symbol or cash_sweep_price <= 0.0: |
664 | 692 | return 0 |
665 | 693 | base_buying_power = max(0.0, float(anticipated_buying_power)) |
| 694 | + funding_needs = [] |
666 | 695 | for symbol in candidate_symbols: |
667 | 696 | underweight_value = target_mv[symbol] - current_mv.get(symbol, 0.0) |
668 | 697 | if underweight_value <= threshold: |
669 | 698 | continue |
670 | 699 | ask = prices.get(symbol) |
671 | 700 | if not ask or ask <= 0.0: |
672 | 701 | continue |
673 | | - max_buy_quantity = int(underweight_value // ask) |
674 | | - if max_buy_quantity <= 0: |
675 | | - continue |
676 | | - required_buying_power = max_buy_quantity * ask * 1.0 |
677 | | - if base_buying_power >= required_buying_power: |
678 | | - return 0 |
679 | | - return min( |
680 | | - max_quantity, |
681 | | - max(1, math.ceil((required_buying_power - base_buying_power) / cash_sweep_price)), |
| 702 | + funding_needs.append( |
| 703 | + ( |
| 704 | + underweight_value, |
| 705 | + round(ask * limit_buy_premium, 2), |
| 706 | + ) |
682 | 707 | ) |
| 708 | + if should_sell_cash_sweep_to_fund_whole_share_buy( |
| 709 | + float(max_quantity), |
| 710 | + cash_sweep_price, |
| 711 | + base_buying_power, |
| 712 | + funding_needs, |
| 713 | + ): |
| 714 | + return int(max_quantity) |
683 | 715 | return 0 |
684 | 716 |
|
685 | 717 | has_sell_plan = False |
|
0 commit comments