首次上传

This commit is contained in:
dekun
2026-05-16 22:25:48 +08:00
commit 2b8f902548
88 changed files with 16386 additions and 0 deletions
@@ -0,0 +1,57 @@
"""移动保本逻辑单元测试。"""
from __future__ import annotations
import unittest
from app.breakeven_logic import (
breakeven_sl_price,
find_sl_plan,
is_1r_reached,
risk_distance,
sl_already_at_or_better,
)
class TestBreakevenLogic(unittest.TestCase):
def test_risk_distance_long(self) -> None:
self.assertAlmostEqual(risk_distance("long", 100.0, 95.0), 5.0)
def test_is_1r_long(self) -> None:
self.assertFalse(is_1r_reached("long", 104.0, 100.0, 95.0, trigger_r=1.0))
self.assertTrue(is_1r_reached("long", 105.0, 100.0, 95.0, trigger_r=1.0))
def test_is_1r_short(self) -> None:
self.assertFalse(is_1r_reached("short", 96.0, 100.0, 105.0, trigger_r=1.0))
self.assertTrue(is_1r_reached("short", 95.0, 100.0, 105.0, trigger_r=1.0))
def test_breakeven_sl_price(self) -> None:
self.assertAlmostEqual(breakeven_sl_price("long", 1000.0, 0.002), 1002.0)
self.assertAlmostEqual(breakeven_sl_price("short", 1000.0, 0.002), 998.0)
def test_sl_already_at_or_better(self) -> None:
self.assertTrue(sl_already_at_or_better("long", 1003.0, 1002.0))
self.assertFalse(sl_already_at_or_better("long", 1001.0, 1002.0))
self.assertTrue(sl_already_at_or_better("short", 997.0, 998.0))
def test_find_sl_plan_long(self) -> None:
plans = [
{
"contract": "BTC_USDT",
"order_id": "tp1",
"rule": 1,
"trigger_price": "110000",
},
{
"contract": "BTC_USDT",
"order_id": "sl1",
"rule": 2,
"trigger_price": "95000",
},
]
oid, px = find_sl_plan("long", "BTC_USDT", plans)
self.assertEqual(oid, "sl1")
self.assertAlmostEqual(px or 0, 95000.0)
if __name__ == "__main__":
unittest.main()
@@ -0,0 +1,58 @@
"""离线测试:TP/SL 触发价按 Gate 合约 tick 对齐(无需 API 密钥)。"""
from __future__ import annotations
import sys
from decimal import Decimal
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
if str(ROOT) not in sys.path:
sys.path.insert(0, str(ROOT))
from app.gate_price_rounding import ( # noqa: E402
_format_trigger_price,
_trigger_price_tick,
)
def test_format_xaut_like_float_garbage() -> None:
assert _format_trigger_price(4752.700000000001, Decimal("0.1")) == "4752.7"
assert _format_trigger_price(4691.7976, Decimal("0.1")) == "4691.8"
def test_format_half_tick() -> None:
assert _format_trigger_price(100.25, Decimal("0.5")) == "100.5"
# 100.24 落在 0.5 网格上为 100.0,去尾零后为 "100"
assert _format_trigger_price(100.24, Decimal("0.5")) == "100"
def test_format_small_coin() -> None:
tick = Decimal("0.00001")
assert _format_trigger_price(0.000123456, tick) == "0.00012"
assert _format_trigger_price(1.23456789e-5, tick) == "0.00001"
def test_trigger_price_tick_from_cdata() -> None:
assert _trigger_price_tick({"order_price_round": "0.1"}) == Decimal("0.1")
assert _trigger_price_tick({"order_price_round": "", "mark_price_round": "0.0001"}) == Decimal("0.0001")
assert _trigger_price_tick({"mark_price_round": "0.01"}) == Decimal("0.01")
assert _trigger_price_tick({}) is None
def test_fallback_no_tick_coarse() -> None:
s = _format_trigger_price(4752.700000000001, None)
assert "00000000000" not in s
assert s.replace(".", "").isdigit() or s.replace(".", "", 1).replace("-", "", 1).isdigit()
def main() -> None:
test_format_xaut_like_float_garbage()
test_format_half_tick()
test_format_small_coin()
test_trigger_price_tick_from_cdata()
test_fallback_no_tick_coarse()
print("test_price_rounding: all passed")
if __name__ == "__main__":
main()