132 lines
3.3 KiB
Python
132 lines
3.3 KiB
Python
from __future__ import annotations
|
|
|
|
from src.analysis.triple_barrier import TripleBarrierSpec, label_with_triple_barrier
|
|
|
|
|
|
def test_long_take_profit_first() -> None:
|
|
highs = [100, 101, 103]
|
|
lows = [100, 99.6, 100]
|
|
closes = [100, 100, 102]
|
|
spec = TripleBarrierSpec(take_profit_pct=0.02, stop_loss_pct=0.01, max_holding_bars=3)
|
|
out = label_with_triple_barrier(
|
|
highs=highs,
|
|
lows=lows,
|
|
closes=closes,
|
|
entry_index=0,
|
|
side=1,
|
|
spec=spec,
|
|
)
|
|
assert out.label == 1
|
|
assert out.touched == "take_profit"
|
|
assert out.touch_bar == 2
|
|
|
|
|
|
def test_long_stop_loss_first() -> None:
|
|
highs = [100, 100.5, 101]
|
|
lows = [100, 98.8, 99]
|
|
closes = [100, 99.5, 100]
|
|
spec = TripleBarrierSpec(take_profit_pct=0.02, stop_loss_pct=0.01, max_holding_bars=3)
|
|
out = label_with_triple_barrier(
|
|
highs=highs,
|
|
lows=lows,
|
|
closes=closes,
|
|
entry_index=0,
|
|
side=1,
|
|
spec=spec,
|
|
)
|
|
assert out.label == -1
|
|
assert out.touched == "stop_loss"
|
|
assert out.touch_bar == 1
|
|
|
|
|
|
def test_time_barrier_timeout() -> None:
|
|
highs = [100, 100.8, 100.7]
|
|
lows = [100, 99.3, 99.4]
|
|
closes = [100, 100, 100]
|
|
spec = TripleBarrierSpec(take_profit_pct=0.02, stop_loss_pct=0.02, max_holding_bars=2)
|
|
out = label_with_triple_barrier(
|
|
highs=highs,
|
|
lows=lows,
|
|
closes=closes,
|
|
entry_index=0,
|
|
side=1,
|
|
spec=spec,
|
|
)
|
|
assert out.label == 0
|
|
assert out.touched == "time"
|
|
assert out.touch_bar == 2
|
|
|
|
|
|
def test_tie_break_stop_first_default() -> None:
|
|
highs = [100, 102.1]
|
|
lows = [100, 98.9]
|
|
closes = [100, 100]
|
|
spec = TripleBarrierSpec(take_profit_pct=0.02, stop_loss_pct=0.01, max_holding_bars=1)
|
|
out = label_with_triple_barrier(
|
|
highs=highs,
|
|
lows=lows,
|
|
closes=closes,
|
|
entry_index=0,
|
|
side=1,
|
|
spec=spec,
|
|
)
|
|
assert out.label == -1
|
|
assert out.touched == "stop_loss"
|
|
|
|
|
|
def test_short_side_inverts_barrier_semantics() -> None:
|
|
highs = [100, 100.5, 101.2]
|
|
lows = [100, 97.8, 98.0]
|
|
closes = [100, 99, 99]
|
|
spec = TripleBarrierSpec(take_profit_pct=0.02, stop_loss_pct=0.01, max_holding_bars=3)
|
|
out = label_with_triple_barrier(
|
|
highs=highs,
|
|
lows=lows,
|
|
closes=closes,
|
|
entry_index=0,
|
|
side=-1,
|
|
spec=spec,
|
|
)
|
|
assert out.label == 1
|
|
assert out.touched == "take_profit"
|
|
|
|
|
|
def test_short_tie_break_modes() -> None:
|
|
highs = [100, 101.1]
|
|
lows = [100, 97.9]
|
|
closes = [100, 100]
|
|
|
|
stop_first = TripleBarrierSpec(
|
|
take_profit_pct=0.02,
|
|
stop_loss_pct=0.01,
|
|
max_holding_bars=1,
|
|
tie_break="stop_first",
|
|
)
|
|
out_stop = label_with_triple_barrier(
|
|
highs=highs,
|
|
lows=lows,
|
|
closes=closes,
|
|
entry_index=0,
|
|
side=-1,
|
|
spec=stop_first,
|
|
)
|
|
assert out_stop.label == -1
|
|
assert out_stop.touched == "stop_loss"
|
|
|
|
take_first = TripleBarrierSpec(
|
|
take_profit_pct=0.02,
|
|
stop_loss_pct=0.01,
|
|
max_holding_bars=1,
|
|
tie_break="take_first",
|
|
)
|
|
out_take = label_with_triple_barrier(
|
|
highs=highs,
|
|
lows=lows,
|
|
closes=closes,
|
|
entry_index=0,
|
|
side=-1,
|
|
spec=take_first,
|
|
)
|
|
assert out_take.label == 1
|
|
assert out_take.touched == "take_profit"
|