refactor: 将共用代码迁入 lib/ 模块化目录
统一 strategy、key_monitor、trade、hub 等共用库到 lib/ 子包,并补充 lib-structure 文档,便于四所与中控维护。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+112
-112
@@ -1,112 +1,112 @@
|
||||
from strategy_roll_lib import (
|
||||
preview_roll,
|
||||
roll_breakout_invalidate,
|
||||
roll_breakout_trigger_crossed,
|
||||
roll_fib_invalidate,
|
||||
roll_fib_trigger_crossed,
|
||||
solve_add_amount_for_total_risk,
|
||||
validate_roll_geometry,
|
||||
)
|
||||
|
||||
|
||||
def test_solve_add_amount_long_one_risk():
|
||||
q2, err = solve_add_amount_for_total_risk(
|
||||
"long", 1.0, 3000.0, 3100.0, 2950.0, 200.0, 1.0
|
||||
)
|
||||
assert err is None
|
||||
avg = (1 * 3000 + q2 * 3100) / (1 + q2)
|
||||
loss = (avg - 2950) * (1 + q2)
|
||||
assert abs(loss - 200.0) < 0.01
|
||||
|
||||
|
||||
def test_preview_roll_market_short():
|
||||
preview, err = preview_roll(
|
||||
direction="short",
|
||||
symbol="HYPE/USDT",
|
||||
qty_existing=3.0,
|
||||
entry_existing=65.0,
|
||||
initial_take_profit=60.0,
|
||||
add_mode="market",
|
||||
new_stop_loss=66.5,
|
||||
risk_percent=2.0,
|
||||
capital_base_usdt=1000.0,
|
||||
add_price=64.0,
|
||||
legs_done=1,
|
||||
)
|
||||
assert err is None
|
||||
assert preview["add_mode_label"] == "市价加仓"
|
||||
sl = preview["new_stop_loss"]
|
||||
avg = preview["avg_entry_after"]
|
||||
qty = preview["qty_after"]
|
||||
loss = (sl - avg) * qty
|
||||
assert abs(loss - 20.0) < 0.01
|
||||
|
||||
|
||||
def test_fib_cross_long_down():
|
||||
assert roll_fib_trigger_crossed("long", 101.0, 100.0, 100.5) is True
|
||||
assert roll_fib_trigger_crossed("long", 100.6, 100.6, 100.5) is False
|
||||
|
||||
|
||||
def test_breakout_cross_long_up():
|
||||
assert roll_breakout_trigger_crossed("long", 99.0, 100.5, 100.0) is True
|
||||
assert roll_breakout_invalidate("long", 98.0, 99.0) is True
|
||||
assert roll_fib_invalidate("long", 110.0, 105.0, 95.0) is True
|
||||
|
||||
|
||||
def test_preview_breakout_mode_label():
|
||||
preview, err = preview_roll(
|
||||
direction="long",
|
||||
symbol="ETH/USDT",
|
||||
qty_existing=1.0,
|
||||
entry_existing=3000.0,
|
||||
initial_take_profit=3500.0,
|
||||
add_mode="breakout",
|
||||
new_stop_loss=2980.0,
|
||||
breakthrough_price=3100.0,
|
||||
risk_percent=10.0,
|
||||
capital_base_usdt=1000.0,
|
||||
add_price=3050.0,
|
||||
)
|
||||
assert err is None
|
||||
assert preview["add_mode_label"] == "突破加仓"
|
||||
|
||||
|
||||
def test_breakout_geometry_short_mark_above_breakout():
|
||||
err = validate_roll_geometry(
|
||||
"short",
|
||||
"breakout",
|
||||
new_stop_loss=568.0,
|
||||
breakthrough_price=551.0,
|
||||
entry_existing=560.0,
|
||||
initial_take_profit=540.0,
|
||||
mark_price=560.0,
|
||||
)
|
||||
assert err is None
|
||||
|
||||
|
||||
def test_breakout_geometry_short_rejects_mark_at_or_below_breakout():
|
||||
err = validate_roll_geometry(
|
||||
"short",
|
||||
"breakout",
|
||||
new_stop_loss=568.0,
|
||||
breakthrough_price=551.0,
|
||||
entry_existing=560.0,
|
||||
initial_take_profit=540.0,
|
||||
mark_price=551.0,
|
||||
)
|
||||
assert err is not None
|
||||
assert "高于突破价" in err
|
||||
|
||||
|
||||
def test_breakout_geometry_long_rejects_mark_at_or_above_breakout():
|
||||
err = validate_roll_geometry(
|
||||
"long",
|
||||
"breakout",
|
||||
new_stop_loss=2980.0,
|
||||
breakthrough_price=3100.0,
|
||||
entry_existing=3000.0,
|
||||
initial_take_profit=3500.0,
|
||||
mark_price=3100.0,
|
||||
)
|
||||
assert err is not None
|
||||
assert "低于突破价" in err
|
||||
from lib.strategy.strategy_roll_lib import (
|
||||
preview_roll,
|
||||
roll_breakout_invalidate,
|
||||
roll_breakout_trigger_crossed,
|
||||
roll_fib_invalidate,
|
||||
roll_fib_trigger_crossed,
|
||||
solve_add_amount_for_total_risk,
|
||||
validate_roll_geometry,
|
||||
)
|
||||
|
||||
|
||||
def test_solve_add_amount_long_one_risk():
|
||||
q2, err = solve_add_amount_for_total_risk(
|
||||
"long", 1.0, 3000.0, 3100.0, 2950.0, 200.0, 1.0
|
||||
)
|
||||
assert err is None
|
||||
avg = (1 * 3000 + q2 * 3100) / (1 + q2)
|
||||
loss = (avg - 2950) * (1 + q2)
|
||||
assert abs(loss - 200.0) < 0.01
|
||||
|
||||
|
||||
def test_preview_roll_market_short():
|
||||
preview, err = preview_roll(
|
||||
direction="short",
|
||||
symbol="HYPE/USDT",
|
||||
qty_existing=3.0,
|
||||
entry_existing=65.0,
|
||||
initial_take_profit=60.0,
|
||||
add_mode="market",
|
||||
new_stop_loss=66.5,
|
||||
risk_percent=2.0,
|
||||
capital_base_usdt=1000.0,
|
||||
add_price=64.0,
|
||||
legs_done=1,
|
||||
)
|
||||
assert err is None
|
||||
assert preview["add_mode_label"] == "市价加仓"
|
||||
sl = preview["new_stop_loss"]
|
||||
avg = preview["avg_entry_after"]
|
||||
qty = preview["qty_after"]
|
||||
loss = (sl - avg) * qty
|
||||
assert abs(loss - 20.0) < 0.01
|
||||
|
||||
|
||||
def test_fib_cross_long_down():
|
||||
assert roll_fib_trigger_crossed("long", 101.0, 100.0, 100.5) is True
|
||||
assert roll_fib_trigger_crossed("long", 100.6, 100.6, 100.5) is False
|
||||
|
||||
|
||||
def test_breakout_cross_long_up():
|
||||
assert roll_breakout_trigger_crossed("long", 99.0, 100.5, 100.0) is True
|
||||
assert roll_breakout_invalidate("long", 98.0, 99.0) is True
|
||||
assert roll_fib_invalidate("long", 110.0, 105.0, 95.0) is True
|
||||
|
||||
|
||||
def test_preview_breakout_mode_label():
|
||||
preview, err = preview_roll(
|
||||
direction="long",
|
||||
symbol="ETH/USDT",
|
||||
qty_existing=1.0,
|
||||
entry_existing=3000.0,
|
||||
initial_take_profit=3500.0,
|
||||
add_mode="breakout",
|
||||
new_stop_loss=2980.0,
|
||||
breakthrough_price=3100.0,
|
||||
risk_percent=10.0,
|
||||
capital_base_usdt=1000.0,
|
||||
add_price=3050.0,
|
||||
)
|
||||
assert err is None
|
||||
assert preview["add_mode_label"] == "突破加仓"
|
||||
|
||||
|
||||
def test_breakout_geometry_short_mark_above_breakout():
|
||||
err = validate_roll_geometry(
|
||||
"short",
|
||||
"breakout",
|
||||
new_stop_loss=568.0,
|
||||
breakthrough_price=551.0,
|
||||
entry_existing=560.0,
|
||||
initial_take_profit=540.0,
|
||||
mark_price=560.0,
|
||||
)
|
||||
assert err is None
|
||||
|
||||
|
||||
def test_breakout_geometry_short_rejects_mark_at_or_below_breakout():
|
||||
err = validate_roll_geometry(
|
||||
"short",
|
||||
"breakout",
|
||||
new_stop_loss=568.0,
|
||||
breakthrough_price=551.0,
|
||||
entry_existing=560.0,
|
||||
initial_take_profit=540.0,
|
||||
mark_price=551.0,
|
||||
)
|
||||
assert err is not None
|
||||
assert "高于突破价" in err
|
||||
|
||||
|
||||
def test_breakout_geometry_long_rejects_mark_at_or_above_breakout():
|
||||
err = validate_roll_geometry(
|
||||
"long",
|
||||
"breakout",
|
||||
new_stop_loss=2980.0,
|
||||
breakthrough_price=3100.0,
|
||||
entry_existing=3000.0,
|
||||
initial_take_profit=3500.0,
|
||||
mark_price=3100.0,
|
||||
)
|
||||
assert err is not None
|
||||
assert "低于突破价" in err
|
||||
|
||||
Reference in New Issue
Block a user