| Overall Statistics |
|
Total Trades 374 Average Win 2.33% Average Loss -2.19% Compounding Annual Return 17172.516% Drawdown 29.500% Expectancy 0.458 Net Profit 443.643% Sharpe Ratio 4.374 Loss Rate 29% Win Rate 71% Profit-Loss Ratio 1.07 Alpha 4.831 Beta -0.515 Annual Standard Deviation 1.1 Annual Variance 1.209 Information Ratio 4.255 Tracking Error 1.12 Treynor Ratio -9.333 Total Fees $3410.70 |
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, 5, 1);
SetCash(20000);
//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 override void OnEndOfAlgorithm()
{
Console.WriteLine("TotalProfit: {0}", Portfolio.TotalProfit);
}
}
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;
}
}
}