| Overall Statistics |
|
Total Trades 1 Average Win 0% Average Loss 0% Compounding Annual Return 16.001% Drawdown 7.200% Expectancy 0 Net Profit 0% Sharpe Ratio 1.39 Loss Rate 0% Win Rate 0% Profit-Loss Ratio 0 Alpha 0.165 Beta -0.063 Annual Standard Deviation 0.111 Annual Variance 0.012 Information Ratio -0.097 Tracking Error 0.163 Treynor Ratio -2.464 Total Fees $1.00 |
namespace QuantConnect
{
/*
* Keltner Channel indicator demostration
*
*
*
*/
public class volatility : QCAlgorithm
{
///Initialise the keltner channels
KeltnerChannels KC;
string _symbol = "SPY";
//Initialize the data and resolution you require for your strategy:
public override void Initialize()
{
//Start and End Date range for the backtest:
SetStartDate(2013, 1, 1);
SetEndDate(DateTime.Now.Date.AddDays(-1));
//Cash allocation
SetCash(25000);
///Set keltner channel variables
KC = new KeltnerChannels(14, 1.5m);
//Add as many securities as you like. All the data will be passed into the event handler:
AddSecurity(SecurityType.Equity, _symbol, Resolution.Daily);
//Register kelter channels for updates
RegisterIndicator(_symbol, KC, Resolution.Daily);
}
//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)
{
///check if indicator is ready
if(!KC.IsReady) return;
///Simple volatility entry
var holdings = Portfolio[_symbol].Quantity;
var trigger = data[_symbol].High > KC.UpperBand ? true : false;
if (holdings==0 && trigger)
{
SetHoldings(_symbol, 1);
}
///plot
Plot("Keltner Channels",_symbol, Securities[_symbol].Price);
Plot("Keltner Channels","Upper Band", KC.UpperBand);
Plot("Keltner Channels","Lower Band", KC.LowerBand);
}
}
}
namespace QuantConnect.Indicators {
/// <summary>
/// This indicator creates a moving average (middle band) with an upper band and lower band
/// fixed at k average true range away from the middle band
/// </summary>
public class KeltnerChannels : TradeBarIndicator
{
/// Set up of variables
private IndicatorBase<IndicatorDataPoint> _MiddleBand;
private IndicatorBase<TradeBar> _UpperBand;
private IndicatorBase<TradeBar> _LowerBand;
private IndicatorBase<TradeBar> _ATR;
/// <summary>
/// Initializes a new instance of the KeltnerChannels class
/// </summary>
/// <param name="period">The period of the average true range and moving average (middle band)</param>
/// <param name="k">The number of multiplies specifying the distance between the middle band and upper or lower bands</param>
/// <param name="movingAverageType">The type of moving average to be used</param>
public KeltnerChannels(int period, decimal k, MovingAverageType movingAverageType = MovingAverageType.Simple)
: this(string.Format("KC({0},{1})", period, k), period, k, movingAverageType)
{
}
/// <summary>
/// Initializes a new instance of the KeltnerChannels class
/// </summary>
/// <param name="name">The name of this indicator</param>
/// <param name="period">The period of the average true range and moving average (middle band)</param>
/// <param name="k">The number of multiples specifying the distance between the middle band and upper or lower bands</param>
/// <param name="movingAverageType">The type of moving average to be used</param>
public KeltnerChannels(string name, int period, decimal k, MovingAverageType movingAverageType = MovingAverageType.Simple)
: base(name)
{
///Initialise ATR and SMA
_ATR = new AverageTrueRange(name + "_AverageTrueRange", period, movingAverageType);
_MiddleBand = new SimpleMovingAverage(name + "_SimpleMovingAverage", period);
///Compute Lower Band
_LowerBand = new FunctionalIndicator<TradeBar>(name + "_LowerBand",
input => ComputeLowerBand(k, period, input),
fastStoch => _MiddleBand.IsReady,
() => _MiddleBand.Reset()
);
///Compute Upper Band
_UpperBand = new FunctionalIndicator<TradeBar>(name + "_UpperBand",
input => ComputeUpperBand(k, period, input),
fastStoch => _MiddleBand.IsReady,
() => _MiddleBand.Reset()
);
}
/// <summary>
/// calculates the lower band
/// </summary>
private decimal ComputeLowerBand(decimal k, int period, TradeBar input)
{
var lowerBand = _MiddleBand.Samples >= period ? _MiddleBand - Decimal.Multiply(_ATR,k): new decimal(0.0);
return lowerBand;
}
/// <summary>
/// calculates the upper band
/// </summary>
private decimal ComputeUpperBand(decimal k, int period, TradeBar input)
{
var upperBand = _MiddleBand.Samples >= period ? _MiddleBand + Decimal.Multiply(_ATR,k): new decimal(0.0);
return upperBand;
}
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady
{
get { return _MiddleBand.IsReady && _UpperBand.IsReady && _LowerBand.IsReady; }
}
/// <summary>
/// Returns the Upper band of the kelter channel
/// </summary>
public decimal UpperBand
{
get { return _UpperBand;}
}
/// <summary>
/// Returns the Lower band of the kelter channel
/// </summary>
public decimal LowerBand
{
get { return _LowerBand;}
}
/// <summary>
/// Returns the Middle band of the kelter channel
/// </summary>
public decimal MiddleBand
{
get { return _MiddleBand;}
}
/// <summary>
/// Returns the average true range value of the Keltner Channels
/// </summary>
public decimal TrueRangeAverage
{
get { return _ATR;}
}
/// <summary>
/// Computes the next value for this indicator from the given state.
/// </summary>
/// <param name="input">The TradeBar to this indicator on this time step</param>
/// <returns>A new value for this indicator</returns>
protected override decimal ComputeNextValue(TradeBar input)
{
_ATR.Update(input);
_MiddleBand.Update(input.Time, input.Close);
_LowerBand.Update(input);
_UpperBand.Update(input);
return _MiddleBand;
}
public override void Reset()
{
_ATR.Reset();
_MiddleBand.Reset();
_UpperBand.Reset();
_LowerBand.Reset();
base.Reset();
}
}
}