Better logic on fund splitting

This commit is contained in:
2026-05-04 09:37:07 -04:00
parent fcc64d6573
commit 9285b303d0
2 changed files with 22 additions and 14 deletions

34
bot.py
View File

@@ -45,9 +45,11 @@ def setup_logging(log_file: str) -> None:
)
def available_usd(client: KrakenClient, config: Config) -> float:
def available_usd(client: KrakenClient, config: Config, portfolio: Portfolio) -> float:
if config.paper_trading:
return float(os.getenv("PAPER_BALANCE_USD", "1000"))
total = float(os.getenv("PAPER_BALANCE_USD", "1000"))
invested = sum(pos.cost_usd for pos in portfolio.all())
return max(0.0, total - invested)
try:
return client.get_usd_balance()
except KrakenError as exc:
@@ -129,7 +131,7 @@ def run_cycle(config: Config) -> bool:
log.info("Portfolio full — no new positions to open.")
return bool(closed)
balance = available_usd(client, config)
balance = available_usd(client, config, portfolio)
log.info("Available balance: $%.2f | Open slots: %d", balance, open_slots)
if balance < config.min_order_usd:
@@ -146,22 +148,26 @@ def run_cycle(config: Config) -> bool:
log.info("No opportunities matching criteria this cycle.")
return bool(closed)
# Cap to available slots and allocate equally
to_buy = opportunities[:open_slots]
alloc_per_asset = balance / len(to_buy)
# Sort by 24h change descending — strongest movers get priority when funds are limited
opportunities.sort(key=lambda o: o.change_pct, reverse=True)
# How many can we actually afford at the minimum order size?
affordable = int(balance // config.min_order_usd)
num_to_buy = min(open_slots, affordable, len(opportunities))
if num_to_buy == 0:
log.info("Balance $%.2f too low for even one minimum order ($%.2f).", balance, config.min_order_usd)
return bool(closed)
to_buy = opportunities[:num_to_buy]
# Split available balance equally across the chosen assets (always >= min_order_usd)
alloc_per_asset = balance / num_to_buy
log.info(
"Buying %d asset(s) @ $%.2f each (total $%.2f)",
len(to_buy), alloc_per_asset, alloc_per_asset * len(to_buy),
num_to_buy, alloc_per_asset, alloc_per_asset * num_to_buy,
)
for opp in to_buy:
if alloc_per_asset < config.min_order_usd:
log.warning(
"Allocation $%.2f < minimum $%.2f — skipping %s",
alloc_per_asset, config.min_order_usd, opp.pair,
)
continue
quantity = round(alloc_per_asset / opp.last_price, opp.lot_decimals)
if opp.order_min > 0 and quantity < opp.order_min: