using System;
using System.Linq;
using QuantConnect.Data;
using QuantConnect.Orders;
using QuantConnect.Securities;
using QuantConnect.Securities.Future;
using QuantConnect.Indicators;
namespace QuantConnect.Algorithm.CSharp
{
/// <summary>
/// EMA cross with SP500 E-mini futures
/// In this example, we demonstrate how to trade futures contracts using
/// a equity to generate the trading signals
/// It also shows how you can prefilter contracts easily based on expirations.
/// It also shows how you can inspect the futures chain to pick a specific contract to trade.
/// </summary>
/// <meta name="tag" content="using data" />
/// <meta name="tag" content="futures" />
/// <meta name="tag" content="indicators" />
/// <meta name="tag" content="strategy example" />
public class FuturesMomentumAlgorithm : QCAlgorithm
{
private const decimal _tolerance = 0.001m;
private ExponentialMovingAverage _fast;
private ExponentialMovingAverage _slow;
private SimpleMovingAverage[] _ribbon;
private RelativeStrengthIndex _rsi;
private AroonOscillator _aroon;
private bool _long = true;
private decimal _price;
private string _symbol = "SPY";
private bool _orderHold = true;
private bool _tradeShort = true;
private bool _tradeLong = true;
private SecurityPortfolioManager _previousPortfolio = null;
private decimal _vix;
public bool IsReady { get { return _fast.IsReady && _slow.IsReady; } }
public bool IsUpTrend { get { return IsReady && _fast > _slow * (1 + _tolerance); } }
public bool IsDownTrend { get { return IsReady && _fast < _slow * (1 + _tolerance); } }
public override void Initialize()
{
SetStartDate(2017, 10, 1);
SetEndDate(DateTime.Now);
SetCash(40000);
SetWarmUp(Math.Max(24, 48));
//VIX volatility
//AddData<Quandl>("CBOE/VIX");
AddData<QuandlVix>("CBOE/VIX");
// Adds SPY to be used in our EMA indicators
AddSecurity(SecurityType.Equity, _symbol, Resolution.Minute);
var equity = AddEquity(_symbol, Resolution.Minute);
_fast = EMA(equity.Symbol, 24, Resolution.Hour);
_slow = EMA(equity.Symbol, 5, Resolution.Daily);
_aroon = AROON(_symbol, 24, Resolution.Hour);
var ribbonCount = 8;
var ribbonInterval = 15;
_ribbon = Enumerable.Range(0, ribbonCount).Select(x => SMA(_symbol, (x + 1)*ribbonInterval, Resolution.Daily)).ToArray();
_rsi = RSI(_symbol, 14, MovingAverageType.Simple, Resolution.Daily);
// Adds the future that will be traded and
// set our expiry filter for this futures chain
var future = AddFuture(Futures.Indices.SP500EMini);
future.SetFilter(TimeSpan.Zero, TimeSpan.FromDays(182));
var benchmark = AddEquity(_symbol);
SetBenchmark(benchmark.Symbol);
Securities[_symbol].TransactionModel = new ConstantFeeTransactionModel(1);
//Brokerage model and account type:
SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage, AccountType.Margin);
}
public bool IsExecuteBeforeMarketClosure
{
get
{
var exchange = Securities[_symbol].Exchange;
bool isMarketOpen = exchange.DateTimeIsOpen(Time);
//bool isExecuteBeforeMarketClosure = isMarketOpen
// && exchange.DateTimeIsOpen(Time.AddMinutes(10))
// && !exchange.DateTimeIsOpen(Time.AddMinutes(15));
//return isExecuteBeforeMarketClosure;
return isMarketOpen;
}
}
public void OnData(Quandl data)
{
if (data.Symbol=="CBOE/VIX")
{
_vix=data.Value;
Plot("Data-vix", "VIX", _vix);
}
}
public void OnData(TradeBars data)
{
if(data.ContainsKey(_symbol))
{
_price = data[_symbol].Close;
}
if (!_slow.IsReady) return;
//avoid random start
if(_orderHold && Math.Abs(_fast - _slow) >= 0.05m)
{
_orderHold = false;
Log("OrderHold = false");
Plot("Data", "Price", _price);
Plot("Data", _fast, _slow);
}
}
public override void OnData(Slice slice)
{
if (!_slow.IsReady || !_rsi.IsReady) return;
if(_orderHold) return;
if(_tradeLong)
{
if (!Portfolio.Invested && IsUpTrend)
{
foreach (var chain in slice.FutureChains)
{
// find the front contract expiring no earlier than in 90 days
var contract = (
from futuresContract in chain.Value.OrderBy(x => x.Expiry)
where futuresContract.Expiry > Time.Date.AddDays(90)
select futuresContract
).FirstOrDefault();
// if found, trade it
if (contract != null)
{
if(IsExecuteBeforeMarketClosure)
{
MarketOrder(contract.Symbol, 1);
_long = true;
}
}
}
}
if (Portfolio.Invested && _long && IsDownTrend)
{
if(IsExecuteBeforeMarketClosure)
{
Liquidate();
}
}
}
if(_tradeShort)
{
if (!Portfolio.Invested && IsDownTrend)
{
foreach (var chain in slice.FutureChains)
{
// find the front contract expiring no earlier than in 90 days
var contract = (
from futuresContract in chain.Value.OrderBy(x => x.Expiry)
where futuresContract.Expiry > Time.Date.AddDays(90)
select futuresContract
).FirstOrDefault();
// if found, trade it
if (contract != null)
{
if(IsExecuteBeforeMarketClosure)
{
MarketOrder(contract.Symbol, -1);
_long = false;
}
}
}
}
if (Portfolio.Invested && !_long && IsUpTrend)
{
if(IsExecuteBeforeMarketClosure)
{
Liquidate();
}
}
}
if(_previousPortfolio != null)
{
//Dictionary<Symbol, SecurityHolding>
foreach (var holding in Portfolio.Values)
{
if(holding != null)
{
foreach (var previousHolding in _previousPortfolio.Values)
{
if(previousHolding != null)
{
if(holding.Quantity != previousHolding.Quantity)// ||
// futureHolding.IsLong != previousFutureHolding.IsLong ||
//futureHolding.IsShort != previousFutureHolding.IsShort)
{
Log("Holdings Changed");
Plot("Indicator Signal", "Trend", IsDownTrend ? -1 : IsUpTrend ? 1 : 0);
Plot("Holdings", "Qty", holding.Quantity);
Plot("Data", "Price", _price);
Plot("Data", _fast, _slow);
}
}
}
}
}
}
_previousPortfolio = Portfolio;
}
public override void OnEndOfDay()
{
if (!_slow.IsReady || !_rsi.IsReady) return;
//Plot("EMA", "Price", _price);
//Plot("EMA", _fast, _slow);
//Plot("Ribbon", _ribbon);
//Plot("RSI", _rsi);
//Plot("AROON", _aroon.AroonUp, _aroon.AroonDown);
//var price = Identity(_symbol);
//PlotIndicator(_symbol, _price, _fast, _slow);
}
public override void OnOrderEvent(OrderEvent orderEvent)
{
Log(orderEvent.ToString());
}
}
public class QuandlVix : Quandl
{
public QuandlVix() : base(valueColumnName: "vix close") { }
}
}