Fix amp-stats perp PnL to exit at daily profit target.
Hit A/B via open-to-high/low; day PnL equals target when touched, otherwise settle at close. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+34
-16
@@ -93,10 +93,10 @@ class AmpStatsLibTests(unittest.TestCase):
|
||||
self.assertIsNone(s["perp_hedge"])
|
||||
|
||||
def test_perp_hedge_hit_and_pnl(self):
|
||||
from lib.hub.amp_stats_lib import perp_hedge_day_pnl
|
||||
from lib.hub.amp_stats_lib import perp_hedge_day_pnl, perp_hedge_day_pnl_eod
|
||||
|
||||
# 开盘=1800 optLev=100 → prem/coin=18; 1:2 → premium=36
|
||||
# A move ≈ 52.83; B portfolio move = 51
|
||||
# 开盘=1800 optLev=100 → prem=36; A≈52.83; B=51
|
||||
# 触达目标出场 → 日盈亏=15, 不再按收盘涨跌算满仓
|
||||
rows = [
|
||||
{"open": 1800, "close": 1860, "change": 60, "up_points": 60, "down_points": 0, "amplitude": 60, "settlement_day": "2026-07-01"},
|
||||
{"open": 1800, "close": 1740, "change": -60, "up_points": 0, "down_points": 60, "amplitude": 60, "settlement_day": "2026-07-02"},
|
||||
@@ -114,30 +114,48 @@ class AmpStatsLibTests(unittest.TestCase):
|
||||
ph = s["perp_hedge"]
|
||||
self.assertIsNotNone(ph)
|
||||
self.assertEqual(ph["entry"], "open")
|
||||
self.assertEqual(ph["exit"], "target_or_eod")
|
||||
self.assertEqual(ph["spot"], 1800.0)
|
||||
self.assertEqual(ph["opt_coins"], 2.0)
|
||||
self.assertEqual(ph["premium_total"], 36.0)
|
||||
self.assertAlmostEqual(ph["move_b"], 51.0, places=4)
|
||||
self.assertEqual(ph["hit_a_days"], 1) # only +60
|
||||
self.assertEqual(ph["hit_b_days"], 1) # only -60
|
||||
self.assertEqual(ph["hit_a_days"], 1) # up 60 >= A
|
||||
self.assertEqual(ph["hit_b_days"], 1) # down 60 >= B
|
||||
self.assertEqual(ph["target_exit_days"], 2)
|
||||
self.assertEqual(ph["eod_days"], 1)
|
||||
# 触达目标 → 15U
|
||||
self.assertAlmostEqual(ph["pnl_max"], 15.0, places=4)
|
||||
up_pnl = perp_hedge_day_pnl(
|
||||
change=60, open_px=1800, close_px=1860, option_leverage=100, opt_coins=2
|
||||
change=60,
|
||||
open_px=1800,
|
||||
close_px=1860,
|
||||
option_leverage=100,
|
||||
opt_coins=2,
|
||||
up_points=60,
|
||||
down_points=0,
|
||||
target_profit_u=15,
|
||||
)
|
||||
down_pnl = perp_hedge_day_pnl(
|
||||
change=-60, open_px=1800, close_px=1740, option_leverage=100, opt_coins=2
|
||||
change=-60,
|
||||
open_px=1800,
|
||||
close_px=1740,
|
||||
option_leverage=100,
|
||||
opt_coins=2,
|
||||
up_points=0,
|
||||
down_points=60,
|
||||
target_profit_u=15,
|
||||
)
|
||||
self.assertAlmostEqual(down_pnl, 60 * (2 - 1) - 36, places=4) # 24
|
||||
self.assertAlmostEqual(ph["down_pnl_total"], down_pnl, places=4)
|
||||
self.assertGreater(up_pnl, 0)
|
||||
self.assertAlmostEqual(up_pnl, 15.0, places=4)
|
||||
self.assertAlmostEqual(down_pnl, 15.0, places=4)
|
||||
self.assertAlmostEqual(ph["down_pnl_total"], 15.0, places=4)
|
||||
# 未触达:收盘结算
|
||||
eod = perp_hedge_day_pnl_eod(
|
||||
change=20, open_px=1800, close_px=1820, option_leverage=100, opt_coins=2
|
||||
)
|
||||
self.assertLess(eod, 0)
|
||||
self.assertEqual(ph["up_days"], 2)
|
||||
self.assertEqual(ph["down_days"], 1)
|
||||
|
||||
# 不同开盘 → 不同权利金
|
||||
hi_open_pnl = perp_hedge_day_pnl(
|
||||
change=-60, open_px=2000, close_px=1940, option_leverage=100, opt_coins=2
|
||||
)
|
||||
self.assertAlmostEqual(hi_open_pnl, 60 - 40, places=4) # prem=40
|
||||
|
||||
csv_text = build_export_csv(
|
||||
{
|
||||
"exchange": "okx",
|
||||
|
||||
Reference in New Issue
Block a user