Overall Statistics |
Total Trades 128 Average Win 2.05% Average Loss -1.36% Compounding Annual Return 5.003% Drawdown 25.400% Expectancy 0.351 Net Profit 74.384% Sharpe Ratio 0.417 Loss Rate 46% Win Rate 54% Profit-Loss Ratio 1.51 Alpha 0.024 Beta 0.365 Annual Standard Deviation 0.141 Annual Variance 0.02 Information Ratio -0.214 Tracking Error 0.174 Treynor Ratio 0.161 Total Fees $475.60 |
namespace QuantConnect { public class DivergenceIndex : QCAlgorithm { //primary instrument to trade string symbol = "SPY"; StandardDeviation _sd; SimpleMovingAverage _smaNorm; SimpleMovingAverage _slowing; StandardDeviation _sdNorm; RollingWindow<TradeBar> _window = new RollingWindow<TradeBar>(40); DateTime lastTradeTime; decimal _delta; decimal _deltaFast; decimal _deltaSlow; decimal _divIndex; decimal _divIndNorm; decimal _prevDiv; //conso0lidating shit private TimeSpan _barPeriod = TimeSpan.FromHours(1); private Consolidator _consolidator; //Initialize the data and resolution you require for your strategy: public override void Initialize() { //Start and End Date range for the backtest: SetStartDate(2004, 1, 3); SetEndDate(DateTime.Now.AddDays(-1)); //Cash allocation SetCash(25000); AddSecurity(SecurityType.Equity, symbol, Resolution.Minute); //Securities[symbol].TransactionModel = new CustomTransactionModel(); //Setup Consolidator bar _consolidator = new Consolidator(_barPeriod); //Custom Data Indicator: //updated inside OnData _sd = new StandardDeviation(40); _sdNorm = new StandardDeviation(30); _smaNorm = new SimpleMovingAverage(30); _slowing = new SimpleMovingAverage(20); } //---------------------------------------------------------------------------------------------- ONDATA public void OnData(TradeBars data) { if (_consolidator.Update(data[symbol])) { try { _window.Add(data[symbol]); if (!_window.IsReady) return; _delta = _window[0].Close-_window[1].Close; _deltaFast = _window[0].Close-_window[9].Close; _deltaSlow = _window[0].Close-_window[39].Close; //updating custom indies TradeBar bar; if (data.TryGetValue(symbol, out bar)) { _sd.Update(bar.Time, _delta); } if(_sd != 0) { _divIndex = (_deltaFast*_deltaSlow)/(_sd*_sd); } if (data.TryGetValue(symbol, out bar)) { _sdNorm.Update(bar.Time, _divIndex); _smaNorm.Update(bar.Time, _divIndex); _slowing.Update(bar.Time, _divIndex); } if(_sdNorm != 0) { _divIndNorm = (_divIndex - _smaNorm)/_sdNorm; } // watchdog plots Plot("Divergence Index", "Ratio", _divIndex); Plot("Divergence Index", "Slowing", _slowing); Plot("Divergence Index Norm", "Ratio", _divIndNorm); //exits if(Portfolio.HoldStock) { if(Portfolio[symbol].IsLong && _slowing < 0) { Liquidate(symbol); }/* else if(Portfolio[symbol].IsShort && _slowing > 0) { Liquidate(symbol); }*/ } //entries if(!Portfolio.HoldStock && _divIndex < -20) { SetHoldings(symbol, 0.8); lastTradeTime = data[symbol].Time; }/* else if(!Portfolio.HoldStock && _divIndex > 20) { SetHoldings(symbol, -0.8); lastTradeTime = data[symbol].Time; }*/ //prevstuff _prevDiv = _divIndNorm; } catch(Exception err) { Debug(err.Message); } }// end of consolidator } // end of trabers ond }// end of algo }//end of namespace
using System; using System.Collections; using System.Collections.Generic; using QuantConnect.Securities; using QuantConnect.Models; namespace QuantConnect { /* * TimeSpanConsolidator Helper Routine: Assemble generic timespan bar lengths: e.g. 10 minutes: * * 1. Setup the new Consolidator class with the timespan period: * var _consolidator = new Consolidator(TimeSpan.FromMinutes(10)); * * 2. Add in the data with the update routine. It will return true when bar ready * if (_consolidator.Update(data["MSFT"])) { UseBar } */ public class Consolidator { private TradeBar _resultBar; private TradeBar _workingBar; private DateTime _start; private TimeSpan _period; //Result: public TradeBar Bar { get { return _resultBar; } } //Constructor: Set the period we'd like to scan public Consolidator(TimeSpan span) { this._period = span; this._resultBar = new TradeBar(); this._workingBar = new TradeBar(new DateTime(), "", Decimal.Zero, Decimal.MinValue, Decimal.MaxValue, 0, 0); } //Submit this bar, return true if we've started a new one. public bool Update(TradeBar newBar) { //Intialize: if (_start == new DateTime()) { _start = newBar.Time; } //While we're less than end date, keep adding to this bar: if (newBar.Time < (_start + _period)) { //Building bar: AddToBar(newBar); return false; } else { //Completed bar: start new one: _resultBar = _workingBar; //Create a new bar: _workingBar = new TradeBar(newBar.Time, newBar.Symbol, Decimal.Zero, Decimal.MinValue, Decimal.MaxValue, 0, 0); //Start of this bar: _start = newBar.Time; AddToBar(newBar); return true; } } //Add to a tradebar private void AddToBar(TradeBar newBar) { //Add this data to working bar: if (_workingBar.Time == new DateTime()) _workingBar.Time = newBar.Time; if (_workingBar.Symbol == "") _workingBar.Symbol = newBar.Symbol; if (_workingBar.Open == Decimal.Zero) _workingBar.Open = newBar.Open; if (newBar.High > _workingBar.High) _workingBar.High = newBar.High; if (newBar.Low < _workingBar.Low) _workingBar.Low = newBar.Low; _workingBar.Close = newBar.Close; _workingBar.Volume = newBar.Volume; } } }