Overall Statistics |
Total Trades 0 Average Win 0% Average Loss 0% Compounding Annual Return 0% Drawdown 0% Expectancy 0 Net Profit 0% Sharpe Ratio 0 Loss Rate 0% Win Rate 0% Profit-Loss Ratio 0 Alpha 0 Beta 0 Annual Standard Deviation 0 Annual Variance 0 Information Ratio 0 Tracking Error 0 Treynor Ratio 0 Total Fees $0.00 |
namespace QuantConnect.Algorithm.CSharp { public class HurstAlgorithm : QCAlgorithm { public string symbol = "EURUSD"; RollingWindow<double> LogPrices; RollingWindow<double> LogReturns; public double H; public override void Initialize() { SetStartDate(2010, 01, 10); SetEndDate(DateTime.Now); SetCash(100000); SetWarmup(300); AddSecurity(SecurityType.Forex, symbol, Resolution.Daily); LogPrices = new RollingWindow<double>(30); LogReturns = new RollingWindow<double>(256); } double RoundToNearest(double n, double x) { return Math.Round(n / x) * x; } public void OnData(QuoteBars data) { LogPrices.Add((Convert.ToDouble(data[symbol].Close))); if (!LogPrices.IsReady) return; LogReturns.Add(Math.Log(LogPrices[0]/LogPrices[1])); if (!LogReturns.IsReady) return; if (IsWarmingUp) return; double[] Xs = new double[6]; double[] Ys = new double[6]; Xs[0] = Math.Log(256,2); Xs[1] = Math.Log(128,2); Xs[2] = Math.Log(64,2); Xs[3] = Math.Log(32,2); Xs[4] = Math.Log(16,2); Xs[5] = Math.Log(8,2); Ys[0] = Hurst.ReScaledRange(LogReturns, 1); Ys[1] = Hurst.ReScaledRange(LogReturns, 2); Ys[2] = Hurst.ReScaledRange(LogReturns, 4); Ys[3] = Hurst.ReScaledRange(LogReturns, 8); Ys[4] = Hurst.ReScaledRange(LogReturns, 16); Ys[5] = Hurst.ReScaledRange(LogReturns, 32); double slope; Hurst.LinearRegression(Xs, Ys, 0, 6, out slope); H = slope; Plot("Hurst Exponent", "Exponent" , H); } } }
namespace QuantConnect { public static class Hurst { public static double CalculateStdDev(IEnumerable<double> values) { double ret = 0; if (values.Count() > 0) { double avg = values.Average(); double sum = values.Sum(d => Math.Pow(d - avg, 2)); ret = Math.Sqrt((sum) / (values.Count()-1)); } return ret; } public static void LinearRegression(double[] xVals, double[] yVals, int inclusiveStart, int exclusiveEnd, 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); slope = sCo / ssX; } public static double ReScaledRange(RollingWindow<double> values, int x) { double Ret = 0; double[] RSRange = new double[x]; if (values.Count() > 0) { int value = values.Count()/x; for (int i = 0; i <= x-1; i++) { int y = 0; double[] Section = new double[value]; double[] Core = new double[value]; for (int ii = (value*i); ii <= (value*i)+(value-1); ii++) { Core[y] = values[ii]; Section[y] = values[ii]; if (y > 0){ Section[y] = Section[y-1] + values[ii];} y = y+1; } double Range = Section.Max() - Section.Min(); double StDev = CalculateStdDev(Core); RSRange[i] = Range/StDev; } Ret = Math.Log(RSRange.Average(),2); } return Ret; } } }
using MathNet.Numerics.Integration; namespace QuantConnect { public static class Dist { public static double V(double O, double alpha, double beta) { double O0 = (1/alpha) * Math.Atan(beta * Math.Tan((Math.PI*alpha)/2)); double x1 = Math.Pow(Math.Cos(alpha * O0),(1/(alpha-1))); double x2 = Math.Pow(Math.Cos(O)/(Math.Sin(alpha*(O+O0))),(alpha/(alpha-1))); double x3 = Math.Cos((alpha*O0)+((alpha-1)*O))/Math.Cos(O); return x1*x2*x3; } public static double C1(double alpha, double beta) { double Ret = 0; double O0 = (1/alpha) * Math.Atan(beta * Math.Tan((Math.PI*alpha)/2)); if (alpha < 1) { Ret = (1/Math.PI) * ((Math.PI/2) - O0); } if (alpha == 1) { Ret = 0; } if (alpha > 1) { Ret = 1; } return Ret; } public static double C2(double X, double alpha, double beta) { double Ret = 0; double S = -beta * Math.Tan((Math.PI*alpha)/2); if (alpha != 1) { Ret = alpha / (Math.PI * Math.Abs(alpha-1) * (X-S)); } if (alpha == 1) { Ret = 1 / (2 * Math.Abs(beta)); } return Ret; } public static double C3(double alpha) { double Ret = 0; if (alpha != 1) { Ret = Math.Sign(1-alpha) / Math.PI; } if (alpha == 1) { Ret = 1/Math.PI; } return Ret; } public static double G(double O, double X, double alpha, double beta) { double Ret = 0; double S = -beta * Math.Tan((Math.PI*alpha)/2); if (alpha != 1) { Ret = Math.Pow(X-S, (alpha/(alpha-1))) * V(O, alpha, beta); } if (alpha == 1) { Ret = Math.Exp(-(Math.PI * X)/(2*beta)) * V(O, 1, beta); } return Ret; } public static double F(double X, double alpha, double beta) { double Ret = 0; double O0 = (1/alpha) * Math.Atan(beta * Math.Tan((Math.PI*alpha)/2)); if(!(alpha<=0 || alpha>2 || beta<-1 || beta>1)) { Ret = C1(alpha, beta) + C3(alpha) * NewtonCotesTrapeziumRule.IntegrateAdaptive(x => Math.Exp(-G(x, X, alpha, beta)), -O0, Math.PI/2, 1e-5); } return Ret; } public static double f(double X, double alpha, double beta) { double Ret = 0; double O0 = (1/alpha) * Math.Atan(beta * Math.Tan((Math.PI*alpha)/2)); if(!(alpha<=0 || alpha>2 || beta<-1 || beta>1)) { Ret = C2(X, alpha, beta) * NewtonCotesTrapeziumRule.IntegrateAdaptive(x => G(x, X, alpha, beta) * Math.Exp(-G(x, X, alpha, beta)), -O0, Math.PI/2, 1e-5); } return Ret; } public static double CDF(double X, double alpha, double beta) { double Ret = 0; double S = -beta * Math.Tan((Math.PI*alpha)/2); double O0 = (1/alpha) * Math.Atan(beta * Math.Tan((Math.PI*alpha)/2)); if(X > S) { Ret = F(X, alpha, beta); } if(X == S) { Ret = (1/Math.PI) * ((Math.PI/2)- O0); } if(X < S) { Ret = 1 - F(-X, alpha, -beta); } return Ret; } public static double PDF(double X, double alpha, double beta) { double Ret = 0; double S = -beta * Math.Tan((Math.PI*alpha)/2); double O0 = (1/alpha) * Math.Atan(beta * Math.Tan((Math.PI*alpha)/2)); if(X > S) { Ret = f(X, alpha, beta); } if(X == S) { Ret = 1; //Noooo fucking clue what this says } if(X < S) { Ret = f(-X, alpha, -beta); } return Ret; } } }