Overall Statistics |
Total Trades 631 Average Win 1.04% Average Loss -0.84% Compounding Annual Return -98.550% Drawdown 52.500% Expectancy -0.186 Net Profit -44.141% Sharpe Ratio -3.612 Loss Rate 63% Win Rate 37% Profit-Loss Ratio 1.23 Alpha -3.194 Beta -0.086 Annual Standard Deviation 0.874 Annual Variance 0.764 Information Ratio -3.037 Tracking Error 0.902 Treynor Ratio 36.789 Total Fees $21002.26 |
/* 30 mins XIV long short using SMA cross */ using System; using System.Linq; using QuantConnect.Indicators; using QuantConnect.Models; namespace QuantConnect.Algorithm.Examples { /// <summary> /// /// QuantConnect University: EMA + SMA Cross /// /// In this example we look at the canonical 20/50 day moving average cross. This algorithm /// will go long when the 20 crosses above the 50 and will liquidate when the 20 crosses /// back below the 50. // -------VATS CHANGES ----------- // 1) Intraday - Hourly // 2) 1/50 period SMA cross // // -------VATS CHANGES ----------- /// </summary> public class QCUMovingAverageCross : QCAlgorithm { private const string Symbol = "XIV"; private SimpleMovingAverage fast; private SimpleMovingAverage slow; TradeBar _spyMinutes; public override void Initialize() { SetStartDate(2016, 01, 01); //SetEndDate(2015, 12, 31); SetEndDate(DateTime.Now.Date.AddDays(-1)); SetCash(100000); AddSecurity(SecurityType.Equity, Symbol, Resolution.Minute); Transactions.MarketOrderFillTimeout = TimeSpan.FromMinutes(10); // define our daily trade bar consolidator. we can access the daily bar // from the DataConsolidated events, this consolidator can only be used // for a single symbol! var minConsolidator = new TradeBarConsolidator(TimeSpan.FromMinutes(5)); // attach our event handler. the event handler is a function that will be called each time we produce // a new consolidated piece of data. minConsolidator.DataConsolidated += OnFiveMinutes; // this call adds our daily consolidator to the manager to receive updates from the engine SubscriptionManager.AddConsolidator(Symbol, minConsolidator); int fastPeriod = 1; int slowPeriod = 5; fast = new SimpleMovingAverage(Symbol + "_SMA_" + fastPeriod, fastPeriod); slow = new SimpleMovingAverage(Symbol + "_SMA_" + slowPeriod, slowPeriod); // we need to manually register these indicators for automatic updates RegisterIndicator(Symbol, fast, minConsolidator); RegisterIndicator(Symbol, slow, minConsolidator); } private DateTime previous; private void OnFiveMinutes(object sender, TradeBar consolidated) { _spyMinutes = consolidated; //Log(consolidated.Time.ToString("o") + " >> " + Symbol + ">> LONG >> 100 >> " + Portfolio[Symbol].Quantity); // if you want code to run every five minutes then you can run it inside of here if (!slow.IsReady) return; // only once per day // Commented the following line to simulate intraday - Vats //if (previous.Date == data.Time.Date) return; // in OnData, returns outside of 9am - 2pm //if (Time.Hour <= 9 || Time.Hour > 16) return; const decimal tolerance = 0*0.10000m; var holdings = Portfolio[Symbol].Quantity; int qnt=0; int total_qnt=0; decimal lvl=1.0m; decimal value = Portfolio.TotalPortfolioValue; { if (fast > slow * (1 + tolerance)) { if (holdings == 0) { Log (consolidated.Time.ToString()) ; qnt = (int) (value*lvl/Securities[Symbol].Price); total_qnt = qnt-holdings;//holdings=0 here //total_qnt = qnt;//holdings=0 here //SetHoldings(Symbol, 0.4); Order(Symbol,total_qnt,OrderType.Market); Log("first BUY >> " + total_qnt + "@ price " + Securities[Symbol].Price+"from cash"+qnt); Log("NET POSITION BEFORE NEXT TRANSACTION >> " + holdings); } else if (holdings < 0) { Log (consolidated.Time.ToString()) ; //SetHoldings(Symbol, 0.4); qnt = (int) (value*lvl/Securities[Symbol].Price); total_qnt = qnt-1*holdings; //reverse the current negative holding and order some more //total_qnt = 2*qnt;//holdings=0 here Order(Symbol,total_qnt,OrderType.Market); Log("BUY >> " + total_qnt + "@ price " + Securities[Symbol].Price+"from cash"+qnt); Log("NET POSITION BEFORE NEXT TRANSACTION >> " + holdings); } } if (fast < slow) //go short { if (holdings == 0) { Log (consolidated.Time.ToString()) ; qnt = (int) (-1*value*lvl/Securities[Symbol].Price); total_qnt = qnt-holdings;//holdings=0 here //total_qnt = qnt;//holdings=0 here //SetHoldings(Symbol, 0.4); Order(Symbol,total_qnt,OrderType.Market); Log("first SELL >> " + total_qnt + "@ price " + Securities[Symbol].Price+"from cash"+qnt); Log("NET POSITION BEFORE NEXT TRANSACTION >> " + holdings); } else if (holdings >0) { Log (consolidated.Time.ToString()) ; qnt = (int) (-1*value*lvl/Securities[Symbol].Price); total_qnt = qnt-1*holdings; //reverse the current positive holding and short some more //total_qnt = 2*qnt;//holdings=0 here Order(Symbol,total_qnt,OrderType.Market); Log("SELL >> " + total_qnt + "@ price " + Securities[Symbol].Price+"from cash"+qnt); Log("NET POSITION BEFORE NEXT TRANSACTION >> " + holdings); //Liquidate(Symbol); } } } previous = consolidated.Time; } public void OnData(TradeBars data) { } bool IsTradingday(TradeBar b) { if ( b.Time.Date.DayOfWeek == DayOfWeek.Monday || b.Time.Date.DayOfWeek == DayOfWeek.Tuesday || b.Time.Date.DayOfWeek == DayOfWeek.Wednesday || b.Time.Date.DayOfWeek == DayOfWeek.Thursday || b.Time.Date.DayOfWeek == DayOfWeek.Friday) return true; else return false; } // avoid weekends but still problematic with the nontrading weekdays } }