Engine: add stop loss integration (fixed & trailing) with tests
This commit is contained in:
39
tests/risk/sizing/test_fixed.py
Normal file
39
tests/risk/sizing/test_fixed.py
Normal file
@@ -0,0 +1,39 @@
|
||||
import sys
|
||||
from pathlib import Path
|
||||
import pytest
|
||||
|
||||
# Añadir raíz del proyecto al path
|
||||
sys.path.insert(0, str(Path(__file__).parent.parent.parent.parent))
|
||||
|
||||
from src.risk.sizing.fixed import FixedPositionSizer
|
||||
|
||||
|
||||
def test_fixed_position_size_basic():
|
||||
sizer = FixedPositionSizer(capital_fraction=0.5)
|
||||
|
||||
capital = 10_000
|
||||
entry_price = 100
|
||||
|
||||
units = sizer.calculate_size(
|
||||
capital=capital,
|
||||
entry_price=entry_price
|
||||
)
|
||||
|
||||
# 50% de 10k = 5k / 100 = 50 unidades
|
||||
assert units == 50
|
||||
|
||||
|
||||
def test_fixed_position_size_full_capital():
|
||||
sizer = FixedPositionSizer(capital_fraction=1.0)
|
||||
|
||||
units = sizer.calculate_size(
|
||||
capital=10_000,
|
||||
entry_price=200
|
||||
)
|
||||
|
||||
assert units == 50
|
||||
|
||||
|
||||
def test_fixed_invalid_fraction():
|
||||
with pytest.raises(ValueError):
|
||||
FixedPositionSizer(capital_fraction=1.5)
|
||||
50
tests/risk/sizing/test_percent_risk.py
Normal file
50
tests/risk/sizing/test_percent_risk.py
Normal file
@@ -0,0 +1,50 @@
|
||||
import sys
|
||||
from pathlib import Path
|
||||
import pytest
|
||||
|
||||
# Añadir raíz del proyecto al path
|
||||
sys.path.insert(0, str(Path(__file__).parent.parent.parent.parent))
|
||||
|
||||
|
||||
from src.risk.sizing.percent_risk import PercentRiskSizer
|
||||
|
||||
|
||||
def test_percent_risk_basic():
|
||||
sizer = PercentRiskSizer(risk_fraction=0.01) # 1%
|
||||
|
||||
capital = 10_000
|
||||
entry_price = 100
|
||||
stop_price = 95
|
||||
|
||||
units = sizer.calculate_size(
|
||||
capital=capital,
|
||||
entry_price=entry_price,
|
||||
stop_price=stop_price
|
||||
)
|
||||
|
||||
# riesgo = 100€
|
||||
# riesgo por unidad = 5
|
||||
# unidades = 100 / 5 = 20
|
||||
assert units == 20
|
||||
|
||||
|
||||
def test_percent_risk_zero_distance():
|
||||
sizer = PercentRiskSizer(0.01)
|
||||
|
||||
units = sizer.calculate_size(
|
||||
capital=10_000,
|
||||
entry_price=100,
|
||||
stop_price=100
|
||||
)
|
||||
|
||||
assert units == 0.0
|
||||
|
||||
|
||||
def test_percent_risk_requires_stop():
|
||||
sizer = PercentRiskSizer(0.01)
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
sizer.calculate_size(
|
||||
capital=10_000,
|
||||
entry_price=100
|
||||
)
|
||||
42
tests/risk/sizing/test_volatility.py
Normal file
42
tests/risk/sizing/test_volatility.py
Normal file
@@ -0,0 +1,42 @@
|
||||
import sys
|
||||
from pathlib import Path
|
||||
import pytest
|
||||
|
||||
# Añadir raíz del proyecto al path
|
||||
sys.path.insert(0, str(Path(__file__).parent.parent.parent.parent))
|
||||
|
||||
|
||||
from src.risk.sizing.volatility import VolatilitySizer
|
||||
|
||||
|
||||
def test_volatility_sizer_basic():
|
||||
sizer = VolatilitySizer(volatility_multiplier=2.0)
|
||||
|
||||
capital = 10_000
|
||||
entry_price = 100
|
||||
volatility = 0.02 # 2%
|
||||
|
||||
units = sizer.calculate_size(
|
||||
capital=capital,
|
||||
entry_price=entry_price,
|
||||
volatility=volatility
|
||||
)
|
||||
|
||||
# riesgo por unidad = 0.02 * 100 * 2 = 4
|
||||
# unidades = 10_000 / 4 = 2500
|
||||
assert units == 2500
|
||||
|
||||
|
||||
def test_volatility_requires_volatility():
|
||||
sizer = VolatilitySizer()
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
sizer.calculate_size(
|
||||
capital=10_000,
|
||||
entry_price=100
|
||||
)
|
||||
|
||||
|
||||
def test_volatility_invalid_multiplier():
|
||||
with pytest.raises(ValueError):
|
||||
VolatilitySizer(volatility_multiplier=0)
|
||||
Reference in New Issue
Block a user