Overall Statistics Total Trades 1 Average Win 0% Average Loss 0% Compounding Annual Return 10.567% Drawdown 18.800% Expectancy 0 Net Profit 0% Sharpe Ratio 0.634 Loss Rate 0% Win Rate 0% Profit-Loss Ratio 0 Alpha 0.124 Beta -0.059 Annual Standard Deviation 0.184 Annual Variance 0.034 Information Ratio 0.016 Tracking Error 0.267 Treynor Ratio -1.996 Total Fees \$5.04
```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;
{
// 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;
}
}
}                        ```
```namespace QuantConnect
{
public partial class TestingLSMA : QCAlgorithm
{
#region Fields
private static string symbol = "SPY";
LeastSquaredMovingAverage LSMA;
#endregion

#region QCAlgorithm Methods
public override void Initialize()
{
SetStartDate(2010, 01, 1);
SetEndDate(2012, 12, 31);

SetCash(100000);

var close = Identity(symbol);

LSMA = new LeastSquaredMovingAverage(20);
RegisterIndicator(symbol, LSMA, Resolution.Daily, Field.Close);

var chart = new Chart("Plot");

PlotIndicator("Plot", close);
PlotIndicator("Plot", true, LSMA);
}

{
if (!Portfolio[symbol].Invested)
{
SetHoldings(symbol, 1);
}
}
#endregion
}
}                        ```