public override void Calculate(int index) { if (barTime == M1.OpenTime.LastValue) { return; } barTime = MarketSeries.OpenTime.LastValue; int prev = M1.OpenTime.GetIndexByExactTime(MarketSeries.OpenTime.Last(1)); int next = M1.OpenTime.GetIndexByExactTime(barTime); if (prev == -1 || next == -1) { return; } RunningStats tempStats = new RunningStats(); for (int i = prev; i < next; i++) { tempStats.Push(M1.Close[i]); } htfStats = htfStats + tempStats; tempStats = null; //上位の時間足の更新と重なったとき int newIndexHtf = HTF.OpenTime.GetIndexByTime(barTime); if (prevIndexHtf != newIndexHtf) { StatsQ.Enqueue(new RunningStats((long)htfStats.n, htfStats.M1, htfStats.M2, htfStats.M3, htfStats.M4)); if (StatsQ.Count > Period) { while (StatsQ.Count > Period) { StatsQ.Dequeue(); } RunningStats totalStats = new RunningStats(); foreach (RunningStats stats in StatsQ) { totalStats = totalStats + stats; } double ma = totalStats.Mean(); double sd = totalStats.StdDev(); double skew = totalStats.Skewness(); double kurt = totalStats.Kurtosis(); totalStats = null; for (int j = prevIndex; j < index; j++) { MA[j] = ma; UPPER[j] = ma + sd * Variance; LOWER[j] = ma - sd * Variance; } } prevIndex = index; prevIndexHtf = newIndexHtf; htfStats.Clear(); } }
protected override void Initialize() { StatsQ = new Queue <RunningStats>(); //--- prevIndex = -1; prevIndexHtf = -1; barTime = new DateTime(0); HTF = MarketData.GetSeries(TF); M1 = MarketData.GetSeries(TimeFrame.Minute); htfStats = new RunningStats(); }
public static RunningStats operator +(RunningStats a, RunningStats b) { // RunningStats combined = new RunningStats(); combined.n = a.n + b.n; double delta = b.M1 - a.M1; double delta2 = delta * delta; double delta3 = delta * delta2; double delta4 = delta2 * delta2; combined.M1 = (a.n * a.M1 + b.n * b.M1) / combined.n; combined.M2 = a.M2 + b.M2 + delta2 * a.n * b.n / combined.n; combined.M3 = a.M3 + b.M3 + delta3 * a.n * b.n * (a.n - b.n) / (combined.n * combined.n); combined.M3 += 3.0 * delta * (a.n * b.M2 - b.n * a.M2) / combined.n; combined.M4 = a.M4 + b.M4 + delta4 * a.n * b.n * (a.n * a.n - a.n * b.n + b.n * b.n) / (combined.n * combined.n * combined.n); combined.M4 += 6.0 * delta2 * (a.n * a.n * b.M2 + b.n * b.n * a.M2) / (combined.n * combined.n) + 4.0 * delta * (a.n * b.M3 - b.n * a.M3) / combined.n; return(combined); }
public override void Calculate(int index) { LVL0[index] = 0; if (barTime == M1.OpenTime.LastValue) { return; } barTime = MarketSeries.OpenTime.LastValue; // 1分のバーインデックスを取得する。 // GetIndexByExactTime(時間) は、時刻からバーインデックスを取得する関数。 int prev = M1.OpenTime.GetIndexByExactTime(MarketSeries.OpenTime.Last(1)); int next = M1.OpenTime.GetIndexByExactTime(barTime); if (prev == -1 || next == -1) { return; } // RunningStatsクラスは、平均、偏差平方和、偏差三乗和、偏差四乗和を計算し、 // 標準偏差、歪度、尖度を計算するクラス。また、計算結果のマージも行える。 RunningStats tempStats = new RunningStats(); // 1分足データの統計情報をオンラインで計算する。 for (int i = prev; i < next; i++) { tempStats.Push(M1.Close[i]); } // 上位足の計算結果とマージする。 htfStats = htfStats + tempStats; tempStats = null; //上位の時間足の更新と重なったとき int newIndexHtf = HTF.OpenTime.GetIndexByTime(barTime); if (prevIndexHtf != newIndexHtf) { // 上位足の計算結果をリングバッファに追加する。 StatsQ.Enqueue(new RunningStats((long)htfStats.n, htfStats.M1, htfStats.M2, htfStats.M3, htfStats.M4)); // 指定期間以上バッファがたまったら、 if (StatsQ.Count > Period) { while (StatsQ.Count > Period) { StatsQ.Dequeue(); } // 合計用のRunningStatsクラスを用意。 RunningStats totalStats = new RunningStats(); // 上位足指定期間分の計算結果をマージする。 foreach (RunningStats stats in StatsQ) { totalStats = totalStats + stats; } //上位足指定期間分の統計情報を求める。 double ma = totalStats.Mean(); //平均 double sd = totalStats.StdDev(); //標準偏差 double skew = totalStats.Skewness(); //歪度 double kurt = totalStats.Kurtosis(); //尖度 totalStats = null; for (int j = prevIndex; j < index; j++) { SKEW[j] = skew; KURT[j] = kurt; } } prevIndex = index; prevIndexHtf = newIndexHtf; htfStats.Clear(); } }