Overall Statistics |
Total Trades 814 Average Win 0.73% Average Loss -0.74% Compounding Annual Return 1.563% Drawdown 11.500% Expectancy 0.102 Net Profit 32.501% Sharpe Ratio 0.327 Loss Rate 45% Win Rate 55% Profit-Loss Ratio 0.99 Alpha 0.017 Beta -0.007 Annual Standard Deviation 0.051 Annual Variance 0.003 Information Ratio -0.276 Tracking Error 0.205 Treynor Ratio -2.369 Total Fees $4597.53 |
namespace QuantConnect { /* * SPYSellAfter3DownDays * By:Ray Bohac * * Playing with purchasing SPY after 3 days of consecutive close < open * Inspiration from article at http://tradingwithpython.blogspot.com/2016/02/a-simple-statistical-edge-in-spy.html */ public class SPYSellAfter3DownDays : QCAlgorithm { string symbol = "SPY"; const int NUM_DAYS = 3; private OpenClose[] priceArray = new OpenClose[NUM_DAYS]; private decimal _last = 0; public override void Initialize() { //Start and End Date range for the backtest: SetStartDate(1998, 1, 1); SetEndDate(DateTime.Now.Date.AddDays(-1)); //Cash allocation SetCash(100000); AddSecurity(SecurityType.Equity, symbol, Resolution.Minute); for (int i = 0; i < NUM_DAYS; i++) { priceArray[i] = new OpenClose();} // TimeRules https://www.quantconnect.com/terminal/docs/topic4253.html Schedule.On(DateRules.EveryDay(symbol), TimeRules.At(7,0,0), () => { RotatePriceArray(); }); Schedule.On(DateRules.EveryDay(symbol), TimeRules.AfterMarketOpen(symbol, 0.30), () => { priceArray[0].open = _last; }); Schedule.On(DateRules.EveryDay(symbol), TimeRules.AfterMarketOpen(symbol, 30), () => { // 30 Minutes after market open SellCheck(); }); //Schedule.On(DateRules.EveryDay(symbol), TimeRules.BeforeMarketClose(symbol, 1), () => //{ // priceArray[0].close = _last; //}); Schedule.On(DateRules.EveryDay(symbol), TimeRules.At(15,30,0), () => { BuyCheck(); }); SetWarmup(new TimeSpan(10, 0, 0, 0, 0)); // 10 Days } private void RotatePriceArray() { for (int i = NUM_DAYS -1; i > 0; i--) { priceArray[i].close = priceArray[i-1].close; priceArray[i].open = priceArray[i-1].open; } priceArray[0].reset(); } private void BuyCheck() { priceArray[0].close = _last; String LogStr = "BuyCheck: Fired at: " + Time; for (int i = 0; i < NUM_DAYS; i++) LogStr += " "+i.ToString()+"="+priceArray[i].ToString(); Log(LogStr); if (allClosedLower() && (!Portfolio.HoldStock)) { Log("Buy On "+ Time); int quantity = (int)Math.Floor(Portfolio.Cash / _last); Order(symbol, quantity); } } private void SellCheck() { if (Securities[symbol].Holdings.Quantity > 0) Order(symbol, -Securities[symbol].Holdings.Quantity); } private bool allClosedLower() { for (int i = 0; i < NUM_DAYS; i++) if (!priceArray[i].closedLower()) return false; return true; } public void OnData(TradeBars data) { if (data.ContainsKey(symbol)) { _last = data[symbol].Close; priceArray[0].close = _last; } } } public class OpenClose { public decimal open = 0; public decimal close = 0; public bool closedLower() { return close < open; } public void reset() { open = 0; close = 0; } public override string ToString() { return "("+ closedLower().ToString()[0]+")O:"+open.ToString("N4")+"/C:"+close.ToString("N4"); } } }