زیان شارپ مقاوم با هزینه گردش معاملات برای یادگیری پرتفوی
خلاصه
این ماژول یک تابع هدف مشتقپذیر برای یادگیری سرتاسری پرتفوی تعریف میکند. وزنهای ریسک محدودشده هر دارایی را با مقیاسدهی نوسان به مواجهههای پرتفوی تبدیل میکند، میانگین بازده ناخالص داراییهای موجود را محاسبه میکند و در صورت انتخاب، هزینههای معامله را بر مبنای تغییر وزنهای قبلی کم میکند. میتوان یک دوره گرمشدن اولیه را از ارزیابی سری بازده کنار گذاشت.
تابع هدف نسبت شارپ تجمیعی را با کمینه نرم نسبتهای شارپ هر پنجره ترکیب میکند؛ وزن ترکیب با پارامتری تنظیمپذیر تعیین میشود و آموزش، منفی امتیاز ترکیبی را کمینه میکند. این ساختار عملکرد کلی تعدیلشده با ریسک را تقویت میکند و همزمان پنجرههای ضعیفتر را نیز لحاظ میکند. توابع گزینههای قابل تنظیم برای سالانهسازی، پایدارسازی عددی، مقیاس هزینه و دمای کمینه نرم ارائه میدهند. سند تعاریف پیادهسازی را عرضه میکند، اما نتایج تجربی، راهنمای کالیبراسیون یا شاهدی بر بهبود عملکرد تحققیافته ارائه نمیدهد؛ بنابراین نتایج به انتخاب وزنها، ماسکها، هزینهها و ابرپارامترها وابستهاند.
ایدههای کلیدی
- بازده پرتفوی از وزنهای ریسک و مقیاسدهی نوسان محاسبه و در هر گام زمانی میان داراییهای موجود میانگینگیری میشود.
- هزینههای معامله را میتوان بهصورت جریمهای بر تغییر مواجهه پرتفوی نسبت به گام قبلی مدلسازی کرد.
- تابع زیان، شارپ تجمیعی را با کمینه نرم نسبتهای شارپ در سطح پنجره ترکیب میکند.
- میتوان مشاهدات دوره گرمشدن اولیه را از محاسبات شارپ کنار گذاشت.
- این ماژول تابع هدف را تعریف میکند، اما شاهد تجربی یا مقادیر پارامتر پیشنهادی ارائه نمیدهد.
برچسبها
متن کامل
# losses.py
```py
"""Loss functions for DeePM-style end-to-end portfolio learning."""
from __future__ import annotations
from dataclasses import dataclass
import torch
@dataclass(frozen=True, slots=True)
class LossOutput:
"""Outputs returned by the robust Sharpe loss."""
loss: torch.Tensor
sharpe_pool: torch.Tensor
softmin_sharpe: torch.Tensor
objective: torch.Tensor
net_returns: torch.Tensor
def compute_net_portfolio_returns(
*,
p: torch.Tensor,
y_fwd1: torch.Tensor,
vol_scale: torch.Tensor,
mask: torch.Tensor,
costs: torch.Tensor | None,
gamma_cost: float,
) -> torch.Tensor:
"""Compute net portfolio returns (Eq. 13).
Parameters
----------
p: Risk weights in (-1, 1), shape (B, T, N).
y_fwd1: Vol-scaled forward returns, shape (B, T, N).
vol_scale: Volatility scaling, shape (B, T, N).
mask: Availability mask, shape (B, T, N).
costs: Per-asset cost coefficients, shape (N,) or (N, 1). None to skip.
gamma_cost: Global cost scaling factor.
Returns
-------
Net portfolio return series, shape (B, T).
"""
b, t, n = p.shape
w = vol_scale * p
w_prev = torch.cat(
[torch.zeros((b, 1, n), device=w.device, dtype=w.dtype), w[:, :-1, :]], dim=1
)
gross = (mask * p * y_fwd1).sum(dim=-1)
n_t = mask.sum(dim=-1).clamp(min=1.0)
gross = gross / n_t
if costs is None:
return gross
if (costs.ndim == 2 and costs.shape[1] == 1) or (costs.ndim == 1 and costs.shape[0] == n):
c = costs.view(1, 1, n)
else:
raise ValueError("costs must have shape (N,) or (N,1)")
turnover = torch.abs(w - w_prev)
cost = (mask * c * turnover).sum(dim=-1)
cost = (gamma_cost * cost) / n_t
return gross - cost
def sharpe_ratio(
returns: torch.Tensor,
*,
annualization_factor: float,
eps: float,
dim: int | None = None,
) -> torch.Tensor:
"""Compute a differentiable Sharpe ratio."""
if dim is None:
mu = returns.mean()
var = returns.var(unbiased=False)
else:
mu = returns.mean(dim=dim)
var = returns.var(dim=dim, unbiased=False)
return (annualization_factor**0.5) * mu / torch.sqrt(var + eps)
def softmin_sharpe(
window_sharpes: torch.Tensor,
*,
tau: float,
) -> torch.Tensor:
"""Soft minimum of window-wise Sharpe ratios (Eq. 33)."""
return -tau * torch.log(torch.mean(torch.exp(-window_sharpes / tau)))
def robust_sharpe_loss(
*,
p: torch.Tensor,
y_fwd1: torch.Tensor,
vol_scale: torch.Tensor,
mask: torch.Tensor,
costs: torch.Tensor | None,
burn_in: int,
gamma_cost: float,
annualization_factor: float,
eps: float,
tau: float,
lambda_soft: float,
) -> LossOutput:
"""Compute DeePM robust objective loss (Eq. 31).
L(theta) = - SR_pool(R) - lambda * SoftMin_tau({SR_b}).
"""
net_r = compute_net_portfolio_returns(
p=p,
y_fwd1=y_fwd1,
vol_scale=vol_scale,
mask=mask,
costs=costs,
gamma_cost=gamma_cost,
)
net_r_eff = net_r[:, burn_in:] if burn_in > 0 else net_r
sr_pool = sharpe_ratio(
net_r_eff.reshape(-1), annualization_factor=annualization_factor, eps=eps
)
sr_windows = sharpe_ratio(net_r_eff, annualization_factor=annualization_factor, eps=eps, dim=1)
sr_softmin = softmin_sharpe(sr_windows, tau=tau)
objective = sr_pool + lambda_soft * sr_softmin
loss = -objective
return LossOutput(
loss=loss,
sharpe_pool=sr_pool.detach(),
softmin_sharpe=sr_softmin.detach(),
objective=objective.detach(),
net_returns=net_r.detach(),
)
```با ذکر منبع و مطابق مجوز اثر، بهطور کامل نمایش داده میشود. مجوز: MIT
این خلاصه را عامل پژوهشی Stratmill بر پایه متن اصلی نوشته است؛ نسخهای از اثر منبع نیست.