| Overall Statistics |
|
Total Trades 8 Average Win 25.41% Average Loss -1.83% Compounding Annual Return 29.549% Drawdown 16.300% Expectancy 12.047 Net Profit 366.278% Sharpe Ratio 1.209 Loss Rate 12% Win Rate 88% Profit-Loss Ratio 13.91 Alpha 0.128 Beta 0.91 Annual Standard Deviation 0.235 Annual Variance 0.055 Information Ratio 0.661 Tracking Error 0.17 Treynor Ratio 0.313 |
-no value-
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.Collections.Generic;
using System.Linq;
using QuantConnect.Indicators;
using QuantConnect.Models;
namespace QuantConnect.Algorithm.Examples
{
/// <summary>
/// Constructs a displaced moving average ribbon and buys when all are lined up, liquidates when they all line down
/// Ribbons are great for visualizing trends
/// Signals are generated when they all line up in a paricular direction
/// A buy signal is when the values of the indicators are increasing (from slowest to fastest)
/// A sell signal is when the values of the indicators are decreasing (from slowest to fastest)
/// </summary>
public class DisplacedMovingAverageRibbon : QCAlgorithm
{
private const string Symbol = "SPY";
private Indicator[] ribbon;
public override void Initialize()
{
SetStartDate(2009, 01, 01);
SetEndDate(2015, 01, 01);
AddSecurity(SecurityType.Equity, Symbol, Resolution.Minute);
int count = 6;
int offset = 5;
int period = 15;
// define our sma as the base of the ribbon
var sma = new SimpleMovingAverage(period);
ribbon = Enumerable.Range(0, count).Select(x =>
{
// define our offset to the zero sma, these various offsets will create our 'displaced' ribbon
var delay = new Delay(offset*(x+1));
// define an indicator that takes the output of the sma and pipes it into our delay indicator
var delayedSma = delay.Of(sma);
// register our new 'delayedSma' for automaic updates on a daily resolution
RegisterIndicator(Symbol, delayedSma, Resolution.Daily, data => data.Value);
return delayedSma;
}).ToArray();
}
private DateTime previous;
public void OnData(TradeBars data)
{
// wait for our entire ribbon to be ready
if (!ribbon.All(x => x.IsReady)) return;
// only once per day
if (previous.Date == data.Time.Date) return;
Plot(Symbol, "Price", data[Symbol].Price);
Plot(Symbol, ribbon);
// check for a buy signal
var values = ribbon.Select(x => x.Value.Data).ToArray();
var holding = Portfolio[Symbol];
if (holding.Quantity <= 0 && IsAscending(values))
{
SetHoldings(Symbol, 1.0);
}
else if (holding.Quantity > 0 && IsDescending(values))
{
Liquidate(Symbol);
}
previous = data.Time;
}
/// <summary>
/// Returns true if the specified values are in ascending order
/// </summary>
private bool IsAscending(IEnumerable<decimal> values)
{
decimal? last = null;
foreach (var val in values)
{
if (last == null)
{
last = val;
continue;
}
if (last.Value < val)
{
return false;
}
last = val;
}
return true;
}
/// <summary>
/// Returns true if the specified values are in descending order
/// </summary>
private bool IsDescending(IEnumerable<decimal> values)
{
decimal? last = null;
foreach (var val in values)
{
if (last == null)
{
last = val;
continue;
}
if (last.Value > val)
{
return false;
}
last = val;
}
return true;
}
}
}/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
namespace QuantConnect.Indicators
{
/// <summary>
/// This indicator is capable of wiring up two separate indicators into a single indicator
/// such that data will be pumped into the First, and the output of the First will be pumped
/// into the Second, after the First IsReady
/// </summary>
public class SequentialIndicator : Indicator
{
/// <summary>
/// Gets the first indicator to receive data
/// </summary>
public Indicator First { get; private set; }
/// <summary>
/// Gets the second indicator that receives the output from the first as its input data
/// </summary>
public Indicator Second { get; private set; }
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady
{
get { return Second.IsReady && First.IsReady; }
}
/// <summary>
/// Creates a new SequentialIndicator that will pipe the output of the first into the second
/// </summary>
/// <param name="name">The name of this indicator</param>
/// <param name="first">The first indicator to receive data</param>
/// <param name="second">The indicator to receive the first's output data</param>
public SequentialIndicator(string name, Indicator first, Indicator second)
: base(name)
{
First = first;
Second = second;
}
/// <summary>
/// Creates a new SequentialIndicator that will pipe the output of the first into the second
/// </summary>
/// <param name="first">The first indicator to receive data</param>
/// <param name="second">The indicator to receive the first's output data</param>
public SequentialIndicator(Indicator first, Indicator second)
: base(string.Format("SEQUENTIAL({0}->{1})", first.Name, second.Name))
{
First = first;
Second = second;
}
/// <summary>
/// Computes the next value of this indicator from the given state
/// </summary>
/// <param name="previousValue">The most recent value of this indicator</param>
/// <param name="input">The input given to the indicator</param>
/// <returns>A new value for this indicator</returns>
protected override decimal ComputeNextValue(IndicatorDataPoint previousValue, IndicatorDataPoint input)
{
First.Update(input);
if (!First.IsReady)
{
// if the first isn't ready just send out a default value
return 0m;
}
Second.Update(First.Value);
return Second.Value.Data;
}
}
}/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
namespace QuantConnect.Indicators
{
/// <summary>
/// An indicator that delays its input for a certain period
/// </summary>
public class Delay : WindowIndicator
{
/// <summary>
/// Creates a new Delay indicator that delays its input by the specified period
/// </summary>
/// <param name="period">The period to delay input, must be greater than zero</param>
public Delay(int period)
: this("DELAY" + period, period)
{
}
/// <summary>
/// Creates a new Delay indicator that delays its input by the specified period
/// </summary>
/// <param name="period">The period to delay input, must be greater than zero</param>
public Delay(string name, int period)
: base(name, period)
{
}
/// <summary>
/// Computes the next value for this indicator from the given state.
/// </summary>
/// <param name="window">The window of data held in this indicator</param>
/// <param name="previousValue">The previous value of this indicator</param>
/// <param name="input">The input value to this indicator on this time step</param>
/// <returns>A new value for this indicator</returns>
protected override decimal ComputeNextValue(IReadOnlyWindow<IndicatorDataPoint> window, IndicatorDataPoint previousValue, IndicatorDataPoint input)
{
if (!window.IsReady)
{
// grab the initial value until we're ready
return window[window.Count - 1];
}
return window.MostRecentlyRemoved;
}
}
}/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
namespace QuantConnect.Indicators
{
/// <summary>
/// Provides extension methods for Indicator
/// </summary>
public static class IndicatorExtensions
{
/// <summary>
/// Creates a new SequentialIndicator such that data from 'first' is piped into 'second'
/// </summary>
/// <param name="second">The indicator that wraps the first</param>
/// <param name="first">The indicator to be wrapped</param>
/// <returns>A new SequentialIndicator that pipes data from first to second</returns>
public static SequentialIndicator Of(this Indicator second, Indicator first)
{
return new SequentialIndicator(first, second);
}
/// <summary>
/// Creates a new SequentialIndicator such that data from 'first' is piped into 'second'
/// </summary>
/// <param name="second">The indicator that wraps the first</param>
/// <param name="first">The indicator to be wrapped</param>
/// <param name="name">The name of the new indicator</param>
/// <returns>A new SequentialIndicator that pipes data from first to second</returns>
public static SequentialIndicator Of(this Indicator second, Indicator first, string name)
{
return new SequentialIndicator(first, second);
}
}
}