Skip to content

Commit dc6bd92

Browse files
committed
fix(strategy-v2): omit redundant flat rebalance targets
1 parent d7642d7 commit dc6bd92

2 files changed

Lines changed: 36 additions & 1 deletion

File tree

‎backend_api_python/app/services/strategy_v2/runtime.py‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -782,7 +782,9 @@ def execute(
782782
else open_price
783783
)
784784
target_qty = self._target_quantity(order, current, sizing_price, equity)
785-
target_weights[position_key] = target_qty * sizing_price / equity if equity else 0.0
785+
target_weight = target_qty * sizing_price / equity if equity else 0.0
786+
if abs(target_weight) > 1e-12 or abs(current.amount) > 1e-12:
787+
target_weights[position_key] = target_weight
786788
delta = target_qty - current.amount
787789
direction = 1 if delta > 0 else -1 if delta < 0 else 0
788790
if order.pending_direction and direction != order.pending_direction:

‎backend_api_python/tests/test_strategy_v2_runtime.py‎

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -714,6 +714,39 @@ def handle_data(context, data):
714714
assert result["winRate"] == 100.0
715715
assert result["profitFactor"] > 0
716716
assert result["avgTrade"] > 0
717+
assert result["rebalanceRecords"][1]["targetWeights"] == {"USStock:AAPL": 0.0}
718+
719+
720+
def test_rebalance_records_omit_zero_targets_for_already_flat_symbols():
721+
code = """
722+
def initialize(context):
723+
context.set_universe(["USStock:AAPL", "USStock:MSFT"])
724+
context.subscribe(frequency="1d")
725+
g.sent = False
726+
727+
def handle_data(context, data):
728+
if not g.sent:
729+
order_target_percent("AAPL", 0.5, reason="entry")
730+
order_target_percent("MSFT", 0.0, reason="already_flat")
731+
g.sent = True
732+
"""
733+
result = StrategyV2BacktestRunner(
734+
code=code,
735+
frames={
736+
"USStock:AAPL": _frame([100, 101, 102]),
737+
"USStock:MSFT": _frame([200, 201, 202]),
738+
},
739+
initial_capital=10000,
740+
commission=0,
741+
slippage=0,
742+
).run()
743+
744+
assert result["rebalanceRecords"][0]["targetWeights"] == {"USStock:AAPL": 0.5}
745+
assert any(
746+
row["symbol"] == "USStock:MSFT"
747+
and row["statusReason"] == "target_already_met"
748+
for row in result["orderLedger"]
749+
)
717750

718751

719752
def test_live_session_processes_each_closed_bar_once_and_preserves_state():

0 commit comments

Comments
 (0)