M squared for Sortino is a M^2 calculated for Downside risk instead of Total Risk
M2Sortino(Ra, Rb, MAR = 0, ...)$$M^2_S = r_P + Sortino ratio * (\sigma_{DM} - \sigma_D)$$
where \(M^2_S\) is MSquared for Sortino, \(r_P\) is the annualised portfolio return, \(\sigma_{DM}\) is the benchmark annualised downside risk and \(D\) is the portfolio annualised downside risk
Carl Bacon, Practical portfolio performance measurement and attribution, second edition 2008 p.102-103
data(portfolio_bacon)
MAR = 0.005
print(M2Sortino(portfolio_bacon[,1], portfolio_bacon[,2], MAR)) #expected 0.1035
#> portfolio.monthly.return....
#> Sortino Ratio (MAR = 0.5%) 0.1034799
data(managers)
MAR = 0
print(MSquaredExcess(managers['1996',1], managers['1996',8], MAR))
#> SP500 TR
#> SP500 TR 0.02027322
print(MSquaredExcess(managers['1996',1:5], managers['1996',8], MAR))
#> HAM1 HAM2 HAM3 HAM4 HAM5
#> MSquaredExcess (Risk free = 0) 0.02027322 NA 0.1409545 -0.02546609 NA