The opinions expressed in these forums do not represent those of C2, and any discussion of profit/loss is not indicative of future performance or success. There is a substantial risk of loss in trading. You should therefore carefully consider whether such trading is suitable for you in light of your financial condition. You should read, understand, and consider the Risk Disclosure Statement that is provided by your broker before you consider trading. Most people who trade lose money.

# Tail Ratio in Explorer

#1

@BobSvan2 is it possible to have a code that would allow to calculate the Tail Ratio for a bunch of systems?

https://www.quora.com/What-is-a-tail-ratio-in-a-finance-or-statistical-context

So:
calculate tail ratio = 95 pecentile / 5 percentile

Thanks!

#2

Hello!

Perhaps this code:

``````
/*
Disclaimer:
The systems used in this example were selected randomly.
Data shown in this example can contain errors.
*/

Int64[] systems = new Int64[] {
46106678, // Bob Dylan
90325773, // Ascendatnt
84690231 // Genefish Hong Kong
};

// Create a TimeSheet object. Define desired data.
ITimeSheet timeSheet = TimeSheetFactory(systems, TimeInterval.Day, EquityType.Rets);

// Let TimeSheet run
timeSheet.EquitiesSheet();

foreach (var systemId in systems)
{
Series<DateTime, Double> returnsColumn = timeSheet.GetColumnAsDouble(systemId, EquityType.Rets);
double percentile5 = Statistics.Percentile(returnsColumn.Values, 5);
double percentile95 = Statistics.Percentile(returnsColumn.Values, 95);
if (percentile5 == 0.0)
{
TEXT = systemId.ToString() + ": TailRatio does not exist.";
}
else
{
double tailRatio = percentile95 / Math.Abs(percentile5);
TEXT = String.Format(
"System {0}:   p5 = {1:N4}   p95 = {2:N4}   ratio = {3:N2}",
systemId, percentile5, percentile95, tailRatio);
}
}

H3 = "Daily returns visualized";
TABLE = GetEquitiesSheet(systems, TimeInterval.Day, EquityType.Rets);

``````

Enjoy!

#3

The above code gives wrong answers if you run multiple systems at once. It uses a timeSheet merged for all systems and that makes inaccurate daily returns percentiles for systems that havenâ€™t traded the whole time period.

If you run the code as-is with 3 systems it calculates the following:
System 46106678: p5 = -1.0250 p95 = 1.6450 ratio = 1.60
System 90325773: p5 = -1.3825 p95 = 1.9025 ratio = 1.38
System 84690231: p5 = -0.9100 p95 = 1.1275 ratio = 1.24

Running the systems one at a time calculates different values for the two systems that havenâ€™t traded as long as the first:
System 46106678: p5 = -1.0250 p95 = 1.6450 ratio = 1.60
System 90325773: p5 = -6.5015 p95 = 6.5970 ratio = 1.01
System 84690231: p5 = -2.4960 p95 = 2.5560 ratio = 1.02

#4

Thanks.

``````    timeSheet.EquitiesSheet();
``````

to

``````    timeSheet.EquitiesSheet(fillLeadingMissing : false);
``````

This eliminates â€śnon commonâ€ť bars from the beginning.

I suppose all systems are live in C2Explorer.
So they should have common bars at the end of the time sheet.
If not, we need other solution.

#5

Thanks it seems to work. For the calculation of the pecentiles do we use for each system on from when the system goes life? Otherwise we would compute a lot of 0 prior to system go liveâ€¦

#6

OK. Letâ€™s do it as good as we can.

The reason for TimeSheet usage is, that it calculates returns data for every day and fills eventual gaps.
TimeSheet is used separately (one system in TimeSheet only) for each system in the following code:

``````// Your systems selection.
// For example - last week most popular systems.
var popularLastWeek = from stat in C2STATS
where stat.StatName == "popular10080"
orderby stat.StatValueVal descending
select stat.SystemId;

// Get 10 most popular systems Ids
Int64[] systems = popularLastWeek.Take(10).ToArray();

// A list for results.
List<object> result = new List<object>();

// And something for fun.
IColumnChart chart = new ColumnChart("Tail Ratio - last week most popular systems", "Systems", "Tail Ratio");

foreach (var systemId in systems)
{
// Get a system for Name, Started date, ...

// Create a TimeSheet object. It calculates daily returns.
ITimeSheet timeSheet = TimeSheetFactory(systemId, TimeInterval.Day, EquityType.Rets);

// Let TimeSheet run for this system.
timeSheet.EquitiesSheet();

// Get the Returns column for statistics.
Series<DateTime, Double> returnsColumn = timeSheet.GetColumnAsDouble(systemId, EquityType.Rets);

// Percentiles
double percentile5 = Statistics.Percentile(returnsColumn.Values, 5);
double percentile95 = Statistics.Percentile(returnsColumn.Values, 95);

double tailRatio = 0.0;
if (percentile5 != 0.0)
{
// Calculate Tail Ratio
tailRatio = percentile95 / Math.Abs(percentile5);

// Prepare data for output
object trdata = new
{
Name = system.Name,
Id = system.Id,
Started = system.Started,
Percentile5 = Math.Round((decimal)percentile5, 4),
Percentile95 = Math.Round((decimal)percentile95, 4),
TailRatio = Math.Round((decimal)tailRatio, 2)
};

// Add to the results list
}
}

CHART = chart;

HR();

H3 = "Tail Ratio - last week most popular systems";
TABLE = result;

// H3 = "Daily returns visualized";
// TABLE = GetEquitiesSheet(systems, TimeInterval.Day, EquityType.Rets);
``````

#7

Great work! would it be too much to ask to add to the column tables other key stats such as:

• number of days
• % win
• avg win
• avg loss
• Sharpe
• APD

#8

@BobSvan2 just making sure you can see the above post. It would also be great to select all live systems with at least 180 days history. Basically we should just put the Tail Ratio in the grid

#9

Hello!

All fields from the `C2ExplorerDB.c2ex_publicsystems` database table are accessible from the IC2TradingSystem interface now.

A documentation is not yet updated - a list of fields is here:
See https://collective2.com/c2explorer_help/html/T_C2ExplorerDB_c2ex_publicsystems.htm

It means you can modify the Tail Ratio code like this (for example):

``````    object trdata = new
{
Name = system.Name,
Id = system.Id,
Started = system.Started,
Percentile5 = Math.Round((decimal)percentile5, 4),
Percentile95 = Math.Round((decimal)percentile95, 4),
TailRatio = Math.Round((decimal)tailRatio, 2),

// --------------- New fields -------------
AvgWin = system.AvgWin,
AvgLoss = system.AvgLoss,
WinPercent = (decimal)Math.Round((double)system.NumWins / (double)system.NumTrades , 4) * 100
};
``````

Other info (Sharpe,â€¦) is not so easy and need to be added from the database.

Here is an example how to get Sharpe:

``````TABLE = from item in C2STATS
where systems.Contains(item.SystemId)
where item.StatName == "jSharpe"
select item;
``````

Based on this example, you can add the following code:

`````` // Get Sharpe
var sharpe = (from item in C2STATS
where item.SystemId == system.Id
where item.StatName == "jSharpe"
select item.StatValueVal).FirstOrDefault();
``````

and use the result in `object trdata = new { ... }`

Here is a new code with those modifications:

``````// Your systems selection.
// For example - last week most popular systems.
var popularLastWeek = from stat in C2STATS
where stat.StatName == "popular10080"
orderby stat.StatValueVal descending
select stat.SystemId;

// Get 10 most popular systems Ids
Int64[] systems = popularLastWeek.Take(10).ToArray();

// A list for results.
List<object> result = new List<object>();

// And something for fun.
IColumnChart chart = new ColumnChart("Tail Ratio - last week most popular systems", "Systems", "Tail Ratio");

foreach (var systemId in systems)
{
// Get a system for Name, Started date, ...

// Create a TimeSheet object. It calculates daily returns.
ITimeSheet timeSheet = TimeSheetFactory(systemId, TimeInterval.Day, EquityType.Rets);

// Let TimeSheet run for this system.
timeSheet.EquitiesSheet();

// Get the Returns column for statistics.
Series<DateTime, Double> returnsColumn = timeSheet.GetColumnAsDouble(systemId, EquityType.Rets);

// Percentiles
double percentile5 = Statistics.Percentile(returnsColumn.Values, 5);
double percentile95 = Statistics.Percentile(returnsColumn.Values, 95);

double tailRatio = 0.0;
if (percentile5 != 0.0)
{
// Calculate Tail Ratio
tailRatio = percentile95 / Math.Abs(percentile5);

// Get Sharpe
var sharpe = (from item in C2STATS
where item.SystemId == system.Id
where item.StatName == "jSharpe"
select item.StatValueVal).FirstOrDefault();

// Prepare data for output
object trdata = new
{
Name = system.Name,
Id = system.Id,
Started = system.Started,
Percentile5 = Math.Round((decimal)percentile5, 4),
Percentile95 = Math.Round((decimal)percentile95, 4),
TailRatio = Math.Round((decimal)tailRatio, 2),
AvgWin = system.AvgWin,
AvgLoss = system.AvgLoss,
WinPercent = (decimal)Math.Round((double)system.NumWins / (double)system.NumTrades , 4) * 100,
Sharpe = (decimal)sharpe
};

// Add to the results list
}
}

CHART = chart;

HR();

H3 = "Tail Ratio - last week most popular systems";
TABLE = result;

// H3 = "Daily returns visualized";
// TABLE = GetEquitiesSheet(systems, TimeInterval.Day, EquityType.Rets);
``````

#10

C2Explorer includes all live systems.

#11

@BobSvan2 thanks so much! what if we wanted to compute all live systems, not just the most popular?

#12

Too much data.
There are 25746 systems there right now.
You will end with timeout.

#13

What is the StatName for
b (slope, estimate of beta)
and
a (intercept, estimate of alpha)
calculated with daily values, full history?

#14

Hi Bob, could you tell me why the Tail Ratio code doesnt work on this system: 81877382 ?

/*
Disclaimer:
The systems used in this example were selected randomly.
Data shown in this example can contain errors.
*/

Int64[] systems = new Int64[] {
81877382

};

// Create a TimeSheet object. Define desired data.
ITimeSheet timeSheet = TimeSheetFactory(systems, TimeInterval.Day, EquityType.Rets);

// Let TimeSheet run

foreach (var systemId in systems)
{
Series<DateTime, Double> returnsColumn = timeSheet.GetColumnAsDouble(systemId, EquityType.Rets);
double percentile5 = Statistics.Percentile(returnsColumn.Values, 5);
double percentile95 = Statistics.Percentile(returnsColumn.Values, 95);
if (percentile5 == 0.0)
{
TEXT = systemId.ToString() + â€ś: TailRatio does not exist.â€ť;
}
else
{
double tailRatio = percentile95 / Math.Abs(percentile5);
TEXT = String.Format(
â€śSystem {0}: p5 = {1:N4} p95 = {2:N4} ratio = {3:N2}â€ť,
systemId, percentile5, percentile95, tailRatio);
}
}

H3 = â€śDaily returns visualizedâ€ť;
TABLE = GetEquitiesSheet(systems, TimeInterval.Day, EquityType.Rets);

#15

Hi guys have you considered adding SPC (statistical process control) code to Explorer?

Pls look at this paper:

SPC has predictive value on future returns. Below I manually used the average 5day returns for system XLN.

Excel example for XLN

It would be great to have a code that can map these control charts based on daily % returnsâ€¦

#16

It works now.

Thanks.

#17

@BobSvan2 @MatthewKlein
Hi guys another useful way of using the daily returns from tail ratio explorer is to apply hypothesis testing on past daily returns and test the hypothesis of whether future returns will be below or above 0. Statistics with T test can be used for this. The formualae are pretty simple , it would be great to implement this test in Explorer for a bunch of systemsâ€¦ See my excel attached!

T test example

#18

Hello TrendNeutral!

Well, it looks like a not easy research task. I think we could add it to C2Explorer only if there is a .NET implementation with appropriate license available there.

#19

Agreed the SPC part is tricky. I googled the below open source codes. Could you have a look to see if you can use them?

https://statistical-process-control-spc.soft112.com/

Regarding hypothesis testing to falsify Null Hypotheses H0: average daily returns <x I believe we have all capabilities already. We just need to take the daily returns from the Tail Ratio code, get rid of the days with return = 0 (likely we are off the market) and then calculate:

n (count)
Mean
Standard deviation
t = (Mean - x) / (St Dev /sqrt(N))
p-value = T.DIST( t, n-1, 1 )
If p-value <=5% then H0 is falsified at 95% confidence and average daily returns are >0

T.Dist is an excel function but there are equivalent you can implement such as Math.Net

https://numerics.mathdotnet.com/api/MathNet.Numerics/ExcelFunctions.htm#TIn

#20

@BobSvan2

I am using the code belove to generate the t test. I canâ€™t generate the p value but the higher the t the better.

var ds = new DescriptiveStatistics(returnsColumn.Values);

double media = Math.Round(ds.Mean,2);
double numero = ds.Count;
double square = Math.Sqrt(numero);
double deviazione = Math.Round(ds.StandardDeviation,2);

double ttest = (media)/(deviazione/square);

Sorting the 100 most popular systems last week by top t value with get the following list. I copy only those with t value >2.5 as lower than that the null hypothese would be falsified for sureâ€¦

Name Ttest
R Option 3.51
Carma Stocks 2.93
CommodityFutures 2.91
IGL CTA 2.89
Quant Models Volatility 2.88
The Momentum of Now 2.84
Optimized Partners I 2.8
QuantAlphaMR 2.77
The Vegan Growth Port 2.75
YZ income fund 2.74
Smart Volatility IRA 2.72
Long Driver Portfolio 2.7
Optimized Partners II 2.69
ETF Timer 2.67