| 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 namespaceusing 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;
}
}
}