private void CalculateSumDistribution(double sigma, PointF[] dens, out double sg1Opt, out double sg2Opt, out double kOpt) { const double mMin = 0.15, mMax = 0.85d, mStep = 0.1; const double kMin = 0.2, kMax = 0.8, kStep = 0.05; const double kSigmMin = 0.1, kSigmMax = 5.0, kSigmStep = 0.05; double?rss = null; sg1Opt = 0; sg2Opt = 0; kOpt = 0; // посчитать F, вычисляя разность квадратов for (var kSigm = kSigmMin; kSigm <= kSigmMax; kSigm += kSigmStep) { for (var k = kMin; k <= kMax; k += kStep) { for (var m = mMin; m < mMax; m += mStep) { var sg2 = sigma * kSigm / (1 + m); var sg1 = sg2 * m; var curRss = 0d; float[] testSynthFunc = null; if (StoreFunction) { testSynthFunc = new float[dens.Length]; } for (var i = 0; i < dens.Length; i++) { var x = dens[i].X; var f = (k * ProbabilityCore.Erf(x / (ProbabilityCore.R2 * sg1)) + (1 - k) * ProbabilityCore.Erf(x / (ProbabilityCore.R2 * sg2))) * 0.5 + 0.5; var delta = f - dens[i].Y; delta = delta * delta; curRss += delta; if (StoreFunction) { testSynthFunc[i] = (float)f; } } if (!rss.HasValue || rss > curRss) { rss = curRss; kOpt = k; sg1Opt = sg1; sg2Opt = sg2; synthFunc = testSynthFunc; } } } } }
private void CalculateSumDistribution(double sigma, PointF[] dens, out double sg1Opt, out double sg2Opt, out double kOpt) { const double mMin = 0.25, mMax = 0.75d, mStep = 0.1; const double kMin = 0.5, kMax = 0.8, kStep = 0.05; const double kSigmMin = 0.8, kSigmMax = 2.0, kSigmStep = 0.05; double?rss = null; sg1Opt = 0; sg2Opt = 0; kOpt = 0; var timeStart = DateTime.Now; // посчитать F, вычисляя разность квадратов for (var kSigm = kSigmMin; kSigm <= kSigmMax; kSigm += kSigmStep) { for (var k = kMin; k <= kMax; k += kStep) { for (var m = mMin; m < mMax; m += mStep) { var sg2 = sigma * kSigm / (1 + m); var sg1 = sg2 * m; var curRss = 0d; var densResulted = new PointF[dens.Length]; for (var i = 0; i < dens.Length; i++) { var x = dens[i].X; var f = k * ProbabilityCore.Erf(x / (ProbabilityCore.R2 * sg1)) + (1 - k) * ProbabilityCore.Erf(x / (ProbabilityCore.R2 * sg2)); var delta = f - dens[i].Y; delta = delta * delta; curRss += delta; densResulted[i] = new PointF(x, (float)f); } if (!rss.HasValue || rss > curRss) { rss = curRss; kOpt = k; sg1Opt = sg1; sg2Opt = sg2; densSum = densResulted; } } } } //var deltaMils = (DateTime.Now - timeStart).TotalMilliseconds; }
private void CalculateQuoteDistribution(int intervals, int minutesDelta) { if (candles == null || candles.Count < 1000) { return; } // перевести свечи в массив длин OC float[] lengths; if (minutesDelta == 1) { lengths = candles.Select(c => Math.Abs(c.close - c.open)).OrderBy(d => d).ToArray(); } else { var listLen = new List <float>(); CandleData prev = null; foreach (var candle in candles) { if (prev != null) { if ((candle.timeOpen - prev.timeOpen).TotalMinutes < minutesDelta) { continue; } var delta = Math.Abs(candle.close - prev.close); listLen.Add(delta); prev = candle; } else { prev = candle; } } lengths = listLen.OrderBy(d => d).ToArray(); } // посчитать интегральную функцию распределения вероятности длина тела свечи / N свечей dens = MakeDistributionCurve(lengths, intervals); // получить оценку согласно "нормальному" закону densMath = new PointF[dens.Length]; var sigma = Math.Sqrt(lengths.Sum(l => l * l) / lengths.Length); for (var i = 0; i < dens.Length; i++) { var x = dens[i].X; var y = 1 * ProbabilityCore.Erf(x / (ProbabilityCore.R2 * sigma)); // P за вычетом 0.5 densMath[i] = new PointF(x, (float)y); } // получить параметры 2-х норм. распределений, дающих в сумме исходное double sg1, sg2, k; CalculateSumDistribution(sigma, dens, out sg1, out sg2, out k); DrawChart(); // сохранить данные в Excel var dlg = new SaveFileDialog { Title = "Сохранить файл", DefaultExt = "csv", Filter = "All Files (*.*)|*.*|CSV (*.csv)|*.csv" }; if (dlg.ShowDialog() != DialogResult.OK) { return; } using (var fs = new StreamWriter(dlg.FileName, false, Encoding.UTF8)) { fs.WriteLine("Sigma;{0}", sigma.ToStringUniform()); for (var i = 0; i < dens.Length; i++) { fs.WriteLine("{0},{1},{2},{3}", i, dens[i].X.ToStringUniform(5), dens[i].Y.ToStringUniform(5), densMath[i].Y.ToStringUniform(5)); } } }
private void BtnCalculateClick(object sender, EventArgs e) { var candles = chart.chart.StockSeries.Data.Candles; if (candles.Count == 0) { return; } var curPrice = candles[candles.Count - 1].close; // посчитать дельта цену и дельта время var targetPrice = tbPrice.Text.ToDoubleUniform(); var side = cbSide.SelectedIndex == 0 ? -1 : 1; var logPrice = Math.Log(targetPrice / curPrice) * side; var deltaTime = (int)Math.Round((dtEnd.Value - DateTime.Now).TotalMinutes); // получить эмпирическую функцию распределения const int funcIntervalsCount = 100; var nSteps = 1d; const int longestInterval = 1440; if (deltaTime > longestInterval) { var delta = longestInterval / 2; nSteps = (double)deltaTime / delta; deltaTime = delta; } var lengths = GetTargetCandlesLengths(deltaTime); lengths.Sort(); var func = MakeDistributionCurve(lengths, funcIntervalsCount); // получить параметры 2-х СВ (нормально распределенных), // в сумме дающих приближение к эмпирической F var avgLen = lengths.Average(); var sigma = Math.Sqrt(lengths.Sum(l => (l - avgLen) * (l - avgLen)) / lengths.Count); double sigm1, sigm2, k; CalculateSumDistribution(sigma, func, out sigm1, out sigm2, out k); // посчитать вреоятность var x = logPrice; var scale = nSteps == 1 ? 1 : Math.Sqrt(nSteps); var f = k * ProbabilityCore.Erf(x / (ProbabilityCore.R2 * sigm1 * scale)) + (1 - k) * ProbabilityCore.Erf(x / (ProbabilityCore.R2 * sigm2 * scale)); f = f * 0.5 + 0.5; var p = 1 - f; tbResult.Text = (p * 100).ToStringUniform(2) + "%"; if (!StoreFunction) { return; } // вывести в Excel synthFunc var dlg = new SaveFileDialog { Title = "Сохранить таблицы", DefaultExt = "csv", Filter = "*.csv|*.csv|*.*|*.*", FilterIndex = 0 }; if (dlg.ShowDialog() != DialogResult.OK) { return; } using (var sw = new StreamWriter(dlg.FileName, false, Encoding.ASCII)) { sw.WriteLine("delta(X);F;F synth"); for (var i = 0; i < func.Count(); i++) { sw.WriteLine("{0};{1};{2}", func[i].X.ToStringUniform(5), func[i].Y.ToStringUniform(4), synthFunc[i].ToStringUniform(4)); } } }