Overall Statistics
Total Trades
310
Average Win
2.00%
Average Loss
-2.32%
Compounding Annual Return
9762.145%
Drawdown
29.100%
Expectancy
0.364
Net Profit
217.953%
Sharpe Ratio
3.966
Loss Rate
27%
Win Rate
73%
Profit-Loss Ratio
0.86
Alpha
4.391
Beta
-0.386
Annual Standard Deviation
1.101
Annual Variance
1.212
Information Ratio
3.834
Tracking Error
1.123
Treynor Ratio
-11.318
Total Fees
$2865.71
//Copyright Warren Harding 2016.
//Granted to the public domain.
//Use entirely at your own risk.
//Custom algorithm development: warrencharding@yahoo.com.
//Do not remove this copyright notice.

using System;
using System.Collections.Generic;
using QuantConnect.Data.Market;
using QuantConnect.Orders;
using QuantConnect.Orders.Fees;
using QuantConnect.Orders.Fills;
using QuantConnect.Orders.Slippage;
using QuantConnect.Securities;
namespace QuantConnect
{
    public class Algo4 : QCAlgorithm
    {
    	//You can adjust this first set to optimize.
    	int atrPeriod = 15;
    	decimal minimumAtrPercentage=0.015m;
    	decimal atrMultiplier=3m;
    	//Your broker is going to hate you if you set these too low as it will result in large amounts of unfilled
    	//order cancellations. It bogs down LEAN as well.
    	int barsToHoldBuyOrdersFor=3;
    	int barsToHoldSellOrdersFor=3;
    	
    	//Be careful adjusting this next one, too high of a setting will result in unrealistically large
    	//purchases being made with no regards for slippage.
    	decimal ratioOfLastBarForMaxTrade =0.05m;
    	
    	Resolution resolution = Resolution.Minute;

        Dictionary<string,AverageTrueRange> atrs=new Dictionary<string,AverageTrueRange>();
        Dictionary<string,OrderTicket> buyOrders=new Dictionary<string,OrderTicket>();
        Dictionary<string,int> buyOrderCounts = new Dictionary<string,int>();
        Dictionary<string,decimal> buyOrderPrices = new Dictionary<string,decimal>();
        Dictionary<string,OrderTicket> sellOrders=new Dictionary<string,OrderTicket>();
        Dictionary<string,int> sellOrderCounts = new Dictionary<string,int>();
        
        public override void Initialize()
        {
            SetStartDate(2016, 1, 1);
			SetEndDate(2016, 4, 1);
            SetCash(25000);

			//volatile etf's
			//string tickersString="JDST,JNUG,DRIP,NUGT,GUSH,UVXY,GASL,LABU,LABD,GASX,TVIX,DWTI,UWTI,DGAZ,UGAZ,UBIO,ZBIO,BRZU,ERY,SCO,ERX,RUSS,UCO,RUSL,SILJ,XIV,SVXY,BIB,VXX,BIS,VIXY,SOXL,VIIX,BOIL,SOXS,SLVP,USLV,DSLV,GDXJ,BZQ,GLDX,RING,TZA,TNA,AMZA,DUG,DIG,XES,SRTY,SIL,PSCE,URTY,YINN,SGDM,YANG,OIL,XME,GDX,DRV,DRN,XOP,TQQQ,SMHD,SQQQ,CURE,XBI,FCG,OIH,SBIO,MIE,EDC,FAZ,FAS,MLPI,EDZ,IEZ,ZSL,AGQ,FXN,JGBT,AMU,SLX,TECL,USO,NTG,TECS,AMLP,BNO,MLPN,MIDU,MLPA,NGE,AMJ,INDL,IEO,UNG,EPU,UGLD,DGLD,YMLP";

			//volatile stocks
			string tickersString="LGCY,CDRB,RPRX,BCEI,SXE,UNXL,LEI,ARGS,ALIM,MCEP,AREX,CWEI,DRYS,GBSN,ORIG,SRPT,DNR,CBAY,DRWI,ECR,RLYP,NADL,EVEP,SKYS,VRNG,PTCT,ERN,CLF,RESN,WG,EPE,BAS,GLF,SDRL,PLG,VYGR,HCLP,ANFI,GST,LEU,GSL,RXII,MEP,FCSC,CHMA,DSX,EMES,TDW,GNCA,CCXI,VSLR,JONE,TTPH,CNXR,CRMD,CARA,SALT,GRAM,SN,CBMX,MEMP,FMSA,CPXX,TROV,ETE,CLVS,OVAS,ENPH,OMEX,NGL,TMST,CHK,CLMT,ORPN,WLL,SM,HBM,GOL,YRD,BBG,BPT,SGYP,UNT,CNAT,RXDX,CLD,VRX,ATW,RBPAA,GLBL,PES,CIE,TKAI,AMID,AVGR,HLX,SKY,SDLP,INAP,AEGR";
			
			string[] tickers = tickersString.Split(new string[1] { "," }, StringSplitOptions.RemoveEmptyEntries);
			foreach (string ticker in tickers)
			{
				AddSecurity(SecurityType.Equity,ticker,resolution);
			}
            foreach (Security s in Securities.Values)
            {
            	s.FeeModel=new CustomFeeModel();
            	atrs.Add(s.Symbol,ATR(s.Symbol,atrPeriod,MovingAverageType.Simple,resolution));
            }
        }
		
        public void OnData(TradeBars data)
        {
			Buy(data);
			Sell(data);
        }
        
        public void Buy(TradeBars data)
        {
        	CancelBuyOrders();
        	int quantity = 0;
        	decimal minimumPurchase = 500m;
        	decimal maxTrade;
            OrderTicket orderTicket;
            decimal buyPrice;
            decimal atrPercentage;
            
    	    foreach (TradeBar bar in data.Values)
            {
            	if (Portfolio.Cash - SumBuyOrders(buyOrders,buyOrderPrices) < minimumPurchase)
                {
                    break;
                }
                if (!Portfolio[bar.Symbol].HoldStock)
                {
                    maxTrade = bar.Close * bar.Volume / ratioOfLastBarForMaxTrade;
                    quantity =(int)Math.Floor(Math.Min(Portfolio.Cash-SumBuyOrders(buyOrders,buyOrderPrices), maxTrade) / bar.Close);
                    if (quantity * bar.Close > minimumPurchase & quantity > 0)
                    {
                    	atrPercentage=atrs[bar.Symbol] / bar.Close;
                        if (atrPercentage > minimumAtrPercentage)
                        {
                        	if (buyOrders.ContainsKey(bar.Symbol) == false)
                        	{
                            	buyPrice=bar.Low * (1-atrPercentage*atrMultiplier);
                                orderTicket = LimitOrder(bar.Symbol, quantity,buyPrice);
                                buyOrders.Add(bar.Symbol,orderTicket);
                                buyOrderCounts.Add(bar.Symbol,0);
       							buyOrderPrices.Add(bar.Symbol,buyPrice);
                        	}
                        }
                    }
                }
            }
            foreach (string key in buyOrderCounts.Keys.ToList())
            {
                buyOrderCounts[key] = buyOrderCounts[key] + 1;
            }
        }
        
        public void Sell(TradeBars data)
        {
        	CancelSellOrders();
        	decimal sellPrice;
    	    TradeBar bar;
    	    OrderTicket orderTicket;
    	    decimal atrPercentage;
            
            foreach (SecurityHolding stock in Portfolio.Values)
            {
                if (Portfolio[stock.Symbol].Quantity > 0 & data.ContainsKey(stock.Symbol))
                {
                    bar = data[stock.Symbol];
                    if (sellOrders.ContainsKey(stock.Symbol)==false)
                    {
                    	atrPercentage=atrs[bar.Symbol] / bar.Close;
                        sellPrice = bar.High * (1+atrPercentage*atrMultiplier);
                        orderTicket = LimitOrder(stock.Symbol, -Portfolio[stock.Symbol].Quantity, sellPrice);
                        sellOrders.Add(stock.Symbol,orderTicket);
                        sellOrderCounts.Add(stock.Symbol,0);
                    }
                }
            }
            foreach (string key in sellOrderCounts.Keys.ToList())
            {
                sellOrderCounts[key] = sellOrderCounts[key] + 1;
            }
        }
        
        public void CancelBuyOrders()
        {
        	string[] symbols=buyOrders.Keys.ToArray();
        	foreach (string symbol in symbols)
        	{
			    if (buyOrderCounts[symbol]>barsToHoldBuyOrdersFor)
	        	{
	        		buyOrders[symbol].Cancel();
	        		buyOrders.Remove(symbol);
	        		buyOrderCounts.Remove(symbol);
	        		buyOrderPrices.Remove(symbol);
	        	}
        	}
        	symbols=buyOrders.Keys.ToArray();
        	foreach (string symbol in symbols)
        	{
    		    if (buyOrders[symbol].Status == OrderStatus.Filled)
	            {
            		buyOrders.Remove(symbol);
            		buyOrderCounts.Remove(symbol);
            		buyOrderPrices.Remove(symbol);
	            }
        	}
        }
        
        public void CancelSellOrders()
        {
        	string[] symbols=sellOrders.Keys.ToArray();
        	foreach (string symbol in symbols)
        	{
			    if (sellOrderCounts[symbol]>barsToHoldSellOrdersFor)
	        	{
	        		sellOrders[symbol].Cancel();
	        		sellOrders.Remove(symbol);
	        		sellOrderCounts.Remove(symbol);
	        	}
        	}
        	symbols=sellOrders.Keys.ToArray();
        	foreach (string symbol in symbols)
        	{
    		    if (sellOrders[symbol].Status == OrderStatus.Filled)
	            {
            		sellOrders.Remove(symbol);
            		sellOrderCounts.Remove(symbol);
	            }
        	}
        }
        
        public static decimal SumBuyOrders(Dictionary<string,OrderTicket> buyOrders, Dictionary<string,decimal> buyOrderPrices)
        {
        	decimal sum=0;
            foreach (string key in buyOrders.Keys.ToList())
            {
                sum += buyOrders[key].Quantity * buyOrderPrices[key];
            }
            return sum;
        }
       
        
    }
    
    public class CustomFeeModel : IFeeModel
    {
        public decimal GetOrderFee(Security security, Order order)
        {
            var fee = order.AbsoluteQuantity*0.01m;
            if (fee<5)
            {
            	fee=5;
            }
            if (fee>10)
            {
            	fee=10;
            }
            return fee;
        }
    }
}