| Overall Statistics |
|
Total Trades 30 Average Win 5.64% Average Loss -8.01% Compounding Annual Return 5.066% Drawdown 15.700% Expectancy -0.148 Net Profit 161.360% Sharpe Ratio 0.625 Loss Rate 50% Win Rate 50% Profit-Loss Ratio 0.70 Alpha -0.055 Beta 5.403 Annual Standard Deviation 0.085 Annual Variance 0.007 Information Ratio 0.39 Tracking Error 0.085 Treynor Ratio 0.01 Total Fees $2674.49 |
namespace QuantConnect
{
public class BasicTemplateAlgorithm : QCAlgorithm
{
public string[] Symbols = {"XLY","XLP","XLE","XLF","XLV","XLI","XLB","XLK","XLU"};
private Dictionary<string, double> Elo = new Dictionary<string, double>();
private Dictionary<string, RollingWindow<decimal>> Return = new Dictionary<string, RollingWindow<decimal>>();
private Dictionary<string, decimal> Price = new Dictionary<string, decimal>();
public Dictionary<string, double> StandardDevation = new Dictionary<string, double>();
public override void Initialize()
{
SetStartDate(2000, 1, 1);
SetEndDate(DateTime.Now);
SetCash(1000000);
SetWarmup(250);
foreach (var symbol in Symbols)
{
AddSecurity(SecurityType.Equity,symbol,Resolution.Daily);
Elo[symbol] = 1500;
Return[symbol] = new RollingWindow<decimal>(50);
Price[symbol] = 0;
StandardDevation[symbol] = 0.0;
Securities[symbol].SetLeverage(10);
}
}
public void OnData(TradeBars data)
{
foreach (var symbol in Symbols)
{
if (!data.ContainsKey(symbol)) continue;
if (Time.DayOfWeek == DayOfWeek.Thursday)
{
var K = 2;
int C = 200;
if (Price[symbol] != 0)
{
Return[symbol].Add(data[symbol].Close / Price[symbol]);
}
Price[symbol] = data[symbol].Close;
foreach (var sector in Symbols)
{
if (!Return[symbol].IsReady) continue; if (!Return[sector].IsReady) continue;
StandardDevation[symbol] = Math.Sqrt(Return[symbol].Sum(d => Math.Pow(Convert.ToDouble(d - Return[symbol].Average()), 2)))/(Return[symbol].Count()-1);
if (((double)(Return[symbol][0])/StandardDevation[symbol]) > ((double)(Return[sector][0])/StandardDevation[sector]))
{
Elo[symbol] = Elo[symbol] + ((K/2)*(1 + (Elo[sector] - Elo[symbol])/(C*2)));
}
if (((double)(Return[symbol][0])/StandardDevation[symbol]) < ((double)(Return[sector][0])/StandardDevation[sector]))
{
Elo[symbol] = Elo[symbol] + ((K/2)*(-1 + (Elo[sector] - Elo[symbol])/(C*2)));
}
}
}
}
string max = Elo.Aggregate((l, r) => l.Value > r.Value ? l : r).Key;
string min = Elo.Aggregate((l, r) => l.Value < r.Value ? l : r).Key;
if (Time.DayOfWeek == DayOfWeek.Thursday)
{
foreach (var symbol in Symbols)
{
if (Portfolio[symbol].IsLong && symbol != max)
{
SetHoldings(symbol, 0, false);
}
if (Portfolio[symbol].IsShort && symbol != min)
{
SetHoldings(symbol, 0, false);
}
Plot("Elo's ", "Elo " + symbol, Elo[symbol]);
}
var Ea = 1/(1 + Math.Pow(10,(Elo[min]-Elo[max])/400));
var Eb = 1 - Ea;
var weight = (double)((Ea-Eb));
var Ratio = (StandardDevation[max]/StandardDevation[min])+1;
var maxweight = (weight/Ratio);
if (Elo[max] != 1500 && Elo[min] != 1500 && Elo[max] != Elo[min] && !Portfolio[max].IsLong)
{
SetHoldings(max, (float)maxweight, false, "Long " + max + " Elo is " + Math.Round(Elo[max],2) + " Odds are " + Math.Round(Ea,2));
}
if (Elo[max] != 1500 && Elo[min] != 1500 && Elo[max] != Elo[min] && !Portfolio[min].IsShort)
{
SetHoldings(min, (float)-(weight-maxweight), false, "Short " + min + " Elo is " + Math.Round(Elo[min],2));
}
}
}
}
}