#[cfg(feature = "serde")]
use serde::{Serialize, Deserialize};
pub trait PortfolioPerformanceMetric: {
fn performance(&self, portfolio_return: f64, portfolio_std: f64) -> f64;
fn objective_function(&self, portfolio_return: f64, portfolio_std: f64) -> f64;
}
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct SharpeRatio {
pub rf: f64,
}
impl PortfolioPerformanceMetric for SharpeRatio {
fn performance(&self, portfolio_return: f64, portfolio_std: f64) -> f64 {
(portfolio_return - self.rf) / portfolio_std
}
fn objective_function(&self, portfolio_return: f64, portfolio_std: f64) -> f64 {
-self.performance(portfolio_return, portfolio_std)
}
}
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct InformationRatio {
pub rf: f64,
pub benchmark_sharpe_ratio: f64,
}
impl PortfolioPerformanceMetric for InformationRatio {
fn performance(&self, portfolio_return: f64, portfolio_std: f64) -> f64 {
(((portfolio_return - self.rf) / portfolio_std).powi(2) - self.benchmark_sharpe_ratio.powi(2)).sqrt()
}
fn objective_function(&self, portfolio_return: f64, portfolio_std: f64) -> f64 {
self.performance(portfolio_return, portfolio_std)
}
}
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct TreynorRatio {
pub rf: f64,
pub expected_market_return: f64,
}
impl PortfolioPerformanceMetric for TreynorRatio {
fn performance(&self, portfolio_return: f64, _: f64) -> f64 {
let portfolio_beta: f64 = (portfolio_return - self.rf) / (self.expected_market_return - self.rf);
(portfolio_return - self.rf) / portfolio_beta
}
fn objective_function(&self, portfolio_return: f64, portfolio_std: f64) -> f64 {
-self.performance(portfolio_return, portfolio_std)
}
}
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct JensensAlpha {
pub rf: f64,
pub theoretical_portfolio_beta: f64,
pub expected_market_return: f64,
}
impl PortfolioPerformanceMetric for JensensAlpha {
fn performance(&self, portfolio_return: f64, _: f64) -> f64 {
portfolio_return - self.rf - self.theoretical_portfolio_beta * (self.expected_market_return - self.rf)
}
fn objective_function(&self, portfolio_return: f64, portfolio_std: f64) -> f64 {
-self.performance(portfolio_return, portfolio_std)
}
}
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct SortinoRatio {
pub target_portfolio_return: f64,
pub downside_risk: f64,
}
impl PortfolioPerformanceMetric for SortinoRatio {
fn performance(&self, portfolio_return: f64, _: f64) -> f64 {
(portfolio_return - self.target_portfolio_return) / self.downside_risk
}
fn objective_function(&self, portfolio_return: f64, portfolio_std: f64) -> f64 {
-self.performance(portfolio_return, portfolio_std)
}
}