Skip to content

Commit 3a273c9

Browse files
authored
Merge pull request #206 from QuantStrategyLab/codex/binance-strict-bool-20260904
fix: reject non-boolean Binance buyer flags
2 parents 086e322 + 01f402b commit 3a273c9

2 files changed

Lines changed: 23 additions & 1 deletion

File tree

application/broker_reconciliation.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,12 @@ def _finite_number(value: object, *, field_name: str) -> float:
5858
return parsed
5959

6060

61+
def _strict_bool(value: object, *, field_name: str) -> bool:
62+
if type(value) is not bool:
63+
raise BinanceReconciliationReadError(f"Binance reconciliation received an invalid {field_name}.")
64+
return value
65+
66+
6167
def _normalize_balance(raw: Mapping[str, object]) -> dict[str, object]:
6268
asset = _text(raw.get("asset")).upper()
6369
if not asset:
@@ -102,7 +108,7 @@ def _normalize_trade(raw: Mapping[str, object]) -> dict[str, object]:
102108
"commission": _finite_number(raw.get("commission"), field_name="trade commission"),
103109
"commission_asset": _text(raw.get("commissionAsset")).upper(),
104110
"time": _text(raw.get("time")),
105-
"is_buyer": bool(raw.get("isBuyer")),
111+
"is_buyer": _strict_bool(raw.get("isBuyer"), field_name="trade buyer flag"),
106112
}
107113

108114

tests/test_broker_reconciliation.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,22 @@ def get_account(self):
109109
)
110110

111111

112+
@pytest.mark.parametrize("invalid_is_buyer", ["false", None, 0, 1])
113+
def test_invalid_trade_buyer_flag_fails_closed(invalid_is_buyer):
114+
class InvalidBuyerFlag(_Client):
115+
def get_my_trades(self, *, symbol, startTime, endTime, limit):
116+
payload = super().get_my_trades(
117+
symbol=symbol, startTime=startTime, endTime=endTime, limit=limit
118+
)[0]
119+
payload["isBuyer"] = invalid_is_buyer
120+
return [payload]
121+
122+
with pytest.raises(BinanceReconciliationReadError, match="buyer flag"):
123+
collect_read_only_reconciliation_observations(
124+
InvalidBuyerFlag(), strategy_symbols=("BTCUSDT",), local_execution_ledger={}
125+
)
126+
127+
112128
def test_recent_trades_are_partitioned_into_day_windows_and_deduplicated():
113129
class WindowRecordingClient(_Client):
114130
def __init__(self):

0 commit comments

Comments
 (0)