User edition: prune docs, license gate, obfuscate core lib.
Keep deploy/basic docs only; integrate sq.bz121.com license client; encrypt strategy/trade/key_monitor/options/hedge_plan for release. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+12
-94
@@ -1,94 +1,12 @@
|
||||
"""永续估算盈亏:固定 taker 手续费(默认单边 0.05%,开+平双边).
|
||||
|
||||
浮盈亏仍读交易所;本模块只服务「盈利金额 / 止盈盈利 / 推送 / 记账 pnl_amount」等估算口径.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import math
|
||||
import os
|
||||
from typing import Optional
|
||||
|
||||
|
||||
def _finite(v) -> Optional[float]:
|
||||
try:
|
||||
f = float(v)
|
||||
return f if math.isfinite(f) else None
|
||||
except (TypeError, ValueError):
|
||||
return None
|
||||
|
||||
|
||||
def taker_fee_rate() -> float:
|
||||
"""单边 taker 费率,默认 0.0005(=0.05%)."""
|
||||
raw = os.getenv("PERP_TAKER_FEE_RATE", "0.0005")
|
||||
rate = _finite(raw)
|
||||
if rate is None or rate < 0:
|
||||
return 0.0005
|
||||
return rate
|
||||
|
||||
|
||||
def notional_usdt(price, qty, contract_size: float = 1.0) -> Optional[float]:
|
||||
"""名义价值 U = 价格 × 张数 × 合约面值."""
|
||||
p = _finite(price)
|
||||
q = _finite(qty)
|
||||
cs = _finite(contract_size)
|
||||
if p is None or q is None or p <= 0 or q <= 0:
|
||||
return None
|
||||
if cs is None or cs <= 0:
|
||||
cs = 1.0
|
||||
return abs(q) * p * cs
|
||||
|
||||
|
||||
def estimate_roundtrip_fee_usdt(
|
||||
entry_price,
|
||||
exit_price,
|
||||
qty=None,
|
||||
contract_size: float = 1.0,
|
||||
*,
|
||||
open_notional: float | None = None,
|
||||
rate: float | None = None,
|
||||
) -> float:
|
||||
"""开+平双边手续费(各单边 rate).
|
||||
|
||||
优先用 价×张×面值;若无张数则用 open_notional 估开仓名义,
|
||||
平仓名义按 exit/entry 缩放.
|
||||
"""
|
||||
fee_rate = taker_fee_rate() if rate is None else float(rate)
|
||||
if fee_rate <= 0:
|
||||
return 0.0
|
||||
entry = _finite(entry_price)
|
||||
exit_p = _finite(exit_price)
|
||||
open_n = notional_usdt(entry, qty, contract_size) if qty is not None else None
|
||||
if open_n is None:
|
||||
open_n = _finite(open_notional)
|
||||
if open_n is None or open_n <= 0:
|
||||
return 0.0
|
||||
if entry is not None and entry > 0 and exit_p is not None and exit_p > 0:
|
||||
close_n = open_n * (exit_p / entry)
|
||||
else:
|
||||
close_n = open_n
|
||||
return round(open_n * fee_rate + close_n * fee_rate, 8)
|
||||
|
||||
|
||||
def net_pnl_after_fee(
|
||||
gross_pnl,
|
||||
entry_price,
|
||||
exit_price,
|
||||
qty=None,
|
||||
contract_size: float = 1.0,
|
||||
*,
|
||||
open_notional: float | None = None,
|
||||
rate: float | None = None,
|
||||
) -> Optional[float]:
|
||||
"""毛利扣双边手续费后的净盈亏;gross 无效则返回 None."""
|
||||
gross = _finite(gross_pnl)
|
||||
if gross is None:
|
||||
return None
|
||||
fee = estimate_roundtrip_fee_usdt(
|
||||
entry_price,
|
||||
exit_price,
|
||||
qty,
|
||||
contract_size,
|
||||
open_notional=open_notional,
|
||||
rate=rate,
|
||||
)
|
||||
return round(gross - fee, 4)
|
||||
# obfuscated module — do not edit
|
||||
import base64, marshal, zlib
|
||||
_B = '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'
|
||||
_K = '5eb9e6dda894c57a4e02d809ae440d49'
|
||||
def _d(b, k):
|
||||
raw = zlib.decompress(base64.b64decode(b))
|
||||
key = k.encode("utf-8") if isinstance(k, str) else k
|
||||
out = bytearray(len(raw))
|
||||
for i, c in enumerate(raw):
|
||||
out[i] = c ^ key[i % len(key)]
|
||||
return bytes(out)
|
||||
exec(marshal.loads(_d(_B, _K)), globals())
|
||||
|
||||
Reference in New Issue
Block a user