protected override void OnStateChange() { if (State == State.SetDefaults) { Description = @"Correlation of Two Instruments"; Name = "Correlation"; Calculate = Calculate.OnBarClose; IsOverlay = false; DisplayInDataBox = true; DrawOnPricePanel = true; DrawHorizontalGridLines = true; DrawVerticalGridLines = true; PaintPriceMarkers = true; ScaleJustification = NinjaTrader.Gui.Chart.ScaleJustification.Right; //Disable this property if your indicator requires custom values that cumulate with each new market data event. //See Help Guide for additional information. IsSuspendedWhileInactive = true; //Symbol2 = string.Empty; Period = 100; PeriodPctChange = 1; AddPlot(Brushes.CornflowerBlue, "Name"); } else if (State == State.Configure) { AddDataSeries("CL 01-18", BarsPeriodType.Day, 1); //AddDataSeries("CL 01-18", new BarsPeriod { BarsPeriodType = BarsPeriodType.Minute, Value = 1440 }, "Default 24 x 7"); } else if (State == State.DataLoaded) { Instrument2BIPClose = new SyncedDataSeries(this, Instrument1BIP, Instrument2BIP, Closes[Instrument2BIP]); } }
private double SyncedRankCorrelation(PriceSeries inputSeries1, SyncedDataSeries inputSeries2, int corrPeriod) // SyncedRankCorrelation: Calculate the Spearman Rank Correlation of 2 Data Series, using only the bars which are synchronized // // Inputs: // inputSeries1: 1st DataSeries, typically Closes[x] // inputSeries2: SyncedDataSeries, synced to InputSeries1; some bars (flagged by BoolSeries "Synced") hold valid (synchronized) values // corrPeriod: Period for Correlation calculation; there must be >= CorrPeriod synced bars in the input series, or it will throw an exception // { int index1 = 0; double[] dataArray1 = new double[corrPeriod]; double[] dataArray2 = new double[corrPeriod]; for (int counter = corrPeriod - 1; counter >= 0; counter--) { while (!inputSeries2.Synced[index1]) //Find next synced Bar { index1++; } dataArray1[counter] = inputSeries1[index1]; dataArray2[counter] = inputSeries2[index1]; index1++; } return(KDRankCorrelation(dataArray1, dataArray2, corrPeriod)); }
private double SyncedPctChangeCorrelation(PriceSeries inputSeries1, SyncedDataSeries inputSeries2, int corrPeriod, int changeLookback) { int index = 0; double[] pctChangeArray1 = new double[corrPeriod]; double[] pctChangeArray2 = new double[corrPeriod]; while (!inputSeries2.Synced[index]) //Find most recent synced Bar { index++; } double val1 = inputSeries1[index]; double val2 = inputSeries2[index]; index++; for (int counter = corrPeriod - 1; counter >= 0; counter--) { int changeIndex; while (!inputSeries2.Synced[index]) //Find previous synced Bar { index++; } double chg2 = inputSeries2.SyncedGet(changeLookback - 1, index, out changeIndex); // this will scan back more synced bars if changeLookback > 0 double chg1 = inputSeries1[changeIndex]; pctChangeArray1[counter] = (val1 - chg1) / chg1; pctChangeArray2[counter] = (val2 - chg2) / chg2; val1 = inputSeries1[index]; val2 = inputSeries2[index]; index++; } // return(KDRankCorrelation(pctChangeArray1,pctChangeArray2,corrPeriod)); // maybe rank correlation of PctChange would be better? return(KDCorrelation(pctChangeArray1, pctChangeArray2, corrPeriod)); }
private double SyncedCorrelation(PriceSeries inputSeries1, SyncedDataSeries inputSeries2, int corrPeriod) // SyncedCorrelation: Calculates the Pearson Product Moment Correlation of 2 Data Series, using only the bars which are synchronized // Note: Correlations may differ from Excel if NinjaTrader is set to dividend-adjust historical prices // // Inputs: // inputSeries1: 1st DataSeries, typically Closes[x] // inputSeries2: SyncedDataSeries, synced to InputSeries1; some bars (flagged by BoolSeries "Synced") hold valid (synchronized) values // corrPeriod: Period for Correlation calculation; there must be >= CorrPeriod synced bars in the input series, or it will throw an exception // { double sum1 = 0; double sum2 = 0; double sum3 = 0; int index1 = 0; double mean1, mean2, variance1, variance2, denominator; mean1 = SyncedSMA(inputSeries1, inputSeries2.Synced, corrPeriod); mean2 = SyncedSMA(inputSeries2, inputSeries2.Synced, corrPeriod); for (int counter = 0; counter < corrPeriod; counter++) { while (!inputSeries2.Synced[index1]) //Find next synced Bar { index1++; } variance1 = inputSeries1[index1] - mean1; variance2 = inputSeries2[index1] - mean2; sum1 += variance1 * variance2; sum2 += variance1 * variance1; sum3 += variance2 * variance2; index1++; } denominator = Math.Sqrt(sum2 * sum3); if (denominator == 0) { return(0); // avoid divide-by-zero error; not really the correct result (actual correlation is undefined) } else { return(sum1 / denominator); } }
private double SyncedResidualCorrelation(PriceSeries inputSeries1, SyncedDataSeries inputSeries2, int corrPeriod) // Correlation of residuals (residual = error = difference between actual values and linear regression line) { int index1 = 0; double[] residualArray1 = new double[corrPeriod]; double[] residualArray2 = new double[corrPeriod]; double[] dataArray1 = new double[corrPeriod]; double[] dataArray2 = new double[corrPeriod]; for (int counter = corrPeriod - 1; counter >= 0; counter--) { while (!inputSeries2.Synced[index1]) //Find next synced Bar { index1++; } dataArray1[counter] = inputSeries1[index1]; dataArray2[counter] = inputSeries2[index1]; index1++; } KDResidual(dataArray1, corrPeriod, residualArray1); KDResidual(dataArray2, corrPeriod, residualArray2); // return(KDRankCorrelation(residualArray1,residualArray2,corrPeriod)); // maybe rank correlation of residuals would be better? return(KDCorrelation(residualArray1, residualArray2, corrPeriod)); }