using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using QuantConnect;
using QuantConnect.Models;
namespace QuantConnect.Indicator {
public class ExponentialMovingAverage : QCAlgorithm
{
private int _period;
private decimal _ema;
private int _samples;
private bool flag;
private Queue <decimal>_data = new Queue <decimal> ();
/********************************************************
* CLASS PUBLIC VARIABLES
*********************************************************/
//Current value of the EMA.
public decimal EMA {
get{ return _ema;}
}
//Track the number of samples:
public int Samples {
get { return _samples; }
}
//The EMA constant multiplier:
public decimal GetExpConst {
get{ return (decimal) 2/(_period +1);}
}
//We've got sufficient data samples to know its the EMA.
public bool Ready {
get { return _data.Count >= _period; }
}
/********************************************************
* CLASS CONSTRUCTOR
*********************************************************/
/// <summary>
/// Initialise the Algorithm
/// </summary>
public ExponentialMovingAverage(int period) {
_period = period;
_ema = 0;
flag = false;
}
/********************************************************
* CLASS METHODS
*********************************************************/
/// <summary>
/// Calculate the exponential moving average
/// </summary>
public decimal AddSample(decimal quote)
{
_data.Enqueue(quote);
_samples++;
if(_data.Count < _period)
{
return _data.Average();
}
else
{
if(!flag)
{
_ema = _data.Average();
flag = true;
}
else
{
_ema = (1-GetExpConst) * _ema +GetExpConst * quote;
}
}
return _ema;
}
}
}
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using QuantConnect.Indicator;
namespace QuantConnect
{
using QuantConnect.Securities;
using QuantConnect.Models;
//50-10 Day EMA Cross: with 1% Safety Margin and
public class QCUMovingAverageCross : QCAlgorithm, IAlgorithm {
//Define required variables:
int quantity = 0;
decimal price = 0;
decimal tolerance = 0.001m; //0.1% safety margin in prices to avoid bouncing.
string symbol = "SPY";
DateTime sampledToday = DateTime.Now;
//Set up the EMA Class:
ExponentialMovingAverage emaShort = new ExponentialMovingAverage(10);
ExponentialMovingAverage emaLong = new ExponentialMovingAverage(50);
//Initialize the data and resolution you require for your strategy:
public override void Initialize() {
SetStartDate(2008, 01, 01);
SetEndDate(2014, 04, 30);
SetCash(25000);
AddSecurity(SecurityType.Equity, symbol, Resolution.Minute);
}
//Handle TradeBar Events: a TradeBar occurs on every time-interval
public void OnData(TradeBars data) {
//One data point per day:
if (sampledToday.Date == data[symbol].Time.Date) return;
//Only take one data point per day (opening price)
price = Securities[symbol].Open;
sampledToday = data[symbol].Time;
//Push values into EMA.
emaShort.AddSample(price);
emaLong.AddSample(price);
//Wait until EMA's are ready:
if (!emaShort.Ready || !emaLong.Ready) return;
//Get fresh cash balance: Set purchase quantity to equivalent 10% of portfolio.
decimal cash = Portfolio.Cash;
int holdings = Portfolio[symbol].Quantity;
quantity = Convert.ToInt32((cash * 0.1m) / price);
if (holdings > 0 || holdings == 0) {
//If we're long, or flat: check if EMA crossed negative: and crossed outside our safety margin:
if ((emaShort.EMA * (1+tolerance)) < emaLong.EMA) {
//Now go short: Short-EMA signals a negative turn: reverse holdings
Order(symbol, -(holdings + quantity));
Log(Time.ToShortDateString() + " > Go Short > Holdings: " + holdings.ToString() + " Quantity:" + quantity.ToString() + " Samples: " + emaShort.Samples);
}
} else if (holdings < 0 || holdings == 0) {
//If we're short, or flat: check if EMA crossed positive: and crossed outside our safety margin:
if ((emaShort.EMA * (1 - tolerance)) > emaLong.EMA ) {
//Now go long: Short-EMA crossed above long-EMA by sufficient margin
Order(symbol, Math.Abs(holdings) + quantity);
Log(Time.ToShortDateString() + "> Go Long > Holdings: " + holdings.ToString() + " Quantity:" + quantity.ToString() + " Samples: " + emaShort.Samples);
}
}
}
}
}