Overall Statistics |
Total Trades 0 Average Win 0% Average Loss 0% Compounding Annual Return 0% Drawdown 0% Expectancy 0 Net Profit 0% Sharpe Ratio NaN Loss Rate 0% Win Rate 0% Profit-Loss Ratio 0 Alpha 0 Beta 0 Annual Standard Deviation 0 Annual Variance 0 Information Ratio NaN Tracking Error NaN Treynor Ratio NaN |
using System; using System.Collections; using System.Collections.Generic; using QuantConnect.Securities; using QuantConnect.Models; namespace QuantConnect { // Name your algorithm class anything, as long as it inherits QCAlgorithm public class BasicTemplateAlgorithm : QCAlgorithm { AverageDirectionalIndex adx = new AverageDirectionalIndex(3); //Initialize the data and resolution you require for your strategy: public override void Initialize() { SetStartDate(2014, 12, 01); SetEndDate(DateTime.Now.Date.AddDays(-1)); SetCash(25000); AddSecurity(SecurityType.Equity, "SPY", Resolution.Minute); } //Data Event Handler: New data arrives here. "TradeBars" type is a dictionary of strings so you can access it by symbol. public void OnData(TradeBars data) { TradeBar SPY = data["SPY"]; adx.AddSample(SPY); Log("READY? " + adx.Ready + " VALUE: " + Math.Round(adx.ADX,2).ToString()); } } }
using System; using System.Collections; using System.Collections.Generic; using QuantConnect.Securities; using QuantConnect.Models; namespace QuantConnect { /* ADX Indicator - Average Directional Index is a complicated but powerful indicator. * * 1. Calculate the Directional Movements: +DM_t, -DM_t. * 2. Find the Average Directional Movement: ADM_t * 3. Calculate the Average True Range: ATR_t * 4. Calculate the Directional Indexes: DI+_t, DI-_t, * Directional Movement Index: DX_t, * then Average Directional Movement Index! ADX_t * * Requires day to be divided into segments, periods and a running record kept of the previous value so the averages can be made. */ public class AverageDirectionalIndex { //Public Result Access: Primary ADX Indicator public decimal ADX { get; private set; } //Public Result Access: DMI Positive: public decimal DMI_Pos { get; private set; } //Public Result Access: DMI Negative: public decimal DMI_Neg { get; private set; } //Public Result Access: Direction of the ADX Indicator: public decimal Decision { get; private set; } //Public Result Access: When indicator has sufficient data flags as true. public bool Ready { get; private set; } //Initialize private ADXCacheItem indicatorMemory = new ADXCacheItem(); private decimal _expConst = 0; private int _samplePeriods = 0; private Candle _superCandle = new Candle(); // Constructor: Set the sample period: public AverageDirectionalIndex(int samplePeriods) { _expConst = (2m / (decimal)(samplePeriods + 1)); _samplePeriods = samplePeriods; Ready = false; } /// <summary> /// Calculate the ADX figure, return an indicator result. /// </summary> public decimal AddSample(TradeBar bar) { //0. Save these samples in running OHLC candle until requested samplePeriod reached: _superCandle.Update(bar); if (_superCandle.Samples < _samplePeriods) return Decision; //0. Define a result storage for this session. ADXCacheItem current = new ADXCacheItem(); current.OHLC = _superCandle; //0. If this is the first candle skip it and come back for second: to calc directional index can't be relative to 0. if (!indicatorMemory.set) { current.set = true; indicatorMemory = current; _superCandle = new Candle(); return Decision; } //1. Calculate the Directional Movements: store results back into current-variable class cache GetDirectionalMovements(ref current); //2. Find the Average Directional Movement. GetAverageDirectionalMovements(ref current); //3. Get the Average True Range: GetAverageTrueRange(ref current); //4. Get the Average Directional Movement Index ADX-t, and DI+, DI- GetADX(ref current); //Strong Trend is Present, and have at least X-min data Decision = 0; if (current.adx > 40) { //NOW! We have an ADX result, interpret it.. if (current.dmiPos > 40) { Decision = 1; } else if (current.dmiNeg > 40) { Decision = -1; } } //Save the results to publicly accessible properties. ADX = current.adx; DMI_Neg = current.dmiNeg; DMI_Pos = current.dmiPos; //Update the indicator cache - store previous result between calls. current.set = true; Ready = true; indicatorMemory = current; _superCandle = new Candle(); return Decision; } /// <summary> /// 1. Get the pure directional movements, in DM+, DM- Form. /// </summary> /// <param name="current">ADX Cache class for easy storing for next analysis session.</param> private void GetDirectionalMovements(ref ADXCacheItem current) { //Change from the previous period to now. decimal deltaHigh = current.OHLC.High - indicatorMemory.OHLC.High; decimal deltaLow = indicatorMemory.OHLC.Low - current.OHLC.Low; //Allocate the Delta Movement. if ((deltaHigh < 0 && deltaLow < 0) || (deltaHigh == deltaLow)) { current.dm_plus = 0; current.dm_neg = 0; } else if (deltaHigh > deltaLow) { current.dm_plus = deltaHigh; current.dm_neg = 0; } else if (deltaHigh < deltaLow) { current.dm_plus = 0; current.dm_neg = deltaLow; } } /// <summary> /// 2. Get the Exp Average of the directional movement indexs /// </summary> private void GetAverageDirectionalMovements(ref ADXCacheItem current) { if (!Ready) { //If this is the first run, current.adm_plus = current.dm_plus; current.adm_neg = current.dm_neg; } else { //This is not our first sample current.adm_plus = (current.dm_plus * _expConst) + (indicatorMemory.adm_plus * (1 - _expConst)); current.adm_neg = (current.dm_neg * _expConst) + (indicatorMemory.adm_neg * (1 - _expConst)); ; } } /// <summary> /// 3. Get the true range of the price. /// </summary> private void GetAverageTrueRange(ref ADXCacheItem current) { decimal yesterdayClose = indicatorMemory.OHLC.Close; decimal trueRange = System.Math.Max(Math.Abs(current.OHLC.High - current.OHLC.Low), System.Math.Max(Math.Abs(current.OHLC.High - yesterdayClose), Math.Abs(yesterdayClose - current.OHLC.Low))); //Get the current true range: if (indicatorMemory.atr == 0) { current.atr = trueRange; } else { current.atr = (trueRange * _expConst) + ((1 - _expConst) * indicatorMemory.atr); } } /// <summary> /// 4. Get the Directional Movement Index /// </summary> private void GetADX(ref ADXCacheItem current) { decimal dmi_plus = 0; decimal dmi_neg = 0; if (current.atr > 0) { dmi_plus = (current.adm_plus / current.atr) * 100; dmi_neg = (current.adm_neg / current.atr) * 100; } if ((dmi_plus + dmi_neg) != 0) { current.dx = (Math.Abs(dmi_plus - dmi_neg) / (dmi_plus + dmi_neg)) * 100; } else { current.dx = indicatorMemory.dx; } //Save the results. current.dmiPos = dmi_plus; current.dmiNeg = dmi_neg; current.adx = current.dx * _expConst + (1 - _expConst) * indicatorMemory.adx; } /// <summary> /// Provide a structure for caching the previous values of the ADX /// </summary> public class ADXCacheItem { public Candle OHLC = new Candle(); public bool set = false; public decimal atr = 0; public decimal dm_plus = 0; public decimal dm_neg = 0; public decimal adm_plus = 0; public decimal adm_neg = 0; public decimal dx = 0; public decimal dmiPos = 0; public decimal dmiNeg = 0; public decimal adx = 0; } /// <summary> /// Simple online "super-tradebar" generator for making an OHLC from multiple bars. /// </summary> public class Candle { public Candle() { } public decimal Open = 0; public decimal High = Decimal.MinValue; public decimal Low = Decimal.MaxValue; public decimal Close = 0; public int Samples = 0; public void Update(TradeBar bar) { if (Open == 0) Open = bar.Open; if (High < bar.High) High = bar.High; if (Low > bar.Low) Low = bar.Low; Close = bar.Close; Samples++; } } } // End ADX Indicator Class } // End Namespace