d938bc6c59
Co-authored-by: Cursor <cursoragent@cursor.com>
112 lines
2.9 KiB
Python
112 lines
2.9 KiB
Python
"""hub_calculator_lib 测算逻辑。"""
|
|
|
|
from hub_calculator_lib import (
|
|
calc_initial_roll_qty,
|
|
calc_roll_calculator,
|
|
calc_trend_calculator,
|
|
)
|
|
|
|
|
|
def test_trend_calculator_long_basic():
|
|
data, err = calc_trend_calculator(
|
|
direction="long",
|
|
capital_usdt=1000,
|
|
risk_percent=5,
|
|
leverage=5,
|
|
entry_price=100,
|
|
stop_loss=95,
|
|
add_upper=110,
|
|
take_profit=120,
|
|
dca_legs=3,
|
|
contract_size=1,
|
|
)
|
|
assert err is None
|
|
assert data is not None
|
|
assert data["risk_budget_u"] == 50.0
|
|
assert len(data["rows"]) >= 2
|
|
assert data["rows"][0]["label"] == "首仓"
|
|
|
|
|
|
def test_trend_calculator_short_rejects_bad_bounds():
|
|
data, err = calc_trend_calculator(
|
|
direction="short",
|
|
capital_usdt=1000,
|
|
risk_percent=5,
|
|
leverage=5,
|
|
entry_price=100,
|
|
stop_loss=90,
|
|
add_upper=110,
|
|
take_profit=80,
|
|
dca_legs=3,
|
|
)
|
|
assert data is None
|
|
assert err is not None
|
|
|
|
|
|
def test_roll_calculator_first_leg_auto():
|
|
data, err = calc_roll_calculator(
|
|
direction="long",
|
|
capital_usdt=1000,
|
|
risk_percent=5,
|
|
entry_price=100,
|
|
stop_loss=95,
|
|
take_profit=120,
|
|
add_legs=[],
|
|
legs_done=0,
|
|
)
|
|
assert err is None
|
|
assert data is not None
|
|
assert data["first_contracts"] == 10.0
|
|
assert len(data["rows"]) == 1
|
|
assert data["rows"][0]["loss_at_sl_u"] == 50.0
|
|
assert data["rows"][0]["profit_at_tp_u"] == 200.0
|
|
|
|
|
|
def test_roll_calculator_chain_two_legs():
|
|
data, err = calc_roll_calculator(
|
|
direction="long",
|
|
capital_usdt=1000,
|
|
risk_percent=5,
|
|
entry_price=100,
|
|
stop_loss=95,
|
|
take_profit=120,
|
|
add_legs=[
|
|
{"add_price": 105, "new_stop_loss": 98},
|
|
{"add_price": 108, "new_stop_loss": 101},
|
|
],
|
|
legs_done=0,
|
|
)
|
|
assert err is None
|
|
assert data is not None
|
|
assert len(data["rows"]) == 3
|
|
assert data["rows"][0]["label"] == "首仓"
|
|
assert data["rows"][1]["label"] == "滚仓1"
|
|
assert data["rows"][2]["label"] == "滚仓2"
|
|
assert float(data["final_contracts"]) > float(data["first_contracts"])
|
|
|
|
|
|
def test_roll_calculator_rejects_too_many_legs():
|
|
data, err = calc_roll_calculator(
|
|
direction="long",
|
|
capital_usdt=1000,
|
|
risk_percent=5,
|
|
entry_price=100,
|
|
stop_loss=95,
|
|
take_profit=120,
|
|
add_legs=[
|
|
{"add_price": 105, "new_stop_loss": 98},
|
|
{"add_price": 108, "new_stop_loss": 101},
|
|
{"add_price": 110, "new_stop_loss": 103},
|
|
{"add_price": 112, "new_stop_loss": 105},
|
|
],
|
|
legs_done=0,
|
|
)
|
|
assert data is None
|
|
assert err is not None
|
|
|
|
|
|
def test_initial_roll_qty():
|
|
qty, err = calc_initial_roll_qty("long", 100, 95, 50)
|
|
assert err is None
|
|
assert qty == 10.0
|