Add OKX hedge-plan P0: env group, preview page, and PnL scenario math.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
"""对冲计划 P0 测算口径单测."""
|
||||
import unittest
|
||||
|
||||
from lib.hedge_plan.hedge_plan_calc_lib import (
|
||||
build_options_options_preview,
|
||||
build_perp_options_preview,
|
||||
gate_status,
|
||||
option_expiry_pnl,
|
||||
option_premium_total,
|
||||
perp_pnl,
|
||||
)
|
||||
|
||||
|
||||
class TestHedgePlanCalc(unittest.TestCase):
|
||||
def test_perp_tp_accounting_is_profit_minus_premium(self):
|
||||
p = build_perp_options_preview(
|
||||
direction="long",
|
||||
entry=3200,
|
||||
tp=3400,
|
||||
sl=3000,
|
||||
contracts=50,
|
||||
contract_size=0.01,
|
||||
opt_type="P",
|
||||
strike=3100,
|
||||
sheets=10,
|
||||
ct_mult=0.01,
|
||||
premium_paid=8,
|
||||
index_px=3200,
|
||||
)
|
||||
self.assertEqual(p["summary"]["tp_total"], 92.0)
|
||||
self.assertEqual(p["scenarios"][0]["options_pnl"], -8.0)
|
||||
|
||||
def test_perp_sl_accounting_is_option_plus_perp_signed(self):
|
||||
p = build_perp_options_preview(
|
||||
direction="long",
|
||||
entry=3200,
|
||||
tp=3400,
|
||||
sl=3000,
|
||||
contracts=50,
|
||||
contract_size=0.01,
|
||||
opt_type="P",
|
||||
strike=3100,
|
||||
sheets=10,
|
||||
ct_mult=0.01,
|
||||
premium_paid=8,
|
||||
index_px=3200,
|
||||
)
|
||||
self.assertEqual(p["summary"]["sl_total"], -98.0)
|
||||
self.assertEqual(p["summary"]["hedge_ratio_at_sl"], 2.0)
|
||||
|
||||
def test_option_premium_and_expiry(self):
|
||||
self.assertEqual(option_premium_total(ask=80, sheets=1, ct_mult=0.01), 0.8)
|
||||
self.assertEqual(
|
||||
option_expiry_pnl(
|
||||
opt_type="P", strike=3100, spot=3000, sheets=10, ct_mult=0.01, premium_paid=8
|
||||
),
|
||||
2.0,
|
||||
)
|
||||
|
||||
def test_gate_perp_requires_full_margin_for_start_message(self):
|
||||
g = gate_status(
|
||||
hedge_enabled=True,
|
||||
sizing_mode="risk",
|
||||
plan_type="perp_options",
|
||||
options_enabled=True,
|
||||
)
|
||||
self.assertTrue(g["can_preview"])
|
||||
self.assertFalse(g["can_start"])
|
||||
self.assertTrue(any("全仓" in r for r in g["reasons"]))
|
||||
|
||||
def test_oo_expiry_loss_flag(self):
|
||||
a = {"opt_type": "C", "strike": 3300, "sheets": 1, "ct_mult": 0.01, "premium_paid": 5}
|
||||
b = {"opt_type": "P", "strike": 3100, "sheets": 1, "ct_mult": 0.01, "premium_paid": 5}
|
||||
p = build_options_options_preview(target_price=3500, index_px=3200, leg_a=a, leg_b=b)
|
||||
self.assertEqual(p["summary"]["premium_paid"], 10)
|
||||
self.assertTrue(p["summary"]["expiry_is_loss"])
|
||||
|
||||
def test_perp_short_pnl(self):
|
||||
self.assertEqual(
|
||||
perp_pnl(direction="short", entry=100, exit_px=90, contracts=1, contract_size=1),
|
||||
10,
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user