| Overall Statistics |
|
Total Trades 1105 Average Win 0.68% Average Loss -0.63% Compounding Annual Return 12.193% Drawdown 16.100% Expectancy 0.346 Net Profit 224.965% Sharpe Ratio 0.962 Loss Rate 35% Win Rate 65% Profit-Loss Ratio 1.08 Alpha 0.104 Beta -0.237 Annual Standard Deviation 0.104 Annual Variance 0.011 Information Ratio 0.804 Tracking Error 0.104 Treynor Ratio -0.423 Total Fees $2881.66 |
using Accord.MachineLearning.VectorMachines;
using Accord.MachineLearning.VectorMachines.Learning;
using Accord.Statistics.Kernels;
using Accord.Math.Optimization.Losses;
namespace QuantConnect
{
public class QuandlFuture : Quandl{
public QuandlFuture():base(valueColumnName:"Settle"){
}
}
public class TrainingData{
public double[] Inputs{get;set;}
public double Target{get;set;}
}
public class DailyMacdSPYFuturesWithSPYandBNDAlgorithm : QCAlgorithm
{
private MovingAverageConvergenceDivergence spyFuturesMacd;
private MovingAverageConvergenceDivergence spyMacd;
private RelativeStrengthIndex spyRsi;
private RelativeStrengthIndex spyFuturesRsi;
private FractalAdaptiveMovingAverage spyFrama;
private decimal weight1 = 0.90M;
private decimal weight2 = 0.07M;
private bool? isLong = null;
private RollingWindow<TrainingData> trainingData = new RollingWindow<TrainingData>(30);
private SupportVectorMachine<Gaussian> svm;
Chart PredictionVsActual = new Chart("PredictionVsActual");
public double[] GetCurrentInputRow(){
var spyFuturesSettle=this.Securities["CHRIS/CME_SP1"].Price;
var spy = this.Securities["SPY"];
var inputRow = new[]{
(double)spy.Open,
(double)spyRsi.AverageLoss.Current.Value,
(double)spyRsi.AverageGain.Current.Value,
(double)spyFuturesRsi.AverageLoss.Current.Value,
(double)spyFuturesRsi.AverageGain.Current.Value,
// (double)spyFrama.Current.Value,
//(double)spy.Fundamentals.ValuationRatios.PERatio, //TODO: Null exception here. How to get fundamentals here?
(double)spyFuturesSettle,
// double.Parse(spyFuturesMacd.Fast.ToString()),
// double.Parse(spyFuturesMacd.Slow.ToString()),
double.Parse((spyFuturesMacd.Fast/spyFuturesMacd.Slow).ToString()),
// double.Parse(spyMacd.Fast.ToString()),
// double.Parse(spyMacd.Slow.ToString()),
double.Parse((spyMacd.Fast/spyMacd.Slow).ToString())};
return inputRow;
}
public override void Initialize()
{
SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage, AccountType.Margin);
SetStartDate(2009,1,1);// # Set Start Date
SetEndDate(2019,3,28);// # Set End Date
SetCash(25000) ;// # Set Strategy Cash
SetWarmUp(30);
AddEquity("SPY", Resolution.Hour);
AddEquity("BND", Resolution.Hour);
// Construct MACD Indicator
PredictionVsActual.AddSeries(new Series("Prediction"));
PredictionVsActual.AddSeries(new Series("Actual")); //TODO: show some sort of consistent error margin. Prediction - Actual?
AddData<QuandlFuture>("CHRIS/CME_SP1", Resolution.Daily);
spyFuturesMacd = MACD("CHRIS/CME_SP1",12, 26,9, MovingAverageType.Simple, Resolution.Daily);
spyMacd = MACD("SPY",12, 26,9, MovingAverageType.Simple, Resolution.Daily);
spyRsi = RSI("SPY", 12, MovingAverageType.Simple, Resolution.Daily);
spyFuturesRsi = RSI("CHRIS/CME_SP1",12);
spyFrama = FRAMA("SPY", 8);
// Log("Time,LastSpyFuturesSettle,LastSpyFuturesMacdFast,LastSpyFuturesMacdSlow,LastSpyFuturesMacdRatio,LastSpyMacdFast,LastSpyMacdSlow,LastSpyMacdRatio,LastSpy");
//Quandl.("Settle");
Schedule.On(DateRules.EveryDay("SPY"), TimeRules.BeforeMarketClose("SPY",5), ()=>{
if(!spyFuturesMacd.IsReady || !spyMacd.IsReady || !spyFuturesRsi.IsReady || !spyFuturesRsi.IsReady || !spyFrama.IsReady) return;
var spy = this.Securities["SPY"].Price;
trainingData.Add(new TrainingData{ Inputs=GetCurrentInputRow(),
Target=(double)spy
});
// Plot("PredictionVsActual","Actual",spy);
if(trainingData.IsReady){
var inputs = trainingData.Select(x=>x.Inputs).ToArray();
var targets = trainingData.Select(x=>x.Target).ToArray();
// svm = new SupportVectorMachine(inputs.First().Length);
var teacher = new FanChenLinSupportVectorRegression<Gaussian>(){
UseKernelEstimation = true,
UseComplexityHeuristic = true
};
svm = teacher.Learn(inputs,targets);
var score = svm.Score(inputs,targets);
var predicted = svm.Compute(trainingData.Last().Inputs);
var predictedVsActual = (predicted/(double)spy)*100;
double error = new SquareLoss(targets).Loss(score);
Plot("PredictionVsActual","Prediction",error);
Log($"Trained with {inputs.Length} inputs. Score: {string.Join(",",score)}");
}
});
Schedule.On(DateRules.EveryDay("SPY"), TimeRules.AfterMarketOpen("SPY",5), ()=>{
if(!spyFuturesMacd.IsReady || !spyMacd.IsReady || !spyFuturesRsi.IsReady || !spyFuturesRsi.IsReady || !spyFrama.IsReady) return;
var spyFuturesSettle=this.Securities["CHRIS/CME_SP1"].Price;
var inputs=GetCurrentInputRow();
// Log(string.Join(",",inputs));
if(trainingData.IsReady && svm != null){
var target = svm.Compute(inputs);
// Plot("PredictionVsActual","Prediction",target);
if(target > (double)Securities["SPY"].Open && !Portfolio["SPY"].Invested) {
Liquidate("BND");
SetHoldings("SPY",.97);
}
if(target <= (double)Securities["SPY"].Open && Portfolio["SPY"].Invested){
Liquidate("SPY");
SetHoldings("BND",.97);
}
}
});
}
public void OnData(QuandlFuture data)
{
// Log("Quandl:" + data.GetProperty("Settle"));
}
public override void OnData(Slice data)
{
}
public override void OnOrderEvent(OrderEvent orderEvent)
{
var order = Transactions.GetOrderById(orderEvent.OrderId);
if(orderEvent.Status == OrderStatus.Filled && order.Tag=="stoploss"){
Log("Stop loss triggered for " + order.Symbol + " at " + Time.ToString("g"));
}
}
}
}