| 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;
}
}
}