Better logic on fund splitting
This commit is contained in:
@@ -4,4 +4,6 @@ KRAKEN_API_KEY=your_api_key_here
|
||||
KRAKEN_API_SECRET=your_api_secret_here
|
||||
|
||||
# Starting balance for paper trading simulation
|
||||
# Needs to be at least (max_positions * min_order_usd) to fill all slots.
|
||||
# Default config: 5 positions * $15 min = $75 minimum, $500+ recommended.
|
||||
PAPER_BALANCE_USD=1000
|
||||
|
||||
34
bot.py
34
bot.py
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user