Source code for fynance.models.loss.calmar

#!/usr/bin/env python3
# coding: utf-8

""" Differentiable Calmar-ratio loss. """

from __future__ import annotations

# Third-party packages
import torch

# Local packages
from ._base import BaseLoss

__all__ = ['CalmarLoss']


[docs] class CalmarLoss(BaseLoss): r""" Negative Calmar ratio as a differentiable loss. Calmar = annualized return / maximum drawdown. Minimizing this loss maximizes return per unit of worst peak-to-trough loss. The maximum drawdown is computed differentiably from the cumulative return path via :func:`torch.cummax`. Parameters are inherited from :class:`BaseLoss` (``period``, ``eps``). """
[docs] def forward( self, y_pred: torch.Tensor, y_true: torch.Tensor | None = None, ) -> torch.Tensor: """ Compute the negative Calmar ratio (scalar). """ self._check_tensor(y_pred) equity = torch.cumsum(y_pred, dim=0) running_max, _ = torch.cummax(equity, dim=0) max_drawdown = (running_max - equity).max() annual_return = y_pred.mean() * self.period return -(annual_return / (max_drawdown + self.eps))