Super newbie here and as per this thread am working on developing the code to back test a momentum strategy. I believe I was able to track down the code the author used on this page. Based on my rudimentary analysis of this code, I believe it will get me to an adjusted slope which is essentially an annualized exponential slope number * r-squared. Have I read that right?
P.S. There will be errors in here as I have not defined the periods.
//Determine the Adjusted Slope for each stock in the defined universe which is the exponential slope * R-squared for each stock in the defined universe.
public double GetSlope()
{
double n = this.periods -1;
double x, y;
double[] xVals;
double[] yVals;
xVals = new double[this.periods];
yVals = new double[this.periods];
for (int i = 0; i < this.periods ; i++)
{
x = ((int)n- i);
y = Math.Log(inputs[0].LookBack(i));
xVals = x;
yVals = y;
}
double rsquared, yintercept, slope;
LinearRegression(xVals,yVals,0,this.periods - 1,out rsquared, out yintercept,out slope);
double annualSlope;
double dayCount = 250;
annualSlope = ((Math.Pow(Math.Exp(slope), dayCount))-1) *100; // Annualized percentage
//
annualSlope = annualSlope *rsquared;
return annualSlope;
}
public static void LinearRegression(double[] xVals, double[] yVals,
int inclusiveStart, int exclusiveEnd,
out double rsquared, out double yintercept,
out double slope)
{
double sumOfX = 0;
double sumOfY = 0;
double sumOfXSq = 0;
double sumOfYSq = 0;
double ssX = 0;
double ssY = 0;
double sumCodeviates = 0;
double sCo = 0;
double count = exclusiveEnd - inclusiveStart;
for (int ctr = inclusiveStart; ctr < exclusiveEnd; ctr++)
{
double x = xVals[ctr];
double y = yVals[ctr];
sumCodeviates += x * y;
sumOfX += x;
sumOfY += y;
sumOfXSq += x * x;
sumOfYSq += y * y;
}
ssX = sumOfXSq - ((sumOfX * sumOfX) / count);
ssY = sumOfYSq - ((sumOfY * sumOfY) / count);
double RNumerator = (count * sumCodeviates) - (sumOfX * sumOfY);
double RDenom = (count * sumOfXSq - (sumOfX * sumOfX))
* (count * sumOfYSq - (sumOfY * sumOfY));
sCo = sumCodeviates - ((sumOfX * sumOfY) / count);
double meanX = sumOfX / count;
double meanY = sumOfY / count;
double dblR = RNumerator / Math.Sqrt(RDenom);
rsquared = dblR * dblR;
yintercept = meanY - ((sCo / ssX) * meanX);
slope = sCo / ssX;
}
Michael Handschuh
Quant Trader
Hi,
Is it possible to use an indicator on the fly dynamically and fill it with history data? I have a universe which is dynamically.
J.
RegisterIndicator("SPY", adjustedSlope, Resolution.Daily, Field.Close);Michael Manus
its a little old but check the post august 2015 a slope indicator was used:
Quant Trader
My algo runs into an algoritmic overflow error as the double is too large to fit the decimal. This happens because of the power of 252 days. If the slope is 2, the number of the power is huge. I tested with this unit test:
public void AESIComputesCorrectlyUptrend() { var aesi = new AnnualizedExponentialSlopeIndicator(4); var data = new[] { 0m, 5m, 10m, 15m, 20m, 25m, 30m }; var seen = new List<decimal>(); for (int i = 0; i < data.Length; i++) { var datum = data[i]; seen.Add(datum); aesi.Update(new IndicatorDataPoint(DateTime.Now.AddSeconds(i), datum)); } Assert.Greater(aesi.Current.Value, 0m); }
my indicator is:
using MathNet.Numerics; using QuantConnect.Indicators; using System; using System.Linq; //Copied from this forum: //href https://www.quantconnect.com/forum/discussion/695/adjusted-slope--exponential-slope----annualized-slope--r-squuared--adjusted-slope/p1 namespace QuantConnect.Algorithm.CSharp.Helpers { public class AnnualizedExponentialSlopeIndicator : WindowIndicator<IndicatorDataPoint> { public AnnualizedExponentialSlopeIndicator(int period) : base("AdjustedSlope" + period, period) { } public AnnualizedExponentialSlopeIndicator(string name, int period) : base(name, period) { } protected override decimal ComputeNextValue(IReadOnlyWindow<IndicatorDataPoint> window, IndicatorDataPoint input) { if (window.Count < 3) return 0m; var xVals = new double[window.Count]; var yVals = new double[window.Count]; // load input data for regression for (int i = 0; i < window.Count; i++) { xVals[i] = i; // we want the log of our y values yVals[i] = Math.Log((double)window[window.Count - i - 1].Value); } //http://numerics.mathdotnet.com/Regression.html // solves y=a + b*x via linear regression var fit = Fit.Line(xVals, yVals); var intercept = fit.Item1; var slope = fit.Item2; // compute rsquared var rsquared = GoodnessOfFit.RSquared(xVals.Select(x => intercept + slope * x), yVals); // anything this small can be viewed as flat if (double.IsNaN(slope) || Math.Abs(slope) < 1e-25) return 0m; // trading days per year for us equities const int dayCount = 252; // annualize dy/dt var annualSlope = ((Math.Pow(Math.Exp(slope), dayCount)) - 1) * 100; // scale with rsquared //annualSlope = annualSlope * Math.Pow(rsquared, 2); annualSlope = annualSlope * rsquared; return Convert.ToDecimal(annualSlope); } } }
So this breaks the algorithm:
// trading days per year for us equities const int dayCount = 252; // annualize dy/dt var annualSlope = ((Math.Pow(Math.Exp(slope), dayCount)) - 1) * 100;
Any idea how to avoid this?
Michael Manus
my fault sorry....dont calculate it, try to use the indicator quantconnect built:
Jeremy McNeil
The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.
To unlock posting to the community forums please complete at least 30% of Boot Camp.
You can continue your Boot Camp training progress from the terminal. We hope to see you in the community soon!