fix复盘真盈亏改为期权币盈亏×平仓价,不再绑卖回与初始权利金差。
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -26,37 +26,18 @@ class FeeConvertTests(unittest.TestCase):
|
||||
|
||||
|
||||
class PremiumMoveFormulaTests(unittest.TestCase):
|
||||
def test_user_formula_matches_coin_basis_minus_initial(self):
|
||||
def test_option_pnl_times_close_px(self):
|
||||
coin = 0.01
|
||||
paid = 0.01
|
||||
open_px = 90000.0
|
||||
close_px = 80000.0
|
||||
initial = paid * open_px
|
||||
a = true_pnl_usdt_premium_move(
|
||||
coin_pnl=coin,
|
||||
premium_paid=paid,
|
||||
sell_back_px=close_px,
|
||||
initial_premium_usdt=initial,
|
||||
)
|
||||
# (权利金+盈亏)×卖回 − 初始权利金U
|
||||
expect = (paid + coin) * close_px - initial
|
||||
self.assertAlmostEqual(float(a), expect, places=4)
|
||||
# 无费时 ≡ 收回×平 − 已付×开
|
||||
recv = paid + coin
|
||||
self.assertAlmostEqual(float(a), recv * close_px - paid * open_px, places=4)
|
||||
# 缺初始时用开仓价补算,结果相同
|
||||
b = true_pnl_usdt_premium_move(
|
||||
coin_pnl=coin,
|
||||
premium_paid=paid,
|
||||
sell_back_px=close_px,
|
||||
open_index_px=open_px,
|
||||
)
|
||||
self.assertAlmostEqual(float(b), float(a), places=4)
|
||||
self.assertAlmostEqual(float(a), coin * close_px, places=4)
|
||||
|
||||
|
||||
class SettleClosedPnlTests(unittest.TestCase):
|
||||
def test_sim_net_times_close_index(self):
|
||||
# 无开仓指数时回退净币×平仓价
|
||||
s = settle_closed_pnl(
|
||||
premium_paid=0.01,
|
||||
premium_received=0.02,
|
||||
@@ -68,23 +49,23 @@ class SettleClosedPnlTests(unittest.TestCase):
|
||||
self.assertAlmostEqual(float(s["realized_pnl"]), 0.009, places=8)
|
||||
self.assertAlmostEqual(float(s["realized_pnl_usdt"]), 27.0, places=4)
|
||||
|
||||
def test_sim_proceeds_minus_open_premium_usdt(self):
|
||||
"""盈利=(收回币)×卖回价 − 已付币×开仓指数 − 手续费U."""
|
||||
def test_sim_coin_pnl_times_close(self):
|
||||
"""真盈亏=净币盈亏×平仓价."""
|
||||
s = settle_closed_pnl(
|
||||
premium_paid=0.011005,
|
||||
premium_received=0.02270864,
|
||||
open_fee=0,
|
||||
close_fee=0,
|
||||
premium_ccy="BTC",
|
||||
index_px=81000, # 卖回价
|
||||
open_index_px=86000, # 初始 U 权利金用开仓指数
|
||||
index_px=81000,
|
||||
open_index_px=86000,
|
||||
)
|
||||
# 0.02270864*81000 - 0.011005*86000
|
||||
expect = 0.02270864 * 81000 - 0.011005 * 86000
|
||||
net = 0.02270864 - 0.011005
|
||||
expect = net * 81000
|
||||
self.assertAlmostEqual(float(s["realized_pnl_usdt"]), expect, places=2)
|
||||
|
||||
def test_sim_loss_remaining_minus_fees(self):
|
||||
"""亏损:费先扣进币盈亏,再按用户式折 U(不另扣手续费U)."""
|
||||
"""亏损:费先扣进币盈亏,再×平仓价."""
|
||||
s = settle_closed_pnl(
|
||||
premium_paid=0.01,
|
||||
premium_received=0.004,
|
||||
@@ -94,34 +75,26 @@ class SettleClosedPnlTests(unittest.TestCase):
|
||||
index_px=2500,
|
||||
open_index_px=3000,
|
||||
)
|
||||
# net_coin=-0.0062; U=-0.0062*2500 - 0.01*(3000-2500)=-20.5
|
||||
self.assertAlmostEqual(float(s["realized_pnl"]), -0.0062, places=8)
|
||||
self.assertAlmostEqual(float(s["realized_pnl_usdt"]), -20.5, places=2)
|
||||
self.assertAlmostEqual(float(s["realized_pnl_usdt"]), -15.5, places=2)
|
||||
|
||||
def test_resolve_loss_does_not_deduct_fee_again(self):
|
||||
"""历史币盈亏已含费;resolve 只跑用户式,不再用 open_fee/close_fee 扣第二遍."""
|
||||
from lib.options.options_pnl_settle_lib import resolve_true_pnl_usdt_from_trade
|
||||
|
||||
# coin 已是 recv-paid-fees=-0.0062
|
||||
pnl, src = resolve_true_pnl_usdt_from_trade(
|
||||
premium_paid=0.01,
|
||||
premium_received=0.004,
|
||||
realized_pnl=-0.0062,
|
||||
open_index_px=3000,
|
||||
close_index_px=2500,
|
||||
initial_premium_usdt=30.0,
|
||||
open_fee=0.0001,
|
||||
close_fee=0.0001,
|
||||
premium_ccy="ETH",
|
||||
)
|
||||
self.assertEqual(src, "premium_move")
|
||||
# (0.01-0.0062)*2500 - 30 = 9.5 - 30 = -20.5
|
||||
self.assertAlmostEqual(float(pnl), -20.5, places=2)
|
||||
# 若再扣一遍费会更亏于 -20.5
|
||||
self.assertGreater(float(pnl), -20.55)
|
||||
self.assertAlmostEqual(float(pnl), -15.5, places=2)
|
||||
|
||||
def test_budget_ignored_for_usdt(self):
|
||||
# budget 不得抬高开仓成本
|
||||
s = settle_closed_pnl(
|
||||
premium_paid=0.01,
|
||||
premium_received=0.02,
|
||||
@@ -158,7 +131,6 @@ class SettleClosedPnlTests(unittest.TestCase):
|
||||
|
||||
class SimPremiumPnlStatsTests(unittest.TestCase):
|
||||
def test_sync_sim_no_longer_overwrites_account_settled(self):
|
||||
"""账户结算后 sync 兼容入口不得改写."""
|
||||
import sqlite3
|
||||
|
||||
from lib.options.options_db import init_options_tables
|
||||
@@ -235,13 +207,11 @@ class ExchangeFreezeStatsTests(unittest.TestCase):
|
||||
]
|
||||
frozen = apply_exchange_pnl_freeze(conn, history, _Ex())
|
||||
converted = history_pnl_to_usdt(frozen, _Ex())
|
||||
# 0.000138*100000=13.8; -0.00648*2500=-16.2; net=-2.4
|
||||
self.assertAlmostEqual(float(converted[0]["realized_pnl"]), 13.8, places=4)
|
||||
self.assertAlmostEqual(float(converted[1]["realized_pnl"]), -16.2, places=4)
|
||||
stats = compute_options_stats_from_history(converted)
|
||||
self.assertAlmostEqual(float(stats["net_realized_pnl"]), -2.4, places=4)
|
||||
|
||||
# 指数再变也不改冻结 U
|
||||
class _Ex2:
|
||||
def public_get_market_ticker(self, params):
|
||||
return {"data": [{"last": "999999"}]}
|
||||
|
||||
Reference in New Issue
Block a user