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