Tail Ratio in Explorer

@TrendNeutral

I read this paper and took a stab at replicating the process for a few of the strategies I subscribe to. I think it’s very interesting but I’m wondering if the claim that it has predictive power with regards to strategy returns is really valid. The underlying premise is that strategy returns should be normally distributed about some average but I’m not sure that’s true. Market returns and by extension I would assume strategy returns are usually non-normal and fat-tailed. Trend following strategies would have right-skewed returns so they might bust the UCL regularly and mean reversion strategies will take the occasional large loss and bust the LCL. Even though these are inherent features of these strategy types, SPC would tell you they are unstable and should be abandoned.

Thoughts?

1 Like

spot on…

1 Like

Hi guys!

I am experimenting wit Accord: http://accord-framework.net/

This is what I have for now: ShapiroWilkTest and TTest.

But my statistics knowledge are limited. So please tell me exactly what to do.

Thanks.

	public object Run(double hypothesizedMean)
	{
		foreach (long systemId in systems)
		{
			Series<DateTime, Double> returns = timesheet.GetColumnAsDouble(systemId, EquityType.Rets);

			// --------------------------------------------------------------
			// All data 
			// --------------------------------------------------------------

			double[] allData = returns.Values.ToArray();

			Debug.WriteLine($"-------- SystemId = {systemId}, HypothesizedMean = {hypothesizedMean}, all data - {allData.Length} datapoints-------------");

			// --------------------------------------------------------------
			// Let's try a normality test
			// --------------------------------------------------------------
			ShapiroWilkTest shapiroWilkTest_AllData = new ShapiroWilkTest(allData);

			Debug.WriteLine(
				$"Strategy {systemId}: shapiroWilkTest_AllData: PValue = {shapiroWilkTest_AllData.PValue} " +
				$" The null hypothesis 'sample came from a normally distributed population' should be rejected: {shapiroWilkTest_AllData.Significant.ToString().ToUpper()}");

			// --------------------------------------------------------------
			// TTest
			// --------------------------------------------------------------
			TTest tt_all_data = new TTest(allData, hypothesizedMean, OneSampleHypothesis.ValueIsDifferentFromHypothesis);

			Debug.WriteLine($"Strategy {systemId}: TTest - all data: hypothesizedMean = {hypothesizedMean} PValue = {tt_all_data.PValue} Significant = {tt_all_data.Significant}");

			// ==============================================================
			// Non-zero data only
			// ==============================================================
			double[] nonZeroData = returns.Values.Where(x => Math.Abs(x) > 1E-6).ToArray();

			Debug.WriteLine($"-------- SystemId = {systemId}, HypothesizedMean = {hypothesizedMean}, non-zero data - {nonZeroData.Length} datapoints -------------");

			// --------------------------------------------------------------
			// Lets try a normality test
			// --------------------------------------------------------------
			ShapiroWilkTest shapiroWilkTest_nonZeroData = new ShapiroWilkTest(nonZeroData);

			Debug.WriteLine(
				$"Strategy {systemId}: shapiroWilkTest_nonZeroData: PValue = {shapiroWilkTest_nonZeroData.PValue} " +
				$" The null hypothesis 'sample came from a normally distributed population' should be rejected: {shapiroWilkTest_nonZeroData.Significant.ToString().ToUpper()}");

			// --------------------------------------------------------------
			// TTest
			// --------------------------------------------------------------
			TTest tt_non_zero_data = new TTest(nonZeroData, hypothesizedMean, OneSampleHypothesis.ValueIsDifferentFromHypothesis);
			Debug.WriteLine($"Strategy {systemId}: TTest - non-zero data: hypothesizedMean = {hypothesizedMean} PValue = {tt_non_zero_data.PValue} Significant = {tt_non_zero_data.Significant}");

		}

		return null; // return nothing for now
	}
}

Results:

-------- SystemId = 84372841, HypothesizedMean = 0, all data - 2067 datapoints-------------
Strategy 84372841: shapiroWilkTest_AllData: PValue = 7.17465290505463E-53 The null hypothesis ‘sample came from a normally distributed population’ should be rejected: TRUE
Strategy 84372841: TTest - all data: hypothesizedMean = 0 PValue = 0.0159801171634086 Significant = True

-------- SystemId = 84372841, HypothesizedMean = 0, non-zero data - 1073 datapoints -------------
Strategy 84372841: shapiroWilkTest_nonZeroData: PValue = 6.06904288872399E-29 The null hypothesis ‘sample came from a normally distributed population’ should be rejected: TRUE
Strategy 84372841: TTest - non-zero data: hypothesizedMean = 0 PValue = 0.0159468184756832 Significant = True

-------- SystemId = 75800796, HypothesizedMean = 0, all data - 2067 datapoints-------------
Strategy 75800796: shapiroWilkTest_AllData: PValue = 2.0954101771429E-40 The null hypothesis ‘sample came from a normally distributed population’ should be rejected: TRUE
Strategy 75800796: TTest - all data: hypothesizedMean = 0 PValue = 0.00302050931792452 Significant = True

-------- SystemId = 75800796, HypothesizedMean = 0, non-zero data - 1511 datapoints -------------
Strategy 75800796: shapiroWilkTest_nonZeroData: PValue = 3.73291914931055E-26 The null hypothesis ‘sample came from a normally distributed population’ should be rejected: TRUE
Strategy 75800796: TTest - non-zero data: hypothesizedMean = 0 PValue = 0.00301297568152137 Significant = True

===================================================================================

-------- SystemId = 84372841, HypothesizedMean = 10, all data - 2067 datapoints-------------
Strategy 84372841: shapiroWilkTest_AllData: PValue = 7.17465290505463E-53 The null hypothesis ‘sample came from a normally distributed population’ should be rejected: TRUE
Strategy 84372841: TTest - all data: hypothesizedMean = 10 PValue = 2.22044604925031E-16 Significant = True

-------- SystemId = 84372841, HypothesizedMean = 10, non-zero data - 1073 datapoints -------------
Strategy 84372841: shapiroWilkTest_nonZeroData: PValue = 6.06904288872399E-29 The null hypothesis ‘sample came from a normally distributed population’ should be rejected: TRUE
Strategy 84372841: TTest - non-zero data: hypothesizedMean = 10 PValue = 2.22044604925031E-16 Significant = True

-------- SystemId = 75800796, HypothesizedMean = 10, all data - 2067 datapoints-------------
Strategy 75800796: shapiroWilkTest_AllData: PValue = 2.0954101771429E-40 The null hypothesis ‘sample came from a normally distributed population’ should be rejected: TRUE
Strategy 75800796: TTest - all data: hypothesizedMean = 10 PValue = 2.22044604925031E-16 Significant = True

-------- SystemId = 75800796, HypothesizedMean = 10, non-zero data - 1511 datapoints -------------
Strategy 75800796: shapiroWilkTest_nonZeroData: PValue = 3.73291914931055E-26 The null hypothesis ‘sample came from a normally distributed population’ should be rejected: TRUE
Strategy 75800796: TTest - non-zero data: hypothesizedMean = 10 PValue = 2.22044604925031E-16 Significant = True

==============================

The above code would be converted to something like this in C2Explorer:

long[] systems = new long[] { 84372841, 75800796 };
StatisticsTesting statisticsTesting = new StatisticsTesting(db, systems);
TABLE = statisticsTesting.Run(0.0);
TABLE = statisticsTesting.Run(10.0);

I forgot to mention that Accord is not yet in C2Explorer. I am trying it just on my desktop.

1 Like

I think analyzing strategy performance like this might give you a nice visual of how erratic or not the returns are, and some investors might prefer strategies that have return series that look cleaner than ones that are erratic, but I’m not convinced one can use SPC to determine with any certainty that a strategy is about to break down.

Hi @BobSvan2 , I would use this test:
http://accord-framework.net/docs/html/T_Accord_Statistics_Testing_TTest.htm
To test whether the mean of the daily returns in statistically significant at various levels of confidecne (eg 95%, 99%)

Some more background here:

I agree with QFund and Philipp.
I we can’t get meaningful results if we do not have data complying t-test assumptions.

1 Like

Hi @BobSvan2 I believe the following stats covers already t tests. Within the stats of a system we can read “Lowerbound of 95% confidence interval for Sharpe Ratio”. Can we extract this value for a bunch on systems in Exclorer?