feat中控市价单:实例按第一档实值与杠杆立即全仓开仓。
EOF Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,138 @@
|
||||
"""市价单选约:第一档实值内按杠杆接近度优选."""
|
||||
from __future__ import annotations
|
||||
|
||||
import unittest
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
|
||||
class TestMarketOrderLeveragePick(unittest.TestCase):
|
||||
def test_picks_closest_leverage_on_first_itm_rung(self):
|
||||
from lib.options.options_cond_order_lib import pick_nearest_itm_contract
|
||||
|
||||
# 指数 3000, Put 实值一档=3100;同档不同 ask → 杠杆≈1/ask
|
||||
chain = {
|
||||
"expiries": [
|
||||
{
|
||||
"exp_time": 9_999_999_999_000,
|
||||
"contracts": [
|
||||
{
|
||||
"inst_id": "ETH-USD-3100-P-far",
|
||||
"strike": 3100,
|
||||
"opt_type": "P",
|
||||
"ask": 0.05,
|
||||
"ask_sz": 10,
|
||||
"ct_mult": 0.1,
|
||||
},
|
||||
{
|
||||
"inst_id": "ETH-USD-3100-P-near-lev",
|
||||
"strike": 3100,
|
||||
"opt_type": "P",
|
||||
"ask": 0.1,
|
||||
"ask_sz": 10,
|
||||
"ct_mult": 0.1,
|
||||
},
|
||||
{
|
||||
"inst_id": "ETH-USD-3200-P-deeper",
|
||||
"strike": 3200,
|
||||
"opt_type": "P",
|
||||
"ask": 0.1,
|
||||
"ask_sz": 10,
|
||||
"ct_mult": 0.1,
|
||||
},
|
||||
],
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
def quote(_ex, inst_id):
|
||||
for c in chain["expiries"][0]["contracts"]:
|
||||
if c["inst_id"] == inst_id:
|
||||
return {
|
||||
"ok": True,
|
||||
"ask": c["ask"],
|
||||
"ask_sz": c["ask_sz"],
|
||||
"ct_mult": c["ct_mult"],
|
||||
}
|
||||
return {"ok": False}
|
||||
|
||||
cfg = {"quote_option_contract": quote}
|
||||
with patch(
|
||||
"lib.exchange.okx_options_lib.build_option_chain", return_value=chain
|
||||
), patch(
|
||||
"lib.exchange.okx_options_lib.option_buy_liquidity_ok",
|
||||
return_value=(True, ""),
|
||||
):
|
||||
# 目标杠杆 10 → 1/0.1=10, 应选 near-lev 而非 far(杠杆20)
|
||||
picked = pick_nearest_itm_contract(
|
||||
cfg,
|
||||
MagicMock(),
|
||||
underlying="ETH",
|
||||
opt_type="P",
|
||||
index_px=3000.0,
|
||||
min_expiry_hours=1.0,
|
||||
target_leverage=10.0,
|
||||
)
|
||||
self.assertIsNotNone(picked)
|
||||
self.assertEqual(picked["inst_id"], "ETH-USD-3100-P-near-lev")
|
||||
self.assertAlmostEqual(float(picked.get("picked_leverage") or 0), 10.0, places=1)
|
||||
|
||||
def test_without_leverage_keeps_nearest_itm(self):
|
||||
from lib.options.options_cond_order_lib import pick_nearest_itm_contract
|
||||
|
||||
chain = {
|
||||
"expiries": [
|
||||
{
|
||||
"exp_time": 9_999_999_999_000,
|
||||
"contracts": [
|
||||
{
|
||||
"inst_id": "ETH-USD-3100-P",
|
||||
"strike": 3100,
|
||||
"opt_type": "P",
|
||||
"ask": 0.1,
|
||||
"ask_sz": 10,
|
||||
"ct_mult": 0.1,
|
||||
},
|
||||
{
|
||||
"inst_id": "ETH-USD-3200-P",
|
||||
"strike": 3200,
|
||||
"opt_type": "P",
|
||||
"ask": 0.05,
|
||||
"ask_sz": 10,
|
||||
"ct_mult": 0.1,
|
||||
},
|
||||
],
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
def quote(_ex, inst_id):
|
||||
for c in chain["expiries"][0]["contracts"]:
|
||||
if c["inst_id"] == inst_id:
|
||||
return {
|
||||
"ok": True,
|
||||
"ask": c["ask"],
|
||||
"ask_sz": c["ask_sz"],
|
||||
"ct_mult": c["ct_mult"],
|
||||
}
|
||||
return {"ok": False}
|
||||
|
||||
cfg = {"quote_option_contract": quote}
|
||||
with patch(
|
||||
"lib.exchange.okx_options_lib.build_option_chain", return_value=chain
|
||||
), patch(
|
||||
"lib.exchange.okx_options_lib.option_buy_liquidity_ok",
|
||||
return_value=(True, ""),
|
||||
):
|
||||
picked = pick_nearest_itm_contract(
|
||||
cfg,
|
||||
MagicMock(),
|
||||
underlying="ETH",
|
||||
opt_type="P",
|
||||
index_px=3000.0,
|
||||
min_expiry_hours=1.0,
|
||||
)
|
||||
self.assertEqual(picked["inst_id"], "ETH-USD-3100-P")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user