Skip to content

Commit 11976f1

Browse files
committed
fix: Improve stacked imbalance detection in orderflow converter
1 parent ea96abe commit 11976f1

File tree

2 files changed

+22
-19
lines changed

2 files changed

+22
-19
lines changed

freqtrade/data/converter/orderflow.py

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -265,20 +265,23 @@ def stacked_imbalance(
265265
"""
266266
imbalance = df[f"{label}_imbalance"]
267267
int_series = pd.Series(np.where(imbalance, 1, 0))
268-
stacked = int_series * (
269-
int_series.groupby((int_series != int_series.shift()).cumsum()).cumcount() + 1
270-
)
271-
272-
stacked_imbalance_idx = stacked.index[stacked >= stacked_imbalance_range]
273-
stacked_imbalance_prices = []
268+
# Group consecutive True values and get their counts
269+
groups = (int_series != int_series.shift()).cumsum()
270+
counts = int_series.groupby(groups).cumsum()
274271

275-
if not stacked_imbalance_idx.empty:
276-
indices = (
277-
stacked_imbalance_idx
272+
# Find indices where count meets or exceeds the range requirement
273+
valid_indices = counts[counts >= stacked_imbalance_range].index
274+
275+
stacked_imbalance_prices = []
276+
if not valid_indices.empty:
277+
# Get all prices from valid indices from beginning of the range
278+
valid_prices = [imbalance.index.values[idx-(stacked_imbalance_range-1)] for idx in valid_indices]
279+
# Sort prices according to direction
280+
stacked_imbalance_prices = (
281+
sorted(valid_prices)
278282
if not should_reverse
279-
else np.flipud(stacked_imbalance_idx)
283+
else sorted(valid_prices, reverse=True)
280284
)
281-
stacked_imbalance_prices = [float(imbalance.index[idx]) for idx in indices]
282285

283286
return stacked_imbalance_prices if stacked_imbalance_prices else [np.nan]
284287

tests/data/test_converter_orderflow.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -193,8 +193,8 @@ def test_public_trades_mock_populate_dataframe_with_trades__check_orderflow(
193193
assert pytest.approx(results["delta"]) == -20.862
194194
assert pytest.approx(results["min_delta"]) == -54.559999
195195
assert 82.842 == results["max_delta"]
196-
assert results["stacked_imbalances_bid"] == [234.99]
197-
assert results["stacked_imbalances_ask"] == [234.96]
196+
assert results["stacked_imbalances_bid"] == [234.97]
197+
assert results["stacked_imbalances_ask"] == [234.94]
198198

199199
# Repeat assertions for the last row
200200
results = df.iloc[-1]
@@ -586,22 +586,22 @@ def test_stacked_imbalances_multiple_prices():
586586
# Create a sample DataFrame with known imbalances
587587
df = pd.DataFrame(
588588
{
589-
'bid_imbalance': [True, True, True, False, False, True, True, False],
590-
'ask_imbalance': [False, False, True, True, True, False, False, True]
589+
'bid_imbalance': [True, True, True, False, False, True, True, False, True],
590+
'ask_imbalance': [False, False, True, True, True, False, False, True, True]
591591
},
592-
index=[234.95, 234.96, 234.97, 234.98, 234.99, 235.00, 235.01, 235.02]
592+
index=[234.95, 234.96, 234.97, 234.98, 234.99, 235.00, 235.01, 235.02, 235.03]
593593
)
594594
# Test bid imbalances (should return prices in ascending order)
595595
bid_prices = stacked_imbalance(df, "bid", stacked_imbalance_range=2, should_reverse=False)
596-
assert bid_prices == [234.95, 234.96, 234.97, 235.00, 235.01]
596+
assert bid_prices == [234.95, 234.96, 235.00]
597597

598598
# Test ask imbalances (should return prices in descending order)
599599
ask_prices = stacked_imbalance(df, "ask", stacked_imbalance_range=2, should_reverse=True)
600-
assert ask_prices == [235.02, 234.99, 234.98, 234.97]
600+
assert ask_prices == [235.02, 234.98, 234.97]
601601

602602
# Test with higher stacked_imbalance_range
603603
bid_prices_higher = stacked_imbalance(df, "bid", stacked_imbalance_range=3, should_reverse=False)
604-
assert bid_prices_higher == [234.95, 234.96, 234.97]
604+
assert bid_prices_higher == [234.95]
605605

606606

607607

0 commit comments

Comments
 (0)