/* * QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals. * Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using Python.Runtime; using QuantConnect.Data; using QuantConnect.Python; namespace QuantConnect.Indicators { /// /// Calculation of the Sharpe Ratio (SR) developed by William F. Sharpe. /// /// Reference: https://www.investopedia.com/articles/07/sharpe_ratio.asp /// Formula: S(x) = (Rx - Rf) / stdDev(Rx) /// Where: /// S(x) - sharpe ratio of x /// Rx - average rate of return for x /// Rf - risk-free rate /// public class SharpeRatio : IndicatorBase, IIndicatorWarmUpPeriodProvider { /// /// Length of lookback period for the Sharpe ratio calculation /// private readonly int _period; /// /// Risk-free rate model /// private readonly IRiskFreeInterestRateModel _riskFreeInterestRateModel; /// /// RateOfChange indicator for calculating the sharpe ratio /// protected RateOfChange RateOfChange { get; } /// /// RiskFreeRate indicator for calculating the sharpe ratio /// protected Identity RiskFreeRate { get; } /// /// Indicator to store the calculation of the sharpe ratio /// protected IndicatorBase Ratio { get; set; } /// /// Indicator to store the numerator of the Sharpe ratio calculation /// protected IndicatorBase Numerator { get; } /// /// Required period, in data points, for the indicator to be ready and fully initialized. /// public int WarmUpPeriod { get; } /// /// Returns whether the indicator is properly initialized with data /// public override bool IsReady => Ratio.Samples > _period; /// /// Creates a new Sharpe Ratio indicator using the specified periods /// /// The name of this indicator /// Period of historical observation for sharpe ratio calculation /// Risk-free rate model public SharpeRatio(string name, int period, IRiskFreeInterestRateModel riskFreeRateModel) : base(name) { _period = period; _riskFreeInterestRateModel = riskFreeRateModel; // calculate sharpe ratio using indicators RateOfChange = new RateOfChange(1); RiskFreeRate = new Identity(name + "_RiskFreeRate"); Numerator = RateOfChange.SMA(period).Minus(RiskFreeRate); var denominator = new StandardDeviation(period).Of(RateOfChange); Ratio = Numerator.Over(denominator); // define warmup value; // _roc is the base of our indicator chain + period of STD and SMA WarmUpPeriod = RateOfChange.WarmUpPeriod + period; } /// /// Creates a new Sharpe Ratio indicator using the specified periods /// /// Period of historical observation for sharpe ratio calculation /// Risk-free rate model public SharpeRatio(int period, IRiskFreeInterestRateModel riskFreeRateModel) : this($"SR({period})", period, riskFreeRateModel) { } /// /// Creates a new Sharpe Ratio indicator using the specified period using a Python risk free rate model /// /// Period of historical observation for sharpe ratio calculation /// Risk-free rate model public SharpeRatio(string name, int period, PyObject riskFreeRateModel) : this(name, period, RiskFreeInterestRateModelPythonWrapper.FromPyObject(riskFreeRateModel)) { } /// /// Creates a new Sharpe Ratio indicator using the specified period using a Python risk free rate model /// /// Period of historical observation for sharpe ratio calculation /// Risk-free rate model public SharpeRatio(int period, PyObject riskFreeRateModel) : this(period, RiskFreeInterestRateModelPythonWrapper.FromPyObject(riskFreeRateModel)) { } /// /// Creates a new Sharpe Ratio indicator using the specified periods /// /// The name of this indicator /// Period of historical observation for sharpe ratio calculation /// Risk-free rate for sharpe ratio calculation public SharpeRatio(string name, int period, decimal riskFreeRate = 0.0m) : this(name, period, new ConstantRiskFreeRateInterestRateModel(riskFreeRate)) { } /// /// Creates a new SharpeRatio indicator using the specified periods /// /// Period of historical observation for sharpe ratio calculation /// Risk-free rate for sharpe ratio calculation public SharpeRatio(int period, decimal riskFreeRate = 0.0m) : this($"SR({period},{riskFreeRate})", period, riskFreeRate) { } /// /// Computes the next value for this indicator from the given state. /// /// The input given to the indicator /// A new value for this indicator protected override decimal ComputeNextValue(IndicatorDataPoint input) { RiskFreeRate.Update(input.EndTime, _riskFreeInterestRateModel.GetInterestRate(input.EndTime)); RateOfChange.Update(input); return Ratio; } /// /// Resets this indicator to its initial state /// public override void Reset() { Ratio.Reset(); RateOfChange.Reset(); base.Reset(); } } }