Overall Statistics |
Total Trades 536 Average Win 2.16% Average Loss -1.37% Compounding Annual Return 1.208% Drawdown 32.200% Expectancy 0.065 Net Profit 16.909% Sharpe Ratio 0.158 Loss Rate 59% Win Rate 41% Profit-Loss Ratio 1.57 Alpha 0.02 Beta -0.019 Annual Standard Deviation 0.125 Annual Variance 0.016 Information Ratio -0.067 Tracking Error 0.247 Treynor Ratio -1.067 Total Fees $2576.96 |
namespace QuantConnect { public partial class TestingLSMA : QCAlgorithm { #region Fields private static string symbol = "SPY"; LeastSquaredMovingAverage LSMA; decimal _prev; #endregion #region QCAlgorithm Methods public override void Initialize() { SetStartDate(2000, 1, 1); SetEndDate(2012, 12, 31); SetCash(100000); AddSecurity(SecurityType.Equity, symbol, Resolution.Daily); var close = Identity(symbol); LSMA = new LeastSquaredMovingAverage(20); RegisterIndicator(symbol, LSMA, Resolution.Daily, Field.Close); var chart = new Chart("Plot"); chart.AddSeries(new Series(close.Name)); chart.AddSeries(new Series(LSMA.Name)); PlotIndicator("Plot", close); PlotIndicator("Plot", true, LSMA); } public void OnData(TradeBars data) { if(Portfolio[symbol].Invested && _prev != 0 && LSMA < _prev) { Liquidate(symbol); } if(!Portfolio[symbol].Invested && _prev != 0 && LSMA > _prev) { SetHoldings(symbol, 1); } _prev = LSMA; } #endregion } }
using System; using System.Linq; using MathNet.Numerics; using MathNet.Numerics.LinearAlgebra; namespace QuantConnect.Indicators { /// <summary> /// The Least Squares Moving Average (LSMA) first calculates a least squares regression line /// over the preceding time periods, and then projects it forward to the current period. In /// essence, it calculates what the value would be if the regression line continued. /// Source: https://rtmath.net/helpFinAnalysis/html/b3fab79c-f4b2-40fb-8709-fdba43cdb363.htm /// </summary> public class LeastSquaredMovingAverage : WindowIndicator<IndicatorDataPoint> { /// <summary> /// Array representing the time. /// </summary> private double[] t; /// <summary> /// Initializes a new instance of the <see cref="LeastSquaredMovingAverage"/> class. /// </summary> /// <param name="name">The name of this indicator</param> /// <param name="period">The number of data points to hold in the window</param> public LeastSquaredMovingAverage(string name, int period) : base(name, period) { t = Vector<double>.Build.Dense(period, i => i + 1).ToArray(); } /// <summary> /// Initializes a new instance of the <see cref="LeastSquaredMovingAverage"/> class. /// </summary> /// <param name="period">The number of data points to hold in the window.</param> public LeastSquaredMovingAverage(int period) : this("LSMA" + period, period) { } /// <summary> /// Computes the next value of this indicator from the given state /// </summary> /// <param name="window"></param> /// <param name="input">The input given to the indicator</param> /// <returns> /// A new value for this indicator /// </returns> protected override decimal ComputeNextValue(IReadOnlyWindow<IndicatorDataPoint> window, IndicatorDataPoint input) { // Until the windows is ready, the indicator returns the input value. decimal output = input; if (IsReady) { // Sort the windows by time, convert the observations ton double and transform it to a double array double[] series = window .OrderBy(i => i.Time) .Select(i => Convert.ToDouble(i.Value)) .ToArray<double>(); // Fit OLS Tuple<double, double> ols = Fit.Line(x: t, y: series); var alfa = (decimal)ols.Item1; var beta = (decimal)ols.Item2; // Make the projection. output = alfa + beta * (Period); } return output; } } }