Files
ibkr-quant/tests/test_rebalance.py
Gahow Wang dc94f63839 Daily UpCap+MomGap trading on an IBKR paper account
Connects to IB Gateway through ib_async and trades the S&P 500 with the
UpCap+MomGap factor combo ported from quant-trading's
fc_up_cap_mom_gap_daily: signal on opens through today's open, equal
weight top 10, MOC orders filled at today's close, 10% resize band.

- make universe/bars/check/plan/submit/fills for the daily loop; refuses
  non-paper accounts unless allow_live, open orders, stale bars, and
  orders outside 09:31-15:45 ET
- make backtest replays the live loop day by day with plan_orders and
  IBKR Fixed commissions; selection uses each day's index members
- make bars fails fast when the Gateway's historical farm is down

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 21:53:31 +08:00

44 lines
1.4 KiB
Python

import pytest
from ibkr_quant.rebalance import plan_orders
def test_closes_dropped_names_and_sells_before_buys():
orders = plan_orders(
target_weights={"AAPL": 0.5, "MSFT": 0.5},
positions={"AAPL": 10, "NVDA": 7},
prices={"AAPL": 100.0, "MSFT": 300.0, "NVDA": 50.0},
investable=10_000,
min_trade_value=200,
)
assert [(o.symbol, o.delta) for o in orders] == [("NVDA", -7), ("AAPL", 40), ("MSFT", 16)]
def test_skips_small_adjustments_but_not_full_exits():
orders = plan_orders(
target_weights={"AAPL": 1.0},
positions={"AAPL": 99, "KO": 1},
prices={"AAPL": 100.0, "KO": 60.0},
investable=10_000,
min_trade_value=200,
)
assert [(o.symbol, o.delta) for o in orders] == [("KO", -1)]
def test_refuses_to_plan_without_prices():
with pytest.raises(ValueError, match="NVDA"):
plan_orders({"AAPL": 1.0}, {"NVDA": 5}, {"AAPL": 100.0}, 10_000, 0)
def test_resize_band_keeps_near_target_holdings():
orders = plan_orders(
target_weights={"AAPL": 0.5, "MSFT": 0.5},
positions={"AAPL": 46, "MSFT": 10},
prices={"AAPL": 100.0, "MSFT": 300.0},
investable=10_000,
min_trade_value=50,
resize_band=0.10,
)
# AAPL is 8% under target and stays; MSFT is 40% under and tops up.
assert [(o.symbol, o.delta) for o in orders] == [("MSFT", 6)]