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;
		}
    }
}