DEV Community

drake
drake

Posted on

Profit Factor — Python 实现(from gpt)

from typing import Iterable, Dict, List, Union

def profit_factor_from_trades_and_positions(
    fills: Iterable[Dict],            # 每笔已平仓或填充记录,包含字段 closedPnl (float)
    asset_positions: Iterable[Dict]  # 当前 assetPositions,包含 position.unrealizedPnl (float)
) -> Union[float, str]:
    """
    根据 JS 实现还原的 Profit Factor:
      - 将所有正的 closedPnl + unrealizedPnl 累加为 wins (s)
      - 将所有负的 closedPnl + unrealizedPnl 的绝对值累加为 losses (i)
      - 若 losses != 0 则返回 wins / losses
      - 若 losses == 0 且 wins > 0 则返回字符串 "1000+"(原码使用类似的显示)
      - 否则返回 0.0

    注意:参数中的记录格式和字段名需与源数据一致(closedPnl / position.unrealizedPnl)。
    """
    from decimal import Decimal

    wins = Decimal(0)
    losses = Decimal(0)

    # 累加 fills 中的 closedPnl(示例中 closedPnl 已经是数字或字符串数值)
    for f in fills:
        try:
            pnl = Decimal(str(f.get("closedPnl", 0) or 0))
        except Exception:
            pnl = Decimal(0)
        if pnl > 0:
            wins += pnl
        elif pnl < 0:
            losses += abs(pnl)

    # 累加 asset_positions 中的未实现 pnl(unrealizedPnl)
    for ap in asset_positions:
        # 许多打包后的结构是 ap.position.unrealizedPnl
        pos = ap.get("position") if isinstance(ap, dict) else None
        if pos and "unrealizedPnl" in pos:
            try:
                upnl = Decimal(str(pos.get("unrealizedPnl", 0) or 0))
            except Exception:
                upnl = Decimal(0)
        else:
            # 也可能直接在顶层:ap.get("unrealizedPnl")
            try:
                upnl = Decimal(str(ap.get("unrealizedPnl", 0) or 0))
            except Exception:
                upnl = Decimal(0)

        if upnl > 0:
            wins += upnl
        elif upnl < 0:
            losses += abs(upnl)

    # 根据原 JS 逻辑:如果 losses != 0 -> wins / losses
    if losses != 0:
        # 保持小数精度(可按需 format)
        return float(wins / losses)
    else:
        # losses == 0
        if wins > 0:
            # 原码显示 "1000+" 的情况
            return "1000+"
        else:
            return 0.0

Enter fullscreen mode Exit fullscreen mode

Top comments (0)