Source code for fynance.models.loss.omega
#!/usr/bin/env python3
# coding: utf-8
""" Differentiable Omega-ratio loss. """
from __future__ import annotations
# Third-party packages
import torch
# Local packages
from ._base import BaseLoss
__all__ = ['OmegaLoss']
[docs]
class OmegaLoss(BaseLoss):
r""" Negative Omega ratio as a differentiable loss.
:math:`\Omega = \frac{E[\max(r - L, 0)]}{E[\max(L - r, 0)] + \varepsilon}`,
the ratio of expected gains to expected losses relative to a threshold
``L``. Fully differentiable through :func:`torch.relu`. Minimizing the
loss maximizes the Omega ratio.
Parameters
----------
threshold : float, optional
Return threshold ``L`` separating gains from losses. Default 0.
**kwargs
Forwarded to :class:`BaseLoss` (``rf``, ``period``, ``eps``).
"""
def __init__(self, threshold: float = 0., **kwargs):
super().__init__(**kwargs)
self.threshold = threshold
[docs]
def forward(
self, y_pred: torch.Tensor, y_true: torch.Tensor | None = None,
) -> torch.Tensor:
""" Compute the negative Omega ratio (scalar). """
self._check_tensor(y_pred)
diff = y_pred - self.threshold
gains = torch.relu(diff).mean()
losses = torch.relu(-diff).mean()
return -(gains / (losses + self.eps))