Overall Statistics
Total Trades
157
Average Win
3.88%
Average Loss
-0.98%
Compounding Annual Return
4.423%
Drawdown
17.400%
Expectancy
0.774
Net Profit
72.687%
Sharpe Ratio
0.526
Loss Rate
64%
Win Rate
36%
Profit-Loss Ratio
3.94
Alpha
0.022
Beta
0.242
Annual Standard Deviation
0.09
Annual Variance
0.008
Information Ratio
-0.357
Tracking Error
0.165
Treynor Ratio
0.196
Total Fees
$173.73
using System.Collections.Concurrent;

namespace QuantConnect 
{   
    
    public class KAMA : QCAlgorithm
    {
        string tradeSymbol = "SPY";
        
        //Data Required 
        List<string> _symbols = new List<string>() { "SPY" };
        
        RollingWindow<TradeBar> _window = new RollingWindow<TradeBar>(110);
        private RollingWindow<decimal> _amaW = new RollingWindow<decimal>(5);
        
        TradeBars _bars = new TradeBars();
        
        //global vars
        decimal _delta;
        decimal _noise;
        decimal _er;
        decimal _c;
        decimal _ama;
        decimal _prevama;
        decimal _slowsc;
        decimal _fastsc;
        decimal _s;
        StandardDeviation _sd;
        //Sum _sum;
        
        //kama parameters
        int _period = 100;
        int _fast = 2;
        int _slow = 30;
        int _filterPeriod = 100;
        //double _filterIndex = 0.1; // used for sl*ATR

        //Initialize the data and resolution you require for your strategy:
        public override void Initialize()
        {
            //Start and End Date range for the backtest:
            SetStartDate(2003, 1, 1);
            //SetEndDate(2015, 6, 5);
            SetEndDate(DateTime.Now.AddDays(-1));
            
            //Cash allocation
            SetCash(25000);
            
            //Add as many securities as you like. All the data will be passed into the event handler:
            foreach (var symbol in _symbols) {
                AddSecurity(SecurityType.Equity, symbol, Resolution.Daily);
                Securities[symbol].SetDataNormalizationMode(DataNormalizationMode.Raw);
                //Securities[symbol].TransactionModel = new CustomTransactionModel();
            }
            
            //Add as many securities as you like. All the data will be passed into the event handler:
            /*foreach (var symbol in _symbols) {
                AddSecurity(SecurityType.Forex, symbol, Resolution.Daily);
                //Securities[symbol].SetLeverage(50m);
                //Securities[symbol].TransactionModel = new CustomForexTransactionModel();
            }*/
            //_symbols.AddRange(_EqSymbols);
            
            //updated inside OnData
            //_sum = new Sum(_period);
            _sd = new StandardDeviation(_filterPeriod);
            
        }
        
        //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)
        {   
            UpdateBars(data);
            if (_bars.Count != _symbols.Count) return;
            //foreach(var symbol in _symbols)
            //{
                try
                {
					_window.Add(_bars[tradeSymbol]);
					if(!_window.IsReady) return;
					
					_er = 1m;
					
					_delta = Math.Abs(_window[0].Close - _window[_period].Close);
					_noise = Math.Abs(_window[0].Close - _window[1].Close);
					
					_s = 0;
					for (int i=_period; i >= 0; i--)
                    {
                    	_s += Math.Abs(_window[i].Close - _window[i+1].Close);
                    }
					
                    if(_s != 0)
                    {
                    	_er = _delta/_s;
                    }

                    _slowsc = 2m /(_slow+1);
                    _fastsc = 2m /(_fast+1);
                    _c = (_er*(_fastsc - _slowsc) + _slowsc) * (_er*(_fastsc - _slowsc) + _slowsc);
					
					//original / optimised kama
					if(_prevama != 0)
					{
						_ama = _prevama + _c*(_window[0].Close - _prevama);
					} else
					{
						_ama = _window[0].Close;
					}
					
					_amaW.Add(_ama);
					if(!_amaW.IsReady) return;
					
					TradeBar bar;
					if (_bars.TryGetValue(tradeSymbol, out bar))
                    {
                        _sd.Update(bar.Time, (_amaW[0]-_amaW[1]));
                    }

                    //indies
                    Plot("KAMA", "ama window", _ama);
                    Plot("KAMA StDev", "ama window", _sd);
					
					//exits
                    if(Portfolio.HoldStock)
                    {
                    	//10% stop loss of everything vavailable
                    	if (Securities[tradeSymbol].Holdings.UnrealizedProfit < -Portfolio.TotalPortfolioValue*0.1m)
						{
							Liquidate(tradeSymbol);
						}

                    	if(Portfolio[tradeSymbol].IsLong)// && _amaW[0] < _amaW[1] && _amaW[1] > _amaW[2])
                    	{
                       		//decimal max = _amaW[1] - _amaW[0];
                       		if(_amaW[0] < _amaW[1])// && max < _sd*(decimal)_filterIndex)
                    		{
	                       		Liquidate(tradeSymbol);
    	                	}
    	                }
                    }

                    //entries
                    if(_prevama != 0)
                    {
	                    if(!Portfolio.HoldStock)// && _amaW[0] > _amaW[1] && _amaW[1] < _amaW[2])
    	                {
                    		//decimal min = _amaW[0] - _amaW[1];
	                    	if(_amaW[0] > _amaW[1])// && min > _sd*(decimal)_filterIndex)
    	                	{
								SetHoldings(tradeSymbol,0.9);
                    		}
                    	}
                    }
                    _prevama = _ama;
                    
                    
                }
                catch(Exception err)
                {
                    Log("ERROR. "+err.Message);
                }
            

        } //end of ondata
            
    //Update the global "_bars" object
        private void UpdateBars(TradeBars data) 
        {
            foreach (var bar in data.Values)
            {
                if (!_bars.ContainsKey(bar.Symbol)) {
                    _bars.Add(bar.Symbol, bar);
                }
                _bars[bar.Symbol] = bar;
            }
        }
        
    } // end of algo
    
    
    
} //end of namesace
namespace QuantConnect.Securities.Forex
{
    /// <summary>
    /// Forex Transaction Model Class: Specific transaction fill models for FOREX orders
    /// </summary>
    /// <seealso cref="SecurityTransactionModel"/>
    /// <seealso cref="ISecurityTransactionModel"/>
    public class CustomForexTransactionModel : SecurityTransactionModel
    {
        private readonly decimal _commissionRate;
        private readonly decimal _minimumOrderFee;

        /// <summary>
        /// Initialise the transaction model class
        /// </summary>
        public CustomForexTransactionModel(decimal monthlyTradeAmountInUSDollars = 0)
        {
            /*            Interactive Brokers Forex Commisions as of 2015.04.15
                Monthly Trade Amount                   Commissions                          Minimum per Order
                <=USD 1,000,000,000                    0.20basis point * Trade Value        USD 2.00
                USD 1,000,000,001 - 2,000,000,000      0.15basis point * Trade Value        USD 1.50
                USD 2,000,000,001 - 5,000,000,000      0.10basis point * Trade Value        USD 1.25
                >USD 5,000,000,000                     0.08basis point * Trade Value        USD 1.00
             * 
            */

            const decimal bp = 0.0001m;
            if (monthlyTradeAmountInUSDollars <= 1000000000) // 1 billion
            {
                _commissionRate = 0.20m*bp;
                _minimumOrderFee = 2.00m;
            }
            else if (monthlyTradeAmountInUSDollars <= 2000000000) // 2 billion
            {
                _commissionRate = 0.15m*bp;
                _minimumOrderFee = 1.50m;
            }
            else if (monthlyTradeAmountInUSDollars <= 5000000000) // 5 billion
            {
                _commissionRate = 0.20m*bp;
                _minimumOrderFee = 1.25m;
            }
            else
            {
                _commissionRate = 0.20m*bp;
                _minimumOrderFee = 1.00m;
            }
        }

        /// <summary>
        /// Get the slippage approximation for this order
        /// </summary>
        /// <returns>Decimal value of the slippage approximation</returns>
        /// <seealso cref="Order"/>
        public override decimal GetSlippageApproximation(Security security, Order order)
        {
            //Return 0 by default
            decimal slippage = 0.0002m;
            //For FOREX, the slippage is the Bid/Ask Spread for Tick, and an approximation for the 
            switch (security.Resolution)
            {
                case Resolution.Minute:
                case Resolution.Second:
                    //Get the last data packet:
                    //Assume slippage is 1/10,000th of the price
                    slippage = security.GetLastData().Value*0.0002m;
                    break;

                case Resolution.Tick:
                    var lastTick = (Tick) security.GetLastData();
                    switch (order.Direction)
                    {
                        case OrderDirection.Buy:
                            //We're buying, assume slip to Asking Price.
                            slippage = Math.Abs(order.Price - lastTick.AskPrice);
                            break;

                        case OrderDirection.Sell:
                            //We're selling, assume slip to the bid price.
                            slippage = Math.Abs(order.Price - lastTick.BidPrice);
                            break;
                    }
                    break;
            }
            return slippage;
        }

        /// <summary>
        /// Get the fees from this order
        /// </summary>
        /// <param name="quantity">Quantity of purchase</param>
        /// <param name="price">Price of the currency</param>
        /// <remarks>
        ///     FXCM now uses a flat fee per trade instead of a spread model. This spread model is 
        ///     out of date but the data has the spread built into historical data. >> New data source needed.
        /// </remarks>
        /// <returns>Decimal value of the order fee</returns>
        public override decimal GetOrderFee(decimal quantity, decimal price)
        {
            var fee = _commissionRate*quantity*price;
            return Math.Max(_minimumOrderFee, fee);
        }

        /// <summary>
        /// Default implementation returns 0 for fees.
        /// </summary>
        /// <param name="security">The security matching the order</param>
        /// <param name="order">The order to compute fees for</param>
        /// <returns>The cost of the order in units of the account currency</returns>
        public override decimal GetOrderFee(Security security, Order order)
        {
            var forex = (Forex) security;

            // get the total order value in the account currency
            var price = order.Status.IsFill() ? order.Price : security.Price;
            var totalOrderValue = order.GetValue(price)*forex.QuoteCurrency.ConversionRate;
            var fee = _commissionRate*totalOrderValue;
            return Math.Max(_minimumOrderFee, fee);
        }
    }
}
namespace QuantConnect.Securities.Forex
{
    /// <summary>
    /// Forex Transaction Model Class: Specific transaction fill models for FOREX orders
    /// </summary>
    /// <seealso cref="SecurityTransactionModel"/>
    /// <seealso cref="ISecurityTransactionModel"/>
    public class CustomTransactionModel : SecurityTransactionModel
    {
        private readonly decimal _commissionRate;
        private readonly decimal _minimumOrderFee;

        /// <summary>
        /// Initialise the transaction model class
        /// </summary>
        public CustomTransactionModel(decimal monthlyTradeAmountInUSDollars = 0)
        {
            /*            Interactive Brokers Forex Commisions as of 2015.04.15
                Monthly Trade Amount                   Commissions                          Minimum per Order
                <=USD 1,000,000,000                    0.20basis point * Trade Value        USD 2.00
                USD 1,000,000,001 - 2,000,000,000      0.15basis point * Trade Value        USD 1.50
                USD 2,000,000,001 - 5,000,000,000      0.10basis point * Trade Value        USD 1.25
                >USD 5,000,000,000                     0.08basis point * Trade Value        USD 1.00
             * 
            */

            const decimal bp = 0.01m;
            if (monthlyTradeAmountInUSDollars <= 1000000000) // 1 billion
            {
                _commissionRate = 0.20m*bp;
                _minimumOrderFee = 2.00m;
            }
            else if (monthlyTradeAmountInUSDollars <= 2000000000) // 2 billion
            {
                _commissionRate = 0.15m*bp;
                _minimumOrderFee = 1.50m;
            }
            else if (monthlyTradeAmountInUSDollars <= 5000000000) // 5 billion
            {
                _commissionRate = 0.20m*bp;
                _minimumOrderFee = 1.25m;
            }
            else
            {
                _commissionRate = 0.20m*bp;
                _minimumOrderFee = 1.00m;
            }
        }

        /// <summary>
        /// Get the slippage approximation for this order
        /// </summary>
        /// <returns>Decimal value of the slippage approximation</returns>
        /// <seealso cref="Order"/>
        public override decimal GetSlippageApproximation(Security security, Order order)
        {
            //Return 0 by default
            decimal slippage = 0.05m;
            //For FOREX, the slippage is the Bid/Ask Spread for Tick, and an approximation for the 
            switch (security.Resolution)
            {
                case Resolution.Minute:
                case Resolution.Second:
                    //Get the last data packet:
                    //Assume slippage is 1/10,000th of the price
                    slippage = security.GetLastData().Value*0.0002m;
                    break;

                case Resolution.Tick:
                    var lastTick = (Tick) security.GetLastData();
                    switch (order.Direction)
                    {
                        case OrderDirection.Buy:
                            //We're buying, assume slip to Asking Price.
                            slippage = Math.Abs(order.Price - lastTick.AskPrice);
                            break;

                        case OrderDirection.Sell:
                            //We're selling, assume slip to the bid price.
                            slippage = Math.Abs(order.Price - lastTick.BidPrice);
                            break;
                    }
                    break;
            }
            return slippage;
        }

        /// <summary>
        /// Get the fees from this order
        /// </summary>
        /// <param name="quantity">Quantity of purchase</param>
        /// <param name="price">Price of the currency</param>
        /// <remarks>
        ///     FXCM now uses a flat fee per trade instead of a spread model. This spread model is 
        ///     out of date but the data has the spread built into historical data. >> New data source needed.
        /// </remarks>
        /// <returns>Decimal value of the order fee</returns>
        public override decimal GetOrderFee(decimal quantity, decimal price)
        {
            var fee = _commissionRate*quantity*price;
            return Math.Max(_minimumOrderFee, fee);
        }

        /// <summary>
        /// Default implementation returns 0 for fees.
        /// </summary>
        /// <param name="security">The security matching the order</param>
        /// <param name="order">The order to compute fees for</param>
        /// <returns>The cost of the order in units of the account currency</returns>
        public override decimal GetOrderFee(Security security, Order order)
        {
            var forex = (Forex) security;

            // get the total order value in the account currency
            var price = order.Status.IsFill() ? order.Price : security.Price;
            var totalOrderValue = order.GetValue(price)*forex.QuoteCurrency.ConversionRate;
            var fee = _commissionRate*totalOrderValue;
            return Math.Max(_minimumOrderFee, fee);
        }
    }
}
namespace QuantConnect 
{
    
    /*
    *   TimeSpanConsolidator Helper Routine: Assemble generic timespan bar lengths: e.g. 10 minutes:
    *
    *   1. Setup the new Consolidator class with the timespan period:
    *   var _consolidator = new Consolidator(TimeSpan.FromMinutes(10));
    *
    *   2. Add in the data with the update routine. It will return true when bar ready
    *   if (_consolidator.Update(data["MSFT"])) {   UseBar    }
    */
    public class Consolidator 
    {
        private TradeBar _resultBar;
        private TradeBar _workingBar;
        private DateTime _start;
        private TimeSpan _period;
        
        //Result:
        public TradeBar Bar
        {
            get
            {
                return _resultBar;
            }
        }
        
        //Constructor: Set the period we'd like to scan
        public Consolidator(TimeSpan span) 
        {
            this._period = span;
            this._resultBar = new TradeBar();
            this._workingBar = new TradeBar(new DateTime(), "", Decimal.Zero, Decimal.MinValue, Decimal.MaxValue, 0, 0);
        }
        
        //Submit this bar, return true if we've started a new one.
        public bool Update(TradeBar newBar)
        {
            //Intialize:
            if (_start == new DateTime()) 
            {
                _start = newBar.Time;
            }
            
            //While we're less than end date, keep adding to this bar:
            if (newBar.Time < (_start + _period))
            {
                //Building bar:
                AddToBar(newBar);
                return false;
            } 
            else 
            {
                //Completed bar: start new one:
                _resultBar = _workingBar;
                //Create a new bar:
                _workingBar = new TradeBar(newBar.Time, newBar.Symbol, Decimal.Zero, Decimal.MinValue, Decimal.MaxValue, 0, 0);
                //Start of this bar:
                _start = newBar.Time;
                AddToBar(newBar);
                return true;
            }
        }
        
        //Add to a tradebar
        private void AddToBar(TradeBar newBar)
        {
            //Add this data to working bar:
            if (_workingBar.Time == new DateTime()) _workingBar.Time = newBar.Time;
            if (_workingBar.Symbol == "") _workingBar.Symbol = newBar.Symbol;
            if (_workingBar.Open == Decimal.Zero) _workingBar.Open = newBar.Open;
            if (newBar.High > _workingBar.High) _workingBar.High = newBar.High;
            if (newBar.Low < _workingBar.Low) _workingBar.Low = newBar.Low;
            _workingBar.Close = newBar.Close;
            _workingBar.Volume = newBar.Volume;
        }
    }

}